diff options
Diffstat (limited to 'WebCore/platform/graphics')
96 files changed, 2022 insertions, 918 deletions
diff --git a/WebCore/platform/graphics/ContextShadow.h b/WebCore/platform/graphics/ContextShadow.h index 0160f8a..2b779f7 100644 --- a/WebCore/platform/graphics/ContextShadow.h +++ b/WebCore/platform/graphics/ContextShadow.h @@ -38,17 +38,24 @@ #if PLATFORM(CAIRO) typedef struct _cairo cairo_t; typedef struct _cairo_surface cairo_surface_t; -typedef cairo_surface_t* PlatformImage; -typedef cairo_t* PlatformContext; #elif PLATFORM(QT) #include <QImage> class QPainter; -typedef QImage PlatformImage; -typedef QPainter* PlatformContext; #endif namespace WebCore { +#if PLATFORM(CAIRO) +typedef cairo_surface_t* PlatformImage; +typedef cairo_t* PlatformContext; +#elif PLATFORM(QT) +typedef QImage PlatformImage; +typedef QPainter* PlatformContext; +#else +typedef void* PlatformImage; +typedef void* PlatformContext; +#endif + // This is to track and keep the shadow state. We use this rather than // using GraphicsContextState to allow possible optimizations (right now // only to determine the shadow type, but in future it might covers things diff --git a/WebCore/platform/graphics/Extensions3D.h b/WebCore/platform/graphics/Extensions3D.h index 0aed8e7..74210a5 100644 --- a/WebCore/platform/graphics/Extensions3D.h +++ b/WebCore/platform/graphics/Extensions3D.h @@ -47,13 +47,15 @@ public: // GL_EXT_texture_format_BGRA8888 // GL_EXT_read_format_bgra // GL_ARB_robustness + // GL_ARB_texture_non_power_of_two / GL_OES_texture_npot // GL_EXT_packed_depth_stencil / GL_OES_packed_depth_stencil + // GL_ANGLE_framebuffer_blit / GL_ANGLE_framebuffer_multisample // Takes full name of extension; for example, // "GL_EXT_texture_format_BGRA8888". virtual bool supports(const String&) = 0; - enum { + enum ExtensionsEnumType { // GL_EXT_texture_format_BGRA8888 enums BGRA_EXT = 0x80E1, @@ -63,11 +65,28 @@ public: UNKNOWN_CONTEXT_RESET_ARB = 0x8255, // GL_EXT/OES_packed_depth_stencil enums - DEPTH24_STENCIL8 = 0x88F0 + DEPTH24_STENCIL8 = 0x88F0, + + // GL_ANGLE_framebuffer_blit names + READ_FRAMEBUFFER = 0x8CA8, + DRAW_FRAMEBUFFER = 0x8CA9, + DRAW_FRAMEBUFFER_BINDING = 0x8CA6, + READ_FRAMEBUFFER_BINDING = 0x8CAA, + + // GL_ANGLE_framebuffer_multisample names + RENDERBUFFER_SAMPLES = 0x8CAB, + FRAMEBUFFER_INCOMPLETE_MULTISAMPLE = 0x8D56, + MAX_SAMPLES = 0x8D57 }; // GL_ARB_robustness virtual int getGraphicsResetStatusARB() = 0; + + // GL_ANGLE_framebuffer_blit + virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter) = 0; + + // GL_ANGLE_framebuffer_multisample + virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height) = 0; }; } // namespace WebCore diff --git a/WebCore/platform/graphics/Font.cpp b/WebCore/platform/graphics/Font.cpp index a0cf5a4..6bbf3d7 100644 --- a/WebCore/platform/graphics/Font.cpp +++ b/WebCore/platform/graphics/Font.cpp @@ -336,4 +336,73 @@ Font::CodePath Font::codePath(const TextRun& run) const return result; } +bool Font::isCJKIdeograph(UChar32 c) +{ + // The basic CJK Unified Ideographs block. + if (c >= 0x4E00 && c <= 0x9FFF) + return true; + + // CJK Unified Ideographs Extension A. + if (c >= 0x3400 && c <= 0x4DBF) + return true; + + // CJK Radicals Supplement. + if (c >= 0x2E80 && c <= 0x2EFF) + return true; + + // Kangxi Radicals. + if (c >= 0x2F00 && c <= 0x2FDF) + return true; + + // Ideographic Description Characters. + if (c >= 0x2FF0 && c <= 0x2FFF) + return true; + + // CJK Symbols and Punctuation. + if (c >= 0x3000 && c <= 0x303F) + return true; + + // CJK Strokes. + if (c >= 0x31C0 && c <= 0x31EF) + return true; + + // Enclosed CJK Letters and Months. + if (c >= 0x3200 && c <= 0x32FF) + return true; + + // CJK Compatibility. + if (c >= 0x3300 && c <= 0x33FF) + return true; + + // CJK Compatibility Ideographs. + if (c >= 0xF900 && c <= 0xFAFF) + return true; + + // CJK Compatibility Forms. + if (c >= 0xFE30 && c <= 0xFE4F) + return true; + + // Emoji. + if (c >= 0x1F200 && c <= 0x1F6F) + return true; + + // CJK Unified Ideographs Extension B. + if (c >= 0x20000 && c <= 0x2A6DF) + return true; + + // CJK Unified Ideographs Extension C. + if (c >= 0x2A700 && c <= 0x2B73F) + return true; + + // CJK Unified Ideographs Extension D. + if (c >= 0x2B740 && c <= 0x2B81F) + return true; + + // CJK Compatibility Ideographs Supplement. + if (c >= 0x2F800 && c <= 0x2FA1F) + return true; + + return false; +} + } diff --git a/WebCore/platform/graphics/Font.h b/WebCore/platform/graphics/Font.h index 1a321bd..cb83ad2 100644 --- a/WebCore/platform/graphics/Font.h +++ b/WebCore/platform/graphics/Font.h @@ -127,8 +127,8 @@ public: bool isPlatformFont() const { return m_isPlatformFont; } // Metrics that we query the FontFallbackList for. - int ascent() const { return primaryFont()->ascent(); } - int descent() const { return primaryFont()->descent(); } + int ascent(FontBaseline baselineType = AlphabeticBaseline) const { return primaryFont()->ascent(baselineType); } + int descent(FontBaseline baselineType = AlphabeticBaseline) const { return primaryFont()->descent(baselineType); } int height() const { return ascent() + descent(); } int lineSpacing() const { return primaryFont()->lineSpacing(); } int lineGap() const { return primaryFont()->lineGap(); } @@ -143,6 +143,8 @@ public: // Used for complex text, and does not utilize the glyph map cache. const FontData* fontDataForCharacters(const UChar*, int length) const; + static bool isCJKIdeograph(UChar32); + #if PLATFORM(QT) QFont font() const; #endif diff --git a/WebCore/platform/graphics/FontBaseline.h b/WebCore/platform/graphics/FontBaseline.h new file mode 100644 index 0000000..f7d256d --- /dev/null +++ b/WebCore/platform/graphics/FontBaseline.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 FontBaseline_h +#define FontBaseline_h + +namespace WebCore { + +enum FontBaseline { AlphabeticBaseline, IdeographicBaseline }; + +} // namespace WebCore + +#endif // FontBaseline_h diff --git a/WebCore/platform/graphics/FontFastPath.cpp b/WebCore/platform/graphics/FontFastPath.cpp index 82f970f..f0dd33e 100644 --- a/WebCore/platform/graphics/FontFastPath.cpp +++ b/WebCore/platform/graphics/FontFastPath.cpp @@ -74,8 +74,23 @@ GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCap page = node->page(); if (page) { GlyphData data = page->glyphDataForCharacter(c); - if (data.fontData) + if (data.fontData) { + if (data.fontData->platformData().orientation() == Vertical && data.fontData->orientation() == Horizontal && Font::isCJKIdeograph(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; + } + + // Shouldn't be possible to even reach this point. + ASSERT_NOT_REACHED(); + } return data; + } + if (node->isSystemFallback()) break; } diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h index a91f3d3..e8ba0e4 100644 --- a/WebCore/platform/graphics/GraphicsContext.h +++ b/WebCore/platform/graphics/GraphicsContext.h @@ -430,6 +430,7 @@ namespace WebCore { bool inTransparencyLayer() const; PlatformPath* currentPath(); void pushTransparencyLayerInternal(const QRect &rect, qreal opacity, QPixmap& alphaMask); + void takeOwnershipOfPlatformContext(); static QPainter::CompositionMode toQtCompositionMode(CompositeOperator op); #endif diff --git a/WebCore/platform/graphics/GraphicsContext3D.cpp b/WebCore/platform/graphics/GraphicsContext3D.cpp index 2a65128..d0ee639 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.cpp +++ b/WebCore/platform/graphics/GraphicsContext3D.cpp @@ -97,11 +97,12 @@ bool GraphicsContext3D::extractImageData(Image* image, unsigned int type, bool flipY, bool premultiplyAlpha, + bool ignoreGammaAndColorProfile, Vector<uint8_t>& data) { if (!image) return false; - if (!getImageData(image, format, type, premultiplyAlpha, data)) + if (!getImageData(image, format, type, premultiplyAlpha, ignoreGammaAndColorProfile, data)) return false; if (flipY) { unsigned long componentsPerPixel, bytesPerComponent; diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h index e34a2f8..c2d5c24 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.h +++ b/WebCore/platform/graphics/GraphicsContext3D.h @@ -404,6 +404,8 @@ public: UNPACK_FLIP_Y_WEBGL = 0x9240, UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241, CONTEXT_LOST_WEBGL = 0x9242, + UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243, + BROWSER_DEFAULT_WEBGL = 0x9244 }; // Context creation attributes. @@ -471,8 +473,6 @@ public: int sizeInBytes(int type); bool isGLES2Compliant() const; - bool isGLES2NPOTStrict() const; - bool isErrorGeneratedOnOutOfBoundsAccesses() const; //---------------------------------------------------------------------- // Helpers for texture uploading and pixel readback. @@ -488,13 +488,14 @@ public: // Extracts the contents of the given Image into the passed Vector, // packing the pixel data according to the given format and type, - // and obeying the flipY and premultiplyAlpha flags. Returns true - // upon success. + // and obeying the flipY, premultiplyAlpha, and ignoreGammaAndColorProfile + // flags. Returns true upon success. bool extractImageData(Image* image, unsigned int format, unsigned int type, bool flipY, bool premultiplyAlpha, + bool ignoreGammaAndColorProfile, Vector<uint8_t>& data); // Extracts the contents of the given ImageData into the passed Vector, @@ -803,12 +804,16 @@ public: // extraction process. This premultiplication occurs before // any packing of pixel data. // + // If ignoreGammaAndColorProfile is true, gamma correction and ICC + // profile won't be applied. + // // No vertical flip of the image data is performed by this // method. bool getImageData(Image* image, unsigned int format, unsigned int type, bool premultiplyAlpha, + bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector); // Possible alpha operations that may need to occur during diff --git a/WebCore/platform/graphics/ImageSource.cpp b/WebCore/platform/graphics/ImageSource.cpp index c6d97fe..d1a944a 100644 --- a/WebCore/platform/graphics/ImageSource.cpp +++ b/WebCore/platform/graphics/ImageSource.cpp @@ -41,9 +41,10 @@ namespace WebCore { unsigned ImageSource::s_maxPixelsPerDecodedImage = 1024 * 1024; #endif -ImageSource::ImageSource(bool premultiplyAlpha) +ImageSource::ImageSource(bool premultiplyAlpha, bool ignoreGammaAndColorProfile) : m_decoder(0) , m_premultiplyAlpha(premultiplyAlpha) + , m_ignoreGammaAndColorProfile(ignoreGammaAndColorProfile) { } @@ -78,7 +79,7 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived) // If insufficient bytes are available to determine the image type, no decoder plugin will be // made. if (!m_decoder) { - m_decoder = static_cast<NativeImageSourcePtr>(ImageDecoder::create(*data, m_premultiplyAlpha)); + m_decoder = static_cast<NativeImageSourcePtr>(ImageDecoder::create(*data, m_premultiplyAlpha, m_ignoreGammaAndColorProfile)); #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) if (m_decoder && s_maxPixelsPerDecodedImage) m_decoder->setMaxNumPixels(s_maxPixelsPerDecodedImage); diff --git a/WebCore/platform/graphics/ImageSource.h b/WebCore/platform/graphics/ImageSource.h index 4d50253..3d96698 100644 --- a/WebCore/platform/graphics/ImageSource.h +++ b/WebCore/platform/graphics/ImageSource.h @@ -138,7 +138,7 @@ const int cAnimationNone = -2; class ImageSource : public Noncopyable { public: - ImageSource(bool premultiplyAlpha = true); + ImageSource(bool premultiplyAlpha = true, bool ignoreGammaAndColorProfile = false); ~ImageSource(); // Tells the ImageSource that the Image no longer cares about decoded frame @@ -207,6 +207,7 @@ protected: #endif NativeImageSourcePtr m_decoder; bool m_premultiplyAlpha; + bool m_ignoreGammaAndColorProfile; #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) static unsigned s_maxPixelsPerDecodedImage; #endif diff --git a/WebCore/platform/graphics/IntPoint.h b/WebCore/platform/graphics/IntPoint.h index d4ea2f2..cd5e4d4 100644 --- a/WebCore/platform/graphics/IntPoint.h +++ b/WebCore/platform/graphics/IntPoint.h @@ -109,6 +109,11 @@ public: *this = expandedTo(zero()); } + IntPoint transposedPoint() const + { + return IntPoint(m_y, m_x); + } + #if PLATFORM(CG) explicit IntPoint(const CGPoint&); // don't do this implicitly since it's lossy operator CGPoint() const; diff --git a/WebCore/platform/graphics/IntRect.h b/WebCore/platform/graphics/IntRect.h index c8d7c71..e43e290 100644 --- a/WebCore/platform/graphics/IntRect.h +++ b/WebCore/platform/graphics/IntRect.h @@ -143,6 +143,8 @@ public: void inflate(int d) { inflateX(d); inflateY(d); } void scale(float s); + IntRect transposedRect() const { return IntRect(m_location.transposedPoint(), m_size.transposedSize()); } + #if PLATFORM(WX) IntRect(const wxRect&); operator wxRect() const; diff --git a/WebCore/platform/graphics/IntSize.h b/WebCore/platform/graphics/IntSize.h index 9ecf389..9db2224 100644 --- a/WebCore/platform/graphics/IntSize.h +++ b/WebCore/platform/graphics/IntSize.h @@ -104,6 +104,11 @@ public: *this = expandedTo(IntSize()); } + IntSize transposedSize() const + { + return IntSize(m_height, m_width); + } + #if PLATFORM(CG) explicit IntSize(const CGSize&); // don't do this implicitly since it's lossy operator CGSize() const; diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp index 9fb2d4a..83e84d9 100644 --- a/WebCore/platform/graphics/MediaPlayer.cpp +++ b/WebCore/platform/graphics/MediaPlayer.cpp @@ -47,21 +47,29 @@ #if PLATFORM(MAC) #include "MediaPlayerPrivateQTKit.h" +#define PlatformMediaEngineClassName MediaPlayerPrivateQTKit #elif OS(WINCE) && !PLATFORM(QT) #include "MediaPlayerPrivateWinCE.h" +#define PlatformMediaEngineClassName MediaPlayerPrivate #elif PLATFORM(WIN) #include "MediaPlayerPrivateQuickTimeVisualContext.h" -#include "MediaPlayerPrivateQuicktimeWin.h" +#define PlatformMediaEngineClassName MediaPlayerPrivateQuickTimeVisualContext #elif PLATFORM(QT) -#if USE(QT_MULTIMEDIA) +#if USE(QT_MULTIMEDIA) && !USE(GSTREAMER) #include "MediaPlayerPrivateQt.h" -#else +#define PlatformMediaEngineClassName MediaPlayerPrivateQt +#elif !USE(GSTREAMER) #include "MediaPlayerPrivatePhonon.h" +#define PlatformMediaEngineClassName MediaPlayerPrivatePhonon #endif #elif PLATFORM(CHROMIUM) #include "MediaPlayerPrivateChromium.h" +<<<<<<< HEAD #elif PLATFORM(ANDROID) #include "MediaPlayerPrivateAndroid.h" +======= +#define PlatformMediaEngineClassName MediaPlayerPrivate +>>>>>>> webkit.org at r72274 #endif namespace WebCore { @@ -167,26 +175,14 @@ static Vector<MediaPlayerFactory*>& installedMediaEngines() if (!enginesQueried) { enginesQueried = true; + #if USE(GSTREAMER) MediaPlayerPrivateGStreamer::registerMediaEngine(addMediaEngine); #endif -#if PLATFORM(WIN) - MediaPlayerPrivateQuickTimeVisualContext::registerMediaEngine(addMediaEngine); -#elif PLATFORM(QT) -#if USE(QT_MULTIMEDIA) - MediaPlayerPrivateQt::registerMediaEngine(addMediaEngine); -#else - MediaPlayerPrivatePhonon::registerMediaEngine(addMediaEngine); +#if !PLATFORM(GTK) && !PLATFORM(EFL) && !(PLATFORM(QT) && USE(GSTREAMER)) + PlatformMediaEngineClassName::registerMediaEngine(addMediaEngine); #endif -#elif !PLATFORM(GTK) && !PLATFORM(EFL) - // FIXME: currently all the MediaEngines are named - // MediaPlayerPrivate. This code will need an update when bug - // 36663 is adressed. - MediaPlayerPrivate::registerMediaEngine(addMediaEngine); -#endif - - // register additional engines here } return installedEngines; @@ -653,6 +649,11 @@ float MediaPlayer::mediaTimeForTimeValue(float timeValue) const return m_private->mediaTimeForTimeValue(timeValue); } +double MediaPlayer::maximumDurationToCacheMediaTime() const +{ + return m_private->maximumDurationToCacheMediaTime(); +} + // Client callbacks. void MediaPlayer::networkStateChanged() { diff --git a/WebCore/platform/graphics/MediaPlayer.h b/WebCore/platform/graphics/MediaPlayer.h index a199352..a9499a5 100644 --- a/WebCore/platform/graphics/MediaPlayer.h +++ b/WebCore/platform/graphics/MediaPlayer.h @@ -281,6 +281,8 @@ public: float mediaTimeForTimeValue(float) const; + double maximumDurationToCacheMediaTime() const; + private: MediaPlayer(MediaPlayerClient*); diff --git a/WebCore/platform/graphics/MediaPlayerPrivate.h b/WebCore/platform/graphics/MediaPlayerPrivate.h index 6a74714..d956286 100644 --- a/WebCore/platform/graphics/MediaPlayerPrivate.h +++ b/WebCore/platform/graphics/MediaPlayerPrivate.h @@ -129,6 +129,11 @@ public: // engine uses rational numbers to represent media time. virtual float mediaTimeForTimeValue(float timeValue) const { return timeValue; } + // Overide this if it is safe for HTMLMediaElement to cache movie time and report + // 'currentTime' as [cached time + elapsed wall time]. Returns the maximum wall time + // it is OK to calculate movie time before refreshing the cached time. + virtual double maximumDurationToCacheMediaTime() const { return 0; } + }; } diff --git a/WebCore/platform/graphics/SimpleFontData.cpp b/WebCore/platform/graphics/SimpleFontData.cpp index 7980643..391873a 100644 --- a/WebCore/platform/graphics/SimpleFontData.cpp +++ b/WebCore/platform/graphics/SimpleFontData.cpp @@ -51,11 +51,14 @@ SimpleFontData::SimpleFontData(const FontPlatformData& platformData, bool isCust : m_maxCharWidth(-1) , m_avgCharWidth(-1) , m_unitsPerEm(defaultUnitsPerEm) + , m_orientation(platformData.orientation()) , m_platformData(platformData) , m_treatAsFixedPitch(false) , m_isCustomFont(isCustomFont) , m_isLoading(isLoading) + , m_isBrokenIdeographFont(false) , m_smallCapsFontData(0) + , m_brokenIdeographFontData(0) { platformInit(); platformGlyphInit(); @@ -64,12 +67,15 @@ SimpleFontData::SimpleFontData(const FontPlatformData& platformData, bool isCust #if ENABLE(SVG_FONTS) SimpleFontData::SimpleFontData(PassOwnPtr<SVGFontData> svgFontData, int size, bool syntheticBold, bool syntheticItalic) - : m_platformData(FontPlatformData(size, syntheticBold, syntheticItalic)) + : m_orientation(Horizontal) + , m_platformData(FontPlatformData(size, syntheticBold, syntheticItalic)) , m_treatAsFixedPitch(false) , m_svgFontData(svgFontData) , m_isCustomFont(true) , m_isLoading(false) + , m_isBrokenIdeographFont(false) , m_smallCapsFontData(0) + , m_brokenIdeographFontData(0) { SVGFontFaceElement* svgFontFaceElement = m_svgFontData->svgFontFaceElement(); m_unitsPerEm = svgFontFaceElement->unitsPerEm(); @@ -178,11 +184,18 @@ SimpleFontData::~SimpleFontData() #endif platformDestroy(); - if (!isCustomFont()) { - if (m_smallCapsFontData) - fontCache()->releaseFontData(m_smallCapsFontData); + if (!isCustomFont()) GlyphPageTreeNode::pruneTreeFontData(this); + else { + if (m_smallCapsFontData) + GlyphPageTreeNode::pruneTreeCustomFontData(m_smallCapsFontData); + + if (m_brokenIdeographFontData) + GlyphPageTreeNode::pruneTreeCustomFontData(m_brokenIdeographFontData); } + + delete m_smallCapsFontData; + delete m_brokenIdeographFontData; } const SimpleFontData* SimpleFontData::fontDataForCharacter(UChar32) const @@ -195,6 +208,16 @@ bool SimpleFontData::isSegmented() const return false; } +SimpleFontData* SimpleFontData::brokenIdeographFontData() const +{ + if (!m_brokenIdeographFontData) { + m_brokenIdeographFontData = new SimpleFontData(m_platformData, isCustomFont(), false); + m_brokenIdeographFontData->m_orientation = Vertical; + m_brokenIdeographFontData->m_isBrokenIdeographFont = true; + } + return m_brokenIdeographFontData; +} + #ifndef NDEBUG String SimpleFontData::description() const { diff --git a/WebCore/platform/graphics/SimpleFontData.h b/WebCore/platform/graphics/SimpleFontData.h index 7bd58ad..432a164 100644 --- a/WebCore/platform/graphics/SimpleFontData.h +++ b/WebCore/platform/graphics/SimpleFontData.h @@ -24,6 +24,7 @@ #ifndef SimpleFontData_h #define SimpleFontData_h +#include "FontBaseline.h" #include "FontData.h" #include "FontPlatformData.h" #include "FloatRect.h" @@ -77,9 +78,14 @@ public: const FontPlatformData& platformData() const { return m_platformData; } SimpleFontData* smallCapsFontData(const FontDescription& fontDescription) const; - // vertical metrics - int ascent() const { return m_ascent; } - int descent() const { return m_descent; } + 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. + int ascent(FontBaseline baselineType = AlphabeticBaseline) const { return baselineType == AlphabeticBaseline ? m_ascent : height() - height() / 2; } + int descent(FontBaseline baselineType = AlphabeticBaseline) const { return baselineType == AlphabeticBaseline ? m_descent : height() / 2; } + int height() const { return m_ascent + m_descent; } int lineSpacing() const { return m_lineSpacing; } int lineGap() const { return m_lineGap; } float maxCharWidth() const { return m_maxCharWidth; } @@ -118,6 +124,8 @@ 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 @@ -162,6 +170,8 @@ public: wxFont* getWxFont() const { return m_platformData.font(); } #endif + FontOrientation orientation() const { return m_orientation; } + private: void platformInit(); void platformGlyphInit(); @@ -188,6 +198,9 @@ private: float m_avgCharWidth; float m_xHeight; unsigned m_unitsPerEm; + + 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; @@ -202,6 +215,7 @@ 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; Glyph m_spaceGlyph; float m_spaceWidth; @@ -213,6 +227,8 @@ private: mutable SimpleFontData* m_smallCapsFontData; + mutable SimpleFontData* m_brokenIdeographFontData; + #if PLATFORM(CG) || PLATFORM(CAIRO) || PLATFORM(WX) float m_syntheticBoldOffset; #endif diff --git a/WebCore/platform/graphics/cairo/FontPlatformData.h b/WebCore/platform/graphics/cairo/FontPlatformData.h deleted file mode 100644 index e5ffef2..0000000 --- a/WebCore/platform/graphics/cairo/FontPlatformData.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2010 Igalia S.L. - * 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 - -#if defined(USE_FREETYPE) -#include "FontPlatformDataFreeType.h" -#elif defined(USE_PANGO) -#include "FontPlatformDataPango.h" -#elif PLATFORM(WIN) -#include "FontPlatformDataCairoWin.h" -#endif - -#endif // FontPlatformData_h diff --git a/WebCore/platform/graphics/cairo/RefPtrCairo.cpp b/WebCore/platform/graphics/cairo/RefPtrCairo.cpp index a6c983e..c8b242c 100644 --- a/WebCore/platform/graphics/cairo/RefPtrCairo.cpp +++ b/WebCore/platform/graphics/cairo/RefPtrCairo.cpp @@ -76,6 +76,18 @@ template<> void derefIfNotNull(cairo_scaled_font_t* ptr) cairo_scaled_font_destroy(ptr); } +template<> void refIfNotNull(cairo_pattern_t* ptr) +{ + if (LIKELY(ptr != 0)) + cairo_pattern_reference(ptr); +} + +template<> void derefIfNotNull(cairo_pattern_t* ptr) +{ + if (LIKELY(ptr != 0)) + cairo_pattern_destroy(ptr); +} + #if defined(USE_FREETYPE) template<> void refIfNotNull(FcPattern* ptr) { diff --git a/WebCore/platform/graphics/cairo/RefPtrCairo.h b/WebCore/platform/graphics/cairo/RefPtrCairo.h index 0429ec5..204d1e3 100644 --- a/WebCore/platform/graphics/cairo/RefPtrCairo.h +++ b/WebCore/platform/graphics/cairo/RefPtrCairo.h @@ -26,6 +26,7 @@ typedef struct _cairo cairo_t; typedef struct _cairo_surface cairo_surface_t; 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) typedef struct _FcPattern FcPattern; @@ -45,6 +46,9 @@ template<> void derefIfNotNull(cairo_font_face_t* ptr); template<> void refIfNotNull(cairo_scaled_font_t* ptr); template<> void derefIfNotNull(cairo_scaled_font_t* ptr); +template<> void refIfNotNull(cairo_pattern_t*); +template<> void derefIfNotNull(cairo_pattern_t*); + #if defined(USE_FREETYPE) template<> void refIfNotNull(FcPattern* ptr); template<> void derefIfNotNull(FcPattern* ptr); diff --git a/WebCore/platform/graphics/cg/FontPlatformData.h b/WebCore/platform/graphics/cg/FontPlatformData.h index b261f87..e21b444 100644 --- a/WebCore/platform/graphics/cg/FontPlatformData.h +++ b/WebCore/platform/graphics/cg/FontPlatformData.h @@ -24,6 +24,7 @@ #ifndef FontPlatformData_h #define FontPlatformData_h +#include "FontOrientation.h" #include "RefCountedGDIHandle.h" #include "StringImpl.h" #include <wtf/Forward.h> @@ -66,6 +67,8 @@ public: 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(); @@ -97,6 +100,6 @@ private: bool m_useGDI; }; -} +} // namespace WebCore #endif diff --git a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp index 0c6acf9..7a58eed 100644 --- a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp +++ b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp @@ -91,6 +91,7 @@ bool GraphicsContext3D::getImageData(Image* image, unsigned int format, unsigned int type, bool premultiplyAlpha, + bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector) { if (!image) @@ -98,7 +99,7 @@ bool GraphicsContext3D::getImageData(Image* image, CGImageRef cgImage; RetainPtr<CGImageRef> decodedImage; if (image->data()) { - ImageSource decoder(false); + ImageSource decoder(false, ignoreGammaAndColorProfile); decoder.setData(image->data(), true); if (!decoder.frameCount()) return false; diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp index 5fa4896..f01c442 100644 --- a/WebCore/platform/graphics/cg/ImageSourceCG.cpp +++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp @@ -63,10 +63,11 @@ void sharedBufferRelease(void* info) } #endif -ImageSource::ImageSource(bool premultiplyAlpha) +ImageSource::ImageSource(bool premultiplyAlpha, bool ignoreGammaAndColorProfile) : m_decoder(0) // FIXME: m_premultiplyAlpha is ignored in cg at the moment. , m_premultiplyAlpha(premultiplyAlpha) + , m_ignoreGammaAndColorProfile(ignoreGammaAndColorProfile) { } diff --git a/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp index eba5349..375a74b 100644 --- a/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp @@ -68,9 +68,7 @@ ContentLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context) " v_texCoord = a_texCoord; \n" "} \n"; - // Note differences between Skia and Core Graphics versions: - // - Skia uses BGRA - // - Core Graphics uses RGBA + // Color is in BGRA order. char fragmentShaderString[] = "precision mediump float; \n" "varying vec2 v_texCoord; \n" @@ -79,13 +77,7 @@ ContentLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context) "void main() \n" "{ \n" " vec4 texColor = texture2D(s_texture, v_texCoord); \n" -#if PLATFORM(SKIA) " gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha; \n" -#elif PLATFORM(CG) - " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n" -#else -#error "Need to implement for your platform." -#endif "} \n"; m_contentShaderProgram = createShaderProgram(m_context, vertexShaderString, fragmentShaderString); @@ -130,6 +122,7 @@ ContentLayerChromium::~ContentLayerChromium() void ContentLayerChromium::cleanupResources() { + LayerChromium::cleanupResources(); if (layerRenderer()) { if (m_contentsTexture) { layerRenderer()->deleteLayerTexture(m_contentsTexture); @@ -141,11 +134,11 @@ void ContentLayerChromium::cleanupResources() bool ContentLayerChromium::requiresClippedUpdateRect() const { // 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 current size - // of the visible rect. This is a temporary measure until layer tiling is implemented. + // one of the layer's dimensions is larger than 2000 pixels or the size of + // surface it's rendering into. This is a temporary measure until layer tiling is implemented. static const int maxLayerSize = 2000; - return (m_bounds.width() > max(maxLayerSize, layerRenderer()->rootLayerContentRect().width()) - || m_bounds.height() > max(maxLayerSize, layerRenderer()->rootLayerContentRect().height()) + return (m_bounds.width() > max(maxLayerSize, m_targetRenderSurface->contentRect().width()) + || m_bounds.height() > max(maxLayerSize, m_targetRenderSurface->contentRect().height()) || !layerRenderer()->checkTextureSize(m_bounds)); } @@ -153,25 +146,26 @@ void ContentLayerChromium::calculateClippedUpdateRect(IntRect& dirtyRect, IntRec { // For the given layer size and content rect, calculate: // 1) The minimal texture space rectangle to be uploaded, returned in dirtyRect. - // 2) The content rect-relative rectangle to draw this texture in, returned in drawRect. - - const IntRect clipRect = layerRenderer()->currentScissorRect(); - const TransformationMatrix& transform = drawTransform(); - // The layer's draw transform points to the center of the layer, relative to - // the content rect. layerPos is the distance from the top left of the - // layer to the top left of the content rect. - const IntPoint layerPos(m_bounds.width() / 2 - transform.m41(), - m_bounds.height() / 2 - transform.m42()); - // Transform the contentRect into the space of the layer. - IntRect contentRectInLayerSpace(layerPos, clipRect.size()); - - // Clip the entire layer against the visible region in the content rect - // and use that as the drawable texture, instead of the entire layer. - dirtyRect = IntRect(IntPoint(0, 0), m_bounds); - dirtyRect.intersect(contentRectInLayerSpace); - - // The draw position is relative to the content rect. - drawRect = IntRect(toPoint(dirtyRect.location() - layerPos), dirtyRect.size()); + // 2) The rectangle to draw this texture in relative to the target render surface, returned in drawRect. + + ASSERT(m_targetRenderSurface); + const IntRect clipRect = m_targetRenderSurface->contentRect(); + + TransformationMatrix layerOriginTransform = drawTransform(); + layerOriginTransform.translate3d(-0.5 * m_bounds.width(), -0.5 * m_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()); + + TransformationMatrix targetToLayerMatrix = layerOriginTransform.inverse(); + IntRect clipRectInLayerCoords = targetToLayerMatrix.mapRect(clipRect); + clipRectInLayerCoords.intersect(IntRect(0, 0, m_bounds.width(), m_bounds.height())); + + dirtyRect = clipRectInLayerCoords; + + // Map back to the target surface coordinate system. + drawRect = layerOriginTransform.mapRect(dirtyRect); } void ContentLayerChromium::updateContents() @@ -205,12 +199,21 @@ void ContentLayerChromium::updateContents() m_skipsDraw = true; return; } - if (m_largeLayerDirtyRect == dirtyRect) - return; - m_largeLayerDirtyRect = dirtyRect; - requiredTextureSize = dirtyRect.size(); - updateRect = IntRect(IntPoint(0, 0), dirtyRect.size()); + // If the portion of the large layer that's visible hasn't changed + // then we don't need to update it, _unless_ its contents have changed + // in which case we only update the dirty bits. + if (m_largeLayerDirtyRect == dirtyRect) { + if (!m_dirtyRect.intersects(dirtyRect)) + return; + dirtyRect.intersect(IntRect(m_dirtyRect)); + updateRect = dirtyRect; + requiredTextureSize = m_largeLayerDirtyRect.size(); + } else { + m_largeLayerDirtyRect = dirtyRect; + requiredTextureSize = dirtyRect.size(); + updateRect = IntRect(IntPoint(0, 0), dirtyRect.size()); + } } else { dirtyRect = IntRect(m_dirtyRect); IntRect boundsRect(IntPoint(0, 0), m_bounds); @@ -227,6 +230,9 @@ void ContentLayerChromium::updateContents() updateRect = dirtyRect; } + if (dirtyRect.isEmpty()) + return; + #if PLATFORM(SKIA) const SkBitmap* skiaBitmap = 0; OwnPtr<skia::PlatformCanvas> canvas; @@ -266,7 +272,7 @@ void ContentLayerChromium::updateContents() RetainPtr<CGContextRef> contextCG(AdoptCF, CGBitmapContextCreate(tempVector.data(), dirtyRect.width(), dirtyRect.height(), 8, rowBytes, colorSpace.get(), - kCGImageAlphaPremultipliedLast)); + kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host)); CGContextTranslateCTM(contextCG.get(), 0, dirtyRect.height()); CGContextScaleCTM(contextCG.get(), 1, -1); diff --git a/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp b/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp index e44ec9d..0395bc2 100644 --- a/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp +++ b/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp @@ -71,6 +71,11 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context, const IntSize& size) : m_context(context) , m_size(size) , m_fbo(0) + , m_colorBuffer(0) + , m_depthStencilBuffer(0) + , m_multisampleFBO(0) + , m_multisampleColorBuffer(0) + , m_multisampleDepthStencilBuffer(0) , m_internal(new DrawingBufferInternal) { if (!m_context->getExtensions()->supports("GL_CHROMIUM_copy_texture_to_parent_texture")) { @@ -79,7 +84,7 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context, const IntSize& size) } m_fbo = context->createFramebuffer(); context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); - m_internal->offscreenColorTexture = generateColorTexture(context, size); + m_colorBuffer = generateColorTexture(context, size); } DrawingBuffer::~DrawingBuffer() @@ -93,7 +98,7 @@ DrawingBuffer::~DrawingBuffer() return; m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); - m_context->deleteTexture(m_internal->offscreenColorTexture); + m_context->deleteTexture(m_colorBuffer); clear(); } @@ -113,23 +118,13 @@ void DrawingBuffer::publishToPlatformLayer() // happens before the compositor draws. This means we might draw stale frames sometimes. Ideally this // would insert a fence into the child command stream that the compositor could wait for. m_context->makeContextCurrent(); - static_cast<Extensions3DChromium*>(m_context->getExtensions())->copyTextureToParentTextureCHROMIUM(m_internal->offscreenColorTexture, parentTexture); + static_cast<Extensions3DChromium*>(m_context->getExtensions())->copyTextureToParentTextureCHROMIUM(m_colorBuffer, parentTexture); m_context->flush(); } #endif -void DrawingBuffer::reset(const IntSize& newSize) +void DrawingBuffer::didReset() { - if (!m_context) - return; - - if (m_size == newSize) - return; - m_size = newSize; - - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_internal->offscreenColorTexture); - m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_size.width(), m_size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0); - #if USE(ACCELERATED_COMPOSITING) if (m_internal->platformLayer) m_internal->platformLayer->setTextureChanged(); @@ -145,9 +140,9 @@ PlatformLayer* DrawingBuffer::platformLayer() } #endif -unsigned DrawingBuffer::getRenderingResultsAsTexture() +Platform3DObject DrawingBuffer::platformColorBuffer() const { - return m_internal->offscreenColorTexture; + return m_colorBuffer; } } diff --git a/WebCore/platform/graphics/chromium/Extensions3DChromium.h b/WebCore/platform/graphics/chromium/Extensions3DChromium.h index 0fd1fff..5fda020 100644 --- a/WebCore/platform/graphics/chromium/Extensions3DChromium.h +++ b/WebCore/platform/graphics/chromium/Extensions3DChromium.h @@ -36,9 +36,15 @@ class Extensions3DChromium : public Extensions3D { public: virtual ~Extensions3DChromium(); + // Supported extensions: + // GL_CHROMIUM_resource_safe : indicating that textures/renderbuffers are always initialized before read/write. + // GL_CHROMIUM_strict_attribs : indicating a GL error is generated for out-of-bounds buffer accesses. + // Extensions3D methods. virtual bool supports(const String&); virtual int getGraphicsResetStatusARB(); + virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter) { } + virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height) { } enum { // GL_CHROMIUM_map_sub (enums inherited from GL_ARB_vertex_buffer_object) diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp index e73747f..9fc7558 100644 --- a/WebCore/platform/graphics/chromium/FontLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontLinux.cpp @@ -164,7 +164,8 @@ public: TextRunWalker(const TextRun&, unsigned, const Font*); ~TextRunWalker(); - bool isWordBreak(unsigned, bool); + bool isWordBreak(unsigned); + int determineWordBreakSpacing(unsigned); // setPadding sets a number of pixels to be distributed across the TextRun. // WebKit uses this to justify text. void setPadding(int); @@ -182,10 +183,8 @@ public: // setLetterSpacingAdjustment sets an additional number of pixels that is // added to the advance after each output cluster. This matches the behaviour // of WidthIterator::advance. - // - // (NOTE: currently does nothing because I don't know how to get the - // cluster information from Harfbuzz.) void setLetterSpacingAdjustment(int letterSpacingAdjustment) { m_letterSpacing = letterSpacingAdjustment; } + int letterSpacing() const { return m_letterSpacing; } // Set the x offset for the next script run. This affects the values in // |xPositions| @@ -256,7 +255,7 @@ private: // Since we only add a whole number of padding pixels at // each word break we accumulate error. This is the // number of pixels that we are behind so far. - unsigned m_letterSpacing; // pixels to be added after each glyph. + int m_letterSpacing; // pixels to be added after each glyph. }; @@ -301,11 +300,32 @@ TextRunWalker::~TextRunWalker() delete[] m_item.log_clusters; } -bool TextRunWalker::isWordBreak(unsigned index, bool isRTL) +bool TextRunWalker::isWordBreak(unsigned index) { - if (!isRTL) - return index && isCodepointSpace(m_item.string[index]) && !isCodepointSpace(m_item.string[index - 1]); - return index != m_item.stringLength - 1 && isCodepointSpace(m_item.string[index]) && !isCodepointSpace(m_item.string[index + 1]); + return index && isCodepointSpace(m_item.string[index]) && !isCodepointSpace(m_item.string[index - 1]); +} + +int TextRunWalker::determineWordBreakSpacing(unsigned logClustersIndex) +{ + int wordBreakSpacing = 0; + // The first half of the conjunction works around the case where + // output glyphs aren't associated with any codepoints by the + // clusters log. + if (logClustersIndex < m_item.item.length + && isWordBreak(m_item.item.pos + logClustersIndex)) { + wordBreakSpacing = m_wordSpacingAdjustment; + + if (m_padding > 0) { + int toPad = roundf(m_padPerWordBreak + m_padError); + m_padError += m_padPerWordBreak - toPad; + + if (m_padding < toPad) + toPad = m_padding; + m_padding -= toPad; + wordBreakSpacing += toPad; + } + } + return wordBreakSpacing; } // setPadding sets a number of pixels to be distributed across the TextRun. @@ -323,7 +343,7 @@ void TextRunWalker::setPadding(int padding) bool isRTL = m_iterateBackwards; for (unsigned i = 0; i < m_item.stringLength; i++) { - if (isWordBreak(i, isRTL)) + if (isWordBreak(i)) numWordBreaks++; } @@ -490,54 +510,51 @@ void TextRunWalker::setGlyphXPositions(bool isRTL) // RTL) codepoint of the current glyph. Each time we advance a glyph, // we skip over all the codepoints that contributed to the current // glyph. - unsigned logClustersIndex = isRTL ? m_item.num_glyphs - 1 : 0; + int logClustersIndex = 0; + + if (isRTL) { + logClustersIndex = m_item.num_glyphs - 1; - for (unsigned iter = 0; iter < m_item.num_glyphs; ++iter) { // Glyphs are stored in logical order, but for layout purposes we // always go left to right. - int i = isRTL ? m_item.num_glyphs - iter - 1 : iter; - - m_glyphs16[i] = m_item.glyphs[i]; - double offsetX = truncateFixedPointToInteger(m_item.offsets[i].x); - m_xPositions[i] = m_offsetX + position + offsetX; - - double advance = truncateFixedPointToInteger(m_item.advances[i]); - // The first half of the conjuction works around the case where - // output glyphs aren't associated with any codepoints by the - // clusters log. - if (logClustersIndex < m_item.item.length - && isWordBreak(m_item.item.pos + logClustersIndex, isRTL)) { - advance += m_wordSpacingAdjustment; - - if (m_padding > 0) { - unsigned toPad = roundf(m_padPerWordBreak + m_padError); - m_padError += m_padPerWordBreak - toPad; - - if (m_padding < toPad) - toPad = m_padding; - m_padding -= toPad; - advance += toPad; - } - } + for (int i = m_item.num_glyphs - 1; i >= 0; --i) { + // Whitespace must be laid out in logical order, so when inserting + // spaces in RTL (but iterating in LTR order) we must insert spaces + // _before_ the next glyph. + if (i + 1 >= m_item.num_glyphs || m_item.attributes[i + 1].clusterStart) + position += m_letterSpacing; + + position += determineWordBreakSpacing(logClustersIndex); - // We would like to add m_letterSpacing after each cluster, but I - // don't know where the cluster information is. This is typically - // fine for Roman languages, but breaks more complex languages - // terribly. - // advance += m_letterSpacing; + m_glyphs16[i] = m_item.glyphs[i]; + double offsetX = truncateFixedPointToInteger(m_item.offsets[i].x); + m_xPositions[i] = m_offsetX + position + offsetX; - if (isRTL) { while (logClustersIndex > 0 && logClusters()[logClustersIndex] == i) logClustersIndex--; - } else { + + position += truncateFixedPointToInteger(m_item.advances[i]); + } + } else { + for (int i = 0; i < m_item.num_glyphs; ++i) { + m_glyphs16[i] = m_item.glyphs[i]; + double offsetX = truncateFixedPointToInteger(m_item.offsets[i].x); + m_xPositions[i] = m_offsetX + position + offsetX; + + double advance = truncateFixedPointToInteger(m_item.advances[i]); + + advance += determineWordBreakSpacing(logClustersIndex); + + if (m_item.attributes[i].clusterStart) + advance += m_letterSpacing; + while (logClustersIndex < m_item.item.length && logClusters()[logClustersIndex] == i) logClustersIndex++; - } - position += advance; + position += advance; + } } - - m_pixelWidth = position; + m_pixelWidth = std::max(position, 0.0); m_offsetX += m_pixelWidth; } @@ -675,16 +692,19 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon static int glyphIndexForXPositionInScriptRun(const TextRunWalker& walker, int x) { const HB_Fixed* advances = walker.advances(); + int letterSpacing = walker.letterSpacing(); int glyphIndex; if (walker.rtl()) { for (glyphIndex = walker.length() - 1; glyphIndex >= 0; --glyphIndex) { - if (x < truncateFixedPointToInteger(advances[glyphIndex])) + // When iterating LTR over RTL text, we must include the whitespace + // _before_ the glyph, so no + 1 here. + if (x < (walker.length() - glyphIndex) * letterSpacing + truncateFixedPointToInteger(advances[glyphIndex])) break; x -= truncateFixedPointToInteger(advances[glyphIndex]); } } else { for (glyphIndex = 0; static_cast<unsigned>(glyphIndex) < walker.length(); ++glyphIndex) { - if (x < truncateFixedPointToInteger(advances[glyphIndex])) + if (x < (glyphIndex * letterSpacing + truncateFixedPointToInteger(advances[glyphIndex]))) break; x -= truncateFixedPointToInteger(advances[glyphIndex]); } diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h b/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h index c59cb56..b6ebb2e 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h +++ b/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h @@ -34,6 +34,7 @@ #include "config.h" +#include "FontOrientation.h" #include <wtf/Forward.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> @@ -69,6 +70,8 @@ public: HFONT hfont() const { return m_font ? m_font->hfont() : 0; } float size() const { return m_size; } + FontOrientation orientation() const { return Horizontal; } // FIXME: Implement. + unsigned hash() const { return m_font ? m_font->hash() : NULL; diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h index 363e55f..694a945 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h +++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h @@ -31,6 +31,7 @@ #ifndef FontPlatformDataLinux_h #define FontPlatformDataLinux_h +#include "FontOrientation.h" #include "FontRenderStyle.h" #include <wtf/Forward.h> #include <wtf/RefPtr.h> @@ -105,6 +106,8 @@ public: unsigned hash() const; float size() const { return m_textSize; } + FontOrientation orientation() const { return Horizontal; } // FIXME: Implement. + bool operator==(const FontPlatformData&) const; FontPlatformData& operator=(const FontPlatformData&); bool isHashTableDeletedValue() const { return m_typeface == hashTableDeletedFontValue(); } diff --git a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp index afcc98c..adcbb82 100644 --- a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp @@ -135,7 +135,7 @@ void ImageLayerChromium::updateContents() RetainPtr<CGContextRef> tempContext(AdoptCF, CGBitmapContextCreate(tempVector.data(), width, height, 8, tempRowBytes, colorSpace, - kCGImageAlphaPremultipliedLast)); + kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host)); CGContextSetBlendMode(tempContext.get(), kCGBlendModeCopy); CGContextDrawImage(tempContext.get(), CGRectMake(0, 0, static_cast<CGFloat>(width), static_cast<CGFloat>(height)), diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp index 23e54e5..1f4feaf 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -143,6 +143,7 @@ PassRefPtr<LayerChromium> LayerChromium::create(GraphicsLayerChromium* owner) LayerChromium::LayerChromium(GraphicsLayerChromium* owner) : m_owner(owner) , m_contentsDirty(false) + , m_targetRenderSurface(0) , m_superlayer(0) , m_anchorPoint(0.5, 0.5) , m_backgroundColor(0, 0, 0, 0) @@ -158,7 +159,9 @@ LayerChromium::LayerChromium(GraphicsLayerChromium* owner) , m_opaque(true) , m_geometryFlipped(false) , m_needsDisplayOnBoundsChange(false) + , m_drawDepth(0) , m_layerRenderer(0) + , m_renderSurface(0) { } @@ -172,6 +175,12 @@ LayerChromium::~LayerChromium() removeAllSublayers(); } +void LayerChromium::cleanupResources() +{ + if (m_renderSurface) + m_renderSurface->cleanupResources(); +} + void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer) { // If we're changing layer renderers then we need to free up any resources @@ -184,6 +193,12 @@ void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer) m_layerRenderer = renderer; } +RenderSurfaceChromium* LayerChromium::createRenderSurface() +{ + m_renderSurface = new RenderSurfaceChromium(this); + return m_renderSurface.get(); +} + unsigned LayerChromium::createShaderProgram(GraphicsContext3D* context, const char* vertexShaderSource, const char* fragmentShaderSource) { unsigned vertexShader = loadShader(context, GraphicsContext3D::VERTEX_SHADER, vertexShaderSource); @@ -463,24 +478,27 @@ const IntRect LayerChromium::getDrawRect() const return mappedRect; } -// Draws the layer with a single colored shader. This method is used to do -// quick draws into the stencil buffer. -void LayerChromium::drawAsMask() +// Returns true if any of the layer's descendants has drawable content. +bool LayerChromium::descendantsDrawContent() { - ASSERT(layerRenderer()); - const SharedValues* sv = layerRenderer()->layerSharedValues(); - ASSERT(sv && sv->initialized()); - layerRenderer()->useShader(sv->borderShaderProgram()); - - // We reuse the border shader here as all we need a single colored shader pass. - // The color specified here is only for debug puproses as typically when we call this - // method, writes to the color channels are disabled. - GraphicsContext3D* context = layerRendererContext(); - GLC(context, context->uniform4f(sv->borderShaderColorLocation(), 0, 1 , 0, 0.7)); + const Vector<RefPtr<LayerChromium> >& sublayers = getSublayers(); + for (size_t i = 0; i < sublayers.size(); ++i) + if (sublayers[i]->descendantsDrawContentRecursive()) + return true; + return false; +} - drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), - bounds().width(), bounds().height(), drawOpacity(), - sv->borderShaderMatrixLocation(), -1); +// 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; } // static diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h index 3956e28..86f3580 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.h +++ b/WebCore/platform/graphics/chromium/LayerChromium.h @@ -38,6 +38,7 @@ #include "GraphicsContext.h" #include "GraphicsLayerChromium.h" #include "PlatformString.h" +#include "RenderSurfaceChromium.h" #include "TransformationMatrix.h" #include <wtf/OwnPtr.h> #include <wtf/PassRefPtr.h> @@ -139,10 +140,7 @@ public: void setGeometryFlipped(bool flipped) { m_geometryFlipped = flipped; setNeedsCommit(); } bool geometryFlipped() const { return m_geometryFlipped; } - void setDrawTransform(const TransformationMatrix& transform) { m_drawTransform = transform; } const TransformationMatrix& drawTransform() const { return m_drawTransform; } - - void setDrawOpacity(float opacity) { m_drawOpacity = opacity; } float drawOpacity() const { return m_drawOpacity; } bool preserves3D() { return m_owner && m_owner->preserves3D(); } @@ -165,8 +163,7 @@ public: void drawDebugBorder(); - // Draws the layer without a texture. This is used for stencil operations. - void drawAsMask(); + RenderSurfaceChromium* createRenderSurface(); // Stores values that are shared between instances of this class that are // associated with the same LayerRendererChromium (and hence the same GL @@ -198,6 +195,8 @@ public: static void prepareForDraw(const SharedValues*); + LayerRendererChromium* layerRenderer() const { return m_layerRenderer.get(); } + protected: GraphicsLayerChromium* m_owner; LayerChromium(GraphicsLayerChromium* owner); @@ -205,11 +204,13 @@ protected: // This is called to clean up resources being held in the same context as // layerRendererContext(). Subclasses should override this method if they // hold context-dependent resources such as textures. - virtual void cleanupResources() { } + virtual void cleanupResources(); - LayerRendererChromium* layerRenderer() const { return m_layerRenderer.get(); } GraphicsContext3D* layerRendererContext() const; + // Returns true if any of the layer's descendants has content to draw. + bool descendantsDrawContent(); + static void drawTexturedQuad(GraphicsContext3D*, const TransformationMatrix& projectionMatrix, const TransformationMatrix& layerMatrix, float width, float height, float opacity, int matrixLocation, int alphaLocation); @@ -222,6 +223,12 @@ protected: FloatRect m_dirtyRect; bool m_contentsDirty; + // Render surface this layer draws into. This is a surface that can belong + // either to this layer (if m_targetRenderSurface == m_renderSurface) or + // to an ancestor of this layer. The target render surface determines the + // coordinate system the layer's transforms are relative to. + RenderSurfaceChromium* m_targetRenderSurface; + // All layer shaders share the same attribute locations for the vertex positions // and texture coordinates. This allows switching shaders without rebinding attribute // arrays. @@ -244,6 +251,8 @@ private: // This should only be called from removeFromSuperlayer. void removeSublayer(LayerChromium*); + bool descendantsDrawContentRecursive(); + Vector<RefPtr<LayerChromium> > m_sublayers; LayerChromium* m_superlayer; @@ -266,6 +275,10 @@ private: bool m_geometryFlipped; bool m_needsDisplayOnBoundsChange; + // The global depth value of the center of the layer. This value is used + // to sort layers from back to front. + float m_drawDepth; + // Points to the layer renderer that updates and draws this layer. RefPtr<LayerRendererChromium> m_layerRenderer; @@ -274,6 +287,18 @@ private: TransformationMatrix m_sublayerTransform; TransformationMatrix m_drawTransform; + // 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. + IntRect m_scissorRect; + + // Render surface associated with this layer. The layer and its descendants + // will render to this surface. + OwnPtr<RenderSurfaceChromium> m_renderSurface; + + // Hierarchical bounding rect containing the layer and its descendants. + IntRect m_drawableContentRect; + String m_name; }; diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index e1b525b..91580cc 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -48,29 +48,38 @@ namespace WebCore { -static TransformationMatrix orthoMatrix(float left, float right, float bottom, float top, float nearZ, float farZ) +static TransformationMatrix orthoMatrix(float left, float right, float bottom, float top) { float deltaX = right - left; float deltaY = top - bottom; - float deltaZ = farZ - nearZ; TransformationMatrix ortho; - if (!deltaX || !deltaY || !deltaZ) + if (!deltaX || !deltaY) return ortho; ortho.setM11(2.0f / deltaX); ortho.setM41(-(right + left) / deltaX); ortho.setM22(2.0f / deltaY); ortho.setM42(-(top + bottom) / deltaY); - ortho.setM33(-2.0f / deltaZ); - ortho.setM43(-(nearZ + farZ) / deltaZ); + + // Z component of vertices is always set to zero as we don't use the depth buffer + // while drawing. + ortho.setM33(0); + return ortho; } -static inline bool compareLayerZ(const LayerChromium* a, const LayerChromium* b) +// Returns true if the matrix has no rotation, skew or perspective components to it. +static bool isScaleOrTranslation(const TransformationMatrix& m) { - const TransformationMatrix& transformA = a->drawTransform(); - const TransformationMatrix& transformB = b->drawTransform(); + return !m.m12() && !m.m13() && !m.m14() + && !m.m21() && !m.m23() && !m.m24() + && !m.m31() && !m.m32() && !m.m43() + && m.m44(); + +} - return transformA.m43() < transformB.m43(); +bool LayerRendererChromium::compareLayerZ(const LayerChromium* a, const LayerChromium* b) +{ + return a->m_drawDepth < b->m_drawDepth; } PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassRefPtr<GraphicsContext3D> context) @@ -89,11 +98,14 @@ LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> conte : m_rootLayerTextureId(0) , m_rootLayerTextureWidth(0) , m_rootLayerTextureHeight(0) - , m_scrollShaderProgram(0) + , m_textureLayerShaderProgram(0) , m_rootLayer(0) , m_scrollPosition(IntPoint(-1, -1)) , m_currentShader(0) + , m_currentRenderSurface(0) + , m_offscreenFramebufferId(0) , m_context(context) + , m_defaultRenderSurface(0) { m_hardwareCompositing = initializeSharedObjects(); } @@ -138,7 +150,7 @@ void LayerRendererChromium::setRootLayerCanvasSize(const IntSize& size) m_rootLayerCGContext.adoptCF(CGBitmapContextCreate(m_rootLayerBackingStore.data(), size.width(), size.height(), 8, rowBytes, colorSpace.get(), - kCGImageAlphaPremultipliedLast)); + kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host)); CGContextTranslateCTM(m_rootLayerCGContext.get(), 0, size.height()); CGContextScaleCTM(m_rootLayerCGContext.get(), 1, -1); m_rootLayerGraphicsContext = new GraphicsContext(m_rootLayerCGContext.get()); @@ -181,12 +193,15 @@ void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, cons int visibleRectWidth = visibleRect.width(); int visibleRectHeight = visibleRect.height(); if (visibleRectWidth != m_rootLayerTextureWidth || visibleRectHeight != m_rootLayerTextureHeight) { - m_rootLayerTextureWidth = visibleRect.width(); - m_rootLayerTextureHeight = visibleRect.height(); + m_rootLayerTextureWidth = visibleRectWidth; + m_rootLayerTextureHeight = visibleRectHeight; - m_projectionMatrix = orthoMatrix(0, visibleRectWidth, visibleRectHeight, 0, -1000, 1000); GLC(m_context, m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_rootLayerTextureWidth, m_rootLayerTextureHeight, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0)); + // Reset the current render surface to force an update of the viewport and + // projection matrix next time useRenderSurface is called. + m_currentRenderSurface = 0; + // The root layer texture was just resized so its contents are not // useful for scrolling. skipScroll = true; @@ -201,8 +216,7 @@ void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, cons // FIXME: These calls can be made once, when the compositor context is initialized. GLC(m_context, m_context->disable(GraphicsContext3D::DEPTH_TEST)); GLC(m_context, m_context->disable(GraphicsContext3D::CULL_FACE)); - GLC(m_context, m_context->depthFunc(GraphicsContext3D::LEQUAL)); - GLC(m_context, m_context->clearStencil(0)); + // Blending disabled by default. Root layer alpha channel on Windows is incorrect when Skia uses ClearType. GLC(m_context, m_context->disable(GraphicsContext3D::BLEND)); @@ -230,11 +244,11 @@ void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, cons 0.5 * visibleRect.height() + scrollDelta.y(), 0); scrolledLayerMatrix.scale3d(1, -1, 1); - useShader(m_scrollShaderProgram); - GLC(m_context, m_context->uniform1i(m_scrollShaderSamplerLocation, 0)); + useShader(m_textureLayerShaderProgram); + GLC(m_context, m_context->uniform1i(m_textureLayerShaderSamplerLocation, 0)); LayerChromium::drawTexturedQuad(m_context.get(), m_projectionMatrix, scrolledLayerMatrix, visibleRect.width(), visibleRect.height(), 1, - m_scrollShaderMatrixLocation, -1); + m_textureLayerShaderMatrixLocation, m_textureLayerShaderAlphaLocation); GLC(m_context, m_context->copyTexSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, 0, 0, contentRect.width(), contentRect.height())); } @@ -257,7 +271,7 @@ void LayerRendererChromium::updateRootLayerTextureRect(const IntRect& updateRect #if PLATFORM(SKIA) // Get the contents of the updated rect. - const SkBitmap bitmap = m_rootLayerCanvas->getDevice()->accessBitmap(false); + const SkBitmap& bitmap = m_rootLayerCanvas->getDevice()->accessBitmap(false); ASSERT(bitmap.width() == updateRect.width() && bitmap.height() == updateRect.height()); void* pixels = bitmap.getPixels(); #elif PLATFORM(CG) @@ -275,8 +289,16 @@ void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect { ASSERT(m_hardwareCompositing); + m_defaultRenderSurface = m_rootLayer->m_renderSurface.get(); + if (!m_defaultRenderSurface) + m_defaultRenderSurface = m_rootLayer->createRenderSurface(); + m_defaultRenderSurface->m_contentRect = IntRect(0, 0, m_rootLayerTextureWidth, m_rootLayerTextureHeight); + + useRenderSurface(m_defaultRenderSurface); + + // Clear to blue to make it easier to spot unrendered regions. m_context->clearColor(0, 0, 1, 1); - m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT); + m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId)); @@ -295,46 +317,54 @@ void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect contentLayerValues->shaderMatrixLocation(), contentLayerValues->shaderAlphaLocation()); GLC(m_context, m_context->colorMask(true, true, true, true)); - // If culling is enabled then we will cull the backface. - GLC(m_context, m_context->cullFace(GraphicsContext3D::BACK)); - // The orthographic projection is setup such that Y starts at zero and - // increases going down the page so we need to adjust the winding order of - // front facing triangles. - GLC(m_context, m_context->frontFace(GraphicsContext3D::CW)); - - // The shader used to render layers returns pre-multiplied alpha colors - // so we need to send the blending mode appropriately. - GLC(m_context, m_context->enable(GraphicsContext3D::BLEND)); - GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); - // Set the root visible/content rects --- used by subsequent drawLayers calls. m_rootVisibleRect = visibleRect; m_rootContentRect = contentRect; - // Traverse the layer tree and update the layer transforms. - float opacity = 1; - const Vector<RefPtr<LayerChromium> >& sublayers = m_rootLayer->getSublayers(); - size_t i; + // Scissor out the scrollbars to avoid rendering on top of them. + IntRect rootScissorRect(contentRect); + // The scissorRect should not include the scroll offset. + rootScissorRect.move(-m_scrollPosition.x(), -m_scrollPosition.y()); + m_rootLayer->m_scissorRect = rootScissorRect; + + Vector<LayerChromium*> renderSurfaceLayerList; + renderSurfaceLayerList.append(m_rootLayer.get()); + TransformationMatrix identityMatrix; - for (i = 0; i < sublayers.size(); i++) - updateLayersRecursive(sublayers[i].get(), identityMatrix, opacity); + m_defaultRenderSurface->m_layerList.clear(); + updateLayersRecursive(m_rootLayer.get(), identityMatrix, renderSurfaceLayerList, m_defaultRenderSurface->m_layerList); - // Enable scissoring to avoid rendering composited layers over the scrollbars. + // The shader used to render layers returns pre-multiplied alpha colors + // so we need to send the blending mode appropriately. + GLC(m_context, m_context->enable(GraphicsContext3D::BLEND)); + GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST)); - IntRect scissorRect(contentRect); - // The scissorRect should not include the scroll offset. - scissorRect.move(-m_scrollPosition.x(), -m_scrollPosition.y()); - scissorToRect(scissorRect); - - // Clear the stencil buffer to 0. - GLC(m_context, m_context->clear(GraphicsContext3D::STENCIL_BUFFER_BIT)); - // Disable writes to the stencil buffer. - GLC(m_context, m_context->stencilMask(0)); + // Update the contents of the render surfaces. We traverse the array from + // back to front to guarantee that nested render surfaces get rendered in the + // correct order. + for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { + LayerChromium* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; + ASSERT(renderSurfaceLayer->m_renderSurface); + + // Render surfaces whose drawable area has zero width or height + // will have no layers associated with them and should be skipped. + if (!renderSurfaceLayer->m_renderSurface->m_layerList.size()) + continue; + + useRenderSurface(renderSurfaceLayer->m_renderSurface.get()); + if (renderSurfaceLayer != m_rootLayer) { + GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST)); + GLC(m_context, m_context->clearColor(0, 0, 0, 0)); + GLC(m_context, m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT)); + GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST)); + } - // Traverse the layer tree one more time to draw the layers. - for (size_t i = 0; i < sublayers.size(); i++) - drawLayersRecursive(sublayers[i].get()); + Vector<LayerChromium*>& layerList = renderSurfaceLayer->m_renderSurface->m_layerList; + ASSERT(layerList.size()); + for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) + drawLayer(layerList[layerIndex], renderSurfaceLayer->m_renderSurface.get()); + } GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST)); GLC(m_context, m_context->disable(GraphicsContext3D::BLEND)); @@ -408,10 +438,12 @@ bool LayerRendererChromium::isLayerVisible(LayerChromium* layer, const Transform return mappedRect.intersects(FloatRect(-1, -1, 2, 2)); } -// Recursively walks the layer tree starting at the given node and updates the -// transform and opacity values. -void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, float opacity) +// Recursively walks the layer tree starting at the given node and computes all the +// necessary transformations, scissor rectangles, render surfaces, etc. +void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, Vector<LayerChromium*>& renderSurfaceLayerList, Vector<LayerChromium*>& layerList) { + layer->setLayerRenderer(this); + // 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 // is the position of the layer's anchor point. Also, the coordinate system used @@ -438,182 +470,254 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr float centerOffsetX = (0.5 - anchorPoint.x()) * bounds.width(); float centerOffsetY = (0.5 - anchorPoint.y()) * bounds.height(); - // M = M[p] - TransformationMatrix localMatrix = parentMatrix; - // M = M[p] * Tr[l] - localMatrix.translate3d(position.x(), position.y(), layer->anchorPointZ()); - // M = M[p] * Tr[l] * M[l] - localMatrix.multLeft(layer->transform()); - // M = M[p] * Tr[l] * M[l] * Tr[c] - localMatrix.translate3d(centerOffsetX, centerOffsetY, -layer->anchorPointZ()); + TransformationMatrix layerLocalTransform; + // LT = Tr[l] + layerLocalTransform.translate3d(position.x(), position.y(), layer->anchorPointZ()); + // LT = Tr[l] * M[l] + layerLocalTransform.multLeft(layer->transform()); + // LT = Tr[l] * M[l] * Tr[c] + layerLocalTransform.translate3d(centerOffsetX, centerOffsetY, -layer->anchorPointZ()); + + TransformationMatrix combinedTransform = parentMatrix; + combinedTransform = combinedTransform.multLeft(layerLocalTransform); + + FloatRect layerRect(-0.5 * layer->bounds().width(), -0.5 * layer->bounds().height(), layer->bounds().width(), layer->bounds().height()); + IntRect transformedLayerRect; + + // The layer and its descendants render on a new RenderSurface if any of + // these conditions hold: + // 1. The layer clips its descendants and its transform is not a simple translation. + // 2. If the layer has opacity != 1 and does not have a preserves-3d transform style. + // 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(); + if ((useSurfaceForClipping || useSurfaceForOpacity) && layer->descendantsDrawContent()) { + RenderSurfaceChromium* renderSurface = layer->m_renderSurface.get(); + if (!renderSurface) + renderSurface = layer->createRenderSurface(); + + // The origin of the new surface is the upper left corner of the layer. + layer->m_drawTransform = TransformationMatrix(); + layer->m_drawTransform.translate3d(0.5 * bounds.width(), 0.5 * bounds.height(), 0); + + 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()->preserves3D()) + renderSurface->m_drawOpacity *= layer->superlayer()->m_drawOpacity; + layer->m_drawOpacity = 1; + + TransformationMatrix layerOriginTransform = combinedTransform; + layerOriginTransform.translate3d(-0.5 * bounds.width(), -0.5 * bounds.height(), 0); + renderSurface->m_originTransform = layerOriginTransform; + if (layerOriginTransform.isInvertible() && layer->superlayer()) { + TransformationMatrix parentToLayer = layerOriginTransform.inverse(); + + layer->m_scissorRect = parentToLayer.mapRect(layer->superlayer()->m_scissorRect); + } else + layer->m_scissorRect = IntRect(); + + // The render surface scissor rect is the scissor rect that needs to + // be applied before drawing the render surface onto its containing + // surface and is therefore expressed in the superlayer's coordinate system. + renderSurface->m_scissorRect = layer->superlayer()->m_scissorRect; + + renderSurface->m_layerList.clear(); + + renderSurfaceLayerList.append(layer); + } else { + // DT = M[p] * LT + layer->m_drawTransform = combinedTransform; + transformedLayerRect = enclosingIntRect(layer->m_drawTransform.mapRect(layerRect)); + + layer->m_drawOpacity = layer->opacity(); + + if (layer->superlayer()) { + if (layer->superlayer()->preserves3D()) + layer->m_drawOpacity *= layer->superlayer()->m_drawOpacity; + + // Layers inherit the scissor rect from their superlayer. + layer->m_scissorRect = layer->superlayer()->m_scissorRect; - // Calculate the layer's opacity. - opacity *= layer->opacity(); + layer->m_targetRenderSurface = layer->superlayer()->m_targetRenderSurface; + } + + if (layer != m_rootLayer) + layer->m_renderSurface = 0; + + if (layer->masksToBounds()) + layer->m_scissorRect.intersect(transformedLayerRect); + } + + if (layer->m_renderSurface) + layer->m_targetRenderSurface = layer->m_renderSurface.get(); + else { + ASSERT(layer->superlayer()); + layer->m_targetRenderSurface = layer->superlayer()->m_targetRenderSurface; + } - layer->setDrawTransform(localMatrix); - layer->setDrawOpacity(opacity); + // m_drawableContentRect is always stored in the coordinate system of the + // RenderSurface the layer draws into. + if (layer->drawsContent()) + layer->m_drawableContentRect = transformedLayerRect; + else + layer->m_drawableContentRect = IntRect(); + + TransformationMatrix sublayerMatrix = layer->m_drawTransform; // Flatten to 2D if the layer doesn't preserve 3D. if (!layer->preserves3D()) { - localMatrix.setM13(0); - localMatrix.setM23(0); - localMatrix.setM31(0); - localMatrix.setM32(0); - localMatrix.setM33(1); - localMatrix.setM34(0); - localMatrix.setM43(0); + sublayerMatrix.setM13(0); + sublayerMatrix.setM23(0); + sublayerMatrix.setM31(0); + sublayerMatrix.setM32(0); + sublayerMatrix.setM33(1); + sublayerMatrix.setM34(0); + sublayerMatrix.setM43(0); } // Apply the sublayer transform at the center of the layer. - localMatrix.multLeft(layer->sublayerTransform()); + sublayerMatrix.multLeft(layer->sublayerTransform()); - // The origin of the sublayers is actually the bottom left corner of the layer - // (or top left when looking it it from the browser's pespective) instead of the center. - // The matrix passed down to the sublayers is therefore: + // 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: // M[s] = M * Tr[-center] - localMatrix.translate3d(-bounds.width() * 0.5, -bounds.height() * 0.5, 0); + sublayerMatrix.translate3d(-bounds.width() * 0.5, -bounds.height() * 0.5, 0); + + Vector<LayerChromium*>& descendants = (layer->m_renderSurface ? layer->m_renderSurface->m_layerList : layerList); + descendants.append(layer); + unsigned thisLayerIndex = descendants.size() - 1; const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); - for (size_t i = 0; i < sublayers.size(); i++) - updateLayersRecursive(sublayers[i].get(), localMatrix, opacity); + for (size_t i = 0; i < sublayers.size(); ++i) { + LayerChromium* sublayer = sublayers[i].get(); + updateLayersRecursive(sublayer, sublayerMatrix, renderSurfaceLayerList, descendants); + + if (sublayer->m_renderSurface) { + RenderSurfaceChromium* sublayerRenderSurface = sublayer->m_renderSurface.get(); + const IntRect& contentRect = sublayerRenderSurface->m_contentRect; + FloatRect sublayerRect(-0.5 * contentRect.width(), -0.5 * contentRect.height(), + contentRect.width(), contentRect.height()); + layer->m_drawableContentRect.unite(enclosingIntRect(sublayerRenderSurface->m_drawTransform.mapRect(sublayerRect))); + descendants.append(sublayer); + } else + layer->m_drawableContentRect.unite(sublayer->m_drawableContentRect); + } - layer->setLayerRenderer(this); -} + if (layer->masksToBounds()) + layer->m_drawableContentRect.intersect(transformedLayerRect); -// Does a quick draw of the given layer into the stencil buffer. If decrement -// is true then it decrements the current stencil values otherwise it increments them. -void LayerRendererChromium::drawLayerIntoStencilBuffer(LayerChromium* layer, bool decrement) -{ - // Enable writes to the stencil buffer and increment the stencil values - // by one for every pixel under the current layer. - GLC(m_context, m_context->stencilMask(0xff)); - GLC(m_context, m_context->stencilFunc(GraphicsContext3D::ALWAYS, 1, 0xff)); - unsigned stencilOp = (decrement ? GraphicsContext3D::DECR : GraphicsContext3D::INCR); - GLC(m_context, m_context->stencilOp(stencilOp, stencilOp, stencilOp)); + if (layer->m_renderSurface && layer != m_rootLayer) { + RenderSurfaceChromium* renderSurface = layer->m_renderSurface.get(); + renderSurface->m_contentRect = layer->m_drawableContentRect; + FloatPoint surfaceCenter = renderSurface->contentRectCenter(); - GLC(m_context, m_context->colorMask(false, false, false, false)); + // Restrict the RenderSurface size to the portion that's visible. + FloatSize centerOffsetDueToClipping; + renderSurface->m_contentRect.intersect(layer->m_scissorRect); + FloatPoint clippedSurfaceCenter = renderSurface->contentRectCenter(); + centerOffsetDueToClipping = clippedSurfaceCenter - surfaceCenter; - layer->drawAsMask(); + // The RenderSurface backing texture cannot exceed the maximum supported + // texture size. + renderSurface->m_contentRect.setWidth(std::min(renderSurface->m_contentRect.width(), m_maxTextureSize)); + renderSurface->m_contentRect.setHeight(std::min(renderSurface->m_contentRect.height(), m_maxTextureSize)); - // Disable writes to the stencil buffer. - GLC(m_context, m_context->stencilMask(0)); - GLC(m_context, m_context->colorMask(true, true, true, true)); + if (renderSurface->m_contentRect.isEmpty()) + renderSurface->m_layerList.clear(); + + // Since the layer starts a new render surface we need to adjust its + // scissor rect to be expressed in the new surface's coordinate system. + layer->m_scissorRect = layer->m_drawableContentRect; + + // Adjust the origin of the transform to be the center of the render surface. + renderSurface->m_drawTransform = renderSurface->m_originTransform; + renderSurface->m_drawTransform.translate3d(surfaceCenter.x() + centerOffsetDueToClipping.width(), surfaceCenter.y() + centerOffsetDueToClipping.height(), 0); + } + + // Compute the depth value of the center of the layer which will be used when + // sorting the layers for the preserves-3d property. + TransformationMatrix& layerDrawMatrix = layer->m_renderSurface ? layer->m_renderSurface->m_drawTransform : layer->m_drawTransform; + if (layer->superlayer()) { + if (!layer->superlayer()->preserves3D()) + layer->m_drawDepth = layer->superlayer()->m_drawDepth; + else + layer->m_drawDepth = layerDrawMatrix.m43(); + } else + layer->m_drawDepth = 0; + + // 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())) + std::stable_sort(&descendants.at(thisLayerIndex), descendants.end(), compareLayerZ); } -// Recursively walk the layer tree and draw the layers. -void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer) +bool LayerRendererChromium::useRenderSurface(RenderSurfaceChromium* renderSurface) { - static bool depthTestEnabledForSubtree = false; - static int currentStencilValue = 0; + if (m_currentRenderSurface == renderSurface) + return true; - // Check if the layer falls within the visible bounds of the page. - IntRect layerRect = layer->getDrawRect(); - bool isLayerVisible = m_currentScissorRect.intersects(layerRect); + m_currentRenderSurface = renderSurface; - // Enable depth testing for this layer and all its descendants if preserves3D is set. - bool mustClearDepth = false; - if (layer->preserves3D()) { - if (!depthTestEnabledForSubtree) { - GLC(m_context, m_context->enable(GraphicsContext3D::DEPTH_TEST)); - depthTestEnabledForSubtree = true; - - // Need to clear the depth buffer when we're done rendering this subtree. - mustClearDepth = true; - } + if (renderSurface == m_defaultRenderSurface) { + GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0)); + setDrawViewportRect(renderSurface->m_contentRect, true); + return true; } - if (isLayerVisible) - drawLayer(layer); - - // FIXME: We should check here if the layer has descendants that draw content - // before we setup for clipping. - IntRect previousScissorRect = m_currentScissorRect; - bool mustResetScissorRect = false; - bool didStencilDraw = false; - if (layer->masksToBounds()) { - // If the layer isn't rotated then we can use scissoring otherwise we need - // to clip using the stencil buffer. - if (layer->drawTransform().isIdentityOrTranslation()) { - IntRect currentScissorRect = previousScissorRect; - currentScissorRect.intersect(layerRect); - if (currentScissorRect != previousScissorRect) { - scissorToRect(currentScissorRect); - mustResetScissorRect = true; - } - } else if (currentStencilValue < ((1 << m_numStencilBits) - 1)) { - // Clipping using the stencil buffer works as follows: When we encounter - // a clipping layer we increment the stencil buffer values for all the pixels - // the layer touches. As a result 1's will be stored in the stencil buffer for pixels under - // the first clipping layer found in a traversal, 2's for pixels in the intersection - // of two nested clipping layers, etc. When the sublayers of a clipping layer are drawn - // we turn on stencil testing to render only pixels that have the correct stencil - // value (one that matches the value of currentStencilValue). As the recursion unravels, - // we decrement the stencil buffer values for each clipping layer. When the entire layer tree - // is rendered, the stencil values should be all back to zero. An 8 bit stencil buffer - // will allow us up to 255 nested clipping layers which is hopefully enough. - if (!currentStencilValue) - GLC(m_context, m_context->enable(GraphicsContext3D::STENCIL_TEST)); - - drawLayerIntoStencilBuffer(layer, false); - - currentStencilValue++; - didStencilDraw = true; - } - } - // Sublayers will render only if the value in the stencil buffer is equal to - // currentStencilValue. - if (didStencilDraw) { - // The sublayers will render only if the stencil test passes. - GLC(m_context, m_context->stencilFunc(GraphicsContext3D::EQUAL, currentStencilValue, 0xff)); - } + GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId)); - // If we're using depth testing then we need to sort the children in Z to - // get the transparency to work properly. - if (depthTestEnabledForSubtree) { - const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); - Vector<LayerChromium*> sublayerList; - size_t i; - for (i = 0; i < sublayers.size(); i++) - sublayerList.append(sublayers[i].get()); - - // Sort by the z coordinate of the layer center so that layers further away - // are drawn first. - std::stable_sort(sublayerList.begin(), sublayerList.end(), compareLayerZ); - - for (i = 0; i < sublayerList.size(); i++) - drawLayersRecursive(sublayerList[i]); - } else { - const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); - for (size_t i = 0; i < sublayers.size(); i++) - drawLayersRecursive(sublayers[i].get()); - } + renderSurface->prepareContentsTexture(); - if (didStencilDraw) { - // Draw into the stencil buffer subtracting 1 for every pixel hit - // effectively removing this mask - drawLayerIntoStencilBuffer(layer, true); - currentStencilValue--; - if (!currentStencilValue) { - // Disable stencil testing. - GLC(m_context, m_context->disable(GraphicsContext3D::STENCIL_TEST)); - GLC(m_context, m_context->stencilFunc(GraphicsContext3D::ALWAYS, 0, 0xff)); - } - } + GLC(m_context, m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, + GraphicsContext3D::TEXTURE_2D, renderSurface->m_contentsTextureId, 0)); - if (mustResetScissorRect) { - scissorToRect(previousScissorRect); +#if !defined ( NDEBUG ) + if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { + ASSERT_NOT_REACHED(); + return false; } +#endif - if (mustClearDepth) { - GLC(m_context, m_context->disable(GraphicsContext3D::DEPTH_TEST)); - GLC(m_context, m_context->clear(GraphicsContext3D::DEPTH_BUFFER_BIT)); - depthTestEnabledForSubtree = false; - } + setDrawViewportRect(renderSurface->m_contentRect, false); + return true; } -void LayerRendererChromium::drawLayer(LayerChromium* layer) +void LayerRendererChromium::drawLayer(LayerChromium* layer, RenderSurfaceChromium* targetSurface) { - IntSize bounds = layer->bounds(); + if (layer->m_renderSurface && layer->m_renderSurface != targetSurface) { + GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, layer->m_renderSurface->m_contentsTextureId)); + useShader(m_textureLayerShaderProgram); + + setScissorToRect(layer->m_renderSurface->m_scissorRect); + + IntRect contentRect = layer->m_renderSurface->m_contentRect; + LayerChromium::drawTexturedQuad(m_context.get(), m_projectionMatrix, layer->m_renderSurface->m_drawTransform, + contentRect.width(), contentRect.height(), layer->m_renderSurface->m_drawOpacity, + m_textureLayerShaderMatrixLocation, m_textureLayerShaderAlphaLocation); + return; + } + + if (layer->m_bounds.isEmpty()) + return; + + setScissorToRect(layer->m_scissorRect); + + // Check if the layer falls within the visible bounds of the page. + IntRect layerRect = layer->getDrawRect(); + bool isLayerVisible = layer->m_scissorRect.intersects(layerRect); + if (!isLayerVisible) + return; + + // FIXME: Need to take into account the transform of the containing + // RenderSurface here, otherwise single-sided layers that draw on + // transformed surfaces won't always be culled properly. + if (!layer->doubleSided() && layer->m_drawTransform.m33() < 0) + return; if (layer->drawsContent()) { // Update the contents of the layer if necessary. @@ -623,11 +727,6 @@ void LayerRendererChromium::drawLayer(LayerChromium* layer) m_context->makeContextCurrent(); } - if (layer->doubleSided()) - m_context->disable(GraphicsContext3D::CULL_FACE); - else - m_context->enable(GraphicsContext3D::CULL_FACE); - layer->draw(); } @@ -637,12 +736,19 @@ void LayerRendererChromium::drawLayer(LayerChromium* layer) // Sets the scissor region to the given rectangle. The coordinate system for the // scissorRect has its origin at the top left corner of the current visible rect. -void LayerRendererChromium::scissorToRect(const IntRect& scissorRect) +void LayerRendererChromium::setScissorToRect(const IntRect& scissorRect) { - // Compute the lower left corner of the scissor rect. - int bottom = std::max(m_rootVisibleRect.height() - scissorRect.bottom(), 0); - GLC(m_context, m_context->scissor(scissorRect.x(), bottom, scissorRect.width(), scissorRect.height())); - m_currentScissorRect = scissorRect; + // The scissor coordinates must be supplied in viewport space so we need to offset + // by the relative position of the top left corner of the current render surface. + int scissorX = scissorRect.x() - m_currentRenderSurface->m_contentRect.x(); + // When rendering to the default render surface we're rendering upside down so the top + // of the GL scissor is the bottom of our layer. + int scissorY; + if (m_currentRenderSurface == m_defaultRenderSurface) + scissorY = m_currentRenderSurface->m_contentRect.height() - (scissorRect.bottom() - m_currentRenderSurface->m_contentRect.y()); + else + scissorY = scissorRect.y() - m_currentRenderSurface->m_contentRect.y(); + GLC(m_context, m_context->scissor(scissorX, scissorY, scissorRect.width(), scissorRect.height())); } bool LayerRendererChromium::makeContextCurrent() @@ -659,6 +765,20 @@ bool LayerRendererChromium::checkTextureSize(const IntSize& textureSize) return true; } +// Sets the coordinate range of content that ends being drawn onto the target render surface. +// The target render surface is assumed to have an origin at 0, 0 and the width and height of +// of the drawRect. +void LayerRendererChromium::setDrawViewportRect(const IntRect& drawRect, bool flipY) +{ + if (flipY) + m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.right(), drawRect.bottom(), drawRect.y()); + else + m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.right(), drawRect.y(), drawRect.bottom()); + GLC(m_context, m_context->viewport(0, 0, drawRect.width(), drawRect.height())); +} + + + void LayerRendererChromium::resizeOnscreenContent(const IntSize& size) { if (m_context) @@ -669,10 +789,10 @@ bool LayerRendererChromium::initializeSharedObjects() { makeContextCurrent(); - // Vertex and fragment shaders for rendering the scrolled root layer quad. - // They differ from a regular content layer shader in that they don't swizzle - // the colors or take an alpha value. - char scrollVertexShaderString[] = + // The following program composites layers whose contents are the results of a previous + // render operation and therefore doesn't perform any color swizzling. It is used + // in scrolling and for compositing offscreen textures. + char textureLayerVertexShaderString[] = "attribute vec4 a_position; \n" "attribute vec2 a_texCoord; \n" "uniform mat4 matrix; \n" @@ -682,27 +802,29 @@ bool LayerRendererChromium::initializeSharedObjects() " gl_Position = matrix * a_position; \n" " v_texCoord = a_texCoord; \n" "} \n"; - char scrollFragmentShaderString[] = + char textureLayerFragmentShaderString[] = "precision mediump float; \n" "varying vec2 v_texCoord; \n" "uniform sampler2D s_texture; \n" + "uniform float alpha; \n" "void main() \n" "{ \n" " vec4 texColor = texture2D(s_texture, v_texCoord); \n" - " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w); \n" + " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n" "} \n"; - m_scrollShaderProgram = LayerChromium::createShaderProgram(m_context.get(), scrollVertexShaderString, scrollFragmentShaderString); - if (!m_scrollShaderProgram) { + m_textureLayerShaderProgram = LayerChromium::createShaderProgram(m_context.get(), textureLayerVertexShaderString, textureLayerFragmentShaderString); + if (!m_textureLayerShaderProgram) { LOG_ERROR("LayerRendererChromium: Failed to create scroll shader program"); cleanupSharedObjects(); return false; } - GLC(m_context, m_scrollShaderSamplerLocation = m_context->getUniformLocation(m_scrollShaderProgram, "s_texture")); - GLC(m_context, m_scrollShaderMatrixLocation = m_context->getUniformLocation(m_scrollShaderProgram, "matrix")); - if (m_scrollShaderSamplerLocation == -1 || m_scrollShaderMatrixLocation == -1) { - LOG_ERROR("Failed to initialize scroll shader."); + GLC(m_context, m_textureLayerShaderSamplerLocation = m_context->getUniformLocation(m_textureLayerShaderProgram, "s_texture")); + GLC(m_context, m_textureLayerShaderMatrixLocation = m_context->getUniformLocation(m_textureLayerShaderProgram, "matrix")); + GLC(m_context, m_textureLayerShaderAlphaLocation = m_context->getUniformLocation(m_textureLayerShaderProgram, "alpha")); + if (m_textureLayerShaderSamplerLocation == -1 || m_textureLayerShaderMatrixLocation == -1 || m_textureLayerShaderAlphaLocation == -1) { + LOG_ERROR("Failed to initialize texture layer shader."); cleanupSharedObjects(); return false; } @@ -723,8 +845,8 @@ bool LayerRendererChromium::initializeSharedObjects() // Get the max texture size supported by the system. GLC(m_context, m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize)); - // Get the number of bits available in the stencil buffer. - GLC(m_context, m_context->getIntegerv(GraphicsContext3D::STENCIL_BITS, &m_numStencilBits)); + // Create an FBO for doing offscreen rendering. + GLC(m_context, m_offscreenFramebufferId = m_context->createFramebuffer()); m_layerSharedValues = adoptPtr(new LayerChromium::SharedValues(m_context.get())); m_contentLayerSharedValues = adoptPtr(new ContentLayerChromium::SharedValues(m_context.get())); @@ -751,15 +873,18 @@ void LayerRendererChromium::cleanupSharedObjects() m_videoLayerSharedValues.clear(); m_pluginLayerSharedValues.clear(); - if (m_scrollShaderProgram) { - GLC(m_context, m_context->deleteProgram(m_scrollShaderProgram)); - m_scrollShaderProgram = 0; + if (m_textureLayerShaderProgram) { + GLC(m_context, m_context->deleteProgram(m_textureLayerShaderProgram)); + m_textureLayerShaderProgram = 0; } if (m_rootLayerTextureId) { deleteLayerTexture(m_rootLayerTextureId); m_rootLayerTextureId = 0; } + + if (m_offscreenFramebufferId) + GLC(m_context, m_context->deleteFramebuffer(m_offscreenFramebufferId)); } } // namespace WebCore diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/WebCore/platform/graphics/chromium/LayerRendererChromium.h index 52fbe36..531d652 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.h +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.h @@ -39,6 +39,7 @@ #include "IntRect.h" #include "LayerChromium.h" #include "PluginLayerChromium.h" +#include "RenderSurfaceChromium.h" #include "SkBitmap.h" #include "VideoLayerChromium.h" #include <wtf/HashMap.h> @@ -94,8 +95,6 @@ public: unsigned createLayerTexture(); void deleteLayerTexture(unsigned); - IntRect currentScissorRect() const { return m_currentScissorRect; } - static void debugGLCall(GraphicsContext3D*, const char* command, const char* file, int line); const TransformationMatrix& projectionMatrix() const { return m_projectionMatrix; } @@ -118,21 +117,22 @@ public: private: explicit LayerRendererChromium(PassRefPtr<GraphicsContext3D> graphicsContext3D); + void updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, Vector<LayerChromium*>& renderSurfaceLayerList, Vector<LayerChromium*>& layerList); - void updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, float opacity); - - void drawLayersRecursive(LayerChromium*); - - void drawLayer(LayerChromium*); + void drawLayer(LayerChromium*, RenderSurfaceChromium*); bool isLayerVisible(LayerChromium*, const TransformationMatrix&, const IntRect& visibleRect); - void drawLayerIntoStencilBuffer(LayerChromium*, bool decrement); + void setScissorToRect(const IntRect&); + + void setDrawViewportRect(const IntRect&, bool flipY); - void scissorToRect(const IntRect&); + bool useRenderSurface(RenderSurfaceChromium*); bool makeContextCurrent(); + static bool compareLayerZ(const LayerChromium*, const LayerChromium*); + bool initializeSharedObjects(); void cleanupSharedObjects(); @@ -140,10 +140,12 @@ private: int m_rootLayerTextureWidth; int m_rootLayerTextureHeight; - // Scroll shader uniform locations. - unsigned m_scrollShaderProgram; - int m_scrollShaderSamplerLocation; - int m_scrollShaderMatrixLocation; + // Shader uniform locations used by layers whose contents are the results of a + // previous rendering operation. + unsigned m_textureLayerShaderProgram; + int m_textureLayerShaderSamplerLocation; + int m_textureLayerShaderMatrixLocation; + int m_textureLayerShaderAlphaLocation; TransformationMatrix m_projectionMatrix; @@ -152,7 +154,10 @@ private: IntPoint m_scrollPosition; bool m_hardwareCompositing; - unsigned int m_currentShader; + unsigned m_currentShader; + RenderSurfaceChromium* m_currentRenderSurface; + + unsigned m_offscreenFramebufferId; #if PLATFORM(SKIA) OwnPtr<skia::PlatformCanvas> m_rootLayerCanvas; @@ -168,12 +173,10 @@ private: IntRect m_rootVisibleRect; IntRect m_rootContentRect; - IntRect m_currentScissorRect; + // Maximum texture dimensions supported. int m_maxTextureSize; - int m_numStencilBits; - // Store values that are shared between instances of each layer type // associated with this instance of the compositor. Since there can be // multiple instances of the compositor running in the same renderer process @@ -185,6 +188,8 @@ private: OwnPtr<PluginLayerChromium::SharedValues> m_pluginLayerSharedValues; RefPtr<GraphicsContext3D> m_context; + + RenderSurfaceChromium* m_defaultRenderSurface; }; // Setting DEBUG_GL_CALLS to 1 will call glGetError() after almost every GL diff --git a/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp b/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp new file mode 100644 index 0000000..816fd3d --- /dev/null +++ b/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 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 "RenderSurfaceChromium.h" + +#include "GraphicsContext3D.h" +#include "LayerRendererChromium.h" + +namespace WebCore { + +RenderSurfaceChromium::RenderSurfaceChromium(LayerChromium* owningLayer) + : m_owningLayer(owningLayer) + , m_contentsTextureId(0) +{ +} + +RenderSurfaceChromium::~RenderSurfaceChromium() +{ + cleanupResources(); +} + +void RenderSurfaceChromium::cleanupResources() +{ + if (!m_contentsTextureId) + return; + + ASSERT(layerRenderer()); + + layerRenderer()->deleteLayerTexture(m_contentsTextureId); + m_contentsTextureId = 0; + m_allocatedTextureSize = IntSize(); +} + +LayerRendererChromium* RenderSurfaceChromium::layerRenderer() +{ + ASSERT(m_owningLayer); + return m_owningLayer->layerRenderer(); +} + +void RenderSurfaceChromium::prepareContentsTexture() +{ + ASSERT(m_owningLayer); + + if (!m_contentsTextureId) { + m_contentsTextureId = layerRenderer()->createLayerTexture(); + ASSERT(m_contentsTextureId); + m_allocatedTextureSize = IntSize(); + } + + IntSize requiredSize(m_contentRect.width(), m_contentRect.height()); + if (m_allocatedTextureSize != requiredSize) { + GraphicsContext3D* context = m_owningLayer->layerRenderer()->context(); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_contentsTextureId)); + GLC(context, context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, + requiredSize.width(), requiredSize.height(), 0, GraphicsContext3D::RGBA, + GraphicsContext3D::UNSIGNED_BYTE, 0)); + m_allocatedTextureSize = requiredSize; + } +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h b/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h new file mode 100644 index 0000000..1f33527 --- /dev/null +++ b/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 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 RenderSurfaceChromium_h +#define RenderSurfaceChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "FloatRect.h" +#include "IntRect.h" +#include "TransformationMatrix.h" +#include <wtf/Noncopyable.h> + +namespace WebCore { + +class LayerRendererChromium; +class LayerChromium; + +class RenderSurfaceChromium : public Noncopyable { + friend class LayerRendererChromium; +public: + explicit RenderSurfaceChromium(LayerChromium*); + ~RenderSurfaceChromium(); + + void prepareContentsTexture(); + void cleanupResources(); + + FloatPoint contentRectCenter() const { return FloatRect(m_contentRect).center(); } + IntRect contentRect() const { return m_contentRect; } + +private: + LayerRendererChromium* layerRenderer(); + + LayerChromium* m_owningLayer; + IntRect m_contentRect; + unsigned m_contentsTextureId; + float m_drawOpacity; + IntSize m_allocatedTextureSize; + TransformationMatrix m_drawTransform; + TransformationMatrix m_originTransform; + IntRect m_scissorRect; + Vector<LayerChromium*> m_layerList; +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp index f3d8b86..deebd31 100644 --- a/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp @@ -98,9 +98,6 @@ void SimpleFontData::platformCharWidthInit() void SimpleFontData::platformDestroy() { - // We don't hash this on Win32, so it's effectively owned by us. - delete m_smallCapsFontData; - m_smallCapsFontData = 0; } SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const @@ -114,7 +111,7 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes winFont.lfHeight = -lroundf(smallCapsSize); HFONT hfont = CreateFontIndirect(&winFont); m_smallCapsFontData = - new SimpleFontData(FontPlatformData(hfont, smallCapsSize)); + new SimpleFontData(FontPlatformData(hfont, smallCapsSize), isCustomFont(), false); } return m_smallCapsFontData; } diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp index d03c615..e7ff9ee 100644 --- a/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp +++ b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp @@ -127,15 +127,13 @@ void SimpleFontData::platformCharWidthInit() void SimpleFontData::platformDestroy() { - delete m_smallCapsFontData; - m_smallCapsFontData = 0; } SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_smallCapsFontData) { const float smallCapsSize = lroundf(fontDescription.computedSize() * smallCapsFraction); - m_smallCapsFontData = new SimpleFontData(FontPlatformData(m_platformData, smallCapsSize)); + m_smallCapsFontData = new SimpleFontData(FontPlatformData(m_platformData, smallCapsSize), isCustomFont(), false); } return m_smallCapsFontData; diff --git a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp index fa6c2c8..feb7ebc 100644 --- a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp @@ -188,6 +188,7 @@ VideoLayerChromium::~VideoLayerChromium() void VideoLayerChromium::cleanupResources() { + LayerChromium::cleanupResources(); releaseCurrentFrame(); if (!layerRenderer()) return; diff --git a/WebCore/platform/graphics/cocoa/FontPlatformData.h b/WebCore/platform/graphics/cocoa/FontPlatformData.h index 17ae4b5..7ab84f5 100644 --- a/WebCore/platform/graphics/cocoa/FontPlatformData.h +++ b/WebCore/platform/graphics/cocoa/FontPlatformData.h @@ -73,7 +73,7 @@ class FontPlatformData { { } - FontPlatformData(NSFont *nsFont, bool syntheticBold = false, bool syntheticOblique = false, FontOrientation = Horizontal); + FontPlatformData(NSFont *nsFont, float size, bool syntheticBold = false, bool syntheticOblique = false, FontOrientation = Horizontal); FontPlatformData(CGFontRef cgFont, ATSUFontID fontID, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation) : m_syntheticBold(syntheticBold) diff --git a/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm b/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm index dbfec5f..52a88ed 100644 --- a/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm +++ b/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm @@ -44,9 +44,10 @@ void FontPlatformData::loadFont(NSFont* nsFont, float, NSFont*& outNSFont, CGFon } #endif // PLATFORM(MAC) -FontPlatformData::FontPlatformData(NSFont *nsFont, bool syntheticBold, bool syntheticOblique, FontOrientation orientation) +FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation) : m_syntheticBold(syntheticBold) , m_syntheticOblique(syntheticOblique) + , m_size(size) , m_font(nsFont) #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) // FIXME: Chromium: The following code isn't correct for the Chromium port since the sandbox might @@ -58,28 +59,8 @@ FontPlatformData::FontPlatformData(NSFont *nsFont, bool syntheticBold, bool synt { ASSERT_ARG(nsFont, nsFont); - m_size = [nsFont pointSize]; - CGFontRef cgFont = 0; - loadFont(nsFont, m_size, m_font, cgFont, m_atsuFontID); - - if (orientation == Vertical) { - // Ignore vertical orientation when the font doesn't support vertical metrics. - // The check doesn't look neat but this is what AppKit does for vertical writing... - RetainPtr<CFArrayRef> tableTags(AdoptCF, CTFontCopyAvailableTables(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; - break; - } - } - - if (found == false) - orientation = Horizontal; - } + loadFont(nsFont, size, m_font, cgFont, m_atsuFontID); m_orientation = orientation; @@ -185,7 +166,7 @@ bool FontPlatformData::roundsGlyphAdvances() const bool FontPlatformData::allowsLigatures() const { - return m_orientation == Horizontal && ![[m_font coveredCharacterSet] characterIsMember:'a']; + return ![[m_font coveredCharacterSet] characterIsMember:'a']; } CTFontRef FontPlatformData::ctFont() const diff --git a/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp b/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp index 61ee625..61ee625 100644 --- a/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp +++ b/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp diff --git a/WebCore/platform/graphics/cairo/FontCustomPlatformData.cpp b/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp index 800907a..800907a 100644 --- a/WebCore/platform/graphics/cairo/FontCustomPlatformData.cpp +++ b/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp diff --git a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h b/WebCore/platform/graphics/freetype/FontPlatformData.h index 016489e..0793746 100644 --- a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h +++ b/WebCore/platform/graphics/freetype/FontPlatformData.h @@ -27,6 +27,7 @@ #define FontPlatformDataFreeType_h #include "FontDescription.h" +#include "FontOrientation.h" #include "GlyphBuffer.h" #include "HashFunctions.h" #include "RefPtrCairo.h" @@ -68,6 +69,8 @@ public: 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 diff --git a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp b/WebCore/platform/graphics/freetype/FontPlatformDataFreeType.cpp index 394082d..394082d 100644 --- a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp +++ b/WebCore/platform/graphics/freetype/FontPlatformDataFreeType.cpp diff --git a/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp b/WebCore/platform/graphics/freetype/GlyphPageTreeNodeFreeType.cpp index e2f09f4..e2f09f4 100644 --- a/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp +++ b/WebCore/platform/graphics/freetype/GlyphPageTreeNodeFreeType.cpp diff --git a/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp b/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp index d350294..cb096c3 100644 --- a/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp +++ b/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp @@ -77,8 +77,6 @@ void SimpleFontData::platformCharWidthInit() void SimpleFontData::platformDestroy() { - delete m_smallCapsFontData; - m_smallCapsFontData = 0; } SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const @@ -87,7 +85,8 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes if (!m_smallCapsFontData) m_smallCapsFontData = new SimpleFontData( FontPlatformData(cairo_scaled_font_get_font_face(m_platformData.scaledFont()), - 0.70f * fontDescription.computedSize(), m_platformData.syntheticBold(), m_platformData.syntheticOblique())); + 0.70f * fontDescription.computedSize(), m_platformData.syntheticBold(), m_platformData.syntheticOblique()), + isCustomFont(), false); return m_smallCapsFontData; } diff --git a/WebCore/platform/graphics/gpu/DrawingBuffer.cpp b/WebCore/platform/graphics/gpu/DrawingBuffer.cpp index 2dc0517..d812e28 100644 --- a/WebCore/platform/graphics/gpu/DrawingBuffer.cpp +++ b/WebCore/platform/graphics/gpu/DrawingBuffer.cpp @@ -34,11 +34,14 @@ #include "DrawingBuffer.h" +#include "Extensions3D.h" + namespace WebCore { PassRefPtr<DrawingBuffer> DrawingBuffer::create(GraphicsContext3D* context, const IntSize& size) { RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(context, size)); + drawingBuffer->m_multisampleExtensionSupported = context->getExtensions()->supports("GL_ANGLE_framebuffer_blit") && context->getExtensions()->supports("GL_ANGLE_framebuffer_multisample"); return (drawingBuffer->m_context) ? drawingBuffer.release() : 0; } @@ -46,21 +49,193 @@ void DrawingBuffer::clear() { if (!m_context) return; - + m_context->makeContextCurrent(); + m_context->deleteTexture(m_colorBuffer); + m_colorBuffer = 0; + + if (m_multisampleColorBuffer) { + m_context->deleteRenderbuffer(m_multisampleColorBuffer); + m_multisampleColorBuffer = 0; + } + + if (m_multisampleDepthStencilBuffer) { + m_context->deleteRenderbuffer(m_multisampleDepthStencilBuffer); + m_multisampleDepthStencilBuffer = 0; + } + + if (m_depthStencilBuffer) { + m_context->deleteRenderbuffer(m_depthStencilBuffer); + m_depthStencilBuffer = 0; + } + + if (m_multisampleFBO) { + m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); + m_context->deleteFramebuffer(m_multisampleFBO); + m_multisampleFBO = 0; + } + m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); m_context->deleteFramebuffer(m_fbo); m_fbo = 0; - + m_context.clear(); } -void DrawingBuffer::bind() +void DrawingBuffer::reset(const IntSize& newSize) { + if (m_size == newSize) + return; + m_size = newSize; + if (!m_context) return; + m_context->makeContextCurrent(); + + const GraphicsContext3D::Attributes& attributes = m_context->getContextAttributes(); + unsigned long internalColorFormat, colorFormat, internalDepthStencilFormat = 0; + if (attributes.alpha) { + internalColorFormat = GraphicsContext3D::RGBA; + colorFormat = GraphicsContext3D::RGBA; + } else { + internalColorFormat = GraphicsContext3D::RGB; + colorFormat = GraphicsContext3D::RGB; + } + if (attributes.stencil || attributes.depth) { + // We don't allow the logic where stencil is required and depth is not. + // See GraphicsContext3D constructor. + if (attributes.stencil && attributes.depth) + internalDepthStencilFormat = GraphicsContext3D::DEPTH_STENCIL; + else + internalDepthStencilFormat = GraphicsContext3D::DEPTH_COMPONENT; + } + + // resize multisample FBO + if (multisample()) { + int maxSampleCount; + + m_context->getIntegerv(Extensions3D::MAX_SAMPLES, &maxSampleCount); + int sampleCount = std::min(8, maxSampleCount); + if (sampleCount > maxSampleCount) + sampleCount = maxSampleCount; + + m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); + + m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); + m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, internalColorFormat, m_size.width(), m_size.height()); + m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); + if (attributes.stencil || attributes.depth) { + m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleDepthStencilBuffer); + m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, internalDepthStencilFormat, m_size.width(), m_size.height()); + if (attributes.stencil) + m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_multisampleDepthStencilBuffer); + if (attributes.depth) + m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_multisampleDepthStencilBuffer); + } + m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0); + if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { + // Cleanup + clear(); + return; + } + } + + // resize regular FBO m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); + + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_colorBuffer); + m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE, 0); + m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE, m_colorBuffer, 0); + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); + if (!multisample() && (attributes.stencil || attributes.depth)) { + m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer); + m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, internalDepthStencilFormat, m_size.width(), m_size.height()); + if (attributes.stencil) + m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer); + if (attributes.depth) + m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer); + m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0); + } + if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { + // Cleanup + clear(); + return; + } + + if (multisample()) + m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); + + // Initialize renderbuffers to 0. + unsigned char colorMask[] = {true, true, true, true}, depthMask = true, stencilMask = true; + unsigned char isScissorEnabled = false; + unsigned char isDitherEnabled = false; + unsigned long clearMask = GraphicsContext3D::COLOR_BUFFER_BIT; + m_context->getBooleanv(GraphicsContext3D::COLOR_WRITEMASK, colorMask); + m_context->colorMask(true, true, true, true); + if (attributes.depth) { + m_context->getBooleanv(GraphicsContext3D::DEPTH_WRITEMASK, &depthMask); + m_context->depthMask(true); + clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT; + } + if (attributes.stencil) { + m_context->getBooleanv(GraphicsContext3D::STENCIL_WRITEMASK, &stencilMask); + m_context->stencilMask(true); + clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT; + } + isScissorEnabled = m_context->isEnabled(GraphicsContext3D::SCISSOR_TEST); + m_context->disable(GraphicsContext3D::SCISSOR_TEST); + isDitherEnabled = m_context->isEnabled(GraphicsContext3D::DITHER); + m_context->disable(GraphicsContext3D::DITHER); + + m_context->clear(clearMask); + + m_context->colorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]); + if (attributes.depth) + m_context->depthMask(depthMask); + if (attributes.stencil) + m_context->stencilMask(stencilMask); + if (isScissorEnabled) + m_context->enable(GraphicsContext3D::SCISSOR_TEST); + else + m_context->disable(GraphicsContext3D::SCISSOR_TEST); + if (isDitherEnabled) + m_context->enable(GraphicsContext3D::DITHER); + else + m_context->disable(GraphicsContext3D::DITHER); + + m_context->flush(); + + didReset(); +} + +void DrawingBuffer::commit(long x, long y, long width, long height) +{ + if (!m_context) + return; + + if (width < 0) + width = m_size.width(); + if (height < 0) + height = m_size.height(); + + m_context->makeContextCurrent(); + + if (m_multisampleFBO) { + m_context->bindFramebuffer(Extensions3D::READ_FRAMEBUFFER, m_multisampleFBO); + m_context->bindFramebuffer(Extensions3D::DRAW_FRAMEBUFFER, m_fbo); + m_context->getExtensions()->blitFramebuffer(x, y, width, height, x, y, width, height, GraphicsContext3D::COLOR_BUFFER_BIT, GraphicsContext3D::LINEAR); + } + + m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); +} + +void DrawingBuffer::bind() +{ + if (!m_context) + return; + + m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO ? m_multisampleFBO : m_fbo); m_context->viewport(0, 0, m_size.width(), m_size.height()); } diff --git a/WebCore/platform/graphics/gpu/DrawingBuffer.h b/WebCore/platform/graphics/gpu/DrawingBuffer.h index 75c7f99..9f79889 100644 --- a/WebCore/platform/graphics/gpu/DrawingBuffer.h +++ b/WebCore/platform/graphics/gpu/DrawingBuffer.h @@ -64,13 +64,18 @@ public: // to prevent invalid accesses to the resources. void clear(); + // Copies the multisample color buffer to the normal color buffer and leaves m_fbo bound + void commit(long x = 0, long y = 0, long width = -1, long height = -1); + + bool multisample() const { return m_context && m_context->getContextAttributes().antialias && m_multisampleExtensionSupported; } + + Platform3DObject platformColorBuffer() const; + #if USE(ACCELERATED_COMPOSITING) PlatformLayer* platformLayer(); void publishToPlatformLayer(); #endif - unsigned getRenderingResultsAsTexture(); - #if PLATFORM(CHROMIUM) class WillPublishCallback : public Noncopyable { public: @@ -88,11 +93,22 @@ private: static PassRefPtr<DrawingBuffer> create(GraphicsContext3D*, const IntSize&); DrawingBuffer(GraphicsContext3D*, const IntSize&); + + // Platform specific function called after reset() so each platform can do extra work if needed + void didReset(); RefPtr<GraphicsContext3D> m_context; IntSize m_size; + bool m_multisampleExtensionSupported; Platform3DObject m_fbo; + Platform3DObject m_colorBuffer; + Platform3DObject m_depthStencilBuffer; + // For multisampling + Platform3DObject m_multisampleFBO; + Platform3DObject m_multisampleColorBuffer; + Platform3DObject m_multisampleDepthStencilBuffer; + #if PLATFORM(CHROMIUM) OwnPtr<WillPublishCallback> m_callback; OwnPtr<DrawingBufferInternal> m_internal; diff --git a/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm b/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm index 7a8c501..89dcb9c 100644 --- a/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm +++ b/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm @@ -29,6 +29,7 @@ #include "DrawingBuffer.h" +#include "Extensions3D.h" #include "WebGLLayer.h" #import "BlockExceptions.h" @@ -39,6 +40,11 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context, const IntSize& size) : m_context(context) , m_size(size) , m_fbo(context->createFramebuffer()) + , m_colorBuffer(0) + , m_depthStencilBuffer(0) + , m_multisampleFBO(0) + , m_multisampleColorBuffer(0) + , m_multisampleDepthStencilBuffer(0) { ASSERT(m_fbo); if (!m_fbo) { @@ -53,6 +59,40 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context, const IntSize& size) [m_platformLayer.get() setName:@"DrawingBuffer Layer"]; #endif END_BLOCK_OBJC_EXCEPTIONS + + // create a texture to render into + m_colorBuffer = context->createTexture(); + context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_colorBuffer); + context->texParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); + context->texParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); + context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); + context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); + context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); + + // Create the FBO + m_fbo = context->createFramebuffer(); + ASSERT(m_fbo); + if (!m_fbo) { + clear(); + return; + } + + const GraphicsContext3D::Attributes& attributes = context->getContextAttributes(); + + // Create the stencil and depth buffer if needed + if (!multisample() && (attributes.stencil || attributes.depth)) + m_depthStencilBuffer = context->createRenderbuffer(); + + // create a multisample FBO + if (multisample()) { + m_multisampleFBO = context->createFramebuffer(); + context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); + m_multisampleColorBuffer = context->createRenderbuffer(); + if (attributes.stencil || attributes.depth) + m_multisampleDepthStencilBuffer = context->createRenderbuffer(); + } + + reset(size); } DrawingBuffer::~DrawingBuffer() @@ -60,24 +100,19 @@ DrawingBuffer::~DrawingBuffer() clear(); } -void DrawingBuffer::reset(const IntSize& newSize) +void DrawingBuffer::didReset() { - if (!m_context) - return; - - if (m_size == newSize) - return; - m_size = newSize; - - m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_size.width(), m_size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0); } -#if USE(ACCELERATED_COMPOSITING) PlatformLayer* DrawingBuffer::platformLayer() { return m_platformLayer.get(); } -#endif + +Platform3DObject DrawingBuffer::platformColorBuffer() const +{ + return m_colorBuffer; +} } diff --git a/WebCore/platform/graphics/gstreamer/ImageGStreamer.h b/WebCore/platform/graphics/gstreamer/ImageGStreamer.h index cf2b9d6..6e53cfc 100644 --- a/WebCore/platform/graphics/gstreamer/ImageGStreamer.h +++ b/WebCore/platform/graphics/gstreamer/ImageGStreamer.h @@ -52,6 +52,10 @@ class ImageGStreamer : public RefCounted<ImageGStreamer> { ImageGStreamer(GstBuffer*&, IntSize, cairo_format_t&); #endif +#if PLATFORM(QT) + ImageGStreamer(GstBuffer*&, IntSize, QImage::Format); +#endif + #if PLATFORM(MAC) ImageGStreamer(GstBuffer*&, IntSize); #endif diff --git a/WebCore/platform/graphics/gstreamer/ImageGStreamerQt.cpp b/WebCore/platform/graphics/gstreamer/ImageGStreamerQt.cpp new file mode 100644 index 0000000..cf46f02 --- /dev/null +++ b/WebCore/platform/graphics/gstreamer/ImageGStreamerQt.cpp @@ -0,0 +1,67 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "ImageGStreamer.h" + +#if USE(GSTREAMER) +#include "GOwnPtr.h" + +using namespace std; +using namespace WebCore; + +PassRefPtr<ImageGStreamer> ImageGStreamer::createImage(GstBuffer* buffer) +{ + int width = 0, height = 0; + GstCaps* caps = gst_buffer_get_caps(buffer); + GstVideoFormat format; + if (!gst_video_format_parse_caps(caps, &format, &width, &height)) { + gst_caps_unref(caps); + return 0; + } + + gst_caps_unref(caps); + + QImage::Format imageFormat; + if (format == GST_VIDEO_FORMAT_RGB) + imageFormat = QImage::Format_RGB888; + else + imageFormat = QImage::Format_RGB32; + + return adoptRef(new ImageGStreamer(buffer, IntSize(width, height), imageFormat)); +} + +ImageGStreamer::ImageGStreamer(GstBuffer*& buffer, IntSize size, QImage::Format imageFormat) + : m_image(0) +{ + QPixmap* surface = new QPixmap; + QImage image(GST_BUFFER_DATA(buffer), size.width(), size.height(), imageFormat); + surface->convertFromImage(image); + m_image = BitmapImage::create(surface); +} + +ImageGStreamer::~ImageGStreamer() +{ + if (m_image) + m_image.clear(); + + m_image = 0; +} +#endif // USE(GSTREAMER) + diff --git a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowPrivate.h b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowPrivate.h new file mode 100644 index 0000000..0ae4587 --- /dev/null +++ b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowPrivate.h @@ -0,0 +1,44 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef PlatformVideoWindowPrivate_h +#define PlatformVideoWindowPrivate_h + +#include <QWidget> + +class QKeyEvent; + +namespace WebCore { + +class FullScreenVideoWindow: public QWidget { +Q_OBJECT +public: + FullScreenVideoWindow(); +signals: + void closed(); +protected: + void keyPressEvent(QKeyEvent* ev); + bool event(QEvent* ev); +}; + + +} // namespace WebCore + + +#endif // PlatformVideoWindowPrivate_h diff --git a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowQt.cpp b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowQt.cpp new file mode 100644 index 0000000..872d055 --- /dev/null +++ b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowQt.cpp @@ -0,0 +1,82 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "PlatformVideoWindow.h" + +#include "PlatformVideoWindowPrivate.h" + +#include <QApplication> +#include <QDesktopWidget> +#include <QKeyEvent> +#include <QPalette> +using namespace WebCore; + +FullScreenVideoWindow::FullScreenVideoWindow() + : QWidget(0, Qt::Window) +{ + setAttribute(Qt::WA_NativeWindow); + // Setting these values ensures smooth resizing since it + // will prevent the system from clearing the background. + setAttribute(Qt::WA_NoSystemBackground, true); + setAttribute(Qt::WA_PaintOnScreen, true); +} + +void FullScreenVideoWindow::keyPressEvent(QKeyEvent* ev) +{ + if (ev->key() == Qt::Key_Escape) { + close(); + emit closed(); + } +} + +bool FullScreenVideoWindow::event(QEvent* ev) +{ + switch (ev->type()) { + case QEvent::MouseButtonDblClick: + close(); + ev->accept(); + return true; + default: + return QWidget::event(ev); + } +} + + +PlatformVideoWindow::PlatformVideoWindow() +{ + m_window = new FullScreenVideoWindow(); + m_window->setWindowFlags(m_window->windowFlags() | Qt::FramelessWindowHint); + QPalette p; + p.setColor(QPalette::Base, Qt::black); + p.setColor(QPalette::Window, Qt::black); + m_window->setPalette(p); + m_window->showFullScreen(); + m_videoWindowId = m_window->winId(); +} + +PlatformVideoWindow::~PlatformVideoWindow() +{ + delete m_window; + m_videoWindowId = 0; +} + +void PlatformVideoWindow::prepareForOverlay(GstMessage*) +{ +} diff --git a/WebCore/platform/graphics/gtk/FontGtk.cpp b/WebCore/platform/graphics/gtk/FontGtk.cpp index 328ec4a..54e18c9 100644 --- a/WebCore/platform/graphics/gtk/FontGtk.cpp +++ b/WebCore/platform/graphics/gtk/FontGtk.cpp @@ -33,19 +33,51 @@ #include "config.h" #include "Font.h" +#include "CairoUtilities.h" +#include "ContextShadow.h" #include "GraphicsContext.h" #include "SimpleFontData.h" - #include <cairo.h> #include <gdk/gdk.h> #include <pango/pango.h> #include <pango/pangocairo.h> + #if defined(USE_FREETYPE) #include <pango/pangofc-fontmap.h> #endif namespace WebCore { +#ifdef GTK_API_VERSION_2 +typedef GdkRegion* PangoRegionType; + +void destroyPangoRegion(PangoRegionType region) +{ + gdk_region_destroy(region); +} + +IntRect getPangoRegionExtents(PangoRegionType region) +{ + GdkRectangle rectangle; + gdk_region_get_clipbox(region, &rectangle); + return IntRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height); +} +#else +typedef cairo_region_t* PangoRegionType; + +void destroyPangoRegion(PangoRegionType region) +{ + cairo_region_destroy(region); +} + +IntRect getPangoRegionExtents(PangoRegionType region) +{ + cairo_rectangle_int_t rectangle; + cairo_region_get_extents(region, &rectangle); + return IntRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height); +} +#endif + #define IS_HIGH_SURROGATE(u) ((UChar)(u) >= (UChar)0xd800 && (UChar)(u) <= (UChar)0xdbff) #define IS_LOW_SURROGATE(u) ((UChar)(u) >= (UChar)0xdc00 && (UChar)(u) <= (UChar)0xdfff) @@ -181,6 +213,52 @@ bool Font::canReturnFallbackFontsForComplexText() return false; } +static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context, const FloatPoint& point, PangoLayoutLine* layoutLine, PangoRegionType renderRegion) +{ + ContextShadow* shadow = graphicsContext->contextShadow(); + ASSERT(shadow); + + if (!(graphicsContext->textDrawingMode() & cTextFill) || shadow->m_type == ContextShadow::NoShadow) + return; + + FloatPoint totalOffset(point + shadow->m_offset); + + // Optimize non-blurry shadows, by just drawing text without the ContextShadow. + if (shadow->m_type == ContextShadow::SolidShadow) { + cairo_save(context); + cairo_translate(context, totalOffset.x(), totalOffset.y()); + + setSourceRGBAFromColor(context, shadow->m_color); + gdk_cairo_region(context, renderRegion); + cairo_clip(context); + pango_cairo_show_layout_line(context, layoutLine); + + cairo_restore(context); + return; + } + + FloatRect extents(getPangoRegionExtents(renderRegion)); + extents.setLocation(FloatPoint(point.x(), point.y() - extents.height())); + cairo_t* shadowContext = shadow->beginShadowLayer(context, extents); + if (shadowContext) { + cairo_translate(shadowContext, point.x(), point.y()); + pango_cairo_show_layout_line(shadowContext, layoutLine); + + // We need the clipping region to be active when we blit the blurred shadow back, + // 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_save(context); + cairo_translate(context, totalOffset.x(), totalOffset.y()); + gdk_cairo_region(context, renderRegion); + cairo_clip(context); + cairo_translate(context, -totalOffset.x(), -totalOffset.y()); + + shadow->endShadowLayer(context); + cairo_restore(context); + } +} + void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const { #if defined(USE_FREETYPE) @@ -191,9 +269,6 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F #endif cairo_t* cr = context->platformContext(); - cairo_save(cr); - cairo_translate(cr, point.x(), point.y()); - PangoLayout* layout = pango_cairo_create_layout(cr); setPangoAttributes(this, run, layout); @@ -203,59 +278,25 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F // Our layouts are single line PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0); -#ifdef GTK_API_VERSION_2 - GdkRegion* partialRegion = 0; -#else - cairo_region_t* partialRegion = 0; -#endif - - if (to - from != run.length()) { - // Clip the region of the run to be rendered - char* start = g_utf8_offset_to_pointer(utf8, from); - char* end = g_utf8_offset_to_pointer(start, to - from); - int ranges[] = {start - utf8, end - utf8}; - partialRegion = gdk_pango_layout_line_get_clip_region(layoutLine, 0, 0, ranges, 1); - } - - Color fillColor = context->fillColor(); - float red, green, blue, alpha; - - // Text shadow, inspired by FontMac - FloatSize shadowOffset; - float shadowBlur = 0; - Color shadowColor; - bool hasShadow = context->textDrawingMode() == cTextFill && - context->getShadow(shadowOffset, shadowBlur, shadowColor); - - // TODO: Blur support - if (hasShadow) { - // Disable graphics context shadows (not yet implemented) and paint them manually - context->clearShadow(); - Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255); - cairo_save(cr); - - shadowFillColor.getRGBA(red, green, blue, alpha); - cairo_set_source_rgba(cr, red, green, blue, alpha); - - cairo_translate(cr, shadowOffset.width(), shadowOffset.height()); - - if (partialRegion) { - gdk_cairo_region(cr, partialRegion); - cairo_clip(cr); - } + // Get the region where this text will be laid out. We will use it to clip + // the Cairo context, for when we are only painting part of the text run and + // to calculate the size of the shadow buffer. + PangoRegionType partialRegion = 0; + char* start = g_utf8_offset_to_pointer(utf8, from); + char* end = g_utf8_offset_to_pointer(start, to - from); + int ranges[] = {start - utf8, end - utf8}; + partialRegion = gdk_pango_layout_line_get_clip_region(layoutLine, 0, 0, ranges, 1); - pango_cairo_show_layout_line(cr, layoutLine); + drawGlyphsShadow(context, cr, point, layoutLine, partialRegion); - cairo_restore(cr); - } + cairo_save(cr); + cairo_translate(cr, point.x(), point.y()); - fillColor.getRGBA(red, green, blue, alpha); + float red, green, blue, alpha; + context->fillColor().getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha); - - if (partialRegion) { - gdk_cairo_region(cr, partialRegion); - cairo_clip(cr); - } + gdk_cairo_region(cr, partialRegion); + cairo_clip(cr); pango_cairo_show_layout_line(cr, layoutLine); @@ -268,20 +309,10 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F cairo_stroke(cr); } - // Re-enable the platform shadow we disabled earlier - if (hasShadow) - context->setShadow(shadowOffset, shadowBlur, shadowColor, ColorSpaceDeviceRGB); - // Pango sometimes leaves behind paths we don't want cairo_new_path(cr); - if (partialRegion) -#ifdef GTK_API_VERSION_2 - gdk_region_destroy(partialRegion); -#else - cairo_region_destroy(partialRegion); -#endif - + destroyPangoRegion(partialRegion); g_free(utf8); g_object_unref(layout); diff --git a/WebCore/platform/graphics/gtk/GdkCairoUtilities.cpp b/WebCore/platform/graphics/gtk/GdkCairoUtilities.cpp index d768ce2..d8018a3 100644 --- a/WebCore/platform/graphics/gtk/GdkCairoUtilities.cpp +++ b/WebCore/platform/graphics/gtk/GdkCairoUtilities.cpp @@ -25,70 +25,15 @@ #include "config.h" #include "GdkCairoUtilities.h" +#include "GtkVersioning.h" #include <cairo.h> #include <gtk/gtk.h> -static inline unsigned char* getCairoSurfacePixel(unsigned char* data, unsigned x, unsigned y, unsigned rowStride) -{ - return data + (y * rowStride) + x * 4; -} - -static inline guchar* getGdkPixbufPixel(guchar* data, unsigned x, unsigned y, unsigned rowStride) -{ - return data + (y * rowStride) + x * 4; -} - GdkPixbuf* cairoImageSurfaceToGdkPixbuf(cairo_surface_t* surface) { - int width = cairo_image_surface_get_width(surface); - int height = cairo_image_surface_get_height(surface); - unsigned char* surfaceData = cairo_image_surface_get_data(surface); - int surfaceRowStride = cairo_image_surface_get_stride(surface); - - GdkPixbuf* dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height); - if (!dest) - return 0; - - guchar* pixbufData = gdk_pixbuf_get_pixels(dest); - int pixbufRowStride = gdk_pixbuf_get_rowstride(dest); - - /* From: http://cairographics.org/manual/cairo-image-surface.html#cairo-format-t - * "CAIRO_FORMAT_ARGB32: each pixel is a 32-bit quantity, with alpha in - * the upper 8 bits, then red, then green, then blue. The 32-bit - * quantities are stored native-endian. Pre-multiplied alpha is used. - * (That is, 50% transparent red is 0x80800000, not 0x80ff0000.)" - * - * See http://developer.gimp.org/api/2.0/gdk-pixbuf/gdk-pixbuf-gdk-pixbuf.html#GdkPixbuf - * for information on the structure of GdkPixbufs stored with GDK_COLORSPACE_RGB. - * - * RGB color channels in CAIRO_FORMAT_ARGB32 are stored based on the - * endianness of the machine and are also multiplied by the alpha channel. - * To properly transfer the data from the Cairo surface we must divide each - * of the RGB channels by the alpha channel and then reorder all channels - * if this machine is little-endian. - */ - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - unsigned char* source = getCairoSurfacePixel(surfaceData, x, y, surfaceRowStride); - guchar* dest = getGdkPixbufPixel(pixbufData, x, y, pixbufRowStride); - -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - guchar alpha = source[3]; - dest[0] = alpha ? ((source[2] * 255) / alpha) : 0; - dest[1] = alpha ? ((source[1] * 255) / alpha) : 0; - dest[2] = alpha ? ((source[0] * 255) / alpha) : 0; - dest[3] = alpha; -#else - guchar alpha = source[0]; - dest[0] = alpha ? ((source[1] * 255) / alpha) : 0; - dest[1] = alpha ? ((source[2] * 255) / alpha) : 0; - dest[2] = alpha ? ((source[3] * 255) / alpha) : 0; - dest[3] = alpha; -#endif - } - } - - return dest; + return gdk_pixbuf_get_from_surface(surface, 0, 0, + cairo_image_surface_get_width(surface), + cairo_image_surface_get_height(surface)); } diff --git a/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp b/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp index 96027cc..a960972 100644 --- a/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp +++ b/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp @@ -64,8 +64,6 @@ void SimpleFontData::platformCharWidthInit() void SimpleFontData::platformDestroy() { - delete m_smallCapsFontData; - m_smallCapsFontData = 0; } SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const @@ -74,7 +72,7 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes FontDescription desc = FontDescription(fontDescription); desc.setSpecifiedSize(0.70f * fontDescription.computedSize()); FontPlatformData fontPlatformData(desc, desc.family().family()); - m_smallCapsFontData = new SimpleFontData(fontPlatformData); + m_smallCapsFontData = new SimpleFontData(fontPlatformData, isCustomFont(), false); } return m_smallCapsFontData; } diff --git a/WebCore/platform/graphics/mac/ComplexTextController.cpp b/WebCore/platform/graphics/mac/ComplexTextController.cpp index a2733f8..e6a7bef 100644 --- a/WebCore/platform/graphics/mac/ComplexTextController.cpp +++ b/WebCore/platform/graphics/mac/ComplexTextController.cpp @@ -487,7 +487,7 @@ void ComplexTextController::adjustGlyphsAndAdvances() advance.width += m_font.letterSpacing(); // Handle justification and word-spacing. - if (glyph == fontData->spaceGlyph()) { + if (treatAsSpace) { // Account for padding. WebCore uses space padding to justify text. // We distribute the specified padding over the available spaces in the run. if (m_padding) { @@ -503,7 +503,7 @@ void ComplexTextController::adjustGlyphsAndAdvances() } // Account for word-spacing. - if (treatAsSpace && characterIndex > 0 && !Font::treatAsSpace(*m_run.data(characterIndex - 1)) && m_font.wordSpacing()) + if (characterIndex > 0 && !Font::treatAsSpace(*m_run.data(characterIndex - 1)) && m_font.wordSpacing()) advance.width += m_font.wordSpacing(); } } diff --git a/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp b/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp index 1656854..7ff316c 100644 --- a/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp +++ b/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp @@ -262,7 +262,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->platformData().allowsLigatures()) + if ((typesettingFeatures & Ligatures) || (fontData->orientation() == Horizontal && fontData->platformData().allowsLigatures())) return; ATSUFontFeatureType featureTypes[] = { kLigaturesType }; diff --git a/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp b/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp index 744e6d4..cbb7610 100644 --- a/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp +++ b/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp @@ -24,6 +24,7 @@ #include "config.h" #include "ComplexTextController.h" +#include "WebCoreSystemInterface.h" #if USE(CORE_TEXT) @@ -101,6 +102,23 @@ void ComplexTextController::ComplexTextRun::createTextRunFromFontDataCoreText(bo m_advances = m_advancesVector.data(); } +struct ProviderInfo { + const UChar* cp; + unsigned length; + CFDictionaryRef attributes; +}; + +static const UniChar* provideStringAndAttributes(CFIndex stringIndex, CFIndex* charCount, CFDictionaryRef* attributes, void* refCon) +{ + ProviderInfo* info = static_cast<struct ProviderInfo*>(refCon); + if (stringIndex < 0 || static_cast<unsigned>(stringIndex) >= info->length) + return 0; + + *charCount = info->length - stringIndex; + *attributes = info->attributes; + return info->cp + stringIndex; +} + void ComplexTextController::collectComplexTextRunsForCharactersCoreText(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData) { if (!fontData) { @@ -112,10 +130,6 @@ void ComplexTextController::collectComplexTextRunsForCharactersCoreText(const UC if (m_fallbackFonts && fontData != m_font.primaryFont()) m_fallbackFonts->add(fontData); - RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(NULL, cp, length, kCFAllocatorNull)); - - RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(NULL, string.get(), fontData->getCFStringAttributes(m_font.typesettingFeatures()))); - RetainPtr<CTLineRef> line; if (!m_mayUseNaturalWritingDirection || m_run.directionalOverride()) { @@ -126,11 +140,22 @@ void ComplexTextController::collectComplexTextRunsForCharactersCoreText(const UC static const void* rtlOptionValues[] = { CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &rtlForcedEmbeddingLevelValue) }; static CFDictionaryRef ltrTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, ltrOptionValues, sizeof(optionKeys) / sizeof(*optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); static CFDictionaryRef rtlTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, rtlOptionValues, sizeof(optionKeys) / sizeof(*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()) }; + 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<CTTypesetterRef> typesetter(AdoptCF, CTTypesetterCreateWithAttributedStringAndOptions(attributedString.get(), m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions)); +#endif line.adoptCF(CTTypesetterCreateLine(typesetter.get(), CFRangeMake(0, 0))); - } else - line.adoptCF(CTLineCreateWithAttributedString(attributedString.get())); + } else { + ProviderInfo info = { cp, length, fontData->getCFStringAttributes(m_font.typesettingFeatures()) }; + + line.adoptCF(wkCreateCTLineWithUniCharProvider(&provideStringAndAttributes, 0, &info)); + } CFArrayRef runArray = CTLineGetGlyphRuns(line.get()); diff --git a/WebCore/platform/graphics/mac/FontCacheMac.mm b/WebCore/platform/graphics/mac/FontCacheMac.mm index 313db1c..068bd8e 100644 --- a/WebCore/platform/graphics/mac/FontCacheMac.mm +++ b/WebCore/platform/graphics/mac/FontCacheMac.mm @@ -140,7 +140,7 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons NSFontTraitMask substituteFontTraits = [fontManager traitsOfFont:substituteFont]; NSInteger substituteFontWeight = [fontManager weightOfFont:substituteFont]; - FontPlatformData alternateFont(substituteFont, + FontPlatformData alternateFont(substituteFont, platformData.size(), !font.isPlatformFont() && isAppKitFontWeightBold(weight) && !isAppKitFontWeightBold(substituteFontWeight), !font.isPlatformFont() && (traits & NSFontItalicTrait) && !(substituteFontTraits & NSFontItalicTrait), platformData.m_orientation); @@ -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, syntheticBold, syntheticOblique, fontDescription.orientation()); + return new FontPlatformData(platformFont, size, syntheticBold, syntheticOblique, fontDescription.orientation()); } } // namespace WebCore diff --git a/WebCore/platform/graphics/mac/FontMac.mm b/WebCore/platform/graphics/mac/FontMac.mm index d760f5a..8dc741b 100644 --- a/WebCore/platform/graphics/mac/FontMac.mm +++ b/WebCore/platform/graphics/mac/FontMac.mm @@ -52,7 +52,7 @@ static void showGlyphsWithAdvances(const SimpleFontData* font, CGContextRef cont const FontPlatformData& platformData = font->platformData(); if (!platformData.isColorBitmapFont()) { CGAffineTransform savedMatrix; - bool isVertical = platformData.orientation() == Vertical; + bool isVertical = font->orientation() == Vertical; if (isVertical) { CGAffineTransform rotateLeftTransform = CGAffineTransformMake(0, -1, 1, 0, 0, 0); diff --git a/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp b/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp index 48ad1c0..9524cd2 100644 --- a/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp +++ b/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp @@ -40,7 +40,7 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b bool haveGlyphs = false; #ifndef BUILDING_ON_TIGER - if (fontData->platformData().orientation() == Horizontal) { + if (fontData->orientation() == Horizontal || fontData->isBrokenIdeographFont()) { Vector<CGGlyph, 512> glyphs(bufferLength); wkGetGlyphsForCharacters(fontData->platformData().cgFont(), buffer, glyphs.data(), bufferLength); for (unsigned i = 0; i < length; ++i) { diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm index ab6993f..321d0ef 100644 --- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm +++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm @@ -251,17 +251,6 @@ bool GraphicsContext3D::isGLES2Compliant() const return false; } -bool GraphicsContext3D::isGLES2NPOTStrict() const -{ - return false; -} - -bool GraphicsContext3D::isErrorGeneratedOnOutOfBoundsAccesses() const -{ - return false; -} - - } #endif // ENABLE(3D_CANVAS) diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.h b/WebCore/platform/graphics/mac/GraphicsLayerMac.h index 17a67ac..5d4dfe2 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.h +++ b/WebCore/platform/graphics/mac/GraphicsLayerMac.h @@ -23,8 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GraphicsLayerCA_h -#define GraphicsLayerCA_h +#ifndef GraphicsLayerMac_h +#define GraphicsLayerMac_h #if USE(ACCELERATED_COMPOSITING) @@ -43,11 +43,11 @@ namespace WebCore { -class GraphicsLayerCA : public GraphicsLayer { +class GraphicsLayerMac : public GraphicsLayer { public: - GraphicsLayerCA(GraphicsLayerClient*); - virtual ~GraphicsLayerCA(); + GraphicsLayerMac(GraphicsLayerClient*); + virtual ~GraphicsLayerMac(); virtual void setName(const String&); @@ -385,4 +385,4 @@ private: #endif // USE(ACCELERATED_COMPOSITING) -#endif // GraphicsLayerCA_h +#endif // GraphicsLayerMac_h diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerMac.mm index c4128ef..f9b16a0 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm +++ b/WebCore/platform/graphics/mac/GraphicsLayerMac.mm @@ -27,7 +27,7 @@ #if USE(ACCELERATED_COMPOSITING) -#import "GraphicsLayerCA.h" +#import "GraphicsLayerMac.h" #import "Animation.h" #import "BlockExceptions.h" @@ -90,12 +90,12 @@ static double mediaTimeToCurrentTime(CFTimeInterval t) @end @interface WebAnimationDelegate : NSObject { - WebCore::GraphicsLayerCA* m_graphicsLayer; + WebCore::GraphicsLayerMac* m_graphicsLayer; } - (void)animationDidStart:(CAAnimation *)anim; -- (WebCore::GraphicsLayerCA*)graphicsLayer; -- (void)setLayer:(WebCore::GraphicsLayerCA*)graphicsLayer; +- (WebCore::GraphicsLayerMac*)graphicsLayer; +- (void)setLayer:(WebCore::GraphicsLayerMac*)graphicsLayer; @end @@ -107,12 +107,12 @@ static double mediaTimeToCurrentTime(CFTimeInterval t) m_graphicsLayer->animationDidStart(animation); } -- (WebCore::GraphicsLayerCA*)graphicsLayer +- (WebCore::GraphicsLayerMac*)graphicsLayer { return m_graphicsLayer; } -- (void)setLayer:(WebCore::GraphicsLayerCA*)graphicsLayer +- (void)setLayer:(WebCore::GraphicsLayerMac*)graphicsLayer { m_graphicsLayer = graphicsLayer; } @@ -342,10 +342,10 @@ static bool animationHasStepsTimingFunction(const KeyframeValueList& valueList, PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) { - return new GraphicsLayerCA(client); + return new GraphicsLayerMac(client); } -GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client) +GraphicsLayerMac::GraphicsLayerMac(GraphicsLayerClient* client) : GraphicsLayer(client) , m_contentsLayerPurpose(NoContentsLayer) , m_contentsLayerHasBackgroundColor(false) @@ -367,11 +367,11 @@ GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client) END_BLOCK_OBJC_EXCEPTIONS } -GraphicsLayerCA::~GraphicsLayerCA() +GraphicsLayerMac::~GraphicsLayerMac() { // We release our references to the CALayers here, but do not actively unparent them, // since that will cause a commit and break our batched commit model. The layers will - // get released when the rootmost modified GraphicsLayerCA rebuilds its child layers. + // get released when the rootmost modified GraphicsLayerMac rebuilds its child layers. BEGIN_BLOCK_OBJC_EXCEPTIONS @@ -395,19 +395,19 @@ GraphicsLayerCA::~GraphicsLayerCA() END_BLOCK_OBJC_EXCEPTIONS } -void GraphicsLayerCA::setName(const String& name) +void GraphicsLayerMac::setName(const String& name) { String longName = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + name; GraphicsLayer::setName(longName); noteLayerPropertyChanged(NameChanged); } -NativeLayer GraphicsLayerCA::nativeLayer() const +NativeLayer GraphicsLayerMac::nativeLayer() const { return m_layer.get(); } -bool GraphicsLayerCA::setChildren(const Vector<GraphicsLayer*>& children) +bool GraphicsLayerMac::setChildren(const Vector<GraphicsLayer*>& children) { bool childrenChanged = GraphicsLayer::setChildren(children); if (childrenChanged) @@ -416,31 +416,31 @@ bool GraphicsLayerCA::setChildren(const Vector<GraphicsLayer*>& children) return childrenChanged; } -void GraphicsLayerCA::addChild(GraphicsLayer* childLayer) +void GraphicsLayerMac::addChild(GraphicsLayer* childLayer) { GraphicsLayer::addChild(childLayer); noteSublayersChanged(); } -void GraphicsLayerCA::addChildAtIndex(GraphicsLayer* childLayer, int index) +void GraphicsLayerMac::addChildAtIndex(GraphicsLayer* childLayer, int index) { GraphicsLayer::addChildAtIndex(childLayer, index); noteSublayersChanged(); } -void GraphicsLayerCA::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling) +void GraphicsLayerMac::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling) { GraphicsLayer::addChildBelow(childLayer, sibling); noteSublayersChanged(); } -void GraphicsLayerCA::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling) +void GraphicsLayerMac::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling) { GraphicsLayer::addChildAbove(childLayer, sibling); noteSublayersChanged(); } -bool GraphicsLayerCA::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) +bool GraphicsLayerMac::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) { if (GraphicsLayer::replaceChild(oldChild, newChild)) { noteSublayersChanged(); @@ -449,14 +449,14 @@ bool GraphicsLayerCA::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newCh return false; } -void GraphicsLayerCA::removeFromParent() +void GraphicsLayerMac::removeFromParent() { if (m_parent) - static_cast<GraphicsLayerCA*>(m_parent)->noteSublayersChanged(); + static_cast<GraphicsLayerMac*>(m_parent)->noteSublayersChanged(); GraphicsLayer::removeFromParent(); } -void GraphicsLayerCA::setMaskLayer(GraphicsLayer* layer) +void GraphicsLayerMac::setMaskLayer(GraphicsLayer* layer) { if (layer == m_maskLayer) return; @@ -467,10 +467,10 @@ void GraphicsLayerCA::setMaskLayer(GraphicsLayer* layer) propagateLayerChangeToReplicas(); if (m_replicatedLayer) - static_cast<GraphicsLayerCA*>(m_replicatedLayer)->propagateLayerChangeToReplicas(); + static_cast<GraphicsLayerMac*>(m_replicatedLayer)->propagateLayerChangeToReplicas(); } -void GraphicsLayerCA::setReplicatedLayer(GraphicsLayer* layer) +void GraphicsLayerMac::setReplicatedLayer(GraphicsLayer* layer) { if (layer == m_replicatedLayer) return; @@ -479,7 +479,7 @@ void GraphicsLayerCA::setReplicatedLayer(GraphicsLayer* layer) noteLayerPropertyChanged(ReplicatedLayerChanged); } -void GraphicsLayerCA::setReplicatedByLayer(GraphicsLayer* layer) +void GraphicsLayerMac::setReplicatedByLayer(GraphicsLayer* layer) { if (layer == m_replicaLayer) return; @@ -489,7 +489,7 @@ void GraphicsLayerCA::setReplicatedByLayer(GraphicsLayer* layer) noteLayerPropertyChanged(ReplicatedLayerChanged); } -void GraphicsLayerCA::setPosition(const FloatPoint& point) +void GraphicsLayerMac::setPosition(const FloatPoint& point) { if (point == m_position) return; @@ -498,7 +498,7 @@ void GraphicsLayerCA::setPosition(const FloatPoint& point) noteLayerPropertyChanged(PositionChanged); } -void GraphicsLayerCA::setAnchorPoint(const FloatPoint3D& point) +void GraphicsLayerMac::setAnchorPoint(const FloatPoint3D& point) { if (point == m_anchorPoint) return; @@ -507,7 +507,7 @@ void GraphicsLayerCA::setAnchorPoint(const FloatPoint3D& point) noteLayerPropertyChanged(AnchorPointChanged); } -void GraphicsLayerCA::setSize(const FloatSize& size) +void GraphicsLayerMac::setSize(const FloatSize& size) { if (size == m_size) return; @@ -516,7 +516,7 @@ void GraphicsLayerCA::setSize(const FloatSize& size) noteLayerPropertyChanged(SizeChanged); } -void GraphicsLayerCA::setTransform(const TransformationMatrix& t) +void GraphicsLayerMac::setTransform(const TransformationMatrix& t) { if (t == m_transform) return; @@ -525,7 +525,7 @@ void GraphicsLayerCA::setTransform(const TransformationMatrix& t) noteLayerPropertyChanged(TransformChanged); } -void GraphicsLayerCA::setChildrenTransform(const TransformationMatrix& t) +void GraphicsLayerMac::setChildrenTransform(const TransformationMatrix& t) { if (t == m_childrenTransform) return; @@ -534,7 +534,7 @@ void GraphicsLayerCA::setChildrenTransform(const TransformationMatrix& t) noteLayerPropertyChanged(ChildrenTransformChanged); } -void GraphicsLayerCA::moveOrCopyLayerAnimation(MoveOrCopy operation, const String& animationIdentifier, CALayer *fromLayer, CALayer *toLayer) +void GraphicsLayerMac::moveOrCopyLayerAnimation(MoveOrCopy operation, const String& animationIdentifier, CALayer *fromLayer, CALayer *toLayer) { NSString *animationID = animationIdentifier; CAAnimation *anim = [fromLayer animationForKey:animationID]; @@ -555,7 +555,7 @@ void GraphicsLayerCA::moveOrCopyLayerAnimation(MoveOrCopy operation, const Strin } } -void GraphicsLayerCA::moveOrCopyAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, CALayer *fromLayer, CALayer *toLayer) +void GraphicsLayerMac::moveOrCopyAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, CALayer *fromLayer, CALayer *toLayer) { // Look for running animations affecting this property. AnimationsMap::const_iterator end = m_runningAnimations.end(); @@ -570,7 +570,7 @@ void GraphicsLayerCA::moveOrCopyAnimationsForProperty(MoveOrCopy operation, Anim } } -void GraphicsLayerCA::setPreserves3D(bool preserves3D) +void GraphicsLayerMac::setPreserves3D(bool preserves3D) { if (preserves3D == m_preserves3D) return; @@ -579,7 +579,7 @@ void GraphicsLayerCA::setPreserves3D(bool preserves3D) noteLayerPropertyChanged(Preserves3DChanged); } -void GraphicsLayerCA::setMasksToBounds(bool masksToBounds) +void GraphicsLayerMac::setMasksToBounds(bool masksToBounds) { if (masksToBounds == m_masksToBounds) return; @@ -588,7 +588,7 @@ void GraphicsLayerCA::setMasksToBounds(bool masksToBounds) noteLayerPropertyChanged(MasksToBoundsChanged); } -void GraphicsLayerCA::setDrawsContent(bool drawsContent) +void GraphicsLayerMac::setDrawsContent(bool drawsContent) { if (drawsContent == m_drawsContent) return; @@ -597,7 +597,7 @@ void GraphicsLayerCA::setDrawsContent(bool drawsContent) noteLayerPropertyChanged(DrawsContentChanged); } -void GraphicsLayerCA::setBackgroundColor(const Color& color) +void GraphicsLayerMac::setBackgroundColor(const Color& color) { if (m_backgroundColorSet && m_backgroundColor == color) return; @@ -608,7 +608,7 @@ void GraphicsLayerCA::setBackgroundColor(const Color& color) noteLayerPropertyChanged(BackgroundColorChanged); } -void GraphicsLayerCA::clearBackgroundColor() +void GraphicsLayerMac::clearBackgroundColor() { if (!m_backgroundColorSet) return; @@ -618,7 +618,7 @@ void GraphicsLayerCA::clearBackgroundColor() noteLayerPropertyChanged(BackgroundColorChanged); } -void GraphicsLayerCA::setContentsOpaque(bool opaque) +void GraphicsLayerMac::setContentsOpaque(bool opaque) { if (m_contentsOpaque == opaque) return; @@ -627,7 +627,7 @@ void GraphicsLayerCA::setContentsOpaque(bool opaque) noteLayerPropertyChanged(ContentsOpaqueChanged); } -void GraphicsLayerCA::setBackfaceVisibility(bool visible) +void GraphicsLayerMac::setBackfaceVisibility(bool visible) { if (m_backfaceVisibility == visible) return; @@ -636,7 +636,7 @@ void GraphicsLayerCA::setBackfaceVisibility(bool visible) noteLayerPropertyChanged(BackfaceVisibilityChanged); } -void GraphicsLayerCA::setOpacity(float opacity) +void GraphicsLayerMac::setOpacity(float opacity) { float clampedOpacity = max(0.0f, min(opacity, 1.0f)); @@ -647,7 +647,7 @@ void GraphicsLayerCA::setOpacity(float opacity) noteLayerPropertyChanged(OpacityChanged); } -void GraphicsLayerCA::setNeedsDisplay() +void GraphicsLayerMac::setNeedsDisplay() { FloatRect hugeRect(-numeric_limits<float>::max() / 2, -numeric_limits<float>::max() / 2, numeric_limits<float>::max(), numeric_limits<float>::max()); @@ -655,7 +655,7 @@ void GraphicsLayerCA::setNeedsDisplay() setNeedsDisplayInRect(hugeRect); } -void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& rect) +void GraphicsLayerMac::setNeedsDisplayInRect(const FloatRect& rect) { if (!drawsContent()) return; @@ -675,12 +675,12 @@ void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& rect) noteLayerPropertyChanged(DirtyRectsChanged); } -void GraphicsLayerCA::setContentsNeedsDisplay() +void GraphicsLayerMac::setContentsNeedsDisplay() { noteLayerPropertyChanged(ContentsNeedsDisplay); } -void GraphicsLayerCA::setContentsRect(const IntRect& rect) +void GraphicsLayerMac::setContentsRect(const IntRect& rect) { if (rect == m_contentsRect) return; @@ -689,7 +689,7 @@ void GraphicsLayerCA::setContentsRect(const IntRect& rect) noteLayerPropertyChanged(ContentsRectChanged); } -bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& animationName, double timeOffset) +bool GraphicsLayerMac::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& animationName, double timeOffset) { ASSERT(!animationName.isEmpty()); @@ -720,7 +720,7 @@ bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const Int return createdAnimations; } -void GraphicsLayerCA::pauseAnimation(const String& animationName, double timeOffset) +void GraphicsLayerMac::pauseAnimation(const String& animationName, double timeOffset) { if (!animationIsRunning(animationName)) return; @@ -737,7 +737,7 @@ void GraphicsLayerCA::pauseAnimation(const String& animationName, double timeOff noteLayerPropertyChanged(AnimationChanged); } -void GraphicsLayerCA::removeAnimation(const String& animationName) +void GraphicsLayerMac::removeAnimation(const String& animationName) { if (!animationIsRunning(animationName)) return; @@ -746,7 +746,7 @@ void GraphicsLayerCA::removeAnimation(const String& animationName) noteLayerPropertyChanged(AnimationChanged); } -void GraphicsLayerCA::animationDidStart(CAAnimation* caAnimation) +void GraphicsLayerMac::animationDidStart(CAAnimation* caAnimation) { bool hadNonZeroBeginTime = [[caAnimation valueForKey:WebKitAnimationBeginTimeSetKey] boolValue]; @@ -762,7 +762,7 @@ void GraphicsLayerCA::animationDidStart(CAAnimation* caAnimation) m_client->notifyAnimationStarted(this, startTime); } -void GraphicsLayerCA::setContentsToImage(Image* image) +void GraphicsLayerMac::setContentsToImage(Image* image) { if (image) { CGImageRef newImage = image->nativeImageForCurrentFrame(); @@ -799,7 +799,7 @@ void GraphicsLayerCA::setContentsToImage(Image* image) noteLayerPropertyChanged(ContentsImageChanged); } -void GraphicsLayerCA::setContentsToMedia(PlatformLayer* mediaLayer) +void GraphicsLayerMac::setContentsToMedia(PlatformLayer* mediaLayer) { if (mediaLayer == m_contentsLayer) return; @@ -811,7 +811,7 @@ void GraphicsLayerCA::setContentsToMedia(PlatformLayer* mediaLayer) noteLayerPropertyChanged(ContentsMediaLayerChanged); } -void GraphicsLayerCA::didDisplay(PlatformLayer* layer) +void GraphicsLayerMac::didDisplay(PlatformLayer* layer) { CALayer* sourceLayer; LayerMap* layerCloneMap; @@ -840,41 +840,41 @@ void GraphicsLayerCA::didDisplay(PlatformLayer* layer) } } -void GraphicsLayerCA::syncCompositingState() +void GraphicsLayerMac::syncCompositingState() { recursiveCommitChanges(); } -void GraphicsLayerCA::syncCompositingStateForThisLayerOnly() +void GraphicsLayerMac::syncCompositingStateForThisLayerOnly() { commitLayerChangesBeforeSublayers(); commitLayerChangesAfterSublayers(); } -void GraphicsLayerCA::recursiveCommitChanges() +void GraphicsLayerMac::recursiveCommitChanges() { commitLayerChangesBeforeSublayers(); if (m_maskLayer) - static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesBeforeSublayers(); + static_cast<GraphicsLayerMac*>(m_maskLayer)->commitLayerChangesBeforeSublayers(); const Vector<GraphicsLayer*>& childLayers = children(); size_t numChildren = childLayers.size(); for (size_t i = 0; i < numChildren; ++i) { - GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); + GraphicsLayerMac* curChild = static_cast<GraphicsLayerMac*>(childLayers[i]); curChild->recursiveCommitChanges(); } if (m_replicaLayer) - static_cast<GraphicsLayerCA*>(m_replicaLayer)->recursiveCommitChanges(); + static_cast<GraphicsLayerMac*>(m_replicaLayer)->recursiveCommitChanges(); if (m_maskLayer) - static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesAfterSublayers(); + static_cast<GraphicsLayerMac*>(m_maskLayer)->commitLayerChangesAfterSublayers(); commitLayerChangesAfterSublayers(); } -void GraphicsLayerCA::commitLayerChangesBeforeSublayers() +void GraphicsLayerMac::commitLayerChangesBeforeSublayers() { if (!m_uncommittedChanges) return; @@ -951,7 +951,7 @@ void GraphicsLayerCA::commitLayerChangesBeforeSublayers() END_BLOCK_OBJC_EXCEPTIONS } -void GraphicsLayerCA::commitLayerChangesAfterSublayers() +void GraphicsLayerMac::commitLayerChangesAfterSublayers() { if (!m_uncommittedChanges) return; @@ -965,7 +965,7 @@ void GraphicsLayerCA::commitLayerChangesAfterSublayers() END_BLOCK_OBJC_EXCEPTIONS } -void GraphicsLayerCA::updateLayerNames() +void GraphicsLayerMac::updateLayerNames() { switch (structuralLayerPurpose()) { case StructuralLayerForPreserves3D: @@ -980,7 +980,7 @@ void GraphicsLayerCA::updateLayerNames() [m_layer.get() setName:name()]; } -void GraphicsLayerCA::updateSublayerList() +void GraphicsLayerMac::updateSublayerList() { NSMutableArray* newSublayers = nil; @@ -992,7 +992,7 @@ void GraphicsLayerCA::updateSublayerList() if (m_structuralLayer) { // Add the replica layer first. if (m_replicaLayer) - [newSublayers addObject:static_cast<GraphicsLayerCA*>(m_replicaLayer)->primaryLayer()]; + [newSublayers addObject:static_cast<GraphicsLayerMac*>(m_replicaLayer)->primaryLayer()]; // Add the primary layer. Even if we have negative z-order children, the primary layer always comes behind. [newSublayers addObject:m_layer.get()]; } else if (m_contentsLayer) { @@ -1004,7 +1004,7 @@ void GraphicsLayerCA::updateSublayerList() size_t numChildren = childLayers.size(); for (size_t i = 0; i < numChildren; ++i) { - GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); + GraphicsLayerMac* curChild = static_cast<GraphicsLayerMac*>(childLayers[i]); CALayer *childLayer = curChild->layerForSuperlayer(); [newSublayers addObject:childLayer]; } @@ -1027,7 +1027,7 @@ void GraphicsLayerCA::updateSublayerList() [newSublayers release]; } -void GraphicsLayerCA::updateLayerPosition() +void GraphicsLayerMac::updateLayerPosition() { FloatSize usedSize = m_usingTiledLayer ? constrainedSize() : m_size; @@ -1052,7 +1052,7 @@ void GraphicsLayerCA::updateLayerPosition() } } -void GraphicsLayerCA::updateLayerSize() +void GraphicsLayerMac::updateLayerSize() { CGRect rect = CGRectMake(0, 0, m_size.width(), m_size.height()); if (m_structuralLayer) { @@ -1101,7 +1101,7 @@ void GraphicsLayerCA::updateLayerSize() updateLayerPosition(); } -void GraphicsLayerCA::updateAnchorPoint() +void GraphicsLayerMac::updateAnchorPoint() { [primaryLayer() setAnchorPoint:FloatPoint(m_anchorPoint.x(), m_anchorPoint.y())]; #if HAVE_MODERN_QUARTZCORE @@ -1122,7 +1122,7 @@ void GraphicsLayerCA::updateAnchorPoint() updateLayerPosition(); } -void GraphicsLayerCA::updateTransform() +void GraphicsLayerMac::updateTransform() { CATransform3D transform; copyTransform(transform, m_transform); @@ -1142,7 +1142,7 @@ void GraphicsLayerCA::updateTransform() } } -void GraphicsLayerCA::updateChildrenTransform() +void GraphicsLayerMac::updateChildrenTransform() { CATransform3D transform; copyTransform(transform, m_childrenTransform); @@ -1157,7 +1157,7 @@ void GraphicsLayerCA::updateChildrenTransform() } } -void GraphicsLayerCA::updateMasksToBounds() +void GraphicsLayerMac::updateMasksToBounds() { [m_layer.get() setMasksToBounds:m_masksToBounds]; @@ -1172,7 +1172,7 @@ void GraphicsLayerCA::updateMasksToBounds() updateDebugIndicators(); } -void GraphicsLayerCA::updateContentsOpaque() +void GraphicsLayerMac::updateContentsOpaque() { [m_layer.get() setOpaque:m_contentsOpaque]; @@ -1185,7 +1185,7 @@ void GraphicsLayerCA::updateContentsOpaque() } } -void GraphicsLayerCA::updateBackfaceVisibility() +void GraphicsLayerMac::updateBackfaceVisibility() { if (m_structuralLayer && structuralLayerPurpose() == StructuralLayerForReplicaFlattening) { [m_structuralLayer.get() setDoubleSided:m_backfaceVisibility]; @@ -1210,12 +1210,12 @@ void GraphicsLayerCA::updateBackfaceVisibility() } } -void GraphicsLayerCA::updateStructuralLayer() +void GraphicsLayerMac::updateStructuralLayer() { ensureStructuralLayer(structuralLayerPurpose()); } -void GraphicsLayerCA::ensureStructuralLayer(StructuralLayerPurpose purpose) +void GraphicsLayerMac::ensureStructuralLayer(StructuralLayerPurpose purpose) { if (purpose == NoStructuralLayer) { if (m_structuralLayer) { @@ -1300,7 +1300,7 @@ void GraphicsLayerCA::ensureStructuralLayer(StructuralLayerPurpose purpose) updateOpacityOnLayer(); } -GraphicsLayerCA::StructuralLayerPurpose GraphicsLayerCA::structuralLayerPurpose() const +GraphicsLayerMac::StructuralLayerPurpose GraphicsLayerMac::structuralLayerPurpose() const { if (preserves3D()) return StructuralLayerForPreserves3D; @@ -1311,7 +1311,7 @@ GraphicsLayerCA::StructuralLayerPurpose GraphicsLayerCA::structuralLayerPurpose( return NoStructuralLayer; } -void GraphicsLayerCA::updateLayerDrawsContent() +void GraphicsLayerMac::updateLayerDrawsContent() { bool needTiledLayer = requiresTiledLayer(m_size); if (needTiledLayer != m_usingTiledLayer) @@ -1325,7 +1325,7 @@ void GraphicsLayerCA::updateLayerDrawsContent() updateDebugIndicators(); } -void GraphicsLayerCA::updateLayerBackgroundColor() +void GraphicsLayerMac::updateLayerBackgroundColor() { if (!m_contentsLayer) return; @@ -1337,7 +1337,7 @@ void GraphicsLayerCA::updateLayerBackgroundColor() clearLayerBackgroundColor(m_contentsLayer.get()); } -void GraphicsLayerCA::updateContentsImage() +void GraphicsLayerMac::updateContentsImage() { if (m_pendingContentsImage) { if (!m_contentsLayer.get()) { @@ -1372,7 +1372,7 @@ void GraphicsLayerCA::updateContentsImage() } } -void GraphicsLayerCA::updateContentsMediaLayer() +void GraphicsLayerMac::updateContentsMediaLayer() { // Video layer was set as m_contentsLayer, and will get parented in updateSublayerList(). if (m_contentsLayer) { @@ -1381,7 +1381,7 @@ void GraphicsLayerCA::updateContentsMediaLayer() } } -void GraphicsLayerCA::updateContentsCanvasLayer() +void GraphicsLayerMac::updateContentsCanvasLayer() { // CanvasLayer was set as m_contentsLayer, and will get parented in updateSublayerList(). if (m_contentsLayer) { @@ -1391,7 +1391,7 @@ void GraphicsLayerCA::updateContentsCanvasLayer() } } -void GraphicsLayerCA::updateContentsRect() +void GraphicsLayerMac::updateContentsRect() { if (!m_contentsLayer) return; @@ -1416,12 +1416,12 @@ void GraphicsLayerCA::updateContentsRect() } } -void GraphicsLayerCA::updateMaskLayer() +void GraphicsLayerMac::updateMaskLayer() { CALayer *maskCALayer = m_maskLayer ? m_maskLayer->platformLayer() : 0; [m_layer.get() setMask:maskCALayer]; - LayerMap* maskLayerCloneMap = m_maskLayer ? static_cast<GraphicsLayerCA*>(m_maskLayer)->primaryLayerClones() : 0; + LayerMap* maskLayerCloneMap = m_maskLayer ? static_cast<GraphicsLayerMac*>(m_maskLayer)->primaryLayerClones() : 0; if (LayerMap* layerCloneMap = m_layerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); @@ -1434,7 +1434,7 @@ void GraphicsLayerCA::updateMaskLayer() } } -void GraphicsLayerCA::updateReplicatedLayers() +void GraphicsLayerMac::updateReplicatedLayers() { // Clone the descendants of the replicated layer, and parent under us. ReplicaState replicaState(ReplicaState::ReplicaBranch); @@ -1450,7 +1450,7 @@ void GraphicsLayerCA::updateReplicatedLayers() } // For now, this assumes that layers only ever have one replica, so replicaIndices contains only 0 and 1. -GraphicsLayerCA::CloneID GraphicsLayerCA::ReplicaState::cloneID() const +GraphicsLayerMac::CloneID GraphicsLayerMac::ReplicaState::cloneID() const { size_t depth = m_replicaBranches.size(); @@ -1470,13 +1470,13 @@ GraphicsLayerCA::CloneID GraphicsLayerCA::ReplicaState::cloneID() const return String::adopt(result); } -CALayer *GraphicsLayerCA::replicatedLayerRoot(ReplicaState& replicaState) +CALayer *GraphicsLayerMac::replicatedLayerRoot(ReplicaState& replicaState) { // Limit replica nesting, to avoid 2^N explosion of replica layers. if (!m_replicatedLayer || replicaState.replicaDepth() == ReplicaState::maxReplicaDepth) return nil; - GraphicsLayerCA* replicatedLayer = static_cast<GraphicsLayerCA*>(m_replicatedLayer); + GraphicsLayerMac* replicatedLayer = static_cast<GraphicsLayerMac*>(m_replicatedLayer); CALayer *clonedLayerRoot = replicatedLayer->fetchCloneLayers(this, replicaState, RootCloneLevel); FloatPoint cloneRootPosition = replicatedLayer->positionForCloneRootLayer(); @@ -1488,7 +1488,7 @@ CALayer *GraphicsLayerCA::replicatedLayerRoot(ReplicaState& replicaState) return clonedLayerRoot; } -void GraphicsLayerCA::updateLayerAnimations() +void GraphicsLayerMac::updateLayerAnimations() { if (m_animationsToProcess.size()) { AnimationsToProcessMap::const_iterator end = m_animationsToProcess.end(); @@ -1540,7 +1540,7 @@ void GraphicsLayerCA::updateLayerAnimations() } } -void GraphicsLayerCA::setCAAnimationOnLayer(CAPropertyAnimation* caAnim, AnimatedPropertyID property, const String& animationName, int index, double timeOffset) +void GraphicsLayerMac::setCAAnimationOnLayer(CAPropertyAnimation* caAnim, AnimatedPropertyID property, const String& animationName, int index, double timeOffset) { PlatformLayer* layer = animatedLayer(property); @@ -1582,7 +1582,7 @@ static void bug7311367Workaround(CALayer* transformLayer, const TransformationMa [transformLayer setTransform:caTransform]; } -bool GraphicsLayerCA::removeCAAnimationFromLayer(AnimatedPropertyID property, const String& animationName, int index) +bool GraphicsLayerMac::removeCAAnimationFromLayer(AnimatedPropertyID property, const String& animationName, int index) { PlatformLayer* layer = animatedLayer(property); @@ -1627,7 +1627,7 @@ static void copyAnimationProperties(CAPropertyAnimation* from, CAPropertyAnimati [to setValue:object forKey:WebKitAnimationBeginTimeSetKey]; } -void GraphicsLayerCA::pauseCAAnimationOnLayer(AnimatedPropertyID property, const String& animationName, int index, double timeOffset) +void GraphicsLayerMac::pauseCAAnimationOnLayer(AnimatedPropertyID property, const String& animationName, int index, double timeOffset) { PlatformLayer* layer = animatedLayer(property); @@ -1675,7 +1675,7 @@ void GraphicsLayerCA::pauseCAAnimationOnLayer(AnimatedPropertyID property, const } } -void GraphicsLayerCA::setContentsToCanvas(PlatformLayer* canvasLayer) +void GraphicsLayerMac::setContentsToCanvas(PlatformLayer* canvasLayer) { if (canvasLayer == m_contentsLayer) return; @@ -1690,7 +1690,7 @@ void GraphicsLayerCA::setContentsToCanvas(PlatformLayer* canvasLayer) noteLayerPropertyChanged(ContentsCanvasLayerChanged); } -void GraphicsLayerCA::repaintLayerDirtyRects() +void GraphicsLayerMac::repaintLayerDirtyRects() { if (!m_dirtyRects.size()) return; @@ -1701,13 +1701,13 @@ void GraphicsLayerCA::repaintLayerDirtyRects() m_dirtyRects.clear(); } -void GraphicsLayerCA::updateContentsNeedsDisplay() +void GraphicsLayerMac::updateContentsNeedsDisplay() { if (m_contentsLayer) [m_contentsLayer.get() setNeedsDisplay]; } -bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset) +bool GraphicsLayerMac::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset) { ASSERT(valueList.property() != AnimatedPropertyWebkitTransform); @@ -1740,7 +1740,7 @@ bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valu return true; } -bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset, const IntSize& boxSize) +bool GraphicsLayerMac::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset, const IntSize& boxSize) { ASSERT(valueList.property() == AnimatedPropertyWebkitTransform); @@ -1799,21 +1799,21 @@ bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValue return validMatrices; } -CABasicAnimation* GraphicsLayerCA::createBasicAnimation(const Animation* anim, AnimatedPropertyID property, bool additive) +CABasicAnimation* GraphicsLayerMac::createBasicAnimation(const Animation* anim, AnimatedPropertyID property, bool additive) { CABasicAnimation* basicAnim = [CABasicAnimation animationWithKeyPath:propertyIdToString(property)]; setupAnimation(basicAnim, anim, additive); return basicAnim; } -CAKeyframeAnimation* GraphicsLayerCA::createKeyframeAnimation(const Animation* anim, AnimatedPropertyID property, bool additive) +CAKeyframeAnimation* GraphicsLayerMac::createKeyframeAnimation(const Animation* anim, AnimatedPropertyID property, bool additive) { CAKeyframeAnimation* keyframeAnim = [CAKeyframeAnimation animationWithKeyPath:propertyIdToString(property)]; setupAnimation(keyframeAnim, anim, additive); return keyframeAnim; } -void GraphicsLayerCA::setupAnimation(CAPropertyAnimation* propertyAnim, const Animation* anim, bool additive) +void GraphicsLayerMac::setupAnimation(CAPropertyAnimation* propertyAnim, const Animation* anim, bool additive) { double duration = anim->duration(); if (duration <= 0) @@ -1851,7 +1851,7 @@ void GraphicsLayerCA::setupAnimation(CAPropertyAnimation* propertyAnim, const An [propertyAnim setDelegate:m_animationDelegate.get()]; } -CAMediaTimingFunction* GraphicsLayerCA::timingFunctionForAnimationValue(const AnimationValue* animValue, const Animation* anim) +CAMediaTimingFunction* GraphicsLayerMac::timingFunctionForAnimationValue(const AnimationValue* animValue, const Animation* anim) { const TimingFunction* tf = 0; if (animValue->timingFunction()) @@ -1862,7 +1862,7 @@ CAMediaTimingFunction* GraphicsLayerCA::timingFunctionForAnimationValue(const An return getCAMediaTimingFunction(tf ? tf : CubicBezierTimingFunction::create().get()); } -bool GraphicsLayerCA::setAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, CABasicAnimation* basicAnim) +bool GraphicsLayerMac::setAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, CABasicAnimation* basicAnim) { id fromValue = nil; id toValue = nil; @@ -1891,7 +1891,7 @@ bool GraphicsLayerCA::setAnimationEndpoints(const KeyframeValueList& valueList, return true; } -bool GraphicsLayerCA::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* anim, CAKeyframeAnimation* keyframeAnim) +bool GraphicsLayerMac::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* anim, CAKeyframeAnimation* keyframeAnim) { RetainPtr<NSMutableArray> keyTimes(AdoptNS, [[NSMutableArray alloc] init]); RetainPtr<NSMutableArray> values(AdoptNS, [[NSMutableArray alloc] init]); @@ -1926,7 +1926,7 @@ bool GraphicsLayerCA::setAnimationKeyframes(const KeyframeValueList& valueList, return true; } -bool GraphicsLayerCA::setTransformAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, CABasicAnimation* basicAnim, int functionIndex, TransformOperation::OperationType transformOp, bool isMatrixAnimation, const IntSize& boxSize) +bool GraphicsLayerMac::setTransformAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, CABasicAnimation* basicAnim, int functionIndex, TransformOperation::OperationType transformOp, bool isMatrixAnimation, const IntSize& boxSize) { id fromValue; id toValue; @@ -1971,7 +1971,7 @@ bool GraphicsLayerCA::setTransformAnimationEndpoints(const KeyframeValueList& va return true; } -bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, CAKeyframeAnimation* keyframeAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize) +bool GraphicsLayerMac::setTransformAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, CAKeyframeAnimation* keyframeAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize) { RetainPtr<NSMutableArray> keyTimes(AdoptNS, [[NSMutableArray alloc] init]); RetainPtr<NSMutableArray> values(AdoptNS, [[NSMutableArray alloc] init]); @@ -2015,7 +2015,7 @@ bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& va return true; } -void GraphicsLayerCA::suspendAnimations(double time) +void GraphicsLayerMac::suspendAnimations(double time) { double t = currentTimeToMediaTime(time ? time : currentTime()); [primaryLayer() setSpeed:0]; @@ -2032,7 +2032,7 @@ void GraphicsLayerCA::suspendAnimations(double time) } } -void GraphicsLayerCA::resumeAnimations() +void GraphicsLayerMac::resumeAnimations() { [primaryLayer() setSpeed:1]; [primaryLayer() setTimeOffset:0]; @@ -2048,32 +2048,32 @@ void GraphicsLayerCA::resumeAnimations() } } -CALayer* GraphicsLayerCA::hostLayerForSublayers() const +CALayer* GraphicsLayerMac::hostLayerForSublayers() const { return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get(); } -CALayer* GraphicsLayerCA::layerForSuperlayer() const +CALayer* GraphicsLayerMac::layerForSuperlayer() const { return m_structuralLayer ? m_structuralLayer.get() : m_layer.get(); } -CALayer* GraphicsLayerCA::animatedLayer(AnimatedPropertyID property) const +CALayer* GraphicsLayerMac::animatedLayer(AnimatedPropertyID property) const { return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayer.get() : primaryLayer(); } -GraphicsLayerCA::LayerMap* GraphicsLayerCA::animatedLayerClones(AnimatedPropertyID property) const +GraphicsLayerMac::LayerMap* GraphicsLayerMac::animatedLayerClones(AnimatedPropertyID property) const { return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayerClones.get() : primaryLayerClones(); } -PlatformLayer* GraphicsLayerCA::platformLayer() const +PlatformLayer* GraphicsLayerMac::platformLayer() const { return primaryLayer(); } -void GraphicsLayerCA::setDebugBackgroundColor(const Color& color) +void GraphicsLayerMac::setDebugBackgroundColor(const Color& color) { BEGIN_BLOCK_OBJC_EXCEPTIONS @@ -2085,7 +2085,7 @@ void GraphicsLayerCA::setDebugBackgroundColor(const Color& color) END_BLOCK_OBJC_EXCEPTIONS } -void GraphicsLayerCA::setDebugBorder(const Color& color, float borderWidth) +void GraphicsLayerMac::setDebugBorder(const Color& color, float borderWidth) { BEGIN_BLOCK_OBJC_EXCEPTIONS @@ -2100,7 +2100,7 @@ void GraphicsLayerCA::setDebugBorder(const Color& color, float borderWidth) END_BLOCK_OBJC_EXCEPTIONS } -FloatSize GraphicsLayerCA::constrainedSize() const +FloatSize GraphicsLayerMac::constrainedSize() const { float tileColumns = ceilf(m_size.width() / cTiledLayerTileSize); float tileRows = ceilf(m_size.height() / cTiledLayerTileSize); @@ -2123,7 +2123,7 @@ FloatSize GraphicsLayerCA::constrainedSize() const return constrainedSize; } -bool GraphicsLayerCA::requiresTiledLayer(const FloatSize& size) const +bool GraphicsLayerMac::requiresTiledLayer(const FloatSize& size) const { if (!m_drawsContent) return false; @@ -2132,7 +2132,7 @@ bool GraphicsLayerCA::requiresTiledLayer(const FloatSize& size) const return size.width() > cMaxPixelDimension || size.height() > cMaxPixelDimension; } -void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer) +void GraphicsLayerMac::swapFromOrToTiledLayer(bool useTiledLayer) { if (useTiledLayer == m_usingTiledLayer) return; @@ -2198,7 +2198,7 @@ void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer) updateDebugIndicators(); } -GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerCA::defaultContentsOrientation() const +GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerMac::defaultContentsOrientation() const { #if !HAVE_MODERN_QUARTZCORE // Older QuartzCore does not support -geometryFlipped, so we manually flip the root @@ -2210,7 +2210,7 @@ GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerCA::defaultContent #endif } -void GraphicsLayerCA::updateContentsTransform() +void GraphicsLayerMac::updateContentsTransform() { #if !HAVE_MODERN_QUARTZCORE if (contentsOrientation() == CompositingCoordinatesBottomUp) { @@ -2221,7 +2221,7 @@ void GraphicsLayerCA::updateContentsTransform() #endif } -void GraphicsLayerCA::setupContentsLayer(CALayer* contentsLayer) +void GraphicsLayerMac::setupContentsLayer(CALayer* contentsLayer) { // Turn off implicit animations on the inner layer. [contentsLayer setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]]; @@ -2244,7 +2244,7 @@ void GraphicsLayerCA::setupContentsLayer(CALayer* contentsLayer) } } -CALayer *GraphicsLayerCA::findOrMakeClone(CloneID cloneID, CALayer *sourceLayer, LayerMap* clones, CloneLevel cloneLevel) +CALayer *GraphicsLayerMac::findOrMakeClone(CloneID cloneID, CALayer *sourceLayer, LayerMap* clones, CloneLevel cloneLevel) { if (!sourceLayer) return 0; @@ -2269,7 +2269,7 @@ CALayer *GraphicsLayerCA::findOrMakeClone(CloneID cloneID, CALayer *sourceLayer, return resultLayer; } -void GraphicsLayerCA::ensureCloneLayers(CloneID cloneID, CALayer *& primaryLayer, CALayer *& structuralLayer, CALayer *& contentsLayer, CloneLevel cloneLevel) +void GraphicsLayerMac::ensureCloneLayers(CloneID cloneID, CALayer *& primaryLayer, CALayer *& structuralLayer, CALayer *& contentsLayer, CloneLevel cloneLevel) { structuralLayer = nil; contentsLayer = nil; @@ -2288,14 +2288,14 @@ void GraphicsLayerCA::ensureCloneLayers(CloneID cloneID, CALayer *& primaryLayer contentsLayer = findOrMakeClone(cloneID, m_contentsLayer.get(), m_contentsLayerClones.get(), cloneLevel); } -void GraphicsLayerCA::removeCloneLayers() +void GraphicsLayerMac::removeCloneLayers() { m_layerClones = 0; m_structuralLayerClones = 0; m_contentsLayerClones = 0; } -FloatPoint GraphicsLayerCA::positionForCloneRootLayer() const +FloatPoint GraphicsLayerMac::positionForCloneRootLayer() const { // This can get called during a sync when we've just removed the m_replicaLayer. if (!m_replicaLayer) @@ -2306,19 +2306,19 @@ FloatPoint GraphicsLayerCA::positionForCloneRootLayer() const replicaPosition.y() + m_anchorPoint.y() * m_size.height()); } -void GraphicsLayerCA::propagateLayerChangeToReplicas() +void GraphicsLayerMac::propagateLayerChangeToReplicas() { for (GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent()) { - GraphicsLayerCA* currLayerCA = static_cast<GraphicsLayerCA*>(currLayer); + GraphicsLayerMac* currLayerCA = static_cast<GraphicsLayerMac*>(currLayer); if (!currLayerCA->hasCloneLayers()) break; if (currLayerCA->replicaLayer()) - static_cast<GraphicsLayerCA*>(currLayerCA->replicaLayer())->noteLayerPropertyChanged(ReplicatedLayerChanged); + static_cast<GraphicsLayerMac*>(currLayerCA->replicaLayer())->noteLayerPropertyChanged(ReplicatedLayerChanged); } } -CALayer *GraphicsLayerCA::fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaState& replicaState, CloneLevel cloneLevel) +CALayer *GraphicsLayerMac::fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaState& replicaState, CloneLevel cloneLevel) { CALayer *primaryLayer; CALayer *structuralLayer; @@ -2326,7 +2326,7 @@ CALayer *GraphicsLayerCA::fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaSt ensureCloneLayers(replicaState.cloneID(), primaryLayer, structuralLayer, contentsLayer, cloneLevel); if (m_maskLayer) { - CALayer *maskClone = static_cast<GraphicsLayerCA*>(m_maskLayer)->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel); + CALayer *maskClone = static_cast<GraphicsLayerMac*>(m_maskLayer)->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel); [primaryLayer setMask:maskClone]; } @@ -2352,7 +2352,7 @@ CALayer *GraphicsLayerCA::fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaSt if (m_replicaLayer && m_replicaLayer != replicaRoot) { // We have nested replicas. Ask the replica layer for a clone of its contents. replicaState.setBranchType(ReplicaState::ReplicaBranch); - replicaLayer = static_cast<GraphicsLayerCA*>(m_replicaLayer)->fetchCloneLayers(replicaRoot, replicaState, RootCloneLevel); + replicaLayer = static_cast<GraphicsLayerMac*>(m_replicaLayer)->fetchCloneLayers(replicaRoot, replicaState, RootCloneLevel); replicaState.setBranchType(ReplicaState::ChildBranch); } @@ -2377,7 +2377,7 @@ CALayer *GraphicsLayerCA::fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaSt size_t numChildren = childLayers.size(); for (size_t i = 0; i < numChildren; ++i) { - GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); + GraphicsLayerMac* curChild = static_cast<GraphicsLayerMac*>(childLayers[i]); CALayer *childLayer = curChild->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel); if (childLayer) @@ -2410,7 +2410,7 @@ CALayer *GraphicsLayerCA::fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaSt return result; } -CALayer *GraphicsLayerCA::cloneLayer(CALayer *layer, CloneLevel cloneLevel) +CALayer *GraphicsLayerMac::cloneLayer(CALayer *layer, CloneLevel cloneLevel) { static Class transformLayerClass = NSClassFromString(@"CATransformLayer"); CALayer *newLayer = nil; @@ -2449,7 +2449,7 @@ CALayer *GraphicsLayerCA::cloneLayer(CALayer *layer, CloneLevel cloneLevel) return newLayer; } -void GraphicsLayerCA::setOpacityInternal(float accumulatedOpacity) +void GraphicsLayerMac::setOpacityInternal(float accumulatedOpacity) { LayerMap* layerCloneMap = 0; @@ -2472,7 +2472,7 @@ void GraphicsLayerCA::setOpacityInternal(float accumulatedOpacity) } } -void GraphicsLayerCA::updateOpacityOnLayer() +void GraphicsLayerMac::updateOpacityOnLayer() { #if !HAVE_MODERN_QUARTZCORE // Distribute opacity either to our own layer or to our children. We pass in the @@ -2495,13 +2495,13 @@ void GraphicsLayerCA::updateOpacityOnLayer() #endif } -void GraphicsLayerCA::noteSublayersChanged() +void GraphicsLayerMac::noteSublayersChanged() { noteLayerPropertyChanged(ChildrenChanged); propagateLayerChangeToReplicas(); } -void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags) +void GraphicsLayerMac::noteLayerPropertyChanged(LayerChangeFlags flags) { if (!m_uncommittedChanges && m_client) m_client->notifySyncRequired(this); diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h index 876bc16..95ab456 100644 --- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h +++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h @@ -55,7 +55,7 @@ class WebCoreMovieObserver; namespace WebCore { -class MediaPlayerPrivate : public MediaPlayerPrivateInterface { +class MediaPlayerPrivateQTKit : public MediaPlayerPrivateInterface { public: static void registerMediaEngine(MediaEngineRegistrar); @@ -67,8 +67,8 @@ public: void didEnd(); private: - MediaPlayerPrivate(MediaPlayer*); - ~MediaPlayerPrivate(); + MediaPlayerPrivateQTKit(MediaPlayer*); + ~MediaPlayerPrivateQTKit(); // engine support static MediaPlayerPrivateInterface* create(MediaPlayer* player); @@ -163,7 +163,7 @@ private: void updateStates(); void doSeek(); void cancelSeek(); - void seekTimerFired(Timer<MediaPlayerPrivate>*); + void seekTimerFired(Timer<MediaPlayerPrivateQTKit>*); float maxTimeLoaded() const; void disableUnsupportedTracks(); @@ -175,6 +175,8 @@ private: virtual float mediaTimeForTimeValue(float) const; + virtual double maximumDurationToCacheMediaTime() const { return 5; } + MediaPlayer* m_player; RetainPtr<QTMovie> m_qtMovie; RetainPtr<QTMovieView> m_qtMovieView; @@ -182,7 +184,7 @@ private: RetainPtr<WebCoreMovieObserver> m_objcObserver; String m_movieURL; float m_seekTo; - Timer<MediaPlayerPrivate> m_seekTimer; + Timer<MediaPlayerPrivateQTKit> m_seekTimer; MediaPlayer::NetworkState m_networkState; MediaPlayer::ReadyState m_readyState; IntRect m_rect; diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm index 06c7924..a2325da 100644 --- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm +++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm @@ -164,11 +164,11 @@ using namespace std; @interface WebCoreMovieObserver : NSObject { - MediaPlayerPrivate* m_callback; + MediaPlayerPrivateQTKit* m_callback; NSView* m_view; BOOL m_delayCallbacks; } --(id)initWithCallback:(MediaPlayerPrivate*)callback; +-(id)initWithCallback:(MediaPlayerPrivateQTKit*)callback; -(void)disconnect; -(void)setView:(NSView*)view; -(void)repaint; @@ -192,22 +192,22 @@ static const long minimumQuickTimeVersion = 0x07300000; // 7.3 #endif -MediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player) +MediaPlayerPrivateInterface* MediaPlayerPrivateQTKit::create(MediaPlayer* player) { - return new MediaPlayerPrivate(player); + return new MediaPlayerPrivateQTKit(player); } -void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar) +void MediaPlayerPrivateQTKit::registerMediaEngine(MediaEngineRegistrar registrar) { if (isAvailable()) registrar(create, getSupportedTypes, supportsType); } -MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) +MediaPlayerPrivateQTKit::MediaPlayerPrivateQTKit(MediaPlayer* player) : m_player(player) , m_objcObserver(AdoptNS, [[WebCoreMovieObserver alloc] initWithCallback:this]) , m_seekTo(-1) - , m_seekTimer(this, &MediaPlayerPrivate::seekTimerFired) + , m_seekTimer(this, &MediaPlayerPrivateQTKit::seekTimerFired) , m_networkState(MediaPlayer::Empty) , m_readyState(MediaPlayer::HaveNothing) , m_rect() @@ -232,7 +232,7 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) { } -MediaPlayerPrivate::~MediaPlayerPrivate() +MediaPlayerPrivateQTKit::~MediaPlayerPrivateQTKit() { tearDownVideoRendering(); @@ -240,24 +240,52 @@ MediaPlayerPrivate::~MediaPlayerPrivate() [m_objcObserver.get() disconnect]; } -void MediaPlayerPrivate::createQTMovie(const String& url) +void MediaPlayerPrivateQTKit::createQTMovie(const String& url) { NSURL *cocoaURL = KURL(ParsedURLString, url); - NSDictionary *movieAttributes = [NSDictionary dictionaryWithObjectsAndKeys: + 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, -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) - [NSNumber numberWithBool:YES], @"QTMovieOpenForPlaybackAttribute", -#endif #ifndef BUILDING_ON_TIGER QTMovieApertureModeClean, QTMovieApertureModeAttribute, #endif nil]; +#if defined(BUILDING_ON_SNOW_LEOPARD) + CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings(); + CFArrayRef proxiesForURL = CFNetworkCopyProxiesForURL((CFURLRef)cocoaURL, proxySettings); + BOOL willUseProxy = YES; + + if (!proxiesForURL || !CFArrayGetCount(proxiesForURL)) + willUseProxy = NO; + + if (CFArrayGetCount(proxiesForURL) == 1) { + CFDictionaryRef proxy = (CFDictionaryRef)CFArrayGetValueAtIndex(proxiesForURL, 0); + ASSERT(CFGetTypeID(proxy) == CFDictionaryGetTypeID()); + + CFStringRef proxyType = (CFStringRef)CFDictionaryGetValue(proxy, kCFProxyTypeKey); + ASSERT(CFGetTypeID(proxyType) == CFStringGetTypeID()); + + if (CFStringCompare(proxyType, kCFProxyTypeNone, 0) == kCFCompareEqualTo) + willUseProxy = NO; + } + + if (!willUseProxy) { + // Only pass the QTMovieOpenForPlaybackAttribute flag if there are no proxy servers, due + // to rdar://problem/7531776. + [movieAttributes setObject:[NSNumber numberWithBool:YES] forKey:@"QTMovieOpenForPlaybackAttribute"]; + } + + if (proxiesForURL) + CFRelease(proxiesForURL); + if (proxySettings) + CFRelease(proxySettings); +#endif + createQTMovie(cocoaURL, movieAttributes); } @@ -292,7 +320,7 @@ static void disableComponentsOnce() wkQTMovieDisableComponent(componentsToDisable[i]); } -void MediaPlayerPrivate::createQTMovie(NSURL *url, NSDictionary *movieAttributes) +void MediaPlayerPrivateQTKit::createQTMovie(NSURL *url, NSDictionary *movieAttributes) { disableComponentsOnce(); @@ -375,7 +403,7 @@ static Class QTVideoRendererClass() return QTVideoRendererWebKitOnlyClass; } -void MediaPlayerPrivate::createQTMovieView() +void MediaPlayerPrivateQTKit::createQTMovieView() { detachQTMovieView(); @@ -420,7 +448,7 @@ void MediaPlayerPrivate::createQTMovieView() [m_objcObserver.get() setDelayCallbacks:NO]; } -void MediaPlayerPrivate::detachQTMovieView() +void MediaPlayerPrivateQTKit::detachQTMovieView() { if (m_qtMovieView) { [m_objcObserver.get() setView:nil]; @@ -435,7 +463,7 @@ void MediaPlayerPrivate::detachQTMovieView() } } -void MediaPlayerPrivate::createQTVideoRenderer(QTVideoRendererMode rendererMode) +void MediaPlayerPrivateQTKit::createQTVideoRenderer(QTVideoRendererMode rendererMode) { destroyQTVideoRenderer(); @@ -455,7 +483,7 @@ void MediaPlayerPrivate::createQTVideoRenderer(QTVideoRendererMode rendererMode) } } -void MediaPlayerPrivate::destroyQTVideoRenderer() +void MediaPlayerPrivateQTKit::destroyQTVideoRenderer() { if (!m_qtVideoRenderer) return; @@ -471,7 +499,7 @@ void MediaPlayerPrivate::destroyQTVideoRenderer() m_qtVideoRenderer = nil; } -void MediaPlayerPrivate::createQTMovieLayer() +void MediaPlayerPrivateQTKit::createQTMovieLayer() { #if USE(ACCELERATED_COMPOSITING) if (!m_qtMovie) @@ -493,7 +521,7 @@ void MediaPlayerPrivate::createQTMovieLayer() #endif } -void MediaPlayerPrivate::destroyQTMovieLayer() +void MediaPlayerPrivateQTKit::destroyQTMovieLayer() { #if USE(ACCELERATED_COMPOSITING) if (!m_qtVideoLayer) @@ -505,7 +533,7 @@ void MediaPlayerPrivate::destroyQTMovieLayer() #endif } -MediaPlayerPrivate::MediaRenderingMode MediaPlayerPrivate::currentRenderingMode() const +MediaPlayerPrivateQTKit::MediaRenderingMode MediaPlayerPrivateQTKit::currentRenderingMode() const { if (m_qtMovieView) return MediaRenderingMovieView; @@ -519,7 +547,7 @@ MediaPlayerPrivate::MediaRenderingMode MediaPlayerPrivate::currentRenderingMode( return MediaRenderingNone; } -MediaPlayerPrivate::MediaRenderingMode MediaPlayerPrivate::preferredRenderingMode() const +MediaPlayerPrivateQTKit::MediaRenderingMode MediaPlayerPrivateQTKit::preferredRenderingMode() const { if (!m_player->frameView() || !m_qtMovie) return MediaRenderingNone; @@ -535,7 +563,7 @@ MediaPlayerPrivate::MediaRenderingMode MediaPlayerPrivate::preferredRenderingMod return MediaRenderingSoftwareRenderer; } -void MediaPlayerPrivate::setUpVideoRendering() +void MediaPlayerPrivateQTKit::setUpVideoRendering() { if (!isReadyForVideoSetup()) return; @@ -566,7 +594,7 @@ void MediaPlayerPrivate::setUpVideoRendering() m_player->mediaPlayerClient()->mediaPlayerRenderingModeChanged(m_player); } -void MediaPlayerPrivate::tearDownVideoRendering() +void MediaPlayerPrivateQTKit::tearDownVideoRendering() { if (m_qtMovieView) detachQTMovieView(); @@ -576,14 +604,14 @@ void MediaPlayerPrivate::tearDownVideoRendering() destroyQTMovieLayer(); } -bool MediaPlayerPrivate::hasSetUpVideoRendering() const +bool MediaPlayerPrivateQTKit::hasSetUpVideoRendering() const { return m_qtMovieView || m_qtVideoLayer || m_qtVideoRenderer; } -QTTime MediaPlayerPrivate::createQTTime(float time) const +QTTime MediaPlayerPrivateQTKit::createQTTime(float time) const { if (!metaDataAvailable()) return QTMakeTime(0, 600); @@ -591,7 +619,7 @@ QTTime MediaPlayerPrivate::createQTTime(float time) const return QTMakeTime(time * timeScale, timeScale); } -void MediaPlayerPrivate::resumeLoad() +void MediaPlayerPrivateQTKit::resumeLoad() { m_delayingLoad = false; @@ -599,7 +627,7 @@ void MediaPlayerPrivate::resumeLoad() loadInternal(m_movieURL); } -void MediaPlayerPrivate::load(const String& url) +void MediaPlayerPrivateQTKit::load(const String& url) { m_movieURL = url; @@ -613,7 +641,7 @@ void MediaPlayerPrivate::load(const String& url) loadInternal(url); } -void MediaPlayerPrivate::loadInternal(const String& url) +void MediaPlayerPrivateQTKit::loadInternal(const String& url) { if (m_networkState != MediaPlayer::Loading) { m_networkState = MediaPlayer::Loading; @@ -634,13 +662,13 @@ void MediaPlayerPrivate::loadInternal(const String& url) [m_objcObserver.get() setDelayCallbacks:NO]; } -void MediaPlayerPrivate::prepareToPlay() +void MediaPlayerPrivateQTKit::prepareToPlay() { if (!m_qtMovie || m_delayingLoad) resumeLoad(); } -PlatformMedia MediaPlayerPrivate::platformMedia() const +PlatformMedia MediaPlayerPrivateQTKit::platformMedia() const { PlatformMedia pm; pm.type = PlatformMedia::QTMovieType; @@ -649,13 +677,13 @@ PlatformMedia MediaPlayerPrivate::platformMedia() const } #if USE(ACCELERATED_COMPOSITING) -PlatformLayer* MediaPlayerPrivate::platformLayer() const +PlatformLayer* MediaPlayerPrivateQTKit::platformLayer() const { return m_qtVideoLayer.get(); } #endif -void MediaPlayerPrivate::play() +void MediaPlayerPrivateQTKit::play() { if (!metaDataAvailable()) return; @@ -668,7 +696,7 @@ void MediaPlayerPrivate::play() [m_objcObserver.get() setDelayCallbacks:NO]; } -void MediaPlayerPrivate::pause() +void MediaPlayerPrivateQTKit::pause() { if (!metaDataAvailable()) return; @@ -681,7 +709,7 @@ void MediaPlayerPrivate::pause() [m_objcObserver.get() setDelayCallbacks:NO]; } -float MediaPlayerPrivate::duration() const +float MediaPlayerPrivateQTKit::duration() const { if (!metaDataAvailable()) return 0; @@ -695,7 +723,7 @@ float MediaPlayerPrivate::duration() const return static_cast<float>(time.timeValue) / time.timeScale; } -float MediaPlayerPrivate::currentTime() const +float MediaPlayerPrivateQTKit::currentTime() const { if (!metaDataAvailable()) return 0; @@ -703,7 +731,7 @@ float MediaPlayerPrivate::currentTime() const return static_cast<float>(time.timeValue) / time.timeScale; } -void MediaPlayerPrivate::seek(float time) +void MediaPlayerPrivateQTKit::seek(float time) { // Nothing to do if we are already in the middle of a seek to the same time. if (time == m_seekTo) @@ -724,7 +752,7 @@ void MediaPlayerPrivate::seek(float time) m_seekTimer.start(0, 0.5f); } -void MediaPlayerPrivate::doSeek() +void MediaPlayerPrivateQTKit::doSeek() { QTTime qttime = createQTTime(m_seekTo); // setCurrentTime generates several event callbacks, update afterwards @@ -744,13 +772,13 @@ void MediaPlayerPrivate::doSeek() [m_objcObserver.get() setDelayCallbacks:NO]; } -void MediaPlayerPrivate::cancelSeek() +void MediaPlayerPrivateQTKit::cancelSeek() { m_seekTo = -1; m_seekTimer.stop(); } -void MediaPlayerPrivate::seekTimerFired(Timer<MediaPlayerPrivate>*) +void MediaPlayerPrivateQTKit::seekTimerFired(Timer<MediaPlayerPrivateQTKit>*) { if (!metaDataAvailable()|| !seeking() || currentTime() == m_seekTo) { cancelSeek(); @@ -771,21 +799,21 @@ void MediaPlayerPrivate::seekTimerFired(Timer<MediaPlayerPrivate>*) } } -bool MediaPlayerPrivate::paused() const +bool MediaPlayerPrivateQTKit::paused() const { if (!metaDataAvailable()) return true; return [m_qtMovie.get() rate] == 0; } -bool MediaPlayerPrivate::seeking() const +bool MediaPlayerPrivateQTKit::seeking() const { if (!metaDataAvailable()) return false; return m_seekTo >= 0; } -IntSize MediaPlayerPrivate::naturalSize() const +IntSize MediaPlayerPrivateQTKit::naturalSize() const { if (!metaDataAvailable()) return IntSize(); @@ -801,21 +829,21 @@ IntSize MediaPlayerPrivate::naturalSize() const return IntSize(naturalSize.width * m_scaleFactor.width(), naturalSize.height * m_scaleFactor.height()); } -bool MediaPlayerPrivate::hasVideo() const +bool MediaPlayerPrivateQTKit::hasVideo() const { if (!metaDataAvailable()) return false; return [[m_qtMovie.get() attributeForKey:QTMovieHasVideoAttribute] boolValue]; } -bool MediaPlayerPrivate::hasAudio() const +bool MediaPlayerPrivateQTKit::hasAudio() const { if (!m_qtMovie) return false; return [[m_qtMovie.get() attributeForKey:QTMovieHasAudioAttribute] boolValue]; } -bool MediaPlayerPrivate::supportsFullscreen() const +bool MediaPlayerPrivateQTKit::supportsFullscreen() const { #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) return true; @@ -825,20 +853,20 @@ bool MediaPlayerPrivate::supportsFullscreen() const #endif } -void MediaPlayerPrivate::setVolume(float volume) +void MediaPlayerPrivateQTKit::setVolume(float volume) { if (m_qtMovie) [m_qtMovie.get() setVolume:volume]; } -bool MediaPlayerPrivate::hasClosedCaptions() const +bool MediaPlayerPrivateQTKit::hasClosedCaptions() const { if (!metaDataAvailable()) return false; return wkQTMovieHasClosedCaptions(m_qtMovie.get()); } -void MediaPlayerPrivate::setClosedCaptionsVisible(bool closedCaptionsVisible) +void MediaPlayerPrivateQTKit::setClosedCaptionsVisible(bool closedCaptionsVisible) { if (metaDataAvailable()) { wkQTMovieSetShowClosedCaptions(m_qtMovie.get(), closedCaptionsVisible); @@ -852,13 +880,13 @@ void MediaPlayerPrivate::setClosedCaptionsVisible(bool closedCaptionsVisible) } } -void MediaPlayerPrivate::setRate(float rate) +void MediaPlayerPrivateQTKit::setRate(float rate) { if (m_qtMovie) [m_qtMovie.get() setRate:rate]; } -void MediaPlayerPrivate::setPreservesPitch(bool preservesPitch) +void MediaPlayerPrivateQTKit::setPreservesPitch(bool preservesPitch) { if (!m_qtMovie) return; @@ -876,7 +904,7 @@ void MediaPlayerPrivate::setPreservesPitch(bool preservesPitch) createQTMovie([movieAttributes valueForKey:QTMovieURLAttribute], movieAttributes); } -PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const +PassRefPtr<TimeRanges> MediaPlayerPrivateQTKit::buffered() const { RefPtr<TimeRanges> timeRanges = TimeRanges::create(); float loaded = maxTimeLoaded(); @@ -885,7 +913,7 @@ PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const return timeRanges.release(); } -float MediaPlayerPrivate::maxTimeSeekable() const +float MediaPlayerPrivateQTKit::maxTimeSeekable() const { if (!metaDataAvailable()) return 0; @@ -897,14 +925,14 @@ float MediaPlayerPrivate::maxTimeSeekable() const return wkQTMovieMaxTimeSeekable(m_qtMovie.get()); } -float MediaPlayerPrivate::maxTimeLoaded() const +float MediaPlayerPrivateQTKit::maxTimeLoaded() const { if (!metaDataAvailable()) return 0; return wkQTMovieMaxTimeLoaded(m_qtMovie.get()); } -unsigned MediaPlayerPrivate::bytesLoaded() const +unsigned MediaPlayerPrivateQTKit::bytesLoaded() const { float dur = duration(); if (!dur) @@ -912,14 +940,14 @@ unsigned MediaPlayerPrivate::bytesLoaded() const return totalBytes() * maxTimeLoaded() / dur; } -unsigned MediaPlayerPrivate::totalBytes() const +unsigned MediaPlayerPrivateQTKit::totalBytes() const { if (!metaDataAvailable()) return 0; return [[m_qtMovie.get() attributeForKey:QTMovieDataSizeAttribute] intValue]; } -void MediaPlayerPrivate::cancelLoad() +void MediaPlayerPrivateQTKit::cancelLoad() { // FIXME: Is there a better way to check for this? if (m_networkState < MediaPlayer::Loading || m_networkState == MediaPlayer::Loaded) @@ -931,7 +959,7 @@ void MediaPlayerPrivate::cancelLoad() updateStates(); } -void MediaPlayerPrivate::cacheMovieScale() +void MediaPlayerPrivateQTKit::cacheMovieScale() { NSSize initialSize = NSZeroSize; NSSize naturalSize = [[m_qtMovie.get() attributeForKey:QTMovieNaturalSizeAttribute] sizeValue]; @@ -956,12 +984,12 @@ void MediaPlayerPrivate::cacheMovieScale() m_scaleFactor.setHeight(initialSize.height / naturalSize.height); } -bool MediaPlayerPrivate::isReadyForVideoSetup() const +bool MediaPlayerPrivateQTKit::isReadyForVideoSetup() const { return m_readyState >= MediaPlayer::HaveMetadata && m_player->visible(); } -void MediaPlayerPrivate::prepareForRendering() +void MediaPlayerPrivateQTKit::prepareForRendering() { if (m_isAllowedToRender) return; @@ -976,7 +1004,7 @@ void MediaPlayerPrivate::prepareForRendering() m_player->mediaPlayerClient()->mediaPlayerRenderingModeChanged(m_player); } -void MediaPlayerPrivate::updateStates() +void MediaPlayerPrivateQTKit::updateStates() { MediaPlayer::NetworkState oldNetworkState = m_networkState; MediaPlayer::ReadyState oldReadyState = m_readyState; @@ -1091,13 +1119,13 @@ void MediaPlayerPrivate::updateStates() } } -void MediaPlayerPrivate::loadStateChanged() +void MediaPlayerPrivateQTKit::loadStateChanged() { if (!m_hasUnsupportedTracks) updateStates(); } -void MediaPlayerPrivate::rateChanged() +void MediaPlayerPrivateQTKit::rateChanged() { if (m_hasUnsupportedTracks) return; @@ -1106,13 +1134,13 @@ void MediaPlayerPrivate::rateChanged() m_player->rateChanged(); } -void MediaPlayerPrivate::sizeChanged() +void MediaPlayerPrivateQTKit::sizeChanged() { if (!m_hasUnsupportedTracks) m_player->sizeChanged(); } -void MediaPlayerPrivate::timeChanged() +void MediaPlayerPrivateQTKit::timeChanged() { if (m_hasUnsupportedTracks) return; @@ -1128,7 +1156,7 @@ void MediaPlayerPrivate::timeChanged() m_player->timeChanged(); } -void MediaPlayerPrivate::didEnd() +void MediaPlayerPrivateQTKit::didEnd() { if (m_hasUnsupportedTracks) return; @@ -1150,7 +1178,7 @@ void MediaPlayerPrivate::didEnd() m_player->timeChanged(); } -void MediaPlayerPrivate::setSize(const IntSize&) +void MediaPlayerPrivateQTKit::setSize(const IntSize&) { // Don't resize the view now because [view setFrame] also resizes the movie itself, and because // the renderer calls this function immediately when we report a size change (QTMovieSizeDidChangeNotification) @@ -1161,7 +1189,7 @@ void MediaPlayerPrivate::setSize(const IntSize&) // <rdar://problem/6336092> REGRESSION: rtsp movie does not resize correctly } -void MediaPlayerPrivate::setVisible(bool b) +void MediaPlayerPrivateQTKit::setVisible(bool b) { if (m_visible != b) { m_visible = b; @@ -1172,7 +1200,7 @@ void MediaPlayerPrivate::setVisible(bool b) } } -bool MediaPlayerPrivate::hasAvailableVideoFrame() const +bool MediaPlayerPrivateQTKit::hasAvailableVideoFrame() const { // When using a QTMovieLayer return true as soon as the movie reaches QTMovieLoadStatePlayable // because although we don't *know* when the first frame has decoded, by the time we get and @@ -1186,7 +1214,7 @@ bool MediaPlayerPrivate::hasAvailableVideoFrame() const return m_videoFrameHasDrawn; } -void MediaPlayerPrivate::repaint() +void MediaPlayerPrivateQTKit::repaint() { if (m_hasUnsupportedTracks) return; @@ -1204,7 +1232,7 @@ void MediaPlayerPrivate::repaint() m_player->repaint(); } -void MediaPlayerPrivate::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& r) +void MediaPlayerPrivateQTKit::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& r) { id qtVideoRenderer = m_qtVideoRenderer.get(); if (!qtVideoRenderer && currentRenderingMode() == MediaRenderingMovieLayer) { @@ -1218,7 +1246,7 @@ void MediaPlayerPrivate::paintCurrentFrameInContext(GraphicsContext* context, co paint(context, r); } -void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& r) +void MediaPlayerPrivateQTKit::paint(GraphicsContext* context, const IntRect& r) { if (context->paintingDisabled() || m_hasUnsupportedTracks) return; @@ -1355,7 +1383,7 @@ static HashSet<String> mimeModernTypesCache() return cache; } -void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& supportedTypes) +void MediaPlayerPrivateQTKit::getSupportedTypes(HashSet<String>& supportedTypes) { supportedTypes = mimeModernTypesCache(); @@ -1368,7 +1396,7 @@ void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& supportedTypes) supportedTypes.add(*it); } -MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs) +MediaPlayer::SupportsType MediaPlayerPrivateQTKit::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 QT if it supports an // extended MIME type yet. @@ -1380,7 +1408,7 @@ MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, c return MediaPlayer::IsNotSupported; } -bool MediaPlayerPrivate::isAvailable() +bool MediaPlayerPrivateQTKit::isAvailable() { #ifdef BUILDING_ON_TIGER SInt32 version; @@ -1401,7 +1429,7 @@ bool MediaPlayerPrivate::isAvailable() #endif } -void MediaPlayerPrivate::disableUnsupportedTracks() +void MediaPlayerPrivateQTKit::disableUnsupportedTracks() { if (!m_qtMovie) { m_enabledTrackCount = 0; @@ -1491,35 +1519,35 @@ void MediaPlayerPrivate::disableUnsupportedTracks() } } -void MediaPlayerPrivate::sawUnsupportedTracks() +void MediaPlayerPrivateQTKit::sawUnsupportedTracks() { m_hasUnsupportedTracks = true; m_player->mediaPlayerClient()->mediaPlayerSawUnsupportedTracks(m_player); } #if USE(ACCELERATED_COMPOSITING) -bool MediaPlayerPrivate::supportsAcceleratedRendering() const +bool MediaPlayerPrivateQTKit::supportsAcceleratedRendering() const { // Also don't claim to support accelerated rendering when in the media document, as we will then render // via QTMovieView which is already accelerated. return isReadyForVideoSetup() && getQTMovieLayerClass() != Nil && !m_player->inMediaDocument(); } -void MediaPlayerPrivate::acceleratedRenderingStateChanged() +void MediaPlayerPrivateQTKit::acceleratedRenderingStateChanged() { // Set up or change the rendering path if necessary. setUpVideoRendering(); } #endif -bool MediaPlayerPrivate::hasSingleSecurityOrigin() const +bool MediaPlayerPrivateQTKit::hasSingleSecurityOrigin() const { // We tell quicktime to disallow resources that come from different origins // so we know all media is single origin. return true; } -MediaPlayer::MovieLoadType MediaPlayerPrivate::movieLoadType() const +MediaPlayer::MovieLoadType MediaPlayerPrivateQTKit::movieLoadType() const { if (!m_qtMovie) return MediaPlayer::Unknown; @@ -1533,14 +1561,14 @@ MediaPlayer::MovieLoadType MediaPlayerPrivate::movieLoadType() const return movieType; } -void MediaPlayerPrivate::setPreload(MediaPlayer::Preload preload) +void MediaPlayerPrivateQTKit::setPreload(MediaPlayer::Preload preload) { m_preload = preload; if (m_delayingLoad && m_preload != MediaPlayer::None) resumeLoad(); } -float MediaPlayerPrivate::mediaTimeForTimeValue(float timeValue) const +float MediaPlayerPrivateQTKit::mediaTimeForTimeValue(float timeValue) const { if (!metaDataAvailable()) return timeValue; @@ -1553,7 +1581,7 @@ float MediaPlayerPrivate::mediaTimeForTimeValue(float timeValue) const @implementation WebCoreMovieObserver -- (id)initWithCallback:(MediaPlayerPrivate*)callback +- (id)initWithCallback:(MediaPlayerPrivateQTKit*)callback { m_callback = callback; return [super init]; diff --git a/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp b/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp index 01d75ee..db6de49 100644 --- a/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp +++ b/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp @@ -47,7 +47,7 @@ CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typese if (!addResult.second) return attributesDictionary.get(); - bool allowLigatures = platformData().allowsLigatures() || (typesettingFeatures & Ligatures); + bool allowLigatures = (orientation() == Horizontal && platformData().allowsLigatures()) || (typesettingFeatures & Ligatures); static const int ligaturesNotAllowedValue = 0; static CFNumberRef ligaturesNotAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesNotAllowedValue); @@ -60,14 +60,14 @@ 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, platformData().orientation() == Vertical ? kCFBooleanTrue : kCFBooleanFalse }; + ? ligaturesAllowed : ligaturesNotAllowed, orientation() == Vertical ? kCFBooleanTrue : kCFBooleanFalse }; attributesDictionary.adoptCF(CFDictionaryCreate(0, keysWithKerningDisabled, valuesWithKerningDisabled, sizeof(keysWithKerningDisabled) / sizeof(*keysWithKerningDisabled), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); } else { // By omitting the kCTKernAttributeName attribute, we get Core Text's standard kerning. static const void* keysWithKerningEnabled[] = { kCTFontAttributeName, kCTLigatureAttributeName, kCTVerticalFormsAttributeName }; - const void* valuesWithKerningEnabled[] = { platformData().ctFont(), allowLigatures ? ligaturesAllowed : ligaturesNotAllowed, platformData().orientation() == Vertical ? kCFBooleanTrue : kCFBooleanFalse }; + const void* valuesWithKerningEnabled[] = { platformData().ctFont(), allowLigatures ? ligaturesAllowed : ligaturesNotAllowed, orientation() == Vertical ? kCFBooleanTrue : kCFBooleanFalse }; attributesDictionary.adoptCF(CFDictionaryCreate(0, keysWithKerningEnabled, valuesWithKerningEnabled, sizeof(keysWithKerningEnabled) / sizeof(*keysWithKerningEnabled), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm index fd57630..e1d3f43 100644 --- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm +++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm @@ -260,6 +260,24 @@ void SimpleFontData::platformInit() m_descent = 3; } + if (m_orientation == Vertical) { + // Ignore vertical orientation when the font doesn't support vertical metrics. + // 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; + break; + } + } + + if (found == false) + m_orientation = Horizontal; + } + // 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(); @@ -339,6 +357,11 @@ void SimpleFontData::platformCharWidthInit() void SimpleFontData::platformDestroy() { + if (m_smallCapsFontData && !isCustomFont()) { + fontCache()->releaseFontData(m_smallCapsFontData); + m_smallCapsFontData = 0; + } + #ifdef BUILDING_ON_TIGER if (m_styleGroup) wkReleaseStyleGroup(m_styleGroup); @@ -359,8 +382,8 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes m_smallCapsFontData = new SimpleFontData(smallCapsFontData, true, false); } else { BEGIN_BLOCK_OBJC_EXCEPTIONS; - float size = [m_platformData.font() pointSize] * smallCapsFontSizeMultiplier; - FontPlatformData smallCapsFont([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toSize:size]); + float size = m_platformData.size() * smallCapsFontSizeMultiplier; + FontPlatformData smallCapsFont([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toSize:size], size); // AppKit resets the type information (screen/printer) when you convert a font to a different size. // We have to fix up the font that we're handed back. @@ -423,7 +446,7 @@ FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const FloatRect boundingBox; #ifndef BUILDING_ON_TIGER boundingBox = CTFontGetBoundingRectsForGlyphs(m_platformData.ctFont(), - m_platformData.orientation() == Vertical ? kCTFontVerticalOrientation : kCTFontHorizontalOrientation, &glyph, 0, 1); + orientation() == Vertical ? kCTFontVerticalOrientation : kCTFontHorizontalOrientation, &glyph, 0, 1); boundingBox.setY(-boundingBox.bottom()); #else // FIXME: Custom fonts don't have NSFonts, so this function doesn't compute correct bounds for these on Tiger. @@ -441,7 +464,7 @@ FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { CGSize advance; - if (m_platformData.orientation() == Horizontal) { + if (orientation() == Horizontal || m_isBrokenIdeographFont) { NSFont* font = platformData().font(); float pointSize = platformData().m_size; CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize); diff --git a/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp b/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp index 8c62e9d..a6fa5d9 100644 --- a/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp +++ b/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp @@ -69,6 +69,14 @@ bool Extensions3DOpenGL::supports(const String& name) m_availableExtensions.add(availableExtensions[i]); m_initializedAvailableExtensions = true; } + + // GL_ANGLE_framebuffer_blit and GL_ANGLE_framebuffer_multisample are "fake". They are implemented using other + // extensions. In particular GL_EXT_framebuffer_blit and GL_EXT_framebuffer_multisample + if (name == "GL_ANGLE_framebuffer_blit") + return m_availableExtensions.contains("GL_EXT_framebuffer_blit"); + if (name == "GL_ANGLE_framebuffer_multisample") + return m_availableExtensions.contains("GL_EXT_framebuffer_multisample"); + return m_availableExtensions.contains(name); } @@ -77,6 +85,16 @@ int Extensions3DOpenGL::getGraphicsResetStatusARB() return GraphicsContext3D::NO_ERROR; } +void Extensions3DOpenGL::blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter) +{ + ::glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); +} + +void Extensions3DOpenGL::renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height) +{ + ::glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height); +} + } // namespace WebCore #endif // ENABLE(3D_CANVAS) diff --git a/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h b/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h index 1b333b2..0fbe022 100644 --- a/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h +++ b/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h @@ -41,6 +41,8 @@ public: // Extensions3D methods. virtual bool supports(const String&); virtual int getGraphicsResetStatusARB(); + virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter); + virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height); private: // This class only needs to be instantiated by GraphicsContext3D implementations. diff --git a/WebCore/platform/graphics/gtk/FontCachePango.cpp b/WebCore/platform/graphics/pango/FontCachePango.cpp index fad29e0..fad29e0 100644 --- a/WebCore/platform/graphics/gtk/FontCachePango.cpp +++ b/WebCore/platform/graphics/pango/FontCachePango.cpp diff --git a/WebCore/platform/graphics/gtk/FontCustomPlatformDataPango.cpp b/WebCore/platform/graphics/pango/FontCustomPlatformDataPango.cpp index a158689..a158689 100644 --- a/WebCore/platform/graphics/gtk/FontCustomPlatformDataPango.cpp +++ b/WebCore/platform/graphics/pango/FontCustomPlatformDataPango.cpp diff --git a/WebCore/platform/graphics/gtk/FontPlatformDataPango.h b/WebCore/platform/graphics/pango/FontPlatformData.h index c42af7f..2929a3f 100644 --- a/WebCore/platform/graphics/gtk/FontPlatformDataPango.h +++ b/WebCore/platform/graphics/pango/FontPlatformData.h @@ -26,6 +26,7 @@ #define FontPlatformDataPango_h #include "FontDescription.h" +#include "FontOrientation.h" #include "GlyphBuffer.h" #include <cairo.h> #include <pango/pangocairo.h> @@ -66,6 +67,8 @@ public: 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 diff --git a/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp b/WebCore/platform/graphics/pango/FontPlatformDataPango.cpp index 59cd3da..03dc33d 100644 --- a/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp +++ b/WebCore/platform/graphics/pango/FontPlatformDataPango.cpp @@ -39,7 +39,6 @@ #include <cairo-ft.h> #include <pango/pangofc-fontmap.h> #endif -#include <gtk/gtk.h> namespace WebCore { diff --git a/WebCore/platform/graphics/gtk/GlyphPageTreeNodePango.cpp b/WebCore/platform/graphics/pango/GlyphPageTreeNodePango.cpp index 8d0baa6..8d0baa6 100644 --- a/WebCore/platform/graphics/gtk/GlyphPageTreeNodePango.cpp +++ b/WebCore/platform/graphics/pango/GlyphPageTreeNodePango.cpp diff --git a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp b/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp index bdfe237..bdfe237 100644 --- a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp +++ b/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp diff --git a/WebCore/platform/graphics/qt/FontPlatformData.h b/WebCore/platform/graphics/qt/FontPlatformData.h index 79daa6b..2201f18 100644 --- a/WebCore/platform/graphics/qt/FontPlatformData.h +++ b/WebCore/platform/graphics/qt/FontPlatformData.h @@ -26,6 +26,7 @@ #include <wtf/Forward.h> #include "FontDescription.h" +#include "FontOrientation.h" #include <QFont> #include <QHash> @@ -153,6 +154,9 @@ public: return m_data->font.pixelSize(); return 0; } + + FontOrientation orientation() const { return Horizontal; } // FIXME: Implement. + unsigned hash() const; #ifndef NDEBUG diff --git a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp index 26db220..2ba358f 100644 --- a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp @@ -1646,8 +1646,10 @@ bool GraphicsContext3D::getImageData(Image* image, unsigned int format, unsigned int type, bool premultiplyAlpha, + bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector) { + UNUSED_PARAM(ignoreGammaAndColorProfile); if (!image) return false; QPixmap* nativePixmap = image->nativeImageForCurrentFrame(); diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 4f68577..06e1e1c 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -220,8 +220,11 @@ public: #endif } + void takeOwnershipOfPlatformContext() { platformContextIsOwned = true; } + private: QPainter* painter; + bool platformContextIsOwned; }; @@ -231,6 +234,7 @@ GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p, cons , solidColor(initialSolidColor) , imageInterpolationQuality(InterpolationDefault) , painter(p) + , platformContextIsOwned(false) { if (!painter) return; @@ -243,6 +247,13 @@ GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p, cons GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate() { + if (!platformContextIsOwned) + return; + + painter->end(); + QPaintDevice* device = painter->device(); + delete painter; + delete device; } GraphicsContext::GraphicsContext(PlatformGraphicsContext* painter) @@ -1400,6 +1411,11 @@ InterpolationQuality GraphicsContext::imageInterpolationQuality() const return m_data->imageInterpolationQuality; } +void GraphicsContext::takeOwnershipOfPlatformContext() +{ + m_data->takeOwnershipOfPlatformContext(); +} + } // vim: ts=4 sw=4 et diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp index 02bb110..2dd239f 100644 --- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp +++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp @@ -37,17 +37,17 @@ namespace WebCore { -ImageDecoder* ImageDecoder::create(const SharedBuffer& data, bool premultiplyAlpha) +ImageDecoder* ImageDecoder::create(const SharedBuffer& data, bool premultiplyAlpha, bool ignoreGammaAndColorProfile) { // We need at least 4 bytes to figure out what kind of image we're dealing with. if (data.size() < 4) return 0; - return new ImageDecoderQt(premultiplyAlpha); + return new ImageDecoderQt(premultiplyAlpha, ignoreGammaAndColorProfile); } -ImageDecoderQt::ImageDecoderQt(bool premultiplyAlpha) - : ImageDecoder(premultiplyAlpha) +ImageDecoderQt::ImageDecoderQt(bool premultiplyAlpha, bool ignoreGammaAndColorProfile) + : ImageDecoder(premultiplyAlpha, ignoreGammaAndColorProfile) , m_repetitionCount(cAnimationNone) { } diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.h b/WebCore/platform/graphics/qt/ImageDecoderQt.h index 5014d53..914c020 100644 --- a/WebCore/platform/graphics/qt/ImageDecoderQt.h +++ b/WebCore/platform/graphics/qt/ImageDecoderQt.h @@ -41,7 +41,7 @@ namespace WebCore { class ImageDecoderQt : public ImageDecoder { public: - ImageDecoderQt(bool premultiplyAlpha); + ImageDecoderQt(bool premultiplyAlpha, bool ignoreGammaAndColorProfile); ~ImageDecoderQt(); virtual void setData(SharedBuffer* data, bool allDataReceived); diff --git a/WebCore/platform/graphics/qt/ImageQt.cpp b/WebCore/platform/graphics/qt/ImageQt.cpp index c0cfae4..7b46b71 100644 --- a/WebCore/platform/graphics/qt/ImageQt.cpp +++ b/WebCore/platform/graphics/qt/ImageQt.cpp @@ -102,20 +102,31 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const if (!framePixmap) // If it's too early we won't have an image yet. return; + QRectF dr = QRectF(destRect).normalized(); + if (!dr.width() || !dr.height()) // Qt interprets 0 width/height as full width/height so just short circuit. + return; + QPixmap pixmap = *framePixmap; - QRect tr = QRectF(tileRect).toRect(); + QRect tr = QRectF(tileRect).toRect().normalized(); if (tr.x() || tr.y() || tr.width() != pixmap.width() || tr.height() != pixmap.height()) pixmap = pixmap.copy(tr); - QBrush b(pixmap); - b.setTransform(patternTransform); ctxt->save(); + ctxt->setCompositeOperation(op); QPainter* p = ctxt->platformContext(); if (!pixmap.hasAlpha() && p->compositionMode() == QPainter::CompositionMode_SourceOver) p->setCompositionMode(QPainter::CompositionMode_Source); - p->setBrushOrigin(phase); - p->fillRect(destRect, b); + + /* Translate the coordinates as phase is not in world matrix coordinate space but the tile rect origin is. */ + QTransform transform(patternTransform); + transform *= QTransform().translate(phase.x(), phase.y()); + transform.translate(tr.x(), tr.y()); + + QBrush b(pixmap); + b.setTransform(transform); + p->fillRect(dr, b); + ctxt->restore(); if (imageObserver()) diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp index b686fef..571b405 100644 --- a/WebCore/platform/graphics/qt/PathQt.cpp +++ b/WebCore/platform/graphics/qt/PathQt.cpp @@ -290,12 +290,15 @@ void Path::addArc(const FloatPoint& p, float r, float sar, float ear, bool antic double width = radius*2; double height = radius*2; - if ((!anticlockwise && (ea - sa >= 360)) || (anticlockwise && (sa - ea >= 360))) + if ((!anticlockwise && (ea - sa >= 360)) || (anticlockwise && (sa - ea >= 360))) { // If the anticlockwise argument is false and endAngle-startAngle is equal to or greater than 2*PI, or, if the // anticlockwise argument is true and startAngle-endAngle is equal to or greater than 2*PI, then the arc is the whole // circumference of this circle. span = 360; - else { + + if (anticlockwise) + span = -span; + } else { if (!anticlockwise && (ea < sa)) span += 360; else if (anticlockwise && (sa < ea)) diff --git a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp index d0dafb1..cbe6775 100644 --- a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp @@ -33,6 +33,8 @@ #include "Image.h" #include "ImageSource.h" #include "NativeImageSkia.h" +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> #include <algorithm> @@ -42,6 +44,7 @@ bool GraphicsContext3D::getImageData(Image* image, unsigned int format, unsigned int type, bool premultiplyAlpha, + bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector) { if (!image) @@ -50,12 +53,12 @@ bool GraphicsContext3D::getImageData(Image* image, NativeImageSkia* skiaImage = 0; AlphaOp neededAlphaOp = AlphaDoNothing; if (image->data()) { - ImageSource decoder(false); + ImageSource decoder(false, ignoreGammaAndColorProfile); decoder.setData(image->data(), true); if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0)) return false; bool hasAlpha = decoder.frameHasAlphaAtIndex(0); - pixels = decoder.createFrameAtIndex(0); + pixels = adoptPtr(decoder.createFrameAtIndex(0)); if (!pixels.get() || !pixels->isDataComplete() || !pixels->width() || !pixels->height()) return false; SkBitmap::Config skiaConfig = pixels->config(); diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp index 143d667..0db96cf 100644 --- a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp +++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp @@ -111,7 +111,7 @@ void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, con if (m_data.m_platformContext.useGPU() && context->platformContext()->useGPU()) { if (context->platformContext()->canAccelerate()) { DrawingBuffer* sourceDrawingBuffer = m_data.m_platformContext.gpuCanvas()->drawingBuffer(); - unsigned sourceTexture = sourceDrawingBuffer->getRenderingResultsAsTexture(); + unsigned sourceTexture = static_cast<unsigned>(sourceDrawingBuffer->platformColorBuffer()); FloatRect destRectFlipped(destRect); destRectFlipped.setY(destRect.y() + destRect.height()); destRectFlipped.setHeight(-destRect.height()); @@ -238,6 +238,14 @@ PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect return getImageData<Premultiplied>(rect, *context()->platformContext()->bitmap(), m_size); } +// This function does the equivalent of (a * b + 254) / 255, without an integer divide. +// Valid for a, b in the range [0..255]. +unsigned mulDiv255Ceil(unsigned a, unsigned b) +{ + unsigned value = a * b + 255; + return (value + (value >> 8)) >> 8; +} + template <Multiply multiplied> void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint, const SkBitmap& bitmap, const IntSize& size) @@ -279,10 +287,13 @@ void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& uint32_t* destRow = bitmap.getAddr32(destX, destY + y); for (int x = 0; x < numColumns; ++x) { const unsigned char* srcPixel = &srcRow[x * 4]; - if (multiplied == Unmultiplied) - destRow[x] = SkPreMultiplyARGB(srcPixel[3], srcPixel[0], - srcPixel[1], srcPixel[2]); - else + if (multiplied == Unmultiplied) { + unsigned char alpha = srcPixel[3]; + unsigned char r = mulDiv255Ceil(srcPixel[0], alpha); + unsigned char g = mulDiv255Ceil(srcPixel[1], alpha); + unsigned char b = mulDiv255Ceil(srcPixel[2], alpha); + destRow[x] = SkPackARGB32(alpha, r, g, b); + } else destRow[x] = SkPackARGB32(srcPixel[3], srcPixel[0], srcPixel[1], srcPixel[2]); } diff --git a/WebCore/platform/graphics/transforms/TransformOperations.h b/WebCore/platform/graphics/transforms/TransformOperations.h index 08efd23..c0da377 100644 --- a/WebCore/platform/graphics/transforms/TransformOperations.h +++ b/WebCore/platform/graphics/transforms/TransformOperations.h @@ -57,6 +57,11 @@ public: return false; } + void clear() + { + m_operations.clear(); + } + Vector<RefPtr<TransformOperation> >& operations() { return m_operations; } const Vector<RefPtr<TransformOperation> >& operations() const { return m_operations; } diff --git a/WebCore/platform/graphics/win/SimpleFontDataWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp index 7010c8a..6d1d777 100644 --- a/WebCore/platform/graphics/win/SimpleFontDataWin.cpp +++ b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp @@ -65,6 +65,18 @@ bool SimpleFontData::shouldApplyMacAscentHack() void SimpleFontData::initGDIFont() { + if (!m_platformData.size()) { + m_ascent = 0; + m_descent = 0; + m_lineGap = 0; + m_lineSpacing = 0; + m_avgCharWidth = 0; + m_maxCharWidth = 0; + m_xHeight = 0; + m_unitsPerEm = 0; + return; + } + HDC hdc = GetDC(0); HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont()); OUTLINETEXTMETRIC metrics; @@ -94,10 +106,6 @@ void SimpleFontData::initGDIFont() void SimpleFontData::platformDestroy() { - // We don't hash this on Win32, so it's effectively owned by us. - delete m_smallCapsFontData; - m_smallCapsFontData = 0; - ScriptFreeCache(&m_scriptCache); delete m_scriptFontProperties; } @@ -115,7 +123,8 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winfont); winfont.lfHeight = -lroundf(smallCapsHeight * (m_platformData.useGDI() ? 1 : 32)); HFONT hfont = CreateFontIndirect(&winfont); - m_smallCapsFontData = new SimpleFontData(FontPlatformData(hfont, smallCapsHeight, m_platformData.syntheticBold(), m_platformData.syntheticOblique(), m_platformData.useGDI())); + m_smallCapsFontData = new SimpleFontData(FontPlatformData(hfont, smallCapsHeight, m_platformData.syntheticBold(), m_platformData.syntheticOblique(), m_platformData.useGDI()), + isCustomFont(), false); } } return m_smallCapsFontData; diff --git a/WebCore/platform/graphics/win/UniscribeController.cpp b/WebCore/platform/graphics/win/UniscribeController.cpp index bceec2d..d0acac2 100644 --- a/WebCore/platform/graphics/win/UniscribeController.cpp +++ b/WebCore/platform/graphics/win/UniscribeController.cpp @@ -275,12 +275,15 @@ bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, const S for (int k = 0; k < len; k++) { UChar ch = *(str + k); - if (Font::treatAsSpace(ch)) { + bool treatAsSpace = Font::treatAsSpace(ch); + bool treatAsZeroWidthSpace = ch == zeroWidthSpace || Font::treatAsZeroWidthSpace(ch); + if (treatAsSpace || treatAsZeroWidthSpace) { // Substitute in the space glyph at the appropriate place in the glyphs // array. glyphs[clusters[k]] = fontData->spaceGlyph(); - advances[clusters[k]] = logicalSpaceWidth; - spaceCharacters[clusters[k]] = m_currentCharacter + k + item.iCharPos; + advances[clusters[k]] = treatAsSpace ? logicalSpaceWidth : 0; + if (treatAsSpace) + spaceCharacters[clusters[k]] = m_currentCharacter + k + item.iCharPos; } if (Font::isRoundingHackCharacter(ch)) @@ -335,7 +338,9 @@ bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, const S advance += m_font.letterSpacing(); // Handle justification and word-spacing. - if (glyph == fontData->spaceGlyph()) { + int characterIndex = spaceCharacters[k]; + // characterIndex is left at the initial value of -1 for glyphs that do not map back to treated-as-space characters. + if (characterIndex != -1) { // Account for padding. WebCore uses space padding to justify text. // We distribute the specified padding over the available spaces in the run. if (m_padding) { @@ -351,7 +356,6 @@ bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, const S } // Account for word-spacing. - int characterIndex = spaceCharacters[k]; if (characterIndex > 0 && !Font::treatAsSpace(*m_run.data(characterIndex - 1)) && m_font.wordSpacing()) advance += m_font.wordSpacing(); } diff --git a/WebCore/platform/graphics/win/FontPlatformDataCairoWin.h b/WebCore/platform/graphics/win/cairo/FontPlatformData.h index 05f9eab..05f9eab 100644 --- a/WebCore/platform/graphics/win/FontPlatformDataCairoWin.h +++ b/WebCore/platform/graphics/win/cairo/FontPlatformData.h diff --git a/WebCore/platform/graphics/wince/FontPlatformData.h b/WebCore/platform/graphics/wince/FontPlatformData.h index 4a174f0..e73a7b2 100644 --- a/WebCore/platform/graphics/wince/FontPlatformData.h +++ b/WebCore/platform/graphics/wince/FontPlatformData.h @@ -26,6 +26,7 @@ #define FontPlatformData_h #include "FontDescription.h" +#include "FontOrientation.h" #include <wtf/Forward.h> #include <wtf/Noncopyable.h> #include <wtf/text/StringImpl.h> @@ -77,6 +78,8 @@ namespace WebCore { static const String& defaultFontFamily(); static LONG adjustedGDIFontWeight(LONG gdiFontWeight, const String& family); + FontOrientation orientation() const { return Horizontal; } // FIXME: Implement. + #ifndef NDEBUG String description() const; #endif diff --git a/WebCore/platform/graphics/wx/FontPlatformData.h b/WebCore/platform/graphics/wx/FontPlatformData.h index b328545..9ae8b54 100644 --- a/WebCore/platform/graphics/wx/FontPlatformData.h +++ b/WebCore/platform/graphics/wx/FontPlatformData.h @@ -30,6 +30,7 @@ #define FontPlatformData_h #include "FontDescription.h" +#include "FontOrientation.h" #include "StringImpl.h" #include <wtf/Forward.h> #include <wtf/RefPtr.h> @@ -147,6 +148,8 @@ public: bool allowsLigatures() const { return false; } + FontOrientation orientation() const { return Horizontal; } // FIXME: Implement. + #if OS(WINDOWS) bool useGDI() const; HFONT hfont() const; diff --git a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp index e899715..96129f9 100644 --- a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp +++ b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp @@ -79,9 +79,6 @@ void SimpleFontData::platformCharWidthInit() void SimpleFontData::platformDestroy() { - delete m_smallCapsFontData; - m_smallCapsFontData = 0; - #if OS(WINDOWS) if (m_scriptFontProperties) { delete m_scriptFontProperties; @@ -99,7 +96,7 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes FontDescription desc = FontDescription(fontDescription); desc.setSpecifiedSize(0.70f * fontDescription.computedSize()); FontPlatformData platformData(desc, desc.family().family()); - m_smallCapsFontData = new SimpleFontData(platformData); + m_smallCapsFontData = new SimpleFontData(platformData, isCustomFont(), false); } return m_smallCapsFontData; } |