diff options
Diffstat (limited to 'Source/WebCore/platform/graphics')
205 files changed, 5911 insertions, 2031 deletions
diff --git a/Source/WebCore/platform/graphics/BitmapImage.h b/Source/WebCore/platform/graphics/BitmapImage.h index 14a3094..c8cf0ab 100644 --- a/Source/WebCore/platform/graphics/BitmapImage.h +++ b/Source/WebCore/platform/graphics/BitmapImage.h @@ -165,7 +165,7 @@ protected: enum RepetitionCountStatus { Unknown, // We haven't checked the source's repetition count. Uncertain, // We have a repetition count, but it might be wrong (some GIFs have a count after the image data, and will report "loop once" until all data has been decoded). - Certain, // The repetition count is known to be correct. + Certain // The repetition count is known to be correct. }; BitmapImage(NativeImagePtr, ImageObserver* = 0); diff --git a/Source/WebCore/platform/graphics/Color.cpp b/Source/WebCore/platform/graphics/Color.cpp index a1c5cd7..7dea765 100644 --- a/Source/WebCore/platform/graphics/Color.cpp +++ b/Source/WebCore/platform/graphics/Color.cpp @@ -27,13 +27,12 @@ #include "Color.h" #include "HashTools.h" -#include "PlatformString.h" -#include <math.h> #include <wtf/Assertions.h> +#include <wtf/HexNumber.h> #include <wtf/MathExtras.h> +#include <wtf/text/StringBuilder.h> using namespace std; -using namespace WTF; namespace WebCore { @@ -180,14 +179,6 @@ Color::Color(const char* name) } } -static inline void appendHexNumber(UChar* destination, uint8_t number) -{ - static const char hexDigits[17] = "0123456789abcdef"; - - destination[0] = hexDigits[number >> 4]; - destination[1] = hexDigits[number & 0xF]; -} - String Color::serialized() const { DEFINE_STATIC_LOCAL(const String, commaSpace, (", ")); @@ -195,13 +186,13 @@ String Color::serialized() const DEFINE_STATIC_LOCAL(const String, zeroPointZero, ("0.0")); if (!hasAlpha()) { - UChar* characters; - String result = String::createUninitialized(7, characters); - characters[0] = '#'; - appendHexNumber(characters + 1, red()); - appendHexNumber(characters + 3, green()); - appendHexNumber(characters + 5, blue()); - return result; + StringBuilder builder; + builder.reserveCapacity(7); + builder.append('#'); + appendByteAsHex(red(), builder, Lowercase); + appendByteAsHex(green(), builder, Lowercase); + appendByteAsHex(blue(), builder, Lowercase); + return builder.toString(); } Vector<UChar> result; diff --git a/Source/WebCore/platform/graphics/ContextShadow.h b/Source/WebCore/platform/graphics/ContextShadow.h index c0571f0..850d489 100644 --- a/Source/WebCore/platform/graphics/ContextShadow.h +++ b/Source/WebCore/platform/graphics/ContextShadow.h @@ -32,7 +32,7 @@ #include "Color.h" #include "FloatRect.h" #include "IntRect.h" -#include "RefCounted.h" +#include <wtf/RefCounted.h> #if PLATFORM(CAIRO) typedef struct _cairo cairo_t; diff --git a/Source/WebCore/platform/graphics/Font.cpp b/Source/WebCore/platform/graphics/Font.cpp index ee85e45..72e3e3b 100644 --- a/Source/WebCore/platform/graphics/Font.cpp +++ b/Source/WebCore/platform/graphics/Font.cpp @@ -177,7 +177,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 : 0); + return floatWidthForSimpleText(run, 0, returnFallbackFonts ? fallbackFonts : 0, codePathToUse == SimpleWithGlyphOverflow || (glyphOverflow && glyphOverflow->computeBounds) ? glyphOverflow : 0); } return floatWidthForComplexText(run, fallbackFonts, glyphOverflow); diff --git a/Source/WebCore/platform/graphics/Font.h b/Source/WebCore/platform/graphics/Font.h index ce03aed..554f8a0 100644 --- a/Source/WebCore/platform/graphics/Font.h +++ b/Source/WebCore/platform/graphics/Font.h @@ -61,6 +61,7 @@ struct GlyphOverflow { , right(0) , top(0) , bottom(0) + , computeBounds(false) { } @@ -68,8 +69,10 @@ struct GlyphOverflow { int right; int top; int bottom; + bool computeBounds; }; + class Font { public: Font(); @@ -138,8 +141,6 @@ public: const FontData* fontDataAt(unsigned) const; GlyphData glyphDataForCharacter(UChar32, bool mirror, FontDataVariant = AutoVariant) const; bool primaryFontHasGlyphForCharacter(UChar32) const; - // Used for complex text, and does not utilize the glyph map cache. - const FontData* fontDataForCharacters(const UChar*, int length) const; static bool isCJKIdeograph(UChar32); static bool isCJKIdeographOrSymbol(UChar32); @@ -255,12 +256,6 @@ inline const FontData* Font::fontDataAt(unsigned index) const return m_fontList->fontDataAt(this, index); } -inline const FontData* Font::fontDataForCharacters(const UChar* characters, int length) const -{ - ASSERT(m_fontList); - return m_fontList->fontDataForCharacters(this, characters, length); -} - inline bool Font::isFixedPitch() const { ASSERT(m_fontList); diff --git a/Source/WebCore/platform/graphics/FontCache.cpp b/Source/WebCore/platform/graphics/FontCache.cpp index 5b508be..8c5edfe 100644 --- a/Source/WebCore/platform/graphics/FontCache.cpp +++ b/Source/WebCore/platform/graphics/FontCache.cpp @@ -57,7 +57,8 @@ struct FontPlatformDataCacheKey { WTF_MAKE_FAST_ALLOCATED; public: FontPlatformDataCacheKey(const AtomicString& family = AtomicString(), unsigned size = 0, unsigned weight = 0, bool italic = false, - bool isPrinterFont = false, FontRenderingMode renderingMode = NormalRenderingMode, FontOrientation orientation = Horizontal, FontWidthVariant widthVariant = RegularWidth) + bool isPrinterFont = false, FontRenderingMode renderingMode = NormalRenderingMode, FontOrientation orientation = Horizontal, + TextOrientation textOrientation = TextOrientationVerticalRight, FontWidthVariant widthVariant = RegularWidth) : m_size(size) , m_weight(weight) , m_family(family) @@ -65,6 +66,7 @@ public: , m_printerFont(isPrinterFont) , m_renderingMode(renderingMode) , m_orientation(orientation) + , m_textOrientation(textOrientation) , m_widthVariant(widthVariant) { } @@ -76,7 +78,7 @@ public: { return equalIgnoringCase(m_family, other.m_family) && m_size == other.m_size && m_weight == other.m_weight && m_italic == other.m_italic && m_printerFont == other.m_printerFont && - m_renderingMode == other.m_renderingMode && m_orientation == other.m_orientation && m_widthVariant == other.m_widthVariant; + m_renderingMode == other.m_renderingMode && m_orientation == other.m_orientation && m_textOrientation == other.m_textOrientation && m_widthVariant == other.m_widthVariant; } unsigned m_size; @@ -86,6 +88,7 @@ public: bool m_printerFont; FontRenderingMode m_renderingMode; FontOrientation m_orientation; + TextOrientation m_textOrientation; FontWidthVariant m_widthVariant; private: @@ -99,9 +102,9 @@ inline unsigned computeHash(const FontPlatformDataCacheKey& fontKey) fontKey.m_size, fontKey.m_weight, fontKey.m_widthVariant, - static_cast<unsigned>(fontKey.m_orientation) << 3 | static_cast<unsigned>(fontKey.m_italic) << 2 | static_cast<unsigned>(fontKey.m_printerFont) << 1 | static_cast<unsigned>(fontKey.m_renderingMode) + static_cast<unsigned>(fontKey.m_textOrientation) << 4 | static_cast<unsigned>(fontKey.m_orientation) << 3 | static_cast<unsigned>(fontKey.m_italic) << 2 | static_cast<unsigned>(fontKey.m_printerFont) << 1 | static_cast<unsigned>(fontKey.m_renderingMode) }; - return WTF::StringHasher::createBlobHash<sizeof(hashCodes)>(hashCodes); + return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes); } struct FontPlatformDataCacheKeyHash { @@ -198,7 +201,8 @@ FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fo } FontPlatformDataCacheKey key(familyName, fontDescription.computedPixelSize(), fontDescription.weight(), fontDescription.italic(), - fontDescription.usePrinterFont(), fontDescription.renderingMode(), fontDescription.orientation(), fontDescription.widthVariant()); + fontDescription.usePrinterFont(), fontDescription.renderingMode(), fontDescription.orientation(), + fontDescription.textOrientation(), fontDescription.widthVariant()); FontPlatformData* result = 0; bool foundResult; FontPlatformDataCache::iterator it = gFontPlatformDataCache->find(key); diff --git a/Source/WebCore/platform/graphics/FontDescription.h b/Source/WebCore/platform/graphics/FontDescription.h index 283d297..5b05f14 100644 --- a/Source/WebCore/platform/graphics/FontDescription.h +++ b/Source/WebCore/platform/graphics/FontDescription.h @@ -31,6 +31,7 @@ #include "FontSmoothingMode.h" #include "FontTraitsMask.h" #include "FontWidthVariant.h" +#include "TextOrientation.h" #include "TextRenderingMode.h" namespace WebCore { @@ -58,6 +59,7 @@ public: : m_specifiedSize(0) , m_computedSize(0) , m_orientation(Horizontal) + , m_textOrientation(TextOrientationVerticalRight) , m_widthVariant(RegularWidth) , m_italic(false) , m_smallCaps(false) @@ -99,6 +101,7 @@ public: FontTraitsMask traitsMask() const; bool isSpecifiedFont() const { return m_isSpecifiedFont; } FontOrientation orientation() const { return m_orientation; } + TextOrientation textOrientation() const { return m_textOrientation; } FontWidthVariant widthVariant() const { return m_widthVariant; } void setFamily(const FontFamily& family) { m_familyList = family; } @@ -120,6 +123,7 @@ public: void setTextRenderingMode(TextRenderingMode rendering) { m_textRendering = rendering; } void setIsSpecifiedFont(bool isSpecifiedFont) { m_isSpecifiedFont = isSpecifiedFont; } void setOrientation(FontOrientation orientation) { m_orientation = orientation; } + void setTextOrientation(TextOrientation textOrientation) { m_textOrientation = textOrientation; } void setWidthVariant(FontWidthVariant widthVariant) { m_widthVariant = widthVariant; } private: @@ -129,8 +133,9 @@ private: // rounding, minimum font sizes, and zooming. float m_computedSize; // Computed size adjusted for the minimum font size and the zoom factor. - FontOrientation m_orientation; - + FontOrientation m_orientation; // Whether the font is rendering on a horizontal line or a vertical line. + TextOrientation m_textOrientation; // Only used by vertical text. Determines the default orientation for non-ideograph glyphs. + FontWidthVariant m_widthVariant; bool m_italic : 1; @@ -169,6 +174,7 @@ inline bool FontDescription::operator==(const FontDescription& other) const && m_textRendering == other.m_textRendering && m_isSpecifiedFont == other.m_isSpecifiedFont && m_orientation == other.m_orientation + && m_textOrientation == other.m_textOrientation && m_widthVariant == other.m_widthVariant; } diff --git a/Source/WebCore/platform/graphics/FontFallbackList.cpp b/Source/WebCore/platform/graphics/FontFallbackList.cpp index 649c117..7df58d9 100644 --- a/Source/WebCore/platform/graphics/FontFallbackList.cpp +++ b/Source/WebCore/platform/graphics/FontFallbackList.cpp @@ -111,23 +111,6 @@ const FontData* FontFallbackList::fontDataAt(const Font* font, unsigned realized return result; } -const FontData* FontFallbackList::fontDataForCharacters(const Font* font, const UChar* characters, int length) const -{ - // This method is only called when the primary font does not contain the characters we need. - // Begin our search at position 1. - unsigned realizedFontIndex = 1; - const FontData* fontData = fontDataAt(font, realizedFontIndex); - while (fontData && !fontData->containsCharacters(characters, length)) - fontData = fontDataAt(font, ++realizedFontIndex); - - if (!fontData) { - ASSERT(fontCache()->generation() == m_generation); - fontData = fontCache()->getFontDataForCharacters(*font, characters, length); - } - - return fontData; -} - void FontFallbackList::setPlatformFont(const FontPlatformData& platformData) { m_familyIndex = cAllFamiliesScanned; diff --git a/Source/WebCore/platform/graphics/FontFallbackList.h b/Source/WebCore/platform/graphics/FontFallbackList.h index a10f5af..e18477c 100644 --- a/Source/WebCore/platform/graphics/FontFallbackList.h +++ b/Source/WebCore/platform/graphics/FontFallbackList.h @@ -65,8 +65,7 @@ private: const FontData* primaryFontData(const Font* f) const { return fontDataAt(f, 0); } const FontData* fontDataAt(const Font*, unsigned index) const; - const FontData* fontDataForCharacters(const Font*, const UChar*, int length) const; - + void setPlatformFont(const FontPlatformData&); void releaseFontData(); diff --git a/Source/WebCore/platform/graphics/FontFastPath.cpp b/Source/WebCore/platform/graphics/FontFastPath.cpp index e62df61..b741ca0 100644 --- a/Source/WebCore/platform/graphics/FontFastPath.cpp +++ b/Source/WebCore/platform/graphics/FontFastPath.cpp @@ -77,17 +77,57 @@ GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, FontDataVariant va page = node->page(); if (page) { GlyphData data = page->glyphDataForCharacter(c); + if (data.fontData && (data.fontData->platformData().orientation() == Horizontal || data.fontData->isTextOrientationFallback())) + return data; + if (data.fontData) { - if (data.fontData->platformData().orientation() == Vertical && data.fontData->orientation() == Horizontal && Font::isCJKIdeographOrSymbol(c)) { - const SimpleFontData* ideographFontData = data.fontData->brokenIdeographFontData(); - GlyphPageTreeNode* ideographNode = GlyphPageTreeNode::getRootChild(ideographFontData, pageNumber); - const GlyphPage* ideographPage = ideographNode->page(); - if (ideographPage) { - GlyphData data = ideographPage->glyphDataForCharacter(c); - if (data.fontData) - return data; + if (isCJKIdeographOrSymbol(c)) { + if (!data.fontData->hasVerticalGlyphs()) { + // Use the broken ideograph font data. The broken ideograph font will use the horizontal width of glyphs + // to make sure you get a square (even for broken glyphs like symbols used for punctuation). + const SimpleFontData* brokenIdeographFontData = data.fontData->brokenIdeographFontData(); + GlyphPageTreeNode* brokenIdeographNode = GlyphPageTreeNode::getRootChild(brokenIdeographFontData, pageNumber); + const GlyphPage* brokenIdeographPage = brokenIdeographNode->page(); + if (brokenIdeographPage) { + GlyphData brokenIdeographData = brokenIdeographPage->glyphDataForCharacter(c); + if (brokenIdeographData.fontData) + return brokenIdeographData; + } + + // Shouldn't be possible to even reach this point. + ASSERT_NOT_REACHED(); + } + } else { + if (m_fontDescription.textOrientation() == TextOrientationVerticalRight) { + const SimpleFontData* verticalRightFontData = data.fontData->verticalRightOrientationFontData(); + GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData, pageNumber); + const 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 data; + // The glyphs are identical, meaning that we should just use the horizontal glyph. + if (verticalRightData.fontData) + return verticalRightData; + } + } else if (m_fontDescription.textOrientation() == TextOrientationUpright) { + const SimpleFontData* uprightFontData = data.fontData->uprightOrientationFontData(); + GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData, pageNumber); + const 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 data; + // 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 uprightData; + } } - + // Shouldn't be possible to even reach this point. ASSERT_NOT_REACHED(); } @@ -364,7 +404,7 @@ void Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuf inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph) { - if (fontData->orientation() == Horizontal) { + if (fontData->platformData().orientation() == Horizontal) { FloatRect bounds = fontData->boundsForGlyph(glyph); return bounds.x() + bounds.width() / 2; } @@ -412,8 +452,8 @@ float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer it.advance(run.length(), glyphBuffer); if (glyphOverflow) { - glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - fontMetrics().ascent()); - glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - fontMetrics().descent()); + glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent())); + glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent())); glyphOverflow->left = ceilf(it.firstGlyphOverflow()); glyphOverflow->right = ceilf(it.lastGlyphOverflow()); } diff --git a/Source/WebCore/platform/graphics/FontPlatformData.cpp b/Source/WebCore/platform/graphics/FontPlatformData.cpp new file mode 100644 index 0000000..5a61cdf --- /dev/null +++ b/Source/WebCore/platform/graphics/FontPlatformData.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2011 Brent Fulgham + * + * 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 "FontPlatformData.h" + +#include "PlatformString.h" +#include <wtf/HashMap.h> +#include <wtf/RetainPtr.h> +#include <wtf/Vector.h> +#include <wtf/text/StringHash.h> + +using namespace std; + +namespace WebCore { + +FontPlatformData::FontPlatformData(const FontPlatformData& source) + : m_syntheticBold(source.m_syntheticBold) + , m_syntheticOblique(source.m_syntheticOblique) + , m_orientation(source.m_orientation) + , m_textOrientation(source.m_textOrientation) + , m_size(source.m_size) + , m_widthVariant(source.m_widthVariant) + , m_isColorBitmapFont(source.m_isColorBitmapFont) +{ + platformDataInit(source); +} + +const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other) +{ + // Check for self-assignment. + if (this == &other) + return *this; + + m_syntheticBold = other.m_syntheticBold; + m_syntheticOblique = other.m_syntheticOblique; + m_orientation = other.m_orientation; + m_textOrientation = other.m_textOrientation; + m_size = other.m_size; + m_widthVariant = other.m_widthVariant; + m_isColorBitmapFont = other.m_isColorBitmapFont; + + return platformDataAssign(other); +} + +} diff --git a/Source/WebCore/platform/graphics/FontPlatformData.h b/Source/WebCore/platform/graphics/FontPlatformData.h new file mode 100644 index 0000000..5981c16 --- /dev/null +++ b/Source/WebCore/platform/graphics/FontPlatformData.h @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. + * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com + * Copyright (C) 2007 Holger Hans Peter Freyther + * Copyright (C) 2007 Pioneer Research Center USA, Inc. + * Copyright (C) 2010, 2011 Brent Fulgham <bfulgham@webkit.org> + * + * 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. + * + */ + +// FIXME: This is temporary until all ports switch to using this file. +#if PLATFORM(CHROMIUM) && !OS(DARWIN) +#include "chromium/FontPlatformData.h" +#elif PLATFORM(QT) +#include "qt/FontPlatformData.h" +#elif PLATFORM(WIN) && OS(WINCE) +#include "wince/FontPlatformData.h" +#elif PLATFORM(WX) +#include "wx/FontPlatformData.h" +#elif (PLATFORM(EFL) || PLATFORM(GTK)) && USE(FREETYPE) +#include "freetype/FontPlatformData.h" +#elif (PLATFORM(EFL) || PLATFORM(GTK)) && USE(PANGO) +#include "pango/FontPlatformData.h" +#elif PLATFORM(ANDROID) +#include "android/FontPlatformData.h" +#else + +#ifndef FontPlatformData_h +#define FontPlatformData_h + +#include "FontOrientation.h" +#include "FontWidthVariant.h" +#include "GlyphBuffer.h" +#include "TextOrientation.h" + +#if PLATFORM(WIN) +#include "RefCountedGDIHandle.h" +#endif + +#if PLATFORM(CAIRO) +#include "HashFunctions.h" +#include <cairo.h> +#endif + +#if OS(DARWIN) +#ifdef __OBJC__ +@class NSFont; +#else +class NSFont; +#endif + +typedef struct CGFont* CGFontRef; +#ifndef BUILDING_ON_TIGER +typedef const struct __CTFont* CTFontRef; +#endif + +#include <CoreFoundation/CFBase.h> +#include <objc/objc-auto.h> +#endif + +#include <wtf/Forward.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RetainPtr.h> +#include <wtf/text/StringImpl.h> + +#if PLATFORM(CHROMIUM) && OS(DARWIN) +#include "CrossProcessFontLoading.h" +#endif + +#if PLATFORM(WIN) +typedef struct HFONT__* HFONT; +#endif + +#if PLATFORM(CG) +typedef struct CGFont* CGFontRef; +#if OS(DARWIN) +#ifndef BUILDING_ON_TIGER +typedef const struct __CTFont* CTFontRef; +typedef UInt32 ATSUFontID; +typedef UInt32 ATSFontRef; +#endif +#endif +#endif + +namespace WebCore { + +class FontDescription; + +#if OS(DARWIN) && !defined(BUILDING_ON_TIGER) +inline CTFontRef toCTFontRef(NSFont *nsFont) { return reinterpret_cast<CTFontRef>(nsFont); } +#endif + +class FontPlatformData { +public: + FontPlatformData(WTF::HashTableDeletedValueType) + : m_syntheticBold(false) + , m_syntheticOblique(false) + , m_orientation(Horizontal) + , m_textOrientation(TextOrientationVerticalRight) + , m_size(0) + , m_widthVariant(RegularWidth) +#if PLATFORM(WIN) + , m_font(WTF::HashTableDeletedValue) +#elif OS(DARWIN) + , m_font(hashTableDeletedFontValue()) +#endif +#if PLATFORM(CG) && (defined(BUILDING_ON_TIGER) || PLATFORM(WIN)) + , m_cgFont(0) +#elif PLATFORM(CAIRO) + , m_scaledFont(hashTableDeletedFontValue()) +#endif + , m_isColorBitmapFont(false) +#if PLATFORM(WIN) + , m_useGDI(false) +#endif + { + } + + FontPlatformData() + : m_syntheticBold(false) + , m_syntheticOblique(false) + , m_orientation(Horizontal) + , m_textOrientation(TextOrientationVerticalRight) + , m_size(0) + , m_widthVariant(RegularWidth) +#if OS(DARWIN) + , m_font(0) +#endif +#if PLATFORM(CG) && (defined(BUILDING_ON_TIGER) || PLATFORM(WIN)) + , m_cgFont(0) +#elif PLATFORM(CAIRO) + , m_scaledFont(0) +#endif + , m_isColorBitmapFont(false) +#if PLATFORM(WIN) + , m_useGDI(false) +#endif + { + } + + FontPlatformData(const FontPlatformData&); + FontPlatformData(const FontDescription&, const AtomicString& family); + FontPlatformData(float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation = Horizontal, + TextOrientation textOrientation = TextOrientationVerticalRight, FontWidthVariant widthVariant = RegularWidth) + : m_syntheticBold(syntheticBold) + , m_syntheticOblique(syntheticOblique) + , m_orientation(orientation) + , m_textOrientation(textOrientation) + , m_size(size) + , m_widthVariant(widthVariant) +#if OS(DARWIN) + , m_font(0) +#endif +#if PLATFORM(CG) && (defined(BUILDING_ON_TIGER) || PLATFORM(WIN)) + , m_cgFont(0) +#elif PLATFORM(CAIRO) + , m_scaledFont(0) +#endif + , m_isColorBitmapFont(false) +#if PLATFORM(WIN) + , m_useGDI(false) +#endif + { + } + +#if OS(DARWIN) + FontPlatformData(NSFont*, float size, bool syntheticBold = false, bool syntheticOblique = false, FontOrientation = Horizontal, + TextOrientation = TextOrientationVerticalRight, FontWidthVariant = RegularWidth); + FontPlatformData(CGFontRef cgFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation, + TextOrientation textOrientation, FontWidthVariant widthVariant) + : m_syntheticBold(syntheticBold) + , m_syntheticOblique(syntheticOblique) + , m_orientation(orientation) + , m_textOrientation(textOrientation) + , m_size(size) + , m_widthVariant(widthVariant) + , m_font(0) + , m_cgFont(cgFont) + , m_isColorBitmapFont(false) + { + } +#endif +#if PLATFORM(WIN) + FontPlatformData(HFONT, float size, bool syntheticBold, bool syntheticOblique, bool useGDI); +#if PLATFORM(CG) + FontPlatformData(HFONT, CGFontRef, float size, bool syntheticBold, bool syntheticOblique, bool useGDI); +#endif +#endif +#if PLATFORM(CAIRO) + FontPlatformData(cairo_font_face_t*, float size, bool bold, bool italic); +#endif + + ~FontPlatformData(); + +#if PLATFORM(WIN) + HFONT hfont() const { return m_font ? m_font->handle() : 0; } + bool useGDI() const { return m_useGDI; } +#elif OS(DARWIN) + NSFont* font() const { return m_font; } + void setFont(NSFont*); +#endif + +#if PLATFORM(CG) +#if OS(DARWIN) +#ifndef BUILDING_ON_TIGER + CGFontRef cgFont() const { return m_cgFont.get(); } +#else + CGFontRef cgFont() const { return m_cgFont; } +#endif + CTFontRef ctFont() const; + + bool roundsGlyphAdvances() const; + bool allowsLigatures() const; +#else + CGFontRef cgFont() const { return m_cgFont.get(); } +#endif +#endif + + bool isFixedPitch() const; + float size() const { return m_size; } + void setSize(float size) { m_size = size; } + bool syntheticBold() const { return m_syntheticBold; } + bool syntheticOblique() const { return m_syntheticOblique; } + bool isColorBitmapFont() const { return m_isColorBitmapFont; } + FontOrientation orientation() const { return m_orientation; } + TextOrientation textOrientation() const { return m_textOrientation; } + FontWidthVariant widthVariant() const { return m_widthVariant; } + + void setOrientation(FontOrientation orientation) { m_orientation = orientation; } + +#if PLATFORM(CAIRO) + cairo_scaled_font_t* scaledFont() const { return m_scaledFont; } +#endif + + unsigned hash() const + { +#if PLATFORM(WIN) && !PLATFORM(CAIRO) + return m_font ? m_font->hash() : 0; +#elif OS(DARWIN) + ASSERT(m_font || !m_cgFont); + uintptr_t hashCodes[3] = { (uintptr_t)m_font, m_widthVariant, m_textOrientation << 3 | m_orientation << 2 | m_syntheticBold << 1 | m_syntheticOblique }; + return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes); +#elif PLATFORM(CAIRO) + return PtrHash<cairo_scaled_font_t*>::hash(m_scaledFont); +#endif + } + + const FontPlatformData& operator=(const FontPlatformData&); + + bool operator==(const FontPlatformData& other) const + { + return platformIsEqual(other) + && m_size == other.m_size + && m_syntheticBold == other.m_syntheticBold + && m_syntheticOblique == other.m_syntheticOblique + && m_isColorBitmapFont == other.m_isColorBitmapFont + && m_orientation == other.m_orientation + && m_textOrientation == other.m_textOrientation + && m_widthVariant == other.m_widthVariant; + } + + bool isHashTableDeletedValue() const + { +#if PLATFORM(WIN) && !PLATFORM(CAIRO) + return m_font.isHashTableDeletedValue(); +#elif OS(DARWIN) + return m_font == hashTableDeletedFontValue(); +#elif PLATFORM(CAIRO) + return m_scaledFont == hashTableDeletedFontValue(); +#endif + } + + +#ifndef NDEBUG + String description() const; +#endif + +private: + bool platformIsEqual(const FontPlatformData&) const; + void platformDataInit(const FontPlatformData&); + const FontPlatformData& platformDataAssign(const FontPlatformData&); +#if OS(DARWIN) + // Load various data about the font specified by |nsFont| with the size fontSize into the following output paramters: + // Note: Callers should always take into account that for the Chromium port, |outNSFont| isn't necessarily the same + // font as |nsFont|. This because the sandbox may block loading of the original font. + // * outNSFont - The font that was actually loaded, for the Chromium port this may be different than nsFont. + // The caller is responsible for calling CFRelease() on this parameter when done with it. + // * cgFont - CGFontRef representing the input font at the specified point size. + void loadFont(NSFont*, float fontSize, NSFont*& outNSFont, CGFontRef&); + static NSFont* hashTableDeletedFontValue() { return reinterpret_cast<NSFont *>(-1); } +#elif PLATFORM(WIN) + void platformDataInit(HFONT, float size, HDC, WCHAR* faceName); +#endif + +#if PLATFORM(CAIRO) + static cairo_scaled_font_t* hashTableDeletedFontValue() { return reinterpret_cast<cairo_scaled_font_t*>(-1); } +#endif + +public: + bool m_syntheticBold; + bool m_syntheticOblique; + FontOrientation m_orientation; + TextOrientation m_textOrientation; + float m_size; + FontWidthVariant m_widthVariant; + +private: +#if OS(DARWIN) + NSFont* m_font; +#elif PLATFORM(WIN) + RefPtr<RefCountedGDIHandle<HFONT> > m_font; +#endif + +#if PLATFORM(CG) +#if PLATFORM(WIN) + RetainPtr<CGFontRef> m_cgFont; +#else +#ifndef BUILDING_ON_TIGER + RetainPtr<CGFontRef> m_cgFont; +#else + CGFontRef m_cgFont; // It is not necessary to refcount this, since either an NSFont owns it or some CachedFont has it referenced. +#endif + mutable RetainPtr<CTFontRef> m_CTFont; +#endif +#endif + +#if PLATFORM(CAIRO) + cairo_scaled_font_t* m_scaledFont; +#endif + +#if PLATFORM(CHROMIUM) && OS(DARWIN) + RefPtr<MemoryActivatedFont> m_inMemoryFont; +#endif + + bool m_isColorBitmapFont; + +#if PLATFORM(WIN) + bool m_useGDI; +#endif +}; + +} // namespace WebCore + +#endif // FontPlatformData_h + +#endif diff --git a/Source/WebCore/platform/graphics/GraphicsContext.h b/Source/WebCore/platform/graphics/GraphicsContext.h index 5eafa16..c555a5f 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext.h +++ b/Source/WebCore/platform/graphics/GraphicsContext.h @@ -42,8 +42,9 @@ typedef struct CGContext PlatformGraphicsContext; #elif PLATFORM(CAIRO) namespace WebCore { class ContextShadow; +class PlatformContextCairo; } -typedef struct _cairo PlatformGraphicsContext; +typedef WebCore::PlatformContextCairo PlatformGraphicsContext; #elif PLATFORM(OPENVG) namespace WebCore { class SurfaceOpenVG; @@ -279,6 +280,9 @@ namespace WebCore { void setIsCALayerContext(bool); bool isCALayerContext() const; + + void setIsAcceleratedContext(bool); + bool isAcceleratedContext() const; #endif #if PLATFORM(ANDROID) @@ -522,6 +526,7 @@ namespace WebCore { #endif #if PLATFORM(CAIRO) + GraphicsContext(cairo_t*); void pushImageMask(cairo_surface_t*, const FloatRect&); #endif diff --git a/Source/WebCore/platform/graphics/GraphicsContext3D.h b/Source/WebCore/platform/graphics/GraphicsContext3D.h index a9db650..351b445 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext3D.h +++ b/Source/WebCore/platform/graphics/GraphicsContext3D.h @@ -51,8 +51,8 @@ @class CALayer; @class WebGLLayer; #else -typedef void* CALayer; -typedef void* WebGLLayer; +class CALayer; +class WebGLLayer; #endif #elif PLATFORM(QT) QT_BEGIN_NAMESPACE @@ -420,6 +420,7 @@ public: , antialias(true) , premultipliedAlpha(true) , canRecoverFromContextLoss(true) + , preserveDrawingBuffer(false) { } @@ -429,6 +430,7 @@ public: bool antialias; bool premultipliedAlpha; bool canRecoverFromContextLoss; + bool preserveDrawingBuffer; }; enum RenderStyle { @@ -449,8 +451,8 @@ public: #if PLATFORM(MAC) PlatformGraphicsContext3D platformGraphicsContext3D() const { return m_contextObj; } - Platform3DObject platformTexture() const { return m_texture; } - CALayer* platformLayer() const { return static_cast<CALayer*>(m_webGLLayer.get()); } + Platform3DObject platformTexture() const { return m_compositorTexture; } + CALayer* platformLayer() const { return reinterpret_cast<CALayer*>(m_webGLLayer.get()); } #elif PLATFORM(CHROMIUM) PlatformGraphicsContext3D platformGraphicsContext3D() const; Platform3DObject platformTexture() const; @@ -461,7 +463,7 @@ public: PlatformGraphicsContext3D platformGraphicsContext3D(); Platform3DObject platformTexture() const; #if USE(ACCELERATED_COMPOSITING) - PlatformLayer* platformLayer() const { return 0; } + PlatformLayer* platformLayer() const; #endif #else PlatformGraphicsContext3D platformGraphicsContext3D() const { return NullPlatformGraphicsContext3D; } @@ -756,10 +758,14 @@ public: int canvasWidth, int canvasHeight, CGContextRef context); #endif + void markContextChanged(); + void markLayerComposited(); + bool layerComposited() const; + void paintRenderingResultsToCanvas(CanvasRenderingContext* context); + PassRefPtr<ImageData> paintRenderingResultsToImageData(); #if PLATFORM(QT) - void paint(QPainter* painter, const QRect& rect) const; bool paintsIntoCanvasBuffer() const { return true; } #elif PLATFORM(CHROMIUM) bool paintsIntoCanvasBuffer() const; @@ -859,6 +865,10 @@ public: // could not be honored based on the capabilities of the OpenGL // implementation. void validateAttributes(); + + // Read rendering results into a pixel array with the same format as the + // backbuffer. + void readRenderingResults(unsigned char* pixels, int pixelsSize); #endif int m_currentWidth, m_currentHeight; @@ -881,12 +891,16 @@ public: CGLContextObj m_contextObj; RetainPtr<WebGLLayer> m_webGLLayer; - GC3Duint m_texture; + GC3Duint m_texture, m_compositorTexture; GC3Duint m_fbo; GC3Duint m_depthStencilBuffer; + bool m_layerComposited; + GC3Duint m_internalColorFormat; - // For tracking which FBO is bound + // For tracking which FBO/texture is bound GC3Duint m_boundFBO; + GC3Denum m_activeTexture; + GC3Duint m_boundTexture0; // For multisampling GC3Duint m_multisampleFBO; diff --git a/Source/WebCore/platform/graphics/GraphicsLayer.h b/Source/WebCore/platform/graphics/GraphicsLayer.h index e3a62b6..4f234d4 100644 --- a/Source/WebCore/platform/graphics/GraphicsLayer.h +++ b/Source/WebCore/platform/graphics/GraphicsLayer.h @@ -46,12 +46,11 @@ #if PLATFORM(MAC) #ifdef __OBJC__ -@class WebLayer; @class CALayer; -typedef CALayer PlatformLayer; #else -typedef void* PlatformLayer; +class CALayer; #endif +typedef CALayer PlatformLayer; #elif PLATFORM(WIN) typedef struct _CACFLayer PlatformLayer; #elif PLATFORM(QT) diff --git a/Source/WebCore/platform/graphics/ImageBuffer.h b/Source/WebCore/platform/graphics/ImageBuffer.h index 48878da..860f574 100644 --- a/Source/WebCore/platform/graphics/ImageBuffer.h +++ b/Source/WebCore/platform/graphics/ImageBuffer.h @@ -132,6 +132,10 @@ namespace WebCore { ImageBuffer(const IntSize&, ColorSpace colorSpace, RenderingMode renderingMode, bool& success); }; +#if PLATFORM(CG) || USE(SKIA) + String ImageDataToDataURL(const ImageData& input, const String& mimeType, const double* quality); +#endif + } // namespace WebCore #endif // ImageBuffer_h diff --git a/Source/WebCore/platform/graphics/MediaPlayer.cpp b/Source/WebCore/platform/graphics/MediaPlayer.cpp index 70576a5..03004b6 100644 --- a/Source/WebCore/platform/graphics/MediaPlayer.cpp +++ b/Source/WebCore/platform/graphics/MediaPlayer.cpp @@ -47,6 +47,9 @@ #if PLATFORM(MAC) #include "MediaPlayerPrivateQTKit.h" +#if USE(AVFOUNDATION) +#include "MediaPlayerPrivateAVFoundationObjC.h" +#endif #define PlatformMediaEngineClassName MediaPlayerPrivateQTKit #elif OS(WINCE) && !PLATFORM(QT) #include "MediaPlayerPrivateWinCE.h" @@ -82,7 +85,7 @@ public: virtual void load(const String&) { } virtual void cancelLoad() { } - + virtual void prepareToPlay() { } virtual void play() { } virtual void pause() { } @@ -189,11 +192,15 @@ static Vector<MediaPlayerFactory*>& installedMediaEngines() MediaPlayerPrivateGStreamer::registerMediaEngine(addMediaEngine); #endif +#if USE(AVFOUNDATION) && PLATFORM(MAC) + MediaPlayerPrivateAVFoundationObjC::registerMediaEngine(addMediaEngine); +#endif + #if !PLATFORM(GTK) && !PLATFORM(EFL) && !(PLATFORM(QT) && USE(GSTREAMER)) PlatformMediaEngineClassName::registerMediaEngine(addMediaEngine); #endif } - + return installedEngines; } @@ -241,7 +248,7 @@ static MediaPlayerFactory* bestMediaEngineForTypeAndCodecs(const String& type, c if (!codecs.isEmpty()) return 0; } - + MediaPlayerFactory* engine = 0; MediaPlayer::SupportsType supported = MediaPlayer::IsNotSupported; unsigned count = engines.size(); @@ -292,6 +299,7 @@ MediaPlayer::MediaPlayer(MediaPlayerClient* client) , m_muted(false) , m_preservesPitch(true) , m_privateBrowsing(false) + , m_shouldPrepareToRender(false) #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) , m_playerProxy(0) #endif @@ -351,7 +359,7 @@ void MediaPlayer::loadWithNextMediaEngine(MediaPlayerFactory* current) engine = nextMediaEngine(current); else engine = bestMediaEngineForTypeAndCodecs(m_contentMIMEType, m_contentTypeCodecs, current); - + // Don't delete and recreate the player unless it comes from a different engine. if (!engine) { m_currentMediaEngine = engine; @@ -368,6 +376,8 @@ void MediaPlayer::loadWithNextMediaEngine(MediaPlayerFactory* current) m_private->setPrivateBrowsingMode(m_privateBrowsing); m_private->setPreload(m_preload); m_private->setPreservesPitch(preservesPitch()); + if (m_shouldPrepareToRender) + m_private->prepareForRendering(); } if (m_private) @@ -383,17 +393,18 @@ bool MediaPlayer::hasAvailableVideoFrame() const { return m_private->hasAvailableVideoFrame(); } - + void MediaPlayer::prepareForRendering() { - return m_private->prepareForRendering(); + m_shouldPrepareToRender = true; + m_private->prepareForRendering(); } - + bool MediaPlayer::canLoadPoster() const { return m_private->canLoadPoster(); } - + void MediaPlayer::setPoster(const String& url) { m_private->setPoster(url); @@ -408,7 +419,7 @@ void MediaPlayer::prepareToPlay() { m_private->prepareToPlay(); } - + void MediaPlayer::play() { m_private->play(); @@ -478,7 +489,7 @@ bool MediaPlayer::inMediaDocument() { Frame* frame = m_frameView ? m_frameView->frame() : 0; Document* document = frame ? frame->document() : 0; - + return document && document->isMediaDocument(); } diff --git a/Source/WebCore/platform/graphics/MediaPlayer.h b/Source/WebCore/platform/graphics/MediaPlayer.h index f41af01..ff304ea 100644 --- a/Source/WebCore/platform/graphics/MediaPlayer.h +++ b/Source/WebCore/platform/graphics/MediaPlayer.h @@ -46,8 +46,10 @@ #endif #ifdef __OBJC__ +@class AVPlayer; @class QTMovie; #else +class AVPlayer; class QTMovie; #endif class QTMovieGWorld; @@ -71,6 +73,7 @@ struct PlatformMedia { GStreamerGWorldType, ChromiumMediaPlayerType, QtMediaPlayerType, + AVFoundationMediaPlayerType, } type; union { @@ -80,6 +83,7 @@ struct PlatformMedia { GStreamerGWorld* gstreamerGWorld; MediaPlayerPrivateInterface* chromiumMediaPlayer; MediaPlayerPrivateInterface* qtMediaPlayer; + AVPlayer* avfMediaPlayer; } media; }; @@ -115,10 +119,10 @@ public: // time has jumped, eg. not as a result of normal playback virtual void mediaPlayerTimeChanged(MediaPlayer*) { } - + // the media file duration has changed, or is now known virtual void mediaPlayerDurationChanged(MediaPlayer*) { } - + // the playback rate has changed virtual void mediaPlayerRateChanged(MediaPlayer*) { } @@ -183,44 +187,44 @@ public: void setMediaElementType(MediaElementType type) { m_mediaElementType = type; } MediaElementType mediaElementType() { return m_mediaElementType; } #endif - + void setFrameView(FrameView* frameView) { m_frameView = frameView; } FrameView* frameView() { return m_frameView; } bool inMediaDocument(); - + IntSize size() const { return m_size; } void setSize(const IntSize& size); - + void load(const String& url, const ContentType&); void cancelLoad(); - + bool visible() const; void setVisible(bool); - + void prepareToPlay(); void play(); void pause(); - + bool paused() const; bool seeking() const; - + float duration() const; float currentTime() const; void seek(float time); float startTime() const; - + float rate() const; void setRate(float); bool preservesPitch() const; void setPreservesPitch(bool); - + PassRefPtr<TimeRanges> buffered(); float maxTimeSeekable(); unsigned bytesLoaded(); - + float volume() const; void setVolume(float); @@ -235,13 +239,13 @@ public: void paint(GraphicsContext*, const IntRect&); void paintCurrentFrameInContext(GraphicsContext*, const IntRect&); - + enum NetworkState { Empty, Idle, Loading, Loaded, FormatError, NetworkError, DecodeError }; NetworkState networkState(); enum ReadyState { HaveNothing, HaveMetadata, HaveCurrentData, HaveFutureData, HaveEnoughData }; ReadyState readyState(); - + enum MovieLoadType { Unknown, Download, StoredStream, LiveStream }; MovieLoadType movieLoadType() const; @@ -320,6 +324,7 @@ private: bool m_muted; bool m_preservesPitch; bool m_privateBrowsing; + bool m_shouldPrepareToRender; #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) WebMediaPlayerProxy* m_playerProxy; // not owned or used, passed to m_private #endif diff --git a/Source/WebCore/platform/graphics/Path.cpp b/Source/WebCore/platform/graphics/Path.cpp index 55760b1..f7aedbe 100644 --- a/Source/WebCore/platform/graphics/Path.cpp +++ b/Source/WebCore/platform/graphics/Path.cpp @@ -83,14 +83,14 @@ static void pathLengthApplierFunction(void* info, const PathElement* element) } } -float Path::length() +float Path::length() const { PathTraversalState traversalState(PathTraversalState::TraversalTotalLength); apply(&traversalState, pathLengthApplierFunction); return traversalState.m_totalLength; } -FloatPoint Path::pointAtLength(float length, bool& ok) +FloatPoint Path::pointAtLength(float length, bool& ok) const { PathTraversalState traversalState(PathTraversalState::TraversalPointAtLength); traversalState.m_desiredLength = length; @@ -99,10 +99,10 @@ FloatPoint Path::pointAtLength(float length, bool& ok) return traversalState.m_current; } -float Path::normalAngleAtLength(float length, bool& ok) +float Path::normalAngleAtLength(float length, bool& ok) const { PathTraversalState traversalState(PathTraversalState::TraversalNormalAngleAtLength); - traversalState.m_desiredLength = length; + traversalState.m_desiredLength = length ? length : std::numeric_limits<float>::epsilon(); apply(&traversalState, pathLengthApplierFunction); ok = traversalState.m_success; return traversalState.m_normalAngle; diff --git a/Source/WebCore/platform/graphics/Path.h b/Source/WebCore/platform/graphics/Path.h index 31f2cd6..c2ca576 100644 --- a/Source/WebCore/platform/graphics/Path.h +++ b/Source/WebCore/platform/graphics/Path.h @@ -112,11 +112,11 @@ namespace WebCore { bool contains(const FloatPoint&, WindRule rule = RULE_NONZERO) const; bool strokeContains(StrokeStyleApplier*, const FloatPoint&) const; FloatRect boundingRect() const; - FloatRect strokeBoundingRect(StrokeStyleApplier* = 0); + FloatRect strokeBoundingRect(StrokeStyleApplier* = 0) const; - float length(); - FloatPoint pointAtLength(float length, bool& ok); - float normalAngleAtLength(float length, bool& ok); + float length() const; + FloatPoint pointAtLength(float length, bool& ok) const; + float normalAngleAtLength(float length, bool& ok) const; void clear(); bool isEmpty() const; diff --git a/Source/WebCore/platform/graphics/SimpleFontData.cpp b/Source/WebCore/platform/graphics/SimpleFontData.cpp index aaab666..82f770d 100644 --- a/Source/WebCore/platform/graphics/SimpleFontData.cpp +++ b/Source/WebCore/platform/graphics/SimpleFontData.cpp @@ -47,15 +47,16 @@ using namespace std; namespace WebCore { -SimpleFontData::SimpleFontData(const FontPlatformData& platformData, bool isCustomFont, bool isLoading) +SimpleFontData::SimpleFontData(const FontPlatformData& platformData, bool isCustomFont, bool isLoading, bool isTextOrientationFallback) : m_maxCharWidth(-1) , m_avgCharWidth(-1) - , m_orientation(platformData.orientation()) , m_platformData(platformData) , m_treatAsFixedPitch(false) , m_isCustomFont(isCustomFont) , m_isLoading(isLoading) - , m_isBrokenIdeographFont(false) + , m_isTextOrientationFallback(isTextOrientationFallback) + , m_isBrokenIdeographFallback(false) + , m_hasVerticalGlyphs(false) { platformInit(); platformGlyphInit(); @@ -64,13 +65,14 @@ SimpleFontData::SimpleFontData(const FontPlatformData& platformData, bool isCust #if ENABLE(SVG_FONTS) SimpleFontData::SimpleFontData(PassOwnPtr<SVGFontData> svgFontData, int size, bool syntheticBold, bool syntheticItalic) - : m_orientation(Horizontal) - , m_platformData(FontPlatformData(size, syntheticBold, syntheticItalic)) + : m_platformData(FontPlatformData(size, syntheticBold, syntheticItalic)) , m_treatAsFixedPitch(false) , m_svgFontData(svgFontData) , m_isCustomFont(true) , m_isLoading(false) - , m_isBrokenIdeographFont(false) + , m_isTextOrientationFallback(false) + , m_isBrokenIdeographFallback(false) + , m_hasVerticalGlyphs(false) { SVGFontFaceElement* svgFontFaceElement = m_svgFontData->svgFontFaceElement(); unsigned unitsPerEm = svgFontFaceElement->unitsPerEm(); @@ -202,14 +204,34 @@ bool SimpleFontData::isSegmented() const return false; } +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 = new SimpleFontData(verticalRightPlatformData, isCustomFont(), false, true); + } + return m_derivedFontData->verticalRightOrientation.get(); +} + +SimpleFontData* SimpleFontData::uprightOrientationFontData() const +{ + if (!m_derivedFontData) + m_derivedFontData = DerivedFontData::create(isCustomFont()); + if (!m_derivedFontData->uprightOrientation) + m_derivedFontData->uprightOrientation = new SimpleFontData(m_platformData, isCustomFont(), false, true); + return m_derivedFontData->uprightOrientation.get(); +} + SimpleFontData* SimpleFontData::brokenIdeographFontData() const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->brokenIdeograph) { m_derivedFontData->brokenIdeograph = new SimpleFontData(m_platformData, isCustomFont(), false); - m_derivedFontData->brokenIdeograph->m_orientation = Vertical; - m_derivedFontData->brokenIdeograph->m_isBrokenIdeographFont = true; + m_derivedFontData->brokenIdeograph->m_isBrokenIdeographFallback = true; } return m_derivedFontData->brokenIdeograph.get(); } @@ -242,6 +264,10 @@ SimpleFontData::DerivedFontData::~DerivedFontData() GlyphPageTreeNode::pruneTreeCustomFontData(emphasisMark.get()); if (brokenIdeograph) GlyphPageTreeNode::pruneTreeCustomFontData(brokenIdeograph.get()); + if (verticalRightOrientation) + GlyphPageTreeNode::pruneTreeCustomFontData(verticalRightOrientation.get()); + if (uprightOrientation) + GlyphPageTreeNode::pruneTreeCustomFontData(uprightOrientation.get()); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/SimpleFontData.h b/Source/WebCore/platform/graphics/SimpleFontData.h index 93d33bb..dfb4be3 100644 --- a/Source/WebCore/platform/graphics/SimpleFontData.h +++ b/Source/WebCore/platform/graphics/SimpleFontData.h @@ -71,7 +71,7 @@ enum Pitch { UnknownPitch, FixedPitch, VariablePitch }; class SimpleFontData : public FontData { public: - SimpleFontData(const FontPlatformData&, bool isCustomFont = false, bool isLoading = false); + SimpleFontData(const FontPlatformData&, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false); #if ENABLE(SVG_FONTS) SimpleFontData(PassOwnPtr<SVGFontData>, int size, bool syntheticBold, bool syntheticItalic); #endif @@ -97,11 +97,13 @@ public: return const_cast<SimpleFontData*>(this); } + SimpleFontData* verticalRightOrientationFontData() const; + SimpleFontData* uprightOrientationFontData() const; SimpleFontData* brokenIdeographFontData() const; - - // FIXME: Use the actual metrics for fonts with vertical tables instead of just hard-coding. If the font is horizontally oriented or - // a broken ideographic font, then just hard-code to split ascent/descent down the middle. Otherwise we should actually use the metrics - // from the font itself. + + bool hasVerticalGlyphs() const { return m_hasVerticalGlyphs; } + bool isTextOrientationFallback() const { return m_isTextOrientationFallback; } + const FontMetrics& fontMetrics() const { return m_fontMetrics; } float maxCharWidth() const { return m_maxCharWidth; } float avgCharWidth() const { return m_avgCharWidth; } @@ -137,8 +139,6 @@ public: virtual bool isLoading() const { return m_isLoading; } virtual bool isSegmented() const; - bool isBrokenIdeographFont() const { return m_isBrokenIdeographFont; } - const GlyphData& missingGlyphData() const { return m_missingGlyphData; } #ifndef NDEBUG @@ -152,7 +152,7 @@ public: #endif #if PLATFORM(MAC) || USE(CORE_TEXT) - CFDictionaryRef getCFStringAttributes(TypesettingFeatures) const; + CFDictionaryRef getCFStringAttributes(TypesettingFeatures, FontOrientation) const; #endif #if USE(ATSUI) @@ -183,8 +183,6 @@ public: wxFont* getWxFont() const { return m_platformData.font(); } #endif - FontOrientation orientation() const { return m_orientation; } - private: void platformInit(); void platformGlyphInit(); @@ -209,9 +207,6 @@ private: float m_maxCharWidth; float m_avgCharWidth; - FontOrientation m_orientation; // This is our supported orientation according to the tables in the font. FontPlatformData will just always have the desired orientation. - // This value represents what we actually support. - FontPlatformData m_platformData; mutable OwnPtr<GlyphMetricsMap<FloatRect> > m_glyphToBoundsMap; @@ -225,8 +220,11 @@ private: bool m_isCustomFont; // Whether or not we are custom font loaded via @font-face bool m_isLoading; // Whether or not this custom font is still in the act of loading. - bool m_isBrokenIdeographFont; - + + bool m_isTextOrientationFallback; + bool m_isBrokenIdeographFallback; + bool m_hasVerticalGlyphs; + Glyph m_spaceGlyph; float m_spaceWidth; @@ -242,6 +240,8 @@ private: OwnPtr<SimpleFontData> smallCaps; OwnPtr<SimpleFontData> emphasisMark; OwnPtr<SimpleFontData> brokenIdeograph; + OwnPtr<SimpleFontData> verticalRightOrientation; + OwnPtr<SimpleFontData> uprightOrientation; private: DerivedFontData(bool custom) diff --git a/Source/WebCore/platform/graphics/TextRun.h b/Source/WebCore/platform/graphics/TextRun.h index 4e0980b..ec763b9 100644 --- a/Source/WebCore/platform/graphics/TextRun.h +++ b/Source/WebCore/platform/graphics/TextRun.h @@ -33,17 +33,21 @@ class RenderSVGResource; class TextRun { public: - enum TrailingExpansionBehavior { - AllowTrailingExpansion, - ForbidTrailingExpansion + enum ExpansionBehaviorFlags { + ForbidTrailingExpansion = 0 << 0, + AllowTrailingExpansion = 1 << 0, + ForbidLeadingExpansion = 0 << 1, + AllowLeadingExpansion = 1 << 1, }; - TextRun(const UChar* c, int len, bool allowTabs = false, float xpos = 0, float expansion = 0, TrailingExpansionBehavior trailingExpansionBehavior = AllowTrailingExpansion, bool rtl = false, bool directionalOverride = false) + typedef unsigned ExpansionBehavior; + + TextRun(const UChar* c, int len, bool allowTabs = false, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, bool rtl = false, bool directionalOverride = false) : m_characters(c) , m_len(len) , m_xpos(xpos) , m_expansion(expansion) - , m_trailingExpansionBehavior(trailingExpansionBehavior) + , m_expansionBehavior(expansionBehavior) #if ENABLE(SVG) , m_horizontalGlyphStretch(1) #endif @@ -58,12 +62,12 @@ public: { } - TextRun(const String& s, bool allowTabs = false, float xpos = 0, float expansion = 0, TrailingExpansionBehavior trailingExpansionBehavior = AllowTrailingExpansion, bool rtl = false, bool directionalOverride = false) + TextRun(const String& s, bool allowTabs = false, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, bool rtl = false, bool directionalOverride = false) : m_characters(s.characters()) , m_len(s.length()) , m_xpos(xpos) , m_expansion(expansion) - , m_trailingExpansionBehavior(trailingExpansionBehavior) + , m_expansionBehavior(expansionBehavior) #if ENABLE(SVG) , m_horizontalGlyphStretch(1) #endif @@ -94,7 +98,8 @@ public: bool allowTabs() const { return m_allowTabs; } float xPos() const { return m_xpos; } float expansion() const { return m_expansion; } - bool allowsTrailingExpansion() const { return m_trailingExpansionBehavior == AllowTrailingExpansion; } + bool allowsLeadingExpansion() const { return m_expansionBehavior & AllowLeadingExpansion; } + bool allowsTrailingExpansion() const { return m_expansionBehavior & AllowTrailingExpansion; } bool rtl() const { return m_rtl; } bool ltr() const { return !m_rtl; } bool directionalOverride() const { return m_directionalOverride; } @@ -121,7 +126,7 @@ private: // the text line is not the same as left start of the containing block. float m_xpos; float m_expansion; - TrailingExpansionBehavior m_trailingExpansionBehavior; + ExpansionBehavior m_expansionBehavior; #if ENABLE(SVG) float m_horizontalGlyphStretch; #endif diff --git a/Source/WebCore/platform/graphics/Tile.h b/Source/WebCore/platform/graphics/Tile.h index c623ec9..02076d2 100644 --- a/Source/WebCore/platform/graphics/Tile.h +++ b/Source/WebCore/platform/graphics/Tile.h @@ -49,7 +49,7 @@ public: bool isDirty() const; void invalidate(const IntRect&); - void updateBackBuffer(); + Vector<IntRect> updateBackBuffer(); void swapBackBufferToFront(); bool isReadyToPaint() const; void paint(GraphicsContext*, const IntRect&); diff --git a/Source/WebCore/platform/graphics/TiledBackingStore.cpp b/Source/WebCore/platform/graphics/TiledBackingStore.cpp index 4d69334..ac7e9c6 100644 --- a/Source/WebCore/platform/graphics/TiledBackingStore.cpp +++ b/Source/WebCore/platform/graphics/TiledBackingStore.cpp @@ -102,8 +102,6 @@ void TiledBackingStore::updateTileBuffers() if (!it->second->isDirty()) continue; dirtyTiles.append(it->second); - // FIXME: should not request system repaint for the full tile. - paintedArea.append(mapToContents(it->second->rect())); } if (dirtyTiles.isEmpty()) { @@ -115,11 +113,11 @@ void TiledBackingStore::updateTileBuffers() // one by one and then swapped to front in one go. This would minimize the time spent // blocking on tile updates. unsigned size = dirtyTiles.size(); - for (unsigned n = 0; n < size; ++n) - dirtyTiles[n]->updateBackBuffer(); - - for (unsigned n = 0; n < size; ++n) + for (unsigned n = 0; n < size; ++n) { + Vector<IntRect> paintedRects = dirtyTiles[n]->updateBackBuffer(); + paintedArea.append(paintedRects); dirtyTiles[n]->swapBackBufferToFront(); + } m_client->tiledBackingStorePaintEnd(paintedArea); } diff --git a/Source/WebCore/platform/graphics/WOFFFileFormat.cpp b/Source/WebCore/platform/graphics/WOFFFileFormat.cpp index b1400ba..80a6dcb 100644 --- a/Source/WebCore/platform/graphics/WOFFFileFormat.cpp +++ b/Source/WebCore/platform/graphics/WOFFFileFormat.cpp @@ -248,7 +248,7 @@ bool convertWOFFToSfnt(SharedBuffer* woff, Vector<char>& sfnt) return sfnt.size() == totalSfntSize; } + +} // namespace WebCore #endif // !ENABLE(OPENTYPE_SANITIZER) - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/WidthIterator.cpp b/Source/WebCore/platform/graphics/WidthIterator.cpp index 27b0627..750a4ac 100644 --- a/Source/WebCore/platform/graphics/WidthIterator.cpp +++ b/Source/WebCore/platform/graphics/WidthIterator.cpp @@ -47,7 +47,7 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const , m_end(run.length()) , m_currentCharacter(0) , m_runWidthSoFar(0) - , m_isAfterExpansion(true) + , m_isAfterExpansion(!run.allowsLeadingExpansion()) , m_fallbackFonts(fallbackFonts) , m_accountForGlyphBounds(accountForGlyphBounds) , m_maxGlyphBoundingBoxY(numeric_limits<float>::min()) @@ -62,7 +62,7 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const if (!m_expansion) m_expansionPerOpportunity = 0; else { - bool isAfterExpansion = true; + bool isAfterExpansion = m_isAfterExpansion; unsigned expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion); if (isAfterExpansion && !m_run.allowsTrailingExpansion()) expansionOpportunityCount--; @@ -164,18 +164,24 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) bool treatAsSpace = Font::treatAsSpace(c); if (treatAsSpace || (expandAroundIdeographs && Font::isCJKIdeographOrSymbol(c))) { // Distribute the run's total expansion evenly over all expansion opportunities in the run. - if (m_expansion && (m_run.allowsTrailingExpansion() || (m_run.ltr() && currentCharacter + clusterLength < static_cast<size_t>(m_run.length())) - || (m_run.rtl() && currentCharacter))) { + if (m_expansion) { if (!treatAsSpace && !m_isAfterExpansion) { // Take the expansion opportunity before this ideograph. m_expansion -= m_expansionPerOpportunity; m_runWidthSoFar += m_expansionPerOpportunity; - if (glyphBuffer) - glyphBuffer->expandLastAdvance(m_expansionPerOpportunity); + if (glyphBuffer) { + if (glyphBuffer->isEmpty()) + glyphBuffer->add(fontData->spaceGlyph(), fontData, m_expansionPerOpportunity); + else + glyphBuffer->expandLastAdvance(m_expansionPerOpportunity); + } + } + if (m_run.allowsTrailingExpansion() || (m_run.ltr() && currentCharacter + clusterLength < static_cast<size_t>(m_run.length())) + || (m_run.rtl() && currentCharacter)) { + m_expansion -= m_expansionPerOpportunity; + width += m_expansionPerOpportunity; + m_isAfterExpansion = true; } - m_expansion -= m_expansionPerOpportunity; - width += m_expansionPerOpportunity; - m_isAfterExpansion = true; } else m_isAfterExpansion = false; diff --git a/Source/WebCore/platform/graphics/android/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/android/FontCustomPlatformData.cpp index 7190f32..72fac68 100644 --- a/Source/WebCore/platform/graphics/android/FontCustomPlatformData.cpp +++ b/Source/WebCore/platform/graphics/android/FontCustomPlatformData.cpp @@ -45,8 +45,7 @@ FontCustomPlatformData::~FontCustomPlatformData() // the unref is enough to release the font data... } -FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, - FontOrientation, FontWidthVariant, FontRenderingMode) +FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode) { // turn bold/italic into fakeBold/fakeItalic if (m_typeface != NULL) { diff --git a/Source/WebCore/platform/graphics/android/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/android/FontCustomPlatformData.h index f74abc5..47e5e71 100644 --- a/Source/WebCore/platform/graphics/android/FontCustomPlatformData.h +++ b/Source/WebCore/platform/graphics/android/FontCustomPlatformData.h @@ -29,6 +29,7 @@ #include "FontOrientation.h" #include "FontRenderingMode.h" #include "FontWidthVariant.h" +#include "TextOrientation.h" #include <wtf/Forward.h> #include <wtf/Noncopyable.h> @@ -47,7 +48,7 @@ public: SkTypeface* typeface() const { return m_typeface; } - FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode); + FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode); static bool supportsFormat(const String&); private: diff --git a/Source/WebCore/platform/graphics/android/FontPlatformData.h b/Source/WebCore/platform/graphics/android/FontPlatformData.h index 498db47..3313aca 100644 --- a/Source/WebCore/platform/graphics/android/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/android/FontPlatformData.h @@ -65,6 +65,7 @@ public: } FontOrientation orientation() const { return Horizontal; } // FIXME: Implement. + void setOrientation(FontOrientation) { } // FIXME: Implement. FontPlatformData& operator=(const FontPlatformData&); bool operator==(const FontPlatformData& a) const; diff --git a/Source/WebCore/platform/graphics/android/PathAndroid.cpp b/Source/WebCore/platform/graphics/android/PathAndroid.cpp index ad345bb..436da59 100644 --- a/Source/WebCore/platform/graphics/android/PathAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/PathAndroid.cpp @@ -285,7 +285,7 @@ void Path::transform(const AffineTransform& xform) /////////////////////////////////////////////////////////////////////////////// -FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) +FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const { GraphicsContext* scratch = scratchContext(); scratch->save(); diff --git a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp new file mode 100644 index 0000000..eb96532 --- /dev/null +++ b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp @@ -0,0 +1,731 @@ +/* + * 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 COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(VIDEO) && USE(AVFOUNDATION) + +#include "MediaPlayerPrivateAVFoundation.h" + +#include "ApplicationCacheHost.h" +#include "DocumentLoader.h" +#include "FrameView.h" +#include "GraphicsContext.h" +#include "GraphicsLayer.h" +#include "KURL.h" +#include "Logging.h" +#include "SoftLinking.h" +#include "TimeRanges.h" +#include <CoreMedia/CoreMedia.h> +#include <wtf/UnusedParam.h> + +using namespace std; + +namespace WebCore { + +static const float invalidTime = -1.0f; + +MediaPlayerPrivateAVFoundation::MediaPlayerPrivateAVFoundation(MediaPlayer* player) + : m_player(player) + , m_queuedNotifications() + , m_queueMutex() + , m_mainThreadCallPending(false) + , m_networkState(MediaPlayer::Empty) + , m_readyState(MediaPlayer::HaveNothing) + , m_preload(MediaPlayer::Auto) + , m_scaleFactor(1, 1) + , m_cachedMaxTimeLoaded(0) + , m_cachedMaxTimeSeekable(0) + , m_cachedDuration(invalidTime) + , m_reportedDuration(invalidTime) + , m_seekTo(invalidTime) + , m_requestedRate(1) + , m_delayCallbacks(false) + , m_havePreparedToPlay(false) + , m_assetIsPlayable(false) + , m_visible(false) + , m_videoFrameHasDrawn(false) + , m_loadingMetadata(false) + , m_delayingLoad(false) + , m_isAllowedToRender(false) + , m_cachedHasAudio(false) + , m_cachedHasVideo(false) + , m_cachedHasCaptions(false) + , m_ignoreLoadStateChanges(false) +{ + LOG(Media, "MediaPlayerPrivateAVFoundation::MediaPlayerPrivateAVFoundation(%p)", this); +} + +MediaPlayerPrivateAVFoundation::~MediaPlayerPrivateAVFoundation() +{ + LOG(Media, "MediaPlayerPrivateAVFoundation::~MediaPlayerPrivateAVFoundation(%p)", this); + cancelCallOnMainThread(mainThreadCallback, this); +} + +MediaPlayerPrivateAVFoundation::MediaRenderingMode MediaPlayerPrivateAVFoundation::currentRenderingMode() const +{ +#if USE(ACCELERATED_COMPOSITING) + if (platformLayer()) + return MediaRenderingToLayer; +#endif + + if (hasContextRenderer()) + return MediaRenderingToContext; + + return MediaRenderingNone; +} + +MediaPlayerPrivateAVFoundation::MediaRenderingMode MediaPlayerPrivateAVFoundation::preferredRenderingMode() const +{ + if (!m_player->visible() || !m_player->frameView() || assetStatus() == MediaPlayerAVAssetStatusUnknown) + return MediaRenderingNone; + +#if USE(ACCELERATED_COMPOSITING) + if (supportsAcceleratedRendering() && m_player->mediaPlayerClient()->mediaPlayerRenderingCanBeAccelerated(m_player)) + return MediaRenderingToLayer; +#endif + + return MediaRenderingToContext; +} + +void MediaPlayerPrivateAVFoundation::setUpVideoRendering() +{ + if (!isReadyForVideoSetup()) + return; + + MediaRenderingMode currentMode = currentRenderingMode(); + MediaRenderingMode preferredMode = preferredRenderingMode(); + if (currentMode == preferredMode && currentMode != MediaRenderingNone) + return; + + LOG(Media, "MediaPlayerPrivateAVFoundation::setUpVideoRendering(%p) - current mode = %d, preferred mode = %d", + this, static_cast<int>(currentMode), static_cast<int>(preferredMode)); + + if (currentMode != MediaRenderingNone) + tearDownVideoRendering(); + + switch (preferredMode) { + case MediaRenderingNone: + case MediaRenderingToContext: + createContextVideoRenderer(); + break; + +#if USE(ACCELERATED_COMPOSITING) + case MediaRenderingToLayer: + createVideoLayer(); + break; +#endif + } + +#if USE(ACCELERATED_COMPOSITING) + // If using a movie layer, inform the client so the compositing tree is updated. + if (currentMode == MediaRenderingToLayer || preferredMode == MediaRenderingToLayer) { + LOG(Media, "MediaPlayerPrivateAVFoundation::setUpVideoRendering(%p) - calling mediaPlayerRenderingModeChanged()", this); + m_player->mediaPlayerClient()->mediaPlayerRenderingModeChanged(m_player); + } +#endif +} + +void MediaPlayerPrivateAVFoundation::tearDownVideoRendering() +{ + LOG(Media, "MediaPlayerPrivateAVFoundation::tearDownVideoRendering(%p)", this); + + destroyContextVideoRenderer(); + +#if USE(ACCELERATED_COMPOSITING) + if (platformLayer()) + destroyVideoLayer(); +#endif +} + +bool MediaPlayerPrivateAVFoundation::hasSetUpVideoRendering() const +{ + return hasLayerRenderer() || hasContextRenderer(); +} + +void MediaPlayerPrivateAVFoundation::resumeLoad() +{ + LOG(Media, "MediaPlayerPrivateAVFoundation::resumeLoad(%p)", this); + + ASSERT(m_delayingLoad); + m_delayingLoad = false; + + if (m_assetURL.length()) + prepareToPlay(); +} + +void MediaPlayerPrivateAVFoundation::load(const String& url) +{ + LOG(Media, "MediaPlayerPrivateAVFoundation::load(%p)", this); + + if (m_networkState != MediaPlayer::Loading) { + m_networkState = MediaPlayer::Loading; + m_player->networkStateChanged(); + } + if (m_readyState != MediaPlayer::HaveNothing) { + m_readyState = MediaPlayer::HaveNothing; + m_player->readyStateChanged(); + } + + m_videoFrameHasDrawn = false; + m_assetURL = url; + + // Don't do any more work if the url is empty. + if (!url.length()) + return; + + if (m_preload == MediaPlayer::None) { + LOG(Media, "MediaPlayerPrivateAVFoundation::load(%p) - preload==none so returning", this); + m_delayingLoad = true; + return; + } + + prepareToPlay(); +} + +void MediaPlayerPrivateAVFoundation::playabilityKnown() +{ + LOG(Media, "MediaPlayerPrivateAVFoundation::playabilityKnown(%p)", this); + + updateStates(); + if (m_assetIsPlayable) + return; + + // Nothing more to do if we already have all of the item's metadata. + if (assetStatus() > MediaPlayerAVAssetStatusLoading) { + LOG(Media, "MediaPlayerPrivateAVFoundation::playabilityKnown(%p) - all metadata loaded", this); + return; + } + + // At this point we are supposed to load metadata. It is OK to ask the asset to load the same + // information multiple times, because if it has already been loaded the completion handler + // will just be called synchronously. + m_loadingMetadata = true; + beginLoadingMetadata(); +} + +void MediaPlayerPrivateAVFoundation::prepareToPlay() +{ + LOG(Media, "MediaPlayerPrivateAVFoundation::prepareToPlay(%p)", this); + + m_preload = MediaPlayer::Auto; + if (m_havePreparedToPlay) + return; + m_havePreparedToPlay = true; + + m_delayingLoad = false; +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : 0; + ApplicationCacheHost* cacheHost = frame ? frame->loader()->documentLoader()->applicationCacheHost() : 0; + ApplicationCacheResource* resource = 0; + if (cacheHost && cacheHost->shouldLoadResourceFromApplicationCache(ResourceRequest(m_assetURL), resource) && resource) + createAVPlayerForCacheResource(resource); + else +#endif + createAVPlayerForURL(m_assetURL); + checkPlayability(); +} + +void MediaPlayerPrivateAVFoundation::paint(GraphicsContext*, const IntRect&) +{ + // This is the base class, only need to remember that a frame has been drawn. + m_videoFrameHasDrawn = true; +} + +float MediaPlayerPrivateAVFoundation::duration() const +{ + if (!metaDataAvailable()) + return 0; + + if (m_cachedDuration == invalidTime) { + m_cachedDuration = platformDuration(); + LOG(Media, "MediaPlayerPrivateAVFMac::duration(%p) - caching %f", this, m_cachedDuration); + } + + return m_cachedDuration; +} + +void MediaPlayerPrivateAVFoundation::seek(float time) +{ + LOG(Media, "MediaPlayerPrivateAVFoundation::seek(%p) - seeking to %f", this, time); + if (!metaDataAvailable()) + return; + + if (time > duration()) + time = duration(); + + m_seekTo = time; + + seekToTime(time); +} + +void MediaPlayerPrivateAVFoundation::setRate(float rate) +{ + LOG(Media, "MediaPlayerPrivateAVFoundation::setRate(%p) - seting to %f", this, rate); + m_requestedRate = rate; +} + +bool MediaPlayerPrivateAVFoundation::paused() const +{ + if (!metaDataAvailable()) + return true; + + return rate() == 0; +} + +bool MediaPlayerPrivateAVFoundation::seeking() const +{ + if (!metaDataAvailable()) + return false; + + return m_seekTo != invalidTime; +} + +IntSize MediaPlayerPrivateAVFoundation::naturalSize() const +{ + if (!metaDataAvailable()) + return IntSize(); + + // In spite of the name of this method, return the natural size transformed by the + // initial movie scale because the spec says intrinsic size is: + // + // ... the dimensions of the resource in CSS pixels after taking into account the resource's + // dimensions, aspect ratio, clean aperture, resolution, and so forth, as defined for the + // format used by the resource + + return m_cachedNaturalSize; +} + +void MediaPlayerPrivateAVFoundation::setNaturalSize(IntSize size) +{ + IntSize oldSize = m_cachedNaturalSize; + m_cachedNaturalSize = size; + if (oldSize != m_cachedNaturalSize) + m_player->sizeChanged(); +} + +PassRefPtr<TimeRanges> MediaPlayerPrivateAVFoundation::buffered() const +{ + if (!m_cachedLoadedTimeRanges) + m_cachedLoadedTimeRanges = platformBufferedTimeRanges(); + + return m_cachedLoadedTimeRanges->copy(); +} + +float MediaPlayerPrivateAVFoundation::maxTimeSeekable() const +{ + if (!metaDataAvailable()) + return 0; + + if (!m_cachedMaxTimeSeekable) + m_cachedMaxTimeSeekable = platformMaxTimeSeekable(); + + LOG(Media, "MediaPlayerPrivateAVFoundation::maxTimeSeekable(%p) - returning %f", this, m_cachedMaxTimeSeekable); + return m_cachedMaxTimeSeekable; +} + +float MediaPlayerPrivateAVFoundation::maxTimeLoaded() const +{ + if (!metaDataAvailable()) + return 0; + + if (!m_cachedMaxTimeLoaded) + m_cachedMaxTimeLoaded = platformMaxTimeLoaded(); + + return m_cachedMaxTimeLoaded; +} + +unsigned MediaPlayerPrivateAVFoundation::bytesLoaded() const +{ + float dur = duration(); + if (!dur) + return 0; + unsigned loaded = totalBytes() * maxTimeLoaded() / dur; + LOG(Media, "MediaPlayerPrivateAVFoundation::bytesLoaded(%p) - returning %i", this, loaded); + return loaded; +} + +bool MediaPlayerPrivateAVFoundation::isReadyForVideoSetup() const +{ + return m_isAllowedToRender && m_readyState >= MediaPlayer::HaveMetadata && m_player->visible(); +} + +void MediaPlayerPrivateAVFoundation::prepareForRendering() +{ + if (m_isAllowedToRender) + return; + m_isAllowedToRender = true; + + setUpVideoRendering(); + + if (currentRenderingMode() == MediaRenderingToLayer || preferredRenderingMode() == MediaRenderingToLayer) + m_player->mediaPlayerClient()->mediaPlayerRenderingModeChanged(m_player); +} + +bool MediaPlayerPrivateAVFoundation::supportsFullscreen() const +{ +#if ENABLE(FULLSCREEN_API) + return true; +#else + // FIXME: WebVideoFullscreenController assumes a QTKit/QuickTime media engine + return false; +#endif +} + +void MediaPlayerPrivateAVFoundation::updateStates() +{ + MediaPlayer::NetworkState oldNetworkState = m_networkState; + MediaPlayer::ReadyState oldReadyState = m_readyState; + + LOG(Media, "MediaPlayerPrivateAVFoundation::updateStates(%p) - entering with networkState = %i, readyState = %i", + this, static_cast<int>(m_networkState), static_cast<int>(m_readyState)); + + if (m_loadingMetadata) + m_networkState = MediaPlayer::Loading; + else { + // -loadValuesAsynchronouslyForKeys:completionHandler: has invoked its handler; test status of keys and determine state. + AVAssetStatus avAssetStatus = assetStatus(); + ItemStatus itemStatus = playerItemStatus(); + + m_assetIsPlayable = (avAssetStatus == MediaPlayerAVAssetStatusPlayable); + if (m_readyState < MediaPlayer::HaveMetadata && avAssetStatus > MediaPlayerAVAssetStatusLoading) { + if (m_assetIsPlayable) { + if (itemStatus == MediaPlayerAVPlayerItemStatusUnknown) { + if (avAssetStatus == MediaPlayerAVAssetStatusFailed || m_preload > MediaPlayer::MetaData) { + // We may have a playable asset that doesn't support inspection prior to playback; go ahead + // and create the AVPlayerItem now. When the AVPlayerItem becomes ready to play, we will + // have access to its metadata. Or we may have been asked to become ready to play immediately. + m_networkState = MediaPlayer::Loading; + prepareToPlay(); + } else + m_networkState = MediaPlayer::Idle; + } + if (avAssetStatus == MediaPlayerAVAssetStatusLoaded) + m_readyState = MediaPlayer::HaveMetadata; + } else { + // FIX ME: fetch the error associated with the @"playable" key to distinguish between format + // and network errors. + m_networkState = MediaPlayer::FormatError; + } + } + + if (avAssetStatus >= MediaPlayerAVAssetStatusLoaded && itemStatus > MediaPlayerAVPlayerItemStatusUnknown) { + if (seeking()) + m_readyState = m_readyState >= MediaPlayer::HaveMetadata ? MediaPlayer::HaveMetadata : MediaPlayer::HaveNothing; + else { + float maxLoaded = maxTimeLoaded(); + switch (itemStatus) { + case MediaPlayerAVPlayerItemStatusUnknown: + break; + case MediaPlayerAVPlayerItemStatusFailed: + m_networkState = MediaPlayer::DecodeError; + break; + case MediaPlayerAVPlayerItemStatusPlaybackLikelyToKeepUp: + m_readyState = MediaPlayer::HaveEnoughData; + break; + case MediaPlayerAVPlayerItemStatusReadyToPlay: + case MediaPlayerAVPlayerItemStatusPlaybackBufferEmpty: + case MediaPlayerAVPlayerItemStatusPlaybackBufferFull: + if (maxLoaded > currentTime()) + m_readyState = MediaPlayer::HaveFutureData; + else + m_readyState = MediaPlayer::HaveCurrentData; + break; + } + + if (itemStatus >= MediaPlayerAVPlayerItemStatusReadyToPlay) + m_networkState = (maxLoaded == duration()) ? MediaPlayer::Loaded : MediaPlayer::Loading; + } + } + } + + if (isReadyForVideoSetup() && currentRenderingMode() != preferredRenderingMode()) + setUpVideoRendering(); + + if (m_networkState != oldNetworkState) + m_player->networkStateChanged(); + + if (m_readyState != oldReadyState) + m_player->readyStateChanged(); + + LOG(Media, "MediaPlayerPrivateAVFoundation::updateStates(%p) - exiting with networkState = %i, readyState = %i", + this, static_cast<int>(m_networkState), static_cast<int>(m_readyState)); +} + +void MediaPlayerPrivateAVFoundation::setSize(const IntSize&) +{ +} + +void MediaPlayerPrivateAVFoundation::setVisible(bool visible) +{ + if (m_visible == visible) + return; + + m_visible = visible; + if (visible) + setUpVideoRendering(); + else + tearDownVideoRendering(); +} + +bool MediaPlayerPrivateAVFoundation::hasAvailableVideoFrame() const +{ + if (currentRenderingMode() == MediaRenderingToLayer) + return videoLayerIsReadyToDisplay(); + + // When using the software renderer we hope someone will signal that a frame is available so we might as well + // wait until we know that a frame has been drawn. + return m_videoFrameHasDrawn; +} + +void MediaPlayerPrivateAVFoundation::acceleratedRenderingStateChanged() +{ + // Set up or change the rendering path if necessary. + setUpVideoRendering(); +} + +void MediaPlayerPrivateAVFoundation::metadataLoaded() +{ + m_loadingMetadata = false; + updateStates(); +} + +void MediaPlayerPrivateAVFoundation::loadStateChanged() +{ + if (m_ignoreLoadStateChanges) + return; + updateStates(); +} + +void MediaPlayerPrivateAVFoundation::rateChanged() +{ + updateStates(); + m_player->rateChanged(); +} + +void MediaPlayerPrivateAVFoundation::loadedTimeRangesChanged() +{ + m_cachedLoadedTimeRanges = 0; + m_cachedMaxTimeLoaded = 0; + updateStates(); + + // For some media files, reported duration is estimated and updated as media is loaded + // so report duration changed when the estimate is upated. + float dur = duration(); + if (dur != m_reportedDuration) { + if (m_reportedDuration != invalidTime) + m_player->durationChanged(); + m_reportedDuration = dur; + } +} + +void MediaPlayerPrivateAVFoundation::seekableTimeRangesChanged() +{ + m_cachedMaxTimeSeekable = 0; +} + +void MediaPlayerPrivateAVFoundation::timeChanged(double time) +{ + LOG(Media, "MediaPlayerPrivateAVFoundation::timeChanged(%p) - time = %f", this, time); + + if (m_seekTo == invalidTime) + return; + + // AVFoundation may call our observer more than once during a seek, and we can't currently tell + // if we will be able to seek to an exact time, so assume that we are done seeking if we are + // "close enough" to the seek time. + const double smallSeekDelta = 1.0 / 100; + + float currentRate = rate(); + if ((currentRate > 0 && time >= m_seekTo) || (currentRate < 0 && time <= m_seekTo) || (abs(m_seekTo - time) <= smallSeekDelta)) { + m_seekTo = invalidTime; + updateStates(); + m_player->timeChanged(); + } +} + +void MediaPlayerPrivateAVFoundation::didEnd() +{ + // Hang onto the current time and use it as duration from now on since we are definitely at + // the end of the movie. Do this because the initial duration is sometimes an estimate. + float now = currentTime(); + if (now > 0) + m_cachedDuration = now; + + updateStates(); + m_player->timeChanged(); +} + +void MediaPlayerPrivateAVFoundation::repaint() +{ + m_videoFrameHasDrawn = true; + m_player->repaint(); +} + +MediaPlayer::MovieLoadType MediaPlayerPrivateAVFoundation::movieLoadType() const +{ + if (!metaDataAvailable() || assetStatus() == MediaPlayerAVAssetStatusUnknown) + return MediaPlayer::Unknown; + + if (isinf(duration())) + return MediaPlayer::LiveStream; + + return MediaPlayer::Download; +} + +void MediaPlayerPrivateAVFoundation::setPreload(MediaPlayer::Preload preload) +{ + m_preload = preload; + if (m_delayingLoad && m_preload != MediaPlayer::None) + resumeLoad(); +} + +void MediaPlayerPrivateAVFoundation::setDelayCallbacks(bool delay) +{ + MutexLocker lock(m_queueMutex); + if (delay) + ++m_delayCallbacks; + else { + ASSERT(m_delayCallbacks); + --m_delayCallbacks; + } +} + +void MediaPlayerPrivateAVFoundation::mainThreadCallback(void* context) +{ + LOG(Media, "MediaPlayerPrivateAVFoundation::mainThreadCallback(%p)", context); + MediaPlayerPrivateAVFoundation* player = static_cast<MediaPlayerPrivateAVFoundation*>(context); + player->clearMainThreadPendingFlag(); + player->dispatchNotification(); +} + +void MediaPlayerPrivateAVFoundation::clearMainThreadPendingFlag() +{ + MutexLocker lock(m_queueMutex); + m_mainThreadCallPending = false; +} + +void MediaPlayerPrivateAVFoundation::scheduleMainThreadNotification(Notification::Type type, double time) +{ + LOG(Media, "MediaPlayerPrivateAVFoundation::scheduleMainThreadNotification(%p) - notification %d", this, static_cast<int>(type)); + m_queueMutex.lock(); + + // It is important to always process the properties in the order that we are notified, + // so always go through the queue because notifications happen on different threads. + m_queuedNotifications.append(Notification(type, time)); + + bool delayDispatch = m_delayCallbacks || !isMainThread(); + if (delayDispatch && !m_mainThreadCallPending) { + m_mainThreadCallPending = true; + callOnMainThread(mainThreadCallback, this); + } + + m_queueMutex.unlock(); + + if (delayDispatch) { + LOG(Media, "MediaPlayerPrivateAVFoundation::scheduleMainThreadNotification(%p) - early return", this); + return; + } + + dispatchNotification(); +} + +void MediaPlayerPrivateAVFoundation::dispatchNotification() +{ + ASSERT(isMainThread()); + + Notification notification = Notification(); + { + MutexLocker lock(m_queueMutex); + + if (m_queuedNotifications.isEmpty()) + return; + + if (!m_delayCallbacks) { + // Only dispatch one notification callback per invocation because they can cause recursion. + notification = m_queuedNotifications.first(); + m_queuedNotifications.remove(0); + } + + if (!m_queuedNotifications.isEmpty() && !m_mainThreadCallPending) + callOnMainThread(mainThreadCallback, this); + + if (!notification.isValid()) + return; + } + + LOG(Media, "MediaPlayerPrivateAVFoundation::dispatchNotification(%p) - dispatching %d", this, static_cast<int>(notification.type())); + + switch (notification.type()) { + case Notification::ItemDidPlayToEndTime: + didEnd(); + break; + case Notification::ItemTracksChanged: + tracksChanged(); + break; + case Notification::ItemStatusChanged: + loadStateChanged(); + break; + case Notification::ItemSeekableTimeRangesChanged: + seekableTimeRangesChanged(); + loadStateChanged(); + break; + case Notification::ItemLoadedTimeRangesChanged: + loadedTimeRangesChanged(); + loadStateChanged(); + break; + case Notification::ItemPresentationSizeChanged: + sizeChanged(); + break; + case Notification::ItemIsPlaybackLikelyToKeepUpChanged: + loadStateChanged(); + break; + case Notification::ItemIsPlaybackBufferEmptyChanged: + loadStateChanged(); + break; + case Notification::ItemIsPlaybackBufferFullChanged: + loadStateChanged(); + break; + case Notification::PlayerRateChanged: + rateChanged(); + break; + case Notification::PlayerTimeChanged: + timeChanged(notification.time()); + break; + case Notification::AssetMetadataLoaded: + metadataLoaded(); + break; + case Notification::AssetPlayabilityKnown: + playabilityKnown(); + break; + case Notification::None: + ASSERT_NOT_REACHED(); + break; + } +} + +} // namespace WebCore + +#endif diff --git a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h new file mode 100644 index 0000000..a768ab4 --- /dev/null +++ b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h @@ -0,0 +1,262 @@ +/* + * 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 COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MediaPlayerPrivateAVFoundation_h +#define MediaPlayerPrivateAVFoundation_h + +#if ENABLE(VIDEO) && USE(AVFOUNDATION) + +#include "FloatSize.h" +#include "MediaPlayerPrivate.h" +#include "Timer.h" +#include <wtf/RetainPtr.h> + +namespace WebCore { + +class ApplicationCacheResource; + +class MediaPlayerPrivateAVFoundation : public MediaPlayerPrivateInterface { +public: + + virtual void repaint(); + virtual void metadataLoaded(); + virtual void loadStateChanged(); + virtual void playabilityKnown(); + virtual void rateChanged(); + virtual void loadedTimeRangesChanged(); + virtual void seekableTimeRangesChanged(); + virtual void timeChanged(double); + virtual void didEnd(); + + class Notification { + public: + enum Type { + None, + ItemDidPlayToEndTime, + ItemTracksChanged, + ItemStatusChanged, + ItemSeekableTimeRangesChanged, + ItemLoadedTimeRangesChanged, + ItemPresentationSizeChanged, + ItemIsPlaybackLikelyToKeepUpChanged, + ItemIsPlaybackBufferEmptyChanged, + ItemIsPlaybackBufferFullChanged, + AssetMetadataLoaded, + AssetPlayabilityKnown, + PlayerRateChanged, + PlayerTimeChanged + }; + + Notification() + : m_type(None) + , m_time(0) + { + } + + Notification(Type type, double time) + : m_type(type) + , m_time(time) + { + } + + Type type() { return m_type; } + bool isValid() { return m_type != None; } + double time() { return m_time; } + + private: + Type m_type; + double m_time; + }; + + void scheduleMainThreadNotification(Notification::Type, double time = 0); + void dispatchNotification(); + void clearMainThreadPendingFlag(); + +protected: + MediaPlayerPrivateAVFoundation(MediaPlayer*); + virtual ~MediaPlayerPrivateAVFoundation(); + + // MediaPlayerPrivatePrivateInterface overrides. + virtual void load(const String& url); + virtual void cancelLoad() = 0; + + virtual void prepareToPlay(); + virtual PlatformMedia platformMedia() const = 0; + + virtual void play() = 0; + virtual void pause() = 0; + + virtual IntSize naturalSize() const; + virtual bool hasVideo() const { return m_cachedHasVideo; } + virtual bool hasAudio() const { return m_cachedHasAudio; } + virtual void setVisible(bool); + virtual float duration() const; + virtual float currentTime() const = 0; + virtual void seek(float); + virtual bool seeking() const; + virtual void setRate(float); + virtual bool paused() const; + virtual void setVolume(float) = 0; + virtual bool hasClosedCaptions() const { return m_cachedHasCaptions; } + virtual void setClosedCaptionsVisible(bool) = 0; + virtual MediaPlayer::NetworkState networkState() const { return m_networkState; } + virtual MediaPlayer::ReadyState readyState() const { return m_readyState; } + virtual float maxTimeSeekable() const; + virtual PassRefPtr<TimeRanges> buffered() const; + virtual unsigned bytesLoaded() const; + virtual void setSize(const IntSize&); + virtual void paint(GraphicsContext*, const IntRect&); + virtual void paintCurrentFrameInContext(GraphicsContext*, const IntRect&) = 0; + virtual void setPreload(MediaPlayer::Preload); + virtual bool hasAvailableVideoFrame() const; +#if USE(ACCELERATED_COMPOSITING) + virtual PlatformLayer* platformLayer() const { return 0; } + virtual bool supportsAcceleratedRendering() const = 0; + virtual void acceleratedRenderingStateChanged(); +#endif + virtual bool hasSingleSecurityOrigin() const { return true; } + virtual MediaPlayer::MovieLoadType movieLoadType() const; + virtual void prepareForRendering(); + virtual float mediaTimeForTimeValue(float) const = 0; + + virtual bool supportsFullscreen() const; + + // Required interfaces for concrete derived classes. + virtual void createAVPlayerForURL(const String& url) = 0; +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + virtual void createAVPlayerForCacheResource(ApplicationCacheResource*) = 0; +#endif + + enum ItemStatus { + MediaPlayerAVPlayerItemStatusUnknown, + MediaPlayerAVPlayerItemStatusFailed, + MediaPlayerAVPlayerItemStatusReadyToPlay, + MediaPlayerAVPlayerItemStatusPlaybackBufferEmpty, + MediaPlayerAVPlayerItemStatusPlaybackBufferFull, + MediaPlayerAVPlayerItemStatusPlaybackLikelyToKeepUp, + }; + virtual ItemStatus playerItemStatus() const = 0; + + enum AVAssetStatus { + MediaPlayerAVAssetStatusUnknown, + MediaPlayerAVAssetStatusLoading, + MediaPlayerAVAssetStatusFailed, + MediaPlayerAVAssetStatusCancelled, + MediaPlayerAVAssetStatusLoaded, + MediaPlayerAVAssetStatusPlayable, + }; + virtual AVAssetStatus assetStatus() const = 0; + + virtual void checkPlayability() = 0; + virtual float rate() const = 0; + virtual void seekToTime(float time) = 0; + virtual unsigned totalBytes() const = 0; + virtual PassRefPtr<TimeRanges> platformBufferedTimeRanges() const = 0; + virtual float platformMaxTimeSeekable() const = 0; + virtual float platformMaxTimeLoaded() const = 0; + virtual float platformDuration() const = 0; + + virtual void beginLoadingMetadata() = 0; + virtual void tracksChanged() = 0; + virtual void sizeChanged() = 0; + + virtual void createContextVideoRenderer() = 0; + virtual void destroyContextVideoRenderer() = 0; + + virtual void createVideoLayer() = 0; + virtual void destroyVideoLayer() = 0; + virtual bool videoLayerIsReadyToDisplay() const = 0; + + virtual bool hasContextRenderer() const = 0; + virtual bool hasLayerRenderer() const = 0; + +protected: + void resumeLoad(); + void updateStates(); + + void setHasVideo(bool b) { m_cachedHasVideo = b; }; + void setHasAudio(bool b) { m_cachedHasAudio = b; } + void setHasClosedCaptions(bool b) { m_cachedHasCaptions = b; } + void setDelayCallbacks(bool); + void setIgnoreLoadStateChanges(bool delay) { m_ignoreLoadStateChanges = delay; } + void setNaturalSize(IntSize); + + enum MediaRenderingMode { MediaRenderingNone, MediaRenderingToContext, MediaRenderingToLayer }; + MediaRenderingMode currentRenderingMode() const; + MediaRenderingMode preferredRenderingMode() const; + + bool metaDataAvailable() const { return m_readyState >= MediaPlayer::HaveMetadata; } + float requestedRate() const { return m_requestedRate; } + float maxTimeLoaded() const; + bool isReadyForVideoSetup() const; + virtual void setUpVideoRendering(); + virtual void tearDownVideoRendering(); + bool hasSetUpVideoRendering() const; + + static void mainThreadCallback(void*); + +private: + + MediaPlayer* m_player; + + Vector<Notification> m_queuedNotifications; + Mutex m_queueMutex; + bool m_mainThreadCallPending; + + mutable RefPtr<TimeRanges> m_cachedLoadedTimeRanges; + + MediaPlayer::NetworkState m_networkState; + MediaPlayer::ReadyState m_readyState; + + String m_assetURL; + MediaPlayer::Preload m_preload; + FloatSize m_scaleFactor; + + IntSize m_cachedNaturalSize; + mutable float m_cachedMaxTimeLoaded; + mutable float m_cachedMaxTimeSeekable; + mutable float m_cachedDuration; + float m_reportedDuration; + + float m_seekTo; + float m_requestedRate; + int m_delayCallbacks; + bool m_havePreparedToPlay; + bool m_assetIsPlayable; + bool m_visible; + bool m_videoFrameHasDrawn; + bool m_loadingMetadata; + bool m_delayingLoad; + bool m_isAllowedToRender; + bool m_cachedHasAudio; + bool m_cachedHasVideo; + bool m_cachedHasCaptions; + bool m_ignoreLoadStateChanges; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.h b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.h new file mode 100644 index 0000000..cc00c15 --- /dev/null +++ b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.h @@ -0,0 +1,131 @@ +/* + * 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 COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MediaPlayerPrivateAVFoundationObjC_h +#define MediaPlayerPrivateAVFoundationObjC_h + +#if ENABLE(VIDEO) && USE(AVFOUNDATION) + +#include "MediaPlayerPrivateAVFoundation.h" + +#ifdef __OBJC__ +@class AVAsset; +@class AVPlayer; +@class AVPlayerItem; +@class AVPlayerLayer; +@class AVAssetImageGenerator; +@class WebCoreAVFMovieObserver; +#else +class AVAsset; +class AVPlayer; +class AVPlayerItem; +class AVPlayerLayer; +class AVAssetImageGenerator; +class WebCoreAVFMovieObserver; +typedef struct objc_object *id; +#endif + +namespace WebCore { + +class ApplicationCacheResource; + +class MediaPlayerPrivateAVFoundationObjC : public MediaPlayerPrivateAVFoundation { +public: + + static void registerMediaEngine(MediaEngineRegistrar); + + void setAsset(id); + virtual void tracksChanged(); + +private: + MediaPlayerPrivateAVFoundationObjC(MediaPlayer*); + ~MediaPlayerPrivateAVFoundationObjC(); + + // engine support + static MediaPlayerPrivateInterface* create(MediaPlayer* player); + static void getSupportedTypes(HashSet<String>& types); + static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs); + static bool isAvailable(); + + virtual void cancelLoad(); + + virtual PlatformMedia platformMedia() const; + + virtual void play(); + virtual void pause(); + virtual float currentTime() const; + virtual void setVolume(float); + virtual void setClosedCaptionsVisible(bool); + virtual void paint(GraphicsContext*, const IntRect&); + virtual void paintCurrentFrameInContext(GraphicsContext*, const IntRect&); + virtual PlatformLayer* platformLayer() const; + virtual bool supportsAcceleratedRendering() const { return true; } + virtual float mediaTimeForTimeValue(float) const; + + virtual void createAVPlayer(); + virtual void createAVPlayerForURL(const String& url); +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + virtual void createAVPlayerForCacheResource(ApplicationCacheResource*); +#endif + virtual MediaPlayerPrivateAVFoundation::ItemStatus playerItemStatus() const; + virtual MediaPlayerPrivateAVFoundation::AVAssetStatus assetStatus() const; + + virtual void checkPlayability(); + virtual float rate() const; + virtual void seekToTime(float time); + virtual unsigned totalBytes() const; + virtual PassRefPtr<TimeRanges> platformBufferedTimeRanges() const; + virtual float platformMaxTimeSeekable() const; + virtual float platformDuration() const; + virtual float platformMaxTimeLoaded() const; + virtual void beginLoadingMetadata(); + virtual void sizeChanged(); + + virtual void createContextVideoRenderer(); + virtual void destroyContextVideoRenderer(); + + virtual void createVideoLayer(); + virtual void destroyVideoLayer(); + virtual bool videoLayerIsReadyToDisplay() const; + + virtual bool hasContextRenderer() const; + virtual bool hasLayerRenderer() const; + + RetainPtr<CGImageRef> createImageForTimeInRect(float, const IntRect&); + + MediaPlayer* m_player; + RetainPtr<AVAsset> m_avAsset; + RetainPtr<AVPlayer> m_avPlayer; + RetainPtr<AVPlayerItem> m_avPlayerItem; + RetainPtr<AVPlayerLayer> m_videoLayer; + RetainPtr<WebCoreAVFMovieObserver> m_objcObserver; + RetainPtr<AVAssetImageGenerator> m_imageGenerator; + id m_timeObserver; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.mm b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.mm new file mode 100644 index 0000000..55eb433 --- /dev/null +++ b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.mm @@ -0,0 +1,811 @@ +/* + * 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 COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "config.h" + +#if ENABLE(VIDEO) && USE(AVFOUNDATION) + +#import "MediaPlayerPrivateAVFoundationObjC.h" + +#import "ApplicationCacheResource.h" +#import "BlockExceptions.h" +#import "FloatConversion.h" +#import "FrameView.h" +#import "FloatConversion.h" +#import "GraphicsContext.h" +#import "KURL.h" +#import "Logging.h" +#import "SoftLinking.h" +#import "TimeRanges.h" +#import "WebCoreSystemInterface.h" +#import <objc/objc-runtime.h> +#import <wtf/UnusedParam.h> + +#import <CoreMedia/CoreMedia.h> +#import <AVFoundation/AVFoundation.h> + +SOFT_LINK_FRAMEWORK(AVFoundation) +SOFT_LINK_FRAMEWORK(CoreMedia) + +SOFT_LINK(CoreMedia, CMTimeCompare, int32_t, (CMTime time1, CMTime time2), (time1, time2)) +SOFT_LINK(CoreMedia, CMTimeMakeWithSeconds, CMTime, (Float64 seconds, int32_t preferredTimeScale), (seconds, preferredTimeScale)) +SOFT_LINK(CoreMedia, CMTimeGetSeconds, Float64, (CMTime time), (time)) +SOFT_LINK(CoreMedia, CMTimeRangeGetEnd, CMTime, (CMTimeRange range), (range)) + +SOFT_LINK_CLASS(AVFoundation, AVPlayer) +SOFT_LINK_CLASS(AVFoundation, AVPlayerItem) +SOFT_LINK_CLASS(AVFoundation, AVPlayerLayer) +SOFT_LINK_CLASS(AVFoundation, AVURLAsset) +SOFT_LINK_CLASS(AVFoundation, AVAssetImageGenerator) + +SOFT_LINK_POINTER(AVFoundation, AVMediaCharacteristicVisual, NSString *) +SOFT_LINK_POINTER(AVFoundation, AVMediaCharacteristicAudible, NSString *) +SOFT_LINK_POINTER(AVFoundation, AVMediaTypeClosedCaption, NSString *) +SOFT_LINK_POINTER(AVFoundation, AVPlayerItemDidPlayToEndTimeNotification, NSString *) +SOFT_LINK_POINTER(AVFoundation, AVAssetImageGeneratorApertureModeCleanAperture, NSString *) + +SOFT_LINK_CONSTANT(CoreMedia, kCMTimeZero, CMTime) + +#define AVPlayer getAVPlayerClass() +#define AVPlayerItem getAVPlayerItemClass() +#define AVPlayerLayer getAVPlayerLayerClass() +#define AVURLAsset getAVURLAssetClass() +#define AVAssetImageGenerator getAVAssetImageGeneratorClass() + +#define AVMediaCharacteristicVisual getAVMediaCharacteristicVisual() +#define AVMediaCharacteristicAudible getAVMediaCharacteristicAudible() +#define AVMediaTypeClosedCaption getAVMediaTypeClosedCaption() +#define AVPlayerItemDidPlayToEndTimeNotification getAVPlayerItemDidPlayToEndTimeNotification() +#define AVAssetImageGeneratorApertureModeCleanAperture getAVAssetImageGeneratorApertureModeCleanAperture() + +#define kCMTimeZero getkCMTimeZero() + +using namespace WebCore; +using namespace std; + +enum MediaPlayerAVFoundationObservationContext { + MediaPlayerAVFoundationObservationContextPlayerItem, + MediaPlayerAVFoundationObservationContextPlayer +}; + +@interface WebCoreAVFMovieObserver : NSObject +{ + MediaPlayerPrivateAVFoundationObjC* m_callback; + int m_delayCallbacks; +} +-(id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback; +-(void)disconnect; +-(void)playableKnown; +-(void)metadataLoaded; +-(void)timeChanged:(double)time; +-(void)didEnd:(NSNotification *)notification; +-(void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary *)change context:(MediaPlayerAVFoundationObservationContext)context; +@end + +namespace WebCore { + +static NSArray *assetMetadataKeyNames(); +static NSArray *itemKVOProperties(); + +#if !LOG_DISABLED +static const char *boolString(bool val) +{ + return val ? "true" : "false"; +} +#endif + +static const float invalidTime = -1.0f; + +MediaPlayerPrivateInterface* MediaPlayerPrivateAVFoundationObjC::create(MediaPlayer* player) +{ + return new MediaPlayerPrivateAVFoundationObjC(player); +} + +void MediaPlayerPrivateAVFoundationObjC::registerMediaEngine(MediaEngineRegistrar registrar) +{ + if (isAvailable()) + registrar(create, getSupportedTypes, supportsType, 0, 0, 0); +} + +MediaPlayerPrivateAVFoundationObjC::MediaPlayerPrivateAVFoundationObjC(MediaPlayer* player) + : MediaPlayerPrivateAVFoundation(player) + , m_objcObserver(AdoptNS, [[WebCoreAVFMovieObserver alloc] initWithCallback:this]) + , m_timeObserver(0) +{ +} + +MediaPlayerPrivateAVFoundationObjC::~MediaPlayerPrivateAVFoundationObjC() +{ + cancelLoad(); + [m_objcObserver.get() disconnect]; +} + +void MediaPlayerPrivateAVFoundationObjC::cancelLoad() +{ + LOG(Media, "MediaPlayerPrivateAVFoundationObjC::cancelLoad(%p)", this); + tearDownVideoRendering(); + + [[NSNotificationCenter defaultCenter] removeObserver:m_objcObserver.get()]; + + // Tell our observer to do nothing when our cancellation of pending loading calls its completion handler. + setIgnoreLoadStateChanges(true); + if (m_avAsset) { + [m_avAsset.get() cancelLoading]; + m_avAsset = nil; + } + if (m_avPlayerItem) { + for (NSString *keyName in itemKVOProperties()) + [m_avPlayerItem.get() removeObserver:m_objcObserver.get() forKeyPath:keyName]; + + m_avPlayerItem = nil; + } + if (m_avPlayer) { + if (m_timeObserver) + [m_avPlayer.get() removeTimeObserver:m_timeObserver]; + [m_avPlayer.get() removeObserver:m_objcObserver.get() forKeyPath:@"rate"]; + m_avPlayer = nil; + } + setIgnoreLoadStateChanges(false); +} + +bool MediaPlayerPrivateAVFoundationObjC::hasLayerRenderer() const +{ + return m_videoLayer; +} + +bool MediaPlayerPrivateAVFoundationObjC::hasContextRenderer() const +{ + return m_imageGenerator; +} + +void MediaPlayerPrivateAVFoundationObjC::createContextVideoRenderer() +{ + LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createContextVideoRenderer(%p)", this); + + if (!m_avAsset || m_imageGenerator) + return; + + m_imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:m_avAsset.get()]; + + [m_imageGenerator.get() setApertureMode:AVAssetImageGeneratorApertureModeCleanAperture]; + [m_imageGenerator.get() setAppliesPreferredTrackTransform:YES]; + + LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createImageGenerator(%p) - returning %p", this, m_imageGenerator.get()); +} + +void MediaPlayerPrivateAVFoundationObjC::destroyContextVideoRenderer() +{ + if (!m_imageGenerator) + return; + + LOG(Media, "MediaPlayerPrivateAVFoundationObjC::destroyContextVideoRenderer(%p) - destroying", this, m_imageGenerator.get()); + + m_imageGenerator = 0; +} + +void MediaPlayerPrivateAVFoundationObjC::createVideoLayer() +{ + if (!m_avPlayer) + return; + + if (!m_videoLayer) { + m_videoLayer.adoptNS([[AVPlayerLayer alloc] init]); + [m_videoLayer.get() setPlayer:m_avPlayer.get()]; + LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createVideoLayer(%p) - returning", this, m_videoLayer.get()); + } +} + +void MediaPlayerPrivateAVFoundationObjC::destroyVideoLayer() +{ + if (!m_videoLayer) + return; + + LOG(Media, "MediaPlayerPrivateAVFoundationObjC::destroyVideoLayer(%p) - destroying", this, m_videoLayer.get()); + + [m_videoLayer.get() setPlayer:nil]; + + m_videoLayer = 0; +} + +bool MediaPlayerPrivateAVFoundationObjC::videoLayerIsReadyToDisplay() const +{ + return (m_videoLayer && [m_videoLayer.get() isReadyForDisplay]); +} + +void MediaPlayerPrivateAVFoundationObjC::createAVPlayerForURL(const String& url) +{ + setDelayCallbacks(true); + + if (!m_avAsset) { + NSURL *cocoaURL = KURL(ParsedURLString, url); + m_avAsset.adoptNS([[AVURLAsset alloc] initWithURL:cocoaURL options:nil]); + } + + createAVPlayer(); +} + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +void MediaPlayerPrivateAVFoundationObjC::createAVPlayerForCacheResource(ApplicationCacheResource* resource) +{ + // AVFoundation can't open arbitrary data pointers, so if this ApplicationCacheResource doesn't + // have a valid local path, just open the resource's original URL. + if (resource->path().isEmpty()) { + createAVPlayerForURL(resource->url()); + return; + } + + setDelayCallbacks(true); + + if (!m_avAsset) { + NSURL* localURL = [NSURL fileURLWithPath:resource->path()]; + m_avAsset.adoptNS([[AVURLAsset alloc] initWithURL:localURL options:nil]); + } + + createAVPlayer(); +} +#endif + +void MediaPlayerPrivateAVFoundationObjC::createAVPlayer() +{ + if (!m_avPlayer) { + m_avPlayer.adoptNS([[AVPlayer alloc] init]); + + [m_avPlayer.get() addObserver:m_objcObserver.get() forKeyPath:@"rate" options:nil context:(void *)MediaPlayerAVFoundationObservationContextPlayer]; + + // Add a time observer, ask to be called infrequently because we don't really want periodic callbacks but + // our observer will also be called whenever a seek happens. + const double veryLongInterval = 60*60*60*24*30; + WebCoreAVFMovieObserver *observer = m_objcObserver.get(); + m_timeObserver = [m_avPlayer.get() addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(veryLongInterval, 10) queue:nil usingBlock:^(CMTime time){ + [observer timeChanged:CMTimeGetSeconds(time)]; + }]; + } + + if (!m_avPlayerItem) { + // Create the player item so we can media data. + m_avPlayerItem.adoptNS([[AVPlayerItem alloc] initWithAsset:m_avAsset.get()]); + + [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()selector:@selector(didEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:m_avPlayerItem.get()]; + + for (NSString *keyName in itemKVOProperties()) + [m_avPlayerItem.get() addObserver:m_objcObserver.get() forKeyPath:keyName options:nil context:(void *)MediaPlayerAVFoundationObservationContextPlayerItem]; + + [m_avPlayer.get() replaceCurrentItemWithPlayerItem:m_avPlayerItem.get()]; + } + + setDelayCallbacks(false); +} + +void MediaPlayerPrivateAVFoundationObjC::checkPlayability() +{ + LOG(Media, "MediaPlayerPrivateAVFoundationObjC::checkPlayability(%p)", this); + + [m_avAsset.get() loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:@"playable"] completionHandler:^{ + [m_objcObserver.get() playableKnown]; + }]; +} + +void MediaPlayerPrivateAVFoundationObjC::beginLoadingMetadata() +{ + LOG(Media, "MediaPlayerPrivateAVFoundationObjC::playabilityKnown(%p) - requesting metadata loading", this); + [m_avAsset.get() loadValuesAsynchronouslyForKeys:[assetMetadataKeyNames() retain] completionHandler:^{ + [m_objcObserver.get() metadataLoaded]; + }]; +} + +MediaPlayerPrivateAVFoundation::ItemStatus MediaPlayerPrivateAVFoundationObjC::playerItemStatus() const +{ + if (!m_avPlayerItem) + return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusUnknown; + + AVPlayerItemStatus status = [m_avPlayerItem.get() status]; + if (status == AVPlayerItemStatusUnknown) + return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusUnknown; + if (status == AVPlayerItemStatusFailed) + return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusFailed; + if ([m_avPlayerItem.get() isPlaybackLikelyToKeepUp]) + return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusPlaybackLikelyToKeepUp; + if ([m_avPlayerItem.get() isPlaybackBufferFull]) + return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusPlaybackBufferFull; + if ([m_avPlayerItem.get() isPlaybackBufferEmpty]) + return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusPlaybackBufferEmpty; + + return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusReadyToPlay; +} + +PlatformMedia MediaPlayerPrivateAVFoundationObjC::platformMedia() const +{ + LOG(Media, "MediaPlayerPrivateAVFoundationObjC::platformMedia(%p)", this); + PlatformMedia pm; + pm.type = PlatformMedia::AVFoundationMediaPlayerType; + pm.media.avfMediaPlayer = m_avPlayer.get(); + return pm; +} + +PlatformLayer* MediaPlayerPrivateAVFoundationObjC::platformLayer() const +{ + LOG(Media, "MediaPlayerPrivateAVFoundationObjC::platformLayer(%p)", this); + return m_videoLayer.get(); +} + +void MediaPlayerPrivateAVFoundationObjC::play() +{ + LOG(Media, "MediaPlayerPrivateAVFoundationObjC::play(%p)", this); + if (!metaDataAvailable()) + return; + + setDelayCallbacks(true); + [m_avPlayer.get() setRate:requestedRate()]; + setDelayCallbacks(false); +} + +void MediaPlayerPrivateAVFoundationObjC::pause() +{ + LOG(Media, "MediaPlayerPrivateAVFoundationObjC::pause(%p)", this); + if (!metaDataAvailable()) + return; + + setDelayCallbacks(true); + [m_avPlayer.get() setRate:nil]; + setDelayCallbacks(false); +} + +float MediaPlayerPrivateAVFoundationObjC::platformDuration() const +{ + if (!metaDataAvailable() || !m_avPlayerItem) + return 0; + + float duration; + CMTime cmDuration = [m_avPlayerItem.get() duration]; + if (CMTIME_IS_NUMERIC(cmDuration)) + duration = narrowPrecisionToFloat(CMTimeGetSeconds(cmDuration)); + else if (CMTIME_IS_INDEFINITE(cmDuration)) + duration = numeric_limits<float>::infinity(); + else { + LOG(Media, "MediaPlayerPrivateAVFoundationObjC::duration(%p) - invalid duration, returning 0", this); + return 0; + } + + return duration; +} + +float MediaPlayerPrivateAVFoundationObjC::currentTime() const +{ + if (!metaDataAvailable() || !m_avPlayerItem) + return 0; + + CMTime itemTime = [m_avPlayerItem.get() currentTime]; + if (CMTIME_IS_NUMERIC(itemTime)) + return narrowPrecisionToFloat(CMTimeGetSeconds(itemTime)); + + return 0; +} + +void MediaPlayerPrivateAVFoundationObjC::seekToTime(float time) +{ + // setCurrentTime generates several event callbacks, update afterwards. + setDelayCallbacks(true); + + float now = currentTime(); + if (time != now) + [m_avPlayerItem.get() seekToTime:CMTimeMakeWithSeconds(time, 600) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero]; + else { + // Force a call to the "time changed" notifier manually because a seek to the current time is a noop + // so the seek will never seem to complete. + [m_objcObserver.get() timeChanged:now]; + } + + setDelayCallbacks(false); +} + +void MediaPlayerPrivateAVFoundationObjC::setVolume(float volume) +{ + if (!metaDataAvailable()) + return; + + [m_avPlayer.get() setVolume:volume]; +} + +void MediaPlayerPrivateAVFoundationObjC::setClosedCaptionsVisible(bool closedCaptionsVisible) +{ + if (!metaDataAvailable()) + return; + + LOG(Media, "MediaPlayerPrivateAVFoundationObjC::setClosedCaptionsVisible(%p) - setting to %s", this, boolString(closedCaptionsVisible)); + [m_avPlayer.get() setClosedCaptionDisplayEnabled:closedCaptionsVisible]; +} + +float MediaPlayerPrivateAVFoundationObjC::rate() const +{ + if (!metaDataAvailable()) + return 0; + + return [m_avPlayer.get() rate]; +} + +PassRefPtr<TimeRanges> MediaPlayerPrivateAVFoundationObjC::platformBufferedTimeRanges() const +{ + RefPtr<TimeRanges> timeRanges = TimeRanges::create(); + + if (!m_avPlayerItem) + return timeRanges.release(); + + NSArray *loadedRanges = [m_avPlayerItem.get() loadedTimeRanges]; + for (NSValue *thisRangeValue in loadedRanges) { + CMTimeRange timeRange = [thisRangeValue CMTimeRangeValue]; + if (CMTIMERANGE_IS_VALID(timeRange) && !CMTIMERANGE_IS_EMPTY(timeRange)) { + float rangeStart = narrowPrecisionToFloat(CMTimeGetSeconds(timeRange.start)); + float rangeEnd = narrowPrecisionToFloat(CMTimeGetSeconds(CMTimeRangeGetEnd(timeRange))); + timeRanges->add(rangeStart, rangeEnd); + } + } + return timeRanges.release(); +} + +float MediaPlayerPrivateAVFoundationObjC::platformMaxTimeSeekable() const +{ + NSArray *seekableRanges = [m_avPlayerItem.get() seekableTimeRanges]; + if (!seekableRanges) + return 0; + + float maxTimeSeekable = 0; + for (NSValue *thisRangeValue in seekableRanges) { + CMTimeRange timeRange = [thisRangeValue CMTimeRangeValue]; + if (!CMTIMERANGE_IS_VALID(timeRange) || CMTIMERANGE_IS_EMPTY(timeRange)) + continue; + + float endOfRange = narrowPrecisionToFloat(CMTimeGetSeconds(CMTimeRangeGetEnd(timeRange))); + if (maxTimeSeekable < endOfRange) + maxTimeSeekable = endOfRange; + } + return maxTimeSeekable; +} + +float MediaPlayerPrivateAVFoundationObjC::platformMaxTimeLoaded() const +{ + NSArray *loadedRanges = [m_avPlayerItem.get() loadedTimeRanges]; + if (!loadedRanges) + return 0; + + float maxTimeLoaded = 0; + for (NSValue *thisRangeValue in loadedRanges) { + CMTimeRange timeRange = [thisRangeValue CMTimeRangeValue]; + if (!CMTIMERANGE_IS_VALID(timeRange) || CMTIMERANGE_IS_EMPTY(timeRange)) + continue; + + float endOfRange = narrowPrecisionToFloat(CMTimeGetSeconds(CMTimeRangeGetEnd(timeRange))); + if (maxTimeLoaded < endOfRange) + maxTimeLoaded = endOfRange; + } + + return maxTimeLoaded; +} + +unsigned MediaPlayerPrivateAVFoundationObjC::totalBytes() const +{ + if (!metaDataAvailable()) + return 0; + + long long totalMediaSize = 0; + NSArray *tracks = [m_avAsset.get() tracks]; + for (AVAssetTrack *thisTrack in tracks) + totalMediaSize += [thisTrack totalSampleDataLength]; + + return static_cast<unsigned>(totalMediaSize); +} + +void MediaPlayerPrivateAVFoundationObjC::setAsset(id asset) +{ + m_avAsset = asset; +} + +MediaPlayerPrivateAVFoundation::AVAssetStatus MediaPlayerPrivateAVFoundationObjC::assetStatus() const +{ + if (!m_avAsset) + return MediaPlayerAVAssetStatusUnknown; + + for (NSString *keyName in assetMetadataKeyNames()) { + AVKeyValueStatus keyStatus = [m_avAsset.get() statusOfValueForKey:keyName error:nil]; + if (keyStatus < AVKeyValueStatusLoaded) + return MediaPlayerAVAssetStatusLoading;// At least one key is not loaded yet. + + if (keyStatus == AVKeyValueStatusFailed) + return MediaPlayerAVAssetStatusFailed; // At least one key could not be loaded. + if (keyStatus == AVKeyValueStatusCancelled) + return MediaPlayerAVAssetStatusCancelled; // Loading of at least one key was cancelled. + } + + if ([[m_avAsset.get() valueForKey:@"playable"] boolValue]) + return MediaPlayerAVAssetStatusPlayable; + + return MediaPlayerAVAssetStatusLoaded; +} + +void MediaPlayerPrivateAVFoundationObjC::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& rect) +{ + if (!metaDataAvailable() || context->paintingDisabled()) + return; + + paint(context, rect); +} + +void MediaPlayerPrivateAVFoundationObjC::paint(GraphicsContext* context, const IntRect& rect) +{ + if (!metaDataAvailable() || context->paintingDisabled()) + return; + + setDelayCallbacks(true); + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + RetainPtr<CGImageRef> image = createImageForTimeInRect(currentTime(), rect); + if (image) { + context->save(); + context->translate(rect.x(), rect.y() + rect.height()); + context->scale(FloatSize(1.0f, -1.0f)); + context->setImageInterpolationQuality(InterpolationLow); + IntRect paintRect(IntPoint(0, 0), IntSize(rect.width(), rect.height())); + CGContextDrawImage(context->platformContext(), CGRectMake(0, 0, paintRect.width(), paintRect.height()), image.get()); + context->restore(); + image = 0; + } + + END_BLOCK_OBJC_EXCEPTIONS; + setDelayCallbacks(false); + + MediaPlayerPrivateAVFoundation::paint(context, rect); +} + +static HashSet<String> mimeTypeCache() +{ + DEFINE_STATIC_LOCAL(HashSet<String>, cache, ()); + static bool typeListInitialized = false; + + if (typeListInitialized) + return cache; + typeListInitialized = true; + + NSArray *types = [AVURLAsset audiovisualMIMETypes]; + for (NSString *mimeType in types) + cache.add(mimeType); + + return cache; +} + +RetainPtr<CGImageRef> MediaPlayerPrivateAVFoundationObjC::createImageForTimeInRect(float time, const IntRect& rect) +{ + if (!m_imageGenerator) + createContextVideoRenderer(); + ASSERT(m_imageGenerator); + +#if !LOG_DISABLED + double start = WTF::currentTime(); +#endif + + [m_imageGenerator.get() setMaximumSize:CGSize(rect.size())]; + CGImageRef image = [m_imageGenerator.get() copyCGImageAtTime:CMTimeMakeWithSeconds(time, 600) actualTime:nil error:nil]; + +#if !LOG_DISABLED + double duration = WTF::currentTime() - start; + LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createImageForTimeInRect(%p) - creating image took %.4f", this, narrowPrecisionToFloat(duration)); +#endif + + return image; +} + +void MediaPlayerPrivateAVFoundationObjC::getSupportedTypes(HashSet<String>& supportedTypes) +{ + supportedTypes = mimeTypeCache(); +} + +MediaPlayer::SupportsType MediaPlayerPrivateAVFoundationObjC::supportsType(const String& type, const String& codecs) +{ + // Only return "IsSupported" if there is no codecs parameter for now as there is no way to ask if it supports an + // extended MIME type until rdar://6220037 is fixed. + if (mimeTypeCache().contains(type)) + return codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported; + + return MediaPlayer::IsNotSupported; +} + +bool MediaPlayerPrivateAVFoundationObjC::isAvailable() +{ + return true; +} + +float MediaPlayerPrivateAVFoundationObjC::mediaTimeForTimeValue(float timeValue) const +{ + if (!metaDataAvailable()) + return timeValue; + + // FIXME - impossible to implement until rdar://8721510 is fixed. + return timeValue; +} + +void MediaPlayerPrivateAVFoundationObjC::tracksChanged() +{ + // This is called whenever the tracks collection changes so cache hasVideo and hasAudio since we get + // asked about those fairly fequently. + setHasVideo([[m_avAsset.get() tracksWithMediaCharacteristic:AVMediaCharacteristicVisual] count]); + setHasAudio([[m_avAsset.get() tracksWithMediaCharacteristic:AVMediaCharacteristicAudible] count]); + setHasClosedCaptions([[m_avAsset.get() tracksWithMediaType:AVMediaTypeClosedCaption] count]); + + sizeChanged(); +} + +void MediaPlayerPrivateAVFoundationObjC::sizeChanged() +{ + NSArray *tracks = [m_avAsset.get() tracks]; + + // Some assets don't report track properties until they are completely ready to play, but we + // want to report a size as early as possible so use presentationSize when an asset has no tracks. + if (![tracks count]) { + setNaturalSize(IntSize([m_avPlayerItem.get() presentationSize])); + return; + } + + // AVAsset's 'naturalSize' property only considers the movie's first video track, so we need to compute + // the union of all visual track rects. + CGRect trackUnionRect = CGRectZero; + for (AVAssetTrack *track in tracks) { + CGSize trackSize = [track naturalSize]; + CGRect trackRect = CGRectMake(0, 0, trackSize.width, trackSize.height); + trackUnionRect = CGRectUnion(trackUnionRect, CGRectApplyAffineTransform(trackRect, [track preferredTransform])); + } + + // The movie is always displayed at 0,0 so move the track rect to the origin before using width and height. + trackUnionRect = CGRectOffset(trackUnionRect, trackUnionRect.origin.x, trackUnionRect.origin.y); + + // Also look at the asset's preferred transform so we account for a movie matrix. + CGSize naturalSize = CGSizeApplyAffineTransform(trackUnionRect.size, [m_avAsset.get() preferredTransform]); + + // Cache the natural size (setNaturalSize will notify the player if it has changed). + setNaturalSize(IntSize(naturalSize)); +} + +NSArray* assetMetadataKeyNames() +{ + static NSArray* keys; + if (!keys) { + keys = [[NSArray alloc] initWithObjects:@"duration", + @"naturalSize", + @"preferredTransform", + @"preferredVolume", + @"preferredRate", + @"playable", + @"tracks", + nil]; + } + return keys; +} + +NSArray* itemKVOProperties() +{ + static NSArray* keys; + if (!keys) { + keys = [[NSArray alloc] initWithObjects:@"presentationSize", + @"status", + @"asset", + @"tracks", + @"seekableTimeRanges", + @"loadedTimeRanges", + @"playbackLikelyToKeepUp", + @"playbackBufferFull", + @"playbackBufferEmpty", + nil]; + } + return keys; +} + +} // namespace WebCore + +@implementation WebCoreAVFMovieObserver + +- (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback +{ + m_callback = callback; + return [super init]; +} + +- (void)disconnect +{ + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + m_callback = 0; +} + +- (void)metadataLoaded +{ + if (!m_callback) + return; + + m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::AssetMetadataLoaded); +} + +- (void)playableKnown +{ + if (!m_callback) + return; + + m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::AssetPlayabilityKnown); +} + +- (void)timeChanged:(double)time +{ + if (!m_callback) + return; + + m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::PlayerTimeChanged, time); +} + +- (void)didEnd:(NSNotification *)unusedNotification +{ + UNUSED_PARAM(unusedNotification); + if (!m_callback) + return; + m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemDidPlayToEndTime); +} + +- (void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary *)change context:(MediaPlayerAVFoundationObservationContext)context +{ + UNUSED_PARAM(change); + + LOG(Media, "WebCoreAVFMovieObserver:observeValueForKeyPath(%p) - keyPath = %s", self, [keyPath UTF8String]); + + if (!m_callback) + return; + + if (context == MediaPlayerAVFoundationObservationContextPlayerItem) { + // A value changed for an AVPlayerItem + if ([keyPath isEqualToString:@"status"]) + m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemStatusChanged); + else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) + m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemIsPlaybackLikelyToKeepUpChanged); + else if ([keyPath isEqualToString:@"playbackBufferEmpty"]) + m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemIsPlaybackBufferEmptyChanged); + else if ([keyPath isEqualToString:@"playbackBufferFull"]) + m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemIsPlaybackBufferFullChanged); + else if ([keyPath isEqualToString:@"asset"]) + m_callback->setAsset([object asset]); + else if ([keyPath isEqualToString:@"loadedTimeRanges"]) + m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemLoadedTimeRangesChanged); + else if ([keyPath isEqualToString:@"seekableTimeRanges"]) + m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemSeekableTimeRangesChanged); + else if ([keyPath isEqualToString:@"tracks"]) + m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemTracksChanged); + else if ([keyPath isEqualToString:@"presentationSize"]) + m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemPresentationSizeChanged); + + return; + } + + if (context == MediaPlayerAVFoundationObservationContextPlayer) { + // A value changed for an AVPlayer. + if ([keyPath isEqualToString:@"rate"]) + m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::PlayerRateChanged); +} +} + +@end + +#endif diff --git a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp index e9663a6..427c7bf 100644 --- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp +++ b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp @@ -550,11 +550,17 @@ void GraphicsLayerCA::setNeedsDisplay() setNeedsDisplayInRect(hugeRect); } -void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& rect) +void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& r) { if (!drawsContent()) return; + FloatRect rect(r); + FloatRect layerBounds(FloatPoint(), m_size); + rect.intersect(layerBounds); + if (rect.isEmpty()) + return; + const size_t maxDirtyRects = 32; for (size_t i = 0; i < m_dirtyRects.size(); ++i) { @@ -1601,9 +1607,11 @@ bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValue TransformOperation::OperationType transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : functionList[animationIndex]; RefPtr<PlatformCAAnimation> caAnimation; -#if defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD) +#if defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD) || PLATFORM(WIN) // CA applies animations in reverse order (<rdar://problem/7095638>) so we need the last one we add (per property) // to be non-additive. + // FIXME: This fix has not been added to QuartzCore on Windows yet (<rdar://problem/9112233>) so we expect the + // reversed animation behavior bool additive = animationIndex < (numAnimations - 1); #else bool additive = animationIndex > 0; diff --git a/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h b/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h index a8528fd..8b5a460 100644 --- a/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h +++ b/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h @@ -38,11 +38,10 @@ #if PLATFORM(MAC) #ifdef __OBJC__ @class CAPropertyAnimation; -typedef CAPropertyAnimation* PlatformAnimationRef; #else -typedef void* CAPropertyAnimation; // So the m_animation declaration works -typedef void* PlatformAnimationRef; +class CAPropertyAnimation; #endif +typedef CAPropertyAnimation* PlatformAnimationRef; #elif PLATFORM(WIN) typedef struct _CACFAnimation* CACFAnimationRef; typedef CACFAnimationRef PlatformAnimationRef; diff --git a/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp b/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp index f2e1950..75f4a10 100644 --- a/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp +++ b/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp @@ -307,13 +307,14 @@ void CACFLayerTreeHost::contextDidChange() void CACFLayerTreeHost::notifyAnimationsStarted() { + // Send currentTime to the pending animations. This function is called by CACF in a callback + // which occurs after the drawInContext calls. So currentTime is very close to the time + // the animations actually start double currentTime = WTF::currentTime(); - double time = currentTime + lastCommitTime() - CACurrentMediaTime(); - ASSERT(time <= currentTime); HashSet<RefPtr<PlatformCALayer> >::iterator end = m_pendingAnimatedLayers.end(); for (HashSet<RefPtr<PlatformCALayer> >::iterator it = m_pendingAnimatedLayers.begin(); it != end; ++it) - (*it)->animationStarted(time); + (*it)->animationStarted(currentTime); m_pendingAnimatedLayers.clear(); } diff --git a/Source/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp b/Source/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp index b0588d6..0f90ce4 100644 --- a/Source/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp @@ -34,6 +34,7 @@ #include "GraphicsContext.h" #include "OwnPtrCairo.h" #include "Path.h" +#include "PlatformContextCairo.h" #include "Timer.h" #include <cairo.h> @@ -88,7 +89,7 @@ PlatformContext ContextShadow::beginShadowLayer(GraphicsContext* context, const adjustBlurDistance(context); double x1, x2, y1, y2; - cairo_clip_extents(context->platformContext(), &x1, &y1, &x2, &y2); + cairo_clip_extents(context->platformContext()->cr(), &x1, &y1, &x2, &y2); IntRect layerRect = calculateLayerBoundingRect(context, layerArea, IntRect(x1, y1, x2 - x1, y2 - y1)); // Don't paint if we are totally outside the clip region. @@ -120,7 +121,7 @@ void ContextShadow::endShadowLayer(GraphicsContext* context) cairo_surface_mark_dirty(m_layerImage); } - cairo_t* cr = context->platformContext(); + cairo_t* cr = context->platformContext()->cr(); cairo_save(cr); setSourceRGBAFromColor(cr, m_color); cairo_mask_surface(cr, m_layerImage, m_layerOrigin.x(), m_layerOrigin.y()); @@ -198,7 +199,7 @@ void ContextShadow::drawRectShadow(GraphicsContext* context, const IntRect& rect int internalShadowHeight = radiusTwice + max(topLeftRadius.height(), topRightRadius.height()) + max(bottomLeftRadius.height(), bottomRightRadius.height()); - cairo_t* cr = context->platformContext(); + cairo_t* cr = context->platformContext()->cr(); // drawShadowedRect still does not work with rotations. // https://bugs.webkit.org/show_bug.cgi?id=45042 diff --git a/Source/WebCore/platform/graphics/cairo/FontCairo.cpp b/Source/WebCore/platform/graphics/cairo/FontCairo.cpp index 2d79499..58a7fd2 100644 --- a/Source/WebCore/platform/graphics/cairo/FontCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/FontCairo.cpp @@ -36,6 +36,7 @@ #include "GlyphBuffer.h" #include "Gradient.h" #include "GraphicsContext.h" +#include "PlatformContextCairo.h" #include "ImageBuffer.h" #include "Pattern.h" #include "SimpleFontData.h" @@ -64,7 +65,7 @@ static void drawGlyphsToContext(cairo_t* context, const SimpleFontData* font, Gl } } -static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context, const FloatPoint& point, const SimpleFontData* font, GlyphBufferGlyph* glyphs, int numGlyphs) +static void drawGlyphsShadow(GraphicsContext* graphicsContext, const FloatPoint& point, const SimpleFontData* font, GlyphBufferGlyph* glyphs, int numGlyphs) { ContextShadow* shadow = graphicsContext->contextShadow(); ASSERT(shadow); @@ -74,6 +75,7 @@ static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context, if (!shadow->mustUseContextShadow(graphicsContext)) { // Optimize non-blurry shadows, by just drawing text without the ContextShadow. + cairo_t* context = graphicsContext->platformContext()->cr(); cairo_save(context); cairo_translate(context, shadow->m_offset.width(), shadow->m_offset.height()); setSourceRGBAFromColor(context, shadow->m_color); @@ -106,9 +108,10 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons offset += glyphBuffer.advanceAt(from + i); } - cairo_t* cr = context->platformContext(); - drawGlyphsShadow(context, cr, point, font, glyphs, numGlyphs); + PlatformContextCairo* platformContext = context->platformContext(); + drawGlyphsShadow(context, point, font, glyphs, numGlyphs); + cairo_t* cr = platformContext->cr(); cairo_save(cr); prepareContextForGlyphDrawing(cr, font, point); if (context->textDrawingMode() & TextModeFill) { diff --git a/Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h index 5807102..f8f3c99 100644 --- a/Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h +++ b/Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h @@ -25,6 +25,7 @@ #include "FontOrientation.h" #include "FontRenderingMode.h" #include "FontWidthVariant.h" +#include "TextOrientation.h" #include <wtf/Forward.h> #include <wtf/Noncopyable.h> @@ -41,7 +42,7 @@ struct FontCustomPlatformData { public: FontCustomPlatformData(FT_Face, SharedBuffer*); ~FontCustomPlatformData(); - FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode); + FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode); static bool supportsFormat(const String&); private: diff --git a/Source/WebCore/platform/graphics/cairo/GradientCairo.cpp b/Source/WebCore/platform/graphics/cairo/GradientCairo.cpp index 4e6ed07..225046a 100644 --- a/Source/WebCore/platform/graphics/cairo/GradientCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/GradientCairo.cpp @@ -29,6 +29,7 @@ #include "CSSParser.h" #include "GraphicsContext.h" +#include "PlatformContextCairo.h" #include <cairo.h> namespace WebCore { @@ -87,7 +88,7 @@ void Gradient::setPlatformGradientSpaceTransform(const AffineTransform& gradient void Gradient::fill(GraphicsContext* context, const FloatRect& rect) { - cairo_t* cr = context->platformContext(); + cairo_t* cr = context->platformContext()->cr(); context->save(); cairo_set_source(cr, platformGradient()); diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp index e69a7a5..0fc94df 100644 --- a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp @@ -47,6 +47,7 @@ #include "NotImplemented.h" #include "Path.h" #include "Pattern.h" +#include "PlatformContextCairo.h" #include "RefPtrCairo.h" #include "SimpleFontData.h" #include <cairo.h> @@ -148,7 +149,7 @@ static inline void drawPathShadow(GraphicsContext* context, PathDrawingStyle dra return; // Calculate the extents of the rendered solid paths. - cairo_t* cairoContext = context->platformContext(); + cairo_t* cairoContext = context->platformContext()->cr(); OwnPtr<cairo_path_t> path(cairo_copy_path(cairoContext)); FloatRect solidFigureExtents; @@ -199,12 +200,18 @@ static void strokeCurrentCairoPath(GraphicsContext* context, cairo_t* cairoCont cairo_new_path(cairoContext); } -void GraphicsContext::platformInit(PlatformGraphicsContext* cr) +GraphicsContext::GraphicsContext(cairo_t* cr) { - m_data = new GraphicsContextPlatformPrivate; - m_data->cr = cairo_reference(cr); - m_data->syncContext(cr); - setPaintingDisabled(!cr); + m_data = new GraphicsContextPlatformPrivate(new PlatformContextCairo(cr)); +} + +void GraphicsContext::platformInit(PlatformContextCairo* platformContext) +{ + m_data = new GraphicsContextPlatformPrivate(platformContext); + if (platformContext) + m_data->syncContext(platformContext->cr()); + else + setPaintingDisabled(true); } void GraphicsContext::platformDestroy() @@ -214,20 +221,20 @@ void GraphicsContext::platformDestroy() AffineTransform GraphicsContext::getCTM() const { - cairo_t* cr = platformContext(); + cairo_t* cr = platformContext()->cr(); cairo_matrix_t m; cairo_get_matrix(cr, &m); return AffineTransform(m.xx, m.yx, m.xy, m.yy, m.x0, m.y0); } -cairo_t* GraphicsContext::platformContext() const +PlatformContextCairo* GraphicsContext::platformContext() const { - return m_data->cr; + return m_data->platformContext; } void GraphicsContext::savePlatformState() { - cairo_save(m_data->cr); + cairo_save(platformContext()->cr()); m_data->save(); m_data->shadowStack.append(m_data->shadow); m_data->maskImageStack.append(ImageMaskInformation()); @@ -235,7 +242,8 @@ void GraphicsContext::savePlatformState() void GraphicsContext::restorePlatformState() { - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); + const ImageMaskInformation& maskInformation = m_data->maskImageStack.last(); if (maskInformation.isValid()) { const FloatRect& maskRect = maskInformation.maskRect(); @@ -251,7 +259,7 @@ void GraphicsContext::restorePlatformState() m_data->shadowStack.removeLast(); } - cairo_restore(m_data->cr); + cairo_restore(cr); m_data->restore(); } @@ -261,7 +269,7 @@ void GraphicsContext::drawRect(const IntRect& rect) if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_save(cr); if (fillColor().alpha()) @@ -289,7 +297,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) if (style == NoStroke) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_save(cr); float width = strokeThickness(); @@ -376,7 +384,7 @@ void GraphicsContext::drawEllipse(const IntRect& rect) if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_save(cr); float yRadius = .5 * rect.height(); float xRadius = .5 * rect.width(); @@ -415,7 +423,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp float fa = startAngle; float falen = fa + angleSpan; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_save(cr); if (w != h) @@ -492,7 +500,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points if (npoints <= 1) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_save(cr); cairo_set_antialias(cr, shouldAntialias ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE); @@ -522,7 +530,7 @@ void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* poin if (numPoints <= 1) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_new_path(cr); cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr); @@ -542,7 +550,7 @@ void GraphicsContext::fillPath(const Path& path) if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); setPathOnCairoContext(cr, path.platformPath()->context()); fillCurrentCairoPath(this, cr); } @@ -552,7 +560,7 @@ void GraphicsContext::strokePath(const Path& path) if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); setPathOnCairoContext(cr, path.platformPath()->context()); strokeCurrentCairoPath(this, cr); } @@ -562,7 +570,7 @@ void GraphicsContext::fillRect(const FloatRect& rect) if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_save(cr); cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height()); fillCurrentCairoPath(this, cr); @@ -578,7 +586,7 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS m_data->shadow.drawRectShadow(this, enclosingIntRect(rect)); if (color.alpha()) - fillRectSourceOver(m_data->cr, rect, color); + fillRectSourceOver(platformContext()->cr(), rect, color); } void GraphicsContext::clip(const FloatRect& rect) @@ -586,7 +594,7 @@ void GraphicsContext::clip(const FloatRect& rect) if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height()); cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr); cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING); @@ -600,7 +608,7 @@ void GraphicsContext::clipPath(const Path& path, WindRule clipRule) if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); setPathOnCairoContext(cr, path.platformPath()->context()); cairo_set_fill_rule(cr, clipRule == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING); cairo_clip(cr); @@ -638,7 +646,7 @@ void GraphicsContext::drawFocusRing(const Path& path, int width, int /* offset * adjustFocusRingColor(ringColor); adjustFocusRingLineWidth(width); - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_save(cr); appendWebCorePathToCairoContext(cr, path); setSourceRGBAFromColor(cr, ringColor); @@ -655,7 +663,7 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int unsigned rectCount = rects.size(); - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_save(cr); cairo_push_group(cr); cairo_new_path(cr); @@ -732,7 +740,7 @@ void GraphicsContext::drawLineForTextChecking(const FloatPoint& origin, float wi if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_save(cr); switch (style) { @@ -762,7 +770,7 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect) FloatRect result; double x = frect.x(); double y = frect.y(); - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_user_to_device(cr, &x, &y); x = round(x); y = round(y); @@ -799,7 +807,7 @@ void GraphicsContext::translate(float x, float y) if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_translate(cr, x, y); m_data->translate(x, y); } @@ -821,7 +829,7 @@ void GraphicsContext::setPlatformStrokeThickness(float strokeThickness) if (paintingDisabled()) return; - cairo_set_line_width(m_data->cr, strokeThickness); + cairo_set_line_width(platformContext()->cr(), strokeThickness); } void GraphicsContext::setPlatformStrokeStyle(StrokeStyle strokeStyle) @@ -835,16 +843,16 @@ void GraphicsContext::setPlatformStrokeStyle(StrokeStyle strokeStyle) switch (strokeStyle) { case NoStroke: // FIXME: is it the right way to emulate NoStroke? - cairo_set_line_width(m_data->cr, 0); + cairo_set_line_width(platformContext()->cr(), 0); break; case SolidStroke: - cairo_set_dash(m_data->cr, 0, 0, 0); + cairo_set_dash(platformContext()->cr(), 0, 0, 0); break; case DottedStroke: - cairo_set_dash(m_data->cr, dotPattern, 2, 0); + cairo_set_dash(platformContext()->cr(), dotPattern, 2, 0); break; case DashedStroke: - cairo_set_dash(m_data->cr, dashPattern, 2, 0); + cairo_set_dash(platformContext()->cr(), dashPattern, 2, 0); break; } } @@ -859,7 +867,7 @@ void GraphicsContext::concatCTM(const AffineTransform& transform) if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); const cairo_matrix_t matrix = cairo_matrix_t(transform); cairo_transform(cr, &matrix); m_data->concatCTM(transform); @@ -870,7 +878,7 @@ void GraphicsContext::setCTM(const AffineTransform& transform) if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); const cairo_matrix_t matrix = cairo_matrix_t(transform); cairo_set_matrix(cr, &matrix); m_data->setCTM(transform); @@ -881,7 +889,7 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); clip(rect); Path p; @@ -928,7 +936,7 @@ void GraphicsContext::beginTransparencyLayer(float opacity) if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_push_group(cr); m_data->layers.append(opacity); m_data->beginTransparencyLayer(); @@ -939,7 +947,7 @@ void GraphicsContext::endTransparencyLayer() if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_pop_group_to_source(cr); cairo_paint_with_alpha(cr, m_data->layers.last()); @@ -952,7 +960,7 @@ void GraphicsContext::clearRect(const FloatRect& rect) if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_save(cr); cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height()); @@ -966,7 +974,7 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float width) if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_save(cr); cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height()); cairo_set_line_width(cr, width); @@ -991,12 +999,12 @@ void GraphicsContext::setLineCap(LineCap lineCap) cairoCap = CAIRO_LINE_CAP_SQUARE; break; } - cairo_set_line_cap(m_data->cr, cairoCap); + cairo_set_line_cap(platformContext()->cr(), cairoCap); } void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset) { - cairo_set_dash(m_data->cr, dashes.data(), dashes.size(), dashOffset); + cairo_set_dash(platformContext()->cr(), dashes.data(), dashes.size(), dashOffset); } void GraphicsContext::setLineJoin(LineJoin lineJoin) @@ -1016,7 +1024,7 @@ void GraphicsContext::setLineJoin(LineJoin lineJoin) cairoJoin = CAIRO_LINE_JOIN_BEVEL; break; } - cairo_set_line_join(m_data->cr, cairoJoin); + cairo_set_line_join(platformContext()->cr(), cairoJoin); } void GraphicsContext::setMiterLimit(float miter) @@ -1024,7 +1032,7 @@ void GraphicsContext::setMiterLimit(float miter) if (paintingDisabled()) return; - cairo_set_miter_limit(m_data->cr, miter); + cairo_set_miter_limit(platformContext()->cr(), miter); } void GraphicsContext::setAlpha(float alpha) @@ -1042,7 +1050,7 @@ void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op) if (paintingDisabled()) return; - cairo_set_operator(m_data->cr, toCairoOperator(op)); + cairo_set_operator(platformContext()->cr(), toCairoOperator(op)); } void GraphicsContext::clip(const Path& path) @@ -1050,7 +1058,7 @@ void GraphicsContext::clip(const Path& path) if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); OwnPtr<cairo_path_t> p(cairo_copy_path(path.platformPath()->context())); cairo_append_path(cr, p.get()); cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr); @@ -1070,7 +1078,7 @@ void GraphicsContext::clipOut(const Path& path) if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); double x1, y1, x2, y2; cairo_clip_extents(cr, &x1, &y1, &x2, &y2); cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1); @@ -1087,7 +1095,7 @@ void GraphicsContext::rotate(float radians) if (paintingDisabled()) return; - cairo_rotate(m_data->cr, radians); + cairo_rotate(platformContext()->cr(), radians); m_data->rotate(radians); } @@ -1096,7 +1104,7 @@ void GraphicsContext::scale(const FloatSize& size) if (paintingDisabled()) return; - cairo_scale(m_data->cr, size.width(), size.height()); + cairo_scale(platformContext()->cr(), size.width(), size.height()); m_data->scale(size); } @@ -1105,7 +1113,7 @@ void GraphicsContext::clipOut(const IntRect& r) if (paintingDisabled()) return; - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); double x1, y1, x2, y2; cairo_clip_extents(cr, &x1, &y1, &x2, &y2); cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1); @@ -1132,7 +1140,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft, if (hasShadow()) m_data->shadow.drawRectShadow(this, r, topLeft, topRight, bottomLeft, bottomRight); - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_save(cr); Path path; path.addRoundedRect(r, topLeft, topRight, bottomLeft, bottomRight); @@ -1170,7 +1178,7 @@ void GraphicsContext::setPlatformShouldAntialias(bool enable) // When true, use the default Cairo backend antialias mode (usually this // enables standard 'grayscale' antialiasing); false to explicitly disable // antialiasing. This is the same strategy as used in drawConvexPolygon(). - cairo_set_antialias(m_data->cr, enable ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE); + cairo_set_antialias(platformContext()->cr(), enable ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE); } void GraphicsContext::setImageInterpolationQuality(InterpolationQuality) @@ -1196,7 +1204,7 @@ void GraphicsContext::pushImageMask(cairo_surface_t* surface, const FloatRect& r // We want to allow the clipped elements to composite with the surface as it // is now, but they are isolated in another group. To make this work, we're // going to blit the current surface contents onto the new group once we push it. - cairo_t* cr = m_data->cr; + cairo_t* cr = platformContext()->cr(); cairo_surface_t* currentTarget = cairo_get_target(cr); cairo_surface_flush(currentTarget); diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h b/Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h index 924f69a..2bc290b 100644 --- a/Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h +++ b/Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h @@ -31,6 +31,7 @@ #include "GraphicsContext.h" #include "ContextShadow.h" +#include "PlatformContextCairo.h" #include "RefPtrCairo.h" #include <cairo.h> #include <math.h> @@ -67,8 +68,8 @@ private: class GraphicsContextPlatformPrivate { public: - GraphicsContextPlatformPrivate() - : cr(0) + GraphicsContextPlatformPrivate(PlatformContextCairo* newPlatformContext) + : platformContext(newPlatformContext) #if PLATFORM(GTK) , expose(0) #elif PLATFORM(WIN) @@ -82,7 +83,6 @@ public: ~GraphicsContextPlatformPrivate() { - cairo_destroy(cr); } #if PLATFORM(WIN) @@ -99,7 +99,7 @@ public: void setCTM(const AffineTransform&); void beginTransparencyLayer() { m_transparencyCount++; } void endTransparencyLayer() { m_transparencyCount--; } - void syncContext(PlatformGraphicsContext* cr); + void syncContext(cairo_t* cr); #else // On everything else, we do nothing. void save() {} @@ -114,12 +114,11 @@ public: void setCTM(const AffineTransform&) {} void beginTransparencyLayer() {} void endTransparencyLayer() {} - void syncContext(PlatformGraphicsContext* cr) {} + void syncContext(cairo_t* cr) {} #endif - cairo_t* cr; + PlatformContextCairo* platformContext; Vector<float> layers; - ContextShadow shadow; Vector<ContextShadow> shadowStack; Vector<ImageMaskInformation> maskImageStack; @@ -133,6 +132,23 @@ public: #endif }; +// This is a specialized private section for the Cairo GraphicsContext, which knows how +// to clean up the heap allocated PlatformContextCairo that we must use for the top-level +// GraphicsContext. +class GraphicsContextPlatformPrivateToplevel : public GraphicsContextPlatformPrivate { +public: + GraphicsContextPlatformPrivateToplevel(PlatformContextCairo* platformContext) + : GraphicsContextPlatformPrivate(platformContext) + { + } + + ~GraphicsContextPlatformPrivateToplevel() + { + delete platformContext; + } +}; + + } // namespace WebCore #endif // GraphicsContextPlatformPrivateCairo_h diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp index 9ee8a94..1d5d492 100644 --- a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp @@ -37,7 +37,9 @@ #include "MIMETypeRegistry.h" #include "NotImplemented.h" #include "Pattern.h" +#include "PlatformContextCairo.h" #include "PlatformString.h" +#include "RefPtrCairo.h" #include <cairo.h> #include <wtf/Vector.h> @@ -66,6 +68,7 @@ namespace WebCore { ImageBufferData::ImageBufferData(const IntSize& size) : m_surface(0) + , m_platformContext(0) { } @@ -80,9 +83,9 @@ ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode, bool& s if (cairo_surface_status(m_data.m_surface) != CAIRO_STATUS_SUCCESS) return; // create will notice we didn't set m_initialized and fail. - cairo_t* cr = cairo_create(m_data.m_surface); - m_context.set(new GraphicsContext(cr)); - cairo_destroy(cr); // The context is now owned by the GraphicsContext. + RefPtr<cairo_t> cr = adoptRef(cairo_create(m_data.m_surface)); + m_data.m_platformContext.setCr(cr.get()); + m_context.set(new GraphicsContext(&m_data.m_platformContext)); success = true; } @@ -301,7 +304,7 @@ static cairo_status_t writeFunction(void* closure, const unsigned char* data, un String ImageBuffer::toDataURL(const String& mimeType, const double*) const { - cairo_surface_t* image = cairo_get_target(context()->platformContext()); + cairo_surface_t* image = cairo_get_target(context()->platformContext()->cr()); if (!image) return "data:,"; diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferData.h b/Source/WebCore/platform/graphics/cairo/ImageBufferData.h index 49f15df..42867d1 100644 --- a/Source/WebCore/platform/graphics/cairo/ImageBufferData.h +++ b/Source/WebCore/platform/graphics/cairo/ImageBufferData.h @@ -26,7 +26,9 @@ #ifndef ImageBufferData_h #define ImageBufferData_h -#include "cairo.h" +#include "PlatformContextCairo.h" + +typedef struct _cairo_surface cairo_surface_t; namespace WebCore { @@ -37,6 +39,7 @@ public: ImageBufferData(const IntSize&); cairo_surface_t* m_surface; + PlatformContextCairo m_platformContext; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp index e51d65a..d3a52ce 100644 --- a/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp @@ -36,6 +36,7 @@ #include "ContextShadow.h" #include "FloatRect.h" #include "GraphicsContext.h" +#include "PlatformContextCairo.h" #include "ImageBuffer.h" #include "ImageObserver.h" #include "RefPtrCairo.h" @@ -114,7 +115,7 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo IntSize selfSize = size(); - cairo_t* cr = context->platformContext(); + cairo_t* cr = context->platformContext()->cr(); context->save(); // Set the compositing operation. @@ -169,8 +170,7 @@ void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, con if (!image) // If it's too early we won't have an image yet. return; - cairo_t* cr = context->platformContext(); - + cairo_t* cr = context->platformContext()->cr(); drawPatternToCairoContext(cr, image, size(), tileRect, patternTransform, phase, toCairoOperator(op), destRect); if (imageObserver()) diff --git a/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp b/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp index 94f6809..1594e7b 100644 --- a/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp @@ -20,7 +20,7 @@ #include "config.h" #include "OwnPtrCairo.h" -#if defined(USE_FREETYPE) +#if USE(FREETYPE) #include <cairo-ft.h> #include <fontconfig/fcfreetype.h> #endif @@ -29,7 +29,7 @@ namespace WTF { -#if defined(USE_FREETYPE) +#if USE(FREETYPE) template <> void deleteOwnedPtr<FcObjectSet>(FcObjectSet* ptr) { if (ptr) diff --git a/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h b/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h index 035d80e..e1dd370 100644 --- a/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h +++ b/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h @@ -22,7 +22,7 @@ #include "OwnPtr.h" -#if defined(USE_FREETYPE) +#if USE(FREETYPE) typedef struct _FcObjectSet FcObjectSet; typedef struct _FcFontSet FcFontSet; #endif @@ -31,7 +31,7 @@ typedef struct cairo_path cairo_path_t; namespace WTF { -#if defined(USE_FREETYPE) +#if USE(FREETYPE) template <> void deleteOwnedPtr<FcObjectSet>(FcObjectSet*); template <> void deleteOwnedPtr<FcFontSet>(FcFontSet*); #endif diff --git a/Source/WebCore/platform/graphics/cairo/PathCairo.cpp b/Source/WebCore/platform/graphics/cairo/PathCairo.cpp index 7a09a52..533df10 100644 --- a/Source/WebCore/platform/graphics/cairo/PathCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/PathCairo.cpp @@ -281,7 +281,7 @@ FloatRect Path::boundingRect() const return FloatRect(x0, y0, x1 - x0, y1 - y0); } -FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) +FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const { cairo_t* cr = platformPath()->context(); if (applier) { diff --git a/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp new file mode 100644 index 0000000..ba75162 --- /dev/null +++ b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2011 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "PlatformContextCairo.h" + +#include <cairo.h> + +namespace WebCore { + +PlatformContextCairo::PlatformContextCairo(cairo_t* cr) + : m_cr(cr) +{ +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h new file mode 100644 index 0000000..c6cceda --- /dev/null +++ b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2011 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PlatformContextCairo_h +#define PlatformContextCairo_h + +#include "ContextShadow.h" +#include "RefPtrCairo.h" + +namespace WebCore { + +// Much like PlatformContextSkia in the Skia port, this class holds information that +// would normally be private to GraphicsContext, except that we want to allow access +// to it in Font and Image code. This allows us to separate the concerns of Cairo-specific +// code from the platform-independent GraphicsContext. + +class PlatformContextCairo { + WTF_MAKE_NONCOPYABLE(PlatformContextCairo); +public: + PlatformContextCairo(cairo_t*); + cairo_t* cr() { return m_cr.get(); } + void setCr(cairo_t* cr) { m_cr = cr; } + +private: + RefPtr<cairo_t> m_cr; +}; + +} // namespace WebCore + +#endif // PlatformContextCairo_h diff --git a/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp b/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp index c8b242c..1792002 100644 --- a/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp @@ -21,7 +21,7 @@ #include <cairo.h> -#if defined(USE_FREETYPE) +#if USE(FREETYPE) #include <cairo-ft.h> #include <fontconfig/fcfreetype.h> #endif @@ -88,7 +88,7 @@ template<> void derefIfNotNull(cairo_pattern_t* ptr) cairo_pattern_destroy(ptr); } -#if defined(USE_FREETYPE) +#if USE(FREETYPE) template<> void refIfNotNull(FcPattern* ptr) { if (LIKELY(ptr != 0)) diff --git a/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h b/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h index 204d1e3..540f9dc 100644 --- a/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h +++ b/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h @@ -28,7 +28,7 @@ typedef struct _cairo_font_face cairo_font_face_t; typedef struct _cairo_scaled_font cairo_scaled_font_t; typedef struct _cairo_pattern cairo_pattern_t; -#if defined(USE_FREETYPE) +#if USE(FREETYPE) typedef struct _FcPattern FcPattern; #endif @@ -49,7 +49,7 @@ template<> void derefIfNotNull(cairo_scaled_font_t* ptr); template<> void refIfNotNull(cairo_pattern_t*); template<> void derefIfNotNull(cairo_pattern_t*); -#if defined(USE_FREETYPE) +#if USE(FREETYPE) template<> void refIfNotNull(FcPattern* ptr); template<> void derefIfNotNull(FcPattern* ptr); #endif diff --git a/Source/WebCore/platform/graphics/cg/FontPlatformData.h b/Source/WebCore/platform/graphics/cg/FontPlatformData.h deleted file mode 100644 index e21b444..0000000 --- a/Source/WebCore/platform/graphics/cg/FontPlatformData.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * This file is part of the internal font implementation. It should not be included by anyone other than - * FontMac.cpp, FontWin.cpp and Font.cpp. - * - * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef FontPlatformData_h -#define FontPlatformData_h - -#include "FontOrientation.h" -#include "RefCountedGDIHandle.h" -#include "StringImpl.h" -#include <wtf/Forward.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/RetainPtr.h> - -typedef struct HFONT__* HFONT; -typedef struct CGFont* CGFontRef; - -namespace WebCore { - -class FontDescription; - -class FontPlatformData { -public: - FontPlatformData() - : m_size(0) - , m_syntheticBold(false) - , m_syntheticOblique(false) - , m_useGDI(false) - { - } - - FontPlatformData(HFONT, float size, bool bold, bool oblique, bool useGDI); - FontPlatformData(float size, bool bold, bool oblique); - - FontPlatformData(HFONT, CGFontRef, float size, bool bold, bool oblique, bool useGDI); - ~FontPlatformData(); - - FontPlatformData(WTF::HashTableDeletedValueType) : m_font(WTF::HashTableDeletedValue) { } - bool isHashTableDeletedValue() const { return m_font.isHashTableDeletedValue(); } - - HFONT hfont() const { return m_font->handle(); } - CGFontRef cgFont() const { return m_cgFont.get(); } - - float size() const { return m_size; } - void setSize(float size) { m_size = size; } - bool syntheticBold() const { return m_syntheticBold; } - bool syntheticOblique() const { return m_syntheticOblique; } - bool useGDI() const { return m_useGDI; } - - FontOrientation orientation() const { return Horizontal; } // FIXME: Implement. - - unsigned hash() const - { - return m_font->hash(); - } - - bool operator==(const FontPlatformData& other) const - { - return m_font == other.m_font - && m_cgFont == other.m_cgFont - && m_size == other.m_size - && m_syntheticBold == other.m_syntheticBold - && m_syntheticOblique == other.m_syntheticOblique - && m_useGDI == other.m_useGDI; - } - -#ifndef NDEBUG - String description() const; -#endif - -private: - void platformDataInit(HFONT, float size, HDC, WCHAR* faceName); - - RefPtr<RefCountedGDIHandle<HFONT> > m_font; - RetainPtr<CGFontRef> m_cgFont; - - float m_size; - bool m_syntheticBold; - bool m_syntheticOblique; - bool m_useGDI; -}; - -} // namespace WebCore - -#endif diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp index dbcab45..7799137 100644 --- a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp +++ b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp @@ -695,7 +695,7 @@ void GraphicsContext::fillRect(const FloatRect& rect) if (m_state.fillPattern) applyFillPattern(); - bool drawOwnShadow = hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet. + bool drawOwnShadow = !isAcceleratedContext() && hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet. if (drawOwnShadow) { float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur; // Turn off CG shadows. @@ -724,7 +724,7 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS if (oldFillColor != color || oldColorSpace != colorSpace) setCGFillColor(context, color, colorSpace); - bool drawOwnShadow = hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet. + bool drawOwnShadow = !isAcceleratedContext() && hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet. if (drawOwnShadow) { float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur; // Turn off CG shadows. @@ -759,7 +759,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef Path path; path.addRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight); - bool drawOwnShadow = hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet. + bool drawOwnShadow = !isAcceleratedContext() && hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet. if (drawOwnShadow) { float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur; @@ -803,7 +803,7 @@ void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const Rounded setFillColor(color, colorSpace); // fillRectWithRoundedHole() assumes that the edges of rect are clipped out, so we only care about shadows cast around inside the hole. - bool drawOwnShadow = hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; + bool drawOwnShadow = !isAcceleratedContext() && hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; if (drawOwnShadow) { float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur; @@ -929,8 +929,7 @@ void GraphicsContext::setPlatformShadow(const FloatSize& offset, float blur, con CGFloat smallEigenvalue = narrowPrecisionToCGFloat(sqrt(0.5 * ((A + D) - sqrt(4 * B * C + (A - D) * (A - D))))); - // Extreme "blur" values can make text drawing crash or take crazy long times, so clamp - blurRadius = min(blur * smallEigenvalue, narrowPrecisionToCGFloat(1000.0)); + blurRadius = blur * smallEigenvalue; CGSize offsetInBaseSpace = CGSizeApplyAffineTransform(offset, userToBaseCTM); @@ -938,6 +937,9 @@ void GraphicsContext::setPlatformShadow(const FloatSize& offset, float blur, con yOffset = offsetInBaseSpace.height; } + // Extreme "blur" values can make text drawing crash or take crazy long times, so clamp + blurRadius = min(blurRadius, narrowPrecisionToCGFloat(1000.0)); + // Work around <rdar://problem/5539388> by ensuring that the offsets will get truncated // to the desired integer. static const CGFloat extraShadowOffset = narrowPrecisionToCGFloat(1.0 / 128); @@ -1343,14 +1345,30 @@ void GraphicsContext::setAllowsFontSmoothing(bool allowsFontSmoothing) #endif } -void GraphicsContext::setIsCALayerContext(bool) +void GraphicsContext::setIsCALayerContext(bool isLayerContext) { - m_data->m_isCALayerContext = true; + if (isLayerContext) + m_data->m_contextFlags |= IsLayerCGContext; + else + m_data->m_contextFlags &= ~IsLayerCGContext; } bool GraphicsContext::isCALayerContext() const { - return m_data->m_isCALayerContext; + return m_data->m_contextFlags & IsLayerCGContext; +} + +void GraphicsContext::setIsAcceleratedContext(bool isAccelerated) +{ + if (isAccelerated) + m_data->m_contextFlags |= IsAcceleratedCGContext; + else + m_data->m_contextFlags &= ~IsAcceleratedCGContext; +} + +bool GraphicsContext::isAcceleratedContext() const +{ + return m_data->m_contextFlags & IsAcceleratedCGContext; } void GraphicsContext::setPlatformTextDrawingMode(TextDrawingModeFlags mode) diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h b/Source/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h index f9255df..722f5a0 100644 --- a/Source/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h +++ b/Source/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h @@ -31,9 +31,16 @@ namespace WebCore { +enum GraphicsContextCGFlag { + IsLayerCGContext = 1 << 0, + IsAcceleratedCGContext = 1 << 1 +}; + +typedef unsigned GraphicsContextCGFlags; + class GraphicsContextPlatformPrivate { public: - GraphicsContextPlatformPrivate(CGContextRef cgContext, bool isLayerContext = false) + GraphicsContextPlatformPrivate(CGContextRef cgContext, GraphicsContextCGFlags flags = 0) : m_cgContext(cgContext) #if PLATFORM(WIN) , m_hdc(0) @@ -41,7 +48,7 @@ public: , m_shouldIncludeChildWindows(false) #endif , m_userToDeviceTransformKnownToBeIdentity(false) - , m_isCALayerContext(isLayerContext) + , m_contextFlags(flags) { } @@ -87,7 +94,7 @@ public: RetainPtr<CGContextRef> m_cgContext; bool m_userToDeviceTransformKnownToBeIdentity; - bool m_isCALayerContext; + GraphicsContextCGFlags m_contextFlags; }; } diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp index 7c8e313..3c8f959 100644 --- a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp +++ b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp @@ -32,6 +32,7 @@ #include "BitmapImage.h" #include "GraphicsContext.h" #include "GraphicsContextCG.h" +#include "ImageData.h" #include "MIMETypeRegistry.h" #include <ApplicationServices/ApplicationServices.h> #include <wtf/Assertions.h> @@ -498,21 +499,8 @@ static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType) #endif } -String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const +static String CGImageToDataURL(CGImageRef image, const String& mimeType, const double* quality) { - ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); - - RetainPtr<CGImageRef> image; - if (!m_accelerateRendering) - image.adoptCF(CGBitmapContextCreateImage(context()->platformContext())); -#if USE(IOSURFACE_CANVAS_BACKING_STORE) - else - image.adoptCF(wkIOSurfaceContextCreateImage(context()->platformContext())); -#endif - - if (!image) - return "data:,"; - RetainPtr<CFMutableDataRef> data(AdoptCF, CFDataCreateMutable(kCFAllocatorDefault, 0)); if (!data) return "data:,"; @@ -533,7 +521,7 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con imageProperties.adoptCF(CFDictionaryCreate(0, &key, &value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); } - CGImageDestinationAddImage(destination.get(), image.get(), imageProperties.get()); + CGImageDestinationAddImage(destination.get(), image, imageProperties.get()); CGImageDestinationFinalize(destination.get()); Vector<char> out; @@ -541,4 +529,46 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con return makeString("data:", mimeType, ";base64,", out); } + +String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const +{ + ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); + + RetainPtr<CGImageRef> image; + if (!m_accelerateRendering) + image.adoptCF(CGBitmapContextCreateImage(context()->platformContext())); +#if USE(IOSURFACE_CANVAS_BACKING_STORE) + else + image.adoptCF(wkIOSurfaceContextCreateImage(context()->platformContext())); +#endif + + if (!image) + return "data:,"; + + return CGImageToDataURL(image.get(), mimeType, quality); +} + +String ImageDataToDataURL(const ImageData& source, const String& mimeType, const double* quality) +{ + ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); + + RetainPtr<CGImageRef> image; + RetainPtr<CGDataProviderRef> dataProvider; + + dataProvider.adoptCF(CGDataProviderCreateWithData(0, source.data()->data()->data(), + 4 * source.width() * source.height(), 0)); + + if (!dataProvider) + return "data:,"; + + image.adoptCF(CGImageCreate(source.width(), source.height(), 8, 32, 4 * source.width(), + CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrderDefault | kCGImageAlphaLast, + dataProvider.get(), 0, false, kCGRenderingIntentDefault)); + + + if (!image) + return "data:,"; + + return CGImageToDataURL(image.get(), mimeType, quality); +} } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/cg/PathCG.cpp b/Source/WebCore/platform/graphics/cg/PathCG.cpp index d6a1e6e..b8fc7d4 100644 --- a/Source/WebCore/platform/graphics/cg/PathCG.cpp +++ b/Source/WebCore/platform/graphics/cg/PathCG.cpp @@ -166,7 +166,7 @@ FloatRect Path::boundingRect() const return CGPathGetBoundingBox(m_path); } -FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) +FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const { CGContextRef context = scratchContext(); diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp index ad961aa..4cb119a 100644 --- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp @@ -56,7 +56,7 @@ Canvas2DLayerChromium::~Canvas2DLayerChromium() layerRendererContext()->deleteTexture(m_textureId); } -void Canvas2DLayerChromium::updateContentsIfDirty() +void Canvas2DLayerChromium::updateCompositorResources() { if (!m_contentsDirty || !m_drawingBuffer) return; diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h index a14cb98..81b118c 100644 --- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h @@ -46,7 +46,7 @@ public: static PassRefPtr<Canvas2DLayerChromium> create(DrawingBuffer*, GraphicsLayerChromium* owner); virtual ~Canvas2DLayerChromium(); virtual bool drawsContent() const { return true; } - virtual void updateContentsIfDirty(); + virtual void updateCompositorResources(); void setTextureChanged(); unsigned textureId() const; @@ -55,8 +55,6 @@ public: private: explicit Canvas2DLayerChromium(DrawingBuffer*, GraphicsLayerChromium* owner); DrawingBuffer* m_drawingBuffer; - - static unsigned m_shaderProgramId; }; } diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp index 0264868..f306207 100644 --- a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp @@ -40,8 +40,6 @@ namespace WebCore { -unsigned CanvasLayerChromium::m_shaderProgramId = 0; - CanvasLayerChromium::CanvasLayerChromium(GraphicsLayerChromium* owner) : LayerChromium(owner) , m_textureChanged(true) @@ -54,22 +52,18 @@ CanvasLayerChromium::~CanvasLayerChromium() { } -void CanvasLayerChromium::draw() +PassRefPtr<CCLayerImpl> CanvasLayerChromium::createCCLayerImpl() { - ASSERT(layerRenderer()); - const CanvasLayerChromium::Program* program = layerRenderer()->canvasLayerProgram(); - ASSERT(program && program->initialized()); - GraphicsContext3D* context = layerRendererContext(); - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId)); - GC3Denum sfactor = m_premultipliedAlpha ? GraphicsContext3D::ONE : GraphicsContext3D::SRC_ALPHA; - GLC(context, context->blendFunc(sfactor, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); - layerRenderer()->useShader(program->program()); - GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); - drawTexturedQuad(context, layerRenderer()->projectionMatrix(), ccLayerImpl()->drawTransform(), - bounds().width(), bounds().height(), ccLayerImpl()->drawOpacity(), - program->vertexShader().matrixLocation(), - program->fragmentShader().alphaLocation()); + return CCCanvasLayerImpl::create(this); +} + +void CanvasLayerChromium::pushPropertiesTo(CCLayerImpl* layer) +{ + LayerChromium::pushPropertiesTo(layer); + + CCCanvasLayerImpl* canvasLayer = static_cast<CCCanvasLayerImpl*>(layer); + canvasLayer->setTextureId(m_textureId); + canvasLayer->setPremultipliedAlpha(m_premultipliedAlpha); } } diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h index ed3a06f..cb2ccc9 100644 --- a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h @@ -43,9 +43,9 @@ class CanvasLayerChromium : public LayerChromium { public: virtual ~CanvasLayerChromium(); - virtual void draw(); + virtual PassRefPtr<CCLayerImpl> createCCLayerImpl(); - typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program; + virtual void pushPropertiesTo(CCLayerImpl*); protected: explicit CanvasLayerChromium(GraphicsLayerChromium* owner); @@ -55,9 +55,6 @@ protected: bool m_textureChanged; unsigned m_textureId; bool m_premultipliedAlpha; - -private: - static unsigned m_shaderProgramId; }; } diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp index 78f93d5..4ea9c92 100644 --- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp @@ -66,7 +66,7 @@ void ContentLayerChromium::cleanupResources() m_contentsTexture.clear(); } -bool ContentLayerChromium::requiresClippedUpdateRect() const +bool ContentLayerChromium::requiresClippedUpdateRect() { // To avoid allocating excessively large textures, switch into "large layer mode" if // one of the layer's dimensions is larger than 2000 pixels or the size of @@ -77,7 +77,7 @@ bool ContentLayerChromium::requiresClippedUpdateRect() const || !layerRenderer()->checkTextureSize(bounds())); } -void ContentLayerChromium::updateContentsIfDirty() +void ContentLayerChromium::paintContentsIfDirty() { RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client()); if (!backing || backing->paintingGoesToWindow()) @@ -93,34 +93,25 @@ void ContentLayerChromium::updateContentsIfDirty() // FIXME: Remove this test when tiled layers are implemented. if (requiresClippedUpdateRect()) { - // A layer with 3D transforms could require an arbitrarily large number - // of texels to be repainted, so ignore these layers until tiling is - // implemented. - if (!ccLayerImpl()->drawTransform().isIdentityOrTranslation()) { - m_skipsDraw = true; - return; - } - // Calculate the region of this layer that is currently visible. const IntRect clipRect = ccLayerImpl()->targetRenderSurface()->contentRect(); TransformationMatrix layerOriginTransform = ccLayerImpl()->drawTransform(); layerOriginTransform.translate3d(-0.5 * bounds().width(), -0.5 * bounds().height(), 0); - // For now we apply the large layer treatment only for layers that are either untransformed - // or are purely translated. Their matrix is expected to be invertible. - ASSERT(layerOriginTransform.isInvertible()); - + // We compute the visible portion of the layer by back-mapping the current RenderSurface + // content area to the layer. To do that, we invert the drawing matrix of the layer + // and project the content area rectangle to it. If the layer transform is not invertible + // then we skip rendering the layer. + if (!layerOriginTransform.isInvertible()) { + m_skipsDraw = true; + return; + } TransformationMatrix targetToLayerMatrix = layerOriginTransform.inverse(); - IntRect visibleRectInLayerCoords = targetToLayerMatrix.mapRect(clipRect); + FloatQuad mappedClipToLayer = targetToLayerMatrix.projectQuad(FloatRect(clipRect)); + IntRect visibleRectInLayerCoords = mappedClipToLayer.enclosingBoundingBox(); visibleRectInLayerCoords.intersect(IntRect(0, 0, bounds().width(), bounds().height())); - // For normal layers, the center of the texture corresponds with the center of the layer. - // In large layers the center of the texture is the center of the visible region so we have - // to keep track of the offset in order to render correctly. - IntRect visibleRectInSurfaceCoords = layerOriginTransform.mapRect(visibleRectInLayerCoords); - m_layerCenterInSurfaceCoords = FloatRect(visibleRectInSurfaceCoords).center(); - // If this is still too large to render, then skip the layer completely. if (!layerRenderer()->checkTextureSize(visibleRectInLayerCoords.size())) { m_skipsDraw = true; @@ -256,9 +247,14 @@ void ContentLayerChromium::draw() GLC(context, context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); if (requiresClippedUpdateRect()) { - float m43 = ccLayerImpl()->drawTransform().m43(); - TransformationMatrix transform; - transform.translate3d(m_layerCenterInSurfaceCoords.x(), m_layerCenterInSurfaceCoords.y(), m43); + // Compute the offset between the layer's center point and the center of the visible portion + // of the layer. + FloatPoint visibleRectCenterOffset = FloatRect(m_visibleRectInLayerCoords).center(); + visibleRectCenterOffset.move(-0.5 * bounds().width(), -0.5 * bounds().height()); + + TransformationMatrix transform = ccLayerImpl()->drawTransform(); + transform.translate(visibleRectCenterOffset.x(), visibleRectCenterOffset.y()); + drawTexturedQuad(context, layerRenderer()->projectionMatrix(), transform, m_visibleRectInLayerCoords.width(), m_visibleRectInLayerCoords.height(), ccLayerImpl()->drawOpacity(), @@ -273,6 +269,11 @@ void ContentLayerChromium::draw() unreserveContentsTexture(); } +void ContentLayerChromium::updateCompositorResources() +{ + updateTextureIfNeeded(); +} + void ContentLayerChromium::unreserveContentsTexture() { if (!m_skipsDraw && m_contentsTexture) @@ -281,8 +282,6 @@ void ContentLayerChromium::unreserveContentsTexture() void ContentLayerChromium::bindContentsTexture() { - updateTextureIfNeeded(); - if (!m_skipsDraw && m_contentsTexture) m_contentsTexture->bindTexture(); } diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h index 6f070c2..cf296ab 100644 --- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h @@ -50,7 +50,8 @@ public: virtual ~ContentLayerChromium(); - virtual void updateContentsIfDirty(); + virtual void paintContentsIfDirty(); + virtual void updateCompositorResources(); virtual void unreserveContentsTexture(); virtual void bindContentsTexture(); @@ -63,7 +64,7 @@ protected: explicit ContentLayerChromium(GraphicsLayerChromium* owner); virtual void cleanupResources(); - bool requiresClippedUpdateRect() const; + bool requiresClippedUpdateRect(); void resizeUploadBuffer(const IntSize&); virtual const char* layerTypeAsString() const { return "ContentLayer"; } @@ -82,7 +83,6 @@ private: PlatformCanvas m_canvas; IntRect m_visibleRectInLayerCoords; - FloatPoint m_layerCenterInSurfaceCoords; }; } diff --git a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm index 227fbe4..b442d53 100644 --- a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm +++ b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm @@ -29,7 +29,7 @@ #import "config.h" #import "CrossProcessFontLoading.h" -#import "../graphics/cocoa/FontPlatformData.h" +#import "../graphics/FontPlatformData.h" #import "PlatformBridge.h" #import <AppKit/NSFont.h> #import <wtf/HashMap.h> diff --git a/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp index d956841..e559edb 100644 --- a/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp @@ -46,10 +46,6 @@ namespace WebCore { -#if ENABLE(SKIA_GPU) -extern GrContext* GetGlobalGrContext(); -#endif - struct DrawingBufferInternal { unsigned offscreenColorTexture; #if USE(ACCELERATED_COMPOSITING) @@ -91,6 +87,9 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context, , m_multisampleFBO(0) , m_multisampleColorBuffer(0) , m_internal(new DrawingBufferInternal) +#if ENABLE(SKIA_GPU) + , m_grContext(0) +#endif { if (!m_context->getExtensions()->supports("GL_CHROMIUM_copy_texture_to_parent_texture")) { m_context.clear(); @@ -137,7 +136,8 @@ void DrawingBuffer::publishToPlatformLayer() // would insert a fence into the child command stream that the compositor could wait for. m_context->makeContextCurrent(); #if ENABLE(SKIA_GPU) - GetGlobalGrContext()->flush(false); + if (m_grContext) + m_grContext->flush(0); #endif static_cast<Extensions3DChromium*>(m_context->getExtensions())->copyTextureToParentTextureCHROMIUM(m_colorBuffer, parentTexture); m_context->flush(); @@ -166,4 +166,13 @@ Platform3DObject DrawingBuffer::platformColorBuffer() const return m_colorBuffer; } +#if ENABLE(SKIA_GPU) +void DrawingBuffer::setGrContext(GrContext* context) +{ + // We just take a ptr without referencing it, as we require that we never outlive + // the SharedGraphicsContext3D object that is giving us the context. + m_grContext = context; +} +#endif + } diff --git a/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp index bbe6d62..598ae86 100644 --- a/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp @@ -153,7 +153,8 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD fontDescription.computedSize(), (style & SkTypeface::kBold) && !tf->isBold(), (style & SkTypeface::kItalic) && !tf->isItalic(), - fontDescription.orientation()); + fontDescription.orientation(), + fontDescription.textOrientation()); tf->unref(); return result; } diff --git a/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp index e57a84c..3c254dc 100644 --- a/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp @@ -196,7 +196,7 @@ class TransparencyAwareGlyphPainter : public TransparencyAwareFontPainter { // left of m_point. We express it this way so that if we're using the Skia // drawing path we can use floating-point positioning, even though we have // to use integer positioning in the GDI path. - bool drawGlyphs(int numGlyphs, const WORD* glyphs, const int* advances, int startAdvance) const; + bool drawGlyphs(int numGlyphs, const WORD* glyphs, const int* advances, float startAdvance) const; private: virtual IntRect estimateTextBounds(); @@ -256,11 +256,11 @@ IntRect TransparencyAwareGlyphPainter::estimateTextBounds() bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs, const WORD* glyphs, const int* advances, - int startAdvance) const + float startAdvance) const { if (!m_useGDI) { SkPoint origin = m_point; - origin.fX += startAdvance; + origin.fX += SkFloatToScalar(startAdvance); return paintSkiaText(m_graphicsContext, m_font->platformData().hfont(), numGlyphs, glyphs, advances, 0, &origin); } @@ -400,17 +400,25 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, Vector<WORD, kMaxBufferLength> glyphs; Vector<int, kMaxBufferLength> advances; int glyphIndex = 0; // The starting glyph of the current chunk. - int curAdvance = 0; // How far from the left the current chunk is. + + // In order to round all offsets to the correct pixel boundary, this code keeps track of the absolute position + // of each glyph in floating point units and rounds to integer advances at the last possible moment. + + float horizontalOffset = point.x(); // The floating point offset of the left side of the current glyph. + int lastHorizontalOffsetRounded = lroundf(horizontalOffset); // The rounded offset of the left side of the last glyph rendered. while (glyphIndex < numGlyphs) { // How many chars will be in this chunk? int curLen = std::min(kMaxBufferLength, numGlyphs - glyphIndex); glyphs.resize(curLen); advances.resize(curLen); - int curWidth = 0; + float currentWidth = 0; for (int i = 0; i < curLen; ++i, ++glyphIndex) { glyphs[i] = glyphBuffer.glyphAt(from + glyphIndex); - advances[i] = static_cast<int>(glyphBuffer.advanceAt(from + glyphIndex)); + horizontalOffset += glyphBuffer.advanceAt(from + glyphIndex); + advances[i] = lroundf(horizontalOffset) - lastHorizontalOffsetRounded; + lastHorizontalOffsetRounded += advances[i]; + currentWidth += glyphBuffer.advanceAt(from + glyphIndex); // Bug 26088 - very large positive or negative runs can fail to // render so we clamp the size here. In the specs, negative @@ -420,15 +428,14 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, // -32830, so we give ourselves a little breathing room. const int maxNegativeRun = -32768; const int maxPositiveRun = 32768; - if ((curWidth + advances[i] < maxNegativeRun) || (curWidth + advances[i] > maxPositiveRun)) + if ((currentWidth + advances[i] < maxNegativeRun) || (currentWidth + advances[i] > maxPositiveRun)) advances[i] = 0; - curWidth += advances[i]; } // Actually draw the glyphs (with retry on failure). bool success = false; for (int executions = 0; executions < 2; ++executions) { - success = painter.drawGlyphs(curLen, &glyphs[0], &advances[0], curAdvance); + success = painter.drawGlyphs(curLen, &glyphs[0], &advances[0], horizontalOffset - point.x() - currentWidth); if (!success && executions == 0) { // Ask the browser to load the font for us and retry. PlatformBridge::ensureFontLoaded(font->platformData().hfont()); @@ -439,8 +446,6 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, if (!success) LOG_ERROR("Unable to draw the glyphs after second attempt"); - - curAdvance += curWidth; } } @@ -509,8 +514,7 @@ void Font::drawComplexText(GraphicsContext* graphicsContext, // Uniscribe counts the coordinates from the upper left, while WebKit uses // the baseline, so we have to subtract off the ascent. - state.draw(graphicsContext, hdc, static_cast<int>(point.x()), - static_cast<int>(point.y() - fontMetrics().ascent()), from, to); + state.draw(graphicsContext, hdc, lroundf(point.x()), lroundf(point.y() - fontMetrics().ascent()), from, to); context->canvas()->endPlatformPaint(); } diff --git a/Source/WebCore/platform/graphics/chromium/FontLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontLinux.cpp index 823dbc9..3c4a494 100644 --- a/Source/WebCore/platform/graphics/chromium/FontLinux.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontLinux.cpp @@ -98,7 +98,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, SkPoint* vPosBegin = storage2.get(); SkPoint* vPosEnd = storage3.get(); - bool isVertical = font->orientation() == Vertical; + bool isVertical = font->platformData().orientation() == Vertical; for (int i = 0; i < numGlyphs; i++) { SkScalar myWidth = SkFloatToScalar(adv[i].width()); pos[i].set(x, y); diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h b/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h index b6ebb2e..84edebc 100644 --- a/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h +++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h @@ -71,6 +71,7 @@ public: float size() const { return m_size; } FontOrientation orientation() const { return Horizontal; } // FIXME: Implement. + void setOrientation(FontOrientation) { } // FIXME: Implement. unsigned hash() const { @@ -105,7 +106,7 @@ private: HFONT hfont() const { return m_hfont; } unsigned hash() const { - return WTF::StringHasher::createBlobHash<sizeof(HFONT)>(&m_hfont); + return StringHasher::hashMemory<sizeof(HFONT)>(&m_hfont); } bool operator==(const RefCountedHFONT& other) const diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp index 6f9009f..c3edfac 100644 --- a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp @@ -76,13 +76,14 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src) , m_fakeBold(src.m_fakeBold) , m_fakeItalic(src.m_fakeItalic) , m_orientation(src.m_orientation) + , m_textOrientation(src.m_textOrientation) , m_style(src.m_style) , m_harfbuzzFace(src.m_harfbuzzFace) { SkSafeRef(m_typeface); } -FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation) +FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation, TextOrientation textOrientation) : m_typeface(tf) , m_family(family) , m_textSize(textSize) @@ -90,6 +91,7 @@ FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float tex , m_fakeBold(fakeBold) , m_fakeItalic(fakeItalic) , m_orientation(orientation) + , m_textOrientation(textOrientation) { SkSafeRef(m_typeface); querySystemForRenderStyle(); @@ -102,6 +104,8 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize) , m_emSizeInFontUnits(src.m_emSizeInFontUnits) , m_fakeBold(src.m_fakeBold) , m_fakeItalic(src.m_fakeItalic) + , m_orientation(src.m_orientation) + , m_textOrientation(src.m_textOrientation) , m_harfbuzzFace(src.m_harfbuzzFace) { SkSafeRef(m_typeface); @@ -134,6 +138,7 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src) m_fakeItalic = src.m_fakeItalic; m_harfbuzzFace = src.m_harfbuzzFace; m_orientation = src.m_orientation; + m_textOrientation = src.m_textOrientation; m_style = src.m_style; m_emSizeInFontUnits = src.m_emSizeInFontUnits; @@ -199,13 +204,14 @@ bool FontPlatformData::operator==(const FontPlatformData& a) const && m_fakeBold == a.m_fakeBold && m_fakeItalic == a.m_fakeItalic && m_orientation == a.m_orientation + && m_textOrientation == a.m_textOrientation && m_style == a.m_style; } unsigned FontPlatformData::hash() const { unsigned h = SkTypeface::UniqueID(m_typeface); - h ^= 0x01010101 * ((static_cast<int>(m_orientation) << 2) | (static_cast<int>(m_fakeBold) << 1) | static_cast<int>(m_fakeItalic)); + h ^= 0x01010101 * ((static_cast<int>(m_textOrientation) << 3) | (static_cast<int>(m_orientation) << 2) | (static_cast<int>(m_fakeBold) << 1) | static_cast<int>(m_fakeItalic)); // This memcpy is to avoid a reinterpret_cast that breaks strict-aliasing // rules. Memcpy is generally optimized enough so that performance doesn't diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h index d9ebb61..541aa86 100644 --- a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h +++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h @@ -33,6 +33,7 @@ #include "FontOrientation.h" #include "FontRenderStyle.h" +#include "TextOrientation.h" #include <wtf/Forward.h> #include <wtf/RefPtr.h> #include <wtf/text/CString.h> @@ -66,6 +67,8 @@ public: , m_emSizeInFontUnits(0) , m_fakeBold(false) , m_fakeItalic(false) + , m_orientation(Horizontal) + , m_textOrientation(TextOrientationVerticalRight) { } FontPlatformData() @@ -75,6 +78,7 @@ public: , m_fakeBold(false) , m_fakeItalic(false) , m_orientation(Horizontal) + , m_textOrientation(TextOrientationVerticalRight) { } FontPlatformData(float textSize, bool fakeBold, bool fakeItalic) @@ -84,10 +88,11 @@ public: , m_fakeBold(fakeBold) , m_fakeItalic(fakeItalic) , m_orientation(Horizontal) + , m_textOrientation(TextOrientationVerticalRight) { } FontPlatformData(const FontPlatformData&); - FontPlatformData(SkTypeface*, const char* name, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation = Horizontal); + FontPlatformData(SkTypeface*, const char* name, float textSize, bool fakeBold, bool fakeItalic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight); FontPlatformData(const FontPlatformData& src, float textSize); ~FontPlatformData(); @@ -113,7 +118,8 @@ public: int emSizeInFontUnits() const; FontOrientation orientation() const { return m_orientation; } - + void setOrientation(FontOrientation orientation) { m_orientation = orientation; } + bool operator==(const FontPlatformData&) const; FontPlatformData& operator=(const FontPlatformData&); bool isHashTableDeletedValue() const { return m_typeface == hashTableDeletedFontValue(); } @@ -161,6 +167,7 @@ private: bool m_fakeBold; bool m_fakeItalic; FontOrientation m_orientation; + TextOrientation m_textOrientation; FontRenderStyle m_style; mutable RefPtr<RefCountedHarfbuzzFace> m_harfbuzzFace; diff --git a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp index 2ff6b8b..cc5a060 100644 --- a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp +++ b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp @@ -62,29 +62,51 @@ typedef void (GLAPIENTRY *TESSCB)(); typedef WTF::Vector<float> FloatVector; typedef WTF::Vector<double> DoubleVector; +struct PathAndTransform { + PathAndTransform(const Path& p, const AffineTransform& t) + : path(p) + , transform(t) + { + } + Path path; + AffineTransform transform; +}; + struct GLES2Canvas::State { State() : m_fillColor(0, 0, 0, 255) + , m_shadowColor(0, 0, 0, 0) , m_alpha(1.0f) , m_compositeOp(CompositeSourceOver) - , m_clippingEnabled(false) + , m_numClippingPaths(0) + , m_shadowOffset(0, 0) + , m_shadowBlur(0) + , m_shadowsIgnoreTransforms(false) { } State(const State& other) : m_fillColor(other.m_fillColor) + , m_shadowColor(other.m_shadowColor) , m_alpha(other.m_alpha) , m_compositeOp(other.m_compositeOp) , m_ctm(other.m_ctm) , m_clippingPaths() // Don't copy; clipping paths are tracked per-state. - , m_clippingEnabled(other.m_clippingEnabled) + , m_numClippingPaths(other.m_numClippingPaths) + , m_shadowOffset(other.m_shadowOffset) + , m_shadowBlur(other.m_shadowBlur) + , m_shadowsIgnoreTransforms(other.m_shadowsIgnoreTransforms) { } Color m_fillColor; + Color m_shadowColor; float m_alpha; CompositeOperator m_compositeOp; AffineTransform m_ctm; - WTF::Vector<Path> m_clippingPaths; - bool m_clippingEnabled; + WTF::Vector<PathAndTransform> m_clippingPaths; + int m_numClippingPaths; + FloatSize m_shadowOffset; + float m_shadowBlur; + bool m_shadowsIgnoreTransforms; // Helper function for applying the state's alpha value to the given input // color to produce a new output color. The logic is the same as @@ -100,7 +122,11 @@ struct GLES2Canvas::State { int a = (c.alpha() * s) >> 8; return Color(c.red(), c.green(), c.blue(), a); } - + bool shadowActive() const + { + return m_shadowColor.alpha() > 0 && (m_shadowBlur || m_shadowOffset.width() || m_shadowOffset.height()); + } + bool clippingEnabled() { return m_numClippingPaths > 0; } }; static inline FloatPoint operator*(const FloatPoint& f, float scale) @@ -193,12 +219,8 @@ void GLES2Canvas::bindFramebuffer() void GLES2Canvas::clearRect(const FloatRect& rect) { bindFramebuffer(); - if (m_state->m_ctm.isIdentity() && !m_state->m_clippingEnabled) { - m_context->scissor(rect.x(), m_size.height() - rect.height() - rect.y(), rect.width(), rect.height()); - m_context->enable(GraphicsContext3D::SCISSOR_TEST); - m_context->clearColor(Color(RGBA32(0))); - m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); - m_context->disable(GraphicsContext3D::SCISSOR_TEST); + if (m_state->m_ctm.isIdentity() && !m_state->clippingEnabled()) { + scissorClear(rect.x(), rect.y(), rect.width(), rect.height()); } else { save(); setCompositeOperation(CompositeClear); @@ -207,35 +229,66 @@ void GLES2Canvas::clearRect(const FloatRect& rect) } } +void GLES2Canvas::scissorClear(float x, float y, float width, float height) +{ + int intX = static_cast<int>(x + 0.5f); + int intY = static_cast<int>(y + 0.5f); + int intWidth = static_cast<int>(x + width + 0.5f) - intX; + int intHeight = static_cast<int>(y + height + 0.5f) - intY; + m_context->scissor(intX, m_size.height() - intHeight - intY, intWidth, intHeight); + m_context->enable(GraphicsContext3D::SCISSOR_TEST); + m_context->clearColor(Color(RGBA32(0))); + m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); + m_context->disable(GraphicsContext3D::SCISSOR_TEST); +} + void GLES2Canvas::fillPath(const Path& path) { + if (m_state->shadowActive()) { + beginShadowDraw(); + fillPathInternal(path, m_state->m_shadowColor); + endShadowDraw(path.boundingRect()); + } + + bindFramebuffer(); m_context->applyCompositeOperator(m_state->m_compositeOp); - applyClipping(m_state->m_clippingEnabled); - fillPath(path, m_state->applyAlpha(m_state->m_fillColor)); + applyClipping(m_state->clippingEnabled()); + + fillPathInternal(path, m_state->applyAlpha(m_state->m_fillColor)); } void GLES2Canvas::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) { + if (m_state->shadowActive()) { + beginShadowDraw(); + fillRectInternal(rect, m_state->m_shadowColor); + endShadowDraw(rect); + } + + bindFramebuffer(); m_context->applyCompositeOperator(m_state->m_compositeOp); - applyClipping(m_state->m_clippingEnabled); - m_context->useQuadVertices(); + applyClipping(m_state->clippingEnabled()); + + fillRectInternal(rect, color); +} + +void GLES2Canvas::fillRect(const FloatRect& rect) +{ + fillRect(rect, m_state->applyAlpha(m_state->m_fillColor), ColorSpaceDeviceRGB); +} +void GLES2Canvas::fillRectInternal(const FloatRect& rect, const Color& color) +{ AffineTransform matrix(m_flipMatrix); matrix *= m_state->m_ctm; matrix.translate(rect.x(), rect.y()); matrix.scale(rect.width(), rect.height()); + m_context->useQuadVertices(); m_context->useFillSolidProgram(matrix, color); - - bindFramebuffer(); m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4); } -void GLES2Canvas::fillRect(const FloatRect& rect) -{ - fillRect(rect, m_state->applyAlpha(m_state->m_fillColor), ColorSpaceDeviceRGB); -} - void GLES2Canvas::setFillColor(const Color& color, ColorSpace colorSpace) { m_state->m_fillColor = color; @@ -246,6 +299,26 @@ void GLES2Canvas::setAlpha(float alpha) m_state->m_alpha = alpha; } +void GLES2Canvas::setShadowColor(const Color& color, ColorSpace) +{ + m_state->m_shadowColor = color; +} + +void GLES2Canvas::setShadowOffset(const FloatSize& offset) +{ + m_state->m_shadowOffset = offset; +} + +void GLES2Canvas::setShadowBlur(float shadowBlur) +{ + m_state->m_shadowBlur = shadowBlur; +} + +void GLES2Canvas::setShadowsIgnoreTransforms(bool shadowsIgnoreTransforms) +{ + m_state->m_shadowsIgnoreTransforms = shadowsIgnoreTransforms; +} + void GLES2Canvas::translate(float x, float y) { m_state->m_ctm.translate(x, y); @@ -275,12 +348,12 @@ void GLES2Canvas::clipPath(const Path& path) { bindFramebuffer(); checkGLError("bindFramebuffer"); - beginStencilDraw(); + beginStencilDraw(GraphicsContext3D::INCR); // Red is used so we can see it if it ends up in the color buffer. Color red(255, 0, 0, 255); - fillPath(path, red); - m_state->m_clippingPaths.append(path); - m_state->m_clippingEnabled = true; + fillPathInternal(path, red); + m_state->m_clippingPaths.append(PathAndTransform(path, m_state->m_ctm)); + m_state->m_numClippingPaths++; } void GLES2Canvas::clipOut(const Path& path) @@ -297,53 +370,48 @@ void GLES2Canvas::save() void GLES2Canvas::restore() { ASSERT(!m_stateStack.isEmpty()); - bool hadClippingPaths = !m_state->m_clippingPaths.isEmpty(); - m_stateStack.removeLast(); - m_state = &m_stateStack.last(); - if (hadClippingPaths) { - m_context->clear(GraphicsContext3D::STENCIL_BUFFER_BIT); - beginStencilDraw(); - StateVector::const_iterator iter; - for (iter = m_stateStack.begin(); iter < m_stateStack.end(); ++iter) { - const State& state = *iter; - const Vector<Path>& clippingPaths = state.m_clippingPaths; - Vector<Path>::const_iterator pathIter; - for (pathIter = clippingPaths.begin(); pathIter < clippingPaths.end(); ++pathIter) { - // Red is used so we can see it if it ends up in the color buffer. - Color red(255, 0, 0, 255); - fillPath(*pathIter, red); - } + const Vector<PathAndTransform>& clippingPaths = m_state->m_clippingPaths; + if (!clippingPaths.isEmpty()) { + beginStencilDraw(GraphicsContext3D::DECR); + WTF::Vector<PathAndTransform>::const_iterator pathIter; + for (pathIter = clippingPaths.begin(); pathIter < clippingPaths.end(); ++pathIter) { + m_state->m_ctm = pathIter->transform; + // Red is used so we can see it if it ends up in the color buffer. + Color red(255, 0, 0, 255); + fillPathInternal(pathIter->path, red); } } + m_stateStack.removeLast(); + m_state = &m_stateStack.last(); } void GLES2Canvas::drawTexturedRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp) { + bindFramebuffer(); m_context->applyCompositeOperator(compositeOp); applyClipping(false); - m_context->useQuadVertices(); m_context->setActiveTexture(GraphicsContext3D::TEXTURE0); m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, texture); - drawQuad(textureSize, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha); + drawTexturedQuad(textureSize, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha); } void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp) { - drawTexturedRect(texture, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha, colorSpace, compositeOp, m_state->m_clippingEnabled); + drawTexturedRect(texture, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha, colorSpace, compositeOp, m_state->clippingEnabled()); } void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha, ColorSpace colorSpace, CompositeOperator compositeOp, bool clip) { + bindFramebuffer(); m_context->applyCompositeOperator(compositeOp); applyClipping(clip); const TilingData& tiles = texture->tiles(); IntRect tileIdxRect = tiles.overlappedTileIndices(srcRect); - m_context->useQuadVertices(); m_context->setActiveTexture(GraphicsContext3D::TEXTURE0); for (int y = tileIdxRect.y(); y <= tileIdxRect.maxY(); y++) { @@ -367,13 +435,18 @@ void GLES2Canvas::drawTexturedRectTile(Texture* texture, int tile, const FloatRe IntRect tileBoundsWithBorder = tiles.tileBoundsWithBorder(tile); - drawQuad(tileBoundsWithBorder.size(), srcRectClippedInTileSpace, dstRectIntersected, transform, alpha); + drawTexturedQuad(tileBoundsWithBorder.size(), srcRectClippedInTileSpace, dstRectIntersected, transform, alpha); } -void GLES2Canvas::drawQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha) +void GLES2Canvas::convolveRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, float imageIncrement[2], const float* kernel, int kernelWidth) { + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, texture); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST); + AffineTransform matrix(m_flipMatrix); - matrix *= transform; matrix.translate(dstRect.x(), dstRect.y()); matrix.scale(dstRect.width(), dstRect.height()); @@ -382,13 +455,79 @@ void GLES2Canvas::drawQuad(const IntSize& textureSize, const FloatRect& srcRect, texMatrix.translate(srcRect.x(), srcRect.y()); texMatrix.scale(srcRect.width(), srcRect.height()); - bindFramebuffer(); + m_context->useQuadVertices(); + m_context->useConvolutionProgram(matrix, texMatrix, kernel, kernelWidth, imageIncrement); + m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4); + checkGLError("glDrawArrays"); +} +static float gauss(float x, float sigma) +{ + return exp(- (x * x) / (2.0f * sigma * sigma)); +} + +static void buildKernel(float sigma, float* kernel, int kernelWidth) +{ + float halfWidth = (kernelWidth - 1.0f) / 2.0f; + float sum = 0.0f; + for (int i = 0; i < kernelWidth; ++i) { + kernel[i] = gauss(i - halfWidth, sigma); + sum += kernel[i]; + } + // Normalize the kernel + float scale = 1.0f / sum; + for (int i = 0; i < kernelWidth; ++i) + kernel[i] *= scale; +} + +void GLES2Canvas::drawTexturedQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha) +{ + AffineTransform matrix(m_flipMatrix); + matrix *= transform; + matrix.translate(dstRect.x(), dstRect.y()); + matrix.scale(dstRect.width(), dstRect.height()); + + AffineTransform texMatrix; + texMatrix.scale(1.0f / textureSize.width(), 1.0f / textureSize.height()); + texMatrix.translate(srcRect.x(), srcRect.y()); + texMatrix.scale(srcRect.width(), srcRect.height()); + + m_context->useQuadVertices(); m_context->useTextureProgram(matrix, texMatrix, alpha); m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4); checkGLError("glDrawArrays"); } +void GLES2Canvas::drawTexturedQuadMitchell(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha) +{ + static const float mitchellCoefficients[16] = { + 0.0f / 18.0f, 1.0f / 18.0f, 16.0f / 18.0f, 1.0f / 18.0f, + 0.0f / 18.0f, 9.0f / 18.0f, 0.0f / 18.0f, -9.0f / 18.0f, + -6.0f / 18.0f, 27.0f / 18.0f, -36.0f / 18.0f, 15.0f / 18.0f, + 7.0f / 18.0f, -21.0f / 18.0f, 21.0f / 18.0f, -7.0f / 18.0f, + }; + + AffineTransform matrix(m_flipMatrix); + matrix *= transform; + matrix.translate(dstRect.x(), dstRect.y()); + matrix.scale(dstRect.width(), dstRect.height()); + + float imageIncrement[2] = { 1.0f / textureSize.width(), 1.0f / textureSize.height() }; + + AffineTransform texMatrix; + texMatrix.scale(imageIncrement[0], imageIncrement[1]); + texMatrix.translate(srcRect.x(), srcRect.y()); + texMatrix.scale(srcRect.width(), srcRect.height()); + + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST); + + m_context->useQuadVertices(); + m_context->useBicubicProgram(matrix, texMatrix, mitchellCoefficients, imageIncrement, alpha); + m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4); + checkGLError("glDrawArrays"); +} + void GLES2Canvas::setCompositeOperation(CompositeOperator op) { m_state->m_compositeOp = op; @@ -554,12 +693,9 @@ void GLES2Canvas::createVertexBufferFromPath(const Path& path, int* count, unsig *count = indices.size(); } -void GLES2Canvas::fillPath(const Path& path, const Color& color) +void GLES2Canvas::fillPathInternal(const Path& path, const Color& color) { if (SharedGraphicsContext3D::useLoopBlinnForPathRendering()) { - bindFramebuffer(); - m_context->applyCompositeOperator(m_state->m_compositeOp); - m_pathCache.clear(); LoopBlinnPathProcessor processor; processor.process(path, m_pathCache); @@ -590,18 +726,18 @@ void GLES2Canvas::fillPath(const Path& path, const Color& color) int count; unsigned vertexBuffer, indexBuffer; createVertexBufferFromPath(path, &count, &vertexBuffer, &indexBuffer); + + AffineTransform matrix(m_flipMatrix); + matrix *= m_state->m_ctm; + m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, vertexBuffer); checkGLError("bindBuffer"); m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, indexBuffer); checkGLError("bindBuffer"); - AffineTransform matrix(m_flipMatrix); - matrix *= m_state->m_ctm; - m_context->useFillSolidProgram(matrix, color); checkGLError("useFillSolidProgram"); - bindFramebuffer(); m_context->graphicsContext3D()->drawElements(GraphicsContext3D::TRIANGLES, count, GraphicsContext3D::UNSIGNED_SHORT, 0); checkGLError("drawArrays"); @@ -613,7 +749,141 @@ void GLES2Canvas::fillPath(const Path& path, const Color& color) } } -void GLES2Canvas::beginStencilDraw() +FloatRect GLES2Canvas::flipRect(const FloatRect& rect) +{ + FloatRect flippedRect(rect); + flippedRect.setY(m_size.height() - rect.y()); + flippedRect.setHeight(-rect.height()); + return flippedRect; +} + +void GLES2Canvas::clearBorders(const FloatRect& rect, int width) +{ + scissorClear(rect.x(), rect.y() - width, rect.width() + width, width); + scissorClear(rect.maxX(), rect.y(), width, rect.height() + width); + scissorClear(rect.x() - width, rect.maxY(), rect.width() + width, width); + scissorClear(rect.x() - width, rect.y() - width, width, rect.height() + width); +} + +void GLES2Canvas::beginShadowDraw() +{ + float offsetX = m_state->m_shadowOffset.width(); + float offsetY = m_state->m_shadowOffset.height(); + save(); + if (m_state->m_shadowsIgnoreTransforms) { + AffineTransform newCTM; + newCTM.translate(offsetX, -offsetY); + newCTM *= m_state->m_ctm; + m_state->m_ctm = newCTM; + } else + m_state->m_ctm.translate(offsetX, offsetY); + + if (m_state->m_shadowBlur > 0) { + // Draw hard shadow to offscreen buffer 0. + DrawingBuffer* dstBuffer = m_context->getOffscreenBuffer(0, m_size); + dstBuffer->bind(); + m_context->applyCompositeOperator(CompositeCopy); + applyClipping(false); + m_context->clearColor(Color(RGBA32(0))); + m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); + } else { + bindFramebuffer(); + m_context->applyCompositeOperator(m_state->m_compositeOp); + applyClipping(m_state->clippingEnabled()); + } +} + +void GLES2Canvas::endShadowDraw(const FloatRect& boundingBox) +{ + if (m_state->m_shadowBlur > 0) { + // Buffer 0 contains the primitive drawn with a hard shadow. + DrawingBuffer* srcBuffer = m_context->getOffscreenBuffer(0, m_size); + DrawingBuffer* dstBuffer = m_context->getOffscreenBuffer(1, m_size); + + float sigma = m_state->m_shadowBlur * 0.333333f; + FloatRect shadowBoundingBox(m_state->m_ctm.mapRect(boundingBox)); + FloatRect rect(FloatPoint(0, 0), m_size); + FloatRect srcRect(shadowBoundingBox); + + int scaleFactor = 1; + while (sigma > cMaxSigma) { + srcRect.scale(0.5f); + scaleFactor *= 2; + sigma *= 0.5f; + } + srcRect = enclosingIntRect(srcRect); + srcRect.scale(scaleFactor); + for (int i = 1; i < scaleFactor; i *= 2) { + dstBuffer->bind(); + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, srcBuffer->colorBuffer()); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); + FloatRect dstRect(srcRect); + dstRect.scale(0.5f); + // Clear out 1 pixel border for linear filtering. + clearBorders(dstRect, 1); + drawTexturedQuad(srcBuffer->size(), flipRect(srcRect), dstRect, AffineTransform(), 1.0); + srcRect = dstRect; + std::swap(srcBuffer, dstBuffer); + } + + int halfWidth = static_cast<int>(sigma * 3.0f); + int kernelWidth = halfWidth * 2 + 1; + OwnArrayPtr<float> kernel = adoptArrayPtr(new float[kernelWidth]); + buildKernel(sigma, kernel.get(), kernelWidth); + + if (scaleFactor > 1) { + scissorClear(srcRect.maxX(), srcRect.y(), kernelWidth, srcRect.height()); + scissorClear(srcRect.x() - kernelWidth, srcRect.y(), kernelWidth, srcRect.height()); + } + + // Blur in X offscreen. + dstBuffer->bind(); + srcRect.inflateX(halfWidth); + srcRect.intersect(rect); + float imageIncrementX[2] = {1.0f / srcBuffer->size().width(), 0.0f}; + convolveRect(srcBuffer->colorBuffer(), srcBuffer->size(), flipRect(srcRect), srcRect, imageIncrementX, kernel.get(), kernelWidth); + + if (scaleFactor > 1) { + scissorClear(srcRect.x(), srcRect.maxY(), srcRect.width(), kernelWidth); + scissorClear(srcRect.x(), srcRect.y() - kernelWidth, srcRect.width(), kernelWidth); + } + srcRect.inflateY(halfWidth); + srcRect.intersect(rect); + std::swap(srcBuffer, dstBuffer); + + float imageIncrementY[2] = {0.0f, 1.0f / srcBuffer->size().height()}; + if (scaleFactor > 1) { + // Blur in Y offscreen. + dstBuffer->bind(); + convolveRect(srcBuffer->colorBuffer(), srcBuffer->size(), flipRect(srcRect), srcRect, imageIncrementY, kernel.get(), kernelWidth); + // Clear out 2 pixel border for bicubic filtering. + clearBorders(srcRect, 2); + std::swap(srcBuffer, dstBuffer); + + // Upsample srcBuffer -> main framebuffer using bicubic filtering. + bindFramebuffer(); + m_context->applyCompositeOperator(m_state->m_compositeOp); + applyClipping(m_state->clippingEnabled()); + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, srcBuffer->colorBuffer()); + FloatRect dstRect = srcRect; + dstRect.scale(scaleFactor); + drawTexturedQuadMitchell(srcBuffer->size(), flipRect(srcRect), dstRect, AffineTransform(), 1.0); + } else { + // Blur in Y directly to framebuffer. + bindFramebuffer(); + m_context->applyCompositeOperator(m_state->m_compositeOp); + applyClipping(m_state->clippingEnabled()); + + convolveRect(srcBuffer->colorBuffer(), srcBuffer->size(), flipRect(srcRect), srcRect, imageIncrementY, kernel.get(), kernelWidth); + } + } + restore(); +} + +void GLES2Canvas::beginStencilDraw(unsigned op) { // Turn on stencil test. m_context->enableStencil(true); @@ -624,9 +894,7 @@ void GLES2Canvas::beginStencilDraw() checkGLError("stencilFunc"); // All writes incremement the stencil buffer. - m_context->graphicsContext3D()->stencilOp(GraphicsContext3D::INCR, - GraphicsContext3D::INCR, - GraphicsContext3D::INCR); + m_context->graphicsContext3D()->stencilOp(op, op, op); checkGLError("stencilOp"); } @@ -635,7 +903,7 @@ void GLES2Canvas::applyClipping(bool enable) m_context->enableStencil(enable); if (enable) { // Enable drawing only where stencil is non-zero. - m_context->graphicsContext3D()->stencilFunc(GraphicsContext3D::EQUAL, m_state->m_clippingPaths.size() % 256, 1); + m_context->graphicsContext3D()->stencilFunc(GraphicsContext3D::EQUAL, m_state->m_numClippingPaths, -1); checkGLError("stencilFunc"); // Keep all stencil values the same. m_context->graphicsContext3D()->stencilOp(GraphicsContext3D::KEEP, diff --git a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h index 8887a16..f6a8bcf 100644 --- a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h +++ b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h @@ -64,6 +64,10 @@ public: void clearRect(const FloatRect&); void setFillColor(const Color&, ColorSpace); void setAlpha(float alpha); + void setShadowColor(const Color&, ColorSpace); + void setShadowOffset(const FloatSize&); + void setShadowBlur(float); + void setShadowsIgnoreTransforms(bool); void setCompositeOperation(CompositeOperator); void translate(float x, float y); void rotate(float angleInRadians); @@ -96,12 +100,21 @@ public: DrawingBuffer* drawingBuffer() const { return m_drawingBuffer; } private: + void scissorClear(float x, float y, float width, float height); void drawTexturedRectTile(Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha); - void drawQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha); + void drawTexturedQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha); + void drawTexturedQuadMitchell(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha); + void convolveRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, float imageIncrement[2], const float* kernel, int kernelWidth); + void applyCompositeOperator(CompositeOperator); void createVertexBufferFromPath(const Path&, int* count, unsigned* vertexBuffer, unsigned* indexBuffer); - void fillPath(const Path&, const Color&); - void beginStencilDraw(); + void fillPathInternal(const Path&, const Color&); + void fillRectInternal(const FloatRect&, const Color&); + FloatRect flipRect(const FloatRect&); + void clearBorders(const FloatRect&, int width); + void beginShadowDraw(); + void endShadowDraw(const FloatRect& boundingBox); + void beginStencilDraw(unsigned op); void applyClipping(bool enable); void checkGLError(const char* header); diff --git a/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp index ee2b5ab..cfc1754 100644 --- a/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp +++ b/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp @@ -36,8 +36,8 @@ #include "GlyphPageTreeNode.h" #include "PlatformBridge.h" #include "SimpleFontData.h" +#include "SystemInfo.h" #include "UniscribeHelperTextRun.h" -#include "WindowsVersion.h" namespace WebCore { @@ -134,7 +134,7 @@ static bool fillBMPGlyphs(unsigned offset, bool haveGlyphs = false; int invalidGlyph = 0xFFFF; const DWORD cffTableTag = 0x20464643; // 4-byte identifier for OpenType CFF table ('CFF '). - if (!isVistaOrNewer() && !(tm.tmPitchAndFamily & TMPF_TRUETYPE) && (GetFontData(dc, cffTableTag, 0, 0, 0) == GDI_ERROR)) + if ((windowsVersion() < WindowsVista) && !(tm.tmPitchAndFamily & TMPF_TRUETYPE) && (GetFontData(dc, cffTableTag, 0, 0, 0) == GDI_ERROR)) invalidGlyph = 0x1F; Glyph spaceGlyph = 0; // Glyph for a space. Lazily filled. diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp index 7c42366..60c1332 100644 --- a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp @@ -60,7 +60,7 @@ void ImageLayerChromium::setContents(Image* contents) setNeedsDisplay(); } -void ImageLayerChromium::updateContentsIfDirty() +void ImageLayerChromium::paintContentsIfDirty() { ASSERT(layerRenderer()); @@ -68,7 +68,7 @@ void ImageLayerChromium::updateContentsIfDirty() if (requiresClippedUpdateRect()) { // Use the base version of updateContents which draws a subset of the // image to a bitmap, as the pixel contents can't be uploaded directly. - ContentLayerChromium::updateContentsIfDirty(); + ContentLayerChromium::paintContentsIfDirty(); return; } diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h index cc9064d..6addabc 100644 --- a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h @@ -50,7 +50,7 @@ class ImageLayerChromium : public ContentLayerChromium { public: static PassRefPtr<ImageLayerChromium> create(GraphicsLayerChromium* owner = 0); - virtual void updateContentsIfDirty(); + virtual void paintContentsIfDirty(); virtual bool drawsContent() const { return m_contents; } void setContents(Image* image); diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp index 95b7386..bc28239 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -62,6 +62,7 @@ LayerChromium::LayerChromium(GraphicsLayerChromium* owner) : m_owner(owner) , m_contentsDirty(false) , m_maskLayer(0) + , m_ccLayerImpl(0) , m_superlayer(0) #ifndef NDEBUG , m_debugID(s_nextLayerDebugID++) @@ -77,7 +78,7 @@ LayerChromium::LayerChromium(GraphicsLayerChromium* owner) , m_opaque(true) , m_geometryFlipped(false) , m_needsDisplayOnBoundsChange(false) - , m_ccLayerImpl(CCLayerImpl::create(this)) + , m_doubleSided(true) , m_replicaLayer(0) { } @@ -94,7 +95,8 @@ LayerChromium::~LayerChromium() void LayerChromium::cleanupResources() { - m_ccLayerImpl->cleanupResources(); + if (m_ccLayerImpl) + m_ccLayerImpl->cleanupResources(); } void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer) @@ -105,8 +107,7 @@ void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer) cleanupResources(); setNeedsDisplay(); } - - m_ccLayerImpl->setLayerRenderer(renderer); + m_layerRenderer = renderer; } void LayerChromium::setNeedsCommit() @@ -188,7 +189,7 @@ void LayerChromium::setBounds(const IntSize& size) bool firstResize = !bounds().width() && !bounds().height() && size.width() && size.height(); - m_ccLayerImpl->setBounds(size); + m_bounds = size; if (firstResize) setNeedsDisplay(FloatRect(0, 0, bounds().width(), bounds().height())); @@ -240,7 +241,6 @@ LayerChromium* LayerChromium::superlayer() const void LayerChromium::setName(const String& name) { m_name = name; - m_ccLayerImpl->setName(name); } void LayerChromium::setNeedsDisplay(const FloatRect& dirtyRect) @@ -288,6 +288,29 @@ void LayerChromium::toGLMatrix(float* flattened, const TransformationMatrix& m) flattened[15] = m.m44(); } +void LayerChromium::pushPropertiesTo(CCLayerImpl* layer) +{ + layer->setAnchorPoint(m_anchorPoint); + layer->setAnchorPointZ(m_anchorPointZ); + layer->setBounds(m_bounds); + layer->setDebugBorderColor(m_debugBorderColor); + layer->setDebugBorderWidth(m_debugBorderWidth); + layer->setDoubleSided(m_doubleSided); + layer->setLayerRenderer(m_layerRenderer.get()); + layer->setMasksToBounds(m_masksToBounds); + layer->setName(m_name); + layer->setOpacity(m_opacity); + layer->setPosition(m_position); + layer->setPreserves3D(preserves3D()); + layer->setSublayerTransform(m_sublayerTransform); + layer->setTransform(m_transform); + + if (maskLayer()) + maskLayer()->pushPropertiesTo(layer->maskLayer()); + if (replicaLayer()) + replicaLayer()->pushPropertiesTo(layer->replicaLayer()); +} + GraphicsContext3D* LayerChromium::layerRendererContext() const { ASSERT(layerRenderer()); @@ -316,31 +339,6 @@ void LayerChromium::drawTexturedQuad(GraphicsContext3D* context, const Transform GLC(context, context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0)); } - - -// Returns true if any of the layer's descendants has drawable content. -bool LayerChromium::descendantsDrawContent() -{ - const Vector<RefPtr<LayerChromium> >& sublayers = getSublayers(); - for (size_t i = 0; i < sublayers.size(); ++i) - if (sublayers[i]->descendantsDrawContentRecursive()) - return true; - return false; -} - -// Returns true if either this layer or one of its descendants has drawable content. -bool LayerChromium::descendantsDrawContentRecursive() -{ - if (drawsContent()) - return true; - - const Vector<RefPtr<LayerChromium> >& sublayers = getSublayers(); - for (size_t i = 0; i < sublayers.size(); ++i) - if (sublayers[i]->descendantsDrawContentRecursive()) - return true; - return false; -} - String LayerChromium::layerTreeAsText() const { TextStream ts; @@ -359,7 +357,8 @@ void LayerChromium::dumpLayer(TextStream& ts, int indent) const writeIndent(ts, indent); ts << layerTypeAsString() << "(" << m_name << ")\n"; dumpLayerProperties(ts, indent+2); - m_ccLayerImpl->dumpLayerProperties(ts, indent+2); + if (m_ccLayerImpl) + m_ccLayerImpl->dumpLayerProperties(ts, indent+2); if (m_replicaLayer) { writeIndent(ts, indent+2); ts << "Replica:\n"; @@ -385,48 +384,38 @@ void LayerChromium::dumpLayerProperties(TextStream& ts, int indent) const } -// Begin calls that forward to the CCLayerImpl. -// ============================================== -// These exists just for debugging (via drawDebugBorder()). -void LayerChromium::setBorderColor(const Color& color) +PassRefPtr<CCLayerImpl> LayerChromium::createCCLayerImpl() { - m_ccLayerImpl->setDebugBorderColor(color); - setNeedsCommit(); + return CCLayerImpl::create(this); } -Color LayerChromium::borderColor() const +void LayerChromium::createCCLayerImplIfNeeded() { - return m_ccLayerImpl->debugBorderColor(); + if (!m_ccLayerImpl) + m_ccLayerImpl = createCCLayerImpl(); } -void LayerChromium::setBorderWidth(float width) +CCLayerImpl* LayerChromium::ccLayerImpl() { - m_ccLayerImpl->setDebugBorderWidth(width); - setNeedsCommit(); + return m_ccLayerImpl.get(); } -float LayerChromium::borderWidth() const -{ - return m_ccLayerImpl->debugBorderWidth(); -} - -LayerRendererChromium* LayerChromium::layerRenderer() const +void LayerChromium::setBorderColor(const Color& color) { - return m_ccLayerImpl->layerRenderer(); + m_debugBorderColor = color; + setNeedsCommit(); } -void LayerChromium::setDoubleSided(bool doubleSided) +void LayerChromium::setBorderWidth(float width) { - m_ccLayerImpl->setDoubleSided(doubleSided); + m_debugBorderWidth = width; setNeedsCommit(); } -const IntSize& LayerChromium::bounds() const +LayerRendererChromium* LayerChromium::layerRenderer() const { - return m_ccLayerImpl->bounds(); + return m_layerRenderer.get(); } -// ============================================== -// End calls that forward to the CCLayerImpl. } #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerChromium.h index 29a2165..428ce61 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.h @@ -89,6 +89,9 @@ public: void setBackgroundColor(const Color& color) { m_backgroundColor = color; setNeedsCommit(); } Color backgroundColor() const { return m_backgroundColor; } + void setBounds(const IntSize&); + const IntSize& bounds() const { return m_bounds; } + void setClearsContext(bool clears) { m_clearsContext = clears; setNeedsCommit(); } bool clearsContext() const { return m_clearsContext; } @@ -133,6 +136,9 @@ public: void setTransform(const TransformationMatrix& transform) { m_transform = transform; setNeedsCommit(); } const TransformationMatrix& transform() const { return m_transform; } + bool doubleSided() const { return m_doubleSided; } + void setDoubleSided(bool doubleSided) { m_doubleSided = doubleSided; setNeedsCommit(); } + // FIXME: This setting is currently ignored. void setGeometryFlipped(bool flipped) { m_geometryFlipped = flipped; setNeedsCommit(); } bool geometryFlipped() const { return m_geometryFlipped; } @@ -143,9 +149,6 @@ public: // in the LayerRendererChromium. virtual void setLayerRenderer(LayerRendererChromium*); - // Returns true if any of the layer's descendants has content to draw. - bool descendantsDrawContent(); - void setOwner(GraphicsLayerChromium* owner) { m_owner = owner; } void setReplicaLayer(LayerChromium* layer) { m_replicaLayer = layer; } @@ -153,14 +156,14 @@ public: // These methods typically need to be overwritten by derived classes. virtual bool drawsContent() const { return false; } - virtual void updateContentsIfDirty() { } + virtual void paintContentsIfDirty() { } + virtual void updateCompositorResources() { } virtual void unreserveContentsTexture() { } virtual void bindContentsTexture() { } virtual void draw() { } // These exists just for debugging (via drawDebugBorder()). void setBorderColor(const Color&); - Color borderColor() const; #ifndef NDEBUG int debugID() const { return m_debugID; } @@ -170,21 +173,19 @@ public: String layerTreeAsText() const; void setBorderWidth(float); - float borderWidth() const; // Everything from here down in the public section will move to CCLayerImpl. - - CCLayerImpl* ccLayerImpl() const { return m_ccLayerImpl.get(); } + CCLayerImpl* ccLayerImpl(); + void createCCLayerImplIfNeeded(); static void drawTexturedQuad(GraphicsContext3D*, const TransformationMatrix& projectionMatrix, const TransformationMatrix& layerMatrix, float width, float height, float opacity, int matrixLocation, int alphaLocation); + virtual void pushPropertiesTo(CCLayerImpl*); + // Begin calls that forward to the CCLayerImpl. LayerRendererChromium* layerRenderer() const; - void setDoubleSided(bool); - void setBounds(const IntSize&); - const IntSize& bounds() const; // End calls that forward to the CCLayerImpl. typedef ProgramBinding<VertexShaderPos, FragmentShaderColor> BorderProgram; @@ -217,6 +218,11 @@ protected: static const unsigned s_positionAttribLocation; static const unsigned s_texCoordAttribLocation; + // Constructs a CCLayerImpl of the correct runtime type for this LayerChromium type. + virtual PassRefPtr<CCLayerImpl> createCCLayerImpl(); + + // For now, the LayerChromium directly owns its CCLayerImpl. + RefPtr<CCLayerImpl> m_ccLayerImpl; private: void setNeedsCommit(); @@ -233,19 +239,22 @@ private: // This should only be called from removeFromSuperlayer. void removeSublayer(LayerChromium*); - bool descendantsDrawContentRecursive(); - Vector<RefPtr<LayerChromium> > m_sublayers; LayerChromium* m_superlayer; + RefPtr<LayerRendererChromium> m_layerRenderer; + #ifndef NDEBUG int m_debugID; #endif // Layer properties. + IntSize m_bounds; FloatPoint m_position; FloatPoint m_anchorPoint; Color m_backgroundColor; + Color m_debugBorderColor; + float m_debugBorderWidth; float m_opacity; float m_zPosition; float m_anchorPointZ; @@ -255,13 +264,12 @@ private: bool m_opaque; bool m_geometryFlipped; bool m_needsDisplayOnBoundsChange; + bool m_doubleSided; TransformationMatrix m_transform; TransformationMatrix m_sublayerTransform; FloatRect m_frame; - // For now, the LayerChromium directly owns its CCLayerImpl. - RefPtr<CCLayerImpl> m_ccLayerImpl; // Replica layer used for reflections. LayerChromium* m_replicaLayer; diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index e7b299f..fc15abd 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -36,6 +36,7 @@ #include "cc/CCLayerImpl.h" #include "Canvas2DLayerChromium.h" +#include "FloatQuad.h" #include "GeometryBinding.h" #include "GraphicsContext3D.h" #include "LayerChromium.h" @@ -43,6 +44,7 @@ #include "NotImplemented.h" #include "TextStream.h" #include "TextureManager.h" +#include "TraceEvent.h" #include "WebGLLayerChromium.h" #include "cc/CCLayerImpl.h" #if USE(SKIA) @@ -91,21 +93,23 @@ bool LayerRendererChromium::compareLayerZ(const CCLayerImpl* a, const CCLayerImp return a->drawDepth() < b->drawDepth(); } -PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassRefPtr<GraphicsContext3D> context) +PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<TilePaintInterface> contentPaint, PassOwnPtr<TilePaintInterface> scrollbarPaint) { if (!context) return 0; - RefPtr<LayerRendererChromium> layerRenderer(adoptRef(new LayerRendererChromium(context))); + RefPtr<LayerRendererChromium> layerRenderer(adoptRef(new LayerRendererChromium(context, contentPaint, scrollbarPaint))); if (!layerRenderer->hardwareCompositing()) return 0; return layerRenderer.release(); } -LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> context) - : m_rootLayer(0) - , m_scrollPosition(IntPoint(-1, -1)) +LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<TilePaintInterface> contentPaint, PassOwnPtr<TilePaintInterface> scrollbarPaint) + : m_viewportScrollPosition(IntPoint(-1, -1)) + , m_rootLayer(0) + , m_rootLayerContentPaint(contentPaint) + , m_rootLayerScrollbarPaint(scrollbarPaint) , m_currentShader(0) , m_currentRenderSurface(0) , m_offscreenFramebufferId(0) @@ -114,8 +118,8 @@ LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> conte , m_defaultRenderSurface(0) { m_hardwareCompositing = initializeSharedObjects(); - m_rootLayerTiler = LayerTilerChromium::create(this, IntSize(256, 256), LayerTilerChromium::NoBorderTexels); - ASSERT(m_rootLayerTiler); + m_rootLayerContentTiler = LayerTilerChromium::create(this, IntSize(256, 256), LayerTilerChromium::NoBorderTexels); + ASSERT(m_rootLayerContentTiler); m_headsUpDisplay = CCHeadsUpDisplay::create(this); } @@ -146,129 +150,149 @@ void LayerRendererChromium::useShader(unsigned programId) } } -IntRect LayerRendererChromium::verticalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect) +IntRect LayerRendererChromium::verticalScrollbarRect() const { - IntRect verticalScrollbar(IntPoint(contentRect.maxX(), contentRect.y()), IntSize(visibleRect.width() - contentRect.width(), visibleRect.height())); + IntRect verticalScrollbar(IntPoint(m_viewportContentRect.maxX(), m_viewportContentRect.y()), IntSize(m_viewportVisibleRect.width() - m_viewportContentRect.width(), m_viewportVisibleRect.height())); return verticalScrollbar; } -IntRect LayerRendererChromium::horizontalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect) +IntRect LayerRendererChromium::horizontalScrollbarRect() const { - IntRect horizontalScrollbar(IntPoint(contentRect.x(), contentRect.maxY()), IntSize(visibleRect.width(), visibleRect.height() - contentRect.height())); + IntRect horizontalScrollbar(IntPoint(m_viewportContentRect.x(), m_viewportContentRect.maxY()), IntSize(m_viewportVisibleRect.width(), m_viewportVisibleRect.height() - m_viewportContentRect.height())); return horizontalScrollbar; } -void LayerRendererChromium::invalidateRootLayerRect(const IntRect& dirtyRect, const IntRect& visibleRect, const IntRect& contentRect) +void LayerRendererChromium::invalidateRootLayerRect(const IntRect& dirtyRect) { - m_rootLayerTiler->invalidateRect(dirtyRect); + m_rootLayerContentTiler->invalidateRect(dirtyRect); + + // Scrollbars never need to render beyond the fold, so clip to the viewport. + IntRect visibleDirtyRect = dirtyRect; + visibleDirtyRect.intersect(m_viewportVisibleRect); + if (m_horizontalScrollbarTiler) { - IntRect scrollbar = horizontalScrollbarRect(visibleRect, contentRect); - if (dirtyRect.intersects(scrollbar)) { + IntRect scrollbar = horizontalScrollbarRect(); + if (visibleDirtyRect.intersects(scrollbar)) { m_horizontalScrollbarTiler->setLayerPosition(scrollbar.location()); - m_horizontalScrollbarTiler->invalidateRect(dirtyRect); + m_horizontalScrollbarTiler->invalidateRect(visibleDirtyRect); } } if (m_verticalScrollbarTiler) { - IntRect scrollbar = verticalScrollbarRect(visibleRect, contentRect); - if (dirtyRect.intersects(scrollbar)) { + IntRect scrollbar = verticalScrollbarRect(); + if (visibleDirtyRect.intersects(scrollbar)) { m_verticalScrollbarTiler->setLayerPosition(scrollbar.location()); - m_verticalScrollbarTiler->invalidateRect(dirtyRect); + m_verticalScrollbarTiler->invalidateRect(visibleDirtyRect); } } } -void LayerRendererChromium::updateRootLayerContents(TilePaintInterface& tilePaint, const IntRect& visibleRect) +void LayerRendererChromium::updateRootLayerContents() { - m_rootLayerTiler->update(tilePaint, visibleRect); + TRACE_EVENT("LayerRendererChromium::updateRootLayerContents", this, 0); + m_rootLayerContentTiler->update(*m_rootLayerContentPaint, m_viewportVisibleRect); } -void LayerRendererChromium::updateRootLayerScrollbars(TilePaintInterface& scrollbarPaint, const IntRect& visibleRect, const IntRect& contentRect) +void LayerRendererChromium::updateRootLayerScrollbars() { - if (visibleRect.width() > contentRect.width()) { - IntRect verticalScrollbar = verticalScrollbarRect(visibleRect, contentRect); + TRACE_EVENT("LayerRendererChromium::updateRootLayerScrollbars", this, 0); + if (m_viewportVisibleRect.width() > m_viewportContentRect.width()) { + IntRect verticalScrollbar = verticalScrollbarRect(); IntSize tileSize = verticalScrollbar.size().shrunkTo(IntSize(m_maxTextureSize, m_maxTextureSize)); if (!m_verticalScrollbarTiler) m_verticalScrollbarTiler = LayerTilerChromium::create(this, tileSize, LayerTilerChromium::NoBorderTexels); else m_verticalScrollbarTiler->setTileSize(tileSize); m_verticalScrollbarTiler->setLayerPosition(verticalScrollbar.location()); - m_verticalScrollbarTiler->update(scrollbarPaint, visibleRect); + m_verticalScrollbarTiler->update(*m_rootLayerScrollbarPaint, m_viewportVisibleRect); } else m_verticalScrollbarTiler.clear(); - if (visibleRect.height() > contentRect.height()) { - IntRect horizontalScrollbar = horizontalScrollbarRect(visibleRect, contentRect); + if (m_viewportVisibleRect.height() > m_viewportContentRect.height()) { + IntRect horizontalScrollbar = horizontalScrollbarRect(); IntSize tileSize = horizontalScrollbar.size().shrunkTo(IntSize(m_maxTextureSize, m_maxTextureSize)); if (!m_horizontalScrollbarTiler) m_horizontalScrollbarTiler = LayerTilerChromium::create(this, tileSize, LayerTilerChromium::NoBorderTexels); else m_horizontalScrollbarTiler->setTileSize(tileSize); m_horizontalScrollbarTiler->setLayerPosition(horizontalScrollbar.location()); - m_horizontalScrollbarTiler->update(scrollbarPaint, visibleRect); + m_horizontalScrollbarTiler->update(*m_rootLayerScrollbarPaint, m_viewportVisibleRect); } else m_horizontalScrollbarTiler.clear(); } void LayerRendererChromium::drawRootLayer() { - m_rootLayerTiler->draw(m_visibleRect); + m_rootLayerContentTiler->draw(m_viewportVisibleRect); if (m_verticalScrollbarTiler) - m_verticalScrollbarTiler->draw(m_visibleRect); + m_verticalScrollbarTiler->draw(m_viewportVisibleRect); if (m_horizontalScrollbarTiler) - m_horizontalScrollbarTiler->draw(m_visibleRect); + m_horizontalScrollbarTiler->draw(m_viewportVisibleRect); +} + +void LayerRendererChromium::setViewport(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition) +{ + bool visibleRectChanged = m_viewportVisibleRect.size() != visibleRect.size(); + + m_viewportVisibleRect = visibleRect; + m_viewportContentRect = contentRect; + m_viewportScrollPosition = scrollPosition; + + if (visibleRectChanged) { + // Reset the current render surface to force an update of the viewport and + // projection matrix next time useRenderSurface is called. + m_currentRenderSurface = 0; + + m_rootLayerContentTiler->invalidateEntireLayer(); + if (m_horizontalScrollbarTiler) + m_horizontalScrollbarTiler->invalidateEntireLayer(); + if (m_verticalScrollbarTiler) + m_verticalScrollbarTiler->invalidateEntireLayer(); + } } -void LayerRendererChromium::updateAndDrawLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition, - TilePaintInterface& tilePaint, TilePaintInterface& scrollbarPaint) +void LayerRendererChromium::updateAndDrawLayers() { ASSERT(m_hardwareCompositing); if (!m_rootLayer) return; - updateRootLayerContents(tilePaint, visibleRect); + updateRootLayerContents(); + // Recheck that we still have a root layer. This may become null if // compositing gets turned off during a paint operation. if (!m_rootLayer) return; - updateRootLayerScrollbars(scrollbarPaint, visibleRect, contentRect); + updateRootLayerScrollbars(); Vector<CCLayerImpl*> renderSurfaceLayerList; - updateLayers(visibleRect, contentRect, scrollPosition, renderSurfaceLayerList); + updateLayers(renderSurfaceLayerList); drawLayers(renderSurfaceLayerList); + + if (isCompositingOffscreen()) + copyOffscreenTextureToDisplay(); } -void LayerRendererChromium::updateLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition, - Vector<CCLayerImpl*>& renderSurfaceLayerList) +void LayerRendererChromium::updateLayers(Vector<CCLayerImpl*>& renderSurfaceLayerList) { + TRACE_EVENT("LayerRendererChromium::updateLayers", this, 0); + m_rootLayer->createCCLayerImplIfNeeded(); CCLayerImpl* rootDrawLayer = m_rootLayer->ccLayerImpl(); if (!rootDrawLayer->renderSurface()) rootDrawLayer->createRenderSurface(); ASSERT(rootDrawLayer->renderSurface()); - // If the size of the visible area has changed then allocate a new texture - // to store the contents of the root layer and adjust the projection matrix - // and viewport. - - rootDrawLayer->renderSurface()->m_contentRect = IntRect(IntPoint(0, 0), visibleRect.size()); + rootDrawLayer->renderSurface()->m_contentRect = IntRect(IntPoint(0, 0), m_viewportVisibleRect.size()); - if (visibleRect.size() != m_visibleRect.size()) { - // Reset the current render surface to force an update of the viewport and - // projection matrix next time useRenderSurface is called. - m_currentRenderSurface = 0; - } - m_visibleRect = visibleRect; - - m_scrollPosition = scrollPosition; // Scissor out the scrollbars to avoid rendering on top of them. - IntRect rootScissorRect(contentRect); + IntRect rootScissorRect(m_viewportContentRect); // The scissorRect should not include the scroll offset. - rootScissorRect.move(-m_scrollPosition.x(), -m_scrollPosition.y()); + rootScissorRect.move(-m_viewportScrollPosition.x(), -m_viewportScrollPosition.y()); rootDrawLayer->setScissorRect(rootScissorRect); m_defaultRenderSurface = rootDrawLayer->renderSurface(); @@ -283,16 +307,19 @@ void LayerRendererChromium::updateLayers(const IntRect& visibleRect, const IntRe // concept of a large content layer. updatePropertiesAndRenderSurfaces(m_rootLayer.get(), identityMatrix, renderSurfaceLayerList, m_defaultRenderSurface->m_layerList); - updateContentsRecursive(m_rootLayer.get()); + paintContentsRecursive(m_rootLayer.get()); + + updateCompositorResourcesRecursive(m_rootLayer.get()); } void LayerRendererChromium::drawLayers(const Vector<CCLayerImpl*>& renderSurfaceLayerList) { + TRACE_EVENT("LayerRendererChromium::drawLayers", this, 0); CCLayerImpl* rootDrawLayer = m_rootLayer->ccLayerImpl(); makeContextCurrent(); // The GL viewport covers the entire visible area, including the scrollbars. - GLC(m_context.get(), m_context->viewport(0, 0, m_visibleRect.width(), m_visibleRect.height())); + GLC(m_context.get(), m_context->viewport(0, 0, m_viewportVisibleRect.width(), m_viewportVisibleRect.height())); // Bind the common vertex attributes used for drawing all the layers. m_sharedGeometry->prepareForDraw(); @@ -363,11 +390,13 @@ void LayerRendererChromium::drawLayers(const Vector<CCLayerImpl*>& renderSurface void LayerRendererChromium::finish() { + TRACE_EVENT("LayerRendererChromium::finish", this, 0); m_context->finish(); } void LayerRendererChromium::present() { + TRACE_EVENT("LayerRendererChromium::present", this, 0); // We're done! Time to swapbuffers! // Note that currently this has the same effect as swapBuffers; we should @@ -382,7 +411,7 @@ void LayerRendererChromium::setRootLayer(PassRefPtr<LayerChromium> layer) m_rootLayer = layer; if (m_rootLayer) m_rootLayer->setLayerRenderer(this); - m_rootLayerTiler->invalidateEntireLayer(); + m_rootLayerContentTiler->invalidateEntireLayer(); if (m_horizontalScrollbarTiler) m_horizontalScrollbarTiler->invalidateEntireLayer(); if (m_verticalScrollbarTiler) @@ -391,7 +420,7 @@ void LayerRendererChromium::setRootLayer(PassRefPtr<LayerChromium> layer) void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect) { - ASSERT(rect.maxX() <= visibleRectSize().width() && rect.maxY() <= visibleRectSize().height()); + ASSERT(rect.maxX() <= m_viewportVisibleRect.width() && rect.maxY() <= m_viewportVisibleRect.height()); if (!pixels) return; @@ -446,8 +475,29 @@ bool LayerRendererChromium::isLayerVisible(LayerChromium* layer, const Transform // necessary transformations, scissor rectangles, render surfaces, etc. void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* layer, const TransformationMatrix& parentMatrix, Vector<CCLayerImpl*>& renderSurfaceLayerList, Vector<CCLayerImpl*>& layerList) { + // Make sure we have CCLayerImpls for this subtree. + layer->createCCLayerImplIfNeeded(); layer->setLayerRenderer(this); + if (layer->maskLayer()) { + layer->maskLayer()->createCCLayerImplIfNeeded(); + layer->maskLayer()->setLayerRenderer(this); + } + if (layer->replicaLayer()) { + layer->replicaLayer()->createCCLayerImplIfNeeded(); + layer->replicaLayer()->setLayerRenderer(this); + } + if (layer->replicaLayer() && layer->replicaLayer()->maskLayer()) { + layer->replicaLayer()->maskLayer()->createCCLayerImplIfNeeded(); + layer->replicaLayer()->maskLayer()->setLayerRenderer(this); + } + CCLayerImpl* drawLayer = layer->ccLayerImpl(); + // Currently we're calling pushPropertiesTo() twice - once here and once in updateCompositorResourcesRecursive(). + // We should only call pushPropertiesTo() in commit, but because we rely on the draw layer state to update + // RenderSurfaces and we rely on RenderSurfaces being up to date in order to paint contents we have + // to update the draw layers twice. + // FIXME: Remove this call once layer updates no longer depend on render surfaces. + layer->pushPropertiesTo(drawLayer); // Compute the new matrix transformation that will be applied to this layer and // all its sublayers. It's important to remember that the layer's position @@ -467,9 +517,9 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay // Where: P is the projection matrix // M is the layer's matrix computed above // S is the scale adjustment (to scale up to the layer size) - IntSize bounds = layer->bounds(); - FloatPoint anchorPoint = layer->anchorPoint(); - FloatPoint position = layer->position(); + IntSize bounds = drawLayer->bounds(); + FloatPoint anchorPoint = drawLayer->anchorPoint(); + FloatPoint position = drawLayer->position(); // Offset between anchor point and the center of the quad. float centerOffsetX = (0.5 - anchorPoint.x()) * bounds.width(); @@ -477,16 +527,16 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay TransformationMatrix layerLocalTransform; // LT = Tr[l] - layerLocalTransform.translate3d(position.x(), position.y(), layer->anchorPointZ()); + layerLocalTransform.translate3d(position.x(), position.y(), drawLayer->anchorPointZ()); // LT = Tr[l] * M[l] - layerLocalTransform.multiply(layer->transform()); + layerLocalTransform.multiply(drawLayer->transform()); // LT = Tr[l] * M[l] * Tr[c] - layerLocalTransform.translate3d(centerOffsetX, centerOffsetY, -layer->anchorPointZ()); + layerLocalTransform.translate3d(centerOffsetX, centerOffsetY, -drawLayer->anchorPointZ()); TransformationMatrix combinedTransform = parentMatrix; combinedTransform = combinedTransform.multiply(layerLocalTransform); - FloatRect layerRect(-0.5 * layer->bounds().width(), -0.5 * layer->bounds().height(), layer->bounds().width(), layer->bounds().height()); + FloatRect layerRect(-0.5 * drawLayer->bounds().width(), -0.5 * drawLayer->bounds().height(), drawLayer->bounds().width(), drawLayer->bounds().height()); IntRect transformedLayerRect; // The layer and its descendants render on a new RenderSurface if any of @@ -498,12 +548,11 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay // If a layer preserves-3d then we don't create a RenderSurface for it to avoid flattening // out its children. The opacity value of the children layers is multiplied by the opacity // of their parent. - bool useSurfaceForClipping = layer->masksToBounds() && !isScaleOrTranslation(combinedTransform); - bool useSurfaceForOpacity = layer->opacity() != 1 && !layer->preserves3D(); - bool useSurfaceForMasking = layer->maskDrawLayer(); - bool useSurfaceForReflection = layer->replicaLayer(); - if (((useSurfaceForClipping || useSurfaceForOpacity) && layer->descendantsDrawContent()) - || useSurfaceForMasking || useSurfaceForReflection) { + bool useSurfaceForClipping = drawLayer->masksToBounds() && !isScaleOrTranslation(combinedTransform); + bool useSurfaceForOpacity = drawLayer->opacity() != 1 && !drawLayer->preserves3D(); + bool useSurfaceForMasking = drawLayer->maskLayer(); + bool useSurfaceForReflection = drawLayer->replicaLayer(); + if (useSurfaceForMasking || useSurfaceForReflection || ((useSurfaceForClipping || useSurfaceForOpacity) && drawLayer->descendantsDrawsContent())) { RenderSurfaceChromium* renderSurface = drawLayer->renderSurface(); if (!renderSurface) renderSurface = drawLayer->createRenderSurface(); @@ -516,15 +565,15 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay transformedLayerRect = IntRect(0, 0, bounds.width(), bounds.height()); // Layer's opacity will be applied when drawing the render surface. - renderSurface->m_drawOpacity = layer->opacity(); - if (layer->superlayer() && layer->superlayer()->preserves3D()) + renderSurface->m_drawOpacity = drawLayer->opacity(); + if (drawLayer->superlayer() && drawLayer->superlayer()->preserves3D()) renderSurface->m_drawOpacity *= drawLayer->superlayer()->drawOpacity(); drawLayer->setDrawOpacity(1); TransformationMatrix layerOriginTransform = combinedTransform; layerOriginTransform.translate3d(-0.5 * bounds.width(), -0.5 * bounds.height(), 0); renderSurface->m_originTransform = layerOriginTransform; - if (layerOriginTransform.isInvertible() && layer->superlayer()) { + if (layerOriginTransform.isInvertible() && drawLayer->superlayer()) { TransformationMatrix parentToLayer = layerOriginTransform.inverse(); drawLayer->setScissorRect(parentToLayer.mapRect(drawLayer->superlayer()->scissorRect())); @@ -538,17 +587,14 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay renderSurface->m_layerList.clear(); - if (layer->maskDrawLayer()) { - renderSurface->m_maskLayer = layer->maskDrawLayer(); - layer->maskDrawLayer()->setLayerRenderer(this); - layer->maskDrawLayer()->setTargetRenderSurface(renderSurface); + if (drawLayer->maskLayer()) { + renderSurface->m_maskLayer = drawLayer->maskLayer(); + drawLayer->maskLayer()->setTargetRenderSurface(renderSurface); } else renderSurface->m_maskLayer = 0; - if (layer->replicaLayer() && layer->replicaLayer()->maskDrawLayer()) { - layer->replicaLayer()->maskDrawLayer()->setLayerRenderer(this); - layer->replicaLayer()->maskDrawLayer()->setTargetRenderSurface(renderSurface); - } + if (drawLayer->replicaLayer() && drawLayer->replicaLayer()->maskLayer()) + drawLayer->replicaLayer()->maskLayer()->setTargetRenderSurface(renderSurface); renderSurfaceLayerList.append(drawLayer); } else { @@ -556,10 +602,10 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay drawLayer->setDrawTransform(combinedTransform); transformedLayerRect = enclosingIntRect(drawLayer->drawTransform().mapRect(layerRect)); - drawLayer->setDrawOpacity(layer->opacity()); + drawLayer->setDrawOpacity(drawLayer->opacity()); - if (layer->superlayer()) { - if (layer->superlayer()->preserves3D()) + if (drawLayer->superlayer()) { + if (drawLayer->superlayer()->preserves3D()) drawLayer->setDrawOpacity(drawLayer->drawOpacity() * drawLayer->superlayer()->drawOpacity()); // Layers inherit the scissor rect from their superlayer. @@ -571,7 +617,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay if (layer != m_rootLayer) drawLayer->clearRenderSurface(); - if (layer->masksToBounds()) { + if (drawLayer->masksToBounds()) { IntRect scissor = drawLayer->scissorRect(); scissor.intersect(transformedLayerRect); drawLayer->setScissorRect(scissor); @@ -581,7 +627,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay if (drawLayer->renderSurface()) drawLayer->setTargetRenderSurface(drawLayer->renderSurface()); else { - ASSERT(layer->superlayer()); + ASSERT(drawLayer->superlayer()); drawLayer->setTargetRenderSurface(drawLayer->superlayer()->targetRenderSurface()); } @@ -595,7 +641,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay TransformationMatrix sublayerMatrix = drawLayer->drawTransform(); // Flatten to 2D if the layer doesn't preserve 3D. - if (!layer->preserves3D()) { + if (!drawLayer->preserves3D()) { sublayerMatrix.setM13(0); sublayerMatrix.setM23(0); sublayerMatrix.setM31(0); @@ -606,7 +652,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay } // Apply the sublayer transform at the center of the layer. - sublayerMatrix.multiply(layer->sublayerTransform()); + sublayerMatrix.multiply(drawLayer->sublayerTransform()); // The origin of the sublayers is the top left corner of the layer, not the // center. The matrix passed down to the sublayers is therefore: @@ -619,6 +665,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); for (size_t i = 0; i < sublayers.size(); ++i) { + sublayers[i]->createCCLayerImplIfNeeded(); CCLayerImpl* sublayer = sublayers[i]->ccLayerImpl(); updatePropertiesAndRenderSurfaces(sublayers[i].get(), sublayerMatrix, renderSurfaceLayerList, descendants); @@ -635,7 +682,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay } } - if (layer->masksToBounds() || useSurfaceForMasking) { + if (drawLayer->masksToBounds() || useSurfaceForMasking) { IntRect drawableContentRect = drawLayer->drawableContentRect(); drawableContentRect.intersect(transformedLayerRect); drawLayer->setDrawableContentRect(drawableContentRect); @@ -651,7 +698,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay // Don't clip if the layer is reflected as the reflection shouldn't be // clipped. - if (!layer->replicaLayer()) { + if (!drawLayer->replicaLayer()) { renderSurface->m_contentRect.intersect(drawLayer->scissorRect()); FloatPoint clippedSurfaceCenter = renderSurface->contentRectCenter(); centerOffsetDueToClipping = clippedSurfaceCenter - surfaceCenter; @@ -675,10 +722,10 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay // Compute the transformation matrix used to draw the replica of the render // surface. - if (layer->replicaLayer()) { + if (drawLayer->replicaLayer()) { renderSurface->m_replicaDrawTransform = renderSurface->m_originTransform; - renderSurface->m_replicaDrawTransform.translate3d(layer->replicaLayer()->position().x(), layer->replicaLayer()->position().y(), 0); - renderSurface->m_replicaDrawTransform.multiply(layer->replicaLayer()->transform()); + renderSurface->m_replicaDrawTransform.translate3d(drawLayer->replicaLayer()->position().x(), drawLayer->replicaLayer()->position().y(), 0); + renderSurface->m_replicaDrawTransform.multiply(drawLayer->replicaLayer()->transform()); renderSurface->m_replicaDrawTransform.translate3d(surfaceCenter.x() - anchorPoint.x() * bounds.width(), surfaceCenter.y() - anchorPoint.y() * bounds.height(), 0); } } @@ -686,8 +733,8 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay // Compute the depth value of the center of the layer which will be used when // sorting the layers for the preserves-3d property. const TransformationMatrix& layerDrawMatrix = drawLayer->renderSurface() ? drawLayer->renderSurface()->m_drawTransform : drawLayer->drawTransform(); - if (layer->superlayer()) { - if (!layer->superlayer()->preserves3D()) + if (drawLayer->superlayer()) { + if (!drawLayer->superlayer()->preserves3D()) drawLayer->setDrawDepth(drawLayer->superlayer()->drawDepth()); else drawLayer->setDrawDepth(layerDrawMatrix.m43()); @@ -697,24 +744,50 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay // If preserves-3d then sort all the descendants by the Z coordinate of their // center. If the preserves-3d property is also set on the superlayer then // skip the sorting as the superlayer will sort all the descendants anyway. - if (layer->preserves3D() && (!layer->superlayer() || !layer->superlayer()->preserves3D())) + if (drawLayer->preserves3D() && (!drawLayer->superlayer() || !drawLayer->superlayer()->preserves3D())) std::stable_sort(&descendants.at(thisLayerIndex), descendants.end(), compareLayerZ); } -void LayerRendererChromium::updateContentsRecursive(LayerChromium* layer) +void LayerRendererChromium::paintContentsRecursive(LayerChromium* layer) { const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); for (size_t i = 0; i < sublayers.size(); ++i) - updateContentsRecursive(sublayers[i].get()); + paintContentsRecursive(sublayers[i].get()); + + if (layer->bounds().isEmpty()) + return; if (layer->drawsContent()) - layer->updateContentsIfDirty(); + layer->paintContentsIfDirty(); if (layer->maskLayer() && layer->maskLayer()->drawsContent()) - layer->maskLayer()->updateContentsIfDirty(); + layer->maskLayer()->paintContentsIfDirty(); if (layer->replicaLayer() && layer->replicaLayer()->drawsContent()) - layer->replicaLayer()->updateContentsIfDirty(); + layer->replicaLayer()->paintContentsIfDirty(); if (layer->replicaLayer() && layer->replicaLayer()->maskLayer() && layer->replicaLayer()->maskLayer()->drawsContent()) - layer->replicaLayer()->maskLayer()->updateContentsIfDirty(); + layer->replicaLayer()->maskLayer()->paintContentsIfDirty(); +} + +void LayerRendererChromium::updateCompositorResourcesRecursive(LayerChromium* layer) +{ + const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); + for (size_t i = 0; i < sublayers.size(); ++i) + updateCompositorResourcesRecursive(sublayers[i].get()); + + if (layer->bounds().isEmpty()) + return; + + CCLayerImpl* drawLayer = layer->ccLayerImpl(); + + if (drawLayer->drawsContent()) + drawLayer->updateCompositorResources(); + if (drawLayer->maskLayer() && drawLayer->maskLayer()->drawsContent()) + drawLayer->maskLayer()->updateCompositorResources(); + if (drawLayer->replicaLayer() && drawLayer->replicaLayer()->drawsContent()) + drawLayer->replicaLayer()->updateCompositorResources(); + if (drawLayer->replicaLayer() && drawLayer->replicaLayer()->maskLayer() && drawLayer->replicaLayer()->maskLayer()->drawsContent()) + drawLayer->replicaLayer()->maskLayer()->updateCompositorResources(); + + layer->pushPropertiesTo(drawLayer); } void LayerRendererChromium::setCompositeOffscreen(bool compositeOffscreen) @@ -788,22 +861,38 @@ void LayerRendererChromium::drawLayer(CCLayerImpl* layer, RenderSurfaceChromium* return; } - if (layer->bounds().isEmpty()) + if (layer->bounds().isEmpty()) { + layer->unreserveContentsTexture(); return; + } setScissorToRect(layer->scissorRect()); // Check if the layer falls within the visible bounds of the page. IntRect layerRect = layer->getDrawRect(); bool isLayerVisible = layer->scissorRect().intersects(layerRect); - if (!isLayerVisible) + if (!isLayerVisible) { + layer->unreserveContentsTexture(); return; + } // FIXME: Need to take into account the commulative render surface transforms all the way from // the default render surface in order to determine visibility. - TransformationMatrix combinedDrawMatrix = (layer->renderSurface() ? layer->renderSurface()->drawTransform().multiply(layer->drawTransform()) : layer->drawTransform()); - if (!layer->doubleSided() && combinedDrawMatrix.m33() < 0) - return; + TransformationMatrix combinedDrawMatrix = (layer->targetRenderSurface() ? layer->targetRenderSurface()->drawTransform().multiply(layer->drawTransform()) : layer->drawTransform()); + + if (!layer->doubleSided()) { + FloatRect layerRect(FloatPoint(0, 0), FloatSize(layer->bounds())); + FloatQuad mappedLayer = combinedDrawMatrix.mapQuad(FloatQuad(layerRect)); + FloatSize horizontalDir = mappedLayer.p2() - mappedLayer.p1(); + FloatSize verticalDir = mappedLayer.p4() - mappedLayer.p1(); + FloatPoint3D xAxis(horizontalDir.width(), horizontalDir.height(), 0); + FloatPoint3D yAxis(verticalDir.width(), verticalDir.height(), 0); + FloatPoint3D zAxis = xAxis.cross(yAxis); + if (zAxis.z() < 0) { + layer->unreserveContentsTexture(); + return; + } + } if (layer->drawsContent()) layer->draw(); @@ -880,10 +969,10 @@ bool LayerRendererChromium::initializeSharedObjects() m_sharedGeometry = adoptPtr(new GeometryBinding(m_context.get())); m_borderProgram = adoptPtr(new LayerChromium::BorderProgram(m_context.get())); m_contentLayerProgram = adoptPtr(new ContentLayerChromium::Program(m_context.get())); - m_canvasLayerProgram = adoptPtr(new CanvasLayerChromium::Program(m_context.get())); - m_videoLayerRGBAProgram = adoptPtr(new VideoLayerChromium::RGBAProgram(m_context.get())); - m_videoLayerYUVProgram = adoptPtr(new VideoLayerChromium::YUVProgram(m_context.get())); - m_pluginLayerProgram = adoptPtr(new PluginLayerChromium::Program(m_context.get())); + m_canvasLayerProgram = adoptPtr(new CCCanvasLayerImpl::Program(m_context.get())); + m_videoLayerRGBAProgram = adoptPtr(new CCVideoLayerImpl::RGBAProgram(m_context.get())); + m_videoLayerYUVProgram = adoptPtr(new CCVideoLayerImpl::YUVProgram(m_context.get())); + m_pluginLayerProgram = adoptPtr(new CCPluginLayerImpl::Program(m_context.get())); m_renderSurfaceProgram = adoptPtr(new RenderSurfaceChromium::Program(m_context.get())); m_renderSurfaceMaskProgram = adoptPtr(new RenderSurfaceChromium::MaskProgram(m_context.get())); m_tilerProgram = adoptPtr(new LayerTilerChromium::Program(m_context.get())); @@ -920,7 +1009,7 @@ void LayerRendererChromium::cleanupSharedObjects() GLC(m_context.get(), m_context->deleteFramebuffer(m_offscreenFramebufferId)); // Clear tilers before the texture manager, as they have references to textures. - m_rootLayerTiler.clear(); + m_rootLayerContentTiler.clear(); m_horizontalScrollbarTiler.clear(); m_verticalScrollbarTiler.clear(); diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h index 7e8850a..667ede2 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h +++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h @@ -34,16 +34,17 @@ #if USE(ACCELERATED_COMPOSITING) -#include "CanvasLayerChromium.h" #include "ContentLayerChromium.h" #include "IntRect.h" #include "LayerChromium.h" #include "LayerTilerChromium.h" -#include "PluginLayerChromium.h" #include "RenderSurfaceChromium.h" #include "SkBitmap.h" #include "VideoLayerChromium.h" +#include "cc/CCCanvasLayerImpl.h" #include "cc/CCHeadsUpDisplay.h" +#include "cc/CCPluginLayerImpl.h" +#include "cc/CCVideoLayerImpl.h" #include <wtf/HashMap.h> #include <wtf/Noncopyable.h> #include <wtf/PassOwnPtr.h> @@ -66,17 +67,18 @@ class CCHeadsUpDisplay; // Class that handles drawing of composited render layers using GL. class LayerRendererChromium : public RefCounted<LayerRendererChromium> { public: - static PassRefPtr<LayerRendererChromium> create(PassRefPtr<GraphicsContext3D> graphicsContext3D); + static PassRefPtr<LayerRendererChromium> create(PassRefPtr<GraphicsContext3D>, PassOwnPtr<TilePaintInterface> contentPaint, PassOwnPtr<TilePaintInterface> scrollbarPaint); ~LayerRendererChromium(); GraphicsContext3D* context(); - void invalidateRootLayerRect(const IntRect& dirtyRect, const IntRect& visibleRect, const IntRect& contentRect); + void invalidateRootLayerRect(const IntRect& dirtyRect); + + void setViewport(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition); // updates and draws the current layers onto the backbuffer - void updateAndDrawLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition, - TilePaintInterface&, TilePaintInterface& scrollbarPaint); + void updateAndDrawLayers(); // waits for rendering to finish void finish(); @@ -84,7 +86,7 @@ public: // puts backbuffer onscreen void present(); - IntSize visibleRectSize() const { return m_visibleRect.size(); } + IntSize viewportSize() const { return m_viewportVisibleRect.size(); } void setRootLayer(PassRefPtr<LayerChromium> layer); LayerChromium* rootLayer() { return m_rootLayer.get(); } @@ -94,8 +96,6 @@ public: void setCompositeOffscreen(bool); bool isCompositingOffscreen() const { return m_compositeOffscreen; } - LayerTexture* getOffscreenLayerTexture(); - void copyOffscreenTextureToDisplay(); unsigned createLayerTexture(); void deleteLayerTexture(unsigned); @@ -111,13 +111,13 @@ public: const GeometryBinding* sharedGeometry() const { return m_sharedGeometry.get(); } const LayerChromium::BorderProgram* borderProgram() const { return m_borderProgram.get(); } const ContentLayerChromium::Program* contentLayerProgram() const { return m_contentLayerProgram.get(); } - const CanvasLayerChromium::Program* canvasLayerProgram() const { return m_canvasLayerProgram.get(); } - const VideoLayerChromium::RGBAProgram* videoLayerRGBAProgram() const { return m_videoLayerRGBAProgram.get(); } - const VideoLayerChromium::YUVProgram* videoLayerYUVProgram() const { return m_videoLayerYUVProgram.get(); } - const PluginLayerChromium::Program* pluginLayerProgram() const { return m_pluginLayerProgram.get(); } const RenderSurfaceChromium::Program* renderSurfaceProgram() const { return m_renderSurfaceProgram.get(); } const RenderSurfaceChromium::MaskProgram* renderSurfaceMaskProgram() const { return m_renderSurfaceMaskProgram.get(); } const LayerTilerChromium::Program* tilerProgram() const { return m_tilerProgram.get(); } + const CCCanvasLayerImpl::Program* canvasLayerProgram() const { return m_canvasLayerProgram.get(); } + const CCPluginLayerImpl::Program* pluginLayerProgram() const { return m_pluginLayerProgram.get(); } + const CCVideoLayerImpl::RGBAProgram* videoLayerRGBAProgram() const { return m_videoLayerRGBAProgram.get(); } + const CCVideoLayerImpl::YUVProgram* videoLayerYUVProgram() const { return m_videoLayerYUVProgram.get(); } void resizeOnscreenContent(const IntSize&); @@ -132,19 +132,21 @@ public: String layerTreeAsText() const; private: - explicit LayerRendererChromium(PassRefPtr<GraphicsContext3D> graphicsContext3D); + explicit LayerRendererChromium(PassRefPtr<GraphicsContext3D>, PassOwnPtr<TilePaintInterface> contentPaint, PassOwnPtr<TilePaintInterface> scrollbarPaint); - void updateLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition, - Vector<CCLayerImpl*>& renderSurfaceLayerList); - void updateRootLayerContents(TilePaintInterface&, const IntRect& visibleRect); - void updateRootLayerScrollbars(TilePaintInterface& scrollbarPaint, const IntRect& visibleRect, const IntRect& contentRect); + void updateLayers(Vector<CCLayerImpl*>& renderSurfaceLayerList); + void updateRootLayerContents(); + void updateRootLayerScrollbars(); void updatePropertiesAndRenderSurfaces(LayerChromium*, const TransformationMatrix& parentMatrix, Vector<CCLayerImpl*>& renderSurfaceLayerList, Vector<CCLayerImpl*>& layerList); - void updateContentsRecursive(LayerChromium*); + void paintContentsRecursive(LayerChromium*); + void updateCompositorResourcesRecursive(LayerChromium*); void drawLayers(const Vector<CCLayerImpl*>& renderSurfaceLayerList); void drawLayer(CCLayerImpl*, RenderSurfaceChromium*); void drawRootLayer(); + LayerTexture* getOffscreenLayerTexture(); + void copyOffscreenTextureToDisplay(); bool isLayerVisible(LayerChromium*, const TransformationMatrix&, const IntRect& visibleRect); @@ -161,19 +163,22 @@ private: bool initializeSharedObjects(); void cleanupSharedObjects(); - static IntRect verticalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect); - static IntRect horizontalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect); + IntRect verticalScrollbarRect() const; + IntRect horizontalScrollbarRect() const; - IntRect m_visibleRect; + IntRect m_viewportVisibleRect; + IntRect m_viewportContentRect; + IntPoint m_viewportScrollPosition; TransformationMatrix m_projectionMatrix; RefPtr<LayerChromium> m_rootLayer; - OwnPtr<LayerTilerChromium> m_rootLayerTiler; + OwnPtr<TilePaintInterface> m_rootLayerContentPaint; + OwnPtr<TilePaintInterface> m_rootLayerScrollbarPaint; + OwnPtr<LayerTilerChromium> m_rootLayerContentTiler; OwnPtr<LayerTilerChromium> m_horizontalScrollbarTiler; OwnPtr<LayerTilerChromium> m_verticalScrollbarTiler; - IntPoint m_scrollPosition; bool m_hardwareCompositing; unsigned m_currentShader; @@ -202,13 +207,13 @@ private: OwnPtr<GeometryBinding> m_sharedGeometry; OwnPtr<LayerChromium::BorderProgram> m_borderProgram; OwnPtr<ContentLayerChromium::Program> m_contentLayerProgram; - OwnPtr<CanvasLayerChromium::Program> m_canvasLayerProgram; - OwnPtr<VideoLayerChromium::RGBAProgram> m_videoLayerRGBAProgram; - OwnPtr<VideoLayerChromium::YUVProgram> m_videoLayerYUVProgram; - OwnPtr<PluginLayerChromium::Program> m_pluginLayerProgram; OwnPtr<RenderSurfaceChromium::Program> m_renderSurfaceProgram; OwnPtr<RenderSurfaceChromium::MaskProgram> m_renderSurfaceMaskProgram; OwnPtr<LayerTilerChromium::Program> m_tilerProgram; + OwnPtr<CCCanvasLayerImpl::Program> m_canvasLayerProgram; + OwnPtr<CCVideoLayerImpl::RGBAProgram> m_videoLayerRGBAProgram; + OwnPtr<CCVideoLayerImpl::YUVProgram> m_videoLayerYUVProgram; + OwnPtr<CCPluginLayerImpl::Program> m_pluginLayerProgram; OwnPtr<TextureManager> m_textureManager; diff --git a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp index 86592a6..bc37201 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp @@ -34,6 +34,7 @@ #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" #include "LayerTexture.h" +#include "TraceEvent.h" #include <wtf/PassOwnArrayPtr.h> @@ -84,58 +85,50 @@ void LayerTilerChromium::reset() { m_tiles.clear(); m_unusedTiles.clear(); - m_tilingData.setTotalSize(0, 0); - m_lastUpdateLayerRect = IntRect(); } LayerTilerChromium::Tile* LayerTilerChromium::createTile(int i, int j) { - const int index = tileIndex(i, j); - ASSERT(!m_tiles[index]); + ASSERT(!tileAt(i, j)); + RefPtr<Tile> tile; if (m_unusedTiles.size() > 0) { - m_tiles[index] = m_unusedTiles.last().release(); + tile = m_unusedTiles.last().release(); m_unusedTiles.removeLast(); + ASSERT(tile->refCount() == 1); } else { GraphicsContext3D* context = layerRendererContext(); TextureManager* manager = layerRenderer()->textureManager(); - OwnPtr<Tile> tile = adoptPtr(new Tile(LayerTexture::create(context, manager))); - m_tiles[index] = tile.release(); + tile = adoptRef(new Tile(LayerTexture::create(context, manager))); } + m_tiles.add(make_pair(i, j), tile); + + tile->moveTo(i, j); + tile->m_dirtyLayerRect = tileLayerRect(tile.get()); - m_tiles[index]->m_dirtyLayerRect = tileLayerRect(i, j); - return m_tiles[index].get(); + return tile.get(); } -void LayerTilerChromium::invalidateTiles(const IntRect& oldLayerRect, const IntRect& newLayerRect) +void LayerTilerChromium::invalidateTiles(const IntRect& contentRect) { if (!m_tiles.size()) return; - IntRect oldContentRect = layerRectToContentRect(oldLayerRect); - int oldLeft, oldTop, oldRight, oldBottom; - contentRectToTileIndices(oldContentRect, oldLeft, oldTop, oldRight, oldBottom); - - IntRect newContentRect = layerRectToContentRect(newLayerRect); - int newLeft, newTop, newRight, newBottom; - contentRectToTileIndices(newContentRect, newLeft, newTop, newRight, newBottom); - - // Iterating through just the old tile indices is an optimization to avoid - // iterating through the entire m_tiles array. - for (int j = oldTop; j <= oldBottom; ++j) { - for (int i = oldLeft; i <= oldRight; ++i) { - if (i >= newLeft && i <= newRight && j >= newTop && j <= newBottom) - continue; - - const int index = tileIndex(i, j); - if (m_tiles[index]) - m_unusedTiles.append(m_tiles[index].release()); - } + Vector<TileMapKey> removeKeys; + for (TileMap::iterator iter = m_tiles.begin(); iter != m_tiles.end(); ++iter) { + Tile* tile = iter->second.get(); + IntRect tileRect = tileContentRect(tile); + if (tileRect.intersects(contentRect)) + continue; + removeKeys.append(iter->first); } + + for (size_t i = 0; i < removeKeys.size(); ++i) + m_unusedTiles.append(m_tiles.take(removeKeys[i])); } -void LayerTilerChromium::contentRectToTileIndices(const IntRect& contentRect, int &left, int &top, int &right, int &bottom) const +void LayerTilerChromium::contentRectToTileIndices(const IntRect& contentRect, int& left, int& top, int& right, int& bottom) const { const IntRect layerRect = contentRectToLayerRect(contentRect); @@ -163,36 +156,28 @@ IntRect LayerTilerChromium::layerRectToContentRect(const IntRect& layerRect) con return contentRect; } -int LayerTilerChromium::tileIndex(int i, int j) const +LayerTilerChromium::Tile* LayerTilerChromium::tileAt(int i, int j) const { - return m_tilingData.tileIndex(i, j); + Tile* tile = m_tiles.get(make_pair(i, j)).get(); + ASSERT(!tile || tile->refCount() == 1); + return tile; } -IntRect LayerTilerChromium::tileContentRect(int i, int j) const +IntRect LayerTilerChromium::tileContentRect(const Tile* tile) const { - IntRect contentRect = tileLayerRect(i, j); + IntRect contentRect = tileLayerRect(tile); contentRect.move(m_layerPosition.x(), m_layerPosition.y()); return contentRect; } -IntRect LayerTilerChromium::tileLayerRect(int i, int j) const +IntRect LayerTilerChromium::tileLayerRect(const Tile* tile) const { - const int index = m_tilingData.tileIndex(i, j); + const int index = m_tilingData.tileIndex(tile->i(), tile->j()); IntRect layerRect = m_tilingData.tileBoundsWithBorder(index); layerRect.setSize(m_tileSize); return layerRect; } -IntSize LayerTilerChromium::layerSize() const -{ - return IntSize(m_tilingData.totalSizeX(), m_tilingData.totalSizeY()); -} - -IntSize LayerTilerChromium::layerTileSize() const -{ - return IntSize(m_tilingData.numTilesX(), m_tilingData.numTilesY()); -} - void LayerTilerChromium::invalidateRect(const IntRect& contentRect) { if (contentRect.isEmpty()) @@ -202,16 +187,16 @@ void LayerTilerChromium::invalidateRect(const IntRect& contentRect) // Dirty rects are always in layer space, as the layer could be repositioned // after invalidation. - IntRect layerRect = contentRectToLayerRect(contentRect); + const IntRect layerRect = contentRectToLayerRect(contentRect); int left, top, right, bottom; contentRectToTileIndices(contentRect, left, top, right, bottom); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { - Tile* tile = m_tiles[tileIndex(i, j)].get(); + Tile* tile = tileAt(i, j); if (!tile) continue; - IntRect bound = tileLayerRect(i, j); + IntRect bound = tileLayerRect(tile); bound.intersect(layerRect); tile->m_dirtyLayerRect.unite(bound); } @@ -220,14 +205,13 @@ void LayerTilerChromium::invalidateRect(const IntRect& contentRect) void LayerTilerChromium::invalidateEntireLayer() { - for (size_t i = 0; i < m_tiles.size(); ++i) { - if (m_tiles[i]) - m_unusedTiles.append(m_tiles[i].release()); + for (TileMap::iterator iter = m_tiles.begin(); iter != m_tiles.end(); ++iter) { + ASSERT(iter->second->refCount() == 1); + m_unusedTiles.append(iter->second.release()); } m_tiles.clear(); m_tilingData.setTotalSize(0, 0); - m_lastUpdateLayerRect = IntRect(); } void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& contentRect) @@ -237,10 +221,7 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont // Invalidate old tiles that were previously used but aren't in use this // frame so that they can get reused for new tiles. - IntRect layerRect = contentRectToLayerRect(contentRect); - invalidateTiles(m_lastUpdateLayerRect, layerRect); - m_lastUpdateLayerRect = layerRect; - + invalidateTiles(contentRect); growLayerToContain(contentRect); // Create tiles as needed, expanding a dirty rect to contain all @@ -250,11 +231,11 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont contentRectToTileIndices(contentRect, left, top, right, bottom); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { - Tile* tile = m_tiles[tileIndex(i, j)].get(); + Tile* tile = tileAt(i, j); if (!tile) tile = createTile(i, j); if (!tile->texture()->isValid(m_tileSize, GraphicsContext3D::RGBA)) - tile->m_dirtyLayerRect = tileLayerRect(i, j); + tile->m_dirtyLayerRect = tileLayerRect(tile); dirtyLayerRect.unite(tile->m_dirtyLayerRect); } } @@ -267,10 +248,16 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont m_canvas.resize(paintRect.size()); PlatformCanvas::Painter canvasPainter(&m_canvas); canvasPainter.context()->translate(-paintRect.x(), -paintRect.y()); - painter.paint(*canvasPainter.context(), paintRect); + { + TRACE_EVENT("LayerTilerChromium::update::paint", this, 0); + painter.paint(*canvasPainter.context(), paintRect); + } PlatformCanvas::AutoLocker locker(&m_canvas); - updateFromPixels(paintRect, locker.pixels()); + { + TRACE_EVENT("LayerTilerChromium::updateFromPixels", this, 0); + updateFromPixels(paintRect, locker.pixels()); + } } void LayerTilerChromium::updateFromPixels(const IntRect& paintRect, const uint8_t* paintPixels) @@ -285,14 +272,14 @@ void LayerTilerChromium::updateFromPixels(const IntRect& paintRect, const uint8_ contentRectToTileIndices(paintRect, left, top, right, bottom); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { - Tile* tile = m_tiles[tileIndex(i, j)].get(); + Tile* tile = tileAt(i, j); if (!tile) CRASH(); if (!tile->dirty()) continue; // Calculate page-space rectangle to copy from. - IntRect sourceRect = tileContentRect(i, j); + IntRect sourceRect = tileContentRect(tile); const IntPoint anchor = sourceRect.location(); sourceRect.intersect(layerRectToContentRect(tile->m_dirtyLayerRect)); if (sourceRect.isEmpty()) @@ -366,8 +353,7 @@ void LayerTilerChromium::draw(const IntRect& contentRect) contentRectToTileIndices(contentRect, left, top, right, bottom); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { - const int index = tileIndex(i, j); - Tile* tile = m_tiles[index].get(); + Tile* tile = tileAt(i, j); ASSERT(tile); tile->texture()->bindTexture(); @@ -376,11 +362,11 @@ void LayerTilerChromium::draw(const IntRect& contentRect) // Don't use tileContentRect here, as that contains the full // rect with border texels which shouldn't be drawn. - IntRect tileRect = m_tilingData.tileBounds(index); + IntRect tileRect = m_tilingData.tileBounds(m_tilingData.tileIndex(tile->i(), tile->j())); tileRect.move(m_layerPosition.x(), m_layerPosition.y()); tileMatrix.translate3d(tileRect.x() - contentRect.x() + tileRect.width() / 2.0, tileRect.y() - contentRect.y() + tileRect.height() / 2.0, 0); - IntPoint texOffset = m_tilingData.textureOffset(i, j); + IntPoint texOffset = m_tilingData.textureOffset(tile->i(), tile->j()); float tileWidth = static_cast<float>(m_tileSize.width()); float tileHeight = static_cast<float>(m_tileSize.height()); float texTranslateX = texOffset.x() / tileWidth; @@ -395,37 +381,15 @@ void LayerTilerChromium::draw(const IntRect& contentRect) } } -void LayerTilerChromium::resizeLayer(const IntSize& size) -{ - if (layerSize() == size) - return; - - const IntSize oldTileSize = layerTileSize(); - m_tilingData.setTotalSize(size.width(), size.height()); - const IntSize newTileSize = layerTileSize(); - - if (oldTileSize == newTileSize) - return; - - if (newTileSize.height() && (newTileSize.width() > INT_MAX / newTileSize.height())) - CRASH(); - - Vector<OwnPtr<Tile> > newTiles; - newTiles.resize(newTileSize.width() * newTileSize.height()); - for (int j = 0; j < oldTileSize.height(); ++j) - for (int i = 0; i < oldTileSize.width(); ++i) - newTiles[i + j * newTileSize.width()].swap(m_tiles[i + j * oldTileSize.width()]); - m_tiles.swap(newTiles); -} - void LayerTilerChromium::growLayerToContain(const IntRect& contentRect) { // Grow the tile array to contain this content rect. IntRect layerRect = contentRectToLayerRect(contentRect); IntSize rectSize = IntSize(layerRect.maxX(), layerRect.maxY()); - IntSize newSize = rectSize.expandedTo(layerSize()); - resizeLayer(newSize); + IntSize oldLayerSize(m_tilingData.totalSizeX(), m_tilingData.totalSizeY()); + IntSize newSize = rectSize.expandedTo(oldLayerSize); + m_tilingData.setTotalSize(newSize.width(), newSize.height()); } void LayerTilerChromium::drawTexturedQuad(GraphicsContext3D* context, const TransformationMatrix& projectionMatrix, const TransformationMatrix& drawMatrix, diff --git a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h index bdb35a5..2f356e4 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h @@ -33,7 +33,9 @@ #include "LayerTexture.h" #include "PlatformCanvas.h" #include "TilingData.h" +#include <wtf/HashTraits.h> #include <wtf/OwnArrayPtr.h> +#include <wtf/RefCounted.h> namespace WebCore { @@ -70,20 +72,26 @@ public: private: LayerTilerChromium(LayerRendererChromium*, const IntSize& tileSize, BorderTexelOption); - class Tile { + class Tile : public RefCounted<Tile> { WTF_MAKE_NONCOPYABLE(Tile); public: - explicit Tile(PassOwnPtr<LayerTexture> tex) : m_tex(tex) {} + explicit Tile(PassOwnPtr<LayerTexture> tex) : m_tex(tex), m_i(-1), m_j(-1) {} LayerTexture* texture() { return m_tex.get(); } bool dirty() const { return !m_dirtyLayerRect.isEmpty(); } void clearDirty() { m_dirtyLayerRect = IntRect(); } + int i() const { return m_i; } + int j() const { return m_j; } + void moveTo(int i, int j) { m_i = i; m_j = j; } + // Layer-space dirty rectangle that needs to be repainted. IntRect m_dirtyLayerRect; private: OwnPtr<LayerTexture> m_tex; + int m_i; + int m_j; }; void drawTexturedQuad(GraphicsContext3D*, const TransformationMatrix& projectionMatrix, const TransformationMatrix& drawMatrix, @@ -92,40 +100,45 @@ private: float texScaleX, float texScaleY, const LayerTilerChromium::Program*); - void resizeLayer(const IntSize& size); // Grow layer size to contain this rectangle. void growLayerToContain(const IntRect& contentRect); LayerRendererChromium* layerRenderer() const { return m_layerRenderer; } GraphicsContext3D* layerRendererContext() const; Tile* createTile(int i, int j); - // Invalidate any tiles which do not intersect with the newLayerRect. - void invalidateTiles(const IntRect& oldLayerRect, const IntRect& newLayerRect); + // Invalidate any tiles which do not intersect with the contentRect + void invalidateTiles(const IntRect& contentRect); void reset(); void contentRectToTileIndices(const IntRect& contentRect, int &left, int &top, int &right, int &bottom) const; IntRect contentRectToLayerRect(const IntRect& contentRect) const; IntRect layerRectToContentRect(const IntRect& layerRect) const; - // Returns the index into m_tiles for a given tile location. - int tileIndex(int i, int j) const; - // Returns the bounds in content space for a given tile location. - IntRect tileContentRect(int i, int j) const; - // Returns the bounds in layer space for a given tile location. - IntRect tileLayerRect(int i, int j) const; - - IntSize layerSize() const; - IntSize layerTileSize() const; + Tile* tileAt(int, int) const; + IntRect tileContentRect(const Tile*) const; + IntRect tileLayerRect(const Tile*) const; IntSize m_tileSize; - IntRect m_lastUpdateLayerRect; IntPoint m_layerPosition; bool m_skipsDraw; - // Logical 2D array of tiles (dimensions of m_layerTileSize) - Vector<OwnPtr<Tile> > m_tiles; - // Linear array of unused tiles. - Vector<OwnPtr<Tile> > m_unusedTiles; + // Default hash key traits for integers disallow 0 and -1 as a key, so + // use a custom hash trait which disallows -1 and -2 instead. + typedef std::pair<int, int> TileMapKey; + struct TileMapKeyTraits : HashTraits<TileMapKey> { + static const bool emptyValueIsZero = false; + static const bool needsDestruction = false; + static TileMapKey emptyValue() { return std::make_pair(-1, -1); } + static void constructDeletedValue(TileMapKey& slot) { slot = std::make_pair(-2, -2); } + static bool isDeletedValue(TileMapKey value) { return value.first == -2 && value.second == -2; } + }; + // FIXME: The mapped value in TileMap should really be an OwnPtr, as the + // refcount of a Tile should never be more than 1. However, HashMap + // doesn't easily support OwnPtr as a value. + typedef HashMap<TileMapKey, RefPtr<Tile>, DefaultHash<TileMapKey>::Hash, TileMapKeyTraits> TileMap; + TileMap m_tiles; + // Tightly packed set of unused tiles. + Vector<RefPtr<Tile> > m_unusedTiles; PlatformCanvas m_canvas; diff --git a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp index 5d595ad..3667fbb 100644 --- a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp @@ -29,10 +29,10 @@ #include "PluginLayerChromium.h" -#include "cc/CCLayerImpl.h" #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" -#include <GLES2/gl2.h> +#include "cc/CCLayerImpl.h" +#include "cc/CCPluginLayerImpl.h" namespace WebCore { @@ -43,40 +43,26 @@ PassRefPtr<PluginLayerChromium> PluginLayerChromium::create(GraphicsLayerChromiu PluginLayerChromium::PluginLayerChromium(GraphicsLayerChromium* owner) : LayerChromium(owner) + , m_textureId(0) { } -void PluginLayerChromium::setTextureId(unsigned id) +PassRefPtr<CCLayerImpl> PluginLayerChromium::createCCLayerImpl() { - m_textureId = id; + return CCPluginLayerImpl::create(this); } -void PluginLayerChromium::updateContentsIfDirty() +void PluginLayerChromium::setTextureId(unsigned id) { + m_textureId = id; } -void PluginLayerChromium::draw() +void PluginLayerChromium::pushPropertiesTo(CCLayerImpl* layer) { - ASSERT(layerRenderer()); - const PluginLayerChromium::Program* program = layerRenderer()->pluginLayerProgram(); - ASSERT(program && program->initialized()); - GraphicsContext3D* context = layerRendererContext(); - GLC(context, context->activeTexture(GL_TEXTURE0)); - GLC(context, context->bindTexture(GL_TEXTURE_2D, m_textureId)); - - // FIXME: setting the texture parameters every time is redundant. Move this code somewhere - // where it will only happen once per texture. - GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); - - layerRenderer()->useShader(program->program()); - GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); - drawTexturedQuad(context, layerRenderer()->projectionMatrix(), ccLayerImpl()->drawTransform(), - bounds().width(), bounds().height(), ccLayerImpl()->drawOpacity(), - program->vertexShader().matrixLocation(), - program->fragmentShader().alphaLocation()); + LayerChromium::pushPropertiesTo(layer); + + CCPluginLayerImpl* pluginLayer = static_cast<CCPluginLayerImpl*>(layer); + pluginLayer->setTextureId(m_textureId); } } diff --git a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h index 8d66f5f..852dc2e 100644 --- a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h @@ -38,18 +38,19 @@ class PluginLayerChromium : public LayerChromium { public: static PassRefPtr<PluginLayerChromium> create(GraphicsLayerChromium* owner = 0); virtual bool drawsContent() const { return true; } - virtual void updateContentsIfDirty(); - virtual void draw(); - + + virtual PassRefPtr<CCLayerImpl> createCCLayerImpl(); + void setTextureId(unsigned textureId); - - typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program; + unsigned textureId() const { return m_textureId; } + + virtual void pushPropertiesTo(CCLayerImpl*); protected: virtual const char* layerTypeAsString() const { return "PluginLayer"; } private: - PluginLayerChromium(GraphicsLayerChromium* owner); + explicit PluginLayerChromium(GraphicsLayerChromium* owner); unsigned m_textureId; }; diff --git a/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp b/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp index 49b3462..b7f447b 100644 --- a/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp @@ -248,7 +248,7 @@ FragmentShaderYUVVideo::FragmentShaderYUVVideo() , m_vTextureLocation(-1) , m_alphaLocation(-1) , m_ccMatrixLocation(-1) - , m_signAdjLocation(-1) + , m_yuvAdjLocation(-1) { } @@ -259,10 +259,10 @@ bool FragmentShaderYUVVideo::init(GraphicsContext3D* context, unsigned program) m_vTextureLocation = context->getUniformLocation(program, "v_texture"); m_alphaLocation = context->getUniformLocation(program, "alpha"); m_ccMatrixLocation = context->getUniformLocation(program, "cc_matrix"); - m_signAdjLocation = context->getUniformLocation(program, "adj"); + m_yuvAdjLocation = context->getUniformLocation(program, "yuv_adj"); return m_yTextureLocation != -1 && m_uTextureLocation != -1 && m_vTextureLocation != -1 - && m_alphaLocation != -1 && m_ccMatrixLocation != -1 && m_signAdjLocation != -1; + && m_alphaLocation != -1 && m_ccMatrixLocation != -1 && m_yuvAdjLocation != -1; } String FragmentShaderYUVVideo::getShaderString() const @@ -276,14 +276,15 @@ String FragmentShaderYUVVideo::getShaderString() const uniform sampler2D u_texture; uniform sampler2D v_texture; uniform float alpha; - uniform float adj; + uniform vec3 yuv_adj; uniform mat3 cc_matrix; void main() { - float y = texture2D(y_texture, y_texCoord).x; - float u = texture2D(u_texture, uv_texCoord).x - adj; - float v = texture2D(v_texture, uv_texCoord).x - adj; - vec3 rgb = cc_matrix * vec3(y, u, v); + float y_raw = texture2D(y_texture, y_texCoord).x; + float u_unsigned = texture2D(u_texture, uv_texCoord).x; + float v_unsigned = texture2D(v_texture, uv_texCoord).x; + vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj; + vec3 rgb = cc_matrix * yuv; gl_FragColor = vec4(rgb, float(1)) * alpha; } ); diff --git a/Source/WebCore/platform/graphics/chromium/ShaderChromium.h b/Source/WebCore/platform/graphics/chromium/ShaderChromium.h index 758c62b..3a3e175 100644 --- a/Source/WebCore/platform/graphics/chromium/ShaderChromium.h +++ b/Source/WebCore/platform/graphics/chromium/ShaderChromium.h @@ -158,7 +158,7 @@ public: int vTextureLocation() const { return m_vTextureLocation; } int alphaLocation() const { return m_alphaLocation; } int ccMatrixLocation() const { return m_ccMatrixLocation; } - int signAdjLocation() const { return m_signAdjLocation; } + int yuvAdjLocation() const { return m_yuvAdjLocation; } private: int m_yTextureLocation; @@ -166,7 +166,7 @@ private: int m_vTextureLocation; int m_alphaLocation; int m_ccMatrixLocation; - int m_signAdjLocation; + int m_yuvAdjLocation; }; class FragmentShaderColor { diff --git a/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp b/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp index 9423d1e..7cd47fe 100644 --- a/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp +++ b/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp @@ -113,13 +113,13 @@ void SimpleFontData::platformInit() m_fontMetrics.setXHeight(xHeight); m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap)); - if (m_orientation == Vertical) { + if (platformData().orientation() == Vertical && !isTextOrientationFallback()) { static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a'); static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G'); size_t vheaSize = SkFontHost::GetTableSize(fontID, vheaTag); size_t vorgSize = SkFontHost::GetTableSize(fontID, vorgTag); - if ((vheaSize <= 0) && (vorgSize <= 0)) - m_orientation = Horizontal; + if ((vheaSize > 0) || (vorgSize > 0)) + m_hasVerticalGlyphs = true; } // In WebKit/WebCore/platform/graphics/SimpleFontData.cpp, m_spaceWidth is diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp index 5d7a6e7..182e730 100644 --- a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp @@ -33,7 +33,6 @@ #if USE(ACCELERATED_COMPOSITING) #include "VideoLayerChromium.h" -#include "cc/CCLayerImpl.h" #include "Extensions3DChromium.h" #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" @@ -41,17 +40,11 @@ #include "RenderLayerBacking.h" #include "VideoFrameChromium.h" #include "VideoFrameProvider.h" +#include "cc/CCLayerImpl.h" +#include "cc/CCVideoLayerImpl.h" namespace WebCore { -// These values are magic numbers that are used in the transformation -// from YUV to RGB color values. -const float VideoLayerChromium::yuv2RGB[9] = { - 1.f, 1.f, 1.f, - 0.f, -.344f, 1.772f, - 1.403f, -.714f, 0.f, -}; - PassRefPtr<VideoLayerChromium> VideoLayerChromium::create(GraphicsLayerChromium* owner, VideoFrameProvider* provider) { @@ -71,23 +64,37 @@ VideoLayerChromium::VideoLayerChromium(GraphicsLayerChromium* owner, VideoFrameP VideoLayerChromium::~VideoLayerChromium() { cleanupResources(); + deleteTexturesInUse(); } -void VideoLayerChromium::cleanupResources() +PassRefPtr<CCLayerImpl> VideoLayerChromium::createCCLayerImpl() +{ + return CCVideoLayerImpl::create(this); +} + +void VideoLayerChromium::deleteTexturesInUse() { - LayerChromium::cleanupResources(); - releaseCurrentFrame(); if (!layerRenderer()) return; GraphicsContext3D* context = layerRendererContext(); for (unsigned plane = 0; plane < VideoFrameChromium::maxPlanes; plane++) { - if (m_textures[plane]) - GLC(context, context->deleteTexture(m_textures[plane])); + Texture texture = m_textures[plane]; + if (!texture.isEmpty && texture.ownedByLayerRenderer) + GLC(context, context->deleteTexture(texture.id)); } } -void VideoLayerChromium::updateContentsIfDirty() +void VideoLayerChromium::cleanupResources() +{ + LayerChromium::cleanupResources(); + if (m_currentFrame) + releaseCurrentFrame(); + else + resetFrameParameters(); +} + +void VideoLayerChromium::updateCompositorResources() { if (!m_contentsDirty) return; @@ -116,6 +123,9 @@ void VideoLayerChromium::updateContentsIfDirty() return; } + // If the incoming frame is backed by a texture (i.e. decoded in hardware), + // then we do not need to allocate a texture via the layer renderer. Instead + // we save the texture data then exit. if (frame->surfaceType() == VideoFrameChromium::TypeTexture) { releaseCurrentFrame(); saveCurrentFrame(frame); @@ -136,8 +146,9 @@ void VideoLayerChromium::updateContentsIfDirty() // Update texture planes. for (unsigned plane = 0; plane < frame->planes(); plane++) { - ASSERT(frame->requiredTextureSize(plane) == m_textureSizes[plane]); - updateTexture(context, m_textures[plane], frame->requiredTextureSize(plane), textureFormat, frame->data(plane)); + Texture texture = m_textures[plane]; + ASSERT(frame->requiredTextureSize(plane) == texture.size); + updateTexture(context, texture.id, texture.size, textureFormat, frame->data(plane)); } m_dirtyRect.setSize(FloatSize()); @@ -146,7 +157,19 @@ void VideoLayerChromium::updateContentsIfDirty() m_provider->putCurrentFrame(frame); } -unsigned VideoLayerChromium::determineTextureFormat(VideoFrameChromium* frame) +void VideoLayerChromium::pushPropertiesTo(CCLayerImpl* layer) +{ + LayerChromium::pushPropertiesTo(layer); + + CCVideoLayerImpl* videoLayer = static_cast<CCVideoLayerImpl*>(layer); + videoLayer->setSkipsDraw(m_skipsDraw); + videoLayer->setFrameFormat(m_frameFormat); + for (size_t i = 0; i < 3; ++i) + videoLayer->setTexture(i, m_textures[i]); +} + + +unsigned VideoLayerChromium::determineTextureFormat(const VideoFrameChromium* frame) { switch (frame->format()) { case VideoFrameChromium::YV12: @@ -160,56 +183,68 @@ unsigned VideoLayerChromium::determineTextureFormat(VideoFrameChromium* frame) return GraphicsContext3D::INVALID_VALUE; } -bool VideoLayerChromium::allocateTexturesIfNeeded(GraphicsContext3D* context, VideoFrameChromium* frame, unsigned textureFormat) +bool VideoLayerChromium::allocateTexturesIfNeeded(GraphicsContext3D* context, const VideoFrameChromium* frame, unsigned textureFormat) { ASSERT(context); ASSERT(frame); for (unsigned plane = 0; plane < frame->planes(); plane++) { - IntSize planeTextureSize = frame->requiredTextureSize(plane); + IntSize requiredTextureSize = frame->requiredTextureSize(plane); + Texture texture = m_textures[plane]; // If the renderer cannot handle this large of a texture, return false. // FIXME: Remove this test when tiled layers are implemented. - if (!layerRenderer()->checkTextureSize(planeTextureSize)) + if (!layerRenderer()->checkTextureSize(requiredTextureSize)) return false; - if (!m_textures[plane]) - m_textures[plane] = layerRenderer()->createLayerTexture(); - - if (!planeTextureSize.isZero() && planeTextureSize != m_textureSizes[plane]) { - allocateTexture(context, m_textures[plane], planeTextureSize, textureFormat); - m_textureSizes[plane] = planeTextureSize; - int frameWidth = frame->width(plane); - int frameHeight = frame->height(plane); - // When there are dead pixels at the edge of the texture, decrease - // the frame width by 1 to prevent the rightmost pixels from - // interpolating with the dead pixels. - if (frame->hasPaddingBytes(plane)) - --frameWidth; - m_frameSizes[plane] = IntSize(frameWidth, frameHeight); + if (texture.isEmpty) { + texture.id = layerRenderer()->createLayerTexture(); + texture.ownedByLayerRenderer = true; + texture.isEmpty = false; + } + + if (!requiredTextureSize.isZero() && requiredTextureSize != texture.size) { + allocateTexture(context, texture.id, requiredTextureSize, textureFormat); + texture.size = requiredTextureSize; + texture.visibleSize = computeVisibleSize(frame, plane); } + m_textures[plane] = texture; } + return true; +} + +IntSize VideoLayerChromium::computeVisibleSize(const VideoFrameChromium* frame, unsigned plane) +{ + int visibleWidth = frame->width(plane); + int visibleHeight = frame->height(plane); + // When there are dead pixels at the edge of the texture, decrease + // the frame width by 1 to prevent the rightmost pixels from + // interpolating with the dead pixels. + if (frame->hasPaddingBytes(plane)) + --visibleWidth; + // In YV12, every 2x2 square of Y values corresponds to one U and // one V value. If we decrease the width of the UV plane, we must decrease the // width of the Y texture by 2 for proper alignment. This must happen // always, even if Y's texture does not have padding bytes. - if (frame->format() == VideoFrameChromium::YV12) { - int yPlaneOriginalWidth = frame->width(VideoFrameChromium::yPlane); - if (frame->hasPaddingBytes(VideoFrameChromium::uPlane)) - m_frameSizes[VideoFrameChromium::yPlane].setWidth(yPlaneOriginalWidth - 2); + if (plane == VideoFrameChromium::yPlane && frame->format() == VideoFrameChromium::YV12) { + if (frame->hasPaddingBytes(VideoFrameChromium::uPlane)) { + int originalWidth = frame->width(plane); + visibleWidth = originalWidth - 2; + } } - return true; + return IntSize(visibleWidth, visibleHeight); } -void VideoLayerChromium::allocateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned textureFormat) +void VideoLayerChromium::allocateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned textureFormat) const { GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); GLC(context, context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, textureFormat, dimensions.width(), dimensions.height(), 0, textureFormat, GraphicsContext3D::UNSIGNED_BYTE)); } -void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned format, const void* data) +void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned format, const void* data) const { ASSERT(context); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); @@ -225,33 +260,6 @@ void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned text } } -void VideoLayerChromium::draw() -{ - if (m_skipsDraw) - return; - - ASSERT(layerRenderer()); - const RGBAProgram* rgbaProgram = layerRenderer()->videoLayerRGBAProgram(); - ASSERT(rgbaProgram && rgbaProgram->initialized()); - const YUVProgram* yuvProgram = layerRenderer()->videoLayerYUVProgram(); - ASSERT(yuvProgram && yuvProgram->initialized()); - - switch (m_frameFormat) { - case VideoFrameChromium::YV12: - case VideoFrameChromium::YV16: - drawYUV(yuvProgram); - break; - case VideoFrameChromium::RGBA: - drawRGBA(rgbaProgram); - break; - default: - // FIXME: Implement other paths. - notImplemented(); - break; - } - releaseCurrentFrame(); -} - void VideoLayerChromium::releaseCurrentFrame() { if (!m_currentFrame) @@ -262,86 +270,29 @@ void VideoLayerChromium::releaseCurrentFrame() resetFrameParameters(); } -void VideoLayerChromium::drawYUV(const VideoLayerChromium::YUVProgram* program) -{ - GraphicsContext3D* context = layerRendererContext(); - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE1)); - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::yPlane])); - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE2)); - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::uPlane])); - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE3)); - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::vPlane])); - - layerRenderer()->useShader(program->program()); - unsigned yFrameWidth = m_frameSizes[VideoFrameChromium::yPlane].width(); - unsigned yTextureWidth = m_textureSizes[VideoFrameChromium::yPlane].width(); - // Arbitrarily take the u sizes because u and v dimensions are identical. - unsigned uvFrameWidth = m_frameSizes[VideoFrameChromium::uPlane].width(); - unsigned uvTextureWidth = m_textureSizes[VideoFrameChromium::uPlane].width(); - - float yWidthScaleFactor = static_cast<float>(yFrameWidth) / yTextureWidth; - float uvWidthScaleFactor = static_cast<float>(uvFrameWidth) / uvTextureWidth; - GLC(context, context->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor)); - GLC(context, context->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor)); - - GLC(context, context->uniform1i(program->fragmentShader().yTextureLocation(), 1)); - GLC(context, context->uniform1i(program->fragmentShader().uTextureLocation(), 2)); - GLC(context, context->uniform1i(program->fragmentShader().vTextureLocation(), 3)); - - // This value of 0.5 maps to 128. It is used in the YUV to RGB conversion - // formula to turn unsigned u and v values to signed u and v values. - // This is loaded as a uniform because certain drivers have problems - // reading literal float values. - GLC(context, context->uniform1f(program->fragmentShader().signAdjLocation(), 0.5)); - - GLC(context, context->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1)); - - drawTexturedQuad(context, layerRenderer()->projectionMatrix(), ccLayerImpl()->drawTransform(), - bounds().width(), bounds().height(), ccLayerImpl()->drawOpacity(), - program->vertexShader().matrixLocation(), - program->fragmentShader().alphaLocation()); - - // Reset active texture back to texture 0. - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); -} - -void VideoLayerChromium::drawRGBA(const VideoLayerChromium::RGBAProgram* program) -{ - GraphicsContext3D* context = layerRendererContext(); - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::rgbPlane])); - - layerRenderer()->useShader(program->program()); - unsigned frameWidth = m_frameSizes[VideoFrameChromium::rgbPlane].width(); - unsigned textureWidth = m_textureSizes[VideoFrameChromium::rgbPlane].width(); - float widthScaleFactor = static_cast<float>(frameWidth) / textureWidth; - GLC(context, context->uniform4f(program->vertexShader().texTransformLocation(), 0, 0, widthScaleFactor, 1)); - - GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); - - drawTexturedQuad(context, layerRenderer()->projectionMatrix(), ccLayerImpl()->drawTransform(), - bounds().width(), bounds().height(), ccLayerImpl()->drawOpacity(), - program->vertexShader().matrixLocation(), - program->fragmentShader().alphaLocation()); -} - void VideoLayerChromium::resetFrameParameters() { + deleteTexturesInUse(); for (unsigned plane = 0; plane < VideoFrameChromium::maxPlanes; plane++) { - m_textures[plane] = 0; - m_textureSizes[plane] = IntSize(); - m_frameSizes[plane] = IntSize(); + m_textures[plane].id = 0; + m_textures[plane].size = IntSize(); + m_textures[plane].visibleSize = IntSize(); + m_textures[plane].ownedByLayerRenderer = false; + m_textures[plane].isEmpty = true; } } void VideoLayerChromium::saveCurrentFrame(VideoFrameChromium* frame) { ASSERT(!m_currentFrame); + deleteTexturesInUse(); m_currentFrame = frame; for (unsigned plane = 0; plane < frame->planes(); plane++) { - m_textures[plane] = frame->texture(plane); - m_textureSizes[plane] = frame->requiredTextureSize(plane); - m_frameSizes[plane] = m_textureSizes[plane]; + m_textures[plane].id = frame->texture(plane); + m_textures[plane].size = frame->requiredTextureSize(plane); + m_textures[plane].visibleSize = computeVisibleSize(frame, plane); + m_textures[plane].ownedByLayerRenderer = false; + m_textures[plane].isEmpty = false; } } diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h index 2170e13..ef08bd8 100644 --- a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h @@ -42,19 +42,28 @@ namespace WebCore { // A Layer that contains a Video element. class VideoLayerChromium : public LayerChromium { public: + struct Texture { + unsigned id; + IntSize size; + IntSize visibleSize; + bool ownedByLayerRenderer; + bool isEmpty; + }; + static PassRefPtr<VideoLayerChromium> create(GraphicsLayerChromium* owner = 0, VideoFrameProvider* = 0); virtual ~VideoLayerChromium(); - virtual void updateContentsIfDirty(); + + virtual PassRefPtr<CCLayerImpl> createCCLayerImpl(); + + virtual void updateCompositorResources(); virtual bool drawsContent() const { return true; } - virtual void draw(); // This function is called by VideoFrameProvider. When this method is called // putCurrentFrame() must be called to return the frame currently held. void releaseCurrentFrame(); - typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexFlipAlpha> RGBAProgram; - typedef ProgramBinding<VertexShaderPosTexYUVStretch, FragmentShaderYUVVideo> YUVProgram; + virtual void pushPropertiesTo(CCLayerImpl*); protected: virtual void cleanupResources(); @@ -63,27 +72,27 @@ protected: private: VideoLayerChromium(GraphicsLayerChromium* owner, VideoFrameProvider*); - static unsigned determineTextureFormat(VideoFrameChromium*); - bool allocateTexturesIfNeeded(GraphicsContext3D*, VideoFrameChromium*, unsigned textureFormat); - void updateYUVContents(GraphicsContext3D*, const VideoFrameChromium*); - void updateRGBAContents(GraphicsContext3D*, const VideoFrameChromium*); - void allocateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat); - void updateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat, const void* data); - void drawYUV(const YUVProgram*); - void drawRGBA(const RGBAProgram*); + static unsigned determineTextureFormat(const VideoFrameChromium*); + static IntSize computeVisibleSize(const VideoFrameChromium*, unsigned plane); + void deleteTexturesInUse(); + + bool allocateTexturesIfNeeded(GraphicsContext3D*, const VideoFrameChromium*, unsigned textureFormat); + void allocateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat) const; + + void updateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat, const void* data) const; + void resetFrameParameters(); void saveCurrentFrame(VideoFrameChromium*); - static const float yuv2RGB[9]; - bool m_skipsDraw; VideoFrameChromium::Format m_frameFormat; VideoFrameProvider* m_provider; - VideoFrameChromium* m_currentFrame; - unsigned m_textures[3]; - IntSize m_textureSizes[3]; - IntSize m_frameSizes[3]; + Texture m_textures[3]; + + // This will be null for the entire duration of video playback if hardware + // decoding is not being used. + VideoFrameChromium* m_currentFrame; }; } diff --git a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp index e83d045..652e752 100644 --- a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp @@ -47,10 +47,11 @@ PassRefPtr<WebGLLayerChromium> WebGLLayerChromium::create(GraphicsLayerChromium* WebGLLayerChromium::WebGLLayerChromium(GraphicsLayerChromium* owner) : CanvasLayerChromium(owner) , m_context(0) + , m_textureUpdated(false) { } -void WebGLLayerChromium::updateContentsIfDirty() +void WebGLLayerChromium::updateCompositorResources() { if (!m_contentsDirty) return; @@ -68,19 +69,28 @@ void WebGLLayerChromium::updateContentsIfDirty() m_textureChanged = false; } // Update the contents of the texture used by the compositor. - if (m_contentsDirty) { + if (m_contentsDirty && m_textureUpdated) { m_context->prepareTexture(); + m_context->markLayerComposited(); m_contentsDirty = false; + m_textureUpdated = false; } } +void WebGLLayerChromium::setTextureUpdated() +{ + m_textureUpdated = true; +} + void WebGLLayerChromium::setContext(const GraphicsContext3D* context) { m_context = const_cast<GraphicsContext3D*>(context); unsigned int textureId = m_context->platformTexture(); - if (textureId != m_textureId) + if (textureId != m_textureId) { m_textureChanged = true; + m_textureUpdated = true; + } m_textureId = textureId; m_premultipliedAlpha = m_context->getContextAttributes().premultipliedAlpha; } diff --git a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h index 70be876..33db730 100644 --- a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h @@ -45,7 +45,8 @@ class WebGLLayerChromium : public CanvasLayerChromium { public: static PassRefPtr<WebGLLayerChromium> create(GraphicsLayerChromium* owner = 0); virtual bool drawsContent() const { return m_context; } - virtual void updateContentsIfDirty(); + virtual void updateCompositorResources(); + void setTextureUpdated(); void setContext(const GraphicsContext3D* context); @@ -55,6 +56,7 @@ protected: private: explicit WebGLLayerChromium(GraphicsLayerChromium* owner); GraphicsContext3D* m_context; + bool m_textureUpdated; }; } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp new file mode 100644 index 0000000..649d049 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp @@ -0,0 +1,80 @@ +/* + * 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: + * + * 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 AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "cc/CCCanvasLayerImpl.h" + +#include "CanvasLayerChromium.h" +#include "GraphicsContext3D.h" +#include "LayerRendererChromium.h" +#include <wtf/text/WTFString.h> + +namespace WebCore { + +CCCanvasLayerImpl::CCCanvasLayerImpl(LayerChromium* owner) + : CCLayerImpl(owner) + , m_textureId(0) + , m_premultipliedAlpha(true) +{ +} + +CCCanvasLayerImpl::~CCCanvasLayerImpl() +{ +} + +void CCCanvasLayerImpl::draw() +{ + ASSERT(layerRenderer()); + const CCCanvasLayerImpl::Program* program = layerRenderer()->canvasLayerProgram(); + ASSERT(program && program->initialized()); + GraphicsContext3D* context = layerRenderer()->context(); + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId)); + GC3Denum sfactor = m_premultipliedAlpha ? GraphicsContext3D::ONE : GraphicsContext3D::SRC_ALPHA; + GLC(context, context->blendFunc(sfactor, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); + layerRenderer()->useShader(program->program()); + GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); + LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), + bounds().width(), bounds().height(), drawOpacity(), + program->vertexShader().matrixLocation(), + program->fragmentShader().alphaLocation()); + +} + + +void CCCanvasLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "canvas layer texture id: " << m_textureId << " premultiplied: " << m_premultipliedAlpha << "\n"; + CCLayerImpl::dumpLayerProperties(ts, indent); +} + +} + +#endif // USE(ACCELERATED_COMPOSITING) + diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h new file mode 100644 index 0000000..8cbf8d1 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h @@ -0,0 +1,61 @@ +/* + * 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: + * + * 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 AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CCCanvasLayerImpl_h +#define CCCanvasLayerImpl_h + +#include "ProgramBinding.h" +#include "ShaderChromium.h" +#include "cc/CCLayerImpl.h" + +namespace WebCore { + +class CCCanvasLayerImpl : public CCLayerImpl { +public: + static PassRefPtr<CCCanvasLayerImpl> create(LayerChromium* owner) + { + return adoptRef(new CCCanvasLayerImpl(owner)); + } + virtual ~CCCanvasLayerImpl(); + + typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program; + + virtual void draw(); + + virtual void dumpLayerProperties(TextStream&, int indent) const; + + void setTextureId(unsigned id) { m_textureId = id; } + void setPremultipliedAlpha(bool premultipliedAlpha) { m_premultipliedAlpha = premultipliedAlpha; } +private: + explicit CCCanvasLayerImpl(LayerChromium*); + + unsigned m_textureId; + bool m_premultipliedAlpha; +}; + +} + +#endif // CCCanvasLayerImpl_h + diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp index 604ef61..404944b 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp @@ -66,8 +66,8 @@ void CCHeadsUpDisplay::draw() // Use a fullscreen texture only if we need to... IntSize hudSize; if (m_showPlatformLayerTree) { - hudSize.setWidth(min(2048, m_layerRenderer->visibleRectSize().width())); - hudSize.setHeight(min(2048, m_layerRenderer->visibleRectSize().height())); + hudSize.setWidth(min(2048, m_layerRenderer->viewportSize().width())); + hudSize.setHeight(min(2048, m_layerRenderer->viewportSize().height())); } else { hudSize.setWidth(512); hudSize.setHeight(128); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h index dbac22a..d56f8ab 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h @@ -53,7 +53,7 @@ public: void setShowPlatformLayerTree(bool enable) { m_showPlatformLayerTree = enable; } bool showPlatformLayerTree() const { return m_showPlatformLayerTree; } - bool enabled() const { return true || m_showPlatformLayerTree || m_showFPSCounter; } + bool enabled() const { return m_showPlatformLayerTree || m_showFPSCounter; } void draw(); private: diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp index a0ad0fb..9411e5a 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp @@ -62,13 +62,18 @@ namespace WebCore { CCLayerImpl::CCLayerImpl(LayerChromium* owner) : m_owner(owner) + , m_anchorPoint(0.5, 0.5) + , m_anchorPointZ(0) + , m_doubleSided(true) + , m_masksToBounds(false) + , m_opacity(1.0) + , m_preserves3D(false) #ifndef NDEBUG , m_debugID(owner->debugID()) #endif , m_targetRenderSurface(0) , m_drawDepth(0) , m_drawOpacity(0) - , m_doubleSided(true) , m_debugBorderColor(0, 0, 0, 0) , m_debugBorderWidth(0) , m_renderSurface(0) @@ -107,7 +112,18 @@ RenderSurfaceChromium* CCLayerImpl::createRenderSurface() return m_renderSurface.get(); } -// These belong on CCLayerImpl, but should be subclased by each type and not defer to the LayerChromium subtypes. +bool CCLayerImpl::descendantsDrawsContent() +{ + const Vector<RefPtr<LayerChromium> >& sublayers = m_owner->getSublayers(); + for (size_t i = 0; i < sublayers.size(); ++i) { + sublayers[i]->createCCLayerImplIfNeeded(); + if (sublayers[i]->ccLayerImpl()->drawsContent() || sublayers[i]->ccLayerImpl()->descendantsDrawsContent()) + return true; + } + return false; +} + +// These belong on CCLayerImpl, but should be overridden by each type and not defer to the LayerChromium subtypes. bool CCLayerImpl::drawsContent() const { return m_owner->drawsContent(); @@ -118,6 +134,11 @@ void CCLayerImpl::draw() return m_owner->draw(); } +void CCLayerImpl::updateCompositorResources() +{ + return m_owner->updateCompositorResources(); +} + void CCLayerImpl::unreserveContentsTexture() { m_owner->unreserveContentsTexture(); @@ -167,7 +188,7 @@ void CCLayerImpl::drawDebugBorder() GLC(context, context->drawElements(GraphicsContext3D::LINE_LOOP, 4, GraphicsContext3D::UNSIGNED_SHORT, 6 * sizeof(unsigned short))); } -static void writeIndent(TextStream& ts, int indent) +void CCLayerImpl::writeIndent(TextStream& ts, int indent) { for (int i = 0; i != indent; ++i) ts << " "; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h index 6892976..96c4f1b 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h @@ -49,7 +49,7 @@ public: return adoptRef(new CCLayerImpl(owner)); } // When this class gets subclasses, remember to add 'virtual' here. - ~CCLayerImpl(); + virtual ~CCLayerImpl(); #ifndef NDEBUG int debugID() const { return m_debugID; } @@ -59,13 +59,43 @@ public: CCLayerImpl* maskLayer() const; CCLayerImpl* replicaLayer() const; - void draw(); - bool drawsContent() const; + virtual void draw(); + virtual void updateCompositorResources(); void unreserveContentsTexture(); void bindContentsTexture(); + // Returns true if this layer has content to draw. + virtual bool drawsContent() const; + + // Returns true if any of the layer's descendants has content to draw. + bool descendantsDrawsContent(); + void cleanupResources(); + void setAnchorPoint(const FloatPoint& anchorPoint) { m_anchorPoint = anchorPoint; } + const FloatPoint& anchorPoint() const { return m_anchorPoint; } + + void setAnchorPointZ(float anchorPointZ) { m_anchorPointZ = anchorPointZ; } + float anchorPointZ() const { return m_anchorPointZ; } + + void setMasksToBounds(bool masksToBounds) { m_masksToBounds = masksToBounds; } + bool masksToBounds() const { return m_masksToBounds; } + + void setOpacity(float opacity) { m_opacity = opacity; } + float opacity() const { return m_opacity; } + + void setPosition(const FloatPoint& position) { m_position = position; } + const FloatPoint& position() const { return m_position; } + + void setPreserves3D(bool preserves3D) { m_preserves3D = preserves3D; } + bool preserves3D() const { return m_preserves3D; } + + void setSublayerTransform(const TransformationMatrix& sublayerTransform) { m_sublayerTransform = sublayerTransform; } + const TransformationMatrix& sublayerTransform() const { return m_sublayerTransform; } + + void setTransform(const TransformationMatrix& transform) { m_transform = transform; } + const TransformationMatrix& transform() const { return m_transform; } + void setName(const String& name) { m_name = name; } const String& name() const { return m_name; } @@ -108,11 +138,30 @@ public: virtual void dumpLayerProperties(TextStream&, int indent) const; -private: +protected: // For now, CCLayers are owned directly by a LayerChromium. LayerChromium* m_owner; explicit CCLayerImpl(LayerChromium*); + static void writeIndent(TextStream&, int indent); + +private: + // Properties synchronized from the associated LayerChromium. + FloatPoint m_anchorPoint; + float m_anchorPointZ; + IntSize m_bounds; + + // Whether the "back" of this layer should draw. + bool m_doubleSided; + + bool m_masksToBounds; + float m_opacity; + FloatPoint m_position; + bool m_preserves3D; + TransformationMatrix m_sublayerTransform; + TransformationMatrix m_transform; + + // Properties owned exclusively by this CCLayerImpl. // Debugging. #ifndef NDEBUG int m_debugID; @@ -131,17 +180,12 @@ private: float m_drawDepth; float m_drawOpacity; - // Whether the "back" of this layer should draw. - bool m_doubleSided; - // Debug borders. Color m_debugBorderColor; float m_debugBorderWidth; TransformationMatrix m_drawTransform; - IntSize m_bounds; - // The scissor rectangle that should be used when this layer is drawn. // Inherited by the parent layer and further restricted if this layer masks // to bounds. diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp new file mode 100644 index 0000000..4aef639 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp @@ -0,0 +1,84 @@ +/* + * 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: + * + * 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 AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "cc/CCPluginLayerImpl.h" + +#include "GraphicsContext3D.h" +#include "LayerRendererChromium.h" +#include "PluginLayerChromium.h" +#include <wtf/text/WTFString.h> + +namespace WebCore { + +CCPluginLayerImpl::CCPluginLayerImpl(LayerChromium* owner) + : CCLayerImpl(owner) + , m_textureId(0) +{ +} + +CCPluginLayerImpl::~CCPluginLayerImpl() +{ +} + +void CCPluginLayerImpl::draw() +{ + ASSERT(layerRenderer()); + const CCPluginLayerImpl::Program* program = layerRenderer()->pluginLayerProgram(); + ASSERT(program && program->initialized()); + GraphicsContext3D* context = layerRenderer()->context(); + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId)); + + // FIXME: setting the texture parameters every time is redundant. Move this code somewhere + // where it will only happen once per texture. + GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); + GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); + GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); + GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); + + layerRenderer()->useShader(program->program()); + GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); + LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), + bounds().width(), bounds().height(), drawOpacity(), + program->vertexShader().matrixLocation(), + program->fragmentShader().alphaLocation()); +} + + +void CCPluginLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "plugin layer texture id: " << m_textureId << "\n"; + CCLayerImpl::dumpLayerProperties(ts, indent); +} + +} + +#endif // USE(ACCELERATED_COMPOSITING) + diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h new file mode 100644 index 0000000..65eb5b7 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h @@ -0,0 +1,60 @@ +/* + * 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: + * + * 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 AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CCPluginLayerImpl_h +#define CCPluginLayerImpl_h + +#include "ProgramBinding.h" +#include "ShaderChromium.h" +#include "cc/CCLayerImpl.h" + +namespace WebCore { + +class CCPluginLayerImpl : public CCLayerImpl { +public: + static PassRefPtr<CCPluginLayerImpl> create(LayerChromium* owner) + { + return adoptRef(new CCPluginLayerImpl(owner)); + } + virtual ~CCPluginLayerImpl(); + + typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program; + + virtual void draw(); + + virtual void dumpLayerProperties(TextStream&, int indent) const; + + void setTextureId(unsigned id) { m_textureId = id; } + +private: + explicit CCPluginLayerImpl(LayerChromium*); + + unsigned m_textureId; +}; + +} + +#endif // CCPluginLayerImpl_h + diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp new file mode 100644 index 0000000..eb3612b --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp @@ -0,0 +1,173 @@ +/* + * 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: + * + * 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 AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "cc/CCVideoLayerImpl.h" + +#include "GraphicsContext3D.h" +#include "LayerRendererChromium.h" +#include "NotImplemented.h" +#include "VideoLayerChromium.h" +#include <wtf/text/WTFString.h> + +namespace WebCore { + +// These values are magic numbers that are used in the transformation +// from YUV to RGB color values. +// They are taken from the following webpage: +// http://www.fourcc.org/fccyvrgb.php +const float CCVideoLayerImpl::yuv2RGB[9] = { + 1.164f, 1.164f, 1.164f, + 0.f, -.391f, 2.018f, + 1.596f, -.813f, 0.f, +}; + +// These values map to 16, 128, and 128 respectively, and are computed +// as a fraction over 256 (e.g. 16 / 256 = 0.0625). +// They are used in the YUV to RGBA conversion formula: +// Y - 16 : Gives 16 values of head and footroom for overshooting +// U - 128 : Turns unsigned U into signed U [-128,127] +// V - 128 : Turns unsigned V into signed V [-128,127] +const float CCVideoLayerImpl::yuvAdjust[3] = { + -0.0625f, + -0.5f, + -0.5f, +}; + +CCVideoLayerImpl::CCVideoLayerImpl(LayerChromium* owner) + : CCLayerImpl(owner) +{ +} + +CCVideoLayerImpl::~CCVideoLayerImpl() +{ + cleanupResources(); +} + +void CCVideoLayerImpl::setTexture(size_t i, VideoLayerChromium::Texture texture) +{ + ASSERT(i < 3); + m_textures[i] = texture; +} + +void CCVideoLayerImpl::draw() +{ + if (m_skipsDraw) + return; + + ASSERT(layerRenderer()); + const RGBAProgram* rgbaProgram = layerRenderer()->videoLayerRGBAProgram(); + ASSERT(rgbaProgram && rgbaProgram->initialized()); + const YUVProgram* yuvProgram = layerRenderer()->videoLayerYUVProgram(); + ASSERT(yuvProgram && yuvProgram->initialized()); + + switch (m_frameFormat) { + case VideoFrameChromium::YV12: + case VideoFrameChromium::YV16: + drawYUV(yuvProgram); + break; + case VideoFrameChromium::RGBA: + drawRGBA(rgbaProgram); + break; + default: + // FIXME: Implement other paths. + notImplemented(); + break; + } +} + +void CCVideoLayerImpl::drawYUV(const CCVideoLayerImpl::YUVProgram* program) const +{ + GraphicsContext3D* context = layerRenderer()->context(); + VideoLayerChromium::Texture yTexture = m_textures[VideoFrameChromium::yPlane]; + VideoLayerChromium::Texture uTexture = m_textures[VideoFrameChromium::uPlane]; + VideoLayerChromium::Texture vTexture = m_textures[VideoFrameChromium::vPlane]; + + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE1)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, yTexture.id)); + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE2)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, uTexture.id)); + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE3)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, vTexture.id)); + + layerRenderer()->useShader(program->program()); + + float yWidthScaleFactor = static_cast<float>(yTexture.visibleSize.width()) / yTexture.size.width(); + // Arbitrarily take the u sizes because u and v dimensions are identical. + float uvWidthScaleFactor = static_cast<float>(uTexture.visibleSize.width()) / uTexture.size.width(); + GLC(context, context->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor)); + GLC(context, context->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor)); + + GLC(context, context->uniform1i(program->fragmentShader().yTextureLocation(), 1)); + GLC(context, context->uniform1i(program->fragmentShader().uTextureLocation(), 2)); + GLC(context, context->uniform1i(program->fragmentShader().vTextureLocation(), 3)); + + GLC(context, context->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1)); + GLC(context, context->uniform3fv(program->fragmentShader().yuvAdjLocation(), const_cast<float*>(yuvAdjust), 1)); + + LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), + bounds().width(), bounds().height(), drawOpacity(), + program->vertexShader().matrixLocation(), + program->fragmentShader().alphaLocation()); + + // Reset active texture back to texture 0. + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); +} + +void CCVideoLayerImpl::drawRGBA(const CCVideoLayerImpl::RGBAProgram* program) const +{ + GraphicsContext3D* context = layerRenderer()->context(); + VideoLayerChromium::Texture texture = m_textures[VideoFrameChromium::rgbPlane]; + + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, texture.id)); + + layerRenderer()->useShader(program->program()); + float widthScaleFactor = static_cast<float>(texture.visibleSize.width()) / texture.size.width(); + GLC(context, context->uniform4f(program->vertexShader().texTransformLocation(), 0, 0, widthScaleFactor, 1)); + + GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); + + LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), + bounds().width(), bounds().height(), drawOpacity(), + program->vertexShader().matrixLocation(), + program->fragmentShader().alphaLocation()); +} + + +void CCVideoLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "video layer\n"; + CCLayerImpl::dumpLayerProperties(ts, indent); +} + +} + +#endif // USE(ACCELERATED_COMPOSITING) + diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h new file mode 100644 index 0000000..62f8778 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h @@ -0,0 +1,75 @@ +/* + * 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: + * + * 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 AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CCVideoLayerImpl_h +#define CCVideoLayerImpl_h + +#include "ProgramBinding.h" +#include "ShaderChromium.h" +#include "VideoFrameChromium.h" +#include "VideoLayerChromium.h" +#include "cc/CCLayerImpl.h" + +namespace WebCore { + +class VideoFrameProvider; + +class CCVideoLayerImpl : public CCLayerImpl { +public: + static PassRefPtr<CCVideoLayerImpl> create(LayerChromium* owner) + { + return adoptRef(new CCVideoLayerImpl(owner)); + } + virtual ~CCVideoLayerImpl(); + + typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexFlipAlpha> RGBAProgram; + typedef ProgramBinding<VertexShaderPosTexYUVStretch, FragmentShaderYUVVideo> YUVProgram; + + virtual void draw(); + + virtual void dumpLayerProperties(TextStream&, int indent) const; + + void setSkipsDraw(bool skipsDraw) { m_skipsDraw = skipsDraw; } + void setFrameFormat(VideoFrameChromium::Format format) { m_frameFormat = format; } + void setTexture(size_t, VideoLayerChromium::Texture); + +private: + explicit CCVideoLayerImpl(LayerChromium*); + + void drawYUV(const YUVProgram*) const; + void drawRGBA(const RGBAProgram*) const; + + static const float yuv2RGB[9]; + static const float yuvAdjust[3]; + + bool m_skipsDraw; + VideoFrameChromium::Format m_frameFormat; + VideoLayerChromium::Texture m_textures[3]; +}; + +} + +#endif // CCVideoLayerImpl_h + diff --git a/Source/WebCore/platform/graphics/cocoa/FontPlatformData.h b/Source/WebCore/platform/graphics/cocoa/FontPlatformData.h deleted file mode 100644 index ca38029..0000000 --- a/Source/WebCore/platform/graphics/cocoa/FontPlatformData.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * This file is part of the internal font implementation. - * It should not be included by source files outside of it. - * - * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef FontPlatformData_h -#define FontPlatformData_h - -#include "FontOrientation.h" -#include "FontWidthVariant.h" -#include <wtf/text/StringImpl.h> - -#ifdef __OBJC__ -@class NSFont; -#else -class NSFont; -#endif - -typedef struct CGFont* CGFontRef; -#ifndef BUILDING_ON_TIGER -typedef const struct __CTFont* CTFontRef; -#endif - -#include <CoreFoundation/CFBase.h> -#include <objc/objc-auto.h> -#include <wtf/Forward.h> -#include <wtf/RetainPtr.h> - -#if PLATFORM(CHROMIUM) && OS(DARWIN) -#include "CrossProcessFontLoading.h" -#endif - - -typedef UInt32 ATSUFontID; -typedef UInt32 ATSFontRef; - -namespace WebCore { - -#ifndef BUILDING_ON_TIGER -inline CTFontRef toCTFontRef(NSFont *nsFont) { return reinterpret_cast<CTFontRef>(nsFont); } -#endif - -class FontPlatformData { - public: - FontPlatformData(float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation = Horizontal, FontWidthVariant widthVariant = RegularWidth) - : m_syntheticBold(syntheticBold) - , m_syntheticOblique(syntheticOblique) - , m_orientation(orientation) - , m_size(size) - , m_widthVariant(widthVariant) - , m_font(0) -#ifdef BUILDING_ON_TIGER - , m_cgFont(0) -#endif - , m_isColorBitmapFont(false) - { - } - - FontPlatformData(NSFont*, float size, bool syntheticBold = false, bool syntheticOblique = false, FontOrientation = Horizontal, FontWidthVariant = RegularWidth); - - FontPlatformData(CGFontRef cgFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation, FontWidthVariant widthVariant) - : m_syntheticBold(syntheticBold) - , m_syntheticOblique(syntheticOblique) - , m_orientation(orientation) - , m_size(size) - , m_widthVariant(widthVariant) - , m_font(0) - , m_cgFont(cgFont) - , m_isColorBitmapFont(false) - { - } - - FontPlatformData(const FontPlatformData&); - - ~FontPlatformData(); - - FontPlatformData(WTF::HashTableDeletedValueType) : m_font(hashTableDeletedFontValue()) { } - bool isHashTableDeletedValue() const { return m_font == hashTableDeletedFontValue(); } - - float size() const { return m_size; } - bool syntheticBold() const { return m_syntheticBold; } - bool syntheticOblique() const { return m_syntheticOblique; } - FontOrientation orientation() const { return m_orientation; } - FontWidthVariant widthVariant() const { return m_widthVariant; } - - bool m_syntheticBold; - bool m_syntheticOblique; - FontOrientation m_orientation; - - float m_size; - - FontWidthVariant m_widthVariant; - - unsigned hash() const - { - ASSERT(m_font != 0 || m_cgFont == 0); - uintptr_t hashCodes[3] = { (uintptr_t)m_font, m_widthVariant, m_orientation << 2 | m_syntheticBold << 1 | m_syntheticOblique }; - return WTF::StringHasher::createBlobHash<sizeof(hashCodes)>(hashCodes); - } - - const FontPlatformData& operator=(const FontPlatformData& f); - - bool operator==(const FontPlatformData& other) const - { - return m_font == other.m_font && m_syntheticBold == other.m_syntheticBold && m_syntheticOblique == other.m_syntheticOblique && - m_cgFont == other.m_cgFont && m_size == other.m_size && m_orientation == other.m_orientation && m_widthVariant == other.m_widthVariant; - } - - NSFont *font() const { return m_font; } - void setFont(NSFont *font); - - CTFontRef ctFont() const; - - bool roundsGlyphAdvances() const; - bool allowsLigatures() const; - bool isColorBitmapFont() const { return m_isColorBitmapFont; } - -#ifndef BUILDING_ON_TIGER - CGFontRef cgFont() const { return m_cgFont.get(); } -#else - CGFontRef cgFont() const { return m_cgFont; } -#endif - -#ifndef NDEBUG - String description() const; -#endif - -private: - static NSFont *hashTableDeletedFontValue() { return reinterpret_cast<NSFont *>(-1); } - - // Load various data about the font specified by |nsFont| with the size fontSize into the following output paramters: - // Note: Callers should always take into account that for the Chromium port, |outNSFont| isn't necessarily the same - // font as |nsFont|. This because the sandbox may block loading of the original font. - // * outNSFont - The font that was actually loaded, for the Chromium port this may be different than nsFont. - // The caller is responsible for calling CFRelease() on this parameter when done with it. - // * cgFont - CGFontRef representing the input font at the specified point size. - void loadFont(NSFont* nsFont, float fontSize, NSFont*& outNSFont, CGFontRef& cgFont); - - NSFont *m_font; - -#ifndef BUILDING_ON_TIGER - RetainPtr<CGFontRef> m_cgFont; -#else - CGFontRef m_cgFont; // It is not necessary to refcount this, since either an NSFont owns it or some CachedFont has it referenced. -#endif - - mutable RetainPtr<CTFontRef> m_CTFont; - - bool m_isColorBitmapFont; - -#if PLATFORM(CHROMIUM) && OS(DARWIN) - RefPtr<MemoryActivatedFont> m_inMemoryFont; -#endif -}; - -} // namespace WebCore - -#endif diff --git a/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm b/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm index b40f698..6a17707 100644 --- a/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm +++ b/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm @@ -45,9 +45,12 @@ void FontPlatformData::loadFont(NSFont* nsFont, float, NSFont*& outNSFont, CGFon } #endif // PLATFORM(MAC) -FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation, FontWidthVariant widthVariant) +FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation, + TextOrientation textOrientation, FontWidthVariant widthVariant) : m_syntheticBold(syntheticBold) , m_syntheticOblique(syntheticOblique) + , m_orientation(orientation) + , m_textOrientation(textOrientation) , m_size(size) , m_widthVariant(widthVariant) , m_font(nsFont) @@ -64,8 +67,6 @@ FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool syntheticBol CGFontRef cgFont = 0; loadFont(nsFont, size, m_font, cgFont); - m_orientation = orientation; - if (m_font) CFRetain(m_font); @@ -76,35 +77,26 @@ FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool syntheticBol #endif } -FontPlatformData::FontPlatformData(const FontPlatformData& f) +FontPlatformData:: ~FontPlatformData() +{ + if (m_font && m_font != reinterpret_cast<NSFont *>(-1)) + CFRelease(m_font); +} + +void FontPlatformData::platformDataInit(const FontPlatformData& f) { m_font = f.m_font && f.m_font != reinterpret_cast<NSFont *>(-1) ? const_cast<NSFont *>(static_cast<const NSFont *>(CFRetain(f.m_font))) : f.m_font; - m_syntheticBold = f.m_syntheticBold; - m_syntheticOblique = f.m_syntheticOblique; - m_size = f.m_size; - m_widthVariant = f.m_widthVariant; m_cgFont = f.m_cgFont; - m_isColorBitmapFont = f.m_isColorBitmapFont; - m_orientation = f.m_orientation; m_CTFont = f.m_CTFont; + #if PLATFORM(CHROMIUM) && OS(DARWIN) m_inMemoryFont = f.m_inMemoryFont; #endif } -FontPlatformData:: ~FontPlatformData() +const FontPlatformData& FontPlatformData::platformDataAssign(const FontPlatformData& f) { - if (m_font && m_font != reinterpret_cast<NSFont *>(-1)) - CFRelease(m_font); -} - -const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& f) -{ - m_syntheticBold = f.m_syntheticBold; - m_syntheticOblique = f.m_syntheticOblique; - m_size = f.m_size; - m_widthVariant = f.m_widthVariant; m_cgFont = f.m_cgFont; if (m_font == f.m_font) return *this; @@ -113,8 +105,6 @@ const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& f) if (m_font && m_font != reinterpret_cast<NSFont *>(-1)) CFRelease(m_font); m_font = f.m_font; - m_isColorBitmapFont = f.m_isColorBitmapFont; - m_orientation = f.m_orientation; m_CTFont = f.m_CTFont; #if PLATFORM(CHROMIUM) && OS(DARWIN) m_inMemoryFont = f.m_inMemoryFont; @@ -122,6 +112,12 @@ const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& f) return *this; } +bool FontPlatformData::platformIsEqual(const FontPlatformData& other) const +{ + return m_font == other.m_font + && m_cgFont == other.m_cgFont; +} + void FontPlatformData::setFont(NSFont *font) { ASSERT_ARG(font, font); diff --git a/Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp b/Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp index 841c8a3..b1cf96b 100644 --- a/Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp +++ b/Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp @@ -59,7 +59,7 @@ FontCustomPlatformData::~FontCustomPlatformData() cairo_font_face_destroy(m_fontFace); } -FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode) +FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode) { return FontPlatformData(m_fontFace, size, bold, italic); } diff --git a/Source/WebCore/platform/graphics/freetype/FontPlatformData.h b/Source/WebCore/platform/graphics/freetype/FontPlatformData.h index 2841b14..d1cb605 100644 --- a/Source/WebCore/platform/graphics/freetype/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/freetype/FontPlatformData.h @@ -71,6 +71,7 @@ public: bool hasCompatibleCharmap(); FontOrientation orientation() const { return Horizontal; } // FIXME: Implement. + void setOrientation(FontOrientation) { } // FIXME: Implement. cairo_scaled_font_t* scaledFont() const { return m_scaledFont; } diff --git a/Source/WebCore/platform/graphics/gpu/BicubicShader.cpp b/Source/WebCore/platform/graphics/gpu/BicubicShader.cpp new file mode 100644 index 0000000..40c9843 --- /dev/null +++ b/Source/WebCore/platform/graphics/gpu/BicubicShader.cpp @@ -0,0 +1,137 @@ +/* + * 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. + */ + +#include "config.h" + +#if ENABLE(ACCELERATED_2D_CANVAS) + +#include "BicubicShader.h" + +#include "GraphicsContext3D.h" + +namespace WebCore { + +BicubicShader::BicubicShader(GraphicsContext3D* context, unsigned program) + : Shader(context, program) + , m_matrixLocation(context->getUniformLocation(program, "matrix")) + , m_texMatrixLocation(context->getUniformLocation(program, "texMatrix")) + , m_coefficientsLocation(context->getUniformLocation(program, "coefficients")) + , m_imageIncrementLocation(context->getUniformLocation(program, "imageIncrement")) + , m_imageLocation(context->getUniformLocation(program, "image")) + , m_alphaLocation(context->getUniformLocation(program, "alpha")) + , m_positionLocation(context->getAttribLocation(program, "position")) +{ +} + +PassOwnPtr<BicubicShader> BicubicShader::create(GraphicsContext3D* context) +{ + static const char* vertexShaderSource = + "uniform mat3 matrix;\n" + "uniform mat3 texMatrix;\n" + "attribute vec3 position;\n" + "varying vec2 texCoord;\n" + "void main() {\n" + " texCoord = (texMatrix * position).xy;\n" + " gl_Position = vec4(matrix * position, 1.0);\n" + "}\n"; + static const char* fragmentShaderSource = + "#ifdef GL_ES\n" + "precision mediump float;\n" + "#endif\n" + "uniform sampler2D image;\n" + "uniform vec2 imageIncrement;\n" + "uniform mat4 coefficients;\n" + "uniform float alpha;\n" + "varying vec2 texCoord;\n" + "vec4 cubicBlend(float t, vec4 c0, vec4 c1, vec4 c2, vec4 c3) {\n" + " vec4 ts = vec4(1.0, t, t * t, t * t * t);\n" + " vec4 result = coefficients * ts;\n" + " return result.w * c0 + result.z * c1 + result.y * c2 + result.x * c3;\n" + "}\n" + "void main() {\n" + " vec2 imageCoord = texCoord;\n" + " vec2 f = fract(imageCoord / imageIncrement) - vec2(0.5, 0.5);\n" + " vec4 t00 = texture2D(image, imageCoord + imageIncrement * vec2(-1, -1));\n" + " vec4 t10 = texture2D(image, imageCoord + imageIncrement * vec2( 0, -1));\n" + " vec4 t20 = texture2D(image, imageCoord + imageIncrement * vec2( 1, -1));\n" + " vec4 t30 = texture2D(image, imageCoord + imageIncrement * vec2( 2, -1));\n" + " vec4 t0 = cubicBlend(f.x, t00, t10, t20, t30);\n" + " vec4 t01 = texture2D(image, imageCoord + imageIncrement * vec2(-1, 0));\n" + " vec4 t11 = texture2D(image, imageCoord + imageIncrement * vec2( 0, 0));\n" + " vec4 t21 = texture2D(image, imageCoord + imageIncrement * vec2( 1, 0));\n" + " vec4 t31 = texture2D(image, imageCoord + imageIncrement * vec2( 2, 0));\n" + " vec4 t1 = cubicBlend(f.x, t01, t11, t21, t31);\n" + " vec4 t02 = texture2D(image, imageCoord + imageIncrement * vec2(-1, 1));\n" + " vec4 t12 = texture2D(image, imageCoord + imageIncrement * vec2( 0, 1));\n" + " vec4 t22 = texture2D(image, imageCoord + imageIncrement * vec2( 1, 1));\n" + " vec4 t32 = texture2D(image, imageCoord + imageIncrement * vec2( 2, 1));\n" + " vec4 t2 = cubicBlend(f.x, t02, t12, t22, t32);\n" + " vec4 t03 = texture2D(image, imageCoord + imageIncrement * vec2(-1, 2));\n" + " vec4 t13 = texture2D(image, imageCoord + imageIncrement * vec2( 0, 2));\n" + " vec4 t23 = texture2D(image, imageCoord + imageIncrement * vec2( 1, 2));\n" + " vec4 t33 = texture2D(image, imageCoord + imageIncrement * vec2( 2, 2));\n" + " vec4 t3 = cubicBlend(f.x, t03, t13, t23, t33);\n" + " gl_FragColor = cubicBlend(f.y, t0, t1, t2, t3);\n" + "}\n"; + + unsigned program = loadProgram(context, vertexShaderSource, fragmentShaderSource); + if (!program) + return 0; + + return new BicubicShader(context, program); +} + +void BicubicShader::use(const AffineTransform& transform, const AffineTransform& texTransform, const float coefficients[16], const float imageIncrement[2], float alpha) +{ + m_context->useProgram(m_program); + float matrix[9]; + affineTo3x3(transform, matrix); + m_context->uniformMatrix3fv(m_matrixLocation, false /*transpose*/, matrix, 1 /*count*/); + + float texMatrix[9]; + affineTo3x3(texTransform, texMatrix); + m_context->uniformMatrix3fv(m_texMatrixLocation, false /*transpose*/, texMatrix, 1 /*count*/); + m_context->uniformMatrix4fv(m_coefficientsLocation, false /*transpose*/, const_cast<float *>(coefficients), 1 /*count*/); + + m_context->uniform2f(m_imageIncrementLocation, imageIncrement[0], imageIncrement[1]); + + // For now, we always use texture unit 0. If that ever changes, we should + // expose this parameter to the caller. + m_context->uniform1i(m_imageLocation, 0); + m_context->uniform1f(m_alphaLocation, alpha); + + m_context->vertexAttribPointer(m_positionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0); + + m_context->enableVertexAttribArray(m_positionLocation); +} + +} + +#endif diff --git a/Source/WebCore/platform/graphics/gpu/BicubicShader.h b/Source/WebCore/platform/graphics/gpu/BicubicShader.h new file mode 100644 index 0000000..f7522f4 --- /dev/null +++ b/Source/WebCore/platform/graphics/gpu/BicubicShader.h @@ -0,0 +1,58 @@ +/* + * 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 BicubicShader_h +#define BicubicShader_h + +#include "Shader.h" + +namespace WebCore { + +class BicubicShader : public Shader { +public: + static PassOwnPtr<BicubicShader> create(GraphicsContext3D*); + + void use(const AffineTransform&, const AffineTransform& texTransform, const float coefficients[16], const float imageIncrement[2], float alpha); + +private: + BicubicShader(GraphicsContext3D*, unsigned program); + + int m_matrixLocation; + int m_texMatrixLocation; + int m_coefficientsLocation; + int m_imageIncrementLocation; + int m_imageLocation; + int m_alphaLocation; + int m_positionLocation; +}; + +} + +#endif // BicubicShader_h diff --git a/Source/WebCore/platform/graphics/gpu/ConvolutionShader.cpp b/Source/WebCore/platform/graphics/gpu/ConvolutionShader.cpp new file mode 100644 index 0000000..f0b6bd9 --- /dev/null +++ b/Source/WebCore/platform/graphics/gpu/ConvolutionShader.cpp @@ -0,0 +1,125 @@ +/* + * 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. + */ + +#include "config.h" + +#if ENABLE(ACCELERATED_2D_CANVAS) + +#include "ConvolutionShader.h" + +#include "GraphicsContext3D.h" +#include "StringExtras.h" + +namespace WebCore { + +ConvolutionShader::ConvolutionShader(GraphicsContext3D* context, unsigned program, int kernelWidth) + : Shader(context, program) + , m_kernelWidth(kernelWidth) + , m_matrixLocation(context->getUniformLocation(program, "matrix")) + , m_texMatrixLocation(context->getUniformLocation(program, "texMatrix")) + , m_kernelLocation(context->getUniformLocation(program, "kernel")) + , m_imageLocation(context->getUniformLocation(program, "image")) + , m_imageIncrementLocation(context->getUniformLocation(program, "imageIncrement")) + , m_positionLocation(context->getAttribLocation(program, "position")) +{ +} + +PassOwnPtr<ConvolutionShader> ConvolutionShader::create(GraphicsContext3D* context, int kernelWidth) +{ + static const char* vertexShaderRaw = + "#define KERNEL_WIDTH %d\n" + "uniform mat3 matrix;\n" + "uniform mat3 texMatrix;\n" + "uniform vec2 imageIncrement;\n" + "attribute vec3 position;\n" + "varying vec2 imageCoord;\n" + "void main() {\n" + " // Offset image coords by half of kernel width, in image texels\n" + " gl_Position = vec4(matrix * position, 1.0);\n" + " float scale = (float(KERNEL_WIDTH) - 1.0) / 2.0;\n" + " imageCoord = (texMatrix * position).xy - vec2(scale, scale) * imageIncrement;\n" + "}\n"; + char vertexShaderSource[1024]; + snprintf(vertexShaderSource, sizeof(vertexShaderSource), vertexShaderRaw, kernelWidth); + static const char* fragmentShaderRaw = + "#ifdef GL_ES\n" + "precision mediump float;\n" + "#endif\n" + "#define KERNEL_WIDTH %d\n" + "uniform sampler2D image;\n" + "uniform float kernel[KERNEL_WIDTH];\n" + "uniform vec2 imageIncrement;\n" + "varying vec2 imageCoord;\n" + "void main() {\n" + " vec2 coord = imageCoord;\n" + " vec4 sum = vec4(0, 0, 0, 0);\n" + " for (int i = 0; i < KERNEL_WIDTH; i++) {\n" + " sum += texture2D(image, coord) * kernel[i];\n" + " coord += imageIncrement;\n" + " }\n" + " gl_FragColor = sum;\n" + "}\n"; + char fragmentShaderSource[1024]; + snprintf(fragmentShaderSource, sizeof(fragmentShaderSource), fragmentShaderRaw, kernelWidth); + + unsigned program = loadProgram(context, vertexShaderSource, fragmentShaderSource); + if (!program) + return 0; + return new ConvolutionShader(context, program, kernelWidth); +} + +void ConvolutionShader::use(const AffineTransform& transform, const AffineTransform& texTransform, const float* kernel, int kernelWidth, float imageIncrement[2]) +{ + m_context->useProgram(m_program); + float matrix[9]; + affineTo3x3(transform, matrix); + m_context->uniformMatrix3fv(m_matrixLocation, false /*transpose*/, matrix, 1 /*count*/); + + float texMatrix[9]; + affineTo3x3(texTransform, texMatrix); + m_context->uniformMatrix3fv(m_texMatrixLocation, false /*transpose*/, texMatrix, 1 /*count*/); + + m_context->uniform2f(m_imageIncrementLocation, imageIncrement[0], imageIncrement[1]); + + // For now, we always use texture unit 0. If that ever changes, we should + // expose this parameter to the caller. + m_context->uniform1i(m_imageLocation, 0); + if (kernelWidth > m_kernelWidth) + kernelWidth = m_kernelWidth; + m_context->uniform1fv(m_kernelLocation, const_cast<float*>(kernel), kernelWidth); + + m_context->vertexAttribPointer(m_positionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0); + + m_context->enableVertexAttribArray(m_positionLocation); +} + +} + +#endif diff --git a/Source/WebCore/platform/graphics/gpu/ConvolutionShader.h b/Source/WebCore/platform/graphics/gpu/ConvolutionShader.h new file mode 100644 index 0000000..533e0f5 --- /dev/null +++ b/Source/WebCore/platform/graphics/gpu/ConvolutionShader.h @@ -0,0 +1,58 @@ +/* + * 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 ConvolutionShader_h +#define ConvolutionShader_h + +#include "Shader.h" + +namespace WebCore { + +class ConvolutionShader : public Shader { +public: + static PassOwnPtr<ConvolutionShader> create(GraphicsContext3D*, int kernelWidth); + + void use(const AffineTransform&, const AffineTransform& texTransform, const float* kernel, int kernelWidth, float imageIncrement[2]); + +private: + ConvolutionShader(GraphicsContext3D*, unsigned program, int kernelWidth); + + int m_kernelWidth; + int m_matrixLocation; + int m_texMatrixLocation; + int m_kernelLocation; + int m_imageLocation; + int m_imageIncrementLocation; + int m_positionLocation; +}; + +} + +#endif // ConvolutionShader_h diff --git a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h index 49ae114..606484e 100644 --- a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h +++ b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h @@ -42,6 +42,10 @@ #include <wtf/RetainPtr.h> #endif +#if ENABLE(SKIA_GPU) +class GrContext; +#endif + namespace WebCore { #if PLATFORM(CHROMIUM) @@ -59,6 +63,7 @@ public: void reset(const IntSize&); void bind(); IntSize size() const { return m_size; } + Platform3DObject colorBuffer() const { return m_colorBuffer; } // Clear all resources from this object, as well as context. Called when context is destroyed // to prevent invalid accesses to the resources. @@ -94,6 +99,10 @@ public: void setWillPublishCallback(PassOwnPtr<WillPublishCallback> callback) { m_callback = callback; } #endif +#if ENABLE(SKIA_GPU) + void setGrContext(GrContext* ctx); +#endif + PassRefPtr<GraphicsContext3D> graphicsContext3D() const { return m_context; } private: @@ -130,6 +139,10 @@ private: #if PLATFORM(MAC) RetainPtr<WebGLLayer> m_platformLayer; #endif + +#if ENABLE(SKIA_GPU) + GrContext* m_grContext; +#endif }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/gpu/LoopBlinnPathProcessor.cpp b/Source/WebCore/platform/graphics/gpu/LoopBlinnPathProcessor.cpp index 5439885..a96213c 100644 --- a/Source/WebCore/platform/graphics/gpu/LoopBlinnPathProcessor.cpp +++ b/Source/WebCore/platform/graphics/gpu/LoopBlinnPathProcessor.cpp @@ -42,6 +42,8 @@ #include <algorithm> #include <wtf/Assertions.h> #include <wtf/FastMalloc.h> +#include <wtf/UnusedParam.h> + #if USE(SKIA) #include "SkGeometry.h" @@ -701,6 +703,7 @@ void LoopBlinnPathProcessor::buildContours(const Path& path) } } while (verb != SkPath::kDone_Verb); #else // !USE(SKIA) + UNUSED_PARAM(path); // Must port to your platform. ASSERT_NOT_REACHED(); #endif @@ -1145,6 +1148,8 @@ static void combineCallback(GLdouble coords[3], void* vertexData[4], GLfloat weight[4], void** outData, void* polygonData) { + UNUSED_PARAM(vertexData); + UNUSED_PARAM(weight); TessellationState* state = static_cast<TessellationState*>(polygonData); GLdouble* outVertex = static_cast<GLdouble*>(fastMalloc(3 * sizeof(GLdouble))); state->allocatedPointers.append(outVertex); diff --git a/Source/WebCore/platform/graphics/gpu/PODRedBlackTree.h b/Source/WebCore/platform/graphics/gpu/PODRedBlackTree.h index bd08988..7dd9ddd 100644 --- a/Source/WebCore/platform/graphics/gpu/PODRedBlackTree.h +++ b/Source/WebCore/platform/graphics/gpu/PODRedBlackTree.h @@ -257,7 +257,7 @@ private: // properly update such summary information based only on the values // in the left and right children. This method should return true if // the node's summary information changed. - virtual bool updateNode(Node* node) { return false; } + virtual bool updateNode(Node*) { return false; } //---------------------------------------------------------------------- // Generic binary search tree operations @@ -713,7 +713,7 @@ private: } #ifdef NDEBUG - void logIfVerbose(const char* output) const { } + void logIfVerbose(const char*) const { } #else void logIfVerbose(const char* output) const { diff --git a/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp b/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp index ea8bc71..662d6a8 100644 --- a/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp +++ b/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp @@ -35,7 +35,10 @@ #include "SharedGraphicsContext3D.h" #include "AffineTransform.h" +#include "BicubicShader.h" #include "Color.h" +#include "ConvolutionShader.h" +#include "DrawingBuffer.h" #include "Extensions3D.h" #include "FloatRect.h" #include "IntSize.h" @@ -43,6 +46,15 @@ #include "SolidFillShader.h" #include "TexShader.h" +#if ENABLE(SKIA_GPU) +#include "GrContext.h" +// Limit the number of textures we hold in the bitmap->texture cache. +static const int maxTextureCacheCount = 512; +// Limit the bytes allocated toward textures in the bitmap->texture cache. +static const size_t maxTextureCacheBytes = 50 * 1024 * 1024; +#endif + +#include <wtf/OwnArrayPtr.h> #include <wtf/text/CString.h> #include <wtf/text/WTFString.h> @@ -65,16 +77,30 @@ PassRefPtr<SharedGraphicsContext3D> SharedGraphicsContext3D::create(HostWindow* OwnPtr<TexShader> texShader = TexShader::create(context.get()); if (!texShader) return 0; - return adoptRef(new SharedGraphicsContext3D(context.release(), solidFillShader.release(), texShader.release())); + OwnPtr<BicubicShader> bicubicShader = BicubicShader::create(context.get()); + if (!bicubicShader) + return 0; + OwnArrayPtr<OwnPtr<ConvolutionShader> > convolutionShaders = adoptArrayPtr(new OwnPtr<ConvolutionShader>[cMaxKernelWidth]); + for (int i = 0; i < cMaxKernelWidth; ++i) { + convolutionShaders[i] = ConvolutionShader::create(context.get(), i + 1); + if (!convolutionShaders[i]) + return 0; + } + return adoptRef(new SharedGraphicsContext3D(context.release(), solidFillShader.release(), texShader.release(), bicubicShader.release(), convolutionShaders.release())); } -SharedGraphicsContext3D::SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<SolidFillShader> solidFillShader, PassOwnPtr<TexShader> texShader) +SharedGraphicsContext3D::SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<SolidFillShader> solidFillShader, PassOwnPtr<TexShader> texShader, PassOwnPtr<BicubicShader> bicubicShader, PassOwnArrayPtr<OwnPtr<ConvolutionShader> > convolutionShaders) : m_context(context) , m_bgraSupported(false) , m_quadVertices(0) , m_solidFillShader(solidFillShader) , m_texShader(texShader) + , m_bicubicShader(bicubicShader) + , m_convolutionShaders(convolutionShaders) , m_oesStandardDerivativesSupported(false) +#if ENABLE(SKIA_GPU) + , m_grContext(0) +#endif { allContexts()->add(this); Extensions3D* extensions = m_context->getExtensions(); @@ -92,6 +118,9 @@ SharedGraphicsContext3D::~SharedGraphicsContext3D() { m_context->deleteBuffer(m_quadVertices); allContexts()->remove(this); +#if ENABLE(SKIA_GPU) + GrSafeUnref(m_grContext); +#endif } void SharedGraphicsContext3D::makeContextCurrent() @@ -369,6 +398,17 @@ void SharedGraphicsContext3D::useTextureProgram(const AffineTransform& transform m_texShader->use(transform, texTransform, 0, alpha); } +void SharedGraphicsContext3D::useBicubicProgram(const AffineTransform& transform, const AffineTransform& texTransform, const float coefficients[16], const float imageIncrement[2], float alpha) +{ + m_bicubicShader->use(transform, texTransform, coefficients, imageIncrement, alpha); +} + +void SharedGraphicsContext3D::useConvolutionProgram(const AffineTransform& transform, const AffineTransform& texTransform, const float* kernel, int kernelWidth, float imageIncrement[2]) +{ + ASSERT(kernelWidth >= 1 && kernelWidth <= cMaxKernelWidth); + m_convolutionShaders[kernelWidth - 1]->use(transform, texTransform, kernel, kernelWidth, imageIncrement); +} + void SharedGraphicsContext3D::bindFramebuffer(Platform3DObject framebuffer) { m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, framebuffer); @@ -411,6 +451,31 @@ void SharedGraphicsContext3D::useLoopBlinnExteriorProgram(unsigned vertexOffset, m_loopBlinnExteriorShader->use(vertexOffset, klmOffset, transform, color); } +DrawingBuffer* SharedGraphicsContext3D::getOffscreenBuffer(unsigned index, const IntSize& size) +{ + if (index >= m_offscreenBuffers.size()) + m_offscreenBuffers.resize(index + 1); + + if (!m_offscreenBuffers[index]) + m_offscreenBuffers[index] = m_context->createDrawingBuffer(size); + + if (size.width() != m_offscreenBuffers[index]->size().width() + || size.height() != m_offscreenBuffers[index]->size().height()) + m_offscreenBuffers[index]->reset(size); + return m_offscreenBuffers[index].get(); +} + +#if ENABLE(SKIA_GPU) +GrContext* SharedGraphicsContext3D::grContext() +{ + if (!m_grContext) { + m_grContext = GrContext::CreateGLShaderContext(); + m_grContext->setTextureCacheLimits(maxTextureCacheCount, maxTextureCacheBytes); + } + return m_grContext; +} +#endif + } // namespace WebCore #endif diff --git a/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h b/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h index 707fd24..8fb3d50 100644 --- a/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h +++ b/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h @@ -38,14 +38,22 @@ #include <wtf/HashMap.h> #include <wtf/HashSet.h> +#include <wtf/OwnArrayPtr.h> #include <wtf/OwnPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> +#if ENABLE(SKIA_GPU) +class GrContext; +#endif + namespace WebCore { class AffineTransform; +class BicubicShader; class Color; +class ConvolutionShader; +class DrawingBuffer; class FloatRect; class HostWindow; class IntSize; @@ -101,6 +109,8 @@ public: void useFillSolidProgram(const AffineTransform&, const Color&); void useTextureProgram(const AffineTransform&, const AffineTransform&, float alpha); + void useBicubicProgram(const AffineTransform&, const AffineTransform&, const float coefficients[16], const float imageIncrement[2], float alpha); + void useConvolutionProgram(const AffineTransform&, const AffineTransform& texTransform, const float* kernel, int kernelWidth, float imageIncrement[2]); void setActiveTexture(GC3Denum textureUnit); void bindTexture(GC3Denum target, Platform3DObject texture); @@ -127,9 +137,14 @@ public: static bool useLoopBlinnForPathRendering(); void useLoopBlinnInteriorProgram(unsigned vertexOffset, const AffineTransform&, const Color&); void useLoopBlinnExteriorProgram(unsigned vertexOffset, unsigned klmOffset, const AffineTransform&, const Color&); + DrawingBuffer* getOffscreenBuffer(unsigned index, const IntSize&); + +#if ENABLE(SKIA_GPU) + GrContext* grContext(); +#endif private: - SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D>, PassOwnPtr<SolidFillShader>, PassOwnPtr<TexShader>); + SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D>, PassOwnPtr<SolidFillShader>, PassOwnPtr<TexShader>, PassOwnPtr<BicubicShader>, PassOwnArrayPtr<OwnPtr<ConvolutionShader> >); // Used to implement removeTexturesFor(), see the comment above. static HashSet<SharedGraphicsContext3D*>* allContexts(); @@ -142,6 +157,8 @@ private: OwnPtr<SolidFillShader> m_solidFillShader; OwnPtr<TexShader> m_texShader; + OwnPtr<BicubicShader> m_bicubicShader; + OwnArrayPtr<OwnPtr<ConvolutionShader> > m_convolutionShaders; TextureHashMap m_textures; @@ -150,8 +167,17 @@ private: OwnPtr<LoopBlinnSolidFillShader> m_loopBlinnInteriorShader; OwnPtr<LoopBlinnSolidFillShader> m_loopBlinnExteriorShader; bool m_oesStandardDerivativesSupported; + + WTF::Vector<RefPtr<DrawingBuffer> > m_offscreenBuffers; + +#if ENABLE(SKIA_GPU) + GrContext* m_grContext; +#endif }; +const float cMaxSigma = 4.0f; +const int cMaxKernelWidth = 25; + } // namespace WebCore #endif // SharedGraphicsContext3D_h diff --git a/Source/WebCore/platform/graphics/gpu/TilingData.cpp b/Source/WebCore/platform/graphics/gpu/TilingData.cpp index dd540b3..1370543 100644 --- a/Source/WebCore/platform/graphics/gpu/TilingData.cpp +++ b/Source/WebCore/platform/graphics/gpu/TilingData.cpp @@ -66,7 +66,7 @@ void TilingData::setTotalSize(int totalSizeX, int totalSizeY) void TilingData::setMaxTextureSize(int maxTextureSize) { - m_maxTextureSize = m_maxTextureSize; + m_maxTextureSize = maxTextureSize; recomputeNumTiles(); } diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp index 3763ef7..2fb4cef 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp @@ -117,6 +117,13 @@ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpo || err->code == GST_RESOURCE_ERROR_NOT_FOUND) error = MediaPlayer::FormatError; else if (err->domain == GST_STREAM_ERROR) { + // Let the mediaPlayerClient handle the stream error, in + // this case the HTMLMediaElement will emit a stalled + // event. + if (err->code == GST_STREAM_ERROR_TYPE_NOT_FOUND) { + LOG_VERBOSE(Media, "Decode error, let the Media element emit a stalled event."); + break; + } error = MediaPlayer::DecodeError; attemptNextLocation = true; } else if (err->domain == GST_RESOURCE_ERROR) @@ -495,7 +502,7 @@ float MediaPlayerPrivateGStreamer::currentTime() const return 0.0f; if (m_seeking) - return static_cast<float>(m_seekTime); + return m_seekTime; return playbackPosition(m_playBin); @@ -513,17 +520,28 @@ void MediaPlayerPrivateGStreamer::seek(float time) if (m_errorOccured) return; - GstClockTime sec = (GstClockTime)(static_cast<float>(time * GST_SECOND)); - LOG_VERBOSE(Media, "Seek: %" GST_TIME_FORMAT, GST_TIME_ARGS(sec)); + // Extract the integer part of the time (seconds) and the + // fractional part (microseconds). Attempt to round the + // microseconds so no floating point precision is lost and we can + // perform an accurate seek. + float seconds; + float microSeconds = modf(time, &seconds) * 1000000; + GTimeVal timeValue; + timeValue.tv_sec = static_cast<glong>(seconds); + timeValue.tv_usec = static_cast<glong>(roundf(microSeconds / 10000) * 10000); + + GstClockTime clockTime = GST_TIMEVAL_TO_TIME(timeValue); + LOG_VERBOSE(Media, "Seek: %" GST_TIME_FORMAT, GST_TIME_ARGS(clockTime)); + if (!gst_element_seek(m_playBin, m_player->rate(), GST_FORMAT_TIME, - (GstSeekFlags)(GST_SEEK_FLAG_FLUSH), - GST_SEEK_TYPE_SET, sec, + (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE), + GST_SEEK_TYPE_SET, clockTime, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) LOG_VERBOSE(Media, "Seek to %f failed", time); else { m_seeking = true; - m_seekTime = sec; + m_seekTime = time; } } @@ -1046,15 +1064,9 @@ void MediaPlayerPrivateGStreamer::updateStates() if (!m_isStreaming && !m_buffering) return; - // Resume playback if a seek was performed in a live pipeline - // or during progressive download. That second use-case - // happens when the seek is performed to a region of the media - // that hasn't been downloaded yet. if (m_seeking) { shouldUpdateAfterSeek = true; m_seeking = false; - if (m_paused) - gst_element_set_state(m_playBin, GST_STATE_PLAYING); } break; case GST_STATE_CHANGE_FAILURE: diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h index 11eb81b..8003887 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h @@ -161,7 +161,7 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface { GstElement* m_videoSinkBin; GstElement* m_fpsSink; GstElement* m_source; - GstClockTime m_seekTime; + float m_seekTime; bool m_changingRate; float m_endTime; bool m_isEndReached; diff --git a/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp index 86e3e7a..66ea9ba 100644 --- a/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp @@ -352,7 +352,7 @@ static void webKitWebSrcStop(WebKitWebSrc* src, bool seeking) } priv->resourceHandle = 0; - if (priv->frame) + if (priv->frame && !seeking) priv->frame.release(); GST_OBJECT_LOCK(src); diff --git a/Source/WebCore/platform/graphics/gtk/FontGtk.cpp b/Source/WebCore/platform/graphics/gtk/FontGtk.cpp index 216fb56..d14b052 100644 --- a/Source/WebCore/platform/graphics/gtk/FontGtk.cpp +++ b/Source/WebCore/platform/graphics/gtk/FontGtk.cpp @@ -35,6 +35,7 @@ #include "CairoUtilities.h" #include "ContextShadow.h" +#include "PlatformContextCairo.h" #include "GraphicsContext.h" #include "NotImplemented.h" #include "SimpleFontData.h" @@ -44,7 +45,7 @@ #include <pango/pango.h> #include <pango/pangocairo.h> -#if defined(USE_FREETYPE) +#if USE(FREETYPE) #include <pango/pangofc-fontmap.h> #endif @@ -171,13 +172,13 @@ static gchar* convertUniCharToUTF8(const UChar* characters, gint length, int fro static void setPangoAttributes(const Font* font, const TextRun& run, PangoLayout* layout) { -#if defined(USE_FREETYPE) +#if USE(FREETYPE) if (font->primaryFont()->platformData().m_pattern) { PangoFontDescription* desc = pango_fc_font_description_from_pattern(font->primaryFont()->platformData().m_pattern.get(), FALSE); pango_layout_set_font_description(layout, desc); pango_font_description_free(desc); } -#elif defined(USE_PANGO) +#elif USE(PANGO) if (font->primaryFont()->platformData().m_font) { PangoFontDescription* desc = pango_font_describe(font->primaryFont()->platformData().m_font); pango_layout_set_font_description(layout, desc); @@ -220,7 +221,7 @@ bool Font::canExpandAroundIdeographsInComplexText() return false; } -static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context, const FloatPoint& point, PangoLayoutLine* layoutLine, PangoRegionType renderRegion) +static void drawGlyphsShadow(GraphicsContext* graphicsContext, const FloatPoint& point, PangoLayoutLine* layoutLine, PangoRegionType renderRegion) { ContextShadow* shadow = graphicsContext->contextShadow(); ASSERT(shadow); @@ -232,6 +233,7 @@ static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context, // Optimize non-blurry shadows, by just drawing text without the ContextShadow. if (!shadow->mustUseContextShadow(graphicsContext)) { + cairo_t* context = graphicsContext->platformContext()->cr(); cairo_save(context); cairo_translate(context, totalOffset.x(), totalOffset.y()); @@ -255,6 +257,7 @@ static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context, // because we don't want any bits and pieces of characters out of range to be // drawn. Since ContextShadow expects a consistent transform, we have to undo the // translation before calling endShadowLayer as well. + cairo_t* context = graphicsContext->platformContext()->cr(); cairo_save(context); cairo_translate(context, totalOffset.x(), totalOffset.y()); gdk_cairo_region(context, renderRegion); @@ -268,14 +271,14 @@ static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context, void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const { -#if defined(USE_FREETYPE) +#if USE(FREETYPE) if (!primaryFont()->platformData().m_pattern) { drawSimpleText(context, run, point, from, to); return; } #endif - cairo_t* cr = context->platformContext(); + cairo_t* cr = context->platformContext()->cr(); PangoLayout* layout = pango_cairo_create_layout(cr); setPangoAttributes(this, run, layout); @@ -294,7 +297,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F int ranges[] = {start - utf8, end - utf8}; partialRegion = gdk_pango_layout_line_get_clip_region(layoutLine, 0, 0, ranges, 1); - drawGlyphsShadow(context, cr, point, layoutLine, partialRegion); + drawGlyphsShadow(context, point, layoutLine, partialRegion); cairo_save(cr); cairo_translate(cr, point.x(), point.y()); @@ -348,7 +351,7 @@ static PangoLayout* getDefaultPangoLayout(const TextRun& run) float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* overflow) const { -#if defined(USE_FREETYPE) +#if USE(FREETYPE) if (!primaryFont()->platformData().m_pattern) return floatWidthForSimpleText(run, 0, fallbackFonts, overflow); #endif @@ -373,7 +376,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool includePartialGlyphs) const { -#if defined(USE_FREETYPE) +#if USE(FREETYPE) if (!primaryFont()->platformData().m_pattern) return offsetForPositionForSimpleText(run, xFloat, includePartialGlyphs); #endif @@ -401,7 +404,7 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const { -#if defined(USE_FREETYPE) +#if USE(FREETYPE) if (!primaryFont()->platformData().m_pattern) return selectionRectForSimpleText(run, point, h, from, to); #endif diff --git a/Source/WebCore/platform/graphics/gtk/IconGtk.cpp b/Source/WebCore/platform/graphics/gtk/IconGtk.cpp index d56b52d..7fdc1f6 100644 --- a/Source/WebCore/platform/graphics/gtk/IconGtk.cpp +++ b/Source/WebCore/platform/graphics/gtk/IconGtk.cpp @@ -33,9 +33,9 @@ #include "GraphicsContext.h" #include "MIMETypeRegistry.h" #include "PassRefPtr.h" -#include <wtf/text/CString.h> - +#include "PlatformContextCairo.h" #include <gtk/gtk.h> +#include <wtf/text/CString.h> namespace WebCore { @@ -117,7 +117,7 @@ void Icon::paint(GraphicsContext* context, const IntRect& rect) return; // TODO: Scale/clip the image if necessary. - cairo_t* cr = context->platformContext(); + cairo_t* cr = context->platformContext()->cr(); cairo_save(cr); gdk_cairo_set_source_pixbuf(cr, m_icon, rect.x(), rect.y()); cairo_paint(cr); diff --git a/Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp b/Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp index 2aa016e..3da0f9b 100644 --- a/Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp +++ b/Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp @@ -54,7 +54,7 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con GError* error = 0; gboolean success = FALSE; if (type == "jpeg" && quality && *quality >= 0.0 && *quality <= 1.0) { - String qualityString = String::format("%f", *quality); + String qualityString = String::format("%f", *quality * 100.0); success = gdk_pixbuf_save_to_buffer(pixbuf.get(), &buffer.outPtr(), &bufferSize, type.utf8().data(), &error, "quality", qualityString.utf8().data(), NULL); } else { diff --git a/Source/WebCore/platform/graphics/gtk/ImageGtk.cpp b/Source/WebCore/platform/graphics/gtk/ImageGtk.cpp index 623ace6..9dd82a9 100644 --- a/Source/WebCore/platform/graphics/gtk/ImageGtk.cpp +++ b/Source/WebCore/platform/graphics/gtk/ImageGtk.cpp @@ -152,7 +152,10 @@ PassRefPtr<Image> Image::loadPlatformThemeIcon(const char* name, int size) GdkPixbuf* BitmapImage::getGdkPixbuf() { - return cairoImageSurfaceToGdkPixbuf(frameAtIndex(currentFrame())); + cairo_surface_t* frame = frameAtIndex(currentFrame()); + if (!frame) + return 0; + return cairoImageSurfaceToGdkPixbuf(frame); } } diff --git a/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp index 017b1e4..352de67 100644 --- a/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp +++ b/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp @@ -31,7 +31,7 @@ FontCustomPlatformData::~FontCustomPlatformData() { } -FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode) +FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode) { return FontPlatformData(size, bold, italic); } diff --git a/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.h index 7ffe89a..a319ce5 100644 --- a/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.h +++ b/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.h @@ -24,6 +24,7 @@ #include "FontOrientation.h" #include "FontRenderingMode.h" #include "FontWidthVariant.h" +#include "TextOrientation.h" #include <wtf/Forward.h> namespace WebCore { @@ -39,7 +40,7 @@ namespace WebCore { static bool supportsFormat(const String&); - FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode); + FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode); }; FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer*); diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp index 1a56664..07bc3ec 100644 --- a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp +++ b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp @@ -63,7 +63,8 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru , m_glyphInCurrentRun(0) , m_characterInCurrentGlyph(0) , m_expansion(run.expansion()) - , m_afterExpansion(true) + , m_leadingExpansion(0) + , m_afterExpansion(!run.allowsLeadingExpansion()) , m_fallbackFonts(fallbackFonts) , m_minGlyphBoundingBoxX(numeric_limits<float>::max()) , m_maxGlyphBoundingBoxX(numeric_limits<float>::min()) @@ -73,7 +74,7 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru if (!m_expansion) m_expansionPerOpportunity = 0; else { - bool isAfterExpansion = true; + bool isAfterExpansion = m_afterExpansion; unsigned expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion); if (isAfterExpansion && !m_run.allowsTrailingExpansion()) expansionOpportunityCount--; @@ -86,12 +87,16 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru collectComplexTextRuns(); adjustGlyphsAndAdvances(); + + m_runWidthSoFar = m_leadingExpansion; } int ComplexTextController::offsetForPosition(float h, bool includePartialGlyphs) { if (h >= m_totalWidth) return m_run.ltr() ? m_end : 0; + + h -= m_leadingExpansion; if (h < 0) return m_run.ltr() ? 0 : m_end; @@ -472,16 +477,21 @@ void ComplexTextController::adjustGlyphsAndAdvances() // Handle justification and word-spacing. if (treatAsSpace || Font::isCJKIdeographOrSymbol(ch)) { // Distribute the run's total expansion evenly over all expansion opportunities in the run. - if (m_expansion && (!lastGlyph || m_run.allowsTrailingExpansion())) { + if (m_expansion) { if (!treatAsSpace && !m_afterExpansion) { // Take the expansion opportunity before this ideograph. m_expansion -= m_expansionPerOpportunity; m_totalWidth += m_expansionPerOpportunity; - m_adjustedAdvances.last().width += m_expansionPerOpportunity; + if (m_adjustedAdvances.isEmpty()) + m_leadingExpansion = m_expansionPerOpportunity; + else + m_adjustedAdvances.last().width += m_expansionPerOpportunity; + } + if (!lastGlyph || m_run.allowsTrailingExpansion()) { + m_expansion -= m_expansionPerOpportunity; + advance.width += m_expansionPerOpportunity; + m_afterExpansion = true; } - m_expansion -= m_expansionPerOpportunity; - advance.width += m_expansionPerOpportunity; - m_afterExpansion = true; } else m_afterExpansion = false; diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextController.h b/Source/WebCore/platform/graphics/mac/ComplexTextController.h index 7373bfe..44a7994 100644 --- a/Source/WebCore/platform/graphics/mac/ComplexTextController.h +++ b/Source/WebCore/platform/graphics/mac/ComplexTextController.h @@ -175,6 +175,7 @@ private: unsigned m_characterInCurrentGlyph; float m_expansion; float m_expansionPerOpportunity; + float m_leadingExpansion; bool m_afterExpansion; HashSet<const SimpleFontData*>* m_fallbackFonts; diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp index b367fdf..d965ada 100644 --- a/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp +++ b/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp @@ -264,7 +264,7 @@ static void disableLigatures(const SimpleFontData* fontData, ATSUStyle atsuStyle // Don't be too aggressive: if the font doesn't contain 'a', then assume that any ligatures it contains are // in characters that always go through ATSUI, and therefore allow them. Geeza Pro is an example. // See bugzilla 5166. - if ((typesettingFeatures & Ligatures) || (fontData->orientation() == Horizontal && fontData->platformData().allowsLigatures())) + if ((typesettingFeatures & Ligatures) || (fontData->platformData().orientation() == Horizontal && fontData->platformData().allowsLigatures())) return; ATSUFontFeatureType featureTypes[] = { kLigaturesType }; diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp index 239113f..d2fbaf5 100644 --- a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp +++ b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp @@ -144,17 +144,17 @@ void ComplexTextController::collectComplexTextRunsForCharactersCoreText(const UC static CFDictionaryRef rtlTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, rtlOptionValues, WTF_ARRAY_LENGTH(optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) - ProviderInfo info = { cp, length, fontData->getCFStringAttributes(m_font.typesettingFeatures()) }; + ProviderInfo info = { cp, length, fontData->getCFStringAttributes(m_font.typesettingFeatures(), fontData->platformData().orientation()) }; RetainPtr<CTTypesetterRef> typesetter(AdoptCF, wkCreateCTTypesetterWithUniCharProviderAndOptions(&provideStringAndAttributes, 0, &info, m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions)); #else RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, cp, length, kCFAllocatorNull)); - RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(m_font.typesettingFeatures()))); + RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(m_font.typesettingFeatures(), fontData->platformData().orientation()))); RetainPtr<CTTypesetterRef> typesetter(AdoptCF, CTTypesetterCreateWithAttributedStringAndOptions(attributedString.get(), m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions)); #endif line.adoptCF(CTTypesetterCreateLine(typesetter.get(), CFRangeMake(0, 0))); } else { - ProviderInfo info = { cp, length, fontData->getCFStringAttributes(m_font.typesettingFeatures()) }; + ProviderInfo info = { cp, length, fontData->getCFStringAttributes(m_font.typesettingFeatures(), fontData->platformData().orientation()) }; line.adoptCF(wkCreateCTLineWithUniCharProvider(&provideStringAndAttributes, 0, &info)); } diff --git a/Source/WebCore/platform/graphics/mac/FontCacheMac.mm b/Source/WebCore/platform/graphics/mac/FontCacheMac.mm index c254906..f7ae6b7 100644 --- a/Source/WebCore/platform/graphics/mac/FontCacheMac.mm +++ b/Source/WebCore/platform/graphics/mac/FontCacheMac.mm @@ -211,7 +211,7 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD bool syntheticBold = isAppKitFontWeightBold(weight) && !isAppKitFontWeightBold(actualWeight); bool syntheticOblique = (traits & NSFontItalicTrait) && !(actualTraits & NSFontItalicTrait); - return new FontPlatformData(platformFont, size, syntheticBold, syntheticOblique, fontDescription.orientation(), fontDescription.widthVariant()); + return new FontPlatformData(platformFont, size, syntheticBold, syntheticOblique, fontDescription.orientation(), fontDescription.textOrientation(), fontDescription.widthVariant()); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp b/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp index eed49a5..fe2a22c 100644 --- a/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp +++ b/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp @@ -111,8 +111,8 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon { ComplexTextController controller(this, run, true, fallbackFonts); if (glyphOverflow) { - glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - fontMetrics().ascent()); - glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - fontMetrics().descent()); + glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent())); + glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent())); glyphOverflow->left = max<int>(0, ceilf(-controller.minGlyphBoundingBoxX())); glyphOverflow->right = max<int>(0, ceilf(controller.maxGlyphBoundingBoxX() - controller.totalWidth())); } diff --git a/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp index f2bc33d..383adef 100644 --- a/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp +++ b/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp @@ -38,9 +38,9 @@ FontCustomPlatformData::~FontCustomPlatformData() CGFontRelease(m_cgFont); } -FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation, FontWidthVariant widthVariant, FontRenderingMode) +FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation, TextOrientation textOrientation, FontWidthVariant widthVariant, FontRenderingMode) { - return FontPlatformData(m_cgFont, size, bold, italic, orientation, widthVariant); + return FontPlatformData(m_cgFont, size, bold, italic, orientation, textOrientation, widthVariant); } FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer) diff --git a/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h index c7ae1ca..c625304 100644 --- a/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h +++ b/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h @@ -24,6 +24,7 @@ #include "FontOrientation.h" #include "FontRenderingMode.h" #include "FontWidthVariant.h" +#include "TextOrientation.h" #include <CoreFoundation/CFBase.h> #include <wtf/Forward.h> #include <wtf/Noncopyable.h> @@ -48,7 +49,7 @@ public: ~FontCustomPlatformData(); - FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode); + FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode); static bool supportsFormat(const String&); diff --git a/Source/WebCore/platform/graphics/mac/FontMac.mm b/Source/WebCore/platform/graphics/mac/FontMac.mm index acd7562..4c28ead 100644 --- a/Source/WebCore/platform/graphics/mac/FontMac.mm +++ b/Source/WebCore/platform/graphics/mac/FontMac.mm @@ -52,28 +52,72 @@ bool Font::canExpandAroundIdeographsInComplexText() return true; } -static void showGlyphsWithAdvances(const SimpleFontData* font, CGContextRef context, const CGGlyph* glyphs, const CGSize* advances, size_t count) +// CTFontGetVerticalTranslationsForGlyphs is different on Snow Leopard. It returns values for a font-size of 1 +// without unitsPerEm applied. We have to apply a transform that scales up to the point size and that also +// divides by unitsPerEm. +static bool hasBrokenCTFontGetVerticalTranslationsForGlyphs() { +// Chromium runs the same binary on both Leopard and Snow Leopard, so the check has to happen at runtime. +#if PLATFORM(CHROMIUM) + static bool isCached = false; + static bool result; + + if (!isCached) { + SInt32 majorVersion = 0; + SInt32 minorVersion = 0; + Gestalt(gestaltSystemVersionMajor, &majorVersion); + Gestalt(gestaltSystemVersionMinor, &minorVersion); + result = majorVersion == 10 && minorVersion == 6; + isCached = true; + } + return result; +#elif defined(BUILDING_ON_SNOW_LEOPARD) + return true; +#else + return false; +#endif +} + +static void showGlyphsWithAdvances(const FloatPoint& point, const SimpleFontData* font, CGContextRef context, const CGGlyph* glyphs, const CGSize* advances, size_t count) +{ + CGContextSetTextPosition(context, point.x(), point.y()); + const FontPlatformData& platformData = font->platformData(); if (!platformData.isColorBitmapFont()) { CGAffineTransform savedMatrix; - bool isVertical = font->orientation() == Vertical; - + bool isVertical = font->platformData().orientation() == Vertical; if (isVertical) { CGAffineTransform rotateLeftTransform = CGAffineTransformMake(0, -1, 1, 0, 0, 0); - savedMatrix = CGContextGetTextMatrix(context); CGAffineTransform runMatrix = CGAffineTransformConcat(savedMatrix, rotateLeftTransform); - // Move start point to put glyphs into original region. - runMatrix.tx = savedMatrix.tx + font->fontMetrics().ascent(); - runMatrix.ty = savedMatrix.ty + font->fontMetrics().descent(); CGContextSetTextMatrix(context, runMatrix); - } - - CGContextShowGlyphsWithAdvances(context, glyphs, advances, count); - - if (isVertical) + + CGAffineTransform translationsTransform; + if (hasBrokenCTFontGetVerticalTranslationsForGlyphs()) { + translationsTransform = CGAffineTransformMake(platformData.m_size, 0, 0, platformData.m_size, 0, 0); + translationsTransform = CGAffineTransformConcat(translationsTransform, rotateLeftTransform); + CGFloat unitsPerEm = CGFontGetUnitsPerEm(platformData.cgFont()); + translationsTransform = CGAffineTransformConcat(translationsTransform, CGAffineTransformMakeScale(1 / unitsPerEm, 1 / unitsPerEm)); + } else { + translationsTransform = rotateLeftTransform; + } + Vector<CGSize, 256> translations(count); + CTFontGetVerticalTranslationsForGlyphs(platformData.ctFont(), glyphs, translations.data(), count); + + CGAffineTransform transform = CGAffineTransformInvert(CGContextGetTextMatrix(context)); + + CGPoint position = FloatPoint(point.x(), point.y() + font->fontMetrics().floatAscent(IdeographicBaseline) - font->fontMetrics().floatAscent()); + Vector<CGPoint, 256> positions(count); + for (size_t i = 0; i < count; ++i) { + CGSize translation = CGSizeApplyAffineTransform(translations[i], translationsTransform); + positions[i] = CGPointApplyAffineTransform(CGPointMake(position.x - translation.width, position.y + translation.height), transform); + position.x += advances[i].width; + position.y += advances[i].height; + } + CGContextShowGlyphsAtPositions(context, glyphs, positions.data(), count); CGContextSetTextMatrix(context, savedMatrix); + } else + CGContextShowGlyphsWithAdvances(context, glyphs, advances, count); } #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) else { @@ -188,21 +232,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); - CGContextSetTextPosition(cgContext, shadowTextX, shadowTextY); - showGlyphsWithAdvances(font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); - if (font->syntheticBoldOffset()) { - CGContextSetTextPosition(cgContext, shadowTextX + font->syntheticBoldOffset(), shadowTextY); - showGlyphsWithAdvances(font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); - } + showGlyphsWithAdvances(FloatPoint(shadowTextX, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + if (font->syntheticBoldOffset()) + showGlyphsWithAdvances(FloatPoint(shadowTextX + font->syntheticBoldOffset(), shadowTextY), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); context->setFillColor(fillColor, fillColorSpace); } - CGContextSetTextPosition(cgContext, point.x(), point.y()); - showGlyphsWithAdvances(font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); - if (font->syntheticBoldOffset()) { - CGContextSetTextPosition(cgContext, point.x() + font->syntheticBoldOffset(), point.y()); - showGlyphsWithAdvances(font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); - } + showGlyphsWithAdvances(point, font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + if (font->syntheticBoldOffset()) + showGlyphsWithAdvances(FloatPoint(point.x() + font->syntheticBoldOffset(), point.y()), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); if (hasSimpleShadow) context->setShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace); diff --git a/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp b/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp index fe2b33a..18d0dc5 100644 --- a/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp +++ b/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp @@ -39,7 +39,7 @@ namespace WebCore { #ifndef BUILDING_ON_TIGER static bool shouldUseCoreText(UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData) { - if (fontData->platformData().widthVariant() != RegularWidth || (fontData->orientation() == Vertical && !fontData->isBrokenIdeographFont())) { + if (fontData->platformData().widthVariant() != RegularWidth || fontData->hasVerticalGlyphs()) { // Ideographs don't have a vertical variant or width variants. for (unsigned i = 0; i < bufferLength; ++i) { if (!Font::isCJKIdeograph(buffer[i])) @@ -70,7 +70,7 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b } else { // We ask CoreText for possible vertical variant glyphs RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull)); - RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(0))); + RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(0, fontData->hasVerticalGlyphs() ? Vertical : Horizontal))); RetainPtr<CTLineRef> line(AdoptCF, CTLineCreateWithAttributedString(attributedString.get())); CFArrayRef runArray = CTLineGetGlyphRuns(line.get()); diff --git a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm index aaa250b..997c976 100644 --- a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm +++ b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm @@ -93,9 +93,14 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWi , m_attrs(attrs) , m_contextObj(0) , m_texture(0) + , m_compositorTexture(0) , m_fbo(0) , m_depthStencilBuffer(0) + , m_layerComposited(false) + , m_internalColorFormat(0) , m_boundFBO(0) + , m_activeTexture(0) + , m_boundTexture0(0) , m_multisampleFBO(0) , m_multisampleDepthStencilBuffer(0) , m_multisampleColorBuffer(0) @@ -166,6 +171,12 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWi ::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); + ::glGenTextures(1, &m_compositorTexture); + ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture); + ::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); ::glBindTexture(GL_TEXTURE_2D, 0); // create an FBO @@ -215,6 +226,7 @@ GraphicsContext3D::~GraphicsContext3D() if (m_contextObj) { CGLSetCurrentContext(m_contextObj); ::glDeleteTextures(1, &m_texture); + ::glDeleteTextures(1, &m_compositorTexture); if (m_attrs.antialias) { ::glDeleteRenderbuffersEXT(1, &m_multisampleColorBuffer); if (m_attrs.stencil || m_attrs.depth) diff --git a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h index 80bc94e..7bdc064 100644 --- a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h +++ b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h @@ -54,6 +54,8 @@ class WebCoreMovieObserver; #endif namespace WebCore { + +class ApplicationCacheResource; class MediaPlayerPrivateQTKit : public MediaPlayerPrivateInterface { public: @@ -139,6 +141,7 @@ private: void createQTMovie(const String& url); void createQTMovie(NSURL *, NSDictionary *movieAttributes); + void createQTMovie(ApplicationCacheResource*); enum MediaRenderingMode { MediaRenderingNone, MediaRenderingMovieView, MediaRenderingSoftwareRenderer, MediaRenderingMovieLayer }; MediaRenderingMode currentRenderingMode() const; @@ -178,6 +181,8 @@ private: virtual double maximumDurationToCacheMediaTime() const { return 5; } virtual void setPrivateBrowsingMode(bool); + + NSMutableDictionary* commonMovieAttributes(); MediaPlayer* m_player; RetainPtr<QTMovie> m_qtMovie; @@ -211,6 +216,7 @@ private: double m_timeStartedPlaying; double m_timeStoppedPlaying; #endif + mutable FloatSize m_cachedNaturalSize; }; } diff --git a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm index ecb7d9f..400fdfb 100644 --- a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm +++ b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm @@ -29,11 +29,18 @@ #import "MediaPlayerPrivateQTKit.h" +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +#include "ApplicationCacheHost.h" +#include "ApplicationCacheResource.h" +#include "DocumentLoader.h" +#endif + #ifdef BUILDING_ON_TIGER #import "AutodrainedPool.h" #endif #import "BlockExceptions.h" +#import "DocumentLoader.h" #import "FrameView.h" #import "GraphicsContext.h" #import "KURL.h" @@ -83,6 +90,7 @@ SOFT_LINK_POINTER(QTKit, QTMediaTypeText, NSString *) SOFT_LINK_POINTER(QTKit, QTMediaTypeVideo, NSString *) SOFT_LINK_POINTER(QTKit, QTMovieAskUnresolvedDataRefsAttribute, NSString *) SOFT_LINK_POINTER(QTKit, QTMovieLoopsAttribute, NSString *) +SOFT_LINK_POINTER(QTKit, QTMovieDataAttribute, NSString *) SOFT_LINK_POINTER(QTKit, QTMovieDataSizeAttribute, NSString *) SOFT_LINK_POINTER(QTKit, QTMovieDidEndNotification, NSString *) SOFT_LINK_POINTER(QTKit, QTMovieHasVideoAttribute, NSString *) @@ -120,6 +128,7 @@ SOFT_LINK_POINTER(QTKit, QTMovieApertureModeAttribute, NSString *) #define QTMediaTypeVideo getQTMediaTypeVideo() #define QTMovieAskUnresolvedDataRefsAttribute getQTMovieAskUnresolvedDataRefsAttribute() #define QTMovieLoopsAttribute getQTMovieLoopsAttribute() +#define QTMovieDataAttribute getQTMovieDataAttribute() #define QTMovieDataSizeAttribute getQTMovieDataSizeAttribute() #define QTMovieDidEndNotification getQTMovieDidEndNotification() #define QTMovieHasVideoAttribute getQTMovieHasVideoAttribute() @@ -241,21 +250,26 @@ MediaPlayerPrivateQTKit::~MediaPlayerPrivateQTKit() [m_objcObserver.get() disconnect]; } -void MediaPlayerPrivateQTKit::createQTMovie(const String& url) +NSMutableDictionary* MediaPlayerPrivateQTKit::commonMovieAttributes() { - NSURL *cocoaURL = KURL(ParsedURLString, url); - NSMutableDictionary *movieAttributes = [NSMutableDictionary dictionaryWithObjectsAndKeys: - cocoaURL, QTMovieURLAttribute, - [NSNumber numberWithBool:m_player->preservesPitch()], QTMovieRateChangesPreservePitchAttribute, - [NSNumber numberWithBool:YES], QTMoviePreventExternalURLLinksAttribute, - [NSNumber numberWithBool:YES], QTSecurityPolicyNoCrossSiteAttribute, - [NSNumber numberWithBool:NO], QTMovieAskUnresolvedDataRefsAttribute, - [NSNumber numberWithBool:NO], QTMovieLoopsAttribute, - [NSNumber numberWithBool:!m_privateBrowsing], @"QTMovieAllowPersistentCacheAttribute", + return [NSMutableDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:m_player->preservesPitch()], QTMovieRateChangesPreservePitchAttribute, + [NSNumber numberWithBool:YES], QTMoviePreventExternalURLLinksAttribute, + [NSNumber numberWithBool:YES], QTSecurityPolicyNoCrossSiteAttribute, + [NSNumber numberWithBool:NO], QTMovieAskUnresolvedDataRefsAttribute, + [NSNumber numberWithBool:NO], QTMovieLoopsAttribute, + [NSNumber numberWithBool:!m_privateBrowsing], @"QTMovieAllowPersistentCacheAttribute", #ifndef BUILDING_ON_TIGER - QTMovieApertureModeClean, QTMovieApertureModeAttribute, + QTMovieApertureModeClean, QTMovieApertureModeAttribute, #endif - nil]; + nil]; +} + +void MediaPlayerPrivateQTKit::createQTMovie(const String& url) +{ + NSURL *cocoaURL = KURL(ParsedURLString, url); + NSMutableDictionary *movieAttributes = commonMovieAttributes(); + [movieAttributes setValue:cocoaURL forKey:QTMovieURLAttribute]; #if !defined(BUILDING_ON_LEOPARD) CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings(); @@ -291,6 +305,33 @@ void MediaPlayerPrivateQTKit::createQTMovie(const String& url) createQTMovie(cocoaURL, movieAttributes); } +void MediaPlayerPrivateQTKit::createQTMovie(ApplicationCacheResource* resource) +{ +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + ASSERT(resource); + + NSMutableDictionary *movieAttributes = commonMovieAttributes(); + [movieAttributes setObject:[NSNumber numberWithBool:YES] forKey:@"QTMovieOpenForPlaybackAttribute"]; + + // ApplicationCacheResources can supply either a data pointer, or a path to a locally cached + // flat file. We would prefer the path over the data, but QTKit can handle either: + String localPath = resource->path(); + NSURL* cocoaURL = !localPath.isEmpty() ? [NSURL fileURLWithPath:localPath isDirectory:NO] : nil; + if (cocoaURL) + [movieAttributes setValue:cocoaURL forKey:QTMovieURLAttribute]; + else { + NSData* movieData = resource->data()->createNSData(); + [movieAttributes setValue:movieData forKey:QTMovieDataAttribute]; + [movieData release]; + } + + createQTMovie(cocoaURL, movieAttributes); + +#else + ASSERT_NOT_REACHED(); +#endif +} + static void disableComponentsOnce() { static bool sComponentsDisabled = false; @@ -658,6 +699,14 @@ void MediaPlayerPrivateQTKit::loadInternal(const String& url) [m_objcObserver.get() setDelayCallbacks:YES]; +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : NULL; + ApplicationCacheHost* cacheHost = frame ? frame->loader()->documentLoader()->applicationCacheHost() : NULL; + ApplicationCacheResource* resource = NULL; + if (cacheHost && cacheHost->shouldLoadResourceFromApplicationCache(ResourceRequest(url), resource) && resource) + createQTMovie(resource); + else +#endif createQTMovie(url); [m_objcObserver.get() loadStateChanged:nil]; @@ -827,8 +876,19 @@ IntSize MediaPlayerPrivateQTKit::naturalSize() const // dimensions, aspect ratio, clean aperture, resolution, and so forth, as defined for the // format used by the resource - NSSize naturalSize = [[m_qtMovie.get() attributeForKey:QTMovieNaturalSizeAttribute] sizeValue]; - return IntSize(naturalSize.width * m_scaleFactor.width(), naturalSize.height * m_scaleFactor.height()); + FloatSize naturalSize([[m_qtMovie.get() attributeForKey:QTMovieNaturalSizeAttribute] sizeValue]); + if (naturalSize.isEmpty() && m_isStreaming) { + // HTTP Live Streams will occasionally return {0,0} natural sizes while scrubbing. + // Work around this problem (<rdar://problem/9078563>) by returning the last valid + // cached natural size: + naturalSize = m_cachedNaturalSize; + } else { + // Unfortunately, due to another QTKit bug (<rdar://problem/9082071>) we won't get a sizeChanged + // event when this happens, so we must cache the last valid naturalSize here: + m_cachedNaturalSize = naturalSize; + } + + return IntSize(naturalSize.width() * m_scaleFactor.width(), naturalSize.height() * m_scaleFactor.height()); } bool MediaPlayerPrivateQTKit::hasVideo() const diff --git a/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp b/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp index 452bd54..832bb9d 100644 --- a/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp +++ b/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp @@ -39,15 +39,17 @@ using namespace std; namespace WebCore { -CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typesettingFeatures) const +CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typesettingFeatures, FontOrientation orientation) const { unsigned key = typesettingFeatures + 1; pair<HashMap<unsigned, RetainPtr<CFDictionaryRef> >::iterator, bool> addResult = m_CFStringAttributes.add(key, RetainPtr<CFDictionaryRef>()); RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.first->second; if (!addResult.second) return attributesDictionary.get(); + + bool treatLineAsVertical = orientation == Vertical; - bool allowLigatures = (orientation() == Horizontal && platformData().allowsLigatures()) || (typesettingFeatures & Ligatures); + bool allowLigatures = (!treatLineAsVertical && platformData().allowsLigatures()) || (typesettingFeatures & Ligatures); static const int ligaturesNotAllowedValue = 0; static CFNumberRef ligaturesNotAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesNotAllowedValue); @@ -60,13 +62,13 @@ CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typese static CFNumberRef kerningAdjustment = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &kerningAdjustmentValue); static const void* keysWithKerningDisabled[] = { kCTFontAttributeName, kCTKernAttributeName, kCTLigatureAttributeName, kCTVerticalFormsAttributeName }; const void* valuesWithKerningDisabled[] = { platformData().ctFont(), kerningAdjustment, allowLigatures - ? ligaturesAllowed : ligaturesNotAllowed, orientation() == Vertical ? kCFBooleanTrue : kCFBooleanFalse }; + ? ligaturesAllowed : ligaturesNotAllowed, treatLineAsVertical ? kCFBooleanTrue : kCFBooleanFalse }; attributesDictionary.adoptCF(CFDictionaryCreate(0, keysWithKerningDisabled, valuesWithKerningDisabled, WTF_ARRAY_LENGTH(keysWithKerningDisabled), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); } else { // By omitting the kCTKernAttributeName attribute, we get Core Text's standard kerning. static const void* keysWithKerningEnabled[] = { kCTFontAttributeName, kCTLigatureAttributeName, kCTVerticalFormsAttributeName }; - const void* valuesWithKerningEnabled[] = { platformData().ctFont(), allowLigatures ? ligaturesAllowed : ligaturesNotAllowed, orientation() == Vertical ? kCFBooleanTrue : kCFBooleanFalse }; + const void* valuesWithKerningEnabled[] = { platformData().ctFont(), allowLigatures ? ligaturesAllowed : ligaturesNotAllowed, treatLineAsVertical ? kCFBooleanTrue : kCFBooleanFalse }; attributesDictionary.adoptCF(CFDictionaryCreate(0, keysWithKerningEnabled, valuesWithKerningEnabled, WTF_ARRAY_LENGTH(keysWithKerningEnabled), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); } diff --git a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm index 3094498..cd34000 100644 --- a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm +++ b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm @@ -259,49 +259,32 @@ void SimpleFontData::platformInit() descent = 3; } - if (m_orientation == Vertical) { - // Ignore vertical orientation when the font doesn't support vertical metrics. + if (platformData().orientation() == Vertical && !isTextOrientationFallback()) { // The check doesn't look neat but this is what AppKit does for vertical writing... RetainPtr<CFArrayRef> tableTags(AdoptCF, CTFontCopyAvailableTables(m_platformData.ctFont(), kCTFontTableOptionExcludeSynthetic)); CFIndex numTables = CFArrayGetCount(tableTags.get()); - bool found = false; for (CFIndex index = 0; index < numTables; ++index) { CTFontTableTag tag = (CTFontTableTag)(uintptr_t)CFArrayGetValueAtIndex(tableTags.get(), index); if (tag == kCTFontTableVhea || tag == kCTFontTableVORG) { - found = true; + m_hasVerticalGlyphs = true; break; } } - - if (found == false) - m_orientation = Horizontal; } float xHeight; - // Measure the actual character "x", because AppKit synthesizes X height rather than getting it from the font. - // Unfortunately, NSFont will round this for us so we don't quite get the right value. - GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page(); - NSGlyph xGlyph = glyphPageZero ? glyphPageZero->glyphDataForCharacter('x').glyph : 0; - if (xGlyph) { - CGRect xBox = platformBoundsForGlyph(xGlyph); - // Use the maximum of either width or height because "x" is nearly square - // and web pages that foolishly use this metric for width will be laid out - // poorly if we return an accurate height. Classic case is Times 13 point, - // which has an "x" that is 7x6 pixels. - xHeight = static_cast<float>(max(CGRectGetMaxX(xBox), -CGRectGetMinY(xBox))); - } else { -#ifndef BUILDING_ON_TIGER - xHeight = static_cast<float>(CGFontGetXHeight(m_platformData.cgFont())) / unitsPerEm; -#else - xHeight = m_platformData.font() ? [m_platformData.font() xHeight] : 0; -#endif - // CGFontGetXHeight() returns a wrong value for "Apple Symbols" font (a float close to 0, but not strictly 0). - // The following code makes a guess for xHeight in that case. - // The int cast is a workaround for the "almost" zero value returned by CGFontGetXHeight(). - if (!static_cast<int>(xHeight) && ascent) - xHeight = 2 * ascent / 3; - } + if (platformData().orientation() == Horizontal) { + // Measure the actual character "x", since it's possible for it to extend below the baseline, and we need the + // reported x-height to only include the portion of the glyph that is above the baseline. + GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page(); + NSGlyph xGlyph = glyphPageZero ? glyphPageZero->glyphDataForCharacter('x').glyph : 0; + if (xGlyph) + xHeight = -CGRectGetMinY(platformBoundsForGlyph(xGlyph)); + else + xHeight = scaleEmToUnits(CGFontGetXHeight(m_platformData.cgFont()), unitsPerEm) * pointSize; + } else + xHeight = verticalRightOrientationFontData()->fontMetrics().xHeight(); m_fontMetrics.setUnitsPerEm(unitsPerEm); m_fontMetrics.setAscent(ascent); @@ -474,17 +457,8 @@ void SimpleFontData::determinePitch() FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const { FloatRect boundingBox; -#ifndef BUILDING_ON_TIGER - boundingBox = CTFontGetBoundingRectsForGlyphs(m_platformData.ctFont(), - orientation() == Vertical ? kCTFontVerticalOrientation : kCTFontHorizontalOrientation, &glyph, 0, 1); + boundingBox = CTFontGetBoundingRectsForGlyphs(m_platformData.ctFont(), platformData().orientation() == Vertical ? kCTFontVerticalOrientation : kCTFontHorizontalOrientation, &glyph, 0, 1); boundingBox.setY(-boundingBox.maxY()); -#else - // FIXME: Custom fonts don't have NSFonts, so this function doesn't compute correct bounds for these on Tiger. - if (!m_platformData.font()) - return boundingBox; - boundingBox = [m_platformData.font() boundingRectForGlyph:glyph]; - boundingBox.setY(-boundingBox.maxY()); -#endif if (m_syntheticBoldOffset) boundingBox.setWidth(boundingBox.width() + m_syntheticBoldOffset); @@ -494,7 +468,7 @@ FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { CGSize advance; - if (orientation() == Horizontal || m_isBrokenIdeographFont) { + if (platformData().orientation() == Horizontal || m_isBrokenIdeographFallback) { NSFont* font = platformData().font(); float pointSize = platformData().m_size; CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize); diff --git a/Source/WebCore/platform/graphics/mac/WebLayer.h b/Source/WebCore/platform/graphics/mac/WebLayer.h index 30bf55b..2e9bea0 100644 --- a/Source/WebCore/platform/graphics/mac/WebLayer.h +++ b/Source/WebCore/platform/graphics/mac/WebLayer.h @@ -32,6 +32,7 @@ namespace WebCore { class GraphicsLayer; + class PlatformCALayer; class PlatformCALayerClient; } @@ -48,7 +49,7 @@ namespace WebCore { @end // Functions allows us to share implementation across WebTiledLayer and WebLayer -void drawLayerContents(CGContextRef, CALayer *, WebCore::PlatformCALayerClient*); +void drawLayerContents(CGContextRef, CALayer *, WebCore::PlatformCALayer*); void setLayerNeedsDisplayInRect(CALayer *, WebCore::PlatformCALayerClient*, CGRect); #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/mac/WebLayer.mm b/Source/WebCore/platform/graphics/mac/WebLayer.mm index 414a75f..c9705d0 100644 --- a/Source/WebCore/platform/graphics/mac/WebLayer.mm +++ b/Source/WebCore/platform/graphics/mac/WebLayer.mm @@ -40,8 +40,9 @@ using namespace WebCore; @implementation WebLayer -void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCALayerClient* layerContents) +void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCALayer* platformLayer) { + WebCore::PlatformCALayerClient* layerContents = platformLayer->owner(); if (!layerContents) return; @@ -62,6 +63,7 @@ void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCA GraphicsContext graphicsContext(context); graphicsContext.setIsCALayerContext(true); + graphicsContext.setIsAcceleratedContext(platformLayer->acceleratesDrawing()); if (!layerContents->platformCALayerContentsOpaque()) { // Turn off font smoothing to improve the appearance of text rendered onto a transparent background. @@ -167,7 +169,7 @@ void setLayerNeedsDisplayInRect(CALayer *layer, WebCore::PlatformCALayerClient* { PlatformCALayer* layer = PlatformCALayer::platformCALayer(self); if (layer) - drawLayerContents(context, self, layer->owner()); + drawLayerContents(context, self, layer); } @end // implementation WebLayer diff --git a/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm b/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm index e9fa5b7..9bcdd54 100644 --- a/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm +++ b/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm @@ -83,7 +83,7 @@ using namespace WebCore; { PlatformCALayer* layer = PlatformCALayer::platformCALayer(self); if (layer) - drawLayerContents(context, self, layer->owner()); + drawLayerContents(context, self, layer); } @end // implementation WebTiledLayer diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp index c224e20..f831550 100644 --- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp @@ -38,6 +38,7 @@ #include "GraphicsContext.h" #include "HTMLCanvasElement.h" #include "ImageBuffer.h" +#include "ImageData.h" #include "Int32Array.h" #include "NotImplemented.h" #include "Uint8Array.h" @@ -53,11 +54,12 @@ namespace WebCore { void GraphicsContext3D::validateAttributes() { - const char* extensions = reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS)); + Extensions3D* extensions = getExtensions(); if (m_attrs.stencil) { - if (std::strstr(extensions, "GL_EXT_packed_depth_stencil")) { - if (!m_attrs.depth) - m_attrs.depth = true; + if (extensions->supports("GL_EXT_packed_depth_stencil")) { + extensions->ensureEnabled("GL_EXT_packed_depth_stencil"); + // Force depth if stencil is true. + m_attrs.depth = true; } else m_attrs.stencil = false; } @@ -67,24 +69,16 @@ void GraphicsContext3D::validateAttributes() const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR)); if (!std::strstr(vendor, "NVIDIA")) isValidVendor = false; - if (!isValidVendor || !std::strstr(extensions, "GL_EXT_framebuffer_multisample")) + if (!isValidVendor || !extensions->supports("GL_ANGLE_framebuffer_multisample")) m_attrs.antialias = false; + else + extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample"); } - // FIXME: instead of enforcing premultipliedAlpha = true, implement the - // correct behavior when premultipliedAlpha = false is requested. - m_attrs.premultipliedAlpha = true; } -void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* context) +void GraphicsContext3D::readRenderingResults(unsigned char *pixels, int pixelsSize) { - HTMLCanvasElement* canvas = context->canvas(); - ImageBuffer* imageBuffer = canvas->buffer(); - - int rowBytes = m_currentWidth * 4; - int totalBytes = rowBytes * m_currentHeight; - - OwnArrayPtr<unsigned char> pixels = adoptArrayPtr(new unsigned char[totalBytes]); - if (!pixels) + if (pixelsSize < m_currentWidth * m_currentHeight * 4) return; makeContextCurrent(); @@ -111,18 +105,62 @@ void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* co mustRestorePackAlignment = true; } - ::glReadPixels(0, 0, m_currentWidth, m_currentHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels.get()); + ::glReadPixels(0, 0, m_currentWidth, m_currentHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels); if (mustRestorePackAlignment) ::glPixelStorei(GL_PACK_ALIGNMENT, packAlignment); if (mustRestoreFBO) ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); +} + +void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* context) +{ + HTMLCanvasElement* canvas = context->canvas(); + ImageBuffer* imageBuffer = canvas->buffer(); + + int rowBytes = m_currentWidth * 4; + int totalBytes = rowBytes * m_currentHeight; + + OwnArrayPtr<unsigned char> pixels = adoptArrayPtr(new unsigned char[totalBytes]); + if (!pixels) + return; + + readRenderingResults(pixels.get(), totalBytes); + + if (!m_attrs.premultipliedAlpha) { + for (int i = 0; i < totalBytes; i += 4) { + // Premultiply alpha + pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255); + pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255); + pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255); + } + } paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight, canvas->width(), canvas->height(), imageBuffer->context()->platformContext()); } +PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData() +{ + // Reading premultiplied alpha would involve unpremultiplying, which is + // lossy + if (m_attrs.premultipliedAlpha) + return 0; + + RefPtr<ImageData> imageData = ImageData::create(IntSize(m_currentWidth, m_currentHeight)); + unsigned char* pixels = imageData->data()->data()->data(); + int totalBytes = 4 * m_currentWidth * m_currentHeight; + + readRenderingResults(pixels, totalBytes); + + // Convert to RGBA + for (int i = 0; i < totalBytes; i += 4) + std::swap(pixels[i], pixels[i + 2]); + + return imageData.release(); +} + void GraphicsContext3D::reshape(int width, int height) { if (!m_contextObj) @@ -135,19 +173,23 @@ void GraphicsContext3D::reshape(int width, int height) m_currentHeight = height; makeContextCurrent(); - - GLuint internalColorFormat, colorFormat, internalDepthStencilFormat = 0; + validateAttributes(); + + GLuint colorFormat, internalDepthStencilFormat = 0; if (m_attrs.alpha) { - internalColorFormat = GL_RGBA8; + m_internalColorFormat = GL_RGBA8; colorFormat = GL_RGBA; } else { - internalColorFormat = GL_RGB8; + m_internalColorFormat = GL_RGB8; colorFormat = GL_RGB; } if (m_attrs.stencil || m_attrs.depth) { // We don't allow the logic where stencil is required and depth is not. - // See GraphicsContext3D constructor. - if (m_attrs.stencil && m_attrs.depth) + // See GraphicsContext3D::validateAttributes. + + Extensions3D* extensions = getExtensions(); + // Use a 24 bit depth buffer where we know we have it + if (extensions->supports("GL_EXT_packed_depth_stencil")) internalDepthStencilFormat = GL_DEPTH24_STENCIL8_EXT; else internalDepthStencilFormat = GL_DEPTH_COMPONENT; @@ -167,7 +209,7 @@ void GraphicsContext3D::reshape(int width, int height) mustRestoreFBO = true; } ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); - ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, internalColorFormat, width, height); + ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, m_internalColorFormat, width, height); ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); if (m_attrs.stencil || m_attrs.depth) { ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); @@ -190,8 +232,10 @@ void GraphicsContext3D::reshape(int width, int height) ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); } ::glBindTexture(GL_TEXTURE_2D, m_texture); - ::glTexImage2D(GL_TEXTURE_2D, 0, internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); + ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, 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); ::glBindTexture(GL_TEXTURE_2D, 0); if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth)) { ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthStencilBuffer); @@ -278,19 +322,29 @@ IntSize GraphicsContext3D::getInternalFramebufferSize() void GraphicsContext3D::prepareTexture() { + if (m_layerComposited) + return; makeContextCurrent(); if (m_attrs.antialias) { ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); ::glBlitFramebufferEXT(0, 0, m_currentWidth, m_currentHeight, 0, 0, m_currentWidth, m_currentHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); } + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + ::glActiveTexture(0); + ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture); + ::glCopyTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, 0, 0, m_currentWidth, m_currentHeight, 0); + ::glBindTexture(GL_TEXTURE_2D, m_boundTexture0); + ::glActiveTexture(m_activeTexture); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); ::glFinish(); + m_layerComposited = true; } void GraphicsContext3D::activeTexture(GC3Denum texture) { makeContextCurrent(); + m_activeTexture = texture; ::glActiveTexture(texture); } @@ -340,6 +394,8 @@ void GraphicsContext3D::bindRenderbuffer(GC3Denum target, Platform3DObject rende void GraphicsContext3D::bindTexture(GC3Denum target, Platform3DObject texture) { makeContextCurrent(); + if (m_activeTexture && target == GL_TEXTURE_2D) + m_boundTexture0 = texture; ::glBindTexture(target, texture); } @@ -1442,6 +1498,21 @@ void GraphicsContext3D::synthesizeGLError(GC3Denum error) m_syntheticErrors.add(error); } +void GraphicsContext3D::markContextChanged() +{ + m_layerComposited = false; +} + +void GraphicsContext3D::markLayerComposited() +{ + m_layerComposited = true; +} + +bool GraphicsContext3D::layerComposited() const +{ + return m_layerComposited; +} + Extensions3D* GraphicsContext3D::getExtensions() { if (!m_extensions) diff --git a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp index 2e2082d..9765937 100644 --- a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp +++ b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp @@ -21,11 +21,11 @@ #include "TextureMapperGL.h" #include "GraphicsContext.h" -#include "HashMap.h" #include "Image.h" -#include "PassRefPtr.h" -#include "RefCounted.h" #include "Timer.h" +#include <wtf/HashMap.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> #if defined(TEXMAP_OPENGL_ES_2) #include <GLES2/gl2.h> diff --git a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.h b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.h index 8035abf..92c5198 100644 --- a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.h +++ b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.h @@ -24,8 +24,8 @@ #include "FloatQuad.h" #include "IntSize.h" +#include "TextureMapper.h" #include "TransformationMatrix.h" -#include "texmap/TextureMapper.h" namespace WebCore { diff --git a/Source/WebCore/platform/graphics/openvg/PathOpenVG.cpp b/Source/WebCore/platform/graphics/openvg/PathOpenVG.cpp index 39a4b06..95df242 100644 --- a/Source/WebCore/platform/graphics/openvg/PathOpenVG.cpp +++ b/Source/WebCore/platform/graphics/openvg/PathOpenVG.cpp @@ -169,7 +169,7 @@ FloatRect Path::boundingRect() const return FloatRect(FloatPoint(minX, minY), FloatSize(width, height)); } -FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) +FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const { notImplemented(); @@ -464,7 +464,7 @@ void Path::transform(const AffineTransform& transformation) // functions and Path::apply() doesn't really work as long as we rely on VGPath // as primary path storage. -float Path::length() +float Path::length() const { m_path->makeCompatibleContextCurrent(); VGfloat length = vgPathLength(m_path->vgPath(), 0, vgGetParameteri(m_path->vgPath(), VG_PATH_NUM_SEGMENTS)); @@ -472,7 +472,7 @@ float Path::length() return length; } -FloatPoint Path::pointAtLength(float length, bool& ok) +FloatPoint Path::pointAtLength(float length, bool& ok) const { VGfloat x = 0, y = 0; m_path->makeCompatibleContextCurrent(); @@ -483,7 +483,7 @@ FloatPoint Path::pointAtLength(float length, bool& ok) return FloatPoint(x, y); } -float Path::normalAngleAtLength(float length, bool& ok) +float Path::normalAngleAtLength(float length, bool& ok) const { VGfloat tangentX, tangentY; m_path->makeCompatibleContextCurrent(); diff --git a/Source/WebCore/platform/graphics/pango/FontCustomPlatformDataPango.cpp b/Source/WebCore/platform/graphics/pango/FontCustomPlatformDataPango.cpp index f9d36d3..deff9f7 100644 --- a/Source/WebCore/platform/graphics/pango/FontCustomPlatformDataPango.cpp +++ b/Source/WebCore/platform/graphics/pango/FontCustomPlatformDataPango.cpp @@ -30,7 +30,7 @@ FontCustomPlatformData::~FontCustomPlatformData() { } -FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode) +FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode) { return FontPlatformData(m_fontFace, size, bold, italic); } diff --git a/Source/WebCore/platform/graphics/pango/FontPlatformData.h b/Source/WebCore/platform/graphics/pango/FontPlatformData.h index 2929a3f..180d23b 100644 --- a/Source/WebCore/platform/graphics/pango/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/pango/FontPlatformData.h @@ -74,7 +74,7 @@ public: unsigned hash() const { uintptr_t hashCodes[1] = { reinterpret_cast<uintptr_t>(m_scaledFont) }; - return WTF::StringHasher::createBlobHash<sizeof(hashCodes)>(hashCodes); + return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes); } bool operator==(const FontPlatformData&) const; diff --git a/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp b/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp index dcea72f..3adc93f 100644 --- a/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp +++ b/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp @@ -30,6 +30,7 @@ #include "Extensions3DQt.h" #include "GraphicsContext3D.h" +#include <QGLContext> namespace WebCore { diff --git a/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h index e8441d2..3996d22 100644 --- a/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h +++ b/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h @@ -25,6 +25,7 @@ #include "FontOrientation.h" #include "FontRenderingMode.h" #include "FontWidthVariant.h" +#include "TextOrientation.h" #include <wtf/FastAllocBase.h> #include <wtf/Forward.h> #include <wtf/Noncopyable.h> @@ -43,7 +44,8 @@ public: // for use with QFontDatabase::addApplicationFont/removeApplicationFont int m_handle; - FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode); + FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight, + FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode); static bool supportsFormat(const String&); }; diff --git a/Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp b/Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp index ec8747d..20f161a 100644 --- a/Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp +++ b/Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp @@ -34,7 +34,7 @@ FontCustomPlatformData::~FontCustomPlatformData() QFontDatabase::removeApplicationFont(m_handle); } -FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode) +FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode) { QFont font; font.setFamily(QFontDatabase::applicationFontFamilies(m_handle)[0]); diff --git a/Source/WebCore/platform/graphics/qt/FontPlatformData.h b/Source/WebCore/platform/graphics/qt/FontPlatformData.h index 32e8a2d..4a92acf 100644 --- a/Source/WebCore/platform/graphics/qt/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/qt/FontPlatformData.h @@ -141,6 +141,7 @@ public: } FontOrientation orientation() const { return Horizontal; } // FIXME: Implement. + void setOrientation(FontOrientation) { } // FIXME: Implement. unsigned hash() const; diff --git a/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp b/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp index 185ae85..95dabd5 100644 --- a/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp +++ b/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp @@ -73,9 +73,7 @@ FontPlatformData::FontPlatformData(const FontDescription& description, const Ato font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing); const bool smallCaps = description.smallCaps(); font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase); -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) font.setStyleStrategy(QFont::ForceIntegerMetrics); -#endif m_data->bold = font.bold(); // WebKit allows font size zero but QFont does not. We will return diff --git a/Source/WebCore/platform/graphics/qt/FontQt.cpp b/Source/WebCore/platform/graphics/qt/FontQt.cpp index 646cd0e..3fe90a4 100644 --- a/Source/WebCore/platform/graphics/qt/FontQt.cpp +++ b/Source/WebCore/platform/graphics/qt/FontQt.cpp @@ -169,21 +169,16 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float p->restore(); return; } -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) int skipWidth = QFontMetrics(font).width(string, from, Qt::TextBypassShaping); pt.setX(pt.x() + skipWidth); string = fromRawDataWithoutRef(sanitized, from, to - from); -#endif } p->setFont(font); int flags = run.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight; -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) - // See QWebPagePrivate::QWebPagePrivate() where the default path is set to Complex for Qt 4.6 and earlier. if (!isComplexText && !(ctx->textDrawingMode() & TextModeStroke)) flags |= Qt::TextBypassShaping; -#endif QPainterPath textStrokePath; if (ctx->textDrawingMode() & TextModeStroke) @@ -200,11 +195,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float p->restore(); } else { QFontMetrics fm(font); -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string, -1, flags), fm.height()); -#else - QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string), fm.height()); -#endif QPainter* shadowPainter = ctxShadow->beginShadowLayer(ctx, boundingRect); if (shadowPainter) { // Since it will be blurred anyway, we don't care about render hints. @@ -221,11 +212,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float p->translate(-ctxShadow->offset()); } else { QFontMetrics fm(font); -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string, -1, flags), fm.height()); -#else - QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string), fm.height()); -#endif QPainter* shadowPainter = ctxShadow->beginShadowLayer(ctx, boundingRect); if (shadowPainter) { // Since it will be blurred anyway, we don't care about render hints. @@ -250,11 +237,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float void Font::drawSimpleText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const { -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) drawTextCommon(ctx, run, point, from, to, font(), /* isComplexText = */false); -#else - Q_ASSERT(false); -#endif } void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const @@ -295,7 +278,6 @@ float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer if (!primaryFont()->platformData().size()) return 0; -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) if (!run.length()) return 0; @@ -309,10 +291,6 @@ float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer w -= m_wordSpacing; return w + run.expansion(); -#else - Q_ASSERT(false); - return 0; -#endif } float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const @@ -339,7 +317,6 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon int Font::offsetForPositionForSimpleText(const TextRun& run, float position, bool includePartialGlyphs) const { -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) String sanitized = Font::normalizeSpaces(run.characters(), run.length()); QString string = fromRawDataWithoutRef(sanitized); @@ -359,10 +336,6 @@ int Font::offsetForPositionForSimpleText(const TextRun& run, float position, boo } while (++curPos < string.size()); return curPos; -#else - Q_ASSERT(false); - return 0; -#endif } int Font::offsetForPositionForComplexText(const TextRun& run, float position, bool) const @@ -377,7 +350,6 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float position, bo FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const { -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) String sanitized = Font::normalizeSpaces(run.characters(), run.length()); QString wholeText = fromRawDataWithoutRef(sanitized); QString selectedText = fromRawDataWithoutRef(sanitized, from, qMin(to - from, wholeText.length() - from)); @@ -386,10 +358,6 @@ FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& int width = QFontMetrics(font()).width(selectedText, -1, Qt::TextBypassShaping); return FloatRect(pt.x() + startX, pt.y(), width, h); -#else - Q_ASSERT(false); - return FloatRect(); -#endif } FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp index b849214..4daa4dc 100644 --- a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp +++ b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp @@ -27,10 +27,14 @@ #include "HTMLCanvasElement.h" #include "HostWindow.h" #include "ImageBuffer.h" +#include "ImageData.h" #include "NotImplemented.h" #include "QWebPageClient.h" +#include "qwebpage.h" #include <QAbstractScrollArea> +#include <QGraphicsObject> #include <QGLContext> +#include <QStyleOptionGraphicsItem> #include <wtf/UnusedParam.h> #include <wtf/text/CString.h> @@ -42,6 +46,10 @@ namespace WebCore { typedef char GLchar; #endif +#if !defined(GL_DEPTH24_STENCIL8) +#define GL_DEPTH24_STENCIL8 0x88F0 +#endif + #if !defined(APIENTRY) #define APIENTRY #endif @@ -145,13 +153,17 @@ typedef void (APIENTRY* glVertexAttrib4fType) (GLuint, const GLfloat, const GLfl typedef void (APIENTRY* glVertexAttrib4fvType) (GLuint, const GLfloat*); typedef void (APIENTRY* glVertexAttribPointerType) (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid*); -class GraphicsContext3DInternal { +class GraphicsContext3DInternal : public QGraphicsObject { public: GraphicsContext3DInternal(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow); ~GraphicsContext3DInternal(); - bool isContextValid() { return m_contextValid; } - QGLWidget* getOwnerGLWidget(QWebPageClient* webPageClient); + bool isValid() { return m_valid; } + + QGLWidget* getViewportGLWidget(); + void reshape(int width, int height); + void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*); + QRectF boundingRect() const; glActiveTextureType activeTexture; glAttachShaderType attachShader; @@ -247,11 +259,13 @@ public: GraphicsContext3D::Attributes m_attrs; HostWindow* m_hostWindow; QGLWidget* m_glWidget; + QGLWidget* m_viewportGLWidget; + QRectF m_boundingRect; GLuint m_texture; - GLuint m_mainFbo; + GLuint m_canvasFbo; GLuint m_currentFbo; GLuint m_depthBuffer; - QImage m_pixels; + bool m_layerComposited; ListHashSet<unsigned int> m_syntheticErrors; OwnPtr<Extensions3DQt> m_extensions; @@ -259,7 +273,7 @@ public: private: void* getProcAddress(const String& proc); - bool m_contextValid; + bool m_valid; }; #if defined (QT_OPENGL_ES_2) @@ -281,39 +295,37 @@ GraphicsContext3DInternal::GraphicsContext3DInternal(GraphicsContext3D::Attribut : m_attrs(attrs) , m_hostWindow(hostWindow) , m_glWidget(0) + , m_viewportGLWidget(0) , m_texture(0) - , m_mainFbo(0) + , m_canvasFbo(0) , m_currentFbo(0) , m_depthBuffer(0) - , m_contextValid(true) + , m_layerComposited(false) + , m_valid(true) { - QWebPageClient* webPageClient = hostWindow->platformPageClient(); - QGLWidget* ownerGLWidget = getOwnerGLWidget(webPageClient); + m_viewportGLWidget = getViewportGLWidget(); - if (ownerGLWidget) - m_glWidget = new QGLWidget(0, ownerGLWidget); - else { - QGLFormat format; - format.setDepth(true); - format.setSampleBuffers(true); - format.setStencil(false); - - m_glWidget = new QGLWidget(format); - } + if (m_viewportGLWidget) + m_glWidget = new QGLWidget(0, m_viewportGLWidget); + else + m_glWidget = new QGLWidget(); if (!m_glWidget->isValid()) { - LOG_ERROR("GraphicsContext3D: QGLWidget does not have a valid context"); - m_contextValid = false; + LOG_ERROR("GraphicsContext3D: QGLWidget initialization failed."); + m_valid = false; return; } - - QGLFormat format = m_glWidget->format(); - m_attrs.alpha = format.alpha(); - m_attrs.depth = format.depth(); - m_attrs.stencil = format.stencil(); + // Geometry can be set to zero because m_glWidget is used only for its QGLContext. + m_glWidget->setGeometry(0, 0, 0, 0); + +#if defined(QT_OPENGL_ES_2) + m_attrs.stencil = false; +#else + if (m_attrs.stencil) + m_attrs.depth = true; +#endif m_attrs.antialias = false; - m_attrs.premultipliedAlpha = true; m_glWidget->makeCurrent(); @@ -408,60 +420,165 @@ GraphicsContext3DInternal::GraphicsContext3DInternal(GraphicsContext3D::Attribut vertexAttrib4fv = GET_PROC_ADDRESS(glVertexAttrib4fv); vertexAttribPointer = GET_PROC_ADDRESS(glVertexAttribPointer); - if (!m_contextValid) { + if (!m_valid) { LOG_ERROR("GraphicsContext3D: All needed OpenGL extensions are not available"); - m_contextValid = false; return; } + // Create buffers for the canvas FBO. + genFramebuffers(/* count */ 1, &m_canvasFbo); + 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); - glTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0); glBindTexture(GraphicsContext3D::TEXTURE_2D, 0); - genFramebuffers(/* count */ 1, &m_mainFbo); - m_currentFbo = m_mainFbo; + if (m_attrs.depth) + genRenderbuffers(/* count */ 1, &m_depthBuffer); + + // Bind canvas FBO and set initial clear color to black. + m_currentFbo = m_canvasFbo; + bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_canvasFbo); + glClearColor(0.0, 0.0, 0.0, 0.0); +} + +GraphicsContext3DInternal::~GraphicsContext3DInternal() +{ + delete m_glWidget; + m_glWidget = 0; +} + +QGLWidget* GraphicsContext3DInternal::getViewportGLWidget() +{ + QWebPageClient* webPageClient = m_hostWindow->platformPageClient(); + if (!webPageClient) + return 0; + + QAbstractScrollArea* scrollArea = qobject_cast<QAbstractScrollArea*>(webPageClient->ownerWidget()); + if (scrollArea) + return qobject_cast<QGLWidget*>(scrollArea->viewport()); + + return 0; +} + +static inline quint32 swapBgrToRgb(quint32 pixel) +{ + return ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00); +} + +void GraphicsContext3DInternal::reshape(int width, int height) +{ + if (width == m_boundingRect.width() && height == m_boundingRect.height()) + return; + + m_boundingRect = QRectF(QPointF(0, 0), QSizeF(width, height)); + + m_glWidget->makeCurrent(); - bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_mainFbo); + // Create color buffer + glBindTexture(GraphicsContext3D::TEXTURE_2D, m_texture); + if (m_attrs.alpha) + glTexImage2D(GraphicsContext3D::TEXTURE_2D, /* level */ 0, GraphicsContext3D::RGBA, width, height, /* border */ 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, /* data */ 0); + else + glTexImage2D(GraphicsContext3D::TEXTURE_2D, /* level */ 0, GraphicsContext3D::RGB, width, height, /* border */ 0, GraphicsContext3D::RGB, GraphicsContext3D::UNSIGNED_BYTE, /* data */ 0); + glBindTexture(GraphicsContext3D::TEXTURE_2D, 0); - genRenderbuffers(/* count */ 1, &m_depthBuffer); - bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthBuffer); + if (m_attrs.depth) { + // Create depth and stencil buffers. + bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthBuffer); #if defined(QT_OPENGL_ES_2) - renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, /* width */ 1, /* height */ 1); + renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, width, height); #else - renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT, /* width */ 1, /* height */ 1); + if (m_attrs.stencil) + renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); + else + renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT, width, height); #endif + bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0); + } - bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0); - + // Construct canvas FBO. + bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_canvasFbo); framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_texture, 0); - framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer); - glClearColor(/* red */ 0, /* green */ 0, /* blue */ 0, /* alpha */ 0); + if (m_attrs.depth) + framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer); +#if !defined(QT_OPENGL_ES_2) + if (m_attrs.stencil) + framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer); +#endif - if (checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { - LOG_ERROR("GraphicsContext3D: Wasn't able to create the main framebuffer"); - m_contextValid = false; + GLenum status = checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER); + if (status != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { + LOG_ERROR("GraphicsContext3D: Canvas FBO initialization failed."); + return; } -} -GraphicsContext3DInternal::~GraphicsContext3DInternal() -{ - delete m_glWidget; - m_glWidget = 0; + int clearFlags = GraphicsContext3D::COLOR_BUFFER_BIT; + if (m_attrs.depth) + clearFlags |= GraphicsContext3D::DEPTH_BUFFER_BIT; + if (m_attrs.stencil) + clearFlags |= GraphicsContext3D::STENCIL_BUFFER_BIT; + + glClear(clearFlags); + glFlush(); } -QGLWidget* GraphicsContext3DInternal::getOwnerGLWidget(QWebPageClient* webPageClient) +void GraphicsContext3DInternal::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { - QAbstractScrollArea* scrollArea = qobject_cast<QAbstractScrollArea*>(webPageClient->ownerWidget()); + Q_UNUSED(widget); - if (scrollArea) - return qobject_cast<QGLWidget*>(scrollArea->viewport()); + QRectF rect = option ? option->rect : boundingRect(); - return 0; + // Use direct texture mapping if WebGL canvas has a shared OpenGL context + // with browsers OpenGL context. + QGLWidget* viewportGLWidget = getViewportGLWidget(); + if (viewportGLWidget && viewportGLWidget == m_viewportGLWidget && viewportGLWidget == painter->device()) { + viewportGLWidget->drawTexture(rect, m_texture); + return; + } + + // Alternatively read pixels to a memory buffer. + QImage offscreenImage(rect.width(), rect.height(), QImage::Format_ARGB32); + quint32* imagePixels = reinterpret_cast<quint32*>(offscreenImage.bits()); + + m_glWidget->makeCurrent(); + bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_canvasFbo); + glReadPixels(/* x */ 0, /* y */ 0, rect.width(), rect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, imagePixels); + + bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_currentFbo); + + // OpenGL gives us ABGR on 32 bits, and with the origin at the bottom left + // We need RGB32 or ARGB32_PM, with the origin at the top left. + quint32* pixelsSrc = imagePixels; + const int height = static_cast<int>(rect.height()); + const int width = static_cast<int>(rect.width()); + const int halfHeight = height / 2; + for (int row = 0; row < halfHeight; ++row) { + const int targetIdx = (height - 1 - row) * width; + quint32* pixelsDst = imagePixels + targetIdx; + for (int column = 0; column < width; ++column) { + quint32 tempPixel = *pixelsSrc; + *pixelsSrc = swapBgrToRgb(*pixelsDst); + *pixelsDst = swapBgrToRgb(tempPixel); + ++pixelsSrc; + ++pixelsDst; + } + } + if (static_cast<int>(height) % 2) { + for (int column = 0; column < width; ++column) { + *pixelsSrc = swapBgrToRgb(*pixelsSrc); + ++pixelsSrc; + } + } + painter->drawImage(/* x */ 0, /* y */ 0, offscreenImage); +} + +QRectF GraphicsContext3DInternal::boundingRect() const +{ + return m_boundingRect; } void* GraphicsContext3DInternal::getProcAddress(const String& proc) @@ -477,7 +594,7 @@ void* GraphicsContext3DInternal::getProcAddress(const String& proc) } LOG_ERROR("GraphicsContext3D: Did not find GL function %s", proc.utf8().data()); - m_contextValid = false; + m_valid = false; return 0; } @@ -493,7 +610,7 @@ PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attri GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, bool) : m_internal(new GraphicsContext3DInternal(attrs, hostWindow)) { - if (!m_internal->isContextValid()) + if (!m_internal->isValid()) m_internal = 0; } @@ -511,6 +628,11 @@ Platform3DObject GraphicsContext3D::platformTexture() const return m_internal->m_texture; } +PlatformLayer* GraphicsContext3D::platformLayer() const +{ + return m_internal.get(); +} + void GraphicsContext3D::makeContextCurrent() { m_internal->m_glWidget->makeCurrent(); @@ -522,62 +644,25 @@ void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* co HTMLCanvasElement* canvas = context->canvas(); ImageBuffer* imageBuffer = canvas->buffer(); QPainter* painter = imageBuffer->context()->platformContext(); - paint(painter, QRect(QPoint(0, 0), QSize(m_currentWidth, m_currentHeight))); + m_internal->paint(painter, 0, 0); } -void GraphicsContext3D::paint(QPainter* painter, const QRect& rect) const +PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData() { -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) - QWebPageClient* webPageClient = m_internal->m_hostWindow->platformPageClient(); - QGLWidget* ownerGLWidget = m_internal->getOwnerGLWidget(webPageClient); - if (ownerGLWidget) { - ownerGLWidget->drawTexture(rect, m_internal->m_texture); - return; - } -#endif - m_internal->m_glWidget->makeCurrent(); - m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_mainFbo); - glReadPixels(/* x */ 0, /* y */ 0, m_currentWidth, m_currentHeight, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, m_internal->m_pixels.bits()); - painter->drawImage(/* x */ 0, /* y */ 0, m_internal->m_pixels.rgbSwapped().transformed(QMatrix().rotate(180))); - m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_currentFbo); + // FIXME: This needs to be implemented for proper non-premultiplied-alpha + // support. + return 0; } void GraphicsContext3D::reshape(int width, int height) { - if (((width == m_currentWidth) && (height == m_currentHeight)) || (!m_internal)) + if (width == m_currentWidth && height == m_currentHeight || (!m_internal)) return; - + m_currentWidth = width; m_currentHeight = height; - m_internal->m_pixels = QImage(m_currentWidth, m_currentHeight, QImage::Format_ARGB32); - - m_internal->m_glWidget->makeCurrent(); - - glBindTexture(GraphicsContext3D::TEXTURE_2D, m_internal->m_texture); - glTexImage2D(GraphicsContext3D::TEXTURE_2D, /* level */ 0, GraphicsContext3D::RGBA, width, height, /* border */ 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, /* data */ 0); - glBindTexture(GraphicsContext3D::TEXTURE_2D, 0); - - m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_mainFbo); - m_internal->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_internal->m_depthBuffer); -#if defined(QT_OPENGL_ES_2) - renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, width, height); -#else - renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT, width, height); -#endif - m_internal->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0); - - m_internal->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_internal->m_texture, 0); - m_internal->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_internal->m_depthBuffer); - - GLenum status = m_internal->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER); - if (status != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { - LOG_ERROR("GraphicsContext3D: Wasn't able to reshape the main framebuffer"); - notImplemented(); - } - - glClear(GraphicsContext3D::COLOR_BUFFER_BIT); - glFlush(); + m_internal->reshape(width, height); } IntSize GraphicsContext3D::getInternalFramebufferSize() @@ -626,7 +711,7 @@ void GraphicsContext3D::bindBuffer(GC3Denum target, Platform3DObject buffer) void GraphicsContext3D::bindFramebuffer(GC3Denum target, Platform3DObject buffer) { m_internal->m_glWidget->makeCurrent(); - m_internal->m_currentFbo = buffer ? buffer : m_internal->m_mainFbo; + m_internal->m_currentFbo = buffer ? buffer : m_internal->m_canvasFbo; m_internal->bindFramebuffer(target, m_internal->m_currentFbo); } @@ -1064,6 +1149,23 @@ void GraphicsContext3D::releaseShaderCompiler() void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) { m_internal->m_glWidget->makeCurrent(); +#if !defined(QT_OPENGL_ES_2) + switch (internalformat) { + case DEPTH_STENCIL: + internalformat = GL_DEPTH24_STENCIL8; + break; + case DEPTH_COMPONENT16: + internalformat = DEPTH_COMPONENT; + break; + case RGBA4: + case RGB5_A1: + internalformat = RGBA; + break; + case RGB565: + internalformat = RGB; + break; + } +#endif m_internal->renderbufferStorage(target, internalformat, width, height); } @@ -1598,6 +1700,22 @@ void GraphicsContext3D::synthesizeGLError(GC3Denum error) m_internal->m_syntheticErrors.add(error); } +void GraphicsContext3D::markLayerComposited() +{ + m_internal->m_layerComposited = true; +} + +void GraphicsContext3D::markContextChanged() +{ + // FIXME: Any accelerated compositor needs to be told to re-read from here. + m_internal->m_layerComposited = false; +} + +bool GraphicsContext3D::layerComposited() const +{ + return m_internal->m_layerComposited; +} + Extensions3D* GraphicsContext3D::getExtensions() { if (!m_internal->m_extensions) diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 9742755..e3e0fa6 100644 --- a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -9,6 +9,7 @@ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2008 Dirk Schulze <vbs85@gmx.de> * Copyright (C) 2010, 2011 Sencha, Inc. + * Copyright (C) 2011 Andreas Kling <kling@webkit.org> * * All rights reserved. * @@ -672,8 +673,6 @@ void GraphicsContext::fillRect(const FloatRect& rect) ContextShadow* shadow = contextShadow(); if (m_state.fillPattern) { - AffineTransform affine; - QBrush brush(m_state.fillPattern->createPlatformPattern(affine)); QPixmap* image = m_state.fillPattern->tileImage()->nativeImageForCurrentFrame(); QPainter* shadowPainter = hasShadow() ? shadow->beginShadowLayer(this, normalizedRect) : 0; if (shadowPainter) { diff --git a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp index f3cfc47..1f77fc2 100644 --- a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp +++ b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp @@ -310,10 +310,6 @@ public: } } m_state; -#if ENABLE(WEBGL) - const GraphicsContext3D* m_gc3D; -#endif - #ifndef QT_NO_ANIMATION friend class AnimationQtBase; #endif @@ -340,9 +336,6 @@ GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer) #if ENABLE(TILED_BACKING_STORE) , m_tiledBackingStore(0) #endif -#if ENABLE(WEBGL) - , m_gc3D(0) -#endif { // We use graphics-view for compositing-only, not for interactivity. setAcceptedMouseButtons(Qt::NoButton); @@ -665,11 +658,6 @@ void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsIte case MediaContentType: // we don't need to paint anything: we have a QGraphicsItem from the media element break; -#if ENABLE(WEBGL) - case Canvas3DContentType: - m_gc3D->paint(painter, option->rect); - break; -#endif } } @@ -808,16 +796,6 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform setFlag(ItemHasNoContents, !m_layer->drawsContent()); break; - -#if ENABLE(WEBGL) - case Canvas3DContentType: - if (m_pendingContent.contentType != m_currentContent.contentType) - update(); - - setCacheMode(NoCache); - setFlag(ItemHasNoContents, false); - break; -#endif } } @@ -1268,23 +1246,6 @@ void GraphicsLayerQt::setContentsBackgroundColor(const Color& color) GraphicsLayer::setContentsBackgroundColor(color); } -#if ENABLE(WEBGL) -void GraphicsLayerQt::setContentsToGraphicsContext3D(const GraphicsContext3D* ctx) -{ - if (ctx == m_impl->m_gc3D) - return; - - m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::Canvas3DContentType; - m_impl->m_gc3D = ctx; - m_impl->notifyChange(GraphicsLayerQtImpl::ContentChange); -} - -void GraphicsLayerQt::setGraphicsContext3DNeedsDisplay() -{ - setNeedsDisplay(); -} -#endif - void GraphicsLayerQt::setContentsToMedia(PlatformLayer* media) { if (media) { @@ -1297,6 +1258,11 @@ void GraphicsLayerQt::setContentsToMedia(PlatformLayer* media) GraphicsLayer::setContentsToMedia(media); } +void GraphicsLayerQt::setContentsToCanvas(PlatformLayer* canvas) +{ + setContentsToMedia(canvas); +} + /* \reimp (GraphicsLayer.h) */ void GraphicsLayerQt::setContentsOrientation(CompositingCoordinatesOrientation orientation) diff --git a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h index 569bd8d..2af98fd 100644 --- a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h +++ b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h @@ -20,9 +20,6 @@ #ifndef GraphicsLayerQt_h #define GraphicsLayerQt_h -#if ENABLE(WEBGL) -#include "GraphicsContext3D.h" -#endif #include "GraphicsLayer.h" #include "GraphicsLayerClient.h" @@ -78,11 +75,8 @@ public: virtual void setContentsToImage(Image*); virtual void setContentsNeedsDisplay(); virtual void setContentsToMedia(PlatformLayer*); + virtual void setContentsToCanvas(PlatformLayer*); virtual void setContentsBackgroundColor(const Color&); -#if ENABLE(WEBGL) - virtual void setContentsToGraphicsContext3D(const GraphicsContext3D*); - virtual void setGraphicsContext3DNeedsDisplay(); -#endif virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation); virtual void distributeOpacity(float); virtual float accumulatedOpacity() const; diff --git a/Source/WebCore/platform/graphics/qt/ImageBufferData.h b/Source/WebCore/platform/graphics/qt/ImageBufferData.h index aa32253..602197e 100644 --- a/Source/WebCore/platform/graphics/qt/ImageBufferData.h +++ b/Source/WebCore/platform/graphics/qt/ImageBufferData.h @@ -42,6 +42,8 @@ class ImageBufferData { public: ImageBufferData(const IntSize&); + 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 62f5c3e..f7d63ca 100644 --- a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp +++ b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp @@ -80,6 +80,21 @@ ImageBufferData::ImageBufferData(const IntSize& size) 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, ColorSpace, RenderingMode, bool& success) : m_data(size) , m_size(size) @@ -159,7 +174,7 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) if (isPainting) m_data.m_painter->end(); - QImage image = m_data.m_pixmap.toImage().convertToFormat(QImage::Format_ARGB32); + QImage image = m_data.toQImage().convertToFormat(QImage::Format_ARGB32); ASSERT(!image.isNull()); uchar* bits = image.bits(); @@ -214,16 +229,12 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& i int numRows = endy - originy; // NOTE: For unmultiplied data, we undo the premultiplication below. - QImage image = imageData.m_pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); + QImage image = imageData.toQImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); ASSERT(!image.isNull()); const int bytesPerLine = image.bytesPerLine(); -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) const uchar* bits = image.constBits(); -#else - const uchar* bits = image.bits(); -#endif quint32* destRows = reinterpret_cast_ptr<quint32*>(&data[desty * rect.width() * 4 + destx * 4]); diff --git a/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp index 3540994..8cda231 100644 --- a/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp +++ b/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp @@ -194,15 +194,7 @@ void ImageDecoderQt::internalReadImage(size_t frameIndex) bool ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex) { - QPixmap pixmap; - -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) - pixmap = QPixmap::fromImageReader(m_reader.get()); -#else - QImage img; - if (m_reader->read(&img)) - pixmap = QPixmap::fromImage(img); -#endif + QPixmap pixmap = QPixmap::fromImageReader(m_reader.get()); if (pixmap.isNull()) { frameCount(); diff --git a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp index 001d45b..bc43acf 100644 --- a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp +++ b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp @@ -74,7 +74,7 @@ void MediaPlayerPrivateQt::getSupportedTypes(HashSet<String> &supported) for (int i = 0; i < types.size(); i++) { QString mime = types.at(i); - if (mime.startsWith("audio/") || mime.startsWith("video/")) + if (mime.startsWith(QString::fromLatin1("audio/")) || mime.startsWith(QString::fromLatin1("video/"))) supported.add(mime); } } @@ -103,7 +103,6 @@ MediaPlayerPrivateQt::MediaPlayerPrivateQt(MediaPlayer* player) , m_isVisible(false) , m_isSeeking(false) , m_composited(false) - , m_queuedSeek(-1) , m_preload(MediaPlayer::Auto) , m_suppressNextPlaybackChanged(false) { @@ -195,7 +194,7 @@ void MediaPlayerPrivateQt::commitLoad(const String& url) HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient()); // Construct the media content with a network request if the resource is http[s] - if (scheme == "http" || scheme == "https") { + if (scheme == QString::fromLatin1("http") || scheme == QString::fromLatin1("https")) { QNetworkRequest request = QNetworkRequest(rUrl); // Grab the current document @@ -220,7 +219,7 @@ void MediaPlayerPrivateQt::commitLoad(const String& url) // Set the refferer, but not when requesting insecure content from a secure page QUrl documentUrl = QUrl(QString(document->documentURI())); - if (documentUrl.scheme().toLower() == "http" || scheme == "https") + if (documentUrl.scheme().toLower() == QString::fromLatin1("http") || scheme == QString::fromLatin1("https")) request.setRawHeader("Referer", documentUrl.toEncoded()); // Set the user agent @@ -296,32 +295,8 @@ void MediaPlayerPrivateQt::seek(float position) if (m_mediaPlayerControl && !m_mediaPlayerControl->availablePlaybackRanges().contains(position * 1000)) return; - if (m_isSeeking) - return; - - if (position > duration()) - position = duration(); - - // Seeking is most reliable when we're paused. - // Webkit will try to pause before seeking, but due to the asynchronous nature - // of the backend, the player may not actually be paused yet. - // In this case, we should queue the seek and wait until pausing has completed - // before attempting to seek. - if (m_mediaPlayer->state() == QMediaPlayer::PlayingState) { - m_mediaPlayer->pause(); - m_isSeeking = true; - m_queuedSeek = static_cast<qint64>(position * 1000); - - // Set a timeout, so that in the event that we don't get a state changed - // signal, we still attempt the seek. - QTimer::singleShot(1000, this, SLOT(queuedSeekTimeout())); - } else { - m_isSeeking = true; - m_mediaPlayer->setPosition(static_cast<qint64>(position * 1000)); - - // Set a timeout, in case we don't get a position changed signal - QTimer::singleShot(10000, this, SLOT(seekTimeout())); - } + m_isSeeking = true; + m_mediaPlayer->setPosition(static_cast<qint64>(position * 1000)); } bool MediaPlayerPrivateQt::seeking() const @@ -443,13 +418,8 @@ void MediaPlayerPrivateQt::handleError(QMediaPlayer::Error) updateStates(); } -void MediaPlayerPrivateQt::stateChanged(QMediaPlayer::State state) +void MediaPlayerPrivateQt::stateChanged(QMediaPlayer::State) { - if (state != QMediaPlayer::PlayingState && m_isSeeking && m_queuedSeek >= 0) { - m_mediaPlayer->setPosition(m_queuedSeek); - m_queuedSeek = -1; - } - if (!m_suppressNextPlaybackChanged) m_webCorePlayer->playbackStateChanged(); else @@ -468,34 +438,12 @@ void MediaPlayerPrivateQt::nativeSizeChanged(const QSizeF& size) m_webCorePlayer->sizeChanged(); } -void MediaPlayerPrivateQt::queuedSeekTimeout() -{ - // If we haven't heard anything, assume the player is now paused - // and we can attempt the seek - if (m_isSeeking && m_queuedSeek >= 0) { - m_mediaPlayer->setPosition(m_queuedSeek); - m_queuedSeek = -1; - - // Set a timeout, in case we don't get a position changed signal - QTimer::singleShot(10000, this, SLOT(seekTimeout())); - } -} - -void MediaPlayerPrivateQt::seekTimeout() -{ - // If we haven't heard anything, assume the seek succeeded - if (m_isSeeking) { - m_webCorePlayer->timeChanged(); - m_isSeeking = false; - } -} - void MediaPlayerPrivateQt::positionChanged(qint64) { // Only propagate this event if we are seeking - if (m_isSeeking && m_queuedSeek == -1) { - m_webCorePlayer->timeChanged(); + if (m_isSeeking) { m_isSeeking = false; + m_webCorePlayer->timeChanged(); } } @@ -649,7 +597,7 @@ void MediaPlayerPrivateQt::repaint() #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) -class TextureMapperVideoLayerQt : public virtual TextureMapperVideoLayer { +class TextureMapperVideoLayerQt : public virtual TextureMapperMediaLayer { public: TextureMapperVideoLayerQt(QGraphicsVideoItem* videoItem) : m_videoItem(videoItem) diff --git a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h index 81cdd79..c6398c9 100644 --- a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h +++ b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h @@ -33,7 +33,7 @@ QT_END_NAMESPACE namespace WebCore { -class TextureMapperVideoLayer; +class TextureMapperMediaLayer; class MediaPlayerPrivateQt : public QObject, public MediaPlayerPrivateInterface { @@ -120,8 +120,6 @@ private slots: void handleError(QMediaPlayer::Error); void stateChanged(QMediaPlayer::State); void nativeSizeChanged(const QSizeF&); - void queuedSeekTimeout(); - void seekTimeout(); void positionChanged(qint64); void durationChanged(qint64); void bufferStatusChanged(int); @@ -141,7 +139,7 @@ private: QGraphicsVideoItem* m_videoItem; QGraphicsScene* m_videoScene; #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) - OwnPtr<TextureMapperVideoLayer> m_platformLayer; + OwnPtr<TextureMapperMediaLayer> m_platformLayer; #endif mutable MediaPlayer::NetworkState m_networkState; @@ -153,7 +151,6 @@ private: bool m_isVisible; bool m_isSeeking; bool m_composited; - qint64 m_queuedSeek; MediaPlayer::Preload m_preload; bool m_delayingLoad; String m_mediaUrl; diff --git a/Source/WebCore/platform/graphics/qt/PathQt.cpp b/Source/WebCore/platform/graphics/qt/PathQt.cpp index ad482f7..ccc7f3d 100644 --- a/Source/WebCore/platform/graphics/qt/PathQt.cpp +++ b/Source/WebCore/platform/graphics/qt/PathQt.cpp @@ -154,7 +154,7 @@ FloatRect Path::boundingRect() const return m_path.boundingRect(); } -FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) +FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const { GraphicsContext* context = scratchContext(); QPainterPathStroker stroke; @@ -398,23 +398,15 @@ void Path::apply(void* info, PathApplierFunction function) const void Path::transform(const AffineTransform& transform) { QTransform qTransform(transform); -#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) - // Workaround for http://bugreports.qt.nokia.com/browse/QTBUG-11264 - // QTransform.map doesn't handle the MoveTo element because of the isEmpty issue - if (m_path.isEmpty() && m_path.elementCount()) { - QPointF point = qTransform.map(m_path.currentPosition()); - moveTo(point); - } else -#endif - m_path = qTransform.map(m_path); -} - -float Path::length() + m_path = qTransform.map(m_path); +} + +float Path::length() const { return m_path.length(); } -FloatPoint Path::pointAtLength(float length, bool& ok) +FloatPoint Path::pointAtLength(float length, bool& ok) const { ok = (length >= 0 && length <= m_path.length()); @@ -424,7 +416,7 @@ FloatPoint Path::pointAtLength(float length, bool& ok) return point; } -float Path::normalAngleAtLength(float length, bool& ok) +float Path::normalAngleAtLength(float length, bool& ok) const { ok = (length >= 0 && length <= m_path.length()); diff --git a/Source/WebCore/platform/graphics/qt/TileQt.cpp b/Source/WebCore/platform/graphics/qt/TileQt.cpp index 096ce14..8723cd4 100644 --- a/Source/WebCore/platform/graphics/qt/TileQt.cpp +++ b/Source/WebCore/platform/graphics/qt/TileQt.cpp @@ -91,10 +91,10 @@ void Tile::invalidate(const IntRect& dirtyRect) *m_dirtyRegion += tileDirtyRect; } -void Tile::updateBackBuffer() +Vector<IntRect> Tile::updateBackBuffer() { if (m_buffer && !isDirty()) - return; + return Vector<IntRect>(); if (!m_backBuffer) { if (!m_buffer) { @@ -115,15 +115,19 @@ void Tile::updateBackBuffer() GraphicsContext context(&painter); context.translate(-m_rect.x(), -m_rect.y()); + Vector<IntRect> updatedRects; int size = dirtyRects.size(); for (int n = 0; n < size; ++n) { context.save(); IntRect rect = dirtyRects[n]; + updatedRects.append(rect); context.clip(FloatRect(rect)); context.scale(FloatSize(m_backingStore->m_contentsScale, m_backingStore->m_contentsScale)); m_backingStore->m_client->tiledBackingStorePaint(&context, m_backingStore->mapToContents(rect)); context.restore(); } + + return updatedRects; } void Tile::swapBackBufferToFront() diff --git a/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp index 0e68c21..cc695a5 100644 --- a/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp +++ b/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp @@ -65,7 +65,8 @@ FontCustomPlatformData::~FontCustomPlatformData() #endif } -FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation, FontWidthVariant, FontRenderingMode mode) +FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation, + TextOrientation textOrientation, FontWidthVariant, FontRenderingMode mode) { #if OS(WINDOWS) ASSERT(m_fontReference); @@ -102,7 +103,7 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b return FontPlatformData(hfont, size); #elif OS(LINUX) || OS(FREEBSD) || PLATFORM(BREWMP) ASSERT(m_fontReference); - return FontPlatformData(m_fontReference, "", size, bold && !m_fontReference->isBold(), italic && !m_fontReference->isItalic(), orientation); + return FontPlatformData(m_fontReference, "", size, bold && !m_fontReference->isBold(), italic && !m_fontReference->isItalic(), orientation, textOrientation); #else notImplemented(); return FontPlatformData(); diff --git a/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.h index 2dee3ab..b68722b 100644 --- a/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.h +++ b/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.h @@ -35,6 +35,7 @@ #include "FontOrientation.h" #include "FontRenderingMode.h" #include "FontWidthVariant.h" +#include "TextOrientation.h" #include <wtf/Forward.h> #include <wtf/Noncopyable.h> @@ -66,8 +67,8 @@ public: ~FontCustomPlatformData(); - FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, - FontRenderingMode = NormalRenderingMode); + FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight, + FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode); static bool supportsFormat(const String&); diff --git a/Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp b/Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp index 66e6839..f362fa3 100644 --- a/Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp @@ -91,7 +91,7 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b return false; } - if ((fontData->orientation() == Vertical) && (!fontData->isBrokenIdeographFont())) { + if (fontData->hasVerticalGlyphs()) { bool lookVariants = false; for (unsigned i = 0; i < bufferLength; ++i) { if (!Font::isCJKIdeograph(buffer[i])) { diff --git a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index 00afd07..df680eb 100644 --- a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -1025,6 +1025,14 @@ void GraphicsContext::setPlatformShadow(const FloatSize& size, if (paintingDisabled()) return; + if (platformContext()->useGPU()) { + GLES2Canvas* canvas = platformContext()->gpuCanvas(); + canvas->setShadowOffset(size); + canvas->setShadowBlur(blurFloat); + canvas->setShadowColor(color, colorSpace); + canvas->setShadowsIgnoreTransforms(m_state.shadowsIgnoreTransforms); + } + // Detect when there's no effective shadow and clear the looper. if (!size.width() && !size.height() && !blurFloat) { platformContext()->setDrawLooper(0); @@ -1035,14 +1043,15 @@ void GraphicsContext::setPlatformShadow(const FloatSize& size, double height = size.height(); double blur = blurFloat; - SkBlurDrawLooper::BlurFlags blurFlags = SkBlurDrawLooper::kNone_BlurFlag; + uint32_t blurFlags = SkBlurDrawLooper::kHighQuality_BlurFlag | + SkBlurDrawLooper::kOverrideColor_BlurFlag; if (m_state.shadowsIgnoreTransforms) { // Currently only the GraphicsContext associated with the // CanvasRenderingContext for HTMLCanvasElement have shadows ignore // Transforms. So with this flag set, we know this state is associated // with a CanvasRenderingContext. - blurFlags = SkBlurDrawLooper::kIgnoreTransform_BlurFlag; + blurFlags |= SkBlurDrawLooper::kIgnoreTransform_BlurFlag; // CG uses natural orientation for Y axis, but the HTML5 canvas spec // does not. diff --git a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp index 2721523..b89c68d 100644 --- a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp @@ -341,6 +341,28 @@ void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& so putImageData<Premultiplied>(source, sourceSize, sourceRect, destPoint, context()->platformContext()->canvas()->getDevice(), m_size); } +template <typename T> +static String ImageToDataURL(T& source, const String& mimeType, const double* quality) +{ + Vector<unsigned char> encodedImage; + if (mimeType == "image/jpeg") { + int compressionQuality = JPEGImageEncoder::DefaultCompressionQuality; + if (quality && *quality >= 0.0 && *quality <= 1.0) + compressionQuality = static_cast<int>(*quality * 100 + 0.5); + if (!JPEGImageEncoder::encode(source, compressionQuality, &encodedImage)) + return "data:,"; + } else { + if (!PNGImageEncoder::encode(source, &encodedImage)) + return "data:,"; + ASSERT(mimeType == "image/png"); + } + + Vector<char> base64Data; + base64Encode(*reinterpret_cast<Vector<char>*>(&encodedImage), base64Data); + + return makeString("data:", mimeType, ";base64,", base64Data); +} + String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const { ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); @@ -358,23 +380,13 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con if (!device->readPixels(bounds, &bitmap)) return "data:,"; } - - if (mimeType == "image/jpeg") { - int compressionQuality = JPEGImageEncoder::DefaultCompressionQuality; - if (quality && *quality >= 0.0 && *quality <= 1.0) - compressionQuality = static_cast<int>(*quality * 100 + 0.5); - if (!JPEGImageEncoder::encode(bitmap, compressionQuality, &encodedImage)) - return "data:,"; - } else { - if (!PNGImageEncoder::encode(bitmap, &encodedImage)) - return "data:,"; - ASSERT(mimeType == "image/png"); - } - Vector<char> base64Data; - base64Encode(*reinterpret_cast<Vector<char>*>(&encodedImage), base64Data); + return ImageToDataURL(bitmap, mimeType, quality); +} - return makeString("data:", mimeType, ";base64,", base64Data); +String ImageDataToDataURL(const ImageData& source, const String& mimeType, const double* quality) +{ + return ImageToDataURL(source, mimeType, quality); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp index 91a4e4f..72bec29 100644 --- a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp @@ -260,6 +260,7 @@ static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImag paint.setXfermodeMode(compOp); paint.setFilterBitmap(true); paint.setAlpha(platformContext->getNormalizedAlpha()); + paint.setLooper(platformContext->getDrawLooper()); skia::PlatformCanvas* canvas = platformContext->canvas(); diff --git a/Source/WebCore/platform/graphics/skia/PathSkia.cpp b/Source/WebCore/platform/graphics/skia/PathSkia.cpp index 0344086..b037a0d 100644 --- a/Source/WebCore/platform/graphics/skia/PathSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/PathSkia.cpp @@ -228,7 +228,7 @@ void Path::transform(const AffineTransform& xform) m_path->transform(xform); } -FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) +FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const { GraphicsContext* scratch = scratchContext(); scratch->save(); diff --git a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp index eac5e4a..8e1937f 100644 --- a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp @@ -68,18 +68,6 @@ namespace WebCore { -#if ENABLE(SKIA_GPU) -GrContext* GetGlobalGrContext() -{ - static GrContext* gGR; - if (!gGR) { - gGR = GrContext::CreateGLShaderContext(); - gGR->setTextureCacheLimits(512, 50 * 1024 * 1024); - } - return gGR; -} -#endif - extern bool isPathSkiaSafe(const SkMatrix& transform, const SkPath& path); // State ----------------------------------------------------------------------- @@ -241,8 +229,14 @@ PlatformContextSkia::PlatformContextSkia(skia::PlatformCanvas* canvas) PlatformContextSkia::~PlatformContextSkia() { #if ENABLE(ACCELERATED_2D_CANVAS) - if (m_gpuCanvas) + if (m_gpuCanvas) { +#if ENABLE(SKIA_GPU) + // make sure everything related to this platform context has been flushed + if (!m_useGPU) + m_gpuCanvas->context()->grContext()->flush(0); +#endif m_gpuCanvas->drawingBuffer()->setWillPublishCallback(0); + } #endif } @@ -697,8 +691,7 @@ void PlatformContextSkia::applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths) bool PlatformContextSkia::canAccelerate() const { - return !m_state->m_fillShader // Can't accelerate with a fill gradient or pattern. - && !m_state->m_looper; // Can't accelerate with a shadow. + return !m_state->m_fillShader; // Can't accelerate with a fill gradient or pattern. } bool PlatformContextSkia::canvasClipApplied() const @@ -741,8 +734,10 @@ void PlatformContextSkia::setSharedGraphicsContext3D(SharedGraphicsContext3D* co context->makeContextCurrent(); m_gpuCanvas->bindFramebuffer(); - GrContext* gr = GetGlobalGrContext(); + GrContext* gr = context->grContext(); gr->resetContext(); + drawingBuffer->setGrContext(gr); + SkDeviceFactory* factory = new SkGpuDeviceFactory(gr, SkGpuDevice::Current3DApiRenderTarget()); SkDevice* device = factory->newDevice(m_canvas, SkBitmap::kARGB_8888_Config, drawingBuffer->size().width(), drawingBuffer->size().height(), false, false); m_canvas->setDevice(device)->unref(); diff --git a/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp b/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp index 54aa35e..b0cb0c7 100644 --- a/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp +++ b/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp @@ -380,6 +380,11 @@ bool paintSkiaText(GraphicsContext* context, paint.reset(); platformContext->setupPaintForStroking(&paint, 0, 0); paint.setFlags(SkPaint::kAntiAlias_Flag); +#if ENABLE(SKIA_TEXT) + paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + setupPaintForFont(hfont, &paint); +#endif + if (didFill) { // If there is a shadow and we filled above, there will already be // a shadow. We don't want to draw it again or it will be too dark @@ -390,7 +395,7 @@ bool paintSkiaText(GraphicsContext* context, // thing would be to draw to a new layer and then draw that layer // with a shadow. But this is a lot of extra work for something // that isn't normally an issue. - SkSafeUnref(paint.setLooper(0)); + paint.setLooper(0); } if (!skiaDrawText(hfont, dc, platformContext->canvas(), *origin, &paint, diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp index 4698239..760ba6c 100644 --- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp +++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp @@ -336,7 +336,7 @@ void GraphicsLayerTextureMapper::setContentsToMedia(PlatformLayer* media) notifyChange(TextureMapperNode::ContentChange); m_pendingContent.contentType = media ? TextureMapperNode::MediaContentType : TextureMapperNode::HTMLContentType; if (media) - m_pendingContent.media = static_cast<TextureMapperVideoLayer*>(media); + m_pendingContent.media = static_cast<TextureMapperMediaLayer*>(media); else m_pendingContent.media = 0; } @@ -366,13 +366,6 @@ void GraphicsLayerTextureMapper::syncCompositingState() } /* \reimp (GraphicsLayer.h) - */ -NativeLayer GraphicsLayerTextureMapper::nativeLayer() const -{ - return m_node.get(); -} - -/* \reimp (GraphicsLayer.h) */ PlatformLayer* GraphicsLayerTextureMapper::platformLayer() const { diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h index 47a27c6..dcf4938 100644 --- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h +++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h @@ -81,7 +81,6 @@ public: virtual void syncCompositingState(); virtual void syncCompositingStateForThisLayerOnly(); virtual void setName(const String& name); - virtual NativeLayer nativeLayer() const; virtual PlatformLayer* platformLayer() const; virtual bool addAnimation(const KeyframeValueList&, const IntSize& /*boxSize*/, const Animation*, const String& /*keyframesName*/, double /*timeOffset*/) { return false; } diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.h b/Source/WebCore/platform/graphics/texmap/TextureMapper.h index 589fda1..8e46e3c 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapper.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.h @@ -31,6 +31,7 @@ #include "IntRect.h" #include "IntSize.h" #include "TransformationMatrix.h" +#include <wtf/UnusedParam.h> /* TextureMapper is a mechanism that enables hardware acceleration of CSS animations (accelerated compositing) without @@ -68,7 +69,7 @@ public: return beginPaint(IntRect(0, 0, size().width(), size().height())); } virtual void setContentsToImage(Image*) = 0; - virtual bool save(const String& filename) { return false; } + virtual bool save(const String&) { return false; } inline void lock() { ++m_lockCount; } inline void unlock() { --m_lockCount; } @@ -101,6 +102,7 @@ public: virtual void bindSurface(BitmapTexture* surface) = 0; virtual void paintToTarget(const BitmapTexture& texture, const IntSize&, const TransformationMatrix& matrix, float opacity, const IntRect& visibleRect) { + UNUSED_PARAM(visibleRect); drawTexture(texture, IntRect(0, 0, texture.contentSize().width(), texture.contentSize().height()), matrix, opacity, 0); } diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h index 9694043..c5decc1 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h @@ -20,19 +20,19 @@ #ifndef TextureMapperNode_h #define TextureMapperNode_h -#include "CurrentTime.h" #include "FloatRect.h" #include "GraphicsContext.h" #include "GraphicsLayer.h" -#include "HashMap.h" #include "Image.h" -#include "RefCounted.h" #include "TextureMapper.h" #include "TextureMapperPlatformLayer.h" #include "Timer.h" #include "TransformOperations.h" #include "TranslateTransformOperation.h" #include "UnitBezier.h" +#include <wtf/CurrentTime.h> +#include <wtf/HashMap.h> +#include <wtf/RefCounted.h> namespace WebCore { @@ -94,7 +94,7 @@ public: ContentType contentType; RefPtr<Image> image; - TextureMapperVideoLayer* media; + TextureMapperMediaLayer* media; ContentData() : needsDisplay(false) diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h index 2a38b90..d2d646a 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h @@ -43,7 +43,7 @@ class TextureMapperPlatformLayer { public: enum Type { ContentLayer, - VideoLayer + MediaLayer }; virtual Type layerType() const = 0; @@ -66,13 +66,11 @@ public: virtual Type layerType() const { return ContentLayer; } }; -#if ENABLE(VIDEO) -class TextureMapperVideoLayer : public TextureMapperPlatformLayer { +class TextureMapperMediaLayer : public TextureMapperPlatformLayer { public: virtual void paint(GraphicsContext*) = 0; - virtual Type layerType() const { return VideoLayer; } + virtual Type layerType() const { return MediaLayer; } }; -#endif } diff --git a/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.cpp b/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.cpp index a8ad131..b1ea99b 100644 --- a/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.cpp +++ b/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.cpp @@ -21,6 +21,7 @@ #include "config.h" #include "TranslateTransformOperation.h" +#include "FloatConversion.h" namespace WebCore { @@ -30,15 +31,15 @@ PassRefPtr<TransformOperation> TranslateTransformOperation::blend(const Transfor return this; if (blendToIdentity) - return TranslateTransformOperation::create(Length(m_x.type()).blend(m_x, progress), - Length(m_y.type()).blend(m_y, progress), - Length(m_z.type()).blend(m_z, progress), m_type); + return TranslateTransformOperation::create(Length(m_x.type()).blend(m_x, narrowPrecisionToFloat(progress)), + Length(m_y.type()).blend(m_y, narrowPrecisionToFloat(progress)), + Length(m_z.type()).blend(m_z, narrowPrecisionToFloat(progress)), m_type); const TranslateTransformOperation* fromOp = static_cast<const TranslateTransformOperation*>(from); Length fromX = fromOp ? fromOp->m_x : Length(m_x.type()); Length fromY = fromOp ? fromOp->m_y : Length(m_y.type()); Length fromZ = fromOp ? fromOp->m_z : Length(m_z.type()); - return TranslateTransformOperation::create(m_x.blend(fromX, progress), m_y.blend(fromY, progress), m_z.blend(fromZ, progress), m_type); + return TranslateTransformOperation::create(m_x.blend(fromX, narrowPrecisionToFloat(progress)), m_y.blend(fromY, narrowPrecisionToFloat(progress)), m_z.blend(fromZ, narrowPrecisionToFloat(progress)), m_type); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/win/FontCacheWin.cpp b/Source/WebCore/platform/graphics/win/FontCacheWin.cpp index e800245..5382ef7 100644 --- a/Source/WebCore/platform/graphics/win/FontCacheWin.cpp +++ b/Source/WebCore/platform/graphics/win/FontCacheWin.cpp @@ -584,7 +584,7 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD #if PLATFORM(CG) bool fontCreationFailed = !result->cgFont(); #elif PLATFORM(CAIRO) - bool fontCreationFailed = !result->fontFace(); + bool fontCreationFailed = !result->scaledFont(); #endif if (fontCreationFailed) { diff --git a/Source/WebCore/platform/graphics/win/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/win/FontCustomPlatformData.cpp index 4aee6cd..8348acb 100644 --- a/Source/WebCore/platform/graphics/win/FontCustomPlatformData.cpp +++ b/Source/WebCore/platform/graphics/win/FontCustomPlatformData.cpp @@ -59,7 +59,7 @@ FontCustomPlatformData::~FontCustomPlatformData() } } -FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode renderingMode) +FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode renderingMode) { ASSERT(m_fontReference); ASSERT(T2embedLibrary()); diff --git a/Source/WebCore/platform/graphics/win/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/win/FontCustomPlatformData.h index abdb356..65388d8 100644 --- a/Source/WebCore/platform/graphics/win/FontCustomPlatformData.h +++ b/Source/WebCore/platform/graphics/win/FontCustomPlatformData.h @@ -25,6 +25,7 @@ #include "FontRenderingMode.h" #include "FontWidthVariant.h" #include "PlatformString.h" +#include "TextOrientation.h" #include <wtf/Forward.h> #include <wtf/Noncopyable.h> @@ -46,7 +47,8 @@ public: ~FontCustomPlatformData(); - FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode); + FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight, + FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode); static bool supportsFormat(const String&); diff --git a/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp b/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp index fd30a6d..6f9bbf0 100644 --- a/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp +++ b/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp @@ -23,8 +23,11 @@ #include "SharedBuffer.h" #include "FontPlatformData.h" + +#include <cairo-win32.h> #include <wtf/RetainPtr.h> + namespace WebCore { FontCustomPlatformData::~FontCustomPlatformData() @@ -32,7 +35,7 @@ FontCustomPlatformData::~FontCustomPlatformData() cairo_font_face_destroy(m_fontFace); } -FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant) +FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant) { return FontPlatformData(m_fontFace, size, bold, italic); } diff --git a/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h b/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h index ea3ae38..bd90f18 100644 --- a/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h +++ b/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h @@ -42,7 +42,7 @@ public: } ~FontCustomPlatformData(); - FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth); + FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight, FontWidthVariant = RegularWidth); static bool supportsFormat(const String&); diff --git a/Source/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp b/Source/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp index 9234229..287121b 100644 --- a/Source/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp +++ b/Source/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp @@ -115,11 +115,15 @@ void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR* } FontPlatformData::FontPlatformData(HFONT hfont, CGFontRef font, float size, bool bold, bool oblique, bool useGDI) - : m_font(RefCountedGDIHandle<HFONT>::create(hfont)) + : m_syntheticBold(bold) + , m_syntheticOblique(oblique) + , m_orientation(Horizontal) + , m_textOrientation(TextOrientationVerticalRight) , m_size(size) + , m_widthVariant(RegularWidth) + , m_font(RefCountedGDIHandle<HFONT>::create(hfont)) , m_cgFont(font) - , m_syntheticBold(bold) - , m_syntheticOblique(oblique) + , m_isColorBitmapFont(false) , m_useGDI(useGDI) { } @@ -128,4 +132,27 @@ FontPlatformData::~FontPlatformData() { } +void FontPlatformData::platformDataInit(const FontPlatformData& source) +{ + m_font = source.m_font; + m_cgFont = source.m_cgFont; + m_useGDI = source.m_useGDI; +} + +const FontPlatformData& FontPlatformData::platformDataAssign(const FontPlatformData& other) +{ + m_font = other.m_font; + m_cgFont = other.m_cgFont; + m_useGDI = other.m_useGDI; + + return *this; +} + +bool FontPlatformData::platformIsEqual(const FontPlatformData& other) const +{ + return m_font == other.m_font + && m_cgFont == other.m_cgFont + && m_useGDI == other.m_useGDI; +} + } diff --git a/Source/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp b/Source/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp index 0f5c365..e60b69b 100644 --- a/Source/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp +++ b/Source/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp @@ -4,7 +4,7 @@ * * Copyright (C) 2006, 2007, 2008 Apple Inc. * Copyright (C) 2007 Alp Toker - * Copyright (C) 2008, 2010 Brent Fulgham + * Copyright (C) 2008, 2010, 2011 Brent Fulgham * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -40,7 +40,7 @@ namespace WebCore { void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR* faceName) { - m_fontFace = cairo_win32_font_face_create_for_hfont(font); + cairo_font_face_t* fontFace = cairo_win32_font_face_create_for_hfont(font); cairo_matrix_t sizeMatrix, ctm; cairo_matrix_init_identity(&ctm); @@ -52,14 +52,18 @@ void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR* cairo_font_options_set_antialias(fontOptions, CAIRO_ANTIALIAS_SUBPIXEL); } - m_scaledFont = cairo_scaled_font_create(m_fontFace, &sizeMatrix, &ctm, fontOptions); + m_scaledFont = cairo_scaled_font_create(fontFace, &sizeMatrix, &ctm, fontOptions); + cairo_font_face_destroy(fontFace); } FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool oblique) : m_font(0) , m_size(size) - , m_fontFace(fontFace) + , m_orientation(Horizontal) + , m_textOrientation(TextOrientationVerticalRight) + , m_widthVariant(RegularWidth) , m_scaledFont(0) + , m_isColorBitmapFont(false) , m_syntheticBold(bold) , m_syntheticOblique(oblique) , m_useGDI(false) @@ -79,64 +83,39 @@ FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool cairo_font_options_destroy(options); } -FontPlatformData::FontPlatformData(const FontPlatformData& source) - : m_font(source.m_font) - , m_size(source.m_size) - , m_fontFace(0) - , m_scaledFont(0) - , m_syntheticBold(source.m_syntheticBold) - , m_syntheticOblique(source.m_syntheticOblique) - , m_useGDI(source.m_useGDI) +FontPlatformData::~FontPlatformData() { - if (source.m_fontFace) - m_fontFace = cairo_font_face_reference(source.m_fontFace); - - if (source.m_scaledFont) - m_scaledFont = cairo_scaled_font_reference(source.m_scaledFont); + if (m_scaledFont && m_scaledFont != hashTableDeletedFontValue()) + cairo_scaled_font_destroy(m_scaledFont); } - -FontPlatformData::~FontPlatformData() +void FontPlatformData::platformDataInit(const FontPlatformData& source) { - cairo_scaled_font_destroy(m_scaledFont); - cairo_font_face_destroy(m_fontFace); + m_font = source.m_font; + m_useGDI = source.m_useGDI; + m_scaledFont = 0; + + if (source.m_scaledFont) + m_scaledFont = cairo_scaled_font_reference(source.m_scaledFont); } -FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other) +const FontPlatformData& FontPlatformData::platformDataAssign(const FontPlatformData& other) { - // Check for self-assignment. - if (this == &other) - return *this; - m_font = other.m_font; - m_size = other.m_size; - m_syntheticBold = other.m_syntheticBold; - m_syntheticOblique = other.m_syntheticOblique; m_useGDI = other.m_useGDI; - if (other.m_fontFace) - cairo_font_face_reference(other.m_fontFace); - if (m_fontFace) - cairo_font_face_destroy(m_fontFace); - m_fontFace = other.m_fontFace; - - if (other.m_scaledFont) - cairo_scaled_font_reference(other.m_scaledFont); - if (m_scaledFont) + if (m_scaledFont && m_scaledFont != hashTableDeletedFontValue()) cairo_scaled_font_destroy(m_scaledFont); - m_scaledFont = other.m_scaledFont; + + m_scaledFont = cairo_scaled_font_reference(other.m_scaledFont); return *this; } -bool FontPlatformData::operator==(const FontPlatformData& other) const -{ +bool FontPlatformData::platformIsEqual(const FontPlatformData& other) const +{ return m_font == other.m_font - && m_fontFace == other.m_fontFace && m_scaledFont == other.m_scaledFont - && m_size == other.m_size - && m_syntheticBold == other.m_syntheticBold - && m_syntheticOblique == other.m_syntheticOblique && m_useGDI == other.m_useGDI; } diff --git a/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp b/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp index 09ed4a6..301198d 100644 --- a/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp +++ b/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp @@ -38,12 +38,15 @@ namespace WebCore { FontPlatformData::FontPlatformData(HFONT font, float size, bool bold, bool oblique, bool useGDI) : m_font(RefCountedGDIHandle<HFONT>::create(font)) , m_size(size) + , m_orientation(Horizontal) + , m_textOrientation(TextOrientationVerticalRight) + , m_widthVariant(RegularWidth) #if PLATFORM(CG) , m_cgFont(0) #elif PLATFORM(CAIRO) - , m_fontFace(0) , m_scaledFont(0) #endif + , m_isColorBitmapFont(false) , m_syntheticBold(bold) , m_syntheticOblique(oblique) , m_useGDI(useGDI) @@ -71,20 +74,6 @@ FontPlatformData::FontPlatformData(HFONT font, float size, bool bold, bool obliq ReleaseDC(0, hdc); } -FontPlatformData::FontPlatformData(float size, bool bold, bool oblique) - : m_size(size) -#if PLATFORM(CG) - , m_cgFont(0) -#elif PLATFORM(CAIRO) - , m_fontFace(0) - , m_scaledFont(0) -#endif - , m_syntheticBold(bold) - , m_syntheticOblique(oblique) - , m_useGDI(false) -{ -} - #ifndef NDEBUG String FontPlatformData::description() const { diff --git a/Source/WebCore/platform/graphics/win/FontWin.cpp b/Source/WebCore/platform/graphics/win/FontWin.cpp index 47c44bc..9e31f56 100644 --- a/Source/WebCore/platform/graphics/win/FontWin.cpp +++ b/Source/WebCore/platform/graphics/win/FontWin.cpp @@ -127,8 +127,8 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon UniscribeController controller(this, run, fallbackFonts); controller.advance(run.length()); if (glyphOverflow) { - glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - fontMetrics().ascent()); - glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - fontMetrics().descent()); + glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent())); + glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent())); glyphOverflow->left = max<int>(0, ceilf(-controller.minGlyphBoundingBoxX())); glyphOverflow->right = max<int>(0, ceilf(controller.maxGlyphBoundingBoxX() - controller.runWidthSoFar())); } diff --git a/Source/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp b/Source/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp index b2c702f..7ce7ee9 100644 --- a/Source/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp +++ b/Source/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp @@ -72,18 +72,15 @@ GraphicsContext::GraphicsContext(HDC dc, bool hasAlpha) void GraphicsContext::platformInit(HDC dc, bool hasAlpha) { - m_data = new GraphicsContextPlatformPrivate; - - if (dc) { - m_data->cr = createCairoContextWithHDC(dc, hasAlpha); - m_data->m_hdc = dc; - } else { + cairo_t* cr = 0; + if (dc) + cr = createCairoContextWithHDC(dc, hasAlpha); + else setPaintingDisabled(true); - m_data->cr = 0; - m_data->m_hdc = 0; - } - if (m_data->cr) { + m_data = new GraphicsContextPlatformPrivateTopLevel(new PlatformContextCairo(cr)); + m_data->m_hdc = dc; + if (platformContext()->cr()) { // Make sure the context starts in sync with our state. setPlatformFillColor(fillColor(), fillColorSpace()); setPlatformStrokeColor(strokeColor(), strokeColorSpace()); @@ -131,24 +128,25 @@ void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, boo // Scale the target surface to the new image size, and flip it // so that when we set the srcImage as the surface it will draw // right-side-up. - cairo_save(m_data->cr); - cairo_translate(m_data->cr, dstRect.x(), dstRect.height() + dstRect.y()); - cairo_scale(m_data->cr, 1.0, -1.0); - cairo_set_source_surface(m_data->cr, image, 0, 0); + cairo_t* cr = platformContext()->cr(); + cairo_save(cr); + cairo_translate(cr, dstRect.x(), dstRect.height() + dstRect.y()); + cairo_scale(cr, 1, -1); + cairo_set_source_surface(cr, image, 0, 0); if (m_data->layers.size()) - cairo_paint_with_alpha(m_data->cr, m_data->layers.last()); + cairo_paint_with_alpha(cr, m_data->layers.last()); else - cairo_paint(m_data->cr); + cairo_paint(cr); // Delete all our junk. cairo_surface_destroy(image); ::DeleteDC(hdc); ::DeleteObject(bitmap); - cairo_restore(m_data->cr); + cairo_restore(cr); } -void GraphicsContextPlatformPrivate::syncContext(PlatformGraphicsContext* cr) +void GraphicsContextPlatformPrivate::syncContext(cairo_t* cr) { if (!cr) return; diff --git a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp index 40fe1d1..bac85f7 100644 --- a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp +++ b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp @@ -28,8 +28,11 @@ #if ENABLE(VIDEO) #include "MediaPlayerPrivateQuickTimeVisualContext.h" +#include "ApplicationCacheHost.h" +#include "ApplicationCacheResource.h" #include "Cookie.h" #include "CookieJar.h" +#include "DocumentLoader.h" #include "Frame.h" #include "FrameView.h" #include "GraphicsContext.h" @@ -369,7 +372,16 @@ void MediaPlayerPrivateQuickTimeVisualContext::loadInternal(const String& url) setUpCookiesForQuickTime(url); m_movie = adoptRef(new QTMovie(m_movieClient.get())); - m_movie->load(url.characters(), url.length(), m_player->preservesPitch()); + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : 0; + ApplicationCacheHost* cacheHost = frame ? frame->loader()->documentLoader()->applicationCacheHost() : 0; + ApplicationCacheResource* resource = 0; + if (cacheHost && cacheHost->shouldLoadResourceFromApplicationCache(ResourceRequest(url), resource) && resource && !resource->path().isEmpty()) + m_movie->load(resource->path().characters(), resource->path().length(), m_player->preservesPitch()); + else +#endif + m_movie->load(url.characters(), url.length(), m_player->preservesPitch()); m_movie->setVolume(m_player->volume()); } diff --git a/Source/WebCore/platform/graphics/win/QTMovie.cpp b/Source/WebCore/platform/graphics/win/QTMovie.cpp index 05fbb86..6f9c668 100644 --- a/Source/WebCore/platform/graphics/win/QTMovie.cpp +++ b/Source/WebCore/platform/graphics/win/QTMovie.cpp @@ -442,6 +442,17 @@ void QTMovie::getNaturalSize(int& width, int& height) height = (rect.bottom - rect.top) * m_private->m_heightScaleFactor; } +void QTMovie::loadPath(const UChar* url, int len, bool preservesPitch) +{ + CFStringRef urlStringRef = CFStringCreateWithCharacters(kCFAllocatorDefault, reinterpret_cast<const UniChar*>(url), len); + CFURLRef cfURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, urlStringRef, kCFURLWindowsPathStyle, false); + + load(cfURL, preservesPitch); + + CFRelease(cfURL); + CFRelease(urlStringRef); +} + void QTMovie::load(const UChar* url, int len, bool preservesPitch) { CFStringRef urlStringRef = CFStringCreateWithCharacters(kCFAllocatorDefault, reinterpret_cast<const UniChar*>(url), len); diff --git a/Source/WebCore/platform/graphics/win/QTMovie.h b/Source/WebCore/platform/graphics/win/QTMovie.h index e97d16d..38b3473 100644 --- a/Source/WebCore/platform/graphics/win/QTMovie.h +++ b/Source/WebCore/platform/graphics/win/QTMovie.h @@ -70,6 +70,7 @@ public: void addClient(QTMovieClient*); void removeClient(QTMovieClient*); + void loadPath(const UChar* url, int len, bool preservesPitch); void load(const UChar* url, int len, bool preservesPitch); void load(CFURLRef, bool preservesPitch); diff --git a/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp b/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp index 30a931e..12f1127 100644 --- a/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp +++ b/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp @@ -97,18 +97,14 @@ void SimpleFontData::platformInit() m_fontMetrics.setLineGap(fLineGap); m_fontMetrics.setLineSpacing(lroundf(fAscent) + lroundf(fDescent) + lroundf(fLineGap)); - // Measure the actual character "x", because AppKit synthesizes X height rather than getting it from the font. - // Unfortunately, NSFont will round this for us so we don't quite get the right value. GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page(); Glyph xGlyph = glyphPageZero ? glyphPageZero->glyphDataForCharacter('x').glyph : 0; if (xGlyph) { + // Measure the actual character "x", since it's possible for it to extend below the baseline, and we need the + // reported x-height to only include the portion of the glyph that is above the baseline. CGRect xBox; CGFontGetGlyphBBoxes(font, &xGlyph, 1, &xBox); - // Use the maximum of either width or height because "x" is nearly square - // and web pages that foolishly use this metric for width will be laid out - // poorly if we return an accurate height. Classic case is Times 13 point, - // which has an "x" that is 7x6 pixels. - m_fontMetrics.setXHeight(scaleEmToUnits(max(CGRectGetMaxX(xBox), CGRectGetMaxY(xBox)), unitsPerEm) * pointSize); + m_fontMetrics.setXHeight(scaleEmToUnits(CGRectGetMaxY(xBox), unitsPerEm) * pointSize); } else { int iXHeight = CGFontGetXHeight(font); m_fontMetrics.setXHeight(scaleEmToUnits(iXHeight, unitsPerEm) * pointSize); diff --git a/Source/WebCore/platform/graphics/win/cairo/FontPlatformData.h b/Source/WebCore/platform/graphics/win/cairo/FontPlatformData.h deleted file mode 100644 index d8f538a..0000000 --- a/Source/WebCore/platform/graphics/win/cairo/FontPlatformData.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008 Apple Inc. - * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com - * Copyright (C) 2007 Holger Hans Peter Freyther - * Copyright (C) 2007 Pioneer Research Center USA, Inc. - * Copyright (C) 2010 Brent Fulgham <bfulgham@webkit.org> - * All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef FontPlatformDataCairoWin_h -#define FontPlatformDataCairoWin_h - -#include "FontOrientation.h" -#include "GlyphBuffer.h" -#include "RefCountedGDIHandle.h" -#include "StringImpl.h" -#include <cairo-win32.h> -#include <cairo.h> -#include <wtf/Forward.h> - -typedef struct HFONT__* HFONT; - -namespace WebCore { - -class FontDescription; - -class FontPlatformData { -public: - FontPlatformData(WTF::HashTableDeletedValueType) - : m_fontFace(0) - , m_useGDI(false) - , m_font(WTF::HashTableDeletedValue) - , m_size(0) - , m_syntheticBold(false) - , m_syntheticOblique(false) - , m_scaledFont(0) - { } - - FontPlatformData() - : m_fontFace(0) - , m_useGDI(false) - , m_size(0) - , m_syntheticBold(false) - , m_syntheticOblique(false) - , m_scaledFont(0) - { } - - FontPlatformData(HFONT, float size, bool bold, bool oblique, bool useGDI); - FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic); - FontPlatformData(float size, bool bold, bool italic); - FontPlatformData(const FontPlatformData&); - ~FontPlatformData(); - - HFONT hfont() const { return m_font->handle(); } - bool useGDI() const { return m_useGDI; } - cairo_font_face_t* fontFace() const { return m_fontFace; } - - bool isFixedPitch(); - float size() const { return m_size; } - void setSize(float size) { m_size = size; } - bool syntheticBold() const { return m_syntheticBold; } - bool syntheticOblique() const { return m_syntheticOblique; } - - FontOrientation orientation() const { return Horizontal; } // FIXME: Implement. - - cairo_scaled_font_t* scaledFont() const { return m_scaledFont; } - - unsigned hash() const - { - return m_font->hash(); - } - - bool operator==(const FontPlatformData&) const; - FontPlatformData& operator=(const FontPlatformData&); - bool isHashTableDeletedValue() const - { - return m_font.isHashTableDeletedValue(); - } - -#ifndef NDEBUG - String description() const; -#endif - -private: - void platformDataInit(HFONT, float size, HDC, WCHAR* faceName); - - RefPtr<RefCountedGDIHandle<HFONT> > m_font; - cairo_font_face_t* m_fontFace; - bool m_useGDI; - float m_size; - bool m_syntheticBold; - bool m_syntheticOblique; - cairo_scaled_font_t* m_scaledFont; -}; - -} - -#endif // FontPlatformDataCairoWin_h diff --git a/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp index fb97fe1..07a8756 100644 --- a/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp +++ b/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp @@ -45,7 +45,7 @@ FontCustomPlatformData::~FontCustomPlatformData() g_customFontCache->unregisterFont(m_name); } -FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode renderingMode) +FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode renderingMode) { FontDescription fontDesc; fontDesc.setComputedSize(size); diff --git a/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.h index fe7ee94..12a86e9 100644 --- a/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.h +++ b/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.h @@ -24,6 +24,7 @@ #include "FontDescription.h" #include "FontRenderingMode.h" #include "FontWidthVariant.h" +#include "TextOrientation.h" #include "PlatformString.h" #include <wtf/Noncopyable.h> @@ -48,7 +49,7 @@ namespace WebCore { ~FontCustomPlatformData(); - FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode); + FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode); static bool supportsFormat(const String&); diff --git a/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp b/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp index d9d8a72..d767ac7 100644 --- a/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp +++ b/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp @@ -148,7 +148,7 @@ struct FixedSizeFontDataKeyHash { font.m_weight, // static_cast<unsigned>(font.m_italic); }; - return WTF::StringHasher::createBlobHash<sizeof(hashCodes)>(hashCodes); + return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes); } static bool equal(const FixedSizeFontDataKey& a, const FixedSizeFontDataKey& b) diff --git a/Source/WebCore/platform/graphics/wince/FontPlatformData.h b/Source/WebCore/platform/graphics/wince/FontPlatformData.h index e73a7b2..9c3f733 100644 --- a/Source/WebCore/platform/graphics/wince/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/wince/FontPlatformData.h @@ -79,6 +79,7 @@ namespace WebCore { static LONG adjustedGDIFontWeight(LONG gdiFontWeight, const String& family); FontOrientation orientation() const { return Horizontal; } // FIXME: Implement. + void setOrientation(FontOrientation) { } // FIXME: Implement. #ifndef NDEBUG String description() const; diff --git a/Source/WebCore/platform/graphics/wince/PathWinCE.cpp b/Source/WebCore/platform/graphics/wince/PathWinCE.cpp index fa4c8fb..9c9112b 100644 --- a/Source/WebCore/platform/graphics/wince/PathWinCE.cpp +++ b/Source/WebCore/platform/graphics/wince/PathWinCE.cpp @@ -133,7 +133,7 @@ void Path::transform(const AffineTransform& t) m_path->transform(t); } -FloatRect Path::strokeBoundingRect(StrokeStyleApplier *) +FloatRect Path::strokeBoundingRect(StrokeStyleApplier*) const { notImplemented(); return FloatRect(); diff --git a/Source/WebCore/platform/graphics/wx/FontPlatformData.h b/Source/WebCore/platform/graphics/wx/FontPlatformData.h index 3ef0179..8a2c4a0 100644 --- a/Source/WebCore/platform/graphics/wx/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/wx/FontPlatformData.h @@ -150,6 +150,7 @@ public: bool allowsLigatures() const { return false; } FontOrientation orientation() const { return Horizontal; } // FIXME: Implement. + void setOrientation(FontOrientation) { } // FIXME: Implement. // We don't support this yet, so just return the default value for now. FontWidthVariant widthVariant() const { return RegularWidth; } diff --git a/Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp b/Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp index c125b7c..830cd05 100644 --- a/Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp +++ b/Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp @@ -126,10 +126,10 @@ unsigned FontPlatformData::computeHash() const thisFont->GetStyle(), thisFont->GetWeight(), thisFont->GetUnderlined(), - WTF::StringHasher::createHash(thisFont->GetFaceName().utf8_str().data()) + StringHasher::computeHash(thisFont->GetFaceName().utf8_str().data()) }; - return WTF::StringHasher::createBlobHash<sizeof(hashCodes)>(hashCodes); + return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes); } FontPlatformData::~FontPlatformData() diff --git a/Source/WebCore/platform/graphics/wx/PathWx.cpp b/Source/WebCore/platform/graphics/wx/PathWx.cpp index f5355f2..a95cc1c 100644 --- a/Source/WebCore/platform/graphics/wx/PathWx.cpp +++ b/Source/WebCore/platform/graphics/wx/PathWx.cpp @@ -105,7 +105,7 @@ FloatRect Path::boundingRect() const return FloatRect(); } -FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) +FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const { notImplemented(); return FloatRect(); |