summaryrefslogtreecommitdiff
path: root/Source/WebCore/platform
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-05-07 11:21:11 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-05-07 11:21:11 +0200
commit2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch)
tree988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/WebCore/platform
parentdd91e772430dc294e3bf478c119ef8d43c0a3358 (diff)
downloadqtwebkit-2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47.tar.gz
Imported WebKit commit 7e538425aa020340619e927792f3d895061fb54b (http://svn.webkit.org/repository/webkit/trunk@116286)
Diffstat (limited to 'Source/WebCore/platform')
-rw-r--r--Source/WebCore/platform/ActivePlatformGestureAnimation.cpp37
-rw-r--r--Source/WebCore/platform/ActivePlatformGestureAnimation.h7
-rw-r--r--Source/WebCore/platform/Arena.cpp226
-rw-r--r--Source/WebCore/platform/Arena.h78
-rw-r--r--Source/WebCore/platform/AsyncFileSystem.cpp10
-rw-r--r--Source/WebCore/platform/AsyncFileSystem.h23
-rwxr-xr-xSource/WebCore/platform/CalculationValue.h3
-rw-r--r--Source/WebCore/platform/ColorChooser.h4
-rw-r--r--Source/WebCore/platform/ColorChooserClient.h4
-rw-r--r--Source/WebCore/platform/ContextMenu.cpp4
-rw-r--r--Source/WebCore/platform/ContextMenu.h3
-rw-r--r--Source/WebCore/platform/ContextMenuItem.cpp4
-rw-r--r--Source/WebCore/platform/ContextMenuItem.h15
-rw-r--r--Source/WebCore/platform/Cursor.h6
-rw-r--r--Source/WebCore/platform/DragData.h2
-rw-r--r--Source/WebCore/platform/DragImage.h3
-rw-r--r--Source/WebCore/platform/FileChooser.cpp19
-rw-r--r--Source/WebCore/platform/FileChooser.h16
-rw-r--r--Source/WebCore/platform/FileSystemType.h61
-rw-r--r--Source/WebCore/platform/FractionalLayoutUnit.h79
-rw-r--r--Source/WebCore/platform/GeolocationService.cpp84
-rw-r--r--Source/WebCore/platform/GeolocationService.h79
-rw-r--r--Source/WebCore/platform/HistogramSupport.cpp4
-rw-r--r--Source/WebCore/platform/HistogramSupport.h1
-rw-r--r--Source/WebCore/platform/KURL.cpp42
-rw-r--r--Source/WebCore/platform/KURL.h3
-rw-r--r--Source/WebCore/platform/Length.h118
-rw-r--r--Source/WebCore/platform/LocalizedStrings.cpp13
-rw-r--r--Source/WebCore/platform/LocalizedStrings.h19
-rw-r--r--Source/WebCore/platform/Logging.cpp5
-rw-r--r--Source/WebCore/platform/Logging.h1
-rwxr-xr-x[-rw-r--r--]Source/WebCore/platform/MIMETypeRegistry.cpp88
-rw-r--r--Source/WebCore/platform/MIMETypeRegistry.h4
-rw-r--r--Source/WebCore/platform/MemoryUsageSupport.cpp (renamed from Source/WebCore/platform/graphics/chromium/VideoFrameChromium.cpp)42
-rw-r--r--Source/WebCore/platform/MemoryUsageSupport.h (renamed from Source/WebCore/platform/graphics/chromium/VideoFrameProvider.h)46
-rw-r--r--Source/WebCore/platform/Pasteboard.h8
-rw-r--r--Source/WebCore/platform/PasteboardStrategy.h3
-rw-r--r--Source/WebCore/platform/PlatformEvent.h4
-rw-r--r--Source/WebCore/platform/PlatformGestureCurve.h3
-rw-r--r--Source/WebCore/platform/PlatformGestureCurveTarget.h4
-rw-r--r--Source/WebCore/platform/PlatformGestureEvent.h15
-rw-r--r--Source/WebCore/platform/PlatformKeyboardEvent.h30
-rw-r--r--Source/WebCore/platform/PlatformMenuDescription.h2
-rw-r--r--Source/WebCore/platform/PlatformMouseEvent.h10
-rw-r--r--Source/WebCore/platform/PlatformPasteboard.h3
-rw-r--r--Source/WebCore/platform/PlatformTouchEvent.h33
-rw-r--r--Source/WebCore/platform/PlatformTouchPoint.h25
-rw-r--r--Source/WebCore/platform/ReferrerPolicy.h48
-rw-r--r--Source/WebCore/platform/RunLoop.h12
-rw-r--r--Source/WebCore/platform/ScrollAnimator.h2
-rw-r--r--Source/WebCore/platform/ScrollAnimatorNone.cpp71
-rw-r--r--Source/WebCore/platform/ScrollAnimatorNone.h25
-rw-r--r--Source/WebCore/platform/ScrollAnimatorWin.cpp310
-rw-r--r--Source/WebCore/platform/ScrollView.cpp19
-rw-r--r--Source/WebCore/platform/ScrollView.h3
-rw-r--r--Source/WebCore/platform/ScrollableArea.cpp45
-rw-r--r--Source/WebCore/platform/ScrollableArea.h18
-rw-r--r--Source/WebCore/platform/SharedBuffer.cpp6
-rw-r--r--Source/WebCore/platform/SharedBuffer.h2
-rw-r--r--Source/WebCore/platform/StatsCounter.cpp40
-rw-r--r--Source/WebCore/platform/StatsCounter.h43
-rw-r--r--Source/WebCore/platform/ThemeTypes.h4
-rw-r--r--Source/WebCore/platform/TouchFlingPlatformGestureCurve.cpp87
-rw-r--r--Source/WebCore/platform/TouchpadFlingPlatformGestureCurve.cpp155
-rw-r--r--Source/WebCore/platform/TouchpadFlingPlatformGestureCurve.h (renamed from Source/WebCore/platform/TouchFlingPlatformGestureCurve.h)25
-rw-r--r--Source/WebCore/platform/WheelFlingPlatformGestureCurve.cpp2
-rw-r--r--Source/WebCore/platform/WheelFlingPlatformGestureCurve.h1
-rw-r--r--Source/WebCore/platform/Widget.h10
-rw-r--r--Source/WebCore/platform/animation/Animation.cpp6
-rw-r--r--Source/WebCore/platform/animation/Animation.h30
-rw-r--r--Source/WebCore/platform/animation/AnimationUtilities.h13
-rw-r--r--Source/WebCore/platform/audio/AudioBus.cpp41
-rw-r--r--Source/WebCore/platform/audio/AudioBus.h6
-rw-r--r--Source/WebCore/platform/audio/AudioChannel.cpp32
-rw-r--r--Source/WebCore/platform/audio/AudioChannel.h29
-rw-r--r--Source/WebCore/platform/audio/AudioDSPKernel.h3
-rw-r--r--Source/WebCore/platform/audio/AudioDSPKernelProcessor.cpp12
-rw-r--r--Source/WebCore/platform/audio/AudioDSPKernelProcessor.h3
-rw-r--r--Source/WebCore/platform/audio/AudioProcessor.h3
-rw-r--r--Source/WebCore/platform/audio/AudioPullFIFO.cpp154
-rw-r--r--Source/WebCore/platform/audio/AudioPullFIFO.h90
-rw-r--r--Source/WebCore/platform/audio/DirectConvolver.cpp385
-rw-r--r--Source/WebCore/platform/audio/DirectConvolver.h59
-rw-r--r--Source/WebCore/platform/audio/DynamicsCompressor.h5
-rw-r--r--Source/WebCore/platform/audio/EqualPowerPanner.cpp80
-rw-r--r--Source/WebCore/platform/audio/EqualPowerPanner.h3
-rw-r--r--Source/WebCore/platform/audio/FFTConvolver.cpp86
-rw-r--r--Source/WebCore/platform/audio/HRTFElevation.cpp2
-rw-r--r--Source/WebCore/platform/audio/HRTFPanner.cpp15
-rw-r--r--Source/WebCore/platform/audio/HRTFPanner.h5
-rw-r--r--Source/WebCore/platform/audio/Panner.h3
-rw-r--r--Source/WebCore/platform/audio/Reverb.cpp10
-rw-r--r--Source/WebCore/platform/audio/Reverb.h3
-rw-r--r--Source/WebCore/platform/audio/ReverbConvolver.cpp22
-rw-r--r--Source/WebCore/platform/audio/ReverbConvolver.h2
-rw-r--r--Source/WebCore/platform/audio/ReverbConvolverStage.cpp41
-rw-r--r--Source/WebCore/platform/audio/ReverbConvolverStage.h12
-rw-r--r--Source/WebCore/platform/audio/chromium/AudioBusChromium.cpp8
-rw-r--r--Source/WebCore/platform/audio/efl/AudioBusEfl.cpp42
-rw-r--r--Source/WebCore/platform/audio/gstreamer/AudioDestinationGStreamer.cpp7
-rw-r--r--Source/WebCore/platform/audio/gstreamer/AudioFileReaderGStreamer.cpp140
-rw-r--r--Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp2
-rw-r--r--Source/WebCore/platform/audio/gtk/AudioBusGtk.cpp5
-rw-r--r--Source/WebCore/platform/blackberry/AsyncFileSystemBlackBerry.cpp196
-rw-r--r--Source/WebCore/platform/blackberry/AsyncFileSystemBlackBerry.h51
-rw-r--r--Source/WebCore/platform/blackberry/ClipboardBlackBerry.cpp22
-rw-r--r--Source/WebCore/platform/blackberry/ClipboardBlackBerry.h7
-rw-r--r--Source/WebCore/platform/blackberry/CookieDatabaseBackingStore/CookieDatabaseBackingStore.cpp6
-rw-r--r--Source/WebCore/platform/blackberry/CookieManager.cpp14
-rw-r--r--Source/WebCore/platform/blackberry/CookieManager.h2
-rw-r--r--Source/WebCore/platform/blackberry/CookieMap.cpp2
-rw-r--r--Source/WebCore/platform/blackberry/CookieMap.h4
-rw-r--r--Source/WebCore/platform/blackberry/CookieParser.cpp4
-rw-r--r--Source/WebCore/platform/blackberry/CookieParser.h2
-rw-r--r--Source/WebCore/platform/blackberry/DragImageBlackBerry.cpp2
-rw-r--r--Source/WebCore/platform/blackberry/EventLoopBlackBerry.cpp4
-rw-r--r--Source/WebCore/platform/blackberry/FileSystemBlackBerry.cpp5
-rw-r--r--Source/WebCore/platform/blackberry/LocalizedStringsBlackBerry.cpp6
-rw-r--r--Source/WebCore/platform/blackberry/MIMETypeRegistryBlackBerry.cpp2
-rw-r--r--Source/WebCore/platform/blackberry/PageClientBlackBerry.h16
-rw-r--r--Source/WebCore/platform/blackberry/ParsedCookie.cpp23
-rw-r--r--Source/WebCore/platform/blackberry/ParsedCookie.h6
-rw-r--r--Source/WebCore/platform/blackberry/PlatformKeyboardEventBlackBerry.cpp10
-rw-r--r--Source/WebCore/platform/blackberry/PlatformMouseEventBlackBerry.cpp20
-rw-r--r--Source/WebCore/platform/blackberry/PlatformTouchEventBlackBerry.cpp5
-rw-r--r--Source/WebCore/platform/blackberry/RenderThemeBlackBerry.cpp34
-rw-r--r--Source/WebCore/platform/blackberry/RenderThemeBlackBerry.h18
-rw-r--r--Source/WebCore/platform/blackberry/SSLKeyGeneratorBlackBerry.cpp2
-rw-r--r--Source/WebCore/platform/blackberry/ScrollAnimatorBlackBerry.cpp50
-rw-r--r--Source/WebCore/platform/blackberry/ScrollAnimatorBlackBerry.h33
-rw-r--r--Source/WebCore/platform/blackberry/SharedTimerBlackBerry.cpp2
-rw-r--r--Source/WebCore/platform/cf/BinaryPropertyList.cpp10
-rw-r--r--Source/WebCore/platform/cf/FileSystemCF.cpp10
-rw-r--r--Source/WebCore/platform/chromium/ChromiumDataObject.cpp349
-rw-r--r--Source/WebCore/platform/chromium/ChromiumDataObject.h104
-rw-r--r--Source/WebCore/platform/chromium/ChromiumDataObjectItem.cpp188
-rw-r--r--Source/WebCore/platform/chromium/ChromiumDataObjectItem.h97
-rw-r--r--Source/WebCore/platform/chromium/ClipboardChromium.cpp238
-rw-r--r--Source/WebCore/platform/chromium/ClipboardChromium.h39
-rw-r--r--Source/WebCore/platform/chromium/ClipboardUtilitiesChromium.cpp22
-rw-r--r--Source/WebCore/platform/chromium/ClipboardUtilitiesChromium.h1
-rw-r--r--Source/WebCore/platform/chromium/DataTransferItemChromium.cpp159
-rw-r--r--Source/WebCore/platform/chromium/DataTransferItemChromium.h84
-rw-r--r--Source/WebCore/platform/chromium/DataTransferItemListChromium.cpp170
-rw-r--r--Source/WebCore/platform/chromium/DragDataChromium.cpp19
-rw-r--r--Source/WebCore/platform/chromium/DragImageChromiumMac.cpp2
-rw-r--r--Source/WebCore/platform/chromium/DragImageChromiumSkia.cpp5
-rw-r--r--Source/WebCore/platform/chromium/GamepadsChromium.cpp23
-rw-r--r--Source/WebCore/platform/chromium/HistogramSupportChromium.cpp9
-rw-r--r--Source/WebCore/platform/chromium/KeyCodeConversionAndroid.cpp146
-rw-r--r--Source/WebCore/platform/chromium/KeyboardCodes.h6
-rw-r--r--Source/WebCore/platform/chromium/LanguageChromium.cpp4
-rw-r--r--Source/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp21
-rw-r--r--Source/WebCore/platform/chromium/MemoryUsageSupportChromium.cpp63
-rw-r--r--Source/WebCore/platform/chromium/PlatformCursor.h2
-rw-r--r--Source/WebCore/platform/chromium/PlatformSupport.h62
-rw-r--r--Source/WebCore/platform/chromium/PopupContainer.cpp86
-rw-r--r--Source/WebCore/platform/chromium/PopupContainer.h8
-rw-r--r--Source/WebCore/platform/chromium/PopupListBox.cpp44
-rw-r--r--Source/WebCore/platform/chromium/PopupListBox.h2
-rw-r--r--Source/WebCore/platform/chromium/PopupMenuChromium.cpp16
-rw-r--r--Source/WebCore/platform/chromium/PopupMenuChromium.h4
-rw-r--r--Source/WebCore/platform/chromium/PopupMenuPrivate.h2
-rw-r--r--Source/WebCore/platform/chromium/SSLKeyGeneratorChromium.cpp9
-rw-r--r--Source/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm7
-rw-r--r--Source/WebCore/platform/chromium/SharedTimerChromium.cpp4
-rw-r--r--Source/WebCore/platform/chromium/StatsCounterChromium.cpp43
-rw-r--r--Source/WebCore/platform/chromium/SuddenTerminationChromium.cpp6
-rw-r--r--Source/WebCore/platform/chromium/ThemeChromiumMac.mm25
-rw-r--r--Source/WebCore/platform/chromium/TraceEvent.h150
-rw-r--r--Source/WebCore/platform/chromium/WidgetChromium.cpp2
-rw-r--r--Source/WebCore/platform/chromium/support/WebAudioBus.cpp132
-rw-r--r--Source/WebCore/platform/chromium/support/WebData.cpp103
-rw-r--r--Source/WebCore/platform/chromium/support/WebFilterOperations.cpp79
-rw-r--r--Source/WebCore/platform/chromium/support/WebHTTPBody.cpp194
-rw-r--r--Source/WebCore/platform/chromium/support/WebHTTPLoadInfo.cpp147
-rw-r--r--Source/WebCore/platform/chromium/support/WebICECandidateDescriptor.cpp89
-rw-r--r--Source/WebCore/platform/chromium/support/WebICEOptions.cpp73
-rw-r--r--Source/WebCore/platform/chromium/support/WebMediaHints.cpp79
-rw-r--r--Source/WebCore/platform/chromium/support/WebMediaStreamComponent.cpp87
-rw-r--r--Source/WebCore/platform/chromium/support/WebMediaStreamDescriptor.cpp153
-rw-r--r--Source/WebCore/platform/chromium/support/WebMediaStreamSource.cpp (renamed from Source/WebCore/platform/chromium/DataTransferItemListChromium.h)92
-rw-r--r--Source/WebCore/platform/chromium/support/WebMediaStreamSourcesRequest.cpp88
-rwxr-xr-xSource/WebCore/platform/chromium/support/WebThreadSafeData.cpp75
-rw-r--r--Source/WebCore/platform/chromium/support/WebURL.cpp58
-rw-r--r--Source/WebCore/platform/chromium/support/WebURLError.cpp74
-rw-r--r--Source/WebCore/platform/chromium/support/WebURLRequest.cpp346
-rw-r--r--Source/WebCore/platform/chromium/support/WebURLRequestPrivate.h53
-rw-r--r--Source/WebCore/platform/chromium/support/WebURLResponse.cpp445
-rw-r--r--Source/WebCore/platform/chromium/support/WebURLResponsePrivate.h52
-rw-r--r--Source/WebCore/platform/chromium/support/WrappedResourceRequest.h80
-rw-r--r--Source/WebCore/platform/chromium/support/WrappedResourceResponse.h80
-rw-r--r--Source/WebCore/platform/clutter/GRefPtrClutter.h2
-rw-r--r--Source/WebCore/platform/efl/ColorChooserEfl.cpp61
-rw-r--r--Source/WebCore/platform/efl/ColorChooserEfl.h56
-rw-r--r--Source/WebCore/platform/efl/ContextMenuEfl.cpp4
-rw-r--r--Source/WebCore/platform/efl/ContextMenuItemEfl.cpp4
-rw-r--r--Source/WebCore/platform/efl/DragImageEfl.cpp2
-rw-r--r--Source/WebCore/platform/efl/EflKeyboardUtilities.cpp6
-rw-r--r--Source/WebCore/platform/efl/FileSystemEfl.cpp22
-rw-r--r--Source/WebCore/platform/efl/LocalizedStringsEfl.cpp5
-rw-r--r--Source/WebCore/platform/efl/RefPtrEfl.h2
-rw-r--r--Source/WebCore/platform/efl/RenderThemeEfl.cpp67
-rw-r--r--Source/WebCore/platform/efl/RenderThemeEfl.h30
-rw-r--r--Source/WebCore/platform/efl/RunLoopEfl.cpp108
-rw-r--r--Source/WebCore/platform/graphics/BitmapImage.cpp117
-rw-r--r--Source/WebCore/platform/graphics/BitmapImage.h67
-rw-r--r--Source/WebCore/platform/graphics/Color.h2
-rw-r--r--Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp11
-rw-r--r--Source/WebCore/platform/graphics/DisplayRefreshMonitor.h30
-rw-r--r--Source/WebCore/platform/graphics/FloatQuad.h7
-rw-r--r--Source/WebCore/platform/graphics/FloatRect.cpp7
-rw-r--r--Source/WebCore/platform/graphics/FloatRect.h2
-rw-r--r--Source/WebCore/platform/graphics/FloatSize.h5
-rw-r--r--Source/WebCore/platform/graphics/Font.cpp34
-rw-r--r--Source/WebCore/platform/graphics/Font.h18
-rw-r--r--Source/WebCore/platform/graphics/FontCache.h3
-rw-r--r--Source/WebCore/platform/graphics/FontDescription.cpp12
-rw-r--r--Source/WebCore/platform/graphics/FontDescription.h8
-rw-r--r--Source/WebCore/platform/graphics/FontPlatformData.cpp8
-rw-r--r--Source/WebCore/platform/graphics/FontPlatformData.h40
-rw-r--r--Source/WebCore/platform/graphics/FractionalLayoutPoint.h1
-rw-r--r--Source/WebCore/platform/graphics/FractionalLayoutRect.cpp4
-rw-r--r--Source/WebCore/platform/graphics/FractionalLayoutRect.h3
-rw-r--r--Source/WebCore/platform/graphics/Gradient.h3
-rw-r--r--Source/WebCore/platform/graphics/GraphicsContext.cpp82
-rw-r--r--Source/WebCore/platform/graphics/GraphicsContext.h37
-rw-r--r--Source/WebCore/platform/graphics/GraphicsContext3D.cpp8
-rw-r--r--Source/WebCore/platform/graphics/GraphicsContext3D.h8
-rw-r--r--Source/WebCore/platform/graphics/GraphicsLayer.cpp46
-rw-r--r--Source/WebCore/platform/graphics/GraphicsLayer.h11
-rw-r--r--Source/WebCore/platform/graphics/GraphicsLayerClient.h9
-rw-r--r--Source/WebCore/platform/graphics/ImageBuffer.cpp10
-rw-r--r--Source/WebCore/platform/graphics/ImageBuffer.h24
-rw-r--r--Source/WebCore/platform/graphics/ImageOrientation.cpp60
-rw-r--r--Source/WebCore/platform/graphics/ImageOrientation.h91
-rw-r--r--Source/WebCore/platform/graphics/ImageSource.cpp22
-rw-r--r--Source/WebCore/platform/graphics/ImageSource.h20
-rw-r--r--Source/WebCore/platform/graphics/IntPoint.h7
-rw-r--r--Source/WebCore/platform/graphics/IntRect.cpp29
-rw-r--r--Source/WebCore/platform/graphics/IntRect.h14
-rw-r--r--Source/WebCore/platform/graphics/IntSize.h29
-rw-r--r--Source/WebCore/platform/graphics/MediaPlayer.cpp108
-rw-r--r--Source/WebCore/platform/graphics/MediaPlayer.h42
-rw-r--r--Source/WebCore/platform/graphics/MediaPlayerPrivate.h13
-rw-r--r--Source/WebCore/platform/graphics/Path.cpp20
-rw-r--r--Source/WebCore/platform/graphics/Path.h15
-rw-r--r--Source/WebCore/platform/graphics/Pattern.h2
-rw-r--r--Source/WebCore/platform/graphics/Region.cpp35
-rw-r--r--Source/WebCore/platform/graphics/ShadowBlur.cpp2
-rw-r--r--Source/WebCore/platform/graphics/SimpleFontData.cpp15
-rw-r--r--Source/WebCore/platform/graphics/SimpleFontData.h18
-rw-r--r--Source/WebCore/platform/graphics/TextRun.cpp14
-rw-r--r--Source/WebCore/platform/graphics/TextRun.h35
-rw-r--r--Source/WebCore/platform/graphics/TiledBacking.h44
-rw-r--r--Source/WebCore/platform/graphics/TiledBackingStore.cpp26
-rw-r--r--Source/WebCore/platform/graphics/TiledBackingStore.h1
-rw-r--r--Source/WebCore/platform/graphics/TiledBackingStoreBackend.h2
-rw-r--r--Source/WebCore/platform/graphics/TiledBackingStoreClient.h1
-rw-r--r--Source/WebCore/platform/graphics/WOFFFileFormat.cpp10
-rw-r--r--Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp3
-rw-r--r--Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm2
-rw-r--r--Source/WebCore/platform/graphics/blackberry/CanvasLayerWebKitThread.cpp42
-rw-r--r--Source/WebCore/platform/graphics/blackberry/CanvasLayerWebKitThread.h15
-rw-r--r--Source/WebCore/platform/graphics/blackberry/DisplayRefreshMonitorBlackBerry.cpp91
-rw-r--r--Source/WebCore/platform/graphics/blackberry/DrawingBufferBlackBerry.cpp35
-rw-r--r--Source/WebCore/platform/graphics/blackberry/GraphicsContext3DBlackBerry.cpp11
-rw-r--r--Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp6
-rw-r--r--Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.h2
-rw-r--r--Source/WebCore/platform/graphics/blackberry/InstrumentedPlatformCanvas.h72
-rw-r--r--Source/WebCore/platform/graphics/blackberry/LayerAnimation.cpp316
-rw-r--r--Source/WebCore/platform/graphics/blackberry/LayerAnimation.h150
-rw-r--r--Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp511
-rw-r--r--Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.h213
-rw-r--r--Source/WebCore/platform/graphics/blackberry/LayerData.h19
-rw-r--r--Source/WebCore/platform/graphics/blackberry/LayerRenderer.cpp45
-rw-r--r--Source/WebCore/platform/graphics/blackberry/LayerTile.cpp4
-rw-r--r--Source/WebCore/platform/graphics/blackberry/LayerTile.h2
-rw-r--r--Source/WebCore/platform/graphics/blackberry/LayerTiler.cpp18
-rw-r--r--Source/WebCore/platform/graphics/blackberry/LayerTiler.h4
-rw-r--r--Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp6
-rw-r--r--Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.h2
-rw-r--r--Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp88
-rw-r--r--Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h5
-rw-r--r--Source/WebCore/platform/graphics/blackberry/Texture.h2
-rw-r--r--Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.cpp4
-rw-r--r--Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.h2
-rw-r--r--Source/WebCore/platform/graphics/blackberry/skia/ImageBufferDataSkia.h (renamed from Source/WebCore/platform/graphics/blackberry/skia/ImageBufferData.h)15
-rw-r--r--Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp188
-rw-r--r--Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h10
-rw-r--r--Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h4
-rw-r--r--Source/WebCore/platform/graphics/ca/PlatformCALayer.h2
-rw-r--r--Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h3
-rw-r--r--Source/WebCore/platform/graphics/ca/mac/LayerFlushSchedulerMac.cpp3
-rw-r--r--Source/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm23
-rw-r--r--Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm22
-rw-r--r--Source/WebCore/platform/graphics/ca/mac/TileCache.h27
-rw-r--r--Source/WebCore/platform/graphics/ca/mac/TileCache.mm197
-rw-r--r--Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.h4
-rw-r--r--Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm22
-rw-r--r--Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.cpp2
-rw-r--r--Source/WebCore/platform/graphics/ca/win/PlatformCAAnimationWin.cpp6
-rw-r--r--Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp3
-rw-r--r--Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp151
-rw-r--r--Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp6
-rw-r--r--Source/WebCore/platform/graphics/cairo/DrawingBufferCairo.cpp27
-rw-r--r--Source/WebCore/platform/graphics/cairo/FontCairo.cpp3
-rw-r--r--Source/WebCore/platform/graphics/cairo/GLContext.cpp68
-rw-r--r--Source/WebCore/platform/graphics/cairo/GLContext.h49
-rw-r--r--Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp4
-rw-r--r--Source/WebCore/platform/graphics/cairo/GraphicsContext3DPrivate.cpp8
-rw-r--r--Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp7
-rw-r--r--Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp52
-rw-r--r--Source/WebCore/platform/graphics/cairo/ImageCairo.cpp121
-rw-r--r--Source/WebCore/platform/graphics/cairo/NativeImageCairo.cpp50
-rw-r--r--Source/WebCore/platform/graphics/cairo/NativeImageCairo.h52
-rw-r--r--Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h4
-rw-r--r--Source/WebCore/platform/graphics/cairo/PatternCairo.cpp7
-rw-r--r--Source/WebCore/platform/graphics/cairo/RefPtrCairo.h2
-rw-r--r--Source/WebCore/platform/graphics/cairo/rgb24-hacks.txt32
-rw-r--r--Source/WebCore/platform/graphics/cairo/scale-removal.txt13
-rw-r--r--Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp58
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp130
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageBufferDataCG.cpp313
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h6
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageCG.cpp16
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp78
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageSourceCGWin.cpp2
-rw-r--r--Source/WebCore/platform/graphics/cg/PathCG.cpp23
-rw-r--r--Source/WebCore/platform/graphics/cg/PatternCG.cpp11
-rw-r--r--Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp7
-rw-r--r--Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp2
-rw-r--r--Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp129
-rw-r--r--Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h33
-rw-r--r--Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp6
-rw-r--r--Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.cpp14
-rw-r--r--Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp20
-rw-r--r--Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h13
-rw-r--r--Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm11
-rw-r--r--Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp141
-rw-r--r--Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h40
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontCacheAndroid.cpp61
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp4
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp9
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp2
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp4
-rw-r--r--Source/WebCore/platform/graphics/chromium/FrameBufferSkPictureCanvasLayerTextureUpdater.cpp2
-rw-r--r--Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp26
-rw-r--r--Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h6
-rw-r--r--Source/WebCore/platform/graphics/chromium/IOSurfaceLayerChromium.cpp77
-rw-r--r--Source/WebCore/platform/graphics/chromium/IOSurfaceLayerChromium.h (renamed from Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h)39
-rw-r--r--Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp6
-rw-r--r--Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h13
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerChromium.cpp225
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerChromium.h78
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp1015
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h215
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerTextureUpdater.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp103
-rw-r--r--Source/WebCore/platform/graphics/chromium/ProgramBinding.h3
-rw-r--r--Source/WebCore/platform/graphics/chromium/RateLimiter.cpp12
-rw-r--r--Source/WebCore/platform/graphics/chromium/RateLimiter.h16
-rw-r--r--Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp8
-rw-r--r--Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h35
-rw-r--r--Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp98
-rw-r--r--Source/WebCore/platform/graphics/chromium/ShaderChromium.h43
-rw-r--r--Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp12
-rw-r--r--Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/TextureCopier.cpp111
-rw-r--r--Source/WebCore/platform/graphics/chromium/TextureCopier.h75
-rw-r--r--Source/WebCore/platform/graphics/chromium/TextureLayerChromium.cpp133
-rw-r--r--Source/WebCore/platform/graphics/chromium/TextureLayerChromium.h104
-rw-r--r--Source/WebCore/platform/graphics/chromium/TextureManager.cpp41
-rw-r--r--Source/WebCore/platform/graphics/chromium/TextureManager.h3
-rw-r--r--Source/WebCore/platform/graphics/chromium/TextureUploader.cpp45
-rw-r--r--Source/WebCore/platform/graphics/chromium/TextureUploader.h59
-rw-r--r--Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp362
-rw-r--r--Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h48
-rw-r--r--Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp16
-rw-r--r--Source/WebCore/platform/graphics/chromium/TransparencyWin.h5
-rw-r--r--Source/WebCore/platform/graphics/chromium/TreeSynchronizer.cpp3
-rw-r--r--Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp36
-rw-r--r--Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp4
-rw-r--r--Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h13
-rw-r--r--Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp184
-rw-r--r--Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h86
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.cpp70
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.h46
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCActiveGestureAnimation.cpp21
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCActiveGestureAnimation.h7
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.cpp93
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.h68
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCCheckerboardDrawQuad.cpp42
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCCheckerboardDrawQuad.h45
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp94
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.h5
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCDebugRectHistory.cpp109
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCDebugRectHistory.h96
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCDelayBasedTimeSource.cpp46
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCDelayBasedTimeSource.h18
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.cpp33
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.h19
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCFontAtlas.cpp175
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCFontAtlas.h92
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.cpp4
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCFrameRateCounter.cpp134
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCFrameRateCounter.h81
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCGestureCurve.h11
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp237
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h53
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCIOSurfaceDrawQuad.cpp (renamed from Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.cpp)16
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCIOSurfaceDrawQuad.h (renamed from Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.h)29
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCIOSurfaceLayerImpl.cpp (renamed from Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp)53
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCIOSurfaceLayerImpl.h64
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCInputHandler.h12
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCKeyframedAnimationCurve.h12
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp323
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.h69
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp230
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.h97
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationDelegate.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp115
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h99
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerIterator.h21
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.cpp354
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.h58
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp6
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.h6
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp285
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h61
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp226
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.h28
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp336
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h83
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.cpp314
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.h68
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp335
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h69
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCOverdrawMetrics.cpp167
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCOverdrawMetrics.h106
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCPageScaleAnimation.cpp1
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h79
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCProxy.h18
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp130
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.h14
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.cpp64
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.h34
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp226
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.h84
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceDrawQuad.cpp7
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceDrawQuad.h6
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceFilters.cpp12
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp41
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCScheduler.h31
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp117
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h38
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.cpp11
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.h10
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCSharedQuadState.h1
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp66
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h56
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.cpp3
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.h6
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCTextureDrawQuad.cpp (renamed from Source/WebCore/platform/graphics/chromium/cc/CCCanvasDrawQuad.cpp)13
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCTextureDrawQuad.h (renamed from Source/WebCore/platform/graphics/chromium/cc/CCCanvasDrawQuad.h)19
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCTextureLayerImpl.cpp (renamed from Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp)28
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCTextureLayerImpl.h (renamed from Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h)35
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.cpp67
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.h37
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp290
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h106
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp63
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.h27
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCTimer.cpp6
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCTimer.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCTimingFunction.h6
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.cpp4
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.h12
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp113
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h49
-rw-r--r--Source/WebCore/platform/graphics/clutter/DrawingBufferClutter.cpp (renamed from Source/WebCore/platform/ScrollAnimatorWin.h)79
-rw-r--r--Source/WebCore/platform/graphics/clutter/GraphicsContext3DClutter.cpp103
-rw-r--r--Source/WebCore/platform/graphics/clutter/GraphicsContext3DPrivate.cpp64
-rw-r--r--Source/WebCore/platform/graphics/clutter/GraphicsContext3DPrivate.h55
-rw-r--r--Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp1
-rw-r--r--Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm37
-rw-r--r--Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp2
-rw-r--r--Source/WebCore/platform/graphics/efl/GraphicsLayerEfl.cpp1
-rw-r--r--Source/WebCore/platform/graphics/efl/IconEfl.cpp2
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterNumberParameter.h21
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterOperation.cpp83
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterOperation.h23
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterParameter.h7
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterProgram.h5
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterShader.cpp10
-rw-r--r--Source/WebCore/platform/graphics/filters/FEBlend.cpp16
-rw-r--r--Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp14
-rw-r--r--Source/WebCore/platform/graphics/filters/FEComponentTransfer.cpp6
-rw-r--r--Source/WebCore/platform/graphics/filters/FEComposite.cpp8
-rw-r--r--Source/WebCore/platform/graphics/filters/FEComposite.h2
-rw-r--r--Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp35
-rw-r--r--Source/WebCore/platform/graphics/filters/FEConvolveMatrix.h6
-rw-r--r--Source/WebCore/platform/graphics/filters/FECustomFilter.cpp35
-rw-r--r--Source/WebCore/platform/graphics/filters/FECustomFilter.h12
-rw-r--r--Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp14
-rw-r--r--Source/WebCore/platform/graphics/filters/FEDropShadow.cpp4
-rw-r--r--Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp28
-rw-r--r--Source/WebCore/platform/graphics/filters/FEGaussianBlur.h10
-rw-r--r--Source/WebCore/platform/graphics/filters/FELighting.cpp108
-rw-r--r--Source/WebCore/platform/graphics/filters/FELighting.h6
-rw-r--r--Source/WebCore/platform/graphics/filters/FEMorphology.cpp20
-rw-r--r--Source/WebCore/platform/graphics/filters/FEMorphology.h7
-rw-r--r--Source/WebCore/platform/graphics/filters/FETile.cpp4
-rw-r--r--Source/WebCore/platform/graphics/filters/FETurbulence.cpp8
-rw-r--r--Source/WebCore/platform/graphics/filters/FETurbulence.h4
-rw-r--r--Source/WebCore/platform/graphics/filters/FilterEffect.cpp33
-rw-r--r--Source/WebCore/platform/graphics/filters/FilterEffect.h20
-rw-r--r--Source/WebCore/platform/graphics/filters/FilterOperation.cpp9
-rw-r--r--Source/WebCore/platform/graphics/filters/FilterOperation.h62
-rw-r--r--Source/WebCore/platform/graphics/filters/FilterOperations.cpp24
-rw-r--r--Source/WebCore/platform/graphics/filters/FilterOperations.h5
-rw-r--r--Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h6
-rw-r--r--Source/WebCore/platform/graphics/filters/skia/FEGaussianBlurSkia.cpp7
-rw-r--r--Source/WebCore/platform/graphics/filters/skia/FEMorphologySkia.cpp66
-rw-r--r--Source/WebCore/platform/graphics/freetype/FontPlatformData.h2
-rw-r--r--Source/WebCore/platform/graphics/glx/GLContextGLX.cpp59
-rw-r--r--Source/WebCore/platform/graphics/glx/GLContextGLX.h77
-rw-r--r--Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp89
-rw-r--r--Source/WebCore/platform/graphics/gpu/DrawingBuffer.h45
-rw-r--r--Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp83
-rw-r--r--Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h16
-rw-r--r--Source/WebCore/platform/graphics/gpu/Texture.cpp19
-rw-r--r--Source/WebCore/platform/graphics/gpu/TilingData.cpp62
-rw-r--r--Source/WebCore/platform/graphics/gpu/TilingData.h17
-rw-r--r--Source/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm27
-rw-r--r--Source/WebCore/platform/graphics/gpu/qt/DrawingBufferQt.cpp27
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.cpp40
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.h12
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h8
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/GStreamerUtilities.cpp41
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/GStreamerUtilities.h22
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp2
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/ImageGStreamerQt.cpp2
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp50
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp8
-rw-r--r--Source/WebCore/platform/graphics/gtk/GLContextGtk.cpp7
-rw-r--r--Source/WebCore/platform/graphics/gtk/IconGtk.cpp4
-rw-r--r--Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp60
-rw-r--r--Source/WebCore/platform/graphics/gtk/ImageGtk.cpp6
-rw-r--r--Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp69
-rw-r--r--Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.h7
-rw-r--r--Source/WebCore/platform/graphics/harfbuzz/FontHarfBuzz.cpp25
-rw-r--r--Source/WebCore/platform/graphics/mac/ComplexTextController.cpp2
-rw-r--r--Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp8
-rw-r--r--Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm12
-rw-r--r--Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp14
-rw-r--r--Source/WebCore/platform/graphics/mac/FontCacheMac.mm9
-rw-r--r--Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp39
-rw-r--r--Source/WebCore/platform/graphics/mac/GraphicsContextMac.mm9
-rw-r--r--Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm5
-rw-r--r--Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp6
-rw-r--r--Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm41
-rw-r--r--Source/WebCore/platform/graphics/mac/WebLayer.mm7
-rw-r--r--Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp36
-rw-r--r--Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp14
-rw-r--r--Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp28
-rw-r--r--Source/WebCore/platform/graphics/opentype/OpenTypeTypes.h73
-rw-r--r--Source/WebCore/platform/graphics/opentype/OpenTypeVerticalData.cpp264
-rw-r--r--Source/WebCore/platform/graphics/opentype/OpenTypeVerticalData.h59
-rw-r--r--Source/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp2
-rw-r--r--Source/WebCore/platform/graphics/pango/FontPango.cpp2
-rw-r--r--Source/WebCore/platform/graphics/qt/FontCacheQt.cpp24
-rw-r--r--Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h7
-rw-r--r--Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp26
-rw-r--r--Source/WebCore/platform/graphics/qt/FontPlatformData.h23
-rw-r--r--Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp35
-rw-r--r--Source/WebCore/platform/graphics/qt/FontQt.cpp423
-rw-r--r--Source/WebCore/platform/graphics/qt/FontQt4.cpp434
-rw-r--r--Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp41
-rw-r--r--Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp6
-rw-r--r--Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp12
-rw-r--r--Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h2
-rw-r--r--Source/WebCore/platform/graphics/qt/ImageBufferDataQt.h3
-rw-r--r--Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp60
-rw-r--r--Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp7
-rw-r--r--Source/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.cpp47
-rw-r--r--Source/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h26
-rw-r--r--Source/WebCore/platform/graphics/skia/FontSkia.cpp21
-rw-r--r--Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp7
-rw-r--r--Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp270
-rw-r--r--Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp62
-rw-r--r--Source/WebCore/platform/graphics/skia/ImageSkia.cpp3
-rw-r--r--Source/WebCore/platform/graphics/skia/NativeImageSkia.cpp5
-rw-r--r--Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.cpp249
-rw-r--r--Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.h43
-rw-r--r--Source/WebCore/platform/graphics/skia/PatternSkia.cpp11
-rw-r--r--Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp87
-rw-r--r--Source/WebCore/platform/graphics/skia/PlatformContextSkia.h21
-rw-r--r--Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp8
-rw-r--r--Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp20
-rw-r--r--Source/WebCore/platform/graphics/skia/SkiaUtils.cpp50
-rw-r--r--Source/WebCore/platform/graphics/surfaces/GraphicsSurface.cpp72
-rw-r--r--Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h104
-rw-r--r--Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp178
-rw-r--r--Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceQt.cpp60
-rw-r--r--Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp7
-rw-r--r--Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h6
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapper.cpp27
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapper.h26
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp2
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.h2
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp14
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h9
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp580
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperGL.h83
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp18
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h8
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp80
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h13
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h1
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp223
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h89
-rw-r--r--Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.cpp6
-rw-r--r--Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h5
-rw-r--r--Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp34
-rw-r--r--Source/WebCore/platform/graphics/transforms/TransformationMatrix.h6
-rw-r--r--Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.h9
-rw-r--r--Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp18
-rw-r--r--Source/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp6
-rw-r--r--Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp3
-rw-r--r--Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp10
-rw-r--r--Source/WebCore/platform/graphics/win/UniscribeController.cpp2
-rw-r--r--Source/WebCore/platform/graphics/win/UniscribeController.h2
-rw-r--r--Source/WebCore/platform/graphics/wince/FontPlatformData.cpp8
-rw-r--r--Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp2
-rw-r--r--Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp22
-rw-r--r--Source/WebCore/platform/graphics/wx/FontPlatformData.h2
-rw-r--r--Source/WebCore/platform/graphics/wx/GradientWx.cpp69
-rw-r--r--Source/WebCore/platform/graphics/wx/GraphicsContextWx.cpp6
-rw-r--r--Source/WebCore/platform/graphics/wx/ImageBufferDataWx.h14
-rw-r--r--Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp107
-rw-r--r--Source/WebCore/platform/graphics/wx/ImageWx.cpp44
-rw-r--r--Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp8
-rw-r--r--Source/WebCore/platform/graphics/wx/TransformationMatrixWx.cpp2
-rw-r--r--Source/WebCore/platform/gtk/AsyncFileSystemGtk.cpp14
-rw-r--r--Source/WebCore/platform/gtk/AsyncFileSystemGtk.h4
-rw-r--r--Source/WebCore/platform/gtk/CompositionResults.h71
-rw-r--r--Source/WebCore/platform/gtk/ContextMenuGtk.cpp7
-rw-r--r--Source/WebCore/platform/gtk/ContextMenuItemGtk.cpp8
-rw-r--r--Source/WebCore/platform/gtk/DataObjectGtk.h2
-rw-r--r--Source/WebCore/platform/gtk/DragImageGtk.cpp5
-rw-r--r--Source/WebCore/platform/gtk/ErrorsGtk.cpp24
-rw-r--r--Source/WebCore/platform/gtk/ErrorsGtk.h11
-rw-r--r--Source/WebCore/platform/gtk/FileSystemGtk.cpp2
-rw-r--r--Source/WebCore/platform/gtk/GOwnPtrGtk.h2
-rw-r--r--Source/WebCore/platform/gtk/GtkAuthenticationDialog.h2
-rw-r--r--Source/WebCore/platform/gtk/GtkInputMethodFilter.cpp350
-rw-r--r--Source/WebCore/platform/gtk/GtkInputMethodFilter.h90
-rw-r--r--Source/WebCore/platform/gtk/GtkPopupMenu.cpp2
-rw-r--r--Source/WebCore/platform/gtk/GtkWidgetBackingStoreX11.cpp7
-rw-r--r--Source/WebCore/platform/gtk/LanguageGtk.cpp2
-rw-r--r--Source/WebCore/platform/gtk/LocalizedStringsGtk.cpp67
-rw-r--r--Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp46
-rw-r--r--Source/WebCore/platform/gtk/PlatformMouseEventGtk.cpp2
-rw-r--r--Source/WebCore/platform/gtk/PopupMenuGtk.cpp2
-rw-r--r--Source/WebCore/platform/gtk/RenderThemeGtk.cpp60
-rw-r--r--Source/WebCore/platform/gtk/RenderThemeGtk.h26
-rw-r--r--Source/WebCore/platform/gtk/RenderThemeGtk2.cpp2
-rw-r--r--Source/WebCore/platform/gtk/RenderThemeGtk3.cpp34
-rw-r--r--Source/WebCore/platform/gtk/TemporaryLinkStubs.cpp3
-rw-r--r--Source/WebCore/platform/image-decoders/cairo/ImageDecoderCairo.cpp7
-rw-r--r--Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp14
-rw-r--r--Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp68
-rw-r--r--Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp4
-rw-r--r--Source/WebCore/platform/image-encoders/skia/JPEGImageEncoder.cpp4
-rw-r--r--Source/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp2
-rw-r--r--Source/WebCore/platform/image-encoders/skia/WEBPImageEncoder.cpp2
-rw-r--r--Source/WebCore/platform/leveldb/LevelDBDatabase.cpp7
-rw-r--r--Source/WebCore/platform/leveldb/LevelDBDatabase.h1
-rw-r--r--Source/WebCore/platform/leveldb/LevelDBSlice.h2
-rw-r--r--Source/WebCore/platform/leveldb/LevelDBTransaction.cpp26
-rw-r--r--Source/WebCore/platform/leveldb/LevelDBTransaction.h2
-rw-r--r--Source/WebCore/platform/mac/ClipboardMac.h13
-rw-r--r--Source/WebCore/platform/mac/ClipboardMac.mm46
-rw-r--r--Source/WebCore/platform/mac/DragDataMac.mm14
-rw-r--r--Source/WebCore/platform/mac/DragImageMac.mm35
-rw-r--r--Source/WebCore/platform/mac/FileSystemMac.mm2
-rw-r--r--Source/WebCore/platform/mac/HTMLConverter.mm4
-rw-r--r--Source/WebCore/platform/mac/LoggingMac.mm1
-rw-r--r--Source/WebCore/platform/mac/MemoryPressureHandlerMac.mm27
-rw-r--r--Source/WebCore/platform/mac/NSScrollerImpDetails.h1
-rw-r--r--Source/WebCore/platform/mac/PasteboardMac.mm99
-rw-r--r--Source/WebCore/platform/mac/PlatformPasteboardMac.mm25
-rw-r--r--Source/WebCore/platform/mac/ScrollAnimatorMac.h2
-rw-r--r--Source/WebCore/platform/mac/ScrollAnimatorMac.mm20
-rw-r--r--Source/WebCore/platform/mac/ScrollElasticityController.h2
-rw-r--r--Source/WebCore/platform/mac/ScrollElasticityController.mm8
-rw-r--r--Source/WebCore/platform/mac/ScrollbarThemeMac.mm2
-rw-r--r--Source/WebCore/platform/mac/SoftLinking.h9
-rw-r--r--Source/WebCore/platform/mac/ThemeMac.h1
-rw-r--r--Source/WebCore/platform/mac/ThemeMac.mm42
-rw-r--r--Source/WebCore/platform/mac/ThreadCheck.mm2
-rw-r--r--Source/WebCore/platform/mac/WebCoreFullScreenWindow.h4
-rw-r--r--Source/WebCore/platform/mac/WebCoreFullScreenWindow.mm4
-rw-r--r--Source/WebCore/platform/mac/WebCoreNSURLExtras.mm8
-rw-r--r--Source/WebCore/platform/mac/WebCoreObjCExtras.h1
-rw-r--r--Source/WebCore/platform/mac/WebCoreSystemInterface.h15
-rw-r--r--Source/WebCore/platform/mac/WebCoreSystemInterface.mm13
-rw-r--r--Source/WebCore/platform/mac/WebWindowAnimation.mm2
-rw-r--r--Source/WebCore/platform/mediastream/DeprecatedPeerConnectionHandler.h (renamed from Source/WebCore/platform/mediastream/PeerConnectionHandler.h)24
-rw-r--r--Source/WebCore/platform/mediastream/DeprecatedPeerConnectionHandlerClient.h (renamed from Source/WebCore/platform/mediastream/PeerConnectionHandlerClient.h)10
-rw-r--r--Source/WebCore/platform/mediastream/IceCandidateDescriptor.cpp63
-rw-r--r--Source/WebCore/platform/mediastream/IceCandidateDescriptor.h63
-rw-r--r--Source/WebCore/platform/mediastream/IceOptions.cpp46
-rw-r--r--Source/WebCore/platform/mediastream/IceOptions.h64
-rw-r--r--Source/WebCore/platform/mediastream/MediaHints.cpp56
-rw-r--r--Source/WebCore/platform/mediastream/MediaHints.h60
-rw-r--r--Source/WebCore/platform/mediastream/MediaStreamCenter.cpp43
-rw-r--r--Source/WebCore/platform/mediastream/MediaStreamCenter.h46
-rw-r--r--Source/WebCore/platform/mediastream/MediaStreamSourcesQueryClient.h55
-rw-r--r--Source/WebCore/platform/mediastream/PeerConnection00Handler.cpp116
-rw-r--r--Source/WebCore/platform/mediastream/PeerConnection00Handler.h86
-rw-r--r--Source/WebCore/platform/mediastream/PeerConnection00HandlerClient.h59
-rw-r--r--Source/WebCore/platform/mediastream/SessionDescriptionDescriptor.cpp83
-rw-r--r--Source/WebCore/platform/mediastream/SessionDescriptionDescriptor.h67
-rw-r--r--Source/WebCore/platform/mediastream/chromium/DeprecatedPeerConnectionHandler.cpp88
-rw-r--r--Source/WebCore/platform/mediastream/chromium/DeprecatedPeerConnectionHandlerInternal.cpp130
-rw-r--r--Source/WebCore/platform/mediastream/chromium/DeprecatedPeerConnectionHandlerInternal.h80
-rw-r--r--Source/WebCore/platform/mediastream/chromium/MediaStreamCenterChromium.cpp115
-rw-r--r--Source/WebCore/platform/mediastream/chromium/MediaStreamCenterChromium.h80
-rw-r--r--Source/WebCore/platform/mediastream/chromium/PeerConnection00Handler.cpp118
-rw-r--r--Source/WebCore/platform/mediastream/chromium/PeerConnection00HandlerInternal.cpp186
-rw-r--r--Source/WebCore/platform/mediastream/chromium/PeerConnection00HandlerInternal.h90
-rw-r--r--Source/WebCore/platform/mediastream/gstreamer/DeprecatedPeerConnectionHandler.cpp (renamed from Source/WebCore/platform/mediastream/gstreamer/PeerConnectionHandler.cpp)24
-rw-r--r--Source/WebCore/platform/mediastream/gstreamer/MediaStreamCenterGStreamer.cpp91
-rw-r--r--Source/WebCore/platform/mediastream/gstreamer/MediaStreamCenterGStreamer.h68
-rw-r--r--Source/WebCore/platform/mock/GeolocationClientMock.cpp4
-rw-r--r--Source/WebCore/platform/mock/GeolocationClientMock.h4
-rw-r--r--Source/WebCore/platform/mock/GeolocationServiceMock.cpp140
-rw-r--r--Source/WebCore/platform/mock/GeolocationServiceMock.h80
-rw-r--r--Source/WebCore/platform/network/DNS.h4
-rw-r--r--Source/WebCore/platform/network/DNSResolveQueue.cpp93
-rw-r--r--Source/WebCore/platform/network/DNSResolveQueue.h64
-rw-r--r--Source/WebCore/platform/network/FormData.cpp2
-rw-r--r--Source/WebCore/platform/network/FormData.h4
-rw-r--r--Source/WebCore/platform/network/HTTPHeaderMap.cpp4
-rw-r--r--Source/WebCore/platform/network/HTTPHeaderMap.h4
-rw-r--r--Source/WebCore/platform/network/HTTPParsers.cpp155
-rw-r--r--Source/WebCore/platform/network/HTTPParsers.h9
-rw-r--r--Source/WebCore/platform/network/HTTPRequest.cpp118
-rw-r--r--Source/WebCore/platform/network/HTTPRequest.h81
-rw-r--r--Source/WebCore/platform/network/MIMESniffing.cpp11
-rw-r--r--Source/WebCore/platform/network/ResourceHandle.cpp8
-rw-r--r--Source/WebCore/platform/network/ResourceHandle.h4
-rw-r--r--Source/WebCore/platform/network/ResourceHandleInternal.h2
-rw-r--r--Source/WebCore/platform/network/ResourceRequestBase.cpp38
-rw-r--r--Source/WebCore/platform/network/ResourceRequestBase.h7
-rw-r--r--Source/WebCore/platform/network/ResourceResponseBase.cpp8
-rw-r--r--Source/WebCore/platform/network/SocketStreamHandleClient.h3
-rw-r--r--Source/WebCore/platform/network/blackberry/AutofillBackingStore.cpp196
-rw-r--r--Source/WebCore/platform/network/blackberry/AutofillBackingStore.h52
-rw-r--r--Source/WebCore/platform/network/blackberry/CredentialBackingStore.cpp75
-rw-r--r--Source/WebCore/platform/network/blackberry/CredentialBackingStore.h6
-rw-r--r--Source/WebCore/platform/network/blackberry/CredentialStorageBlackBerry.cpp2
-rw-r--r--Source/WebCore/platform/network/blackberry/DeferredData.cpp13
-rw-r--r--Source/WebCore/platform/network/blackberry/DeferredData.h4
-rw-r--r--Source/WebCore/platform/network/blackberry/NetworkJob.cpp137
-rw-r--r--Source/WebCore/platform/network/blackberry/NetworkJob.h7
-rw-r--r--Source/WebCore/platform/network/blackberry/NetworkManager.cpp17
-rw-r--r--Source/WebCore/platform/network/blackberry/ResourceRequest.h15
-rw-r--r--Source/WebCore/platform/network/blackberry/ResourceRequestBlackBerry.cpp94
-rw-r--r--Source/WebCore/platform/network/blackberry/ResourceResponse.h8
-rw-r--r--Source/WebCore/platform/network/blackberry/ResourceResponseBlackBerry.cpp2
-rw-r--r--Source/WebCore/platform/network/blackberry/SocketStreamHandle.h6
-rw-r--r--Source/WebCore/platform/network/blackberry/SocketStreamHandleBlackBerry.cpp21
-rw-r--r--Source/WebCore/platform/network/cf/DNSCFNet.cpp100
-rw-r--r--Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp480
-rw-r--r--Source/WebCore/platform/network/cf/FormDataStreamCFNet.h19
-rw-r--r--Source/WebCore/platform/network/cf/ResourceErrorCF.cpp2
-rw-r--r--Source/WebCore/platform/network/chromium/DNSChromium.cpp10
-rw-r--r--Source/WebCore/platform/network/chromium/ResourceHandle.cpp295
-rw-r--r--Source/WebCore/platform/network/chromium/ResourceHandleInternal.h97
-rw-r--r--Source/WebCore/platform/network/mac/FormDataStreamMac.h7
-rw-r--r--Source/WebCore/platform/network/mac/FormDataStreamMac.mm481
-rw-r--r--Source/WebCore/platform/network/mac/ResourceErrorMac.mm4
-rw-r--r--Source/WebCore/platform/network/mac/ResourceHandleMac.mm29
-rw-r--r--Source/WebCore/platform/network/qt/SocketStreamHandle.h6
-rw-r--r--Source/WebCore/platform/network/qt/SocketStreamHandlePrivate.h2
-rw-r--r--Source/WebCore/platform/network/qt/SocketStreamHandleQt.cpp43
-rw-r--r--Source/WebCore/platform/network/soup/CookieJarSoup.cpp158
-rw-r--r--Source/WebCore/platform/network/soup/CookieJarSoup.h6
-rw-r--r--Source/WebCore/platform/network/soup/CookieStorageSoup.cpp60
-rw-r--r--Source/WebCore/platform/network/soup/DNSSoup.cpp67
-rw-r--r--Source/WebCore/platform/network/soup/GOwnPtrSoup.cpp7
-rw-r--r--Source/WebCore/platform/network/soup/GOwnPtrSoup.h4
-rw-r--r--Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp333
-rw-r--r--Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp2
-rw-r--r--Source/WebCore/platform/network/soup/ResourceResponseSoup.cpp2
-rw-r--r--Source/WebCore/platform/network/soup/SocketStreamHandle.h2
-rw-r--r--Source/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp11
-rw-r--r--Source/WebCore/platform/network/soup/SoupURIUtils.cpp2
-rw-r--r--Source/WebCore/platform/network/win/ResourceHandleWin.cpp6
-rw-r--r--Source/WebCore/platform/posix/FileSystemPOSIX.cpp30
-rw-r--r--Source/WebCore/platform/qt/CookieJarQt.cpp15
-rw-r--r--Source/WebCore/platform/qt/DeviceMotionClientQt.cpp67
-rw-r--r--Source/WebCore/platform/qt/DeviceMotionClientQt.h55
-rw-r--r--Source/WebCore/platform/qt/DeviceMotionProviderQt.cpp89
-rw-r--r--Source/WebCore/platform/qt/DeviceMotionProviderQt.h61
-rw-r--r--Source/WebCore/platform/qt/DeviceOrientationClientQt.cpp59
-rw-r--r--Source/WebCore/platform/qt/DeviceOrientationClientQt.h49
-rw-r--r--Source/WebCore/platform/qt/DeviceOrientationProviderQt.cpp79
-rw-r--r--Source/WebCore/platform/qt/DeviceOrientationProviderQt.h59
-rw-r--r--Source/WebCore/platform/qt/DragImageQt.cpp2
-rw-r--r--Source/WebCore/platform/qt/LocalizedStringsQt.cpp10
-rw-r--r--Source/WebCore/platform/qt/PlatformMouseEventQt.cpp164
-rw-r--r--Source/WebCore/platform/qt/PlatformSupportQt.cpp2
-rw-r--r--Source/WebCore/platform/qt/PlatformTouchEventQt.cpp92
-rw-r--r--Source/WebCore/platform/qt/PlatformTouchPointQt.cpp53
-rw-r--r--Source/WebCore/platform/qt/RenderThemeQt.cpp57
-rw-r--r--Source/WebCore/platform/qt/RenderThemeQt.h26
-rw-r--r--Source/WebCore/platform/qt/RenderThemeQtMobile.cpp48
-rw-r--r--Source/WebCore/platform/qt/RenderThemeQtMobile.h11
-rw-r--r--Source/WebCore/platform/qt/RunLoopQt.cpp22
-rw-r--r--Source/WebCore/platform/qt/WheelEventQt.cpp93
-rw-r--r--Source/WebCore/platform/text/BidiContext.cpp7
-rw-r--r--Source/WebCore/platform/text/BidiContext.h4
-rw-r--r--Source/WebCore/platform/text/BidiResolver.h2
-rw-r--r--Source/WebCore/platform/text/LocaleICU.cpp484
-rw-r--r--Source/WebCore/platform/text/LocaleICU.h (renamed from Source/WebCore/platform/text/LocalizedNumberICU.h)50
-rw-r--r--Source/WebCore/platform/text/LocaleToScriptMapping.h3
-rw-r--r--Source/WebCore/platform/text/LocaleToScriptMappingDefault.cpp6
-rw-r--r--Source/WebCore/platform/text/LocaleToScriptMappingICU.cpp8
-rw-r--r--Source/WebCore/platform/text/LocaleWin.cpp593
-rw-r--r--Source/WebCore/platform/text/LocaleWin.h88
-rw-r--r--Source/WebCore/platform/text/LocalizedDate.h17
-rw-r--r--Source/WebCore/platform/text/LocalizedDateICU.cpp95
-rw-r--r--Source/WebCore/platform/text/LocalizedDateWin.cpp (renamed from Source/WebCore/platform/graphics/chromium/VideoFrameChromium.h)102
-rw-r--r--Source/WebCore/platform/text/LocalizedNumberICU.cpp230
-rw-r--r--Source/WebCore/platform/text/RegularExpression.cpp2
-rw-r--r--Source/WebCore/platform/text/TextBreakIterator.h1
-rw-r--r--Source/WebCore/platform/text/TextBreakIteratorICU.cpp6
-rw-r--r--Source/WebCore/platform/text/TextEncoding.cpp2
-rw-r--r--Source/WebCore/platform/text/gtk/TextBreakIteratorGtk.cpp7
-rw-r--r--Source/WebCore/platform/text/gtk/TextCodecGtk.cpp2
-rw-r--r--Source/WebCore/platform/text/gtk/TextCodecGtk.h2
-rw-r--r--Source/WebCore/platform/text/mac/LocalizedDateMac.mm201
-rw-r--r--Source/WebCore/platform/text/mac/LocalizedNumberMac.mm2
-rw-r--r--Source/WebCore/platform/text/qt/TextBreakIteratorQt.cpp5
-rw-r--r--Source/WebCore/platform/text/wince/TextBreakIteratorWinCE.cpp5
-rw-r--r--Source/WebCore/platform/text/wince/TextCodecWinCE.cpp2
-rw-r--r--Source/WebCore/platform/win/DragImageCGWin.cpp4
-rw-r--r--Source/WebCore/platform/win/DragImageCairoWin.cpp4
-rw-r--r--Source/WebCore/platform/win/DragImageWin.cpp2
-rw-r--r--Source/WebCore/platform/win/FileSystemWin.cpp5
-rw-r--r--Source/WebCore/platform/win/PopupMenuWin.cpp7
-rw-r--r--Source/WebCore/platform/wince/DragImageWinCE.cpp2
-rw-r--r--Source/WebCore/platform/wx/DragImageWx.cpp2
-rw-r--r--Source/WebCore/platform/wx/LocalDC.h7
-rw-r--r--Source/WebCore/platform/wx/MouseEventWx.cpp2
-rw-r--r--Source/WebCore/platform/wx/RenderThemeWx.cpp16
-rw-r--r--Source/WebCore/platform/wx/wxcode/win/fontprops.cpp6
866 files changed, 30173 insertions, 11843 deletions
diff --git a/Source/WebCore/platform/ActivePlatformGestureAnimation.cpp b/Source/WebCore/platform/ActivePlatformGestureAnimation.cpp
index 7f6e7c2c9..5a9332686 100644
--- a/Source/WebCore/platform/ActivePlatformGestureAnimation.cpp
+++ b/Source/WebCore/platform/ActivePlatformGestureAnimation.cpp
@@ -30,26 +30,57 @@
#include "PlatformGestureCurve.h"
#include "PlatformGestureCurveTarget.h"
+#if PLATFORM(CHROMIUM)
+#include "TraceEvent.h"
+#endif
+
namespace WebCore {
-PassOwnPtr<ActivePlatformGestureAnimation> ActivePlatformGestureAnimation::create(double startTime, PassOwnPtr<PlatformGestureCurve> curve, PlatformGestureCurveTarget* target)
+PassOwnPtr<ActivePlatformGestureAnimation> ActivePlatformGestureAnimation::create(PassOwnPtr<PlatformGestureCurve> curve, PlatformGestureCurveTarget* target)
{
- return adoptPtr(new ActivePlatformGestureAnimation(startTime, curve, target));
+ return adoptPtr(new ActivePlatformGestureAnimation(curve, target));
+}
+
+PassOwnPtr<ActivePlatformGestureAnimation> ActivePlatformGestureAnimation::create(PassOwnPtr<PlatformGestureCurve> curve, PlatformGestureCurveTarget* target, double startTime)
+{
+ return adoptPtr(new ActivePlatformGestureAnimation(curve, target, startTime));
}
ActivePlatformGestureAnimation::~ActivePlatformGestureAnimation()
{
+#if PLATFORM(CHROMIUM)
+ TRACE_EVENT_ASYNC_END0("input", "GestureAnimation", this);
+#endif
+}
+
+ActivePlatformGestureAnimation::ActivePlatformGestureAnimation(PassOwnPtr<PlatformGestureCurve> curve, PlatformGestureCurveTarget* target)
+ : m_startTime(0)
+ , m_waitingForFirstTick(true)
+ , m_curve(curve)
+ , m_target(target)
+{
+#if PLATFORM(CHROMIUM)
+ TRACE_EVENT_ASYNC_BEGIN1("input", "GestureAnimation", this, "curve", m_curve->debugName());
+#endif
}
-ActivePlatformGestureAnimation::ActivePlatformGestureAnimation(double startTime, PassOwnPtr<PlatformGestureCurve> curve, PlatformGestureCurveTarget* target)
+ActivePlatformGestureAnimation::ActivePlatformGestureAnimation(PassOwnPtr<PlatformGestureCurve> curve, PlatformGestureCurveTarget* target, double startTime)
: m_startTime(startTime)
+ , m_waitingForFirstTick(false)
, m_curve(curve)
, m_target(target)
{
+#if PLATFORM(CHROMIUM)
+ TRACE_EVENT_ASYNC_BEGIN1("input", "GestureAnimation", this, "curve", m_curve->debugName());
+#endif
}
bool ActivePlatformGestureAnimation::animate(double time)
{
+ if (m_waitingForFirstTick) {
+ m_startTime = time;
+ m_waitingForFirstTick = false;
+ }
// All PlatformGestureCurves assume zero-based time, so we subtract
// the animation start time before passing to the curve.
return m_curve->apply(time - m_startTime, m_target);
diff --git a/Source/WebCore/platform/ActivePlatformGestureAnimation.h b/Source/WebCore/platform/ActivePlatformGestureAnimation.h
index aae40de7b..21f199c07 100644
--- a/Source/WebCore/platform/ActivePlatformGestureAnimation.h
+++ b/Source/WebCore/platform/ActivePlatformGestureAnimation.h
@@ -42,16 +42,19 @@ class PlatformGestureCurveTarget;
class ActivePlatformGestureAnimation {
WTF_MAKE_NONCOPYABLE(ActivePlatformGestureAnimation);
public:
- static PassOwnPtr<ActivePlatformGestureAnimation> create(double startTime, PassOwnPtr<PlatformGestureCurve>, PlatformGestureCurveTarget*);
+ static PassOwnPtr<ActivePlatformGestureAnimation> create(PassOwnPtr<PlatformGestureCurve>, PlatformGestureCurveTarget*);
+ static PassOwnPtr<ActivePlatformGestureAnimation> create(PassOwnPtr<PlatformGestureCurve>, PlatformGestureCurveTarget*, double startTime);
~ActivePlatformGestureAnimation();
bool animate(double time);
private:
// Assumes a valid PlatformGestureCurveTarget that outlives the animation.
- ActivePlatformGestureAnimation(double startTime, PassOwnPtr<PlatformGestureCurve>, PlatformGestureCurveTarget*);
+ ActivePlatformGestureAnimation(PassOwnPtr<PlatformGestureCurve>, PlatformGestureCurveTarget*);
+ ActivePlatformGestureAnimation(PassOwnPtr<PlatformGestureCurve>, PlatformGestureCurveTarget*, double startTime);
double m_startTime;
+ bool m_waitingForFirstTick;
OwnPtr<PlatformGestureCurve> m_curve;
PlatformGestureCurveTarget* m_target;
};
diff --git a/Source/WebCore/platform/Arena.cpp b/Source/WebCore/platform/Arena.cpp
index 33980edfe..606092626 100644
--- a/Source/WebCore/platform/Arena.cpp
+++ b/Source/WebCore/platform/Arena.cpp
@@ -56,37 +56,33 @@ using namespace std;
namespace WebCore {
-//#define DEBUG_ARENA_MALLOC
#ifdef DEBUG_ARENA_MALLOC
static int i = 0;
#endif
-#define FREELIST_MAX 30
-static Arena *arena_freelist;
-static int freelist_count = 0;
-
-#define ARENA_DEFAULT_ALIGN sizeof(double)
-#define BIT(n) ((unsigned int)1 << (n))
-#define BITMASK(n) (BIT(n) - 1)
-#define CEILING_LOG2(_log2,_n) \
- unsigned int j_ = (unsigned int)(_n); \
- (_log2) = 0; \
- if ((j_) & ((j_)-1)) \
- (_log2) += 1; \
- if ((j_) >> 16) \
- (_log2) += 16, (j_) >>= 16; \
- if ((j_) >> 8) \
- (_log2) += 8, (j_) >>= 8; \
- if ((j_) >> 4) \
- (_log2) += 4, (j_) >>= 4; \
- if ((j_) >> 2) \
- (_log2) += 2, (j_) >>= 2; \
- if ((j_) >> 1) \
- (_log2) += 1;
+#define ARENA_DEFAULT_ALIGN sizeof(double)
+#define BIT(n) ((unsigned int)1 << (n))
+#define BITMASK(n) (BIT(n) - 1)
+#define CEILING_LOG2(_log2, _n) \
+ unsigned int j_ = (unsigned int)(_n); \
+ (_log2) = 0; \
+ if ((j_) & ((j_)-1)) \
+ (_log2) += 1; \
+ if ((j_) >> 16) \
+ (_log2) += 16, (j_) >>= 16; \
+ if ((j_) >> 8) \
+ (_log2) += 8, (j_) >>= 8; \
+ if ((j_) >> 4) \
+ (_log2) += 4, (j_) >>= 4; \
+ if ((j_) >> 2) \
+ (_log2) += 2, (j_) >>= 2; \
+ if ((j_) >> 1) \
+ (_log2) += 1;
+#define FREE_PATTERN 0xDA
static int CeilingLog2(unsigned int i) {
int log2;
- CEILING_LOG2(log2,i);
+ CEILING_LOG2(log2, i);
return log2;
}
@@ -96,163 +92,99 @@ void InitArenaPool(ArenaPool* pool, const char*, unsigned size, unsigned align)
align = ARENA_DEFAULT_ALIGN;
pool->mask = BITMASK(CeilingLog2(align));
pool->first.next = NULL;
- pool->first.base = pool->first.avail = pool->first.limit =
- (uword)ARENA_ALIGN(&pool->first + 1);
+ pool->first.base = pool->first.avail = pool->first.limit = (uword)ARENA_ALIGN(&pool->first + 1);
pool->current = &pool->first;
pool->arenasize = size;
}
-
-/*
- ** ArenaAllocate() -- allocate space from an arena pool
- **
- ** Description: ArenaAllocate() allocates space from an arena
- ** pool.
- **
- ** First try to satisfy the request from arenas starting at
- ** pool->current.
- **
- ** If there is not enough space in the arena pool->current, try
- ** to claim an arena, on a first fit basis, from the global
- ** freelist (arena_freelist).
- **
- ** If no arena in arena_freelist is suitable, then try to
- ** allocate a new arena from the heap.
- **
- ** Returns: pointer to allocated space or NULL
- **
- */
-void* ArenaAllocate(ArenaPool *pool, unsigned int nb)
+void* ArenaAllocate(ArenaPool* pool, unsigned int numBytes, unsigned int& bytesAllocated)
{
- Arena *a;
- char *rp; /* returned pointer */
+ Arena* arena;
+ char* returnPointer;
- ASSERT((nb & pool->mask) == 0);
+ ASSERT((numBytes & pool->mask) == 0);
- nb = (uword)ARENA_ALIGN(nb); /* force alignment */
+ numBytes = (uword)ARENA_ALIGN(numBytes);
- /* attempt to allocate from arenas at pool->current */
+ // attempt to allocate from arenas at pool->current
{
- a = pool->current;
+ arena = pool->current;
do {
- if ( a->avail +nb <= a->limit ) {
- pool->current = a;
- rp = (char *)a->avail;
- a->avail += nb;
- return rp;
- }
- } while( NULL != (a = a->next) );
- }
-
- /* attempt to allocate from arena_freelist */
- {
- Arena *p = NULL; /* previous pointer, for unlinking from freelist */
-
- for ( a = arena_freelist; a != NULL ; p = a, a = a->next ) {
- if ( a->base +nb <= a->limit ) {
- if ( p == NULL )
- arena_freelist = a->next;
- else
- p->next = a->next;
- a->avail = a->base;
- rp = (char *)a->avail;
- a->avail += nb;
- /* the newly allocated arena is linked after pool->current
- * and becomes pool->current */
- a->next = pool->current->next;
- pool->current->next = a;
- pool->current = a;
- if ( 0 == pool->first.next )
- pool->first.next = a;
- freelist_count--;
- return(rp);
+ if (arena->avail + numBytes <= arena->limit) {
+ pool->current = arena;
+ returnPointer = (char *)arena->avail;
+ arena->avail += numBytes;
+ return returnPointer;
}
- }
+ } while (NULL != (arena = arena->next));
}
- /* attempt to allocate from the heap */
+ // attempt to allocate from the heap
{
- unsigned int sz = max(pool->arenasize, nb);
- sz += sizeof *a + pool->mask; /* header and alignment slop */
+ unsigned int size = max(pool->arenasize, numBytes);
+ size += sizeof *arena + pool->mask; /* header and alignment slop */
#ifdef DEBUG_ARENA_MALLOC
i++;
printf("Malloc: %d\n", i);
#endif
- a = (Arena*)fastMalloc(sz);
+ bytesAllocated = size;
+ arena = (Arena*)fastMalloc(size);
// fastMalloc will abort() if it fails, so we are guaranteed that a is not 0.
- a->limit = (uword)a + sz;
- a->base = a->avail = (uword)ARENA_ALIGN(a + 1);
- rp = (char *)a->avail;
- a->avail += nb;
- /* the newly allocated arena is linked after pool->current
- * and becomes pool->current */
- a->next = pool->current->next;
- pool->current->next = a;
- pool->current = a;
- if ( !pool->first.next )
- pool->first.next = a;
- return(rp);
+ arena->limit = (uword)arena + size;
+ arena->base = arena->avail = (uword)ARENA_ALIGN(arena + 1);
+ returnPointer = (char *)arena->avail;
+ arena->avail += numBytes;
+ // the newly allocated arena is linked after pool->current and becomes pool->current.
+ arena->next = pool->current->next;
+ pool->current->next = arena;
+ pool->current = arena;
+ if (!pool->first.next)
+ pool->first.next = arena;
+ return(returnPointer);
}
-} /* --- end ArenaAllocate() --- */
+}
-/*
- * Free tail arenas linked after head, which may not be the true list head.
- * Reset pool->current to point to head in case it pointed at a tail arena.
- */
-static void FreeArenaList(ArenaPool *pool, Arena *head, bool reallyFree)
+// Free tail arenas linked after head, which may not be the true list head.
+// Reset pool->current to point to head in case it pointed at a tail arena.
+static void FreeArenaList(ArenaPool* pool, Arena* head)
{
- Arena **ap, *a;
-
- ap = &head->next;
- a = *ap;
- if (!a)
+ Arena** arenaPointer = &head->next;
+ Arena* arena = *arenaPointer;
+ if (!arena)
return;
#ifdef DEBUG
do {
- ASSERT(a->base <= a->avail && a->avail <= a->limit);
- a->avail = a->base;
- CLEAR_UNUSED(a);
- } while ((a = a->next) != 0);
- a = *ap;
+ ASSERT(arena->base <= arena->avail && arena->avail <= arena->limit);
+ arena->avail = arena->base;
+ memset((void*)(arena)->avail, FREE_PATTERN, (arena)->limit - (arena)->avail)
+ } while ((arena = arena->next) != 0);
+ arena = *arenaPointer;
+#endif
+
+ do {
+ *arenaPointer = arena->next;
+
+#ifdef DEBUG
+ memset((void*)(arena), FREE_PATTERN, (arena)->limit - (uword)(arena));
#endif
- if (freelist_count >= FREELIST_MAX)
- reallyFree = true;
-
- if (reallyFree) {
- do {
- *ap = a->next;
- CLEAR_ARENA(a);
#ifdef DEBUG_ARENA_MALLOC
- if (a) {
- i--;
- printf("Free: %d\n", i);
- }
+ if (arena) {
+ i--;
+ printf("Free: %d\n", i);
+ }
#endif
- fastFree(a); a = 0;
- } while ((a = *ap) != 0);
- } else {
- /* Insert the whole arena chain at the front of the freelist. */
- do {
- ap = &(*ap)->next;
- freelist_count++;
- } while (*ap);
- *ap = arena_freelist;
- arena_freelist = a;
- head->next = 0;
- }
- pool->current = head;
-}
-void FreeArenaPool(ArenaPool *pool)
-{
- FreeArenaList(pool, &pool->first, false);
+ fastFree(arena);
+ arena = 0;
+ } while ((arena = *arenaPointer) != 0);
+ pool->current = head;
}
-void FinishArenaPool(ArenaPool *pool)
+void FinishArenaPool(ArenaPool* pool)
{
- FreeArenaList(pool, &pool->first, true);
+ FreeArenaList(pool, &pool->first);
}
}
diff --git a/Source/WebCore/platform/Arena.h b/Source/WebCore/platform/Arena.h
index 06e09f2a5..c1185e47f 100644
--- a/Source/WebCore/platform/Arena.h
+++ b/Source/WebCore/platform/Arena.h
@@ -41,8 +41,6 @@
#ifndef Arena_h
#define Arena_h
-#include <wtf/FastMalloc.h>
-
// FIXME: We'd always like to use AllocAlignmentInteger for Arena alignment
// but there is concern over the memory growth this may cause.
#ifdef WTF_USE_ARENA_ALLOC_ALIGNMENT_INTEGER
@@ -69,70 +67,22 @@ struct ArenaPool {
uword mask; // Mask (power-of-2 - 1)
};
-void InitArenaPool(ArenaPool *pool, const char *name,
- unsigned int size, unsigned int align);
-void FinishArenaPool(ArenaPool *pool);
-void FreeArenaPool(ArenaPool *pool);
-void* ArenaAllocate(ArenaPool *pool, unsigned int nb);
+void InitArenaPool(ArenaPool*, const char* name, unsigned int size, unsigned int align);
+void FinishArenaPool(ArenaPool*);
+void* ArenaAllocate(ArenaPool*, unsigned int numBytes, unsigned int& bytesAllocated);
#define ARENA_ALIGN(n) (((uword)(n) + ARENA_ALIGN_MASK) & ~ARENA_ALIGN_MASK)
-#define INIT_ARENA_POOL(pool, name, size) \
- InitArenaPool(pool, name, size, ARENA_ALIGN_MASK + 1)
-
-#define ARENA_ALLOCATE(p, pool, nb) \
- Arena *_a = (pool)->current; \
- unsigned int _nb = ARENA_ALIGN(nb); \
- uword _p = _a->avail; \
- uword _q = _p + _nb; \
- if (_q > _a->limit) \
- _p = (uword)ArenaAllocate(pool, _nb); \
- else \
- _a->avail = _q; \
- p = (void *)_p;
-
-#define ARENA_GROW(p, pool, size, incr) \
- Arena *_a = (pool)->current; \
- unsigned int _incr = ARENA_ALIGN(incr); \
- uword _p = _a->avail; \
- uword _q = _p + _incr; \
- if (_p == (uword)(p) + ARENA_ALIGN(size) && \
- _q <= _a->limit) { \
- _a->avail = _q; \
- } else { \
- p = ArenaGrow(pool, p, size, incr); \
- }
-
-#define ARENA_MARK(pool) ((void *) (pool)->current->avail)
-#define UPTRDIFF(p,q) ((uword)(p) - (uword)(q))
-
-#ifdef DEBUG
-#define FREE_PATTERN 0xDA
-#define CLEAR_UNUSED(a) ASSERT((a)->avail <= (a)->limit); \
- memset((void*)(a)->avail, FREE_PATTERN, \
- (a)->limit - (a)->avail)
-#define CLEAR_ARENA(a) memset((void*)(a), FREE_PATTERN, \
- (a)->limit - (uword)(a))
-#else
-#define CLEAR_UNUSED(a)
-#define CLEAR_ARENA(a)
-#endif
-
-#define ARENA_RELEASE(pool, mark) \
- char *_m = (char *)(mark); \
- Arena *_a = (pool)->current; \
- if (UPTRDIFF(_m, _a->base) <= UPTRDIFF(_a->avail, _a->base)) { \
- _a->avail = (uword)ARENA_ALIGN(_m); \
- CLEAR_UNUSED(_a); \
- } else { \
- ArenaRelease(pool, _m); \
- }
-
-#define ARENA_DESTROY(pool, a, pnext) \
- if ((pool)->current == (a)) (pool)->current = &(pool)->first; \
- *(pnext) = (a)->next; \
- CLEAR_ARENA(a); \
- fastFree(a); \
- (a) = 0;
+#define INIT_ARENA_POOL(pool, name, size) InitArenaPool(pool, name, size, ARENA_ALIGN_MASK + 1)
+#define ARENA_ALLOCATE(p, pool, nb, bytesAllocated) \
+ Arena* _a = (pool)->current; \
+ unsigned int _nb = ARENA_ALIGN(nb); \
+ uword _p = _a->avail; \
+ uword _q = _p + _nb; \
+ if (_q > _a->limit) \
+ _p = (uword)ArenaAllocate(pool, _nb, *bytesAllocated); \
+ else \
+ _a->avail = _q; \
+ p = (void*)_p;
}
diff --git a/Source/WebCore/platform/AsyncFileSystem.cpp b/Source/WebCore/platform/AsyncFileSystem.cpp
index 7b811d4c3..13c282e20 100644
--- a/Source/WebCore/platform/AsyncFileSystem.cpp
+++ b/Source/WebCore/platform/AsyncFileSystem.cpp
@@ -45,25 +45,25 @@ const size_t AsyncFileSystem::persistentPathPrefixLength = sizeof(AsyncFileSyste
const char AsyncFileSystem::temporaryPathPrefix[] = "temporary";
const size_t AsyncFileSystem::temporaryPathPrefixLength = sizeof(AsyncFileSystem::temporaryPathPrefix) - 1;
-#if !PLATFORM(CHROMIUM) && !PLATFORM(GTK)
+#if !PLATFORM(CHROMIUM) && !PLATFORM(GTK) && !PLATFORM(BLACKBERRY)
bool AsyncFileSystem::isAvailable()
{
notImplemented();
return false;
}
-bool AsyncFileSystem::isValidType(Type type)
+bool AsyncFileSystem::isValidType(FileSystemType type)
{
- return type == Temporary || type == Persistent;
+ return type == FileSystemTypeTemporary || type == FileSystemTypePersistent;
}
-PassOwnPtr<AsyncFileSystem> AsyncFileSystem::create(Type)
+PassOwnPtr<AsyncFileSystem> AsyncFileSystem::create(FileSystemType)
{
notImplemented();
return nullptr;
}
-void AsyncFileSystem::openFileSystem(const String& basePath, const String& storageIdentifier, Type type, bool, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
+void AsyncFileSystem::openFileSystem(const String& basePath, const String& storageIdentifier, FileSystemType, bool, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
{
notImplemented();
callbacks->didFail(NOT_SUPPORTED_ERR);
diff --git a/Source/WebCore/platform/AsyncFileSystem.h b/Source/WebCore/platform/AsyncFileSystem.h
index 7792101c5..683297924 100644
--- a/Source/WebCore/platform/AsyncFileSystem.h
+++ b/Source/WebCore/platform/AsyncFileSystem.h
@@ -33,6 +33,7 @@
#if ENABLE(FILE_SYSTEM)
+#include "FileSystemType.h"
#include "KURL.h"
#include "PlatformString.h"
#include "Timer.h"
@@ -50,12 +51,6 @@ class AsyncFileSystem {
public:
virtual ~AsyncFileSystem() { }
- // FileSystem type
- enum Type {
- Temporary,
- Persistent,
- };
-
// Path prefixes that are used in the filesystem URLs (that can be obtained by toURL()).
// http://www.w3.org/TR/file-system-api/#widl-Entry-toURL
static const char persistentPathPrefix[];
@@ -68,21 +63,21 @@ public:
static bool isAvailable();
- static bool isValidType(Type);
+ static bool isValidType(FileSystemType);
- static bool crackFileSystemURL(const KURL&, Type&, String& filePath);
+ static bool crackFileSystemURL(const KURL&, FileSystemType&, String& filePath);
- virtual String toURL(const String& originString, const String& fullPath) = 0;
+ virtual KURL toURL(const String& originString, const String& fullPath) const = 0;
// Subclass must implement this if it supports synchronous operations.
// This should return false if there are no pending operations.
virtual bool waitForOperationToComplete() { return false; }
// Creates and returns a new platform-specific AsyncFileSystem instance if the platform has its own implementation.
- static PassOwnPtr<AsyncFileSystem> create(Type);
+ static PassOwnPtr<AsyncFileSystem> create(FileSystemType);
// Opens a new file system. The create parameter specifies whether or not to create the path if it does not already exists.
- static void openFileSystem(const String& basePath, const String& storageIdentifier, Type, bool create, PassOwnPtr<AsyncFileSystemCallbacks>);
+ static void openFileSystem(const String& basePath, const String& storageIdentifier, FileSystemType, bool create, PassOwnPtr<AsyncFileSystemCallbacks>);
// Moves a file or directory from srcPath to destPath.
// AsyncFileSystemCallbacks::didSucceed() is called when the operation is completed successfully.
@@ -147,15 +142,15 @@ public:
// AsyncFileSystemCallbacks::didFail() is called otherwise.
virtual void createSnapshotFileAndReadMetadata(const String& path, PassOwnPtr<AsyncFileSystemCallbacks>) = 0;
- Type type() const { return m_type; }
+ FileSystemType type() const { return m_type; }
protected:
- AsyncFileSystem(Type type)
+ AsyncFileSystem(FileSystemType type)
: m_type(type)
{
}
- Type m_type;
+ FileSystemType m_type;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/CalculationValue.h b/Source/WebCore/platform/CalculationValue.h
index c55845542..9339b105f 100755
--- a/Source/WebCore/platform/CalculationValue.h
+++ b/Source/WebCore/platform/CalculationValue.h
@@ -32,6 +32,7 @@
#define CalculationValue_h
#include "Length.h"
+#include "LengthFunctions.h"
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/RefCounted.h>
@@ -101,7 +102,7 @@ public:
virtual float evaluate(float maxValue) const
{
- return m_length.calcFloatValue(maxValue);
+ return floatValueForLength(m_length, maxValue);
}
private:
diff --git a/Source/WebCore/platform/ColorChooser.h b/Source/WebCore/platform/ColorChooser.h
index 1baa988f6..7c23b1b1a 100644
--- a/Source/WebCore/platform/ColorChooser.h
+++ b/Source/WebCore/platform/ColorChooser.h
@@ -30,7 +30,7 @@
#ifndef ColorChooser_h
#define ColorChooser_h
-#if ENABLE(INPUT_COLOR)
+#if ENABLE(INPUT_TYPE_COLOR)
namespace WebCore {
@@ -46,6 +46,6 @@ public:
} // namespace WebCore
-#endif // ENABLE(INPUT_COLOR)
+#endif // ENABLE(INPUT_TYPE_COLOR)
#endif // ColorChooser_h
diff --git a/Source/WebCore/platform/ColorChooserClient.h b/Source/WebCore/platform/ColorChooserClient.h
index 0c5bf3623..54fa5cc01 100644
--- a/Source/WebCore/platform/ColorChooserClient.h
+++ b/Source/WebCore/platform/ColorChooserClient.h
@@ -1,7 +1,7 @@
#ifndef ColorChooserClient_h
#define ColorChooserClient_h
-#if ENABLE(INPUT_COLOR)
+#if ENABLE(INPUT_TYPE_COLOR)
#include "ColorChooser.h"
#include <wtf/OwnPtr.h>
@@ -21,6 +21,6 @@ public:
} // namespace WebCore
-#endif // ENABLE(INPUT_COLOR)
+#endif // ENABLE(INPUT_TYPE_COLOR)
#endif // ColorChooserClient_h
diff --git a/Source/WebCore/platform/ContextMenu.cpp b/Source/WebCore/platform/ContextMenu.cpp
index 014d58f87..0bd1bf2ed 100644
--- a/Source/WebCore/platform/ContextMenu.cpp
+++ b/Source/WebCore/platform/ContextMenu.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "ContextMenu.h"
-#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+#if ENABLE(CONTEXT_MENUS) && USE(CROSS_PLATFORM_CONTEXT_MENUS)
namespace WebCore {
@@ -58,4 +58,4 @@ ContextMenuItem* ContextMenu::itemWithAction(unsigned action)
} // namespace WebCore
-#endif // USE(CROSS_PLATFORM_CONTEXT_MENUS)
+#endif // ENABLE(CONTEXT_MENUS) && USE(CROSS_PLATFORM_CONTEXT_MENUS)
diff --git a/Source/WebCore/platform/ContextMenu.h b/Source/WebCore/platform/ContextMenu.h
index 00ceb2009..6a43b49a6 100644
--- a/Source/WebCore/platform/ContextMenu.h
+++ b/Source/WebCore/platform/ContextMenu.h
@@ -26,6 +26,8 @@
#ifndef ContextMenu_h
#define ContextMenu_h
+#if ENABLE(CONTEXT_MENUS)
+
#include <wtf/Noncopyable.h>
#include "ContextMenuItem.h"
@@ -118,4 +120,5 @@ PlatformMenuDescription platformMenuDescription(Vector<ContextMenuItem>&);
}
+#endif // ENABLE(CONTEXT_MENUS)
#endif // ContextMenu_h
diff --git a/Source/WebCore/platform/ContextMenuItem.cpp b/Source/WebCore/platform/ContextMenuItem.cpp
index 0c2a6ea4a..246ad4aaa 100644
--- a/Source/WebCore/platform/ContextMenuItem.cpp
+++ b/Source/WebCore/platform/ContextMenuItem.cpp
@@ -28,7 +28,7 @@
#include "ContextMenu.h"
-#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+#if ENABLE(CONTEXT_MENUS) && USE(CROSS_PLATFORM_CONTEXT_MENUS)
namespace WebCore {
@@ -119,4 +119,4 @@ bool ContextMenuItem::enabled() const
} // namespace WebCore
-#endif // USE(CROSS_PLATFORM_CONTEXT_MENUS)
+#endif // ENABLE(CONTEXT_MENUS) && USE(CROSS_PLATFORM_CONTEXT_MENUS)
diff --git a/Source/WebCore/platform/ContextMenuItem.h b/Source/WebCore/platform/ContextMenuItem.h
index 15bff4839..f97e2fb05 100644
--- a/Source/WebCore/platform/ContextMenuItem.h
+++ b/Source/WebCore/platform/ContextMenuItem.h
@@ -27,6 +27,8 @@
#ifndef ContextMenuItem_h
#define ContextMenuItem_h
+#if ENABLE(CONTEXT_MENUS)
+
#include "PlatformMenuDescription.h"
#include "PlatformString.h"
#include <wtf/OwnPtr.h>
@@ -42,6 +44,7 @@ typedef struct _GtkAction GtkAction;
#elif PLATFORM(WX)
class wxMenuItem;
#endif
+#endif // ENABLE(CONTEXT_MENUS)
namespace WebCore {
@@ -77,6 +80,16 @@ namespace WebCore {
#if PLATFORM(GTK)
ContextMenuItemTagInputMethods,
ContextMenuItemTagUnicode,
+ ContextMenuItemTagUnicodeInsertLRMMark,
+ ContextMenuItemTagUnicodeInsertRLMMark,
+ ContextMenuItemTagUnicodeInsertLREMark,
+ ContextMenuItemTagUnicodeInsertRLEMark,
+ ContextMenuItemTagUnicodeInsertLROMark,
+ ContextMenuItemTagUnicodeInsertRLOMark,
+ ContextMenuItemTagUnicodeInsertPDFMark,
+ ContextMenuItemTagUnicodeInsertZWSMark,
+ ContextMenuItemTagUnicodeInsertZWJMark,
+ ContextMenuItemTagUnicodeInsertZWNJMark,
#endif
ContextMenuItemTagSpellingGuess,
ContextMenuItemTagNoGuessesFound,
@@ -163,6 +176,7 @@ namespace WebCore {
SubmenuType
};
+#if ENABLE(CONTEXT_MENUS)
#if PLATFORM(MAC)
typedef NSMenuItem* PlatformMenuItemDescription;
#elif PLATFORM(QT)
@@ -291,6 +305,7 @@ namespace WebCore {
#endif // USE(CROSS_PLATFORM_CONTEXT_MENUS)
};
+#endif // ENABLE(CONTEXT_MENUS)
}
#endif // ContextMenuItem_h
diff --git a/Source/WebCore/platform/Cursor.h b/Source/WebCore/platform/Cursor.h
index bc5184070..d52f67cad 100644
--- a/Source/WebCore/platform/Cursor.h
+++ b/Source/WebCore/platform/Cursor.h
@@ -43,6 +43,8 @@ typedef HICON HCURSOR;
#include <QCursor>
#elif PLATFORM(CHROMIUM)
#include "PlatformCursor.h"
+#elif PLATFORM(BLACKBERRY)
+#include <BlackBerryPlatformCursor.h>
#endif
#if PLATFORM(MAC) && !PLATFORM(IOS)
@@ -90,6 +92,8 @@ namespace WebCore {
typedef wxCursor* PlatformCursor;
#elif PLATFORM(CHROMIUM)
// See PlatformCursor.h
+#elif PLATFORM(BLACKBERRY)
+ typedef BlackBerry::Platform::BlackBerryCursor PlatformCursor;
#else
typedef void* PlatformCursor;
#endif
@@ -146,7 +150,7 @@ namespace WebCore {
static const Cursor& fromType(Cursor::Type);
Cursor()
-#if !PLATFORM(IOS)
+#if !PLATFORM(IOS) && !PLATFORM(BLACKBERRY)
: m_platformCursor(0)
#endif
{
diff --git a/Source/WebCore/platform/DragData.h b/Source/WebCore/platform/DragData.h
index 6737b8f16..823ac553e 100644
--- a/Source/WebCore/platform/DragData.h
+++ b/Source/WebCore/platform/DragData.h
@@ -63,7 +63,7 @@ class DataObjectGtk;
typedef WebCore::DataObjectGtk* DragDataRef;
#elif PLATFORM(CHROMIUM)
#include "DragDataRef.h"
-#elif PLATFORM(EFL)
+#elif PLATFORM(EFL) || PLATFORM(BLACKBERRY)
typedef void* DragDataRef;
#endif
diff --git a/Source/WebCore/platform/DragImage.h b/Source/WebCore/platform/DragImage.h
index a22db6a76..dd970d293 100644
--- a/Source/WebCore/platform/DragImage.h
+++ b/Source/WebCore/platform/DragImage.h
@@ -26,6 +26,7 @@
#ifndef DragImage_h
#define DragImage_h
+#include "ImageOrientation.h"
#include "IntSize.h"
#include "FloatSize.h"
#include <wtf/Forward.h>
@@ -81,7 +82,7 @@ namespace WebCore {
DragImageRef scaleDragImage(DragImageRef, FloatSize scale);
DragImageRef dissolveDragImageToFraction(DragImageRef image, float delta);
- DragImageRef createDragImageFromImage(Image*);
+ DragImageRef createDragImageFromImage(Image*, RespectImageOrientationEnum = DoNotRespectImageOrientation);
DragImageRef createDragImageForSelection(Frame*);
DragImageRef createDragImageIconForCachedImage(CachedImage*);
DragImageRef createDragImageForLink(KURL&, const String& label, Frame*);
diff --git a/Source/WebCore/platform/FileChooser.cpp b/Source/WebCore/platform/FileChooser.cpp
index a9792aa6a..50e4c6011 100644
--- a/Source/WebCore/platform/FileChooser.cpp
+++ b/Source/WebCore/platform/FileChooser.cpp
@@ -78,8 +78,25 @@ void FileChooser::chooseFiles(const Vector<String>& filenames)
if (m_settings.selectedFiles == filenames)
return;
+ if (m_client) {
+ Vector<FileChooserFileInfo> files;
+ for (unsigned i = 0; i < filenames.size(); ++i)
+ files.append(FileChooserFileInfo(filenames[i]));
+ m_client->filesChosen(files);
+ }
+}
+
+void FileChooser::chooseFiles(const Vector<FileChooserFileInfo>& files)
+{
+ // FIXME: This is inelegant. We should not be looking at settings here.
+ Vector<String> paths;
+ for (unsigned i = 0; i < files.size(); ++i)
+ paths.append(files[i].path);
+ if (m_settings.selectedFiles == paths)
+ return;
+
if (m_client)
- m_client->filesChosen(filenames);
+ m_client->filesChosen(files);
}
}
diff --git a/Source/WebCore/platform/FileChooser.h b/Source/WebCore/platform/FileChooser.h
index cc20be281..98dc99cc8 100644
--- a/Source/WebCore/platform/FileChooser.h
+++ b/Source/WebCore/platform/FileChooser.h
@@ -38,6 +38,17 @@ namespace WebCore {
class FileChooser;
+struct FileChooserFileInfo {
+ FileChooserFileInfo(const String& path, const String& displayName = String())
+ : path(path)
+ , displayName(displayName)
+ {
+ }
+
+ const String path;
+ const String displayName;
+};
+
struct FileChooserSettings {
bool allowsMultipleFiles;
#if ENABLE(DIRECTORY_UPLOAD)
@@ -49,7 +60,7 @@ struct FileChooserSettings {
class FileChooserClient {
public:
- virtual void filesChosen(const Vector<String>&) = 0;
+ virtual void filesChosen(const Vector<FileChooserFileInfo>&) = 0;
virtual ~FileChooserClient();
protected:
@@ -71,6 +82,9 @@ public:
void chooseFile(const String& path);
void chooseFiles(const Vector<String>& paths);
+ // FIXME: We should probably just pass file paths that could be virtual paths with proper display names rather than passing structs.
+ void chooseFiles(const Vector<FileChooserFileInfo>& files);
+
const FileChooserSettings& settings() const { return m_settings; }
private:
diff --git a/Source/WebCore/platform/FileSystemType.h b/Source/WebCore/platform/FileSystemType.h
new file mode 100644
index 000000000..a2fd9ae63
--- /dev/null
+++ b/Source/WebCore/platform/FileSystemType.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FileSystemType_h
+#define FileSystemType_h
+
+#if ENABLE(FILE_SYSTEM)
+
+namespace WebCore {
+
+// For file system types used in FileSystem API.
+enum FileSystemType {
+ FileSystemTypeTemporary,
+ FileSystemTypePersistent,
+
+#if PLATFORM(CHROMIUM)
+ // Temporary isolated non-sandbox filesystem.
+ FileSystemTypeIsolated,
+
+ // Non-sandbox filesystem.
+ FileSystemTypeExternal,
+#endif
+};
+
+enum FileSystemSynchronousType {
+ AsynchronousFileSystem,
+ SynchronousFileSystem,
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(FILE_SYSTEM)
+
+#endif // FileSystemType_h
diff --git a/Source/WebCore/platform/FractionalLayoutUnit.h b/Source/WebCore/platform/FractionalLayoutUnit.h
index 77adaa796..193ec984d 100644
--- a/Source/WebCore/platform/FractionalLayoutUnit.h
+++ b/Source/WebCore/platform/FractionalLayoutUnit.h
@@ -33,26 +33,49 @@
#include <limits.h>
#include <limits>
+#include <math.h>
#include <stdlib.h>
namespace WebCore {
+#ifdef NDEBUG
+
+#define REPORT_OVERFLOW(doesOverflow) ((void)0)
+
+#else
+
+#define REPORT_OVERFLOW(doesOverflow) do \
+ if (!(doesOverflow)) { \
+ WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, "!(%s)", #doesOverflow); \
+ } \
+while (0)
+
+#endif
+
+#if ENABLE(SUBPIXEL_LAYOUT)
static const int kFixedPointDenominator = 60;
+#else
+static const int kFixedPointDenominator = 1;
+#endif
const int intMaxForLayoutUnit = INT_MAX / kFixedPointDenominator;
const int intMinForLayoutUnit = -intMaxForLayoutUnit;
class FractionalLayoutUnit {
public:
+ // FIXME: Ideally we would have size_t versions of the constructor and operators.
+ // However due to compiler and platform differences adding those are non-trivial.
+ // See https://bugs.webkit.org/show_bug.cgi?id=83848 for details.
+
FractionalLayoutUnit() : m_value(0) { }
- FractionalLayoutUnit(int value) { ASSERT(isInBounds(value)); m_value = value * kFixedPointDenominator; }
- FractionalLayoutUnit(unsigned short value) { ASSERT(isInBounds(value)); m_value = value * kFixedPointDenominator; }
- FractionalLayoutUnit(unsigned int value) { ASSERT(isInBounds(value)); m_value = value * kFixedPointDenominator; }
- FractionalLayoutUnit(float value) { ASSERT(isInBounds(value)); m_value = value * kFixedPointDenominator; }
- FractionalLayoutUnit(double value) { ASSERT(isInBounds(value)); m_value = value * kFixedPointDenominator; }
+ FractionalLayoutUnit(int value) { REPORT_OVERFLOW(isInBounds(value)); m_value = value * kFixedPointDenominator; }
+ FractionalLayoutUnit(unsigned short value) { REPORT_OVERFLOW(isInBounds(value)); m_value = value * kFixedPointDenominator; }
+ FractionalLayoutUnit(unsigned int value) { REPORT_OVERFLOW(isInBounds(value)); m_value = value * kFixedPointDenominator; }
+ FractionalLayoutUnit(float value) { REPORT_OVERFLOW(isInBounds(value)); m_value = value * kFixedPointDenominator; }
+ FractionalLayoutUnit(double value) { REPORT_OVERFLOW(isInBounds(value)); m_value = value * kFixedPointDenominator; }
FractionalLayoutUnit(const FractionalLayoutUnit& value) { m_value = value.rawValue(); }
inline int toInt() const { return m_value / kFixedPointDenominator; }
- inline unsigned toUnsigned() const { ASSERT(m_value >= 0); return toInt(); }
+ inline unsigned toUnsigned() const { REPORT_OVERFLOW(m_value >= 0); return toInt(); }
inline float toFloat() const { return static_cast<float>(m_value) / kFixedPointDenominator; }
inline double toDouble() const { return static_cast<double>(m_value) / kFixedPointDenominator; }
@@ -62,38 +85,44 @@ public:
operator double() const { return toDouble(); }
operator bool() const { return m_value; }
+ inline FractionalLayoutUnit operator++(int)
+ {
+ m_value += kFixedPointDenominator;
+ return *this;
+ }
+
inline int rawValue() const { return m_value; }
inline void setRawValue(int value) { m_value = value; }
inline void setRawValue(long long value)
{
- ASSERT(value > std::numeric_limits<int>::min() && value < std::numeric_limits<int>::max());
+ REPORT_OVERFLOW(value > std::numeric_limits<int>::min() && value < std::numeric_limits<int>::max());
m_value = static_cast<int>(value);
}
- inline FractionalLayoutUnit abs()
+ inline FractionalLayoutUnit abs() const
{
FractionalLayoutUnit returnValue;
returnValue.setRawValue(::abs(m_value));
return returnValue;
}
#if OS(DARWIN)
- inline int wtf_ceil()
+ inline int wtf_ceil() const
#else
- inline int ceil()
+ inline int ceil() const
#endif
{
if (m_value > 0)
return (m_value + kFixedPointDenominator - 1) / kFixedPointDenominator;
return (m_value - kFixedPointDenominator + 1) / kFixedPointDenominator;
}
- inline int round()
+ inline int round() const
{
if (m_value > 0)
return (m_value + (kFixedPointDenominator / 2)) / kFixedPointDenominator;
return (m_value - (kFixedPointDenominator / 2)) / kFixedPointDenominator;
}
- inline int floor()
+ inline int floor() const
{
return toInt();
}
@@ -115,15 +144,15 @@ public:
private:
inline bool isInBounds(int value)
{
- return ::abs(value) < std::numeric_limits<int>::max() / kFixedPointDenominator;
+ return ::abs(value) <= std::numeric_limits<int>::max() / kFixedPointDenominator;
}
inline bool isInBounds(unsigned value)
{
- return value < static_cast<unsigned>(std::numeric_limits<int>::max()) / kFixedPointDenominator;
+ return value <= static_cast<unsigned>(std::numeric_limits<int>::max()) / kFixedPointDenominator;
}
inline bool isInBounds(double value)
{
- return ::fabs(value) < std::numeric_limits<int>::max() / kFixedPointDenominator;
+ return ::fabs(value) <= std::numeric_limits<int>::max() / kFixedPointDenominator;
}
int m_value;
@@ -194,6 +223,11 @@ inline bool operator<(const FractionalLayoutUnit& a, float b)
return a.toFloat() < b;
}
+inline bool operator<(const FractionalLayoutUnit& a, double b)
+{
+ return a.toDouble() < b;
+}
+
inline bool operator<(const int a, const FractionalLayoutUnit& b)
{
return FractionalLayoutUnit(a) < b;
@@ -378,6 +412,11 @@ inline float operator/(const float a, const FractionalLayoutUnit& b)
return a / b.toFloat();
}
+inline double operator/(const double a, const FractionalLayoutUnit& b)
+{
+ return a / b.toDouble();
+}
+
inline FractionalLayoutUnit operator/(const int a, const FractionalLayoutUnit& b)
{
return FractionalLayoutUnit(a) / b;
@@ -420,6 +459,11 @@ inline float operator+(const float a, const FractionalLayoutUnit& b)
return a + b.toFloat();
}
+inline double operator+(const double a, const FractionalLayoutUnit& b)
+{
+ return a + b.toDouble();
+}
+
inline FractionalLayoutUnit operator-(const FractionalLayoutUnit& a, const FractionalLayoutUnit& b)
{
FractionalLayoutUnit returnVal;
@@ -432,6 +476,11 @@ inline FractionalLayoutUnit operator-(const FractionalLayoutUnit& a, int b)
return a - FractionalLayoutUnit(b);
}
+inline FractionalLayoutUnit operator-(const FractionalLayoutUnit& a, unsigned b)
+{
+ return a - FractionalLayoutUnit(b);
+}
+
inline float operator-(const FractionalLayoutUnit& a, float b)
{
return a.toFloat() - b;
diff --git a/Source/WebCore/platform/GeolocationService.cpp b/Source/WebCore/platform/GeolocationService.cpp
deleted file mode 100644
index f8793a170..000000000
--- a/Source/WebCore/platform/GeolocationService.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "GeolocationService.h"
-
-#include "GeolocationServiceMock.h"
-#include "Geoposition.h"
-#include "PositionError.h"
-
-#include <wtf/Assertions.h>
-#include <wtf/CurrentTime.h>
-
-namespace WebCore {
-
-#if !ENABLE(GEOLOCATION) || ENABLE(CLIENT_BASED_GEOLOCATION)
-static PassOwnPtr<GeolocationService> createGeolocationServiceNull(GeolocationServiceClient*)
-{
- return nullptr;
-}
-
-GeolocationService::FactoryFunction* GeolocationService::s_factoryFunction = &createGeolocationServiceNull;
-GeolocationService::FactoryFunction* GeolocationService::s_mockFactoryFunction = &createGeolocationServiceNull;
-#else
-GeolocationService::FactoryFunction* GeolocationService::s_mockFactoryFunction = &GeolocationServiceMock::create;
-#endif
-
-PassOwnPtr<GeolocationService> GeolocationService::create(GeolocationServiceClient* client)
-{
- return (*s_factoryFunction)(client);
-}
-
-#if ENABLE(GEOLOCATION)
-void GeolocationService::useMock()
-{
- s_factoryFunction = s_mockFactoryFunction;
-}
-
-void GeolocationService::setCustomMockFactory(FactoryFunction f)
-{
- s_mockFactoryFunction = f;
-}
-
-GeolocationService::GeolocationService(GeolocationServiceClient* client)
- : m_geolocationServiceClient(client)
-{
- ASSERT(m_geolocationServiceClient);
-}
-
-void GeolocationService::positionChanged()
-{
- m_geolocationServiceClient->geolocationServicePositionChanged(this);
-}
-
-void GeolocationService::errorOccurred()
-{
- m_geolocationServiceClient->geolocationServiceErrorOccurred(this);
-}
-
-#endif
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/GeolocationService.h b/Source/WebCore/platform/GeolocationService.h
deleted file mode 100644
index 5ba9fd753..000000000
--- a/Source/WebCore/platform/GeolocationService.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef GeolocationService_h
-#define GeolocationService_h
-
-#include <wtf/Noncopyable.h>
-#include <wtf/PassOwnPtr.h>
-
-namespace WebCore {
-
-class GeolocationService;
-class Geoposition;
-class PositionError;
-class PositionOptions;
-
-class GeolocationServiceClient {
-public:
- virtual ~GeolocationServiceClient() { }
- virtual void geolocationServicePositionChanged(GeolocationService*) = 0;
- virtual void geolocationServiceErrorOccurred(GeolocationService*) = 0;
-};
-
-class GeolocationService {
- WTF_MAKE_NONCOPYABLE(GeolocationService);
-public:
- static PassOwnPtr<GeolocationService> create(GeolocationServiceClient*);
- virtual ~GeolocationService() { }
-
- virtual bool startUpdating(PositionOptions*) { return false; }
- virtual void stopUpdating() { }
-
- virtual Geoposition* lastPosition() const { return 0; }
- virtual PositionError* lastError() const { return 0; }
-
- void positionChanged();
- void errorOccurred();
-
- static void useMock();
- typedef PassOwnPtr<GeolocationService> (FactoryFunction)(GeolocationServiceClient*);
- static void setCustomMockFactory(FactoryFunction);
-
-protected:
- GeolocationService(GeolocationServiceClient*);
- GeolocationServiceClient* geolocationServiceClient() const { return m_geolocationServiceClient; }
-
-private:
- GeolocationServiceClient* m_geolocationServiceClient;
-
- static FactoryFunction* s_factoryFunction;
- static FactoryFunction* s_mockFactoryFunction;
-};
-
-} // namespace WebCore
-
-#endif // GeolocationService_h
-
diff --git a/Source/WebCore/platform/HistogramSupport.cpp b/Source/WebCore/platform/HistogramSupport.cpp
index 8052fdacc..d9ea79c27 100644
--- a/Source/WebCore/platform/HistogramSupport.cpp
+++ b/Source/WebCore/platform/HistogramSupport.cpp
@@ -37,4 +37,8 @@ void HistogramSupport::histogramEnumeration(const char*, int, int)
{
}
+void HistogramSupport::histogramCustomCounts(const char*, int, int, int, int)
+{
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/HistogramSupport.h b/Source/WebCore/platform/HistogramSupport.h
index 5811e3282..9bb265a8f 100644
--- a/Source/WebCore/platform/HistogramSupport.h
+++ b/Source/WebCore/platform/HistogramSupport.h
@@ -36,6 +36,7 @@ namespace WebCore {
class HistogramSupport {
public:
static void histogramEnumeration(const char* name, int sample, int boundaryValue);
+ static void histogramCustomCounts(const char* name, int sample, int min, int max, int bucketCount);
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/KURL.cpp b/Source/WebCore/platform/KURL.cpp
index ad5feea3b..0b46ec0fc 100644
--- a/Source/WebCore/platform/KURL.cpp
+++ b/Source/WebCore/platform/KURL.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2004, 2007, 2008, 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -44,7 +45,7 @@
#include <QUrl>
#elif USE(GLIB_UNICODE)
#include <glib.h>
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#endif
// FIXME: This file makes too much use of the + operator on String.
@@ -761,21 +762,24 @@ void KURL::setUser(const String& user)
// FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations,
// and to avoid changing more than just the user login.
- String u;
+
int end = m_userEnd;
if (!user.isEmpty()) {
- u = user;
+ String u = user;
if (m_userStart == m_schemeEnd + 1)
u = "//" + u;
// Add '@' if we didn't have one before.
if (end == m_hostEnd || (end == m_passwordEnd && m_string[end] != '@'))
u.append('@');
+ parse(m_string.left(m_userStart) + u + m_string.substring(end));
} else {
// Remove '@' if we now have neither user nor password.
if (m_userEnd == m_passwordEnd && end != m_hostEnd && m_string[end] == '@')
end += 1;
+ // We don't want to parse in the extremely common case where we are not going to make a change.
+ if (m_userStart != end)
+ parse(m_string.left(m_userStart) + m_string.substring(end));
}
- parse(m_string.left(m_userStart) + u + m_string.substring(end));
}
void KURL::setPass(const String& password)
@@ -785,21 +789,24 @@ void KURL::setPass(const String& password)
// FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations,
// and to avoid changing more than just the user password.
- String p;
+
int end = m_passwordEnd;
if (!password.isEmpty()) {
- p = ":" + password + "@";
+ String p = ":" + password + "@";
if (m_userEnd == m_schemeEnd + 1)
p = "//" + p;
// Eat the existing '@' since we are going to add our own.
if (end != m_hostEnd && m_string[end] == '@')
end += 1;
+ parse(m_string.left(m_userEnd) + p + m_string.substring(end));
} else {
// Remove '@' if we now have neither user nor password.
if (m_userStart == m_userEnd && end != m_hostEnd && m_string[end] == '@')
end += 1;
+ // We don't want to parse in the extremely common case where we are not going to make a change.
+ if (m_userEnd != end)
+ parse(m_string.left(m_userEnd) + m_string.substring(end));
}
- parse(m_string.left(m_userEnd) + p + m_string.substring(end));
}
void KURL::setFragmentIdentifier(const String& s)
@@ -1107,6 +1114,17 @@ void KURL::parse(const char* url, const String* originalString)
&& isLetterMatchIgnoringCase(url[2], 'l')
&& isLetterMatchIgnoringCase(url[3], 'e');
+#if PLATFORM(BLACKBERRY)
+ // Parse local: urls the same as file: urls.
+ if (!isFile)
+ isFile = schemeEnd == 5
+ && isLetterMatchIgnoringCase(url[0], 'l')
+ && isLetterMatchIgnoringCase(url[1], 'o')
+ && isLetterMatchIgnoringCase(url[2], 'c')
+ && isLetterMatchIgnoringCase(url[3], 'a')
+ && isLetterMatchIgnoringCase(url[4], 'l');
+#endif
+
m_protocolIsInHTTPFamily = isLetterMatchIgnoringCase(url[0], 'h')
&& isLetterMatchIgnoringCase(url[1], 't')
&& isLetterMatchIgnoringCase(url[2], 't')
@@ -1754,6 +1772,11 @@ const KURL& blankURL()
return staticBlankURL;
}
+bool KURL::isBlankURL() const
+{
+ return protocolIs("about");
+}
+
bool isDefaultPortForProtocol(unsigned short port, const String& protocol)
{
if (protocol.isEmpty())
@@ -1871,6 +1894,11 @@ bool portAllowed(const KURL& url)
if (url.protocolIs("file"))
return true;
+#if PLATFORM(BLACKBERRY)
+ if (url.protocolIs("local"))
+ return true;
+#endif
+
return false;
}
diff --git a/Source/WebCore/platform/KURL.h b/Source/WebCore/platform/KURL.h
index 3cba090aa..ee67e16fc 100644
--- a/Source/WebCore/platform/KURL.h
+++ b/Source/WebCore/platform/KURL.h
@@ -155,6 +155,7 @@ public:
bool protocolIsData() const { return protocolIs("data"); }
bool protocolIsInHTTPFamily() const;
bool isLocalFile() const;
+ bool isBlankURL() const;
bool setProtocol(const String&);
void setHost(const String&);
@@ -273,7 +274,7 @@ bool operator!=(const String&, const KURL&);
bool equalIgnoringFragmentIdentifier(const KURL&, const KURL&);
bool protocolHostAndPortAreEqual(const KURL&, const KURL&);
-
+
const KURL& blankURL();
// Functions to do URL operations on strings.
diff --git a/Source/WebCore/platform/Length.h b/Source/WebCore/platform/Length.h
index 2bcf93262..0c963dd85 100644
--- a/Source/WebCore/platform/Length.h
+++ b/Source/WebCore/platform/Length.h
@@ -2,6 +2,7 @@
Copyright (C) 1999 Lars Knoll (knoll@kde.org)
Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
Copyright (C) 2011 Rik Cabanier (cabanier@adobe.com)
+ Copyright (C) 2011 Adobe Systems Incorporated. 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
@@ -23,6 +24,7 @@
#define Length_h
#include "AnimationUtilities.h"
+#include "LayoutTypes.h"
#include <wtf/Assertions.h>
#include <wtf/FastAllocBase.h>
#include <wtf/Forward.h>
@@ -32,10 +34,7 @@
namespace WebCore {
-const int intMaxForLength = 0x7ffffff; // max value for a 28-bit int
-const int intMinForLength = (-0x7ffffff - 1); // min value for a 28-bit int
-
-enum LengthType { Auto, Relative, Percent, Fixed, Intrinsic, MinIntrinsic, Calculated, Undefined };
+enum LengthType { Auto, Relative, Percent, Fixed, Intrinsic, MinIntrinsic, Calculated, ViewportPercentageWidth, ViewportPercentageHeight, ViewportPercentageMin, Undefined };
class CalculationValue;
@@ -57,6 +56,11 @@ public:
{
}
+ Length(FractionalLayoutUnit v, LengthType t, bool q = false)
+ : m_floatValue(v.toFloat()), m_quirk(q), m_type(t), m_isFloat(true)
+ {
+ }
+
Length(float v, LengthType t, bool q = false)
: m_floatValue(v), m_quirk(q), m_type(t), m_isFloat(true)
{
@@ -105,8 +109,13 @@ public:
return *this;
}
- int value() const
+ inline float value() const
{
+ return getFloatValue();
+ }
+
+ int intValue() const
+ {
if (isCalculated()) {
ASSERT_NOT_REACHED();
return 0;
@@ -153,76 +162,16 @@ public:
m_isFloat = true;
}
- void setValue(float value)
- {
- *this = Length(value, Fixed);
- }
-
- int calcValue(int maxValue, bool roundPercentages = false) const
- {
- switch (type()) {
- case Fixed:
- case Percent:
- case Calculated:
- return calcMinValue(maxValue, roundPercentages);
- case Auto:
- return maxValue;
- case Relative:
- case Intrinsic:
- case MinIntrinsic:
- case Undefined:
- ASSERT_NOT_REACHED();
- return 0;
- }
- ASSERT_NOT_REACHED();
- return 0;
- }
-
- int calcMinValue(int maxValue, bool roundPercentages = false) const
+ void setValue(LengthType t, FractionalLayoutUnit value)
{
- switch (type()) {
- case Fixed:
- return value();
- case Percent:
- if (roundPercentages)
- return static_cast<int>(round(maxValue * percent() / 100.0f));
- // Don't remove the extra cast to float. It is needed for rounding on 32-bit Intel machines that use the FPU stack.
- return static_cast<int>(static_cast<float>(maxValue * percent() / 100.0f));
- case Calculated:
- return nonNanCalculatedValue(maxValue);
- case Auto:
- return 0;
- case Relative:
- case Intrinsic:
- case MinIntrinsic:
- case Undefined:
- ASSERT_NOT_REACHED();
- return 0;
- }
- ASSERT_NOT_REACHED();
- return 0;
+ m_type = t;
+ m_floatValue = value;
+ m_isFloat = true;
}
- float calcFloatValue(int maxValue) const
+ void setValue(float value)
{
- switch (type()) {
- case Fixed:
- return getFloatValue();
- case Percent:
- return static_cast<float>(maxValue * percent() / 100.0f);
- case Auto:
- return static_cast<float>(maxValue);
- case Calculated:
- return nonNanCalculatedValue(maxValue);
- case Relative:
- case Intrinsic:
- case MinIntrinsic:
- case Undefined:
- ASSERT_NOT_REACHED();
- return 0;
- }
- ASSERT_NOT_REACHED();
- return 0;
+ *this = Length(value, Fixed);
}
bool isUndefined() const { return type() == Undefined; }
@@ -261,7 +210,7 @@ public:
bool isPercent() const { return type() == Percent || type() == Calculated; }
bool isFixed() const { return type() == Fixed; }
bool isIntrinsicOrAuto() const { return type() == Auto || type() == MinIntrinsic || type() == Intrinsic; }
- bool isSpecified() const { return type() == Fixed || type() == Percent || type() == Calculated; }
+ bool isSpecified() const { return type() == Fixed || type() == Percent || type() == Calculated || isViewportPercentage(); }
bool isCalculated() const { return type() == Calculated; }
Length blend(const Length& from, double progress) const
@@ -288,19 +237,29 @@ public:
return Length(WebCore::blend(fromValue, toValue, progress), resultType);
}
-private:
- int getIntValue() const
+ float getFloatValue() const
{
ASSERT(!isUndefined());
- return m_isFloat ? static_cast<int>(m_floatValue) : m_intValue;
+ return m_isFloat ? m_floatValue : m_intValue;
}
+ float nonNanCalculatedValue(int maxValue) const;
- float getFloatValue() const
+ bool isViewportPercentage() const
+ {
+ LengthType lengthType = type();
+ return lengthType >= ViewportPercentageWidth && lengthType <= ViewportPercentageMin;
+ }
+ float viewportPercentageLength() const
+ {
+ ASSERT(isViewportPercentage());
+ return getFloatValue();
+ }
+private:
+ int getIntValue() const
{
ASSERT(!isUndefined());
- return m_isFloat ? m_floatValue : m_intValue;
+ return m_isFloat ? static_cast<int>(m_floatValue) : m_intValue;
}
-
void initFromLength(const Length &length)
{
m_quirk = length.m_quirk;
@@ -315,8 +274,7 @@ private:
if (isCalculated())
incrementCalculatedRef();
}
-
- float nonNanCalculatedValue(int maxValue) const;
+
int calculationHandle() const
{
ASSERT(isCalculated());
diff --git a/Source/WebCore/platform/LocalizedStrings.cpp b/Source/WebCore/platform/LocalizedStrings.cpp
index 27d17f03f..24c9aa415 100644
--- a/Source/WebCore/platform/LocalizedStrings.cpp
+++ b/Source/WebCore/platform/LocalizedStrings.cpp
@@ -567,6 +567,11 @@ String AXDefinitionListDefinitionText()
return WEB_UI_STRING("definition", "definition phrase");
}
+String AXFooterRoleDescriptionText()
+{
+ return WEB_UI_STRING("footer", "accessibility role description for a footer");
+}
+
#if PLATFORM(MAC)
String AXARIAContentGroupText(const String& ariaType)
{
@@ -599,7 +604,7 @@ String AXARIAContentGroupText(const String& ariaType)
if (ariaType == "ARIALandmarkComplementary")
return WEB_UI_STRING("complementary", "An ARIA accessibility group that acts as a region of complementary information.");
if (ariaType == "ARIALandmarkContentInfo")
- return WEB_UI_STRING("content", "An ARIA accessibility group that contains content.");
+ return WEB_UI_STRING("content information", "An ARIA accessibility group that contains content.");
if (ariaType == "ARIALandmarkMain")
return WEB_UI_STRING("main", "An ARIA accessibility group that is the main portion of the website.");
if (ariaType == "ARIALandmarkNavigation")
@@ -806,8 +811,10 @@ String localizedMediaControlElementString(const String& name)
return WEB_UI_STRING("remaining time", "accessibility role description for time remaining display");
if (name == "StatusDisplay")
return WEB_UI_STRING("status", "accessibility role description for movie status");
- if (name == "FullscreenButton")
- return WEB_UI_STRING("fullscreen", "accessibility role description for enter fullscreen button");
+ if (name == "EnterFullscreenButton")
+ return WEB_UI_STRING("enter fullscreen", "accessibility role description for enter fullscreen button");
+ if (name == "ExitFullscreenButton")
+ return WEB_UI_STRING("exit fullscreen", "accessibility role description for exit fullscreen button");
if (name == "SeekForwardButton")
return WEB_UI_STRING("fast forward", "accessibility role description for fast forward button");
if (name == "SeekBackButton")
diff --git a/Source/WebCore/platform/LocalizedStrings.h b/Source/WebCore/platform/LocalizedStrings.h
index 3ebbef722..cda8bd69d 100644
--- a/Source/WebCore/platform/LocalizedStrings.h
+++ b/Source/WebCore/platform/LocalizedStrings.h
@@ -69,6 +69,16 @@ namespace WebCore {
String contextMenuItemTagDelete();
String contextMenuItemTagInputMethods();
String contextMenuItemTagUnicode();
+ String contextMenuItemTagUnicodeInsertLRMMark();
+ String contextMenuItemTagUnicodeInsertRLMMark();
+ String contextMenuItemTagUnicodeInsertLREMark();
+ String contextMenuItemTagUnicodeInsertRLEMark();
+ String contextMenuItemTagUnicodeInsertLROMark();
+ String contextMenuItemTagUnicodeInsertRLOMark();
+ String contextMenuItemTagUnicodeInsertPDFMark();
+ String contextMenuItemTagUnicodeInsertZWSMark();
+ String contextMenuItemTagUnicodeInsertZWJMark();
+ String contextMenuItemTagUnicodeInsertZWNJMark();
#endif
#if PLATFORM(GTK) || PLATFORM(QT) || PLATFORM(EFL)
String contextMenuItemTagSelectAll();
@@ -141,7 +151,7 @@ namespace WebCore {
String AXHeadingText();
String AXDefinitionListTermText();
String AXDefinitionListDefinitionText();
-
+ String AXFooterRoleDescriptionText();
#if PLATFORM(MAC)
String AXARIAContentGroupText(const String& ariaType);
#endif
@@ -201,6 +211,13 @@ namespace WebCore {
String validationMessageRangeUnderflowText(const String& minimum);
String validationMessageRangeOverflowText(const String& maximum);
String validationMessageStepMismatchText(const String& base, const String& step);
+#if ENABLE(CALENDAR_PICKER)
+ String calendarTodayText();
+ String calendarClearText();
+ String dateFormatYearText();
+ String dateFormatMonthText();
+ String dateFormatDayInMonthText();
+#endif
#if !PLATFORM(CHROMIUM)
#define WEB_UI_STRING(string, description) WebCore::localizedString(string)
diff --git a/Source/WebCore/platform/Logging.cpp b/Source/WebCore/platform/Logging.cpp
index bd0196410..34637a7cc 100644
--- a/Source/WebCore/platform/Logging.cpp
+++ b/Source/WebCore/platform/Logging.cpp
@@ -62,6 +62,8 @@ WTFLogChannel LogProgress = { 0x08000000, "WebCoreLogLevel", WTFLogChan
WTFLogChannel LogFileAPI = { 0x10000000, "WebCoreLogLevel", WTFLogChannelOff };
WTFLogChannel LogWebAudio = { 0x20000000, "WebCoreLogLevel", WTFLogChannelOff };
+WTFLogChannel LogCompositing = { 0x40000000, "WebCoreLogLevel", WTFLogChannelOff };
+
WTFLogChannel* getChannelFromName(const String& channelName)
{
@@ -140,6 +142,9 @@ WTFLogChannel* getChannelFromName(const String& channelName)
if (equalIgnoringCase(channelName, String("WebAudio")))
return &LogWebAudio;
+ if (equalIgnoringCase(channelName, String("Compositing")))
+ return &LogCompositing;
+
return 0;
}
diff --git a/Source/WebCore/platform/Logging.h b/Source/WebCore/platform/Logging.h
index 8201f16b3..1af1c04ab 100644
--- a/Source/WebCore/platform/Logging.h
+++ b/Source/WebCore/platform/Logging.h
@@ -60,6 +60,7 @@ namespace WebCore {
extern WTFLogChannel LogProgress;
extern WTFLogChannel LogFileAPI;
extern WTFLogChannel LogWebAudio;
+ extern WTFLogChannel LogCompositing;
void initializeLoggingChannelsIfNecessary();
WTFLogChannel* getChannelFromName(const String& channelName);
diff --git a/Source/WebCore/platform/MIMETypeRegistry.cpp b/Source/WebCore/platform/MIMETypeRegistry.cpp
index 8e1e8e8aa..de2aca671 100644..100755
--- a/Source/WebCore/platform/MIMETypeRegistry.cpp
+++ b/Source/WebCore/platform/MIMETypeRegistry.cpp
@@ -139,7 +139,6 @@ static const TypeExtensionPair commonMediaTypes[] = {
{ "audio/x-wav", "wav" }
};
-#if ENABLE(FILE_SYSTEM)
static const char textPlain[] = "text/plain";
static const char textHtml[] = "text/html";
static const char imageJpeg[] = "image/jpeg";
@@ -181,7 +180,6 @@ static const TypeExtensionPair wellKnownMimeTypes[] = {
{ "application/rdf+xml", "rdf" },
{ "application/x-shockwave-flash", "swf" },
};
-#endif
static HashSet<String>* supportedImageResourceMIMETypes;
static HashSet<String>* supportedImageMIMETypes;
@@ -261,10 +259,6 @@ static void initializeSupportedImageMIMETypes()
supportedImageMIMETypes->add(types[i]);
supportedImageResourceMIMETypes->add(types[i]);
}
-#if PLATFORM(BLACKBERRY)
- supportedImageMIMETypes->add("image/pjpeg");
- supportedImageResourceMIMETypes->add("image/pjpeg");
-#endif
#endif
}
@@ -296,7 +290,7 @@ static void initializeSupportedImageMIMETypesForEncoding()
if (!mimeType.isEmpty())
supportedImageMIMETypesForEncoding->add(mimeType);
}
-#elif PLATFORM(GTK)
+#elif PLATFORM(GTK) || (PLATFORM(QT) && !USE(QT_IMAGE_DECODER))
supportedImageMIMETypesForEncoding->add("image/png");
supportedImageMIMETypesForEncoding->add("image/jpeg");
supportedImageMIMETypesForEncoding->add("image/tiff");
@@ -304,6 +298,9 @@ static void initializeSupportedImageMIMETypesForEncoding()
supportedImageMIMETypesForEncoding->add("image/ico");
#elif USE(CAIRO)
supportedImageMIMETypesForEncoding->add("image/png");
+#elif PLATFORM(BLACKBERRY)
+ supportedImageMIMETypesForEncoding->add("image/png");
+ supportedImageMIMETypesForEncoding->add("image/jpeg");
#endif
}
@@ -474,7 +471,6 @@ static void initializeMIMETypeRegistry()
initializeUnsupportedTextMIMETypes();
}
-#if ENABLE(FILE_SYSTEM)
static String findMimeType(const TypeExtensionPair* pairs, unsigned numPairs, const String& extension)
{
if (!extension.isEmpty()) {
@@ -494,7 +490,6 @@ String MIMETypeRegistry::getWellKnownMIMETypeForExtension(const String& extensio
return found;
return findMimeType(commonMediaTypes, sizeof(commonMediaTypes) / sizeof(commonMediaTypes[0]), extension);
}
-#endif
String MIMETypeRegistry::getMIMETypeForPath(const String& path)
{
@@ -514,7 +509,7 @@ bool MIMETypeRegistry::isSupportedImageMIMEType(const String& mimeType)
return false;
if (!supportedImageMIMETypes)
initializeMIMETypeRegistry();
- return supportedImageMIMETypes->contains(mimeType);
+ return supportedImageMIMETypes->contains(getNormalizedMIMEType(mimeType));
}
bool MIMETypeRegistry::isSupportedImageResourceMIMEType(const String& mimeType)
@@ -523,7 +518,7 @@ bool MIMETypeRegistry::isSupportedImageResourceMIMEType(const String& mimeType)
return false;
if (!supportedImageResourceMIMETypes)
initializeMIMETypeRegistry();
- return supportedImageResourceMIMETypes->contains(mimeType);
+ return supportedImageResourceMIMETypes->contains(getNormalizedMIMEType(mimeType));
}
bool MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(const String& mimeType)
@@ -632,4 +627,75 @@ const String& defaultMIMEType()
return defaultMIMEType;
}
+#if PLATFORM(BLACKBERRY)
+typedef HashMap<String, String> MIMETypeAssociationMap;
+
+static const MIMETypeAssociationMap& mimeTypeAssociationMap()
+{
+ static MIMETypeAssociationMap* mimeTypeMap = 0;
+ if (mimeTypeMap)
+ return *mimeTypeMap;
+
+ mimeTypeMap = new MIMETypeAssociationMap;
+ mimeTypeMap->add("image/x-ms-bmp", "image/bmp");
+ mimeTypeMap->add("image/x-windows-bmp", "image/bmp");
+ mimeTypeMap->add("image/x-bmp", "image/bmp");
+ mimeTypeMap->add("image/x-bitmap", "image/bmp");
+ mimeTypeMap->add("image/x-ms-bitmap", "image/bmp");
+ mimeTypeMap->add("image/jpg", "image/jpeg");
+ mimeTypeMap->add("image/pjpeg", "image/jpeg");
+ mimeTypeMap->add("image/x-png", "image/png");
+ mimeTypeMap->add("image/vnd.rim.png", "image/png");
+ mimeTypeMap->add("image/ico", "image/vnd.microsoft.icon");
+ mimeTypeMap->add("image/icon", "image/vnd.microsoft.icon");
+ mimeTypeMap->add("text/ico", "image/vnd.microsoft.icon");
+ mimeTypeMap->add("application/ico", "image/vnd.microsoft.icon");
+ mimeTypeMap->add("image/x-icon", "image/vnd.microsoft.icon");
+ mimeTypeMap->add("audio/vnd.qcelp", "audio/qcelp");
+ mimeTypeMap->add("audio/qcp", "audio/qcelp");
+ mimeTypeMap->add("audio/vnd.qcp", "audio/qcelp");
+ mimeTypeMap->add("audio/wav", "audio/x-wav");
+ mimeTypeMap->add("audio/mid", "audio/midi");
+ mimeTypeMap->add("audio/sp-midi", "audio/midi");
+ mimeTypeMap->add("audio/x-mid", "audio/midi");
+ mimeTypeMap->add("audio/x-midi", "audio/midi");
+ mimeTypeMap->add("audio/x-mpeg", "audio/mpeg");
+ mimeTypeMap->add("audio/mp3", "audio/mpeg");
+ mimeTypeMap->add("audio/x-mp3", "audio/mpeg");
+ mimeTypeMap->add("audio/mpeg3", "audio/mpeg");
+ mimeTypeMap->add("audio/x-mpeg3", "audio/mpeg");
+ mimeTypeMap->add("audio/mpg3", "audio/mpeg");
+ mimeTypeMap->add("audio/mpg", "audio/mpeg");
+ mimeTypeMap->add("audio/x-mpg", "audio/mpeg");
+ mimeTypeMap->add("audio/m4a", "audio/mp4");
+ mimeTypeMap->add("audio/x-m4a", "audio/mp4");
+ mimeTypeMap->add("audio/x-mp4", "audio/mp4");
+ mimeTypeMap->add("audio/x-aac", "audio/aac");
+ mimeTypeMap->add("audio/x-amr", "audio/amr");
+ mimeTypeMap->add("audio/mpegurl", "audio/x-mpegurl");
+ mimeTypeMap->add("audio/flac", "audio/x-flac");
+ mimeTypeMap->add("video/3gp", "video/3gpp");
+ mimeTypeMap->add("video/avi", "video/x-msvideo");
+ mimeTypeMap->add("video/x-m4v", "video/mp4");
+ mimeTypeMap->add("video/x-quicktime", "video/quicktime");
+ mimeTypeMap->add("application/java", "application/java-archive");
+ mimeTypeMap->add("application/x-java-archive", "application/java-archive");
+ mimeTypeMap->add("application/x-zip-compressed", "application/zip");
+
+ return *mimeTypeMap;
+}
+#endif
+
+String MIMETypeRegistry::getNormalizedMIMEType(const String& mimeType)
+{
+#if PLATFORM(BLACKBERRY)
+ MIMETypeAssociationMap::const_iterator it = mimeTypeAssociationMap().find(mimeType);
+
+ if (it != mimeTypeAssociationMap().end())
+ return it->second;
+#endif
+ return mimeType;
+}
+
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/MIMETypeRegistry.h b/Source/WebCore/platform/MIMETypeRegistry.h
index d2c375214..bcfedca14 100644
--- a/Source/WebCore/platform/MIMETypeRegistry.h
+++ b/Source/WebCore/platform/MIMETypeRegistry.h
@@ -36,9 +36,7 @@ namespace WebCore {
class MIMETypeRegistry {
public:
static String getMIMETypeForExtension(const String& extension);
-#if ENABLE(FILE_SYSTEM)
static String getWellKnownMIMETypeForExtension(const String& extension);
-#endif
static Vector<String> getExtensionsForMIMEType(const String& type);
static String getPreferredExtensionForMIMEType(const String& type);
@@ -86,6 +84,8 @@ public:
static HashSet<String>& getSupportedNonImageMIMETypes();
static HashSet<String>& getSupportedMediaMIMETypes();
static HashSet<String>& getUnsupportedTextMIMETypes();
+
+ static String getNormalizedMIMEType(const String&);
};
const String& defaultMIMEType();
diff --git a/Source/WebCore/platform/graphics/chromium/VideoFrameChromium.cpp b/Source/WebCore/platform/MemoryUsageSupport.cpp
index ca9284224..2f06c7639 100644
--- a/Source/WebCore/platform/graphics/chromium/VideoFrameChromium.cpp
+++ b/Source/WebCore/platform/MemoryUsageSupport.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -29,21 +29,33 @@
*/
#include "config.h"
-
-#include "VideoFrameChromium.h"
+#include "MemoryUsageSupport.h"
namespace WebCore {
-const unsigned VideoFrameChromium::maxPlanes = 3;
-const unsigned VideoFrameChromium::numRGBPlanes = 1;
-const unsigned VideoFrameChromium::rgbPlane = 0;
-const unsigned VideoFrameChromium::numYUVPlanes = 3;
-const unsigned VideoFrameChromium::yPlane = 0;
-const unsigned VideoFrameChromium::uPlane = 1;
-const unsigned VideoFrameChromium::vPlane = 2;
-
-VideoFrameChromium::~VideoFrameChromium() { }
-
+int MemoryUsageSupport::memoryUsageMB()
+{
+ return 0;
+}
+
+int MemoryUsageSupport::actualMemoryUsageMB()
+{
+ return 0;
+}
+
+int MemoryUsageSupport::lowMemoryUsageMB()
+{
+ return 0;
+}
+
+int MemoryUsageSupport::highMemoryUsageMB()
+{
+ return 0;
+}
+
+int MemoryUsageSupport::highUsageDeltaMB()
+{
+ return 0;
+}
+
} // namespace WebCore
-
-
diff --git a/Source/WebCore/platform/graphics/chromium/VideoFrameProvider.h b/Source/WebCore/platform/MemoryUsageSupport.h
index 9794794a7..9d12e3740 100644
--- a/Source/WebCore/platform/graphics/chromium/VideoFrameProvider.h
+++ b/Source/WebCore/platform/MemoryUsageSupport.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -28,40 +28,32 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef VideoFrameProvider_h
-#define VideoFrameProvider_h
-
-#include "VideoFrameChromium.h"
+#ifndef MemoryUsageSupport_h
+#define MemoryUsageSupport_h
namespace WebCore {
-class VideoFrameProvider {
+class MemoryUsageSupport {
public:
- virtual ~VideoFrameProvider() { }
+ // Returns the current space allocated for the pagefile, in MB.
+ // That is committed size for Windows and virtual memory size for POSIX.
+ static int memoryUsageMB();
+
+ // Same as above, but always returns actual value, without any
+ // caches.
+ static int actualMemoryUsageMB();
- class Client {
- public:
- // Provider will call this method to tell the client to stop using it.
- virtual void stopUsingProvider() = 0;
- virtual void didReceiveFrame() = 0;
- virtual void didUpdateMatrix(const float*) = 0;
- };
+ // If memory usage is below this threshold, do not bother forcing GC.
+ static int lowMemoryUsageMB();
- virtual void setVideoFrameProviderClient(Client*) = 0;
+ // If memory usage is above this threshold, force GC more aggressively.
+ static int highMemoryUsageMB();
- // This function returns a pointer to a VideoFrameChromium, which is
- // the WebCore wrapper for a video frame in Chromium. getCurrentFrame()
- // places a lock on the frame in Chromium. Calls to this method should
- // always be followed with a call to putCurrentFrame().
- // The ownership of the object is not transferred to the caller and
- // the caller should not free the returned object.
- virtual VideoFrameChromium* getCurrentFrame() = 0;
- // This function releases the lock on the video frame in chromium. It should
- // always be called after getCurrentFrame(). Frames passed into this method
- // should no longer be referenced after the call is made.
- virtual void putCurrentFrame(VideoFrameChromium*) = 0;
+ // Delta of memory usage growth (vs. last actualMemoryUsageMB())
+ // to force GC when memory usage is high.
+ static int highUsageDeltaMB();
};
} // namespace WebCore
-#endif
+#endif // MemoryUsageSupport_h
diff --git a/Source/WebCore/platform/Pasteboard.h b/Source/WebCore/platform/Pasteboard.h
index f12c854b7..4681357ae 100644
--- a/Source/WebCore/platform/Pasteboard.h
+++ b/Source/WebCore/platform/Pasteboard.h
@@ -43,6 +43,7 @@
// knowledge of the frame and editor or moved into the editing directory.
#if PLATFORM(MAC)
+OBJC_CLASS NSAttributedString;
OBJC_CLASS NSFileWrapper;
OBJC_CLASS NSArray;
#endif
@@ -66,6 +67,7 @@ extern const char* WebURLPboardType;
extern const char* WebURLsWithTitlesPboardType;
#endif
+ class ArchiveResource;
class Clipboard;
class DocumentFragment;
class Frame;
@@ -73,15 +75,17 @@ class HitTestResult;
class KURL;
class Node;
class Range;
-class ArchiveResource;
+class SharedBuffer;
class Pasteboard {
WTF_MAKE_NONCOPYABLE(Pasteboard); WTF_MAKE_FAST_ALLOCATED;
public:
#if PLATFORM(MAC)
// This is required to support OS X services.
- void writeSelectionForTypes(const Vector<String>& pasteboardTypes, Range* selectedRange, bool canSmartCopyOrDelete, Frame*);
+ void writeSelectionForTypes(const Vector<String>& pasteboardTypes, bool canSmartCopyOrDelete, Frame*);
Pasteboard(const String& pasteboardName);
+ static String getStringSelection(Frame*);
+ static PassRefPtr<SharedBuffer> getDataSelection(Frame*, const String& pasteboardType);
#endif
static Pasteboard* generalPasteboard();
diff --git a/Source/WebCore/platform/PasteboardStrategy.h b/Source/WebCore/platform/PasteboardStrategy.h
index 515f55d49..f922c6632 100644
--- a/Source/WebCore/platform/PasteboardStrategy.h
+++ b/Source/WebCore/platform/PasteboardStrategy.h
@@ -36,6 +36,7 @@
namespace WebCore {
class Color;
+class KURL;
class PasteboardStrategy {
public:
@@ -47,8 +48,10 @@ public:
virtual int changeCount(const String& pasteboardName) = 0;
virtual String uniqueName() = 0;
virtual Color color(const String& pasteboardName) = 0;
+ virtual KURL url(const String& pasteboardName) = 0;
virtual void copy(const String& fromPasteboard, const String& toPasteboard) = 0;
+ virtual void addTypes(const Vector<String>& pasteboardTypes, const String& pasteboardName) = 0;
virtual void setTypes(const Vector<String>& pasteboardTypes, const String& pasteboardName) = 0;
virtual void setBufferForType(PassRefPtr<SharedBuffer>, const String& pasteboardType, const String& pasteboardName) = 0;
virtual void setPathnamesForType(const Vector<String>&, const String& pasteboardType, const String& pasteboardName) = 0;
diff --git a/Source/WebCore/platform/PlatformEvent.h b/Source/WebCore/platform/PlatformEvent.h
index 77d447e4c..2016f7237 100644
--- a/Source/WebCore/platform/PlatformEvent.h
+++ b/Source/WebCore/platform/PlatformEvent.h
@@ -55,6 +55,10 @@ public:
GestureTap,
GestureTapDown,
GestureDoubleTap,
+ GestureLongPress,
+ GesturePinchBegin,
+ GesturePinchEnd,
+ GesturePinchUpdate,
#if ENABLE(TOUCH_EVENTS)
// PlatformTouchEvent
diff --git a/Source/WebCore/platform/PlatformGestureCurve.h b/Source/WebCore/platform/PlatformGestureCurve.h
index 922199147..06124d860 100644
--- a/Source/WebCore/platform/PlatformGestureCurve.h
+++ b/Source/WebCore/platform/PlatformGestureCurve.h
@@ -37,6 +37,9 @@ class PlatformGestureCurve {
public:
virtual ~PlatformGestureCurve() { }
+ // Returns a name of the curve for use in debugging.
+ virtual const char* debugName() const = 0;
+
// Returns false if curve has finished and can no longer be applied.
virtual bool apply(double time, PlatformGestureCurveTarget*) = 0;
};
diff --git a/Source/WebCore/platform/PlatformGestureCurveTarget.h b/Source/WebCore/platform/PlatformGestureCurveTarget.h
index bfb0aebcd..b28b292c1 100644
--- a/Source/WebCore/platform/PlatformGestureCurveTarget.h
+++ b/Source/WebCore/platform/PlatformGestureCurveTarget.h
@@ -31,8 +31,8 @@ class IntPoint;
class PlatformGestureCurveTarget {
public:
- virtual void setScrollIncrement(const IntPoint&) = 0;
- // FIXME: add interfaces for setScroll(), setPageScaleAndScroll(), etc.
+ virtual void scrollBy(const IntPoint&) = 0;
+ // FIXME: add interfaces for scroll(), etc.
protected:
virtual ~PlatformGestureCurveTarget() { }
diff --git a/Source/WebCore/platform/PlatformGestureEvent.h b/Source/WebCore/platform/PlatformGestureEvent.h
index ed557c178..8c08862c5 100644
--- a/Source/WebCore/platform/PlatformGestureEvent.h
+++ b/Source/WebCore/platform/PlatformGestureEvent.h
@@ -41,25 +41,31 @@ public:
: PlatformEvent(PlatformEvent::GestureScrollBegin)
, m_deltaX(0)
, m_deltaY(0)
+ , m_gammaX(0)
+ , m_gammaY(0)
{
}
- PlatformGestureEvent(Type type, const IntPoint& position, const IntPoint& globalPosition, double timestamp, float deltaX, float deltaY, bool shiftKey, bool ctrlKey, bool altKey, bool metaKey)
+ PlatformGestureEvent(Type type, const IntPoint& position, const IntPoint& globalPosition, double timestamp, float deltaX, float deltaY, float gammaX, float gammaY, bool shiftKey, bool ctrlKey, bool altKey, bool metaKey)
: PlatformEvent(type, shiftKey, ctrlKey, altKey, metaKey, timestamp)
, m_position(position)
, m_globalPosition(globalPosition)
, m_deltaX(deltaX)
, m_deltaY(deltaY)
+ , m_gammaX(gammaX)
+ , m_gammaY(gammaY)
{
}
- PlatformGestureEvent(Type type, const IntPoint& position, const IntPoint& globalPosition, double timestamp, const IntSize& area, const FloatPoint& delta, bool shiftKey, bool ctrlKey, bool altKey, bool metaKey)
+ PlatformGestureEvent(Type type, const IntPoint& position, const IntPoint& globalPosition, double timestamp, const IntSize& area, const FloatPoint& delta, const FloatPoint& gamma, bool shiftKey, bool ctrlKey, bool altKey, bool metaKey)
: PlatformEvent(type, shiftKey, ctrlKey, altKey, metaKey, timestamp)
, m_position(position)
, m_globalPosition(globalPosition)
, m_area(area)
, m_deltaX(delta.x())
, m_deltaY(delta.y())
+ , m_gammaX(gamma.x())
+ , m_gammaY(gamma.y())
{
}
@@ -70,6 +76,9 @@ public:
float deltaX() const { return m_deltaX; }
float deltaY() const { return m_deltaY; }
+
+ float gammaX() const { return m_gammaX; }
+ float gammaY() const { return m_gammaY; }
protected:
IntPoint m_position;
@@ -77,6 +86,8 @@ protected:
IntSize m_area;
float m_deltaX;
float m_deltaY;
+ float m_gammaX;
+ float m_gammaY;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/PlatformKeyboardEvent.h b/Source/WebCore/platform/PlatformKeyboardEvent.h
index 5990098db..42577f9e6 100644
--- a/Source/WebCore/platform/PlatformKeyboardEvent.h
+++ b/Source/WebCore/platform/PlatformKeyboardEvent.h
@@ -43,6 +43,7 @@ typedef long LPARAM;
#if PLATFORM(GTK)
typedef struct _GdkEventKey GdkEventKey;
+#include "CompositionResults.h"
#endif
#if PLATFORM(QT)
@@ -55,6 +56,14 @@ QT_END_NAMESPACE
class wxKeyEvent;
#endif
+#if PLATFORM(BLACKBERRY)
+namespace BlackBerry {
+namespace Platform {
+class KeyboardEvent;
+}
+}
+#endif
+
#if PLATFORM(EFL)
typedef struct _Evas_Event_Key_Down Evas_Event_Key_Down;
typedef struct _Evas_Event_Key_Up Evas_Event_Key_Up;
@@ -72,6 +81,9 @@ namespace WebCore {
, m_autoRepeat(false)
, m_isKeypad(false)
, m_isSystemKey(false)
+#if PLATFORM(BLACKBERRY)
+ , m_unmodifiedCharacter(0)
+#endif
#if PLATFORM(GTK)
, m_gdkEventKey(0)
#endif
@@ -127,6 +139,10 @@ namespace WebCore {
static bool currentCapsLockState();
static void getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey);
+#if PLATFORM(BLACKBERRY)
+ unsigned short unmodifiedCharacter() const { return m_unmodifiedCharacter; }
+#endif
+
#if PLATFORM(MAC)
NSEvent* macEvent() const { return m_macEvent.get(); }
#endif
@@ -136,8 +152,9 @@ namespace WebCore {
#endif
#if PLATFORM(GTK)
- PlatformKeyboardEvent(GdkEventKey*);
- GdkEventKey* gdkEventKey() const;
+ PlatformKeyboardEvent(GdkEventKey*, const CompositionResults&);
+ GdkEventKey* gdkEventKey() const { return m_gdkEventKey; }
+ const CompositionResults& compositionResults() const { return m_compositionResults; }
// Used by WebKit2
static String keyIdentifierForGdkKeyCode(unsigned);
@@ -156,6 +173,10 @@ namespace WebCore {
PlatformKeyboardEvent(wxKeyEvent&);
#endif
+#if PLATFORM(BLACKBERRY)
+ PlatformKeyboardEvent(const BlackBerry::Platform::KeyboardEvent&);
+#endif
+
#if PLATFORM(EFL)
PlatformKeyboardEvent(const Evas_Event_Key_Down*);
PlatformKeyboardEvent(const Evas_Event_Key_Up*);
@@ -172,11 +193,16 @@ namespace WebCore {
bool m_isKeypad;
bool m_isSystemKey;
+#if PLATFORM(BLACKBERRY)
+ unsigned short m_unmodifiedCharacter;
+#endif
+
#if PLATFORM(MAC)
RetainPtr<NSEvent> m_macEvent;
#endif
#if PLATFORM(GTK)
GdkEventKey* m_gdkEventKey;
+ CompositionResults m_compositionResults;
#endif
#if PLATFORM(QT)
QKeyEvent* m_qtEvent;
diff --git a/Source/WebCore/platform/PlatformMenuDescription.h b/Source/WebCore/platform/PlatformMenuDescription.h
index 459d0a5ea..78196add8 100644
--- a/Source/WebCore/platform/PlatformMenuDescription.h
+++ b/Source/WebCore/platform/PlatformMenuDescription.h
@@ -52,7 +52,7 @@ namespace WebCore {
typedef wxMenu* PlatformMenuDescription;
#elif PLATFORM(EFL)
class ContextMenuItem;
- typedef Vector<ContextMenuItem>* PlatformMenuDescription;
+ typedef const Vector<ContextMenuItem>* PlatformMenuDescription;
#else
typedef void* PlatformMenuDescription;
#endif
diff --git a/Source/WebCore/platform/PlatformMouseEvent.h b/Source/WebCore/platform/PlatformMouseEvent.h
index 20aecf107..44c9f5d90 100644
--- a/Source/WebCore/platform/PlatformMouseEvent.h
+++ b/Source/WebCore/platform/PlatformMouseEvent.h
@@ -55,6 +55,10 @@ namespace WebCore {
// These button numbers match the ones used in the DOM API, 0 through 2, except for NoButton which isn't specified.
enum MouseButton { NoButton = -1, LeftButton, MiddleButton, RightButton };
+
+#if PLATFORM(BLACKBERRY)
+ enum MouseInputMethod { PointingDevice, TouchScreen };
+#endif
class PlatformMouseEvent : public PlatformEvent {
public:
@@ -125,6 +129,10 @@ namespace WebCore {
PlatformMouseEvent(const wxMouseEvent&, const wxPoint& globalPoint, int clickCount);
#endif
+#if PLATFORM(BLACKBERRY)
+ PlatformMouseEvent(const IntPoint& eventPosition, const IntPoint& globalPosition, const PlatformEvent::Type, int clickCount, MouseButton, MouseInputMethod = PointingDevice);
+ MouseInputMethod inputMethod() const { return m_inputMethod; }
+#endif
protected:
IntPoint m_position;
IntPoint m_globalPosition;
@@ -139,6 +147,8 @@ namespace WebCore {
int m_eventNumber;
#elif PLATFORM(WIN)
bool m_didActivateWebView;
+#elif PLATFORM(BLACKBERRY)
+ MouseInputMethod m_inputMethod;
#endif
};
diff --git a/Source/WebCore/platform/PlatformPasteboard.h b/Source/WebCore/platform/PlatformPasteboard.h
index 2f94a667a..27ef39122 100644
--- a/Source/WebCore/platform/PlatformPasteboard.h
+++ b/Source/WebCore/platform/PlatformPasteboard.h
@@ -38,6 +38,7 @@ OBJC_CLASS NSPasteboard;
namespace WebCore {
class Color;
+class KURL;
class PlatformPasteboard {
public:
@@ -50,8 +51,10 @@ public:
String stringForType(const String& pasteboardType);
int changeCount() const;
Color color();
+ KURL url();
void copy(const String& fromPasteboard);
+ void addTypes(const Vector<String>& pasteboardTypes);
void setTypes(const Vector<String>& pasteboardTypes);
void setBufferForType(PassRefPtr<SharedBuffer>, const String& pasteboardType);
void setPathnamesForType(const Vector<String>& pathnames, const String& pasteboardType);
diff --git a/Source/WebCore/platform/PlatformTouchEvent.h b/Source/WebCore/platform/PlatformTouchEvent.h
index 126634291..59cbb206d 100644
--- a/Source/WebCore/platform/PlatformTouchEvent.h
+++ b/Source/WebCore/platform/PlatformTouchEvent.h
@@ -36,6 +36,14 @@ QT_END_NAMESPACE
typedef struct _Eina_List Eina_List;
#endif
+#if PLATFORM(BLACKBERRY)
+namespace BlackBerry {
+namespace Platform {
+class TouchEvent;
+};
+};
+#endif
+
namespace WebCore {
@@ -43,19 +51,38 @@ class PlatformTouchEvent : public PlatformEvent {
public:
PlatformTouchEvent()
: PlatformEvent(PlatformEvent::TouchStart)
+#if PLATFORM(BLACKBERRY)
+ , m_rotation(0)
+ , m_scale(1)
+ , m_doubleTap(false)
+ , m_touchHold(false)
+#endif
{
}
-#if PLATFORM(QT)
- PlatformTouchEvent(QTouchEvent*);
-#elif PLATFORM(EFL)
+#if PLATFORM(EFL)
PlatformTouchEvent(Eina_List*, const IntPoint, PlatformEvent::Type, int metaState);
+#elif PLATFORM(BLACKBERRY)
+ PlatformTouchEvent(BlackBerry::Platform::TouchEvent*);
#endif
const Vector<PlatformTouchPoint>& touchPoints() const { return m_touchPoints; }
+#if PLATFORM(BLACKBERRY)
+ float rotation() const { return m_rotation; }
+ float scale() const { return m_scale; }
+ bool doubleTap() const { return m_doubleTap; }
+ bool touchHold() const { return m_touchHold; }
+#endif
+
protected:
Vector<PlatformTouchPoint> m_touchPoints;
+#if PLATFORM(BLACKBERRY)
+ float m_rotation;
+ float m_scale;
+ bool m_doubleTap;
+ bool m_touchHold;
+#endif
};
}
diff --git a/Source/WebCore/platform/PlatformTouchPoint.h b/Source/WebCore/platform/PlatformTouchPoint.h
index 6e1594f30..0b6514073 100644
--- a/Source/WebCore/platform/PlatformTouchPoint.h
+++ b/Source/WebCore/platform/PlatformTouchPoint.h
@@ -29,6 +29,14 @@
#include <QTouchEvent>
#endif
+#if PLATFORM(BLACKBERRY)
+namespace BlackBerry {
+namespace Platform {
+class TouchPoint;
+};
+};
+#endif
+
namespace WebCore {
class PlatformTouchEvent;
@@ -45,12 +53,19 @@ public:
};
// This is necessary for us to be able to build synthetic events.
- PlatformTouchPoint() { };
-
-#if PLATFORM(QT)
- PlatformTouchPoint(const QTouchEvent::TouchPoint&, State);
-#elif PLATFORM(EFL)
+ PlatformTouchPoint()
+ : m_id(0)
+ , m_radiusY(0)
+ , m_radiusX(0)
+ , m_rotationAngle(0)
+ , m_force(0)
+ {
+ }
+
+#if PLATFORM(EFL)
PlatformTouchPoint(unsigned id, const IntPoint& windowPos, State);
+#elif PLATFORM(BLACKBERRY)
+ PlatformTouchPoint(const BlackBerry::Platform::TouchPoint&);
#endif
unsigned id() const { return m_id; }
diff --git a/Source/WebCore/platform/ReferrerPolicy.h b/Source/WebCore/platform/ReferrerPolicy.h
new file mode 100644
index 000000000..39b60bb43
--- /dev/null
+++ b/Source/WebCore/platform/ReferrerPolicy.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef ReferrerPolicy_h
+#define ReferrerPolicy_h
+
+namespace WebCore {
+
+enum ReferrerPolicy {
+ ReferrerPolicyAlways,
+ ReferrerPolicyDefault,
+ ReferrerPolicyNever,
+ // Same as ReferrerPolicyAlways, except that only the origin of the
+ // referring URL is send.
+ ReferrerPolicyOrigin,
+};
+
+}
+
+#endif // ReferrerPolicy_h
diff --git a/Source/WebCore/platform/RunLoop.h b/Source/WebCore/platform/RunLoop.h
index f08a04224..40b41949c 100644
--- a/Source/WebCore/platform/RunLoop.h
+++ b/Source/WebCore/platform/RunLoop.h
@@ -39,6 +39,10 @@
#include <wtf/gobject/GRefPtr.h>
#endif
+#if PLATFORM(EFL)
+#include <Ecore.h>
+#endif
+
namespace WebCore {
class RunLoop {
@@ -95,6 +99,10 @@ public:
void clearTimerSource();
GRefPtr<GSource> m_timerSource;
gboolean m_isRepeating;
+#elif PLATFORM(EFL)
+ static bool timerFired(void* data);
+ OwnPtr<Ecore_Timer> m_timer;
+ bool m_isRepeating;
#endif
};
@@ -157,6 +165,10 @@ public:
private:
GRefPtr<GMainContext> m_runLoopContext;
Vector<GRefPtr<GMainLoop> > m_runLoopMainLoops;
+#elif PLATFORM(EFL)
+ bool m_initEfl;
+ OwnPtr<Ecore_Pipe> m_pipe;
+ static void wakeUpEvent(void* data, void*, unsigned int);
#endif
};
diff --git a/Source/WebCore/platform/ScrollAnimator.h b/Source/WebCore/platform/ScrollAnimator.h
index a3c4ca7e0..4e5c42763 100644
--- a/Source/WebCore/platform/ScrollAnimator.h
+++ b/Source/WebCore/platform/ScrollAnimator.h
@@ -92,6 +92,8 @@ public:
virtual void notifyContentAreaScrolled() { }
+ virtual bool isRubberBandInProgress() const { return false; }
+
protected:
ScrollAnimator(ScrollableArea*);
diff --git a/Source/WebCore/platform/ScrollAnimatorNone.cpp b/Source/WebCore/platform/ScrollAnimatorNone.cpp
index 96844f7eb..277dd942d 100644
--- a/Source/WebCore/platform/ScrollAnimatorNone.cpp
+++ b/Source/WebCore/platform/ScrollAnimatorNone.cpp
@@ -34,12 +34,14 @@
#include "ScrollAnimatorNone.h"
+#include "ActivePlatformGestureAnimation.h"
#include "FloatPoint.h"
#include "NotImplemented.h"
-#include "OwnArrayPtr.h"
+#include <wtf/OwnArrayPtr.h>
#include "PlatformGestureEvent.h"
#include "ScrollableArea.h"
#include "ScrollbarTheme.h"
+#include "TouchpadFlingPlatformGestureCurve.h"
#include <algorithm>
#include <wtf/CurrentTime.h>
#include <wtf/PassOwnPtr.h>
@@ -57,12 +59,14 @@ const double kTickTime = 1 / kFrameRate;
const double kMinimumTimerInterval = .001;
const double kZoomTicks = 11;
+#if !(PLATFORM(BLACKBERRY))
PassOwnPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea)
{
if (scrollableArea && scrollableArea->scrollAnimatorEnabled())
return adoptPtr(new ScrollAnimatorNone(scrollableArea));
return adoptPtr(new ScrollAnimator(scrollableArea));
}
+#endif
ScrollAnimatorNone::Parameters::Parameters()
: m_isEnabled(false)
@@ -378,7 +382,12 @@ ScrollAnimatorNone::ScrollAnimatorNone(ScrollableArea* scrollableArea)
: ScrollAnimator(scrollableArea)
, m_horizontalData(this, &m_currentPosX, scrollableArea->visibleWidth())
, m_verticalData(this, &m_currentPosY, scrollableArea->visibleHeight())
+ , m_startTime(0)
+#if USE(REQUEST_ANIMATION_FRAME_TIMER)
+ , m_animationTimer(this, &ScrollAnimatorNone::animationTimerFired)
+#else
, m_animationActive(false)
+#endif
, m_firstVelocity(0)
, m_firstVelocitySet(false)
, m_firstVelocityIsVertical(false)
@@ -392,7 +401,14 @@ ScrollAnimatorNone::~ScrollAnimatorNone()
void ScrollAnimatorNone::fireUpAnAnimation(FloatPoint fp)
{
- UNUSED_PARAM(fp);
+ if (m_gestureAnimation)
+ m_gestureAnimation.clear();
+ m_gestureAnimation = ActivePlatformGestureAnimation::create(TouchpadFlingPlatformGestureCurve::create(fp), this);
+#if USE(REQUEST_ANIMATION_FRAME_TIMER)
+ startNextTimer(0);
+#else
+ startNextTimer();
+#endif
}
bool ScrollAnimatorNone::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier)
@@ -418,8 +434,13 @@ bool ScrollAnimatorNone::scroll(ScrollbarOrientation orientation, ScrollGranular
parameters = Parameters(true, 15 * kTickTime, 10 * kTickTime, Cubic, 5 * kTickTime, Cubic, 5 * kTickTime, Linear, 1);
break;
case ScrollByPixel:
+#if PLATFORM(CHROMIUM)
+ // FIXME: plumb a flag specifying precise deltas.
+ return ScrollAnimator::scroll(orientation, granularity, step, multiplier);
+#else
parameters = Parameters(true, 11 * kTickTime, 2 * kTickTime, Cubic, 3 * kTickTime, Cubic, 3 * kTickTime, Quadratic, 1.25);
break;
+#endif
case ScrollByPixelVelocity:
// FIXME: Generalize the scroll interface to support a richer set of parameters.
if (m_firstVelocitySet) {
@@ -448,6 +469,7 @@ bool ScrollAnimatorNone::scroll(ScrollbarOrientation orientation, ScrollGranular
bool needToScroll = data.updateDataFromParameters(step, multiplier, scrollableSize, WTF::monotonicallyIncreasingTime(), &parameters);
if (needToScroll && !animationTimerActive()) {
m_startTime = data.m_startTime;
+ animationWillStart();
animationTimerFired();
}
return needToScroll;
@@ -468,9 +490,11 @@ void ScrollAnimatorNone::scrollToOffsetWithoutAnimation(const FloatPoint& offset
notifyPositionChanged();
}
+#if !USE(REQUEST_ANIMATION_FRAME_TIMER)
void ScrollAnimatorNone::cancelAnimations()
{
m_animationActive = false;
+ m_gestureAnimation.clear();
}
void ScrollAnimatorNone::serviceScrollAnimations()
@@ -478,6 +502,7 @@ void ScrollAnimatorNone::serviceScrollAnimations()
if (m_animationActive)
animationTimerFired();
}
+#endif
void ScrollAnimatorNone::willEndLiveResize()
{
@@ -500,6 +525,13 @@ void ScrollAnimatorNone::updateVisibleLengths()
m_verticalData.updateVisibleLength(scrollableArea()->visibleHeight());
}
+#if USE(REQUEST_ANIMATION_FRAME_TIMER)
+void ScrollAnimatorNone::animationTimerFired(Timer<ScrollAnimatorNone>* timer)
+{
+ animationTimerFired();
+}
+#endif
+
void ScrollAnimatorNone::animationTimerFired()
{
#if PLATFORM(CHROMIUM)
@@ -516,32 +548,67 @@ void ScrollAnimatorNone::animationTimerFired()
if (m_verticalData.m_startTime && m_verticalData.animateScroll(currentTime))
continueAnimation = true;
+ if (m_gestureAnimation) {
+ if (m_gestureAnimation->animate(currentTime))
+ continueAnimation = true;
+ else
+ m_gestureAnimation.clear();
+ }
+
if (continueAnimation)
+#if USE(REQUEST_ANIMATION_FRAME_TIMER)
+ startNextTimer(max(kMinimumTimerInterval, deltaToNextFrame));
+#else
startNextTimer();
else
m_animationActive = false;
+#endif
#if PLATFORM(CHROMIUM)
TRACE_EVENT("ScrollAnimatorNone::notifyPositionChanged", this, 0);
#endif
notifyPositionChanged();
+
+ if (!continueAnimation)
+ animationDidFinish();
}
+#if USE(REQUEST_ANIMATION_FRAME_TIMER)
+void ScrollAnimatorNone::startNextTimer(double delay)
+{
+ m_animationTimer.startOneShot(delay);
+}
+#else
void ScrollAnimatorNone::startNextTimer()
{
if (scrollableArea()->scheduleAnimation())
m_animationActive = true;
}
+#endif
bool ScrollAnimatorNone::animationTimerActive()
{
+#if USE(REQUEST_ANIMATION_FRAME_TIMER)
+ return m_animationTimer.isActive();
+#else
return m_animationActive;
+#endif
}
void ScrollAnimatorNone::stopAnimationTimerIfNeeded()
{
if (animationTimerActive())
+#if USE(REQUEST_ANIMATION_FRAME_TIMER)
+ m_animationTimer.stop();
+#else
m_animationActive = false;
+#endif
+}
+
+void ScrollAnimatorNone::scrollBy(const IntPoint& location)
+{
+ m_currentPosX += location.x();
+ m_currentPosY += location.y();
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/ScrollAnimatorNone.h b/Source/WebCore/platform/ScrollAnimatorNone.h
index 495e0cdda..3b683f184 100644
--- a/Source/WebCore/platform/ScrollAnimatorNone.h
+++ b/Source/WebCore/platform/ScrollAnimatorNone.h
@@ -38,16 +38,20 @@
#endif
#include "FloatPoint.h"
+#include "PlatformGestureCurveTarget.h"
#include "ScrollAnimator.h"
#include "Timer.h"
+#include <wtf/OwnPtr.h>
class ScrollAnimatorNoneTest;
namespace WebCore {
+class IntPoint;
+class ActivePlatformGestureAnimation;
struct ScrollAnimatorParameters;
-class ScrollAnimatorNone : public ScrollAnimator {
+class ScrollAnimatorNone : public ScrollAnimator, public PlatformGestureCurveTarget {
public:
ScrollAnimatorNone(ScrollableArea*);
virtual ~ScrollAnimatorNone();
@@ -55,8 +59,10 @@ public:
virtual bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier);
virtual void scrollToOffsetWithoutAnimation(const FloatPoint&);
+#if !USE(REQUEST_ANIMATION_FRAME_TIMER)
virtual void cancelAnimations();
virtual void serviceScrollAnimations();
+#endif
virtual void willEndLiveResize();
virtual void didAddVerticalScrollbar(Scrollbar*);
@@ -91,7 +97,13 @@ public:
double m_maximumCoastTime;
};
+ // PlatformGestureCurveTarget implementation.
+ virtual void scrollBy(const IntPoint&);
+
protected:
+ virtual void animationWillStart() { }
+ virtual void animationDidFinish() { }
+
friend class ::ScrollAnimatorNoneTest;
struct PerAxisData {
@@ -134,7 +146,12 @@ protected:
int m_visibleLength;
};
+#if USE(REQUEST_ANIMATION_FRAME_TIMER)
+ void animationTimerFired(Timer<ScrollAnimatorNone>*);
+ void startNextTimer(double delay);
+#else
void startNextTimer();
+#endif
void animationTimerFired();
void stopAnimationTimerIfNeeded();
@@ -146,11 +163,17 @@ protected:
PerAxisData m_verticalData;
double m_startTime;
+#if USE(REQUEST_ANIMATION_FRAME_TIMER)
+ Timer<ScrollAnimatorNone> m_animationTimer;
+#else
bool m_animationActive;
+#endif
float m_firstVelocity;
bool m_firstVelocitySet;
bool m_firstVelocityIsVertical;
+
+ OwnPtr<ActivePlatformGestureAnimation> m_gestureAnimation;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/ScrollAnimatorWin.cpp b/Source/WebCore/platform/ScrollAnimatorWin.cpp
deleted file mode 100644
index 58b049d27..000000000
--- a/Source/WebCore/platform/ScrollAnimatorWin.cpp
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * 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:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(SMOOTH_SCROLLING)
-
-#include "ScrollAnimatorWin.h"
-
-#include "FloatPoint.h"
-#include "ScrollableArea.h"
-#include "ScrollbarTheme.h"
-#include <algorithm>
-#include <wtf/CurrentTime.h>
-#include <wtf/PassOwnPtr.h>
-
-namespace WebCore {
-
-PassOwnPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea)
-{
- return adoptPtr(new ScrollAnimatorWin(scrollableArea));
-}
-
-const double ScrollAnimatorWin::animationTimerDelay = 0.01;
-
-ScrollAnimatorWin::PerAxisData::PerAxisData(ScrollAnimatorWin* parent, float* currentPos)
- : m_currentPos(currentPos)
- , m_desiredPos(0)
- , m_currentVelocity(0)
- , m_desiredVelocity(0)
- , m_lastAnimationTime(0)
- , m_animationTimer(parent, &ScrollAnimatorWin::animationTimerFired)
-{
-}
-
-
-ScrollAnimatorWin::ScrollAnimatorWin(ScrollableArea* scrollableArea)
- : ScrollAnimator(scrollableArea)
- , m_horizontalData(this, &m_currentPosX)
- , m_verticalData(this, &m_currentPosY)
-{
-}
-
-ScrollAnimatorWin::~ScrollAnimatorWin()
-{
- stopAnimationTimerIfNeeded(&m_horizontalData);
- stopAnimationTimerIfNeeded(&m_verticalData);
-}
-
-bool ScrollAnimatorWin::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier)
-{
- // Don't animate jumping to the beginning or end of the document.
- if (granularity == ScrollByDocument)
- return ScrollAnimator::scroll(orientation, granularity, step, multiplier);
-
- // This is an animatable scroll. Calculate the scroll delta.
- PerAxisData* data = (orientation == VerticalScrollbar) ? &m_verticalData : &m_horizontalData;
- float newPos = std::max(std::min(data->m_desiredPos + (step * multiplier), static_cast<float>(m_scrollableArea->scrollSize(orientation))), 0.0f);
- if (newPos == data->m_desiredPos)
- return false;
- data->m_desiredPos = newPos;
-
- // Calculate the animation velocity.
- if (*data->m_currentPos == data->m_desiredPos)
- return false;
- bool alreadyAnimating = data->m_animationTimer.isActive();
- // There are a number of different sources of scroll requests. We want to
- // make both keyboard and wheel-generated scroll requests (which can come at
- // unpredictable rates) and autoscrolling from holding down the mouse button
- // on a scrollbar part (where the request rate can be obtained from the
- // scrollbar theme) feel smooth, responsive, and similar.
- //
- // When autoscrolling, the scrollbar's autoscroll timer will call us to
- // increment the desired position by |step| (with |multiplier| == 1) every
- // ScrollbarTheme::theme()->autoscrollTimerDelay() seconds. If we set
- // the desired velocity to exactly this rate, smooth scrolling will neither
- // race ahead (and then have to slow down) nor increasingly lag behind, but
- // will be smooth and synchronized.
- //
- // Note that because of the acceleration period, the current position in
- // this case would lag the desired one by a small, constant amount (see
- // comments on animateScroll()); the exact amount is given by
- // lag = |step| - v(0.5tA + tD)
- // Where
- // v = The steady-state velocity,
- // |step| / ScrollbarTheme::theme()->autoscrollTimerDelay()
- // tA = accelerationTime()
- // tD = The time we pretend has already passed when starting to scroll,
- // |animationTimerDelay|
- //
- // This lag provides some buffer against timer jitter so we're less likely
- // to hit the desired position and stop (and thus have to re-accelerate,
- // causing a visible hitch) while waiting for the next autoscroll increment.
- //
- // Thus, for autoscroll-timer-triggered requests, the ideal steady-state
- // distance to travel in each time interval is:
- // float animationStep = step;
- // Note that when we're not already animating, this is exactly the same as
- // the distance to the target position. We'll return to that in a moment.
- //
- // For keyboard and wheel scrolls, we don't know when the next increment
- // will be requested. If we set the target velocity based on how far away
- // from the target position we are, then for keyboard/wheel events that come
- // faster than the autoscroll delay, we'll asymptotically approach the
- // velocity needed to stay smoothly in sync with the user's actions; for
- // events that come slower, we'll scroll one increment and then pause until
- // the next event fires.
- float animationStep = fabs(newPos - *data->m_currentPos);
- // If a key is held down (or the wheel continually spun), then once we have
- // reached a velocity close to the steady-state velocity, we're likely to
- // hit the desired position at around the same time we'd expect the next
- // increment to occur -- bad because it leads to hitching as described above
- // (if autoscroll-based requests didn't result in a small amount of constant
- // lag). So if we're called again while already animating, we want to trim
- // the animationStep slightly to maintain lag like what's described above.
- // (I say "maintain" since we'll already be lagged due to the acceleration
- // during the first scroll period.)
- //
- // Remember that trimming won't cause us to fall steadily further behind
- // here, because the further behind we are, the larger the base step value
- // above. Given the scrolling algorithm in animateScroll(), the practical
- // effect will actually be that, assuming a constant trim factor, we'll lag
- // by a constant amount depending on the rate at which increments occur
- // compared to the autoscroll timer delay. The exact lag is given by
- // lag = |step| * ((r / k) - 1)
- // Where
- // r = The ratio of the autoscroll repeat delay,
- // ScrollbarTheme::theme()->autoscrollTimerDelay(), to the
- // key/wheel repeat delay (i.e. > 1 when keys repeat faster)
- // k = The velocity trim constant given below
- //
- // We want to choose the trim factor such that for calls that come at the
- // autoscroll timer rate, we'll wind up with the same lag as in the
- // "perfect" case described above (or, to put it another way, we'll end up
- // with |animationStep| == |step| * |multiplier| despite the actual distance
- // calculated above being larger than that). This will result in "perfect"
- // behavior for autoscrolling without having to special-case it.
- if (alreadyAnimating)
- animationStep /= (2.0 - ((1.0 / ScrollbarTheme::theme()->autoscrollTimerDelay()) * (0.5 * accelerationTime() + animationTimerDelay)));
- // The result of all this is that single keypresses or wheel flicks will
- // scroll in the same time period as single presses of scrollbar elements;
- // holding the mouse down on a scrollbar part will scroll as fast as
- // possible without hitching; and other repeated scroll events will also
- // scroll with the same time lag as holding down the mouse on a scrollbar
- // part.
- data->m_desiredVelocity = animationStep / ScrollbarTheme::theme()->autoscrollTimerDelay();
-
- // If we're not already scrolling, start.
- if (!alreadyAnimating)
- animateScroll(data);
- return true;
-}
-
-void ScrollAnimatorWin::scrollToOffsetWithoutAnimation(const FloatPoint& offset)
-{
- stopAnimationTimerIfNeeded(&m_horizontalData);
- stopAnimationTimerIfNeeded(&m_verticalData);
-
- *m_horizontalData.m_currentPos = offset.x();
- m_horizontalData.m_desiredPos = offset.x();
- m_horizontalData.m_currentVelocity = 0;
- m_horizontalData.m_desiredVelocity = 0;
-
- *m_verticalData.m_currentPos = offset.y();
- m_verticalData.m_desiredPos = offset.y();
- m_verticalData.m_currentVelocity = 0;
- m_verticalData.m_desiredVelocity = 0;
-
- notifyPositionChanged();
-}
-
-double ScrollAnimatorWin::accelerationTime()
-{
- // We elect to use ScrollbarTheme::theme()->autoscrollTimerDelay() as
- // the length of time we'll take to accelerate from 0 to our target
- // velocity. Choosing a larger value would produce a more pronounced
- // acceleration effect.
- return ScrollbarTheme::theme()->autoscrollTimerDelay();
-}
-
-void ScrollAnimatorWin::animationTimerFired(Timer<ScrollAnimatorWin>* timer)
-{
- animateScroll((timer == &m_horizontalData.m_animationTimer) ? &m_horizontalData : &m_verticalData);
-}
-
-void ScrollAnimatorWin::stopAnimationTimerIfNeeded(PerAxisData* data)
-{
- if (data->m_animationTimer.isActive())
- data->m_animationTimer.stop();
-}
-
-void ScrollAnimatorWin::animateScroll(PerAxisData* data)
-{
- // Note on smooth scrolling perf versus non-smooth scrolling perf:
- // The total time to perform a complete scroll is given by
- // t = t0 + 0.5tA - tD + tS
- // Where
- // t0 = The time to perform the scroll without smooth scrolling
- // tA = The acceleration time,
- // ScrollbarTheme::theme()->autoscrollTimerDelay() (see below)
- // tD = |animationTimerDelay|
- // tS = A value less than or equal to the time required to perform a
- // single scroll increment, i.e. the work done due to calling
- // client()->valueChanged() (~0 for simple pages, larger for complex
- // pages).
- //
- // Because tA and tD are fairly small, the total lag (as users perceive it)
- // is negligible for simple pages and roughly tS for complex pages. Without
- // knowing in advance how large tS is it's hard to do better than this.
- // Perhaps we could try to remember previous values and forward-compensate.
-
-
- // We want to update the scroll position based on the time it's been since
- // our last update. This may be longer than our ideal time, especially if
- // the page is complex or the system is slow.
- //
- // To avoid feeling laggy, if we've just started smooth scrolling we pretend
- // we've already accelerated for one ideal interval, so that we'll scroll at
- // least some distance immediately.
- double lastScrollInterval = data->m_currentVelocity ? (WTF::currentTime() - data->m_lastAnimationTime) : animationTimerDelay;
-
- // Figure out how far we've actually traveled and update our current
- // velocity.
- float distanceTraveled;
- if (data->m_currentVelocity < data->m_desiredVelocity) {
- // We accelerate at a constant rate until we reach the desired velocity.
- float accelerationRate = data->m_desiredVelocity / accelerationTime();
-
- // Figure out whether contant acceleration has caused us to reach our
- // target velocity.
- float potentialVelocityChange = accelerationRate * lastScrollInterval;
- float potentialNewVelocity = data->m_currentVelocity + potentialVelocityChange;
- if (potentialNewVelocity > data->m_desiredVelocity) {
- // We reached the target velocity at some point between our last
- // update and now. The distance traveled can be calculated in two
- // pieces: the distance traveled while accelerating, and the
- // distance traveled after reaching the target velocity.
- float actualVelocityChange = data->m_desiredVelocity - data->m_currentVelocity;
- float accelerationInterval = actualVelocityChange / accelerationRate;
- // The distance traveled under constant acceleration is the area
- // under a line segment with a constant rising slope. Break this
- // into a triangular portion atop a rectangular portion and sum.
- distanceTraveled = ((data->m_currentVelocity + (actualVelocityChange / 2)) * accelerationInterval);
- // The distance traveled at the target velocity is simply
- // (target velocity) * (remaining time after accelerating).
- distanceTraveled += (data->m_desiredVelocity * (lastScrollInterval - accelerationInterval));
- data->m_currentVelocity = data->m_desiredVelocity;
- } else {
- // Constant acceleration through the entire time interval.
- distanceTraveled = (data->m_currentVelocity + (potentialVelocityChange / 2)) * lastScrollInterval;
- data->m_currentVelocity = potentialNewVelocity;
- }
- } else {
- // We've already reached the target velocity, so the distance we've
- // traveled is simply (current velocity) * (elapsed time).
- distanceTraveled = data->m_currentVelocity * lastScrollInterval;
- // If our desired velocity has decreased, drop the current velocity too.
- data->m_currentVelocity = data->m_desiredVelocity;
- }
-
- // Now update the scroll position based on the distance traveled.
- if (distanceTraveled >= fabs(data->m_desiredPos - *data->m_currentPos)) {
- // We've traveled far enough to reach the desired position. Stop smooth
- // scrolling.
- *data->m_currentPos = data->m_desiredPos;
- data->m_currentVelocity = 0;
- data->m_desiredVelocity = 0;
- } else {
- // Not yet at the target position. Travel towards it and set up the
- // next update.
- if (*data->m_currentPos > data->m_desiredPos)
- distanceTraveled = -distanceTraveled;
- *data->m_currentPos += distanceTraveled;
- data->m_animationTimer.startOneShot(animationTimerDelay);
- data->m_lastAnimationTime = WTF::currentTime();
- }
-
- notifyPositionChanged();
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(SMOOTH_SCROLLING)
diff --git a/Source/WebCore/platform/ScrollView.cpp b/Source/WebCore/platform/ScrollView.cpp
index 6af2aa696..b982d4dce 100644
--- a/Source/WebCore/platform/ScrollView.cpp
+++ b/Source/WebCore/platform/ScrollView.cpp
@@ -319,6 +319,9 @@ IntPoint ScrollView::minimumScrollPosition() const
IntPoint ScrollView::adjustScrollPositionWithinRange(const IntPoint& scrollPoint) const
{
+ if (!constrainsScrollingToContentEdge())
+ return scrollPoint;
+
IntPoint newScrollPosition = scrollPoint.shrunkTo(maximumScrollPosition());
newScrollPosition = newScrollPosition.expandedTo(minimumScrollPosition());
return newScrollPosition;
@@ -326,6 +329,13 @@ IntPoint ScrollView::adjustScrollPositionWithinRange(const IntPoint& scrollPoint
int ScrollView::scrollSize(ScrollbarOrientation orientation) const
{
+ // If no scrollbars are present, it does not indicate content is not be scrollable.
+ if (!m_horizontalScrollbar && !m_verticalScrollbar && !prohibitsScrolling()) {
+ IntSize scrollSize = m_contentsSize - visibleContentRect().size();
+ scrollSize.clampNegativeToZero();
+ return orientation == HorizontalScrollbar ? scrollSize.width() : scrollSize.height();
+ }
+
Scrollbar* scrollbar = ((orientation == HorizontalScrollbar) ? m_horizontalScrollbar : m_verticalScrollbar).get();
return scrollbar ? (scrollbar->totalSize() - scrollbar->visibleSize()) : 0;
}
@@ -362,6 +372,7 @@ void ScrollView::scrollTo(const IntSize& newOffset)
repaintFixedElementsAfterScrolling();
scrollContents(scrollDelta);
+ updateFixedElementsAfterScrolling();
}
int ScrollView::scrollPosition(Scrollbar* scrollbar) const
@@ -590,7 +601,13 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset)
invalidateScrollCornerRect(oldScrollCornerRect);
}
- IntPoint adjustedScrollPosition = adjustScrollPositionWithinRange(IntPoint(desiredOffset));
+ IntPoint adjustedScrollPosition = IntPoint(desiredOffset);
+
+ if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) {
+ if (!scrollAnimator->isRubberBandInProgress())
+ adjustedScrollPosition = adjustScrollPositionWithinRange(adjustedScrollPosition);
+ }
+
if (adjustedScrollPosition != scrollPosition() || scrollOriginChanged()) {
ScrollableArea::scrollToOffsetWithoutAnimation(adjustedScrollPosition + IntSize(scrollOrigin().x(), scrollOrigin().y()));
resetScrollOriginChanged();
diff --git a/Source/WebCore/platform/ScrollView.h b/Source/WebCore/platform/ScrollView.h
index 4c1b5de5c..e7873f916 100644
--- a/Source/WebCore/platform/ScrollView.h
+++ b/Source/WebCore/platform/ScrollView.h
@@ -362,7 +362,8 @@ private:
IntRect rectToCopyOnScroll() const;
// Called when the scroll position within this view changes. FrameView overrides this to generate repaint invalidations.
- virtual void repaintFixedElementsAfterScrolling() {}
+ virtual void repaintFixedElementsAfterScrolling() { }
+ virtual void updateFixedElementsAfterScrolling() { }
void platformInit();
void platformDestroy();
diff --git a/Source/WebCore/platform/ScrollableArea.cpp b/Source/WebCore/platform/ScrollableArea.cpp
index 871760304..fed37cf9f 100644
--- a/Source/WebCore/platform/ScrollableArea.cpp
+++ b/Source/WebCore/platform/ScrollableArea.cpp
@@ -42,6 +42,15 @@
namespace WebCore {
+struct SameSizeAsScrollableArea {
+ virtual ~SameSizeAsScrollableArea();
+ void* pointer;
+ unsigned bitfields : 16;
+ IntPoint origin;
+};
+
+COMPILE_ASSERT(sizeof(ScrollableArea) == sizeof(SameSizeAsScrollableArea), ScrollableArea_should_stay_small);
+
ScrollableArea::ScrollableArea()
: m_constrainsScrollingToContentEdge(true)
, m_inLiveResize(false)
@@ -185,7 +194,8 @@ void ScrollableArea::willStartLiveResize()
if (m_inLiveResize)
return;
m_inLiveResize = true;
- scrollAnimator()->willStartLiveResize();
+ if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
+ scrollAnimator->willStartLiveResize();
}
void ScrollableArea::willEndLiveResize()
@@ -193,27 +203,32 @@ void ScrollableArea::willEndLiveResize()
if (!m_inLiveResize)
return;
m_inLiveResize = false;
- scrollAnimator()->willEndLiveResize();
+ if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
+ scrollAnimator->willEndLiveResize();
}
void ScrollableArea::contentAreaWillPaint() const
{
- scrollAnimator()->contentAreaWillPaint();
+ if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
+ scrollAnimator->contentAreaWillPaint();
}
void ScrollableArea::mouseEnteredContentArea() const
{
- scrollAnimator()->mouseEnteredContentArea();
+ if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
+ scrollAnimator->mouseEnteredContentArea();
}
void ScrollableArea::mouseExitedContentArea() const
{
- scrollAnimator()->mouseEnteredContentArea();
+ if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
+ scrollAnimator->mouseEnteredContentArea();
}
void ScrollableArea::mouseMovedInContentArea() const
{
- scrollAnimator()->mouseMovedInContentArea();
+ if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
+ scrollAnimator->mouseMovedInContentArea();
}
void ScrollableArea::mouseEnteredScrollbar(Scrollbar* scrollbar) const
@@ -228,12 +243,14 @@ void ScrollableArea::mouseExitedScrollbar(Scrollbar* scrollbar) const
void ScrollableArea::contentAreaDidShow() const
{
- scrollAnimator()->contentAreaDidShow();
+ if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
+ scrollAnimator->contentAreaDidShow();
}
void ScrollableArea::contentAreaDidHide() const
{
- scrollAnimator()->contentAreaDidHide();
+ if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
+ scrollAnimator->contentAreaDidHide();
}
void ScrollableArea::didAddVerticalScrollbar(Scrollbar* scrollbar)
@@ -257,14 +274,15 @@ void ScrollableArea::didAddHorizontalScrollbar(Scrollbar* scrollbar)
setScrollbarOverlayStyle(scrollbarOverlayStyle());
}
-void ScrollableArea::contentsResized()
+void ScrollableArea::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
{
- scrollAnimator()->contentsResized();
+ scrollAnimator()->willRemoveHorizontalScrollbar(scrollbar);
}
-void ScrollableArea::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
+void ScrollableArea::contentsResized()
{
- scrollAnimator()->willRemoveHorizontalScrollbar(scrollbar);
+ if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
+ scrollAnimator->contentsResized();
}
bool ScrollableArea::hasOverlayScrollbars() const
@@ -348,7 +366,8 @@ bool ScrollableArea::hasLayerForScrollCorner() const
void ScrollableArea::serviceScrollAnimations()
{
- scrollAnimator()->serviceScrollAnimations();
+ if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
+ scrollAnimator->serviceScrollAnimations();
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/ScrollableArea.h b/Source/WebCore/platform/ScrollableArea.h
index 617873afd..5a278a9b5 100644
--- a/Source/WebCore/platform/ScrollableArea.h
+++ b/Source/WebCore/platform/ScrollableArea.h
@@ -38,6 +38,7 @@ class PlatformWheelEvent;
class ScrollAnimator;
#if USE(ACCELERATED_COMPOSITING)
class GraphicsLayer;
+class TiledBacking;
#endif
class ScrollableArea {
@@ -91,7 +92,12 @@ public:
virtual void setScrollbarOverlayStyle(ScrollbarOverlayStyle);
ScrollbarOverlayStyle scrollbarOverlayStyle() const { return static_cast<ScrollbarOverlayStyle>(m_scrollbarOverlayStyle); }
+ // This getter will create a ScrollAnimator if it doesn't already exist.
ScrollAnimator* scrollAnimator() const;
+
+ // This getter will return null if the ScrollAnimator hasn't been created yet.
+ ScrollAnimator* existingScrollAnimator() const { return m_scrollAnimator.get(); }
+
const IntPoint& scrollOrigin() const { return m_scrollOrigin; }
bool scrollOriginChanged() const { return m_scrollOriginChanged; }
@@ -161,6 +167,10 @@ public:
virtual bool scheduleAnimation() { return false; }
void serviceScrollAnimations();
+#if USE(ACCELERATED_COMPOSITING)
+ virtual TiledBacking* tiledBacking() { return 0; }
+#endif
+
protected:
ScrollableArea();
virtual ~ScrollableArea();
@@ -195,15 +205,17 @@ private:
virtual void setScrollOffset(const IntPoint&) = 0;
mutable OwnPtr<ScrollAnimator> m_scrollAnimator;
- bool m_constrainsScrollingToContentEdge : 1;
+ unsigned m_constrainsScrollingToContentEdge : 1;
- bool m_inLiveResize : 1;
+ unsigned m_inLiveResize : 1;
unsigned m_verticalScrollElasticity : 2; // ScrollElasticity
unsigned m_horizontalScrollElasticity : 2; // ScrollElasticity
unsigned m_scrollbarOverlayStyle : 2; // ScrollbarOverlayStyle
+ unsigned m_scrollOriginChanged : 1;
+
// There are 8 possible combinations of writing mode and direction. Scroll origin will be non-zero in the x or y axis
// if there is any reversed direction or writing-mode. The combinations are:
// writing-mode / direction scrollOrigin.x() set scrollOrigin.y() set
@@ -216,8 +228,6 @@ private:
// vertical-rl / ltr YES NO
// vertical-rl / rtl YES YES
IntPoint m_scrollOrigin;
-
- bool m_scrollOriginChanged;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/SharedBuffer.cpp b/Source/WebCore/platform/SharedBuffer.cpp
index ee6a29fd5..82efab753 100644
--- a/Source/WebCore/platform/SharedBuffer.cpp
+++ b/Source/WebCore/platform/SharedBuffer.cpp
@@ -62,6 +62,12 @@ SharedBuffer::SharedBuffer()
{
}
+SharedBuffer::SharedBuffer(size_t size)
+ : m_size(size)
+ , m_buffer(size)
+{
+}
+
SharedBuffer::SharedBuffer(const char* data, int size)
: m_size(0)
{
diff --git a/Source/WebCore/platform/SharedBuffer.h b/Source/WebCore/platform/SharedBuffer.h
index fe3e4b6b8..b66a033e5 100644
--- a/Source/WebCore/platform/SharedBuffer.h
+++ b/Source/WebCore/platform/SharedBuffer.h
@@ -48,6 +48,7 @@ class PurgeableBuffer;
class SharedBuffer : public RefCounted<SharedBuffer> {
public:
static PassRefPtr<SharedBuffer> create() { return adoptRef(new SharedBuffer); }
+ static PassRefPtr<SharedBuffer> create(size_t size) { return adoptRef(new SharedBuffer(size)); }
static PassRefPtr<SharedBuffer> create(const char* c, int i) { return adoptRef(new SharedBuffer(c, i)); }
static PassRefPtr<SharedBuffer> create(const unsigned char* c, int i) { return adoptRef(new SharedBuffer(c, i)); }
@@ -115,6 +116,7 @@ public:
private:
SharedBuffer();
+ SharedBuffer(size_t);
SharedBuffer(const char*, int);
SharedBuffer(const unsigned char*, int);
diff --git a/Source/WebCore/platform/StatsCounter.cpp b/Source/WebCore/platform/StatsCounter.cpp
new file mode 100644
index 000000000..a20580a7c
--- /dev/null
+++ b/Source/WebCore/platform/StatsCounter.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "StatsCounter.h"
+
+namespace WebCore {
+
+void StatsCounter::incrementStatsCounter(const char*)
+{
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/StatsCounter.h b/Source/WebCore/platform/StatsCounter.h
new file mode 100644
index 000000000..edd3e796f
--- /dev/null
+++ b/Source/WebCore/platform/StatsCounter.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StatsCounter_h
+#define StatsCounter_h
+
+namespace WebCore {
+
+class StatsCounter {
+public:
+ static void incrementStatsCounter(const char*);
+};
+
+} // namespace WebCore
+
+#endif // StatsCounter_h
diff --git a/Source/WebCore/platform/ThemeTypes.h b/Source/WebCore/platform/ThemeTypes.h
index f2515fc1a..1208a9a2e 100644
--- a/Source/WebCore/platform/ThemeTypes.h
+++ b/Source/WebCore/platform/ThemeTypes.h
@@ -47,8 +47,8 @@ typedef unsigned ControlStates;
// Must follow CSSValueKeywords.in order
enum ControlPart {
NoControlPart, CheckboxPart, RadioPart, PushButtonPart, SquareButtonPart, ButtonPart,
- ButtonBevelPart, DefaultButtonPart, InnerSpinButtonPart, InputSpeechButtonPart, ListButtonPart, ListboxPart, ListItemPart,
- MediaFullscreenButtonPart, MediaFullScreenVolumeSliderPart, MediaFullScreenVolumeSliderThumbPart, MediaMuteButtonPart, MediaPlayButtonPart, MediaSeekBackButtonPart,
+ ButtonBevelPart, DefaultButtonPart, InnerSpinButtonPart, InputSpeechButtonPart, ListboxPart, ListItemPart,
+ MediaEnterFullscreenButtonPart, MediaExitFullscreenButtonPart, MediaFullScreenVolumeSliderPart, MediaFullScreenVolumeSliderThumbPart, MediaMuteButtonPart, MediaPlayButtonPart, MediaSeekBackButtonPart,
MediaSeekForwardButtonPart, MediaRewindButtonPart, MediaReturnToRealtimeButtonPart, MediaToggleClosedCaptionsButtonPart,
MediaSliderPart, MediaSliderThumbPart, MediaVolumeSliderContainerPart, MediaVolumeSliderPart, MediaVolumeSliderThumbPart,
MediaVolumeSliderMuteButtonPart, MediaControlsBackgroundPart, MediaControlsFullscreenBackgroundPart, MediaCurrentTimePart, MediaTimeRemainingPart,
diff --git a/Source/WebCore/platform/TouchFlingPlatformGestureCurve.cpp b/Source/WebCore/platform/TouchFlingPlatformGestureCurve.cpp
deleted file mode 100644
index 076099583..000000000
--- a/Source/WebCore/platform/TouchFlingPlatformGestureCurve.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include "TouchFlingPlatformGestureCurve.h"
-
-#include "PlatformGestureCurveTarget.h"
-#include <math.h>
-
-namespace WebCore {
-
-using namespace std;
-
-PassOwnPtr<PlatformGestureCurve> TouchFlingPlatformGestureCurve::create(const FloatPoint& velocity)
-{
- return adoptPtr(new TouchFlingPlatformGestureCurve(velocity));
-}
-
-TouchFlingPlatformGestureCurve::TouchFlingPlatformGestureCurve(const FloatPoint& velocity)
- : m_velocity(velocity)
- , m_timeScaleFactor(1000 / max(1.f, max(fabs(velocity.x()), fabs(velocity.y()))))
-{
- ASSERT(velocity != FloatPoint::zero());
-}
-
-TouchFlingPlatformGestureCurve::~TouchFlingPlatformGestureCurve()
-{
-}
-
-bool TouchFlingPlatformGestureCurve::apply(double time, PlatformGestureCurveTarget* target)
-{
- // Here we implement a cubic bezier curve with parameters [1 1 0 0] which gives
- // v(0) = 1, a(0) = 0, v(1) = 0, a(1) = 0. The curve is scaled by the initial
- // velocity, and the time parameter is re-scaled so that larger initial velocities
- // lead to longer initial animations. This should allow the animation to smoothly
- // continue the velocity at the end of the GestureScroll, and smoothly come to a rest
- // at the end. Finally, we have integrated the curve so we can deal with displacement
- // as a function of time, and not velocity.
- // Finally, we place a constant velocity from ts = 0 .. 0.5, and run the Bezier curve
- // from ts = 0.5 .. 1.5 to give a longer run-out.
- time *= m_timeScaleFactor;
-
- float displacement;
- if (time <= 0.5)
- displacement = time;
- else if (time <= 1.5) {
- double t = time - 0.5;
- displacement = t * (1 + t * t * (0.5 * t - 1)) + 0.5;
- } else
- displacement = 1.0;
-
- // Keep track of integer portion of scroll thus far, and prepare increment.
- IntPoint scroll(displacement * m_velocity.x(), displacement * m_velocity.y());
- IntPoint scrollIncrement(scroll - m_cumulativeScroll);
- m_cumulativeScroll = scroll;
-
- if (time < 1.5 || scrollIncrement != IntPoint::zero()) {
- target->setScrollIncrement(scrollIncrement);
- return true;
- }
-
- return false;
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/TouchpadFlingPlatformGestureCurve.cpp b/Source/WebCore/platform/TouchpadFlingPlatformGestureCurve.cpp
new file mode 100644
index 000000000..09f185a9f
--- /dev/null
+++ b/Source/WebCore/platform/TouchpadFlingPlatformGestureCurve.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "TouchpadFlingPlatformGestureCurve.h"
+
+#include "PlatformGestureCurveTarget.h"
+#include <math.h>
+
+namespace WebCore {
+
+using namespace std;
+
+// This curve implementation is based on the notion of a single, absolute curve, which starts at
+// a large velocity and smoothly decreases to zero. For a given input velocity, we find where on
+// the curve this velocity occurs, and start the animation at this point---denoted by (m_timeOffset,
+// m_positionOffset).
+//
+// This has the effect of automatically determining an animation duration that scales with input
+// velocity, as faster initial velocities start earlier on the curve and thus take longer to reach the end.
+// No complicated time scaling is required.
+//
+// Since the starting velocity is implicitly determined by our starting point, we only store the
+// relative magnitude and direction of both initial x- and y-velocities, and use this to scale the
+// computed displacement at any point in time. This guarantees that fling trajectories are straight
+// lines when viewed in x-y space. Initial velocities that lie outside the max velocity are constrained
+// to start at zero (and thus are implicitly scaled).
+//
+// The curve is modelled as a 4th order polynomial, starting at t = 0, and ending at t = m_curveDuration.
+// Attempts to generate position/velocity estimates outside this range are undefined.
+
+const int TouchpadFlingPlatformGestureCurve::m_maxSearchIterations = 20;
+
+PassOwnPtr<PlatformGestureCurve> TouchpadFlingPlatformGestureCurve::create(const FloatPoint& velocity, IntPoint cumulativeScroll)
+{
+ // The default parameters listed below are a matched set, and should not be changed independently of one another.
+ return create(velocity, -5.70762e+03, 1.72e+02, 3.7e+00, 0, 0, 1.3, cumulativeScroll);
+}
+
+// FIXME: need to remove p3, p4 here and below as they are not used in the exponential curve, but leave in for now to facilitate
+// the in-flight patch for https://bugs.webkit.org/show_bug.cgi?id=81663 .
+PassOwnPtr<PlatformGestureCurve> TouchpadFlingPlatformGestureCurve::create(const FloatPoint& velocity, float p0, float p1, float p2, float p3, float p4, float curveDuration, IntPoint cumulativeScroll)
+{
+ return adoptPtr(new TouchpadFlingPlatformGestureCurve(velocity, p0, p1, p2, p3, p4, curveDuration, cumulativeScroll));
+}
+
+inline double position(double t, float* p)
+{
+ return p[0] * exp(-p[2] * t) - p[1] * t - p[0];
+}
+
+inline double velocity(double t, float* p)
+{
+ return -p[0] * p[2] * exp(-p[2] * t) - p[1];
+}
+
+TouchpadFlingPlatformGestureCurve::TouchpadFlingPlatformGestureCurve(const FloatPoint& initialVelocity, float p0, float p1, float p2, float p3, float p4, float curveDuration, const IntPoint& cumulativeScroll)
+ : m_cumulativeScroll(cumulativeScroll)
+ , m_curveDuration(curveDuration)
+{
+ ASSERT(initialVelocity != FloatPoint::zero());
+
+ m_coeffs[0] = p0; // alpha
+ m_coeffs[1] = p1; // beta
+ m_coeffs[2] = p2; // gamma
+ m_coeffs[3] = p3; // not used
+ m_coeffs[4] = p4; // not used
+
+ float maxInitialVelocity = max(fabs(initialVelocity.x()), fabs(initialVelocity.y()));
+
+ // Force maxInitialVelocity to lie in the range v(0) to v(curveDuration), and assume that
+ // the curve parameters define a monotonically decreasing velocity, or else bisection search may
+ // fail.
+ if (maxInitialVelocity > velocity(0, m_coeffs))
+ maxInitialVelocity = velocity(0, m_coeffs);
+
+ if (maxInitialVelocity < velocity(m_curveDuration, m_coeffs))
+ maxInitialVelocity = velocity(m_curveDuration, m_coeffs);
+
+ // We keep track of relative magnitudes and directions of the velocity/displacement components here.
+ m_displacementRatio = FloatPoint(initialVelocity.x() / maxInitialVelocity, initialVelocity.y() / maxInitialVelocity);
+
+ // Use basic bisection to estimate where we should start on the curve.
+ // FIXME: Would Newton's method be better?
+ const double epsilon = 1; // It is probably good enough to get the start point to within 1 pixel/sec.
+ double t0 = 0;
+ double t1 = curveDuration;
+ int numIterations = 0;
+ while (t0 < t1 && numIterations < m_maxSearchIterations) {
+ numIterations++;
+ m_timeOffset = (t0 + t1) * 0.5;
+ double vOffset = velocity(m_timeOffset, m_coeffs);
+ if (fabs(maxInitialVelocity - vOffset) < epsilon)
+ break;
+
+ if (vOffset > maxInitialVelocity)
+ t0 = m_timeOffset;
+ else
+ t1 = m_timeOffset;
+ }
+
+ // Compute curve position at offset time
+ m_positionOffset = position(m_timeOffset, m_coeffs);
+}
+
+TouchpadFlingPlatformGestureCurve::~TouchpadFlingPlatformGestureCurve()
+{
+}
+
+bool TouchpadFlingPlatformGestureCurve::apply(double time, PlatformGestureCurveTarget* target)
+{
+ float displacement;
+ if (time < 0)
+ displacement = 0;
+ else if (time + m_timeOffset < m_curveDuration)
+ displacement = position(time + m_timeOffset, m_coeffs) - m_positionOffset;
+ else
+ displacement = position(m_curveDuration, m_coeffs) - m_positionOffset;
+
+ // Keep track of integer portion of scroll thus far, and prepare increment.
+ IntPoint scroll(displacement * m_displacementRatio.x(), displacement * m_displacementRatio.y());
+ IntPoint scrollIncrement(scroll - m_cumulativeScroll);
+ m_cumulativeScroll = scroll;
+
+ if (time + m_timeOffset < m_curveDuration || scrollIncrement != IntPoint::zero()) {
+ target->scrollBy(scrollIncrement);
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/TouchFlingPlatformGestureCurve.h b/Source/WebCore/platform/TouchpadFlingPlatformGestureCurve.h
index fd52bc4ec..46b0aa5b6 100644
--- a/Source/WebCore/platform/TouchFlingPlatformGestureCurve.h
+++ b/Source/WebCore/platform/TouchpadFlingPlatformGestureCurve.h
@@ -22,8 +22,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TouchFlingPlatformGestureCurve_h
-#define TouchFlingPlatformGestureCurve_h
+#ifndef TouchpadFlingPlatformGestureCurve_h
+#define TouchpadFlingPlatformGestureCurve_h
#include "FloatPoint.h"
#include "PlatformGestureCurve.h"
@@ -38,19 +38,26 @@ class PlatformGestureCurveTarget;
// fling scroll. Starts with a flat velocity profile based on 'velocity', which
// tails off to zero. Time is scaled to that duration of the fling is proportional
// the initial velocity.
-class TouchFlingPlatformGestureCurve : public PlatformGestureCurve {
+class TouchpadFlingPlatformGestureCurve : public PlatformGestureCurve {
public:
- static PassOwnPtr<PlatformGestureCurve> create(const FloatPoint& velocity);
- virtual ~TouchFlingPlatformGestureCurve();
+ static PassOwnPtr<PlatformGestureCurve> create(const FloatPoint& velocity, IntPoint cumulativeScroll = IntPoint());
+ static PassOwnPtr<PlatformGestureCurve> create(const FloatPoint& velocity, float p0, float p1, float p2, float p3, float p4, float curveDuration, IntPoint cumulativeScroll = IntPoint());
+ virtual ~TouchpadFlingPlatformGestureCurve();
- virtual bool apply(double time, PlatformGestureCurveTarget*);
+ virtual const char* debugName() const { return "TouchpadFling"; }
+ virtual bool apply(double monotonicTime, PlatformGestureCurveTarget*);
private:
- explicit TouchFlingPlatformGestureCurve(const FloatPoint& velocity);
+ TouchpadFlingPlatformGestureCurve(const FloatPoint& velocity, float p0, float p1, float p2, float p3, float p4, float curveDuration, const IntPoint& cumulativeScroll);
- FloatPoint m_velocity;
- float m_timeScaleFactor;
+ FloatPoint m_displacementRatio;
IntPoint m_cumulativeScroll;
+ float m_coeffs[5];
+ float m_timeOffset;
+ float m_curveDuration;
+ float m_positionOffset;
+
+ static const int m_maxSearchIterations;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/WheelFlingPlatformGestureCurve.cpp b/Source/WebCore/platform/WheelFlingPlatformGestureCurve.cpp
index fab57cd5f..c9f173289 100644
--- a/Source/WebCore/platform/WheelFlingPlatformGestureCurve.cpp
+++ b/Source/WebCore/platform/WheelFlingPlatformGestureCurve.cpp
@@ -64,7 +64,7 @@ bool WheelFlingPlatformGestureCurve::apply(double time, PlatformGestureCurveTarg
m_cumulativeScroll = scroll;
if (cdf < 0.5 || scrollIncrement != IntPoint::zero()) {
- target->setScrollIncrement(scrollIncrement);
+ target->scrollBy(scrollIncrement);
return true;
}
diff --git a/Source/WebCore/platform/WheelFlingPlatformGestureCurve.h b/Source/WebCore/platform/WheelFlingPlatformGestureCurve.h
index b72146165..a6eeca407 100644
--- a/Source/WebCore/platform/WheelFlingPlatformGestureCurve.h
+++ b/Source/WebCore/platform/WheelFlingPlatformGestureCurve.h
@@ -43,6 +43,7 @@ public:
static PassOwnPtr<PlatformGestureCurve> create(const FloatPoint& velocity);
virtual ~WheelFlingPlatformGestureCurve();
+ virtual const char* debugName() const { return "WheelFling"; }
virtual bool apply(double time, PlatformGestureCurveTarget*);
private:
diff --git a/Source/WebCore/platform/Widget.h b/Source/WebCore/platform/Widget.h
index d710716ba..ffa1cc068 100644
--- a/Source/WebCore/platform/Widget.h
+++ b/Source/WebCore/platform/Widget.h
@@ -68,6 +68,10 @@ QT_END_NAMESPACE
typedef QObject* PlatformWidget;
#endif
+#if PLATFORM(BLACKBERRY)
+typedef void* PlatformWidget;
+#endif
+
#if PLATFORM(WX)
class wxWindow;
typedef wxWindow* PlatformWidget;
@@ -83,6 +87,12 @@ typedef Evas_Object* PlatformWidget;
#if PLATFORM(QT)
class QWebPageClient;
typedef QWebPageClient* PlatformPageClient;
+#elif PLATFORM(BLACKBERRY)
+#include "PageClientBlackBerry.h"
+typedef PageClientBlackBerry* PlatformPageClient;
+#elif PLATFORM(EFL)
+class PageClientEfl;
+typedef PageClientEfl* PlatformPageClient;
#else
typedef PlatformWidget PlatformPageClient;
#endif
diff --git a/Source/WebCore/platform/animation/Animation.cpp b/Source/WebCore/platform/animation/Animation.cpp
index 119c0234c..d397ae201 100644
--- a/Source/WebCore/platform/animation/Animation.cpp
+++ b/Source/WebCore/platform/animation/Animation.cpp
@@ -26,7 +26,8 @@ namespace WebCore {
Animation::Animation()
: m_name(initialAnimationName())
- , m_property(initialAnimationProperty())
+ , m_property(CSSPropertyInvalid)
+ , m_mode(AnimateAll)
, m_iterationCount(initialAnimationIterationCount())
, m_delay(initialAnimationDelay())
, m_duration(initialAnimationDuration())
@@ -51,6 +52,7 @@ Animation::Animation(const Animation& o)
: RefCounted<Animation>()
, m_name(o.m_name)
, m_property(o.m_property)
+ , m_mode(o.m_mode)
, m_iterationCount(o.m_iterationCount)
, m_delay(o.m_delay)
, m_duration(o.m_duration)
@@ -75,6 +77,7 @@ Animation& Animation::operator=(const Animation& o)
{
m_name = o.m_name;
m_property = o.m_property;
+ m_mode = o.m_mode;
m_iterationCount = o.m_iterationCount;
m_delay = o.m_delay;
m_duration = o.m_duration;
@@ -108,6 +111,7 @@ bool Animation::animationsMatch(const Animation* o, bool matchPlayStates) const
bool result = m_name == o->m_name
&& m_property == o->m_property
+ && m_mode == o->m_mode
&& m_iterationCount == o->m_iterationCount
&& m_delay == o->m_delay
&& m_duration == o->m_duration
diff --git a/Source/WebCore/platform/animation/Animation.h b/Source/WebCore/platform/animation/Animation.h
index 175d95a5b..b5da99076 100644
--- a/Source/WebCore/platform/animation/Animation.h
+++ b/Source/WebCore/platform/animation/Animation.h
@@ -25,6 +25,7 @@
#ifndef Animation_h
#define Animation_h
+#include "CSSPropertyNames.h"
#include "PlatformString.h"
#include "RenderStyleConstants.h"
#include "TimingFunction.h"
@@ -33,9 +34,6 @@
namespace WebCore {
-const int cAnimateNone = 0;
-const int cAnimateAll = -2;
-
class Animation : public RefCounted<Animation> {
public:
~Animation();
@@ -96,6 +94,12 @@ public:
double delay() const { return m_delay; }
+ enum AnimationMode {
+ AnimateAll,
+ AnimateNone,
+ AnimateSingleProperty
+ };
+
enum AnimationDirection {
AnimationDirectionNormal,
AnimationDirectionAlternate,
@@ -103,27 +107,30 @@ public:
AnimationDirectionAlternateReverse
};
AnimationDirection direction() const { return static_cast<AnimationDirection>(m_direction); }
+ bool directionIsForwards() const { return m_direction == AnimationDirectionNormal || m_direction == AnimationDirectionAlternate; }
unsigned fillMode() const { return m_fillMode; }
double duration() const { return m_duration; }
enum { IterationCountInfinite = -1 };
- int iterationCount() const { return m_iterationCount; }
+ double iterationCount() const { return m_iterationCount; }
const String& name() const { return m_name; }
EAnimPlayState playState() const { return static_cast<EAnimPlayState>(m_playState); }
- int property() const { return m_property; }
+ CSSPropertyID property() const { return m_property; }
const PassRefPtr<TimingFunction> timingFunction() const { return m_timingFunction; }
+ AnimationMode animationMode() const { return m_mode; }
void setDelay(double c) { m_delay = c; m_delaySet = true; }
void setDirection(AnimationDirection d) { m_direction = d; m_directionSet = true; }
void setDuration(double d) { ASSERT(d >= 0); m_duration = d; m_durationSet = true; }
void setFillMode(unsigned f) { m_fillMode = f; m_fillModeSet = true; }
- void setIterationCount(int c) { m_iterationCount = c; m_iterationCountSet = true; }
+ void setIterationCount(double c) { m_iterationCount = c; m_iterationCountSet = true; }
void setName(const String& n) { m_name = n; m_nameSet = true; }
void setPlayState(EAnimPlayState d) { m_playState = d; m_playStateSet = true; }
- void setProperty(int t) { m_property = t; m_propertySet = true; }
+ void setProperty(CSSPropertyID t) { m_property = t; m_propertySet = true; }
void setTimingFunction(PassRefPtr<TimingFunction> f) { m_timingFunction = f; m_timingFunctionSet = true; }
+ void setAnimationMode(AnimationMode mode) { m_mode = mode; }
void setIsNoneAnimation(bool n) { m_isNone = n; }
@@ -144,8 +151,9 @@ private:
Animation(const Animation& o);
String m_name;
- int m_property;
- int m_iterationCount;
+ CSSPropertyID m_property;
+ AnimationMode m_mode;
+ double m_iterationCount;
double m_delay;
double m_duration;
RefPtr<TimingFunction> m_timingFunction;
@@ -171,10 +179,10 @@ public:
static AnimationDirection initialAnimationDirection() { return AnimationDirectionNormal; }
static double initialAnimationDuration() { return 0; }
static unsigned initialAnimationFillMode() { return AnimationFillModeNone; }
- static int initialAnimationIterationCount() { return 1; }
+ static double initialAnimationIterationCount() { return 1.0; }
static const String& initialAnimationName();
static EAnimPlayState initialAnimationPlayState() { return AnimPlayStatePlaying; }
- static int initialAnimationProperty() { return cAnimateAll; }
+ static CSSPropertyID initialAnimationProperty() { return CSSPropertyInvalid; }
static const PassRefPtr<TimingFunction> initialAnimationTimingFunction() { return CubicBezierTimingFunction::create(); }
};
diff --git a/Source/WebCore/platform/animation/AnimationUtilities.h b/Source/WebCore/platform/animation/AnimationUtilities.h
index 87dabe6a6..1b0fe3e24 100644
--- a/Source/WebCore/platform/animation/AnimationUtilities.h
+++ b/Source/WebCore/platform/animation/AnimationUtilities.h
@@ -26,6 +26,8 @@
#ifndef AnimationUtilities_h
#define AnimationUtilities_h
+#include "FractionalLayoutUnit.h"
+#include "IntPoint.h"
#include <wtf/MathExtras.h>
namespace WebCore {
@@ -50,6 +52,17 @@ inline float blend(float from, float to, double progress)
return static_cast<float>(from + (to - from) * progress);
}
+inline FractionalLayoutUnit blend(FractionalLayoutUnit from, FractionalLayoutUnit to, double progress)
+{
+ return from + (to - from) * progress;
+}
+
+inline IntPoint blend(const IntPoint& from, const IntPoint& to, double progress)
+{
+ return IntPoint(blend(from.x(), to.x(), progress),
+ blend(from.y(), to.y(), progress));
+}
+
} // namespace WebCore
#endif // AnimationUtilities_h
diff --git a/Source/WebCore/platform/audio/AudioBus.cpp b/Source/WebCore/platform/audio/AudioBus.cpp
index e7f8902f7..b486a38b4 100644
--- a/Source/WebCore/platform/audio/AudioBus.cpp
+++ b/Source/WebCore/platform/audio/AudioBus.cpp
@@ -424,6 +424,12 @@ void AudioBus::processWithGainFromMonoStereo(const AudioBus &sourceBus, float* l
const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
const float* sourceR = numberOfSourceChannels > 1 ? sourceBusSafe.channelByType(ChannelRight)->data() : 0;
+ if (sourceBusSafe.isSilent()) {
+ if (!sumToBus)
+ zero();
+ return;
+ }
+
float* destinationL = channelByType(ChannelLeft)->mutableData();
float* destinationR = numberOfDestinationChannels > 1 ? channelByType(ChannelRight)->mutableData() : 0;
@@ -510,6 +516,11 @@ void AudioBus::copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, f
return;
}
+ if (sourceBus.length() == numberOfGainValues && sourceBus.length() == length() && sourceBus.isSilent()) {
+ zero();
+ return;
+ }
+
// We handle both the 1 -> N and N -> N case here.
const float* source = sourceBus.channel(0)->data();
for (unsigned channelIndex = 0; channelIndex < numberOfChannels(); ++channelIndex) {
@@ -539,6 +550,7 @@ PassOwnPtr<AudioBus> AudioBus::createBySampleRateConverting(const AudioBus* sour
double sourceSampleRate = sourceBus->sampleRate();
double destinationSampleRate = newSampleRate;
+ double sampleRateRatio = sourceSampleRate / destinationSampleRate;
unsigned numberOfSourceChannels = sourceBus->numberOfChannels();
if (numberOfSourceChannels == 1)
@@ -552,7 +564,13 @@ PassOwnPtr<AudioBus> AudioBus::createBySampleRateConverting(const AudioBus* sour
// Return exact copy.
return AudioBus::createBufferFromRange(sourceBus, 0, sourceBus->length());
}
-
+
+ if (sourceBus->isSilent()) {
+ OwnPtr<AudioBus> silentBus = adoptPtr(new AudioBus(numberOfSourceChannels, sourceBus->length() / sampleRateRatio));
+ silentBus->setSampleRate(newSampleRate);
+ return silentBus.release();
+ }
+
// First, mix to mono (if necessary) then sample-rate convert.
const AudioBus* resamplerSourceBus;
OwnPtr<AudioBus> mixedMonoBus;
@@ -565,7 +583,6 @@ PassOwnPtr<AudioBus> AudioBus::createBySampleRateConverting(const AudioBus* sour
}
// Calculate destination length based on the sample-rates.
- double sampleRateRatio = sourceSampleRate / destinationSampleRate;
int sourceLength = resamplerSourceBus->length();
int destinationLength = sourceLength / sampleRateRatio;
@@ -582,12 +599,16 @@ PassOwnPtr<AudioBus> AudioBus::createBySampleRateConverting(const AudioBus* sour
resampler.process(source, destination, sourceLength);
}
+ destinationBus->clearSilentFlag();
destinationBus->setSampleRate(newSampleRate);
return destinationBus.release();
}
PassOwnPtr<AudioBus> AudioBus::createByMixingToMono(const AudioBus* sourceBus)
{
+ if (sourceBus->isSilent())
+ return adoptPtr(new AudioBus(1, sourceBus->length()));
+
switch (sourceBus->numberOfChannels()) {
case 1:
// Simply create an exact copy.
@@ -605,6 +626,7 @@ PassOwnPtr<AudioBus> AudioBus::createByMixingToMono(const AudioBus* sourceBus)
for (unsigned i = 0; i < n; ++i)
destination[i] = (sourceL[i] + sourceR[i]) / 2;
+ destinationBus->clearSilentFlag();
destinationBus->setSampleRate(sourceBus->sampleRate());
return destinationBus.release();
}
@@ -614,6 +636,21 @@ PassOwnPtr<AudioBus> AudioBus::createByMixingToMono(const AudioBus* sourceBus)
return nullptr;
}
+bool AudioBus::isSilent() const
+{
+ for (size_t i = 0; i < m_channels.size(); ++i) {
+ if (!m_channels[i]->isSilent())
+ return false;
+ }
+ return true;
+}
+
+void AudioBus::clearSilentFlag()
+{
+ for (size_t i = 0; i < m_channels.size(); ++i)
+ m_channels[i]->clearSilentFlag();
+}
+
} // WebCore
#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/platform/audio/AudioBus.h b/Source/WebCore/platform/audio/AudioBus.h
index b3da0f451..4dd3fd626 100644
--- a/Source/WebCore/platform/audio/AudioBus.h
+++ b/Source/WebCore/platform/audio/AudioBus.h
@@ -83,6 +83,12 @@ public:
// Zeroes all channels.
void zero();
+ // Clears the silent flag on all channels.
+ void clearSilentFlag();
+
+ // Returns true if the silent bit is set on all channels.
+ bool isSilent() const;
+
// Returns true if the channel count and frame-size match.
bool topologyMatches(const AudioBus &sourceBus) const;
diff --git a/Source/WebCore/platform/audio/AudioChannel.cpp b/Source/WebCore/platform/audio/AudioChannel.cpp
index 3c748e633..2321349bc 100644
--- a/Source/WebCore/platform/audio/AudioChannel.cpp
+++ b/Source/WebCore/platform/audio/AudioChannel.cpp
@@ -43,6 +43,9 @@ using namespace VectorMath;
void AudioChannel::scale(float scale)
{
+ if (isSilent())
+ return;
+
vsmul(data(), 1, &scale, mutableData(), 1, length());
}
@@ -53,11 +56,18 @@ void AudioChannel::copyFrom(const AudioChannel* sourceChannel)
if (!isSafe)
return;
+ if (sourceChannel->isSilent()) {
+ zero();
+ return;
+ }
memcpy(mutableData(), sourceChannel->data(), sizeof(float) * length());
}
void AudioChannel::copyFromRange(const AudioChannel* sourceChannel, unsigned startFrame, unsigned endFrame)
{
+ if (sourceChannel->isSilent() && isSilent())
+ return;
+
// Check that range is safe for reading from sourceChannel.
bool isRangeSafe = sourceChannel && startFrame < endFrame && endFrame <= sourceChannel->length();
ASSERT(isRangeSafe);
@@ -73,22 +83,38 @@ void AudioChannel::copyFromRange(const AudioChannel* sourceChannel, unsigned sta
const float* source = sourceChannel->data();
float* destination = mutableData();
- memcpy(destination, source + startFrame, sizeof(float) * rangeLength);
+
+ if (sourceChannel->isSilent()) {
+ if (rangeLength == length())
+ zero();
+ else
+ memset(destination, 0, sizeof(float) * rangeLength);
+ } else
+ memcpy(destination, source + startFrame, sizeof(float) * rangeLength);
}
void AudioChannel::sumFrom(const AudioChannel* sourceChannel)
{
+ if (sourceChannel->isSilent())
+ return;
+
bool isSafe = sourceChannel && sourceChannel->length() >= length();
ASSERT(isSafe);
if (!isSafe)
return;
- vadd(data(), 1, sourceChannel->data(), 1, mutableData(), 1, length());
+ if (isSilent())
+ copyFrom(sourceChannel);
+ else
+ vadd(data(), 1, sourceChannel->data(), 1, mutableData(), 1, length());
}
float AudioChannel::maxAbsValue() const
{
- float max = 0.0f;
+ if (isSilent())
+ return 0;
+
+ float max = 0;
vmaxmgv(data(), 1, &max, length());
diff --git a/Source/WebCore/platform/audio/AudioChannel.h b/Source/WebCore/platform/audio/AudioChannel.h
index 24de3f9e8..4d277596f 100644
--- a/Source/WebCore/platform/audio/AudioChannel.h
+++ b/Source/WebCore/platform/audio/AudioChannel.h
@@ -43,12 +43,17 @@ public:
// Reference an external buffer.
AudioChannel(float* storage, size_t length)
- : m_length(length), m_rawPointer(storage) { }
+ : m_length(length)
+ , m_rawPointer(storage)
+ , m_silent(false)
+ {
+ }
// Manage storage for us.
explicit AudioChannel(size_t length)
: m_length(length)
, m_rawPointer(0)
+ , m_silent(true)
{
m_memBuffer = adoptPtr(new AudioFloatArray(length));
}
@@ -57,6 +62,7 @@ public:
AudioChannel()
: m_length(0)
, m_rawPointer(0)
+ , m_silent(true)
{
}
@@ -67,24 +73,40 @@ public:
m_memBuffer.clear(); // cleanup managed storage
m_rawPointer = storage;
m_length = length;
+ m_silent = false;
}
// How many sample-frames do we contain?
size_t length() const { return m_length; }
- // Direct access to PCM sample data
- float* mutableData() { return m_rawPointer ? m_rawPointer : m_memBuffer->data(); }
+ // Direct access to PCM sample data. Non-const accessor clears silent flag.
+ float* mutableData()
+ {
+ clearSilentFlag();
+ return m_rawPointer ? m_rawPointer : m_memBuffer->data();
+ }
+
const float* data() const { return m_rawPointer ? m_rawPointer : m_memBuffer->data(); }
// Zeroes out all sample values in buffer.
void zero()
{
+ if (m_silent)
+ return;
+
+ m_silent = true;
+
if (m_memBuffer.get())
m_memBuffer->zero();
else
memset(m_rawPointer, 0, sizeof(float) * m_length);
}
+ // Clears the silent flag.
+ void clearSilentFlag() { m_silent = false; }
+
+ bool isSilent() const { return m_silent; }
+
// Scales all samples by the same amount.
void scale(float scale);
@@ -105,6 +127,7 @@ private:
float* m_rawPointer;
OwnPtr<AudioFloatArray> m_memBuffer;
+ bool m_silent;
};
} // WebCore
diff --git a/Source/WebCore/platform/audio/AudioDSPKernel.h b/Source/WebCore/platform/audio/AudioDSPKernel.h
index f33c9ede4..f501d6583 100644
--- a/Source/WebCore/platform/audio/AudioDSPKernel.h
+++ b/Source/WebCore/platform/audio/AudioDSPKernel.h
@@ -63,6 +63,9 @@ public:
AudioDSPKernelProcessor* processor() { return m_kernelProcessor; }
const AudioDSPKernelProcessor* processor() const { return m_kernelProcessor; }
+ virtual double tailTime() const = 0;
+ virtual double latencyTime() const = 0;
+
protected:
AudioDSPKernelProcessor* m_kernelProcessor;
float m_sampleRate;
diff --git a/Source/WebCore/platform/audio/AudioDSPKernelProcessor.cpp b/Source/WebCore/platform/audio/AudioDSPKernelProcessor.cpp
index 5f9139f03..02890899b 100644
--- a/Source/WebCore/platform/audio/AudioDSPKernelProcessor.cpp
+++ b/Source/WebCore/platform/audio/AudioDSPKernelProcessor.cpp
@@ -115,6 +115,18 @@ void AudioDSPKernelProcessor::setNumberOfChannels(unsigned numberOfChannels)
m_numberOfChannels = numberOfChannels;
}
+double AudioDSPKernelProcessor::tailTime() const
+{
+ // It is expected that all the kernels have the same tailTime.
+ return !m_kernels.isEmpty() ? m_kernels.first()->tailTime() : 0;
+}
+
+double AudioDSPKernelProcessor::latencyTime() const
+{
+ // It is expected that all the kernels have the same latencyTime.
+ return !m_kernels.isEmpty() ? m_kernels.first()->latencyTime() : 0;
+}
+
} // namespace WebCore
#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/platform/audio/AudioDSPKernelProcessor.h b/Source/WebCore/platform/audio/AudioDSPKernelProcessor.h
index 7f8f81d2f..a4fc33faf 100644
--- a/Source/WebCore/platform/audio/AudioDSPKernelProcessor.h
+++ b/Source/WebCore/platform/audio/AudioDSPKernelProcessor.h
@@ -65,6 +65,9 @@ public:
unsigned numberOfChannels() const { return m_numberOfChannels; }
+ virtual double tailTime() const OVERRIDE;
+ virtual double latencyTime() const OVERRIDE;
+
protected:
unsigned m_numberOfChannels;
Vector<OwnPtr<AudioDSPKernel> > m_kernels;
diff --git a/Source/WebCore/platform/audio/AudioProcessor.h b/Source/WebCore/platform/audio/AudioProcessor.h
index 469f83322..4f240c830 100644
--- a/Source/WebCore/platform/audio/AudioProcessor.h
+++ b/Source/WebCore/platform/audio/AudioProcessor.h
@@ -65,6 +65,9 @@ public:
float sampleRate() const { return m_sampleRate; }
+ virtual double tailTime() const = 0;
+ virtual double latencyTime() const = 0;
+
protected:
bool m_initialized;
float m_sampleRate;
diff --git a/Source/WebCore/platform/audio/AudioPullFIFO.cpp b/Source/WebCore/platform/audio/AudioPullFIFO.cpp
new file mode 100644
index 000000000..03e89deba
--- /dev/null
+++ b/Source/WebCore/platform/audio/AudioPullFIFO.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(WEB_AUDIO)
+
+#include "AudioPullFIFO.h"
+
+namespace WebCore {
+
+AudioPullFIFO::AudioPullFIFO(AudioSourceProvider& audioProvider, unsigned numberOfChannels, size_t fifoLength, size_t providerSize)
+ : m_provider(audioProvider)
+ , m_fifoAudioBus(numberOfChannels, fifoLength)
+ , m_fifoLength(fifoLength)
+ , m_framesInFifo(0)
+ , m_readIndex(0)
+ , m_writeIndex(0)
+ , m_providerSize(providerSize)
+ , m_tempBus(numberOfChannels, providerSize)
+{
+}
+
+void AudioPullFIFO::consume(AudioBus* destination, size_t framesToConsume)
+{
+ bool isGood = destination && (framesToConsume <= m_fifoLength);
+ ASSERT(isGood);
+ if (!isGood)
+ return;
+
+ if (framesToConsume > m_framesInFifo) {
+ // We don't have enough data in the FIFO to fulfill the request. Ask for more data.
+ fillBuffer(framesToConsume - m_framesInFifo);
+ }
+
+ // We have enough data now. Copy the requested number of samples to the destination.
+
+ size_t part1Length;
+ size_t part2Length;
+ findWrapLengths(m_readIndex, framesToConsume, part1Length, part2Length);
+
+ size_t numberOfChannels = m_fifoAudioBus.numberOfChannels();
+
+ for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) {
+ float* destinationData = destination->channel(channelIndex)->mutableData();
+ const float* sourceData = m_fifoAudioBus.channel(channelIndex)->data();
+
+ bool isCopyGood = ((m_readIndex < m_fifoLength)
+ && (m_readIndex + part1Length) <= m_fifoLength
+ && (part1Length <= destination->length())
+ && (part1Length + part2Length) <= destination->length());
+ ASSERT(isCopyGood);
+ if (!isCopyGood)
+ return;
+
+ memcpy(destinationData, sourceData + m_readIndex, part1Length * sizeof(*sourceData));
+ // Handle wrap around of the FIFO, if needed.
+ if (part2Length > 0)
+ memcpy(destinationData + part1Length, sourceData, part2Length * sizeof(*sourceData));
+ }
+ m_readIndex = updateIndex(m_readIndex, framesToConsume);
+ m_framesInFifo -= framesToConsume;
+ ASSERT(m_framesInFifo >= 0);
+}
+
+void AudioPullFIFO::findWrapLengths(size_t index, size_t size, size_t& part1Length, size_t& part2Length)
+{
+ ASSERT(index < m_fifoLength && size <= m_fifoLength);
+ if (index < m_fifoLength && size <= m_fifoLength) {
+ if (index + size > m_fifoLength) {
+ // Need to wrap. Figure out the length of each piece.
+ part1Length = m_fifoLength - index;
+ part2Length = size - part1Length;
+ } else {
+ // No wrap needed.
+ part1Length = size;
+ part2Length = 0;
+ }
+ } else {
+ // Invalid values for index or size. Set the part lengths to zero so nothing is copied.
+ part1Length = 0;
+ part2Length = 0;
+ }
+}
+
+void AudioPullFIFO::fillBuffer(size_t numberOfFrames)
+{
+ // Keep asking the provider to give us data until we have received at least |numberOfFrames| of
+ // data. Stuff the data into the FIFO.
+ size_t framesProvided = 0;
+
+ while (framesProvided < numberOfFrames) {
+ m_provider.provideInput(&m_tempBus, m_providerSize);
+
+ size_t part1Length;
+ size_t part2Length;
+ findWrapLengths(m_writeIndex, m_providerSize, part1Length, part2Length);
+
+ size_t numberOfChannels = m_fifoAudioBus.numberOfChannels();
+
+ for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) {
+ float* destination = m_fifoAudioBus.channel(channelIndex)->mutableData();
+ const float* source = m_tempBus.channel(channelIndex)->data();
+
+ bool isCopyGood = (part1Length <= m_providerSize
+ && (part1Length + part2Length) <= m_providerSize
+ && (m_writeIndex < m_fifoLength)
+ && (m_writeIndex + part1Length) <= m_fifoLength
+ && part2Length < m_fifoLength);
+ ASSERT(isCopyGood);
+ if (!isCopyGood)
+ return;
+
+ memcpy(destination + m_writeIndex, source, part1Length * sizeof(*destination));
+ // Handle wrap around of the FIFO, if needed.
+ if (part2Length > 0)
+ memcpy(destination, source + part1Length, part2Length * sizeof(*destination));
+ }
+
+ m_framesInFifo += m_providerSize;
+ ASSERT(m_framesInFifo <= m_fifoLength);
+ m_writeIndex = updateIndex(m_writeIndex, m_providerSize);
+ framesProvided += m_providerSize;
+ }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/platform/audio/AudioPullFIFO.h b/Source/WebCore/platform/audio/AudioPullFIFO.h
new file mode 100644
index 000000000..fac19b9d1
--- /dev/null
+++ b/Source/WebCore/platform/audio/AudioPullFIFO.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AudioPullFIFO_h
+#define AudioPullFIFO_h
+
+#include "AudioBus.h"
+#include "AudioSourceProvider.h"
+
+namespace WebCore {
+
+// A FIFO (First In First Out) buffer to handle mismatches in buffer sizes between a provider and
+// receiver. The receiver will "pull" data from this FIFO. If data is already available in the
+// FIFO, it is provided to the receiver. If insufficient data is available to satisfy the request,
+// the FIFO will ask the provider for more data when necessary to fulfill a request. Contrast this
+// with a "push" FIFO, where the sender pushes data to the FIFO which will itself push the data to
+// the receiver when the FIFO is full.
+class AudioPullFIFO {
+public:
+ // Create a FIFO that gets data from |provider|. The FIFO will be large enough to hold
+ // |fifoLength| frames of data of |numberOfChannels| channels. The AudioSourceProvider will be
+ // asked to produce |providerSize| frames when the FIFO needs more data.
+ AudioPullFIFO(AudioSourceProvider& audioProvider, unsigned numberOfChannels, size_t fifoLength, size_t providerSize);
+
+ // Read |framesToConsume| frames from the FIFO into the destination. If the FIFO does not have
+ // enough data, we ask the |provider| to get more data to fulfill the request.
+ void consume(AudioBus* destination, size_t framesToConsume);
+
+private:
+ // Update the FIFO index by the step, with appropriate wrapping around the endpoint.
+ int updateIndex(int index, int step) { return (index + step) % m_fifoLength; }
+
+ void findWrapLengths(size_t index, size_t providerSize, size_t& part1Length, size_t& part2Length);
+
+ // Fill the FIFO buffer with at least |numberOfFrames| more data.
+ void fillBuffer(size_t numberOfFrames);
+
+ // The provider of the data in our FIFO.
+ AudioSourceProvider& m_provider;
+
+ // The FIFO itself. In reality, the FIFO is a circular buffer.
+ AudioBus m_fifoAudioBus;
+
+ // The total available space in the FIFO.
+ size_t m_fifoLength;
+
+ // The number of actual elements in the FIFO
+ size_t m_framesInFifo;
+
+ // Where to start reading from the FIFO.
+ size_t m_readIndex;
+
+ // Where to start writing to the FIFO.
+ size_t m_writeIndex;
+
+ // Number of frames of data that the provider will produce per call.
+ unsigned int m_providerSize;
+
+ // Temporary workspace to hold the data from the provider.
+ AudioBus m_tempBus;
+};
+
+} // namespace WebCore
+
+#endif // AudioPullFIFO.h
diff --git a/Source/WebCore/platform/audio/DirectConvolver.cpp b/Source/WebCore/platform/audio/DirectConvolver.cpp
new file mode 100644
index 000000000..62c4e68af
--- /dev/null
+++ b/Source/WebCore/platform/audio/DirectConvolver.cpp
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2012 Intel Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(WEB_AUDIO)
+
+#include "DirectConvolver.h"
+
+#if OS(DARWIN)
+#include <Accelerate/Accelerate.h>
+#endif
+
+#include "VectorMath.h"
+
+namespace WebCore {
+
+using namespace VectorMath;
+
+DirectConvolver::DirectConvolver(size_t inputBlockSize)
+ : m_inputBlockSize(inputBlockSize)
+#if USE(WEBAUDIO_IPP)
+ , m_overlayBuffer(inputBlockSize)
+#endif // USE(WEBAUDIO_IPP)
+ , m_buffer(inputBlockSize * 2)
+{
+}
+
+void DirectConvolver::process(AudioFloatArray* convolutionKernel, const float* sourceP, float* destP, size_t framesToProcess)
+{
+ ASSERT(framesToProcess == m_inputBlockSize);
+ if (framesToProcess != m_inputBlockSize)
+ return;
+
+ // Only support kernelSize <= m_inputBlockSize
+ size_t kernelSize = convolutionKernel->size();
+ ASSERT(kernelSize <= m_inputBlockSize);
+ if (kernelSize > m_inputBlockSize)
+ return;
+
+ float* kernelP = convolutionKernel->data();
+
+ // Sanity check
+ bool isCopyGood = kernelP && sourceP && destP && m_buffer.data();
+ ASSERT(isCopyGood);
+ if (!isCopyGood)
+ return;
+
+#if USE(WEBAUDIO_IPP)
+ float* outputBuffer = m_buffer.data();
+ float* overlayBuffer = m_overlayBuffer.data();
+ bool isCopyGood2 = overlayBuffer && m_overlayBuffer.size() >= kernelSize && m_buffer.size() == m_inputBlockSize * 2;
+ ASSERT(isCopyGood2);
+ if (!isCopyGood2)
+ return;
+
+ ippsConv_32f(static_cast<const Ipp32f*>(sourceP), framesToProcess, static_cast<Ipp32f*>(kernelP), kernelSize, static_cast<Ipp32f*>(outputBuffer));
+
+ vadd(outputBuffer, 1, overlayBuffer, 1, destP, 1, framesToProcess);
+ memcpy(overlayBuffer, outputBuffer + m_inputBlockSize, sizeof(float) * kernelSize);
+#else
+ float* inputP = m_buffer.data() + m_inputBlockSize;
+
+ // Copy samples to 2nd half of input buffer.
+ memcpy(inputP, sourceP, sizeof(float) * framesToProcess);
+
+#if OS(DARWIN)
+#if defined(__ppc__) || defined(__i386__)
+ conv(inputP - kernelSize + 1, 1, kernelP + kernelSize - 1, -1, destP, 1, framesToProcess, kernelSize);
+#else
+ vDSP_conv(inputP - kernelSize + 1, 1, kernelP + kernelSize - 1, -1, destP, 1, framesToProcess, kernelSize);
+#endif // defined(__ppc__) || defined(__i386__)
+#else
+ // FIXME: The macro can be further optimized to avoid pipeline stalls. One possibility is to maintain 4 separate sums and change the macro to CONVOLVE_FOUR_SAMPLES.
+#define CONVOLVE_ONE_SAMPLE \
+ sum += inputP[i - j] * kernelP[j]; \
+ j++;
+
+ size_t i = 0;
+ while (i < framesToProcess) {
+ size_t j = 0;
+ float sum = 0;
+
+ // FIXME: SSE optimization may be applied here.
+ if (kernelSize == 32) {
+ CONVOLVE_ONE_SAMPLE // 1
+ CONVOLVE_ONE_SAMPLE // 2
+ CONVOLVE_ONE_SAMPLE // 3
+ CONVOLVE_ONE_SAMPLE // 4
+ CONVOLVE_ONE_SAMPLE // 5
+ CONVOLVE_ONE_SAMPLE // 6
+ CONVOLVE_ONE_SAMPLE // 7
+ CONVOLVE_ONE_SAMPLE // 8
+ CONVOLVE_ONE_SAMPLE // 9
+ CONVOLVE_ONE_SAMPLE // 10
+
+ CONVOLVE_ONE_SAMPLE // 11
+ CONVOLVE_ONE_SAMPLE // 12
+ CONVOLVE_ONE_SAMPLE // 13
+ CONVOLVE_ONE_SAMPLE // 14
+ CONVOLVE_ONE_SAMPLE // 15
+ CONVOLVE_ONE_SAMPLE // 16
+ CONVOLVE_ONE_SAMPLE // 17
+ CONVOLVE_ONE_SAMPLE // 18
+ CONVOLVE_ONE_SAMPLE // 19
+ CONVOLVE_ONE_SAMPLE // 20
+
+ CONVOLVE_ONE_SAMPLE // 21
+ CONVOLVE_ONE_SAMPLE // 22
+ CONVOLVE_ONE_SAMPLE // 23
+ CONVOLVE_ONE_SAMPLE // 24
+ CONVOLVE_ONE_SAMPLE // 25
+ CONVOLVE_ONE_SAMPLE // 26
+ CONVOLVE_ONE_SAMPLE // 27
+ CONVOLVE_ONE_SAMPLE // 28
+ CONVOLVE_ONE_SAMPLE // 29
+ CONVOLVE_ONE_SAMPLE // 30
+
+ CONVOLVE_ONE_SAMPLE // 31
+ CONVOLVE_ONE_SAMPLE // 32
+
+ } else if (kernelSize == 64) {
+ CONVOLVE_ONE_SAMPLE // 1
+ CONVOLVE_ONE_SAMPLE // 2
+ CONVOLVE_ONE_SAMPLE // 3
+ CONVOLVE_ONE_SAMPLE // 4
+ CONVOLVE_ONE_SAMPLE // 5
+ CONVOLVE_ONE_SAMPLE // 6
+ CONVOLVE_ONE_SAMPLE // 7
+ CONVOLVE_ONE_SAMPLE // 8
+ CONVOLVE_ONE_SAMPLE // 9
+ CONVOLVE_ONE_SAMPLE // 10
+
+ CONVOLVE_ONE_SAMPLE // 11
+ CONVOLVE_ONE_SAMPLE // 12
+ CONVOLVE_ONE_SAMPLE // 13
+ CONVOLVE_ONE_SAMPLE // 14
+ CONVOLVE_ONE_SAMPLE // 15
+ CONVOLVE_ONE_SAMPLE // 16
+ CONVOLVE_ONE_SAMPLE // 17
+ CONVOLVE_ONE_SAMPLE // 18
+ CONVOLVE_ONE_SAMPLE // 19
+ CONVOLVE_ONE_SAMPLE // 20
+
+ CONVOLVE_ONE_SAMPLE // 21
+ CONVOLVE_ONE_SAMPLE // 22
+ CONVOLVE_ONE_SAMPLE // 23
+ CONVOLVE_ONE_SAMPLE // 24
+ CONVOLVE_ONE_SAMPLE // 25
+ CONVOLVE_ONE_SAMPLE // 26
+ CONVOLVE_ONE_SAMPLE // 27
+ CONVOLVE_ONE_SAMPLE // 28
+ CONVOLVE_ONE_SAMPLE // 29
+ CONVOLVE_ONE_SAMPLE // 30
+
+ CONVOLVE_ONE_SAMPLE // 31
+ CONVOLVE_ONE_SAMPLE // 32
+ CONVOLVE_ONE_SAMPLE // 33
+ CONVOLVE_ONE_SAMPLE // 34
+ CONVOLVE_ONE_SAMPLE // 35
+ CONVOLVE_ONE_SAMPLE // 36
+ CONVOLVE_ONE_SAMPLE // 37
+ CONVOLVE_ONE_SAMPLE // 38
+ CONVOLVE_ONE_SAMPLE // 39
+ CONVOLVE_ONE_SAMPLE // 40
+
+ CONVOLVE_ONE_SAMPLE // 41
+ CONVOLVE_ONE_SAMPLE // 42
+ CONVOLVE_ONE_SAMPLE // 43
+ CONVOLVE_ONE_SAMPLE // 44
+ CONVOLVE_ONE_SAMPLE // 45
+ CONVOLVE_ONE_SAMPLE // 46
+ CONVOLVE_ONE_SAMPLE // 47
+ CONVOLVE_ONE_SAMPLE // 48
+ CONVOLVE_ONE_SAMPLE // 49
+ CONVOLVE_ONE_SAMPLE // 50
+
+ CONVOLVE_ONE_SAMPLE // 51
+ CONVOLVE_ONE_SAMPLE // 52
+ CONVOLVE_ONE_SAMPLE // 53
+ CONVOLVE_ONE_SAMPLE // 54
+ CONVOLVE_ONE_SAMPLE // 55
+ CONVOLVE_ONE_SAMPLE // 56
+ CONVOLVE_ONE_SAMPLE // 57
+ CONVOLVE_ONE_SAMPLE // 58
+ CONVOLVE_ONE_SAMPLE // 59
+ CONVOLVE_ONE_SAMPLE // 60
+
+ CONVOLVE_ONE_SAMPLE // 61
+ CONVOLVE_ONE_SAMPLE // 62
+ CONVOLVE_ONE_SAMPLE // 63
+ CONVOLVE_ONE_SAMPLE // 64
+
+ } else if (kernelSize == 128) {
+ CONVOLVE_ONE_SAMPLE // 1
+ CONVOLVE_ONE_SAMPLE // 2
+ CONVOLVE_ONE_SAMPLE // 3
+ CONVOLVE_ONE_SAMPLE // 4
+ CONVOLVE_ONE_SAMPLE // 5
+ CONVOLVE_ONE_SAMPLE // 6
+ CONVOLVE_ONE_SAMPLE // 7
+ CONVOLVE_ONE_SAMPLE // 8
+ CONVOLVE_ONE_SAMPLE // 9
+ CONVOLVE_ONE_SAMPLE // 10
+
+ CONVOLVE_ONE_SAMPLE // 11
+ CONVOLVE_ONE_SAMPLE // 12
+ CONVOLVE_ONE_SAMPLE // 13
+ CONVOLVE_ONE_SAMPLE // 14
+ CONVOLVE_ONE_SAMPLE // 15
+ CONVOLVE_ONE_SAMPLE // 16
+ CONVOLVE_ONE_SAMPLE // 17
+ CONVOLVE_ONE_SAMPLE // 18
+ CONVOLVE_ONE_SAMPLE // 19
+ CONVOLVE_ONE_SAMPLE // 20
+
+ CONVOLVE_ONE_SAMPLE // 21
+ CONVOLVE_ONE_SAMPLE // 22
+ CONVOLVE_ONE_SAMPLE // 23
+ CONVOLVE_ONE_SAMPLE // 24
+ CONVOLVE_ONE_SAMPLE // 25
+ CONVOLVE_ONE_SAMPLE // 26
+ CONVOLVE_ONE_SAMPLE // 27
+ CONVOLVE_ONE_SAMPLE // 28
+ CONVOLVE_ONE_SAMPLE // 29
+ CONVOLVE_ONE_SAMPLE // 30
+
+ CONVOLVE_ONE_SAMPLE // 31
+ CONVOLVE_ONE_SAMPLE // 32
+ CONVOLVE_ONE_SAMPLE // 33
+ CONVOLVE_ONE_SAMPLE // 34
+ CONVOLVE_ONE_SAMPLE // 35
+ CONVOLVE_ONE_SAMPLE // 36
+ CONVOLVE_ONE_SAMPLE // 37
+ CONVOLVE_ONE_SAMPLE // 38
+ CONVOLVE_ONE_SAMPLE // 39
+ CONVOLVE_ONE_SAMPLE // 40
+
+ CONVOLVE_ONE_SAMPLE // 41
+ CONVOLVE_ONE_SAMPLE // 42
+ CONVOLVE_ONE_SAMPLE // 43
+ CONVOLVE_ONE_SAMPLE // 44
+ CONVOLVE_ONE_SAMPLE // 45
+ CONVOLVE_ONE_SAMPLE // 46
+ CONVOLVE_ONE_SAMPLE // 47
+ CONVOLVE_ONE_SAMPLE // 48
+ CONVOLVE_ONE_SAMPLE // 49
+ CONVOLVE_ONE_SAMPLE // 50
+
+ CONVOLVE_ONE_SAMPLE // 51
+ CONVOLVE_ONE_SAMPLE // 52
+ CONVOLVE_ONE_SAMPLE // 53
+ CONVOLVE_ONE_SAMPLE // 54
+ CONVOLVE_ONE_SAMPLE // 55
+ CONVOLVE_ONE_SAMPLE // 56
+ CONVOLVE_ONE_SAMPLE // 57
+ CONVOLVE_ONE_SAMPLE // 58
+ CONVOLVE_ONE_SAMPLE // 59
+ CONVOLVE_ONE_SAMPLE // 60
+
+ CONVOLVE_ONE_SAMPLE // 61
+ CONVOLVE_ONE_SAMPLE // 62
+ CONVOLVE_ONE_SAMPLE // 63
+ CONVOLVE_ONE_SAMPLE // 64
+ CONVOLVE_ONE_SAMPLE // 65
+ CONVOLVE_ONE_SAMPLE // 66
+ CONVOLVE_ONE_SAMPLE // 67
+ CONVOLVE_ONE_SAMPLE // 68
+ CONVOLVE_ONE_SAMPLE // 69
+ CONVOLVE_ONE_SAMPLE // 70
+
+ CONVOLVE_ONE_SAMPLE // 71
+ CONVOLVE_ONE_SAMPLE // 72
+ CONVOLVE_ONE_SAMPLE // 73
+ CONVOLVE_ONE_SAMPLE // 74
+ CONVOLVE_ONE_SAMPLE // 75
+ CONVOLVE_ONE_SAMPLE // 76
+ CONVOLVE_ONE_SAMPLE // 77
+ CONVOLVE_ONE_SAMPLE // 78
+ CONVOLVE_ONE_SAMPLE // 79
+ CONVOLVE_ONE_SAMPLE // 80
+
+ CONVOLVE_ONE_SAMPLE // 81
+ CONVOLVE_ONE_SAMPLE // 82
+ CONVOLVE_ONE_SAMPLE // 83
+ CONVOLVE_ONE_SAMPLE // 84
+ CONVOLVE_ONE_SAMPLE // 85
+ CONVOLVE_ONE_SAMPLE // 86
+ CONVOLVE_ONE_SAMPLE // 87
+ CONVOLVE_ONE_SAMPLE // 88
+ CONVOLVE_ONE_SAMPLE // 89
+ CONVOLVE_ONE_SAMPLE // 90
+
+ CONVOLVE_ONE_SAMPLE // 91
+ CONVOLVE_ONE_SAMPLE // 92
+ CONVOLVE_ONE_SAMPLE // 93
+ CONVOLVE_ONE_SAMPLE // 94
+ CONVOLVE_ONE_SAMPLE // 95
+ CONVOLVE_ONE_SAMPLE // 96
+ CONVOLVE_ONE_SAMPLE // 97
+ CONVOLVE_ONE_SAMPLE // 98
+ CONVOLVE_ONE_SAMPLE // 99
+ CONVOLVE_ONE_SAMPLE // 100
+
+ CONVOLVE_ONE_SAMPLE // 101
+ CONVOLVE_ONE_SAMPLE // 102
+ CONVOLVE_ONE_SAMPLE // 103
+ CONVOLVE_ONE_SAMPLE // 104
+ CONVOLVE_ONE_SAMPLE // 105
+ CONVOLVE_ONE_SAMPLE // 106
+ CONVOLVE_ONE_SAMPLE // 107
+ CONVOLVE_ONE_SAMPLE // 108
+ CONVOLVE_ONE_SAMPLE // 109
+ CONVOLVE_ONE_SAMPLE // 110
+
+ CONVOLVE_ONE_SAMPLE // 111
+ CONVOLVE_ONE_SAMPLE // 112
+ CONVOLVE_ONE_SAMPLE // 113
+ CONVOLVE_ONE_SAMPLE // 114
+ CONVOLVE_ONE_SAMPLE // 115
+ CONVOLVE_ONE_SAMPLE // 116
+ CONVOLVE_ONE_SAMPLE // 117
+ CONVOLVE_ONE_SAMPLE // 118
+ CONVOLVE_ONE_SAMPLE // 119
+ CONVOLVE_ONE_SAMPLE // 120
+
+ CONVOLVE_ONE_SAMPLE // 121
+ CONVOLVE_ONE_SAMPLE // 122
+ CONVOLVE_ONE_SAMPLE // 123
+ CONVOLVE_ONE_SAMPLE // 124
+ CONVOLVE_ONE_SAMPLE // 125
+ CONVOLVE_ONE_SAMPLE // 126
+ CONVOLVE_ONE_SAMPLE // 127
+ CONVOLVE_ONE_SAMPLE // 128
+ } else {
+ while (j < kernelSize) {
+ // Non-optimized using actual while loop.
+ CONVOLVE_ONE_SAMPLE
+ }
+ }
+ destP[i++] = sum;
+ }
+#endif // OS(DARWIN)
+
+ // Copy 2nd half of input buffer to 1st half.
+ memcpy(m_buffer.data(), inputP, sizeof(float) * framesToProcess);
+#endif
+}
+
+void DirectConvolver::reset()
+{
+ m_buffer.zero();
+#if USE(WEBAUDIO_IPP)
+ m_overlayBuffer.zero();
+#endif // USE(WEBAUDIO_IPP)
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/platform/audio/DirectConvolver.h b/Source/WebCore/platform/audio/DirectConvolver.h
new file mode 100644
index 000000000..1cb8c672d
--- /dev/null
+++ b/Source/WebCore/platform/audio/DirectConvolver.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 Intel Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DirectConvolver_h
+#define DirectConvolver_h
+
+#include "AudioArray.h"
+
+#if USE(WEBAUDIO_IPP)
+#include <ipps.h>
+#endif // USE(WEBAUDIO_IPP)
+
+namespace WebCore {
+
+class DirectConvolver {
+public:
+ DirectConvolver(size_t inputBlockSize);
+
+ void process(AudioFloatArray* convolutionKernel, const float* sourceP, float* destP, size_t framesToProcess);
+
+ void reset();
+
+private:
+ size_t m_inputBlockSize;
+
+#if USE(WEBAUDIO_IPP)
+ AudioFloatArray m_overlayBuffer;
+#endif // USE(WEBAUDIO_IPP)
+ AudioFloatArray m_buffer;
+};
+
+} // namespace WebCore
+
+#endif // DirectConvolver_h
diff --git a/Source/WebCore/platform/audio/DynamicsCompressor.h b/Source/WebCore/platform/audio/DynamicsCompressor.h
index b35294d6a..f781afe7b 100644
--- a/Source/WebCore/platform/audio/DynamicsCompressor.h
+++ b/Source/WebCore/platform/audio/DynamicsCompressor.h
@@ -78,12 +78,13 @@ public:
float sampleRate() const { return m_sampleRate; }
float nyquist() const { return m_sampleRate / 2; }
+ double tailTime() const { return 0; }
+ double latencyTime() const { return m_compressor.latencyFrames() / static_cast<double>(sampleRate()); }
+
protected:
unsigned m_numberOfChannels;
// m_parameters holds the tweakable compressor parameters.
- // FIXME: expose some of the most important ones (such as threshold, attack, release)
- // as DynamicsCompressorNode attributes.
float m_parameters[ParamLast];
void initializeParameters();
diff --git a/Source/WebCore/platform/audio/EqualPowerPanner.cpp b/Source/WebCore/platform/audio/EqualPowerPanner.cpp
index a2d2dff4c..903536786 100644
--- a/Source/WebCore/platform/audio/EqualPowerPanner.cpp
+++ b/Source/WebCore/platform/audio/EqualPowerPanner.cpp
@@ -51,8 +51,8 @@ EqualPowerPanner::EqualPowerPanner(float sampleRate)
void EqualPowerPanner::pan(double azimuth, double /*elevation*/, const AudioBus* inputBus, AudioBus* outputBus, size_t framesToProcess)
{
- // FIXME: implement stereo sources
- bool isInputSafe = inputBus && inputBus->numberOfChannels() == 1 && framesToProcess <= inputBus->length();
+ unsigned numberOfInputChannels = inputBus->numberOfChannels();
+ bool isInputSafe = inputBus && (numberOfInputChannels == 1 || numberOfInputChannels == 2) && framesToProcess <= inputBus->length();
ASSERT(isInputSafe);
if (!isInputSafe)
return;
@@ -62,14 +62,14 @@ void EqualPowerPanner::pan(double azimuth, double /*elevation*/, const AudioBus*
if (!isOutputSafe)
return;
- const AudioChannel* channel = inputBus->channel(0);
- const float* sourceP = channel->data();
+ const float* sourceL = inputBus->channel(0)->data();
+ const float* sourceR = numberOfInputChannels > 1 ? inputBus->channel(1)->data() : sourceL;
float* destinationL = outputBus->channelByType(AudioBus::ChannelLeft)->mutableData();
float* destinationR = outputBus->channelByType(AudioBus::ChannelRight)->mutableData();
-
- if (!sourceP || !destinationL || !destinationR)
+
+ if (!sourceL || !sourceR || !destinationL || !destinationR)
return;
-
+
// Clamp azimuth to allowed range of -180 -> +180.
azimuth = max(-180.0, azimuth);
azimuth = min(180.0, azimuth);
@@ -80,35 +80,73 @@ void EqualPowerPanner::pan(double azimuth, double /*elevation*/, const AudioBus*
azimuth = -180 - azimuth;
else if (azimuth > 90)
azimuth = 180 - azimuth;
-
- // Pan smoothly from left to right with azimuth going from -90 -> +90 degrees.
- double desiredPanPosition = (azimuth + 90) / 180;
- double desiredGainL = cos(0.5 * piDouble * desiredPanPosition);
- double desiredGainR = sin(0.5 * piDouble * desiredPanPosition);
+ double desiredPanPosition;
+ double desiredGainL;
+ double desiredGainR;
+
+ if (numberOfInputChannels == 1) { // For mono source case.
+ // Pan smoothly from left to right with azimuth going from -90 -> +90 degrees.
+ desiredPanPosition = (azimuth + 90) / 180;
+ } else { // For stereo source case.
+ if (azimuth <= 0) { // from -90 -> 0
+ // sourceL -> destL and "equal-power pan" sourceR as in mono case
+ // by transforming the "azimuth" value from -90 -> 0 degrees into the range -90 -> +90.
+ desiredPanPosition = (azimuth + 90) / 90;
+ } else { // from 0 -> +90
+ // sourceR -> destR and "equal-power pan" sourceL as in mono case
+ // by transforming the "azimuth" value from 0 -> +90 degrees into the range -90 -> +90.
+ desiredPanPosition = azimuth / 90;
+ }
+ }
+ desiredGainL = cos(0.5 * piDouble * desiredPanPosition);
+ desiredGainR = sin(0.5 * piDouble * desiredPanPosition);
+
// Don't de-zipper on first render call.
if (m_isFirstRender) {
m_isFirstRender = false;
m_gainL = desiredGainL;
m_gainR = desiredGainR;
}
-
+
// Cache in local variables.
double gainL = m_gainL;
double gainR = m_gainR;
-
+
// Get local copy of smoothing constant.
const double SmoothingConstant = m_smoothingConstant;
-
+
int n = framesToProcess;
- while (n--) {
- float input = *sourceP++;
- gainL += (desiredGainL - gainL) * SmoothingConstant;
- gainR += (desiredGainR - gainR) * SmoothingConstant;
- *destinationL++ = static_cast<float>(input * gainL);
- *destinationR++ = static_cast<float>(input * gainR);
+ if (numberOfInputChannels == 1) { // For mono source case.
+ while (n--) {
+ float inputL = *sourceL++;
+ gainL += (desiredGainL - gainL) * SmoothingConstant;
+ gainR += (desiredGainR - gainR) * SmoothingConstant;
+ *destinationL++ = static_cast<float>(inputL * gainL);
+ *destinationR++ = static_cast<float>(inputL * gainR);
+ }
+ } else { // For stereo source case.
+ if (azimuth <= 0) { // from -90 -> 0
+ while (n--) {
+ float inputL = *sourceL++;
+ float inputR = *sourceR++;
+ gainL += (desiredGainL - gainL) * SmoothingConstant;
+ gainR += (desiredGainR - gainR) * SmoothingConstant;
+ *destinationL++ = static_cast<float>(inputL + inputR * gainL);
+ *destinationR++ = static_cast<float>(inputR * gainR);
+ }
+ } else { // from 0 -> +90
+ while (n--) {
+ float inputL = *sourceL++;
+ float inputR = *sourceR++;
+ gainL += (desiredGainL - gainL) * SmoothingConstant;
+ gainR += (desiredGainR - gainR) * SmoothingConstant;
+ *destinationL++ = static_cast<float>(inputL * gainL);
+ *destinationR++ = static_cast<float>(inputR + inputL * gainR);
+ }
+ }
}
m_gainL = gainL;
diff --git a/Source/WebCore/platform/audio/EqualPowerPanner.h b/Source/WebCore/platform/audio/EqualPowerPanner.h
index 016cd4aa1..012e214ca 100644
--- a/Source/WebCore/platform/audio/EqualPowerPanner.h
+++ b/Source/WebCore/platform/audio/EqualPowerPanner.h
@@ -39,6 +39,9 @@ public:
virtual void reset() { m_isFirstRender = true; }
+ virtual double tailTime() const OVERRIDE { return 0; }
+ virtual double latencyTime() const OVERRIDE { return 0; }
+
private:
// For smoothing / de-zippering
bool m_isFirstRender;
diff --git a/Source/WebCore/platform/audio/FFTConvolver.cpp b/Source/WebCore/platform/audio/FFTConvolver.cpp
index 2321de0cf..fa158696e 100644
--- a/Source/WebCore/platform/audio/FFTConvolver.cpp
+++ b/Source/WebCore/platform/audio/FFTConvolver.cpp
@@ -49,53 +49,63 @@ FFTConvolver::FFTConvolver(size_t fftSize)
void FFTConvolver::process(FFTFrame* fftKernel, const float* sourceP, float* destP, size_t framesToProcess)
{
- // FIXME: make so framesToProcess is not required to fit evenly into fftSize/2
-
- // Copy samples to input buffer (note contraint above!)
- float* inputP = m_inputBuffer.data();
+ size_t halfSize = fftSize() / 2;
- // Sanity check
- bool isCopyGood1 = sourceP && inputP && m_readWriteIndex + framesToProcess <= m_inputBuffer.size();
- ASSERT(isCopyGood1);
- if (!isCopyGood1)
+ // framesToProcess must be an exact multiple of halfSize,
+ // or halfSize is a multiple of framesToProcess when halfSize > framesToProcess.
+ bool isGood = !(halfSize % framesToProcess && framesToProcess % halfSize);
+ ASSERT(isGood);
+ if (!isGood)
return;
-
- memcpy(inputP + m_readWriteIndex, sourceP, sizeof(float) * framesToProcess);
- // Copy samples from output buffer
- float* outputP = m_outputBuffer.data();
+ size_t numberOfDivisions = halfSize <= framesToProcess ? (framesToProcess / halfSize) : 1;
+ size_t divisionSize = numberOfDivisions == 1 ? framesToProcess : halfSize;
- // Sanity check
- bool isCopyGood2 = destP && outputP && m_readWriteIndex + framesToProcess <= m_outputBuffer.size();
- ASSERT(isCopyGood2);
- if (!isCopyGood2)
- return;
+ for (size_t i = 0; i < numberOfDivisions; ++i, sourceP += divisionSize, destP += divisionSize) {
+ // Copy samples to input buffer (note contraint above!)
+ float* inputP = m_inputBuffer.data();
- memcpy(destP, outputP + m_readWriteIndex, sizeof(float) * framesToProcess);
- m_readWriteIndex += framesToProcess;
+ // Sanity check
+ bool isCopyGood1 = sourceP && inputP && m_readWriteIndex + divisionSize <= m_inputBuffer.size();
+ ASSERT(isCopyGood1);
+ if (!isCopyGood1)
+ return;
+ memcpy(inputP + m_readWriteIndex, sourceP, sizeof(float) * divisionSize);
- // Check if it's time to perform the next FFT
- size_t halfSize = fftSize() / 2;
- if (m_readWriteIndex == halfSize) {
- // The input buffer is now filled (get frequency-domain version)
- m_frame.doFFT(m_inputBuffer.data());
- m_frame.multiply(*fftKernel);
- m_frame.doInverseFFT(m_outputBuffer.data());
-
- // Overlap-add 1st half from previous time
- vadd(m_outputBuffer.data(), 1, m_lastOverlapBuffer.data(), 1, m_outputBuffer.data(), 1, halfSize);
-
- // Finally, save 2nd half of result
- bool isCopyGood3 = m_outputBuffer.size() == 2 * halfSize && m_lastOverlapBuffer.size() == halfSize;
- ASSERT(isCopyGood3);
- if (!isCopyGood3)
+ // Copy samples from output buffer
+ float* outputP = m_outputBuffer.data();
+
+ // Sanity check
+ bool isCopyGood2 = destP && outputP && m_readWriteIndex + divisionSize <= m_outputBuffer.size();
+ ASSERT(isCopyGood2);
+ if (!isCopyGood2)
return;
-
- memcpy(m_lastOverlapBuffer.data(), m_outputBuffer.data() + halfSize, sizeof(float) * halfSize);
- // Reset index back to start for next time
- m_readWriteIndex = 0;
+ memcpy(destP, outputP + m_readWriteIndex, sizeof(float) * divisionSize);
+ m_readWriteIndex += divisionSize;
+
+ // Check if it's time to perform the next FFT
+ if (m_readWriteIndex == halfSize) {
+ // The input buffer is now filled (get frequency-domain version)
+ m_frame.doFFT(m_inputBuffer.data());
+ m_frame.multiply(*fftKernel);
+ m_frame.doInverseFFT(m_outputBuffer.data());
+
+ // Overlap-add 1st half from previous time
+ vadd(m_outputBuffer.data(), 1, m_lastOverlapBuffer.data(), 1, m_outputBuffer.data(), 1, halfSize);
+
+ // Finally, save 2nd half of result
+ bool isCopyGood3 = m_outputBuffer.size() == 2 * halfSize && m_lastOverlapBuffer.size() == halfSize;
+ ASSERT(isCopyGood3);
+ if (!isCopyGood3)
+ return;
+
+ memcpy(m_lastOverlapBuffer.data(), m_outputBuffer.data() + halfSize, sizeof(float) * halfSize);
+
+ // Reset index back to start for next time
+ m_readWriteIndex = 0;
+ }
}
}
diff --git a/Source/WebCore/platform/audio/HRTFElevation.cpp b/Source/WebCore/platform/audio/HRTFElevation.cpp
index eb07d4ec9..080b3911e 100644
--- a/Source/WebCore/platform/audio/HRTFElevation.cpp
+++ b/Source/WebCore/platform/audio/HRTFElevation.cpp
@@ -60,7 +60,7 @@ const size_t ResponseFrameSize = 256;
// The impulse responses may be resampled to a different sample-rate (depending on the audio hardware) when they are loaded.
const float ResponseSampleRate = 44100;
-#if PLATFORM(GTK) || PLATFORM(MAC)
+#if PLATFORM(GTK) || PLATFORM(MAC) || PLATFORM(EFL)
#define USE_CONCATENATED_IMPULSE_RESPONSES
#endif
diff --git a/Source/WebCore/platform/audio/HRTFPanner.cpp b/Source/WebCore/platform/audio/HRTFPanner.cpp
index 4c69932ed..1cc9ff863 100644
--- a/Source/WebCore/platform/audio/HRTFPanner.cpp
+++ b/Source/WebCore/platform/audio/HRTFPanner.cpp
@@ -294,6 +294,21 @@ void HRTFPanner::pan(double desiredAzimuth, double elevation, const AudioBus* in
}
}
+double HRTFPanner::tailTime() const
+{
+ // Because HRTFPanner is implemented with a DelayKernel and a FFTConvolver, the tailTime of the HRTFPanner
+ // is the sum of the tailTime of the DelayKernel and the tailTime of the FFTConvolver, which is MaxDelayTimeSeconds
+ // and fftSize() / 2, respectively.
+ return MaxDelayTimeSeconds + (fftSize() / 2) / static_cast<double>(sampleRate());
+}
+
+double HRTFPanner::latencyTime() const
+{
+ // The latency of a FFTConvolver is also fftSize() / 2, and is in addition to its tailTime of the
+ // same value.
+ return (fftSize() / 2) / static_cast<double>(sampleRate());
+}
+
} // namespace WebCore
#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/platform/audio/HRTFPanner.h b/Source/WebCore/platform/audio/HRTFPanner.h
index f5af1d152..785cf095a 100644
--- a/Source/WebCore/platform/audio/HRTFPanner.h
+++ b/Source/WebCore/platform/audio/HRTFPanner.h
@@ -40,11 +40,14 @@ public:
virtual void pan(double azimuth, double elevation, const AudioBus* inputBus, AudioBus* outputBus, size_t framesToProcess);
virtual void reset();
- size_t fftSize() { return fftSizeForSampleRate(m_sampleRate); }
+ size_t fftSize() const { return fftSizeForSampleRate(m_sampleRate); }
static size_t fftSizeForSampleRate(float sampleRate);
float sampleRate() const { return m_sampleRate; }
+ virtual double tailTime() const OVERRIDE;
+ virtual double latencyTime() const OVERRIDE;
+
private:
// Given an azimuth angle in the range -180 -> +180, returns the corresponding azimuth index for the database,
// and azimuthBlend which is an interpolation value from 0 -> 1.
diff --git a/Source/WebCore/platform/audio/Panner.h b/Source/WebCore/platform/audio/Panner.h
index d8b8dd0f1..f8b240e60 100644
--- a/Source/WebCore/platform/audio/Panner.h
+++ b/Source/WebCore/platform/audio/Panner.h
@@ -57,6 +57,9 @@ public:
virtual void reset() = 0;
+ virtual double tailTime() const = 0;
+ virtual double latencyTime() const = 0;
+
protected:
Panner(PanningModel model) : m_panningModel(model) { }
diff --git a/Source/WebCore/platform/audio/Reverb.cpp b/Source/WebCore/platform/audio/Reverb.cpp
index 122e21b68..ca7317d1e 100644
--- a/Source/WebCore/platform/audio/Reverb.cpp
+++ b/Source/WebCore/platform/audio/Reverb.cpp
@@ -51,6 +51,7 @@ using namespace VectorMath;
// Empirical gain calibration tested across many impulse responses to ensure perceived volume is same as dry (unprocessed) signal
const float GainCalibration = -58;
+const float GainCalibrationSampleRate = 44100;
// A minimum power value to when normalizing a silent (or very quiet) impulse response
const float MinPower = 0.000125f;
@@ -79,6 +80,10 @@ static float calculateNormalizationScale(AudioBus* response)
scale *= powf(10, GainCalibration * 0.05f); // calibrate to make perceived volume same as unprocessed
+ // Scale depends on sample-rate.
+ if (response->sampleRate())
+ scale *= GainCalibrationSampleRate / response->sampleRate();
+
// True-stereo compensation
if (response->numberOfChannels() == 4)
scale *= 0.5f;
@@ -228,6 +233,11 @@ void Reverb::reset()
m_convolvers[i]->reset();
}
+size_t Reverb::latencyFrames() const
+{
+ return !m_convolvers.isEmpty() ? m_convolvers.first()->latencyFrames() : 0;
+}
+
} // namespace WebCore
#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/platform/audio/Reverb.h b/Source/WebCore/platform/audio/Reverb.h
index 779e7bba4..0ae50d6d1 100644
--- a/Source/WebCore/platform/audio/Reverb.h
+++ b/Source/WebCore/platform/audio/Reverb.h
@@ -48,7 +48,8 @@ public:
void process(const AudioBus* sourceBus, AudioBus* destinationBus, size_t framesToProcess);
void reset();
- unsigned impulseResponseLength() const { return m_impulseResponseLength; }
+ size_t impulseResponseLength() const { return m_impulseResponseLength; }
+ size_t latencyFrames() const;
private:
void initialize(AudioBus* impulseResponseBuffer, size_t renderSliceSize, size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads);
diff --git a/Source/WebCore/platform/audio/ReverbConvolver.cpp b/Source/WebCore/platform/audio/ReverbConvolver.cpp
index c6ab54e8e..ad9cfcf41 100644
--- a/Source/WebCore/platform/audio/ReverbConvolver.cpp
+++ b/Source/WebCore/platform/audio/ReverbConvolver.cpp
@@ -50,7 +50,7 @@ const int InputBufferSize = 8 * 16384;
// tuned for individual platforms if this assumption is found to be incorrect.
const size_t RealtimeFrameLimit = 8192 + 4096; // ~278msec @ 44.1KHz
-const size_t MinFFTSize = 256;
+const size_t MinFFTSize = 128;
const size_t MaxRealtimeFFTSize = 2048;
static void backgroundThreadEntry(void* threadData)
@@ -84,8 +84,8 @@ ReverbConvolver::ReverbConvolver(AudioChannel* impulseResponse, size_t renderSli
const float* response = impulseResponse->data();
size_t totalResponseLength = impulseResponse->length();
- // Because we're not using direct-convolution in the leading portion, the reverb has an overall latency of half the first-stage FFT size
- size_t reverbTotalLatency = m_minFFTSize / 2;
+ // The total latency is zero because the direct-convolution is used in the leading portion.
+ size_t reverbTotalLatency = 0;
size_t stageOffset = 0;
int i = 0;
@@ -101,7 +101,9 @@ ReverbConvolver::ReverbConvolver(AudioChannel* impulseResponse, size_t renderSli
// This "staggers" the time when each FFT happens so they don't all happen at the same time
int renderPhase = convolverRenderPhase + i * renderSliceSize;
- OwnPtr<ReverbConvolverStage> stage = adoptPtr(new ReverbConvolverStage(response, totalResponseLength, reverbTotalLatency, stageOffset, stageSize, fftSize, renderPhase, renderSliceSize, &m_accumulationBuffer));
+ bool useDirectConvolver = !stageOffset;
+
+ OwnPtr<ReverbConvolverStage> stage = adoptPtr(new ReverbConvolverStage(response, totalResponseLength, reverbTotalLatency, stageOffset, stageSize, fftSize, renderPhase, renderSliceSize, &m_accumulationBuffer, useDirectConvolver));
bool isBackgroundStage = false;
@@ -114,8 +116,11 @@ ReverbConvolver::ReverbConvolver(AudioChannel* impulseResponse, size_t renderSli
stageOffset += stageSize;
++i;
- // Figure out next FFT size
- fftSize *= 2;
+ if (!useDirectConvolver) {
+ // Figure out next FFT size
+ fftSize *= 2;
+ }
+
if (hasRealtimeConstraint && !isBackgroundStage && fftSize > m_maxRealtimeFFTSize)
fftSize = m_maxRealtimeFFTSize;
if (fftSize > m_maxFFTSize)
@@ -224,6 +229,11 @@ void ReverbConvolver::reset()
m_inputBuffer.reset();
}
+size_t ReverbConvolver::latencyFrames() const
+{
+ return 0;
+}
+
} // namespace WebCore
#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/platform/audio/ReverbConvolver.h b/Source/WebCore/platform/audio/ReverbConvolver.h
index 370b87206..a7d661976 100644
--- a/Source/WebCore/platform/audio/ReverbConvolver.h
+++ b/Source/WebCore/platform/audio/ReverbConvolver.h
@@ -30,6 +30,7 @@
#define ReverbConvolver_h
#include "AudioArray.h"
+#include "DirectConvolver.h"
#include "FFTConvolver.h"
#include "ReverbAccumulationBuffer.h"
#include "ReverbConvolverStage.h"
@@ -62,6 +63,7 @@ public:
bool useBackgroundThreads() const { return m_useBackgroundThreads; }
void backgroundThreadEntry();
+ size_t latencyFrames() const;
private:
Vector<OwnPtr<ReverbConvolverStage> > m_stages;
Vector<OwnPtr<ReverbConvolverStage> > m_backgroundStages;
diff --git a/Source/WebCore/platform/audio/ReverbConvolverStage.cpp b/Source/WebCore/platform/audio/ReverbConvolverStage.cpp
index 53bb65008..e8c4d3fb8 100644
--- a/Source/WebCore/platform/audio/ReverbConvolverStage.cpp
+++ b/Source/WebCore/platform/audio/ReverbConvolverStage.cpp
@@ -44,18 +44,25 @@ namespace WebCore {
using namespace VectorMath;
ReverbConvolverStage::ReverbConvolverStage(const float* impulseResponse, size_t responseLength, size_t reverbTotalLatency, size_t stageOffset, size_t stageLength,
- size_t fftSize, size_t renderPhase, size_t renderSliceSize, ReverbAccumulationBuffer* accumulationBuffer)
- : m_fftKernel(fftSize)
- , m_accumulationBuffer(accumulationBuffer)
+ size_t fftSize, size_t renderPhase, size_t renderSliceSize, ReverbAccumulationBuffer* accumulationBuffer, bool directMode)
+ : m_accumulationBuffer(accumulationBuffer)
, m_accumulationReadIndex(0)
, m_inputReadIndex(0)
, m_impulseResponseLength(responseLength)
+ , m_directMode(directMode)
{
ASSERT(impulseResponse);
ASSERT(accumulationBuffer);
-
- m_fftKernel.doPaddedFFT(impulseResponse + stageOffset, stageLength);
- m_convolver = adoptPtr(new FFTConvolver(fftSize));
+
+ if (!m_directMode) {
+ m_fftKernel = adoptPtr(new FFTFrame(fftSize));
+ m_fftKernel->doPaddedFFT(impulseResponse + stageOffset, stageLength);
+ m_fftConvolver = adoptPtr(new FFTConvolver(fftSize));
+ } else {
+ m_directKernel = adoptPtr(new AudioFloatArray(fftSize / 2));
+ m_directKernel->copyToRange(impulseResponse + stageOffset, 0, fftSize / 2);
+ m_directConvolver = adoptPtr(new DirectConvolver(renderSliceSize));
+ }
m_temporaryBuffer.allocate(renderSliceSize);
// The convolution stage at offset stageOffset needs to have a corresponding delay to cancel out the offset.
@@ -63,9 +70,11 @@ ReverbConvolverStage::ReverbConvolverStage(const float* impulseResponse, size_t
// But, the FFT convolution itself incurs fftSize / 2 latency, so subtract this out...
size_t halfSize = fftSize / 2;
- ASSERT(totalDelay >= halfSize);
- if (totalDelay >= halfSize)
- totalDelay -= halfSize;
+ if (!m_directMode) {
+ ASSERT(totalDelay >= halfSize);
+ if (totalDelay >= halfSize)
+ totalDelay -= halfSize;
+ }
// We divide up the total delay, into pre and post delay sections so that we can schedule at exactly the moment when the FFT will happen.
// This is coordinated with the other stages, so they don't all do their FFTs at the same time...
@@ -78,7 +87,9 @@ ReverbConvolverStage::ReverbConvolverStage(const float* impulseResponse, size_t
m_preReadWriteIndex = 0;
m_framesProcessed = 0; // total frames processed so far
- m_preDelayBuffer.allocate(m_preDelayLength < fftSize ? fftSize : m_preDelayLength);
+ size_t delayBufferSize = m_preDelayLength < fftSize ? fftSize : m_preDelayLength;
+ delayBufferSize = delayBufferSize < renderSliceSize ? renderSliceSize : delayBufferSize;
+ m_preDelayBuffer.allocate(delayBufferSize);
}
void ReverbConvolverStage::processInBackground(ReverbConvolver* convolver, size_t framesToProcess)
@@ -133,7 +144,10 @@ void ReverbConvolverStage::process(const float* source, size_t framesToProcess)
// Now, run the convolution (into the delay buffer).
// An expensive FFT will happen every fftSize / 2 frames.
// We process in-place here...
- m_convolver->process(&m_fftKernel, preDelayedSource, temporaryBuffer, framesToProcess);
+ if (!m_directMode)
+ m_fftConvolver->process(m_fftKernel.get(), preDelayedSource, temporaryBuffer, framesToProcess);
+ else
+ m_directConvolver->process(m_directKernel.get(), preDelayedSource, temporaryBuffer, framesToProcess);
// Now accumulate into reverb's accumulation buffer.
m_accumulationBuffer->accumulate(temporaryBuffer, framesToProcess, &m_accumulationReadIndex, m_postDelayLength);
@@ -154,7 +168,10 @@ void ReverbConvolverStage::process(const float* source, size_t framesToProcess)
void ReverbConvolverStage::reset()
{
- m_convolver->reset();
+ if (!m_directMode)
+ m_fftConvolver->reset();
+ else
+ m_directConvolver->reset();
m_preDelayBuffer.zero();
m_accumulationReadIndex = 0;
m_inputReadIndex = 0;
diff --git a/Source/WebCore/platform/audio/ReverbConvolverStage.h b/Source/WebCore/platform/audio/ReverbConvolverStage.h
index 9811bc603..9ce8dcac8 100644
--- a/Source/WebCore/platform/audio/ReverbConvolverStage.h
+++ b/Source/WebCore/platform/audio/ReverbConvolverStage.h
@@ -38,6 +38,7 @@ namespace WebCore {
class ReverbAccumulationBuffer;
class ReverbConvolver;
class FFTConvolver;
+class DirectConvolver;
// A ReverbConvolverStage represents the convolution associated with a sub-section of a large impulse response.
// It incorporates a delay line to account for the offset of the sub-section within the larger impulse response.
@@ -45,8 +46,7 @@ class ReverbConvolverStage {
public:
// renderPhase is useful to know so that we can manipulate the pre versus post delay so that stages will perform
// their heavy work (FFT processing) on different slices to balance the load in a real-time thread.
- ReverbConvolverStage(const float* impulseResponse, size_t responseLength, size_t reverbTotalLatency, size_t stageOffset, size_t stageLength,
- size_t fftSize, size_t renderPhase, size_t renderSliceSize, ReverbAccumulationBuffer* accumulationBuffer);
+ ReverbConvolverStage(const float* impulseResponse, size_t responseLength, size_t reverbTotalLatency, size_t stageOffset, size_t stageLength, size_t fftSize, size_t renderPhase, size_t renderSliceSize, ReverbAccumulationBuffer*, bool directMode = false);
// WARNING: framesToProcess must be such that it evenly divides the delay buffer size (stage_offset).
void process(const float* source, size_t framesToProcess);
@@ -59,8 +59,8 @@ public:
int inputReadIndex() const { return m_inputReadIndex; }
private:
- FFTFrame m_fftKernel;
- OwnPtr<FFTConvolver> m_convolver;
+ OwnPtr<FFTFrame> m_fftKernel;
+ OwnPtr<FFTConvolver> m_fftConvolver;
AudioFloatArray m_preDelayBuffer;
@@ -76,6 +76,10 @@ private:
AudioFloatArray m_temporaryBuffer;
size_t m_impulseResponseLength;
+
+ bool m_directMode;
+ OwnPtr<AudioFloatArray> m_directKernel;
+ OwnPtr<DirectConvolver> m_directConvolver;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/audio/chromium/AudioBusChromium.cpp b/Source/WebCore/platform/audio/chromium/AudioBusChromium.cpp
index f2a009641..ba35a2c9f 100644
--- a/Source/WebCore/platform/audio/chromium/AudioBusChromium.cpp
+++ b/Source/WebCore/platform/audio/chromium/AudioBusChromium.cpp
@@ -30,14 +30,20 @@
#include "AudioFileReader.h"
#include "PlatformSupport.h"
+#include <public/Platform.h>
#include <wtf/PassOwnPtr.h>
namespace WebCore {
PassOwnPtr<AudioBus> AudioBus::loadPlatformResource(const char* name, float sampleRate)
{
+ const WebKit::WebData& resource = WebKit::Platform::current()->loadResource(name);
+ if (resource.isEmpty())
+ return nullptr;
+
// FIXME: the sampleRate parameter is ignored. It should be removed from the API.
- OwnPtr<AudioBus> audioBus = PlatformSupport::loadPlatformAudioResource(name, sampleRate);
+ OwnPtr<AudioBus> audioBus = PlatformSupport::decodeAudioFileData(resource.data(), resource.size(), sampleRate);
+
if (!audioBus.get())
return nullptr;
diff --git a/Source/WebCore/platform/audio/efl/AudioBusEfl.cpp b/Source/WebCore/platform/audio/efl/AudioBusEfl.cpp
new file mode 100644
index 000000000..79dcef107
--- /dev/null
+++ b/Source/WebCore/platform/audio/efl/AudioBusEfl.cpp
@@ -0,0 +1,42 @@
+/*
+ Copyright (C) 2012 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#if ENABLE(WEB_AUDIO)
+#include "AudioBus.h"
+
+#include "AudioFileReader.h"
+#include "FileSystem.h"
+#include <wtf/text/CString.h>
+#include <wtf/text/StringConcatenate.h>
+
+namespace WebCore {
+
+PassOwnPtr<AudioBus> AudioBus::loadPlatformResource(const char* name, float sampleRate)
+{
+ String absoluteFilename(makeString(DATA_DIR, "/webaudio/resources/", name, ".wav"));
+ if (!fileExists(absoluteFilename))
+ absoluteFilename = makeString(UNINSTALLED_AUDIO_RESOURCES_DIR, "/", name, ".wav");
+
+ return createBusFromAudioFile(absoluteFilename.utf8().data(), false, sampleRate);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/platform/audio/gstreamer/AudioDestinationGStreamer.cpp b/Source/WebCore/platform/audio/gstreamer/AudioDestinationGStreamer.cpp
index 30ebbf9b8..5611bdb67 100644
--- a/Source/WebCore/platform/audio/gstreamer/AudioDestinationGStreamer.cpp
+++ b/Source/WebCore/platform/audio/gstreamer/AudioDestinationGStreamer.cpp
@@ -24,7 +24,7 @@
#include "AudioChannel.h"
#include "AudioSourceProvider.h"
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#include "GRefPtrGStreamer.h"
#include "WebKitWebAudioSourceGStreamer.h"
#include <gst/gst.h>
@@ -57,11 +57,6 @@ AudioDestinationGStreamer::AudioDestinationGStreamer(AudioSourceProvider& provid
, m_sampleRate(sampleRate)
, m_isPlaying(false)
{
- static bool gstInitialized = false;
- if (!gstInitialized)
- gstInitialized = gst_init_check(0, 0, 0);
- ASSERT_WITH_MESSAGE(gstInitialized, "GStreamer initialization failed");
-
m_pipeline = gst_pipeline_new("play");
GstElement* webkitAudioSrc = reinterpret_cast<GstElement*>(g_object_new(WEBKIT_TYPE_WEB_AUDIO_SRC,
diff --git a/Source/WebCore/platform/audio/gstreamer/AudioFileReaderGStreamer.cpp b/Source/WebCore/platform/audio/gstreamer/AudioFileReaderGStreamer.cpp
index 093f81fa8..5b92eb7bd 100644
--- a/Source/WebCore/platform/audio/gstreamer/AudioFileReaderGStreamer.cpp
+++ b/Source/WebCore/platform/audio/gstreamer/AudioFileReaderGStreamer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Igalia S.L
+ * Copyright (C) 2011, 2012 Igalia S.L
* Copyright (C) 2011 Zan Dobersek <zandobersek@gmail.com>
*
* This library is free software; you can redistribute it and/or
@@ -24,8 +24,6 @@
#include "AudioFileReader.h"
#include "AudioBus.h"
-#include "GOwnPtr.h"
-#include "GRefPtr.h"
#include <gio/gio.h>
#include <gst/app/gstappsink.h>
#include <gst/audio/multichannel.h>
@@ -33,6 +31,8 @@
#include <gst/pbutils/pbutils.h>
#include <wtf/Noncopyable.h>
#include <wtf/PassOwnPtr.h>
+#include <wtf/gobject/GOwnPtr.h>
+#include <wtf/gobject/GRefPtr.h>
namespace WebCore {
@@ -50,6 +50,7 @@ public:
void handleNewDeinterleavePad(GstPad*);
void deinterleavePadsConfigured();
void plugDeinterleave(GstPad*);
+ void decodeAudioForBusCreation();
private:
const void* m_data;
@@ -62,11 +63,10 @@ private:
GstBufferList* m_frontRightBuffers;
GstBufferListIterator* m_frontRightBuffersIterator;
GstElement* m_pipeline;
- bool m_eos;
unsigned m_channelSize;
-
- gulong m_deinterleavePadAddedSignalHandlerId;
- gulong m_deinterleaveNoMorePadSignalHandlerId;
+ GRefPtr<GstElement> m_decodebin;
+ GRefPtr<GstElement> m_deInterleave;
+ GRefPtr<GMainLoop> m_loop;
};
static GstCaps* getGStreamerAudioCaps(int channels, float sampleRate)
@@ -112,11 +112,18 @@ static void onGStreamerDecodebinPadAddedCallback(GstElement* element, GstPad* pa
reader->plugDeinterleave(pad);
}
+gboolean enteredMainLoopCallback(gpointer userData)
+{
+ AudioFileReader* reader = reinterpret_cast<AudioFileReader*>(userData);
+ reader->decodeAudioForBusCreation();
+ return FALSE;
+}
+
AudioFileReader::AudioFileReader(const char* filePath)
: m_data(0)
, m_dataSize(0)
, m_filePath(filePath)
- , m_eos(false)
+ , m_channelSize(0)
{
}
@@ -124,7 +131,7 @@ AudioFileReader::AudioFileReader(const void* data, size_t dataSize)
: m_data(data)
, m_dataSize(dataSize)
, m_filePath(0)
- , m_eos(false)
+ , m_channelSize(0)
{
}
@@ -148,13 +155,30 @@ GstFlowReturn AudioFileReader::handleBuffer(GstAppSink* sink)
return GST_FLOW_ERROR;
}
+ gint sampleRate = 0;
+ if (!gst_structure_get_int(structure, "rate", &sampleRate) || !sampleRate) {
+ gst_caps_unref(caps);
+ gst_buffer_unref(buffer);
+ return GST_FLOW_ERROR;
+ }
+
+ gint width = 0;
+ if (!gst_structure_get_int(structure, "width", &width) || !width) {
+ gst_caps_unref(caps);
+ gst_buffer_unref(buffer);
+ return GST_FLOW_ERROR;
+ }
+
+ GstClockTime duration = (static_cast<guint64>(GST_BUFFER_SIZE(buffer)) * 8 * GST_SECOND) / (sampleRate * channels * width);
+ int frames = GST_CLOCK_TIME_TO_FRAMES(duration, sampleRate);
+
// Check the first audio channel. The buffer is supposed to store
// data of a single channel anyway.
GstAudioChannelPosition* positions = gst_audio_get_channel_positions(structure);
switch (positions[0]) {
case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT:
gst_buffer_list_iterator_add(m_frontLeftBuffersIterator, buffer);
- m_channelSize += GST_BUFFER_OFFSET_END(buffer) - GST_BUFFER_OFFSET(buffer);
+ m_channelSize += frames;
break;
case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT:
gst_buffer_list_iterator_add(m_frontRightBuffersIterator, buffer);
@@ -176,7 +200,7 @@ gboolean AudioFileReader::handleMessage(GstMessage* message)
switch (GST_MESSAGE_TYPE(message)) {
case GST_MESSAGE_EOS:
- m_eos = true;
+ g_main_loop_quit(m_loop.get());
break;
case GST_MESSAGE_WARNING:
gst_message_parse_warning(message, &error.outPtr(), &debug.outPtr());
@@ -241,17 +265,17 @@ void AudioFileReader::plugDeinterleave(GstPad* pad)
GstElement* audioConvert = gst_element_factory_make("audioconvert", 0);
GstElement* audioResample = gst_element_factory_make("audioresample", 0);
GstElement* capsFilter = gst_element_factory_make("capsfilter", 0);
- GstElement* deInterleave = gst_element_factory_make("deinterleave", "deinterleave");
+ m_deInterleave = gst_element_factory_make("deinterleave", "deinterleave");
- g_object_set(deInterleave, "keep-positions", TRUE, NULL);
- m_deinterleavePadAddedSignalHandlerId = g_signal_connect(deInterleave, "pad-added", G_CALLBACK(onGStreamerDeinterleavePadAddedCallback), this);
- m_deinterleaveNoMorePadSignalHandlerId = g_signal_connect(deInterleave, "no-more-pads", G_CALLBACK(onGStreamerDeinterleaveReadyCallback), this);
+ g_object_set(m_deInterleave.get(), "keep-positions", TRUE, NULL);
+ g_signal_connect(m_deInterleave.get(), "pad-added", G_CALLBACK(onGStreamerDeinterleavePadAddedCallback), this);
+ g_signal_connect(m_deInterleave.get(), "no-more-pads", G_CALLBACK(onGStreamerDeinterleaveReadyCallback), this);
GstCaps* caps = getGStreamerAudioCaps(2, m_sampleRate);
g_object_set(capsFilter, "caps", caps, NULL);
gst_caps_unref(caps);
- gst_bin_add_many(GST_BIN(m_pipeline), audioConvert, audioResample, capsFilter, deInterleave, NULL);
+ gst_bin_add_many(GST_BIN(m_pipeline), audioConvert, audioResample, capsFilter, m_deInterleave.get(), NULL);
GstPad* sinkPad = gst_element_get_static_pad(audioConvert, "sink");
gst_pad_link(pad, sinkPad);
@@ -259,41 +283,23 @@ void AudioFileReader::plugDeinterleave(GstPad* pad)
gst_element_link_pads_full(audioConvert, "src", audioResample, "sink", GST_PAD_LINK_CHECK_NOTHING);
gst_element_link_pads_full(audioResample, "src", capsFilter, "sink", GST_PAD_LINK_CHECK_NOTHING);
- gst_element_link_pads_full(capsFilter, "src", deInterleave, "sink", GST_PAD_LINK_CHECK_NOTHING);
+ gst_element_link_pads_full(capsFilter, "src", m_deInterleave.get(), "sink", GST_PAD_LINK_CHECK_NOTHING);
gst_element_sync_state_with_parent(audioConvert);
gst_element_sync_state_with_parent(audioResample);
gst_element_sync_state_with_parent(capsFilter);
- gst_element_sync_state_with_parent(deInterleave);
+ gst_element_sync_state_with_parent(m_deInterleave.get());
}
-
-PassOwnPtr<AudioBus> AudioFileReader::createBus(float sampleRate, bool mixToMono)
+void AudioFileReader::decodeAudioForBusCreation()
{
- m_sampleRate = sampleRate;
-
- static bool gstInitialized = false;
- if (!gstInitialized)
- gstInitialized = gst_init_check(0, 0, 0);
-
- if (!gstInitialized)
- return nullptr;
-
- m_frontLeftBuffers = gst_buffer_list_new();
- m_frontLeftBuffersIterator = gst_buffer_list_iterate(m_frontLeftBuffers);
- gst_buffer_list_iterator_add_group(m_frontLeftBuffersIterator);
-
- m_frontRightBuffers = gst_buffer_list_new();
- m_frontRightBuffersIterator = gst_buffer_list_iterate(m_frontRightBuffers);
- gst_buffer_list_iterator_add_group(m_frontRightBuffersIterator);
-
// Build the pipeline (giostreamsrc | filesrc) ! decodebin2
// A deinterleave element is added once a src pad becomes available in decodebin.
m_pipeline = gst_pipeline_new(0);
- GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(m_pipeline));
- gst_bus_add_signal_watch(bus);
- gulong busSignalHandlerId = g_signal_connect(bus, "message", G_CALLBACK(messageCallback), this);
+ GRefPtr<GstBus> bus = gst_pipeline_get_bus(GST_PIPELINE(m_pipeline));
+ gst_bus_add_signal_watch(bus.get());
+ g_signal_connect(bus.get(), "message", G_CALLBACK(messageCallback), this);
GstElement* source;
if (m_data) {
@@ -306,30 +312,44 @@ PassOwnPtr<AudioBus> AudioFileReader::createBus(float sampleRate, bool mixToMono
g_object_set(source, "location", m_filePath, NULL);
}
- GstElement* decodebin = gst_element_factory_make("decodebin2", "decodebin");
- gulong decodebinPadAddedSignalHandlerId = g_signal_connect(decodebin, "pad-added", G_CALLBACK(onGStreamerDecodebinPadAddedCallback), this);
+ m_decodebin = gst_element_factory_make("decodebin2", "decodebin");
+ g_signal_connect(m_decodebin.get(), "pad-added", G_CALLBACK(onGStreamerDecodebinPadAddedCallback), this);
- gst_bin_add_many(GST_BIN(m_pipeline), source, decodebin, NULL);
- gst_element_link_pads_full(source, "src", decodebin, "sink", GST_PAD_LINK_CHECK_NOTHING);
-
- m_eos = false;
- m_channelSize = 0;
+ gst_bin_add_many(GST_BIN(m_pipeline), source, m_decodebin.get(), NULL);
+ gst_element_link_pads_full(source, "src", m_decodebin.get(), "sink", GST_PAD_LINK_CHECK_NOTHING);
gst_element_set_state(m_pipeline, GST_STATE_PAUSED);
- while (!m_eos)
- g_main_context_iteration(0, FALSE);
+}
- g_signal_handler_disconnect(bus, busSignalHandlerId);
- gst_object_unref(bus);
+PassOwnPtr<AudioBus> AudioFileReader::createBus(float sampleRate, bool mixToMono)
+{
+ m_sampleRate = sampleRate;
- g_signal_handler_disconnect(decodebin, decodebinPadAddedSignalHandlerId);
+ m_frontLeftBuffers = gst_buffer_list_new();
+ m_frontLeftBuffersIterator = gst_buffer_list_iterate(m_frontLeftBuffers);
+ gst_buffer_list_iterator_add_group(m_frontLeftBuffersIterator);
- if (GstElement* deinterleave = gst_bin_get_by_name(GST_BIN(m_pipeline), "deinterleave")) {
- if (g_signal_handler_is_connected(deinterleave, m_deinterleavePadAddedSignalHandlerId))
- g_signal_handler_disconnect(deinterleave, m_deinterleavePadAddedSignalHandlerId);
- if (g_signal_handler_is_connected(deinterleave, m_deinterleaveNoMorePadSignalHandlerId))
- g_signal_handler_disconnect(deinterleave, m_deinterleaveNoMorePadSignalHandlerId);
- gst_object_unref(deinterleave);
- }
+ m_frontRightBuffers = gst_buffer_list_new();
+ m_frontRightBuffersIterator = gst_buffer_list_iterate(m_frontRightBuffers);
+ gst_buffer_list_iterator_add_group(m_frontRightBuffersIterator);
+
+ GRefPtr<GMainContext> context = g_main_context_new();
+ g_main_context_push_thread_default(context.get());
+ m_loop = adoptGRef(g_main_loop_new(context.get(), FALSE));
+
+ // Start the pipeline processing just after the loop is started.
+ GSource* timeoutSource = g_timeout_source_new(0);
+ g_source_attach(timeoutSource, context.get());
+ g_source_set_callback(timeoutSource, reinterpret_cast<GSourceFunc>(enteredMainLoopCallback), this, 0);
+
+ g_main_loop_run(m_loop.get());
+ g_main_context_pop_thread_default(context.get());
+
+ GRefPtr<GstBus> bus = gst_pipeline_get_bus(GST_PIPELINE(m_pipeline));
+ g_signal_handlers_disconnect_by_func(bus.get(), reinterpret_cast<gpointer>(messageCallback), this);
+
+ g_signal_handlers_disconnect_by_func(m_decodebin.get(), reinterpret_cast<gpointer>(onGStreamerDecodebinPadAddedCallback), this);
+ g_signal_handlers_disconnect_by_func(m_deInterleave.get(), reinterpret_cast<gpointer>(onGStreamerDeinterleavePadAddedCallback), this);
+ g_signal_handlers_disconnect_by_func(m_deInterleave.get(), reinterpret_cast<gpointer>(onGStreamerDeinterleaveReadyCallback), this);
unsigned channels = mixToMono ? 1 : 2;
OwnPtr<AudioBus> audioBus = adoptPtr(new AudioBus(channels, m_channelSize, true));
@@ -347,6 +367,8 @@ PassOwnPtr<AudioBus> AudioFileReader::createBus(float sampleRate, bool mixToMono
gst_element_set_state(m_pipeline, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(m_pipeline));
+ m_decodebin.clear();
+ m_deInterleave.clear();
return audioBus.release();
}
diff --git a/Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp b/Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp
index 2228f41d0..00e4491e6 100644
--- a/Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp
+++ b/Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp
@@ -24,7 +24,7 @@
#include "AudioBus.h"
#include "AudioSourceProvider.h"
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#include "GRefPtrGStreamer.h"
#include <gst/audio/multichannel.h>
#include <gst/pbutils/pbutils.h>
diff --git a/Source/WebCore/platform/audio/gtk/AudioBusGtk.cpp b/Source/WebCore/platform/audio/gtk/AudioBusGtk.cpp
index f9d635b44..310f39c1c 100644
--- a/Source/WebCore/platform/audio/gtk/AudioBusGtk.cpp
+++ b/Source/WebCore/platform/audio/gtk/AudioBusGtk.cpp
@@ -23,9 +23,10 @@
#include "AudioBus.h"
#include "AudioFileReader.h"
-#include "CString.h"
#include "FileSystem.h"
-#include "GOwnPtr.h"
+
+#include <wtf/gobject/GOwnPtr.h>
+#include <wtf/text/CString.h>
#include <gio/gio.h>
#include <glib.h>
diff --git a/Source/WebCore/platform/blackberry/AsyncFileSystemBlackBerry.cpp b/Source/WebCore/platform/blackberry/AsyncFileSystemBlackBerry.cpp
new file mode 100644
index 000000000..dc26bb5dc
--- /dev/null
+++ b/Source/WebCore/platform/blackberry/AsyncFileSystemBlackBerry.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#if ENABLE(FILE_SYSTEM)
+#include "AsyncFileSystemBlackBerry.h"
+
+#include "AsyncFileSystemCallbacks.h"
+#include "ExceptionCode.h"
+#include "NotImplemented.h"
+
+#include <wtf/UnusedParam.h>
+
+namespace WebCore {
+
+bool AsyncFileSystem::isAvailable()
+{
+ notImplemented();
+ return false;
+}
+
+bool AsyncFileSystem::isValidType(FileSystemType type)
+{
+ UNUSED_PARAM(type);
+
+ notImplemented();
+ return false;
+}
+
+PassOwnPtr<AsyncFileSystem> AsyncFileSystem::create(FileSystemType type)
+{
+ return adoptPtr(new AsyncFileSystemBlackBerry(type));
+}
+
+void AsyncFileSystem::openFileSystem(const String& basePath, const String& storageIdentifier, FileSystemType type, bool, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
+{
+ UNUSED_PARAM(basePath);
+ UNUSED_PARAM(storageIdentifier);
+ UNUSED_PARAM(type);
+ UNUSED_PARAM(callbacks);
+
+ notImplemented();
+ callbacks->didFail(NOT_SUPPORTED_ERR);
+}
+
+bool AsyncFileSystem::crackFileSystemURL(const KURL& url, FileSystemType& type, String& filePath)
+{
+ UNUSED_PARAM(url);
+ UNUSED_PARAM(type);
+ UNUSED_PARAM(filePath);
+
+ notImplemented();
+ return false;
+}
+
+AsyncFileSystemBlackBerry::AsyncFileSystemBlackBerry(FileSystemType type)
+ : AsyncFileSystem(type)
+{
+ notImplemented();
+}
+
+AsyncFileSystemBlackBerry::~AsyncFileSystemBlackBerry()
+{
+ notImplemented();
+}
+
+KURL AsyncFileSystemBlackBerry::toURL(const String& originString, const String& fullPath) const
+{
+ UNUSED_PARAM(originString);
+ UNUSED_PARAM(fullPath);
+
+ notImplemented();
+ return KURL();
+}
+
+void AsyncFileSystemBlackBerry::move(const String& sourcePath, const String& destinationPath, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
+{
+ UNUSED_PARAM(sourcePath);
+ UNUSED_PARAM(destinationPath);
+ UNUSED_PARAM(callbacks);
+
+ notImplemented();
+}
+
+void AsyncFileSystemBlackBerry::copy(const String& sourcePath, const String& destinationPath, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
+{
+ UNUSED_PARAM(sourcePath);
+ UNUSED_PARAM(destinationPath);
+ UNUSED_PARAM(callbacks);
+
+ notImplemented();
+}
+
+void AsyncFileSystemBlackBerry::remove(const String& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
+{
+ UNUSED_PARAM(path);
+ UNUSED_PARAM(callbacks);
+
+ notImplemented();
+}
+
+void AsyncFileSystemBlackBerry::removeRecursively(const String& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
+{
+ UNUSED_PARAM(path);
+ UNUSED_PARAM(callbacks);
+
+ notImplemented();
+}
+
+void AsyncFileSystemBlackBerry::readMetadata(const String& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
+{
+ UNUSED_PARAM(path);
+ UNUSED_PARAM(callbacks);
+
+ notImplemented();
+}
+
+void AsyncFileSystemBlackBerry::createFile(const String& path, bool exclusive, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
+{
+ UNUSED_PARAM(path);
+ UNUSED_PARAM(exclusive);
+ UNUSED_PARAM(callbacks);
+
+ notImplemented();
+}
+
+void AsyncFileSystemBlackBerry::createDirectory(const String& path, bool exclusive, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
+{
+ UNUSED_PARAM(path);
+ UNUSED_PARAM(exclusive);
+ UNUSED_PARAM(callbacks);
+
+ notImplemented();
+}
+
+void AsyncFileSystemBlackBerry::fileExists(const String& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
+{
+ UNUSED_PARAM(path);
+ UNUSED_PARAM(callbacks);
+
+ notImplemented();
+}
+
+void AsyncFileSystemBlackBerry::directoryExists(const String& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
+{
+ UNUSED_PARAM(path);
+ UNUSED_PARAM(callbacks);
+
+ notImplemented();
+}
+
+void AsyncFileSystemBlackBerry::readDirectory(const String& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
+{
+ UNUSED_PARAM(path);
+ UNUSED_PARAM(callbacks);
+
+ notImplemented();
+}
+
+
+void AsyncFileSystemBlackBerry::createWriter(AsyncFileWriterClient* client, const String& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
+{
+ UNUSED_PARAM(client);
+ UNUSED_PARAM(path);
+ UNUSED_PARAM(callbacks);
+
+ notImplemented();
+}
+
+void AsyncFileSystemBlackBerry::createSnapshotFileAndReadMetadata(const String& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
+{
+ UNUSED_PARAM(path);
+ UNUSED_PARAM(callbacks);
+
+ notImplemented();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(FILE_SYSTEM)
diff --git a/Source/WebCore/platform/blackberry/AsyncFileSystemBlackBerry.h b/Source/WebCore/platform/blackberry/AsyncFileSystemBlackBerry.h
new file mode 100644
index 000000000..38b17c70f
--- /dev/null
+++ b/Source/WebCore/platform/blackberry/AsyncFileSystemBlackBerry.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef AsyncFileSystemBlackBerry_h
+#define AsyncFileSystemBlackBerry_h
+
+#if ENABLE(FILE_SYSTEM)
+#include "AsyncFileSystem.h"
+
+namespace WebCore {
+
+class AsyncFileSystemBlackBerry : public AsyncFileSystem {
+public:
+ AsyncFileSystemBlackBerry(FileSystemType);
+ virtual ~AsyncFileSystemBlackBerry();
+ virtual KURL toURL(const String& originString, const String& fullPath) const;
+ virtual void move(const String& sourcePath, const String& destinationPath, PassOwnPtr<AsyncFileSystemCallbacks>);
+ virtual void copy(const String& sourcePath, const String& destinationPath, PassOwnPtr<AsyncFileSystemCallbacks>);
+ virtual void remove(const String& path, PassOwnPtr<AsyncFileSystemCallbacks>);
+ virtual void removeRecursively(const String& path, PassOwnPtr<AsyncFileSystemCallbacks>);
+ virtual void readMetadata(const String& path, PassOwnPtr<AsyncFileSystemCallbacks>);
+ virtual void createFile(const String& path, bool exclusive, PassOwnPtr<AsyncFileSystemCallbacks>);
+ virtual void createDirectory(const String& path, bool exclusive, PassOwnPtr<AsyncFileSystemCallbacks>);
+ virtual void fileExists(const String& path, PassOwnPtr<AsyncFileSystemCallbacks>);
+ virtual void directoryExists(const String& path, PassOwnPtr<AsyncFileSystemCallbacks>);
+ virtual void readDirectory(const String& path, PassOwnPtr<AsyncFileSystemCallbacks>);
+ virtual void createWriter(AsyncFileWriterClient*, const String& path, PassOwnPtr<AsyncFileSystemCallbacks>);
+ virtual void createSnapshotFileAndReadMetadata(const String& path, PassOwnPtr<AsyncFileSystemCallbacks>);
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(FILE_SYSTEM)
+
+#endif // AsyncFileSystemBlackBerry_h
diff --git a/Source/WebCore/platform/blackberry/ClipboardBlackBerry.cpp b/Source/WebCore/platform/blackberry/ClipboardBlackBerry.cpp
index 66b7710d1..2a31be862 100644
--- a/Source/WebCore/platform/blackberry/ClipboardBlackBerry.cpp
+++ b/Source/WebCore/platform/blackberry/ClipboardBlackBerry.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010, 2011 Research In Motion Limited. All rights reserved.
+ * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -26,11 +26,6 @@
namespace WebCore {
-PassRefPtr<ClipboardBlackBerry> ClipboardBlackBerry::create(ClipboardAccessPolicy policy, ClipboardType clipboardType)
-{
- return adoptRef(new ClipboardBlackBerry(policy, clipboardType));
-}
-
PassRefPtr<Clipboard> Clipboard::create(ClipboardAccessPolicy policy, DragData*, Frame*)
{
return ClipboardBlackBerry::create(policy, DragAndDrop);
@@ -47,21 +42,33 @@ ClipboardBlackBerry::~ClipboardBlackBerry()
void ClipboardBlackBerry::clearData(const String& type)
{
+ if (policy() != ClipboardWritable)
+ return;
+
BlackBerry::Platform::Clipboard::clearClipboardByType(type.utf8().data());
}
void ClipboardBlackBerry::clearAllData()
{
+ if (policy() != ClipboardWritable)
+ return;
+
BlackBerry::Platform::Clipboard::clearClipboard();
}
String ClipboardBlackBerry::getData(const String& type) const
{
+ if (policy() != ClipboardReadable)
+ return String();
+
return String::fromUTF8(BlackBerry::Platform::Clipboard::readClipboardByType(type.utf8().data()).c_str());
}
bool ClipboardBlackBerry::setData(const String& type, const String& text)
{
+ if (policy() != ClipboardWritable)
+ return false;
+
if (type == "text/plain")
BlackBerry::Platform::Clipboard::writePlainText(text.utf8().data());
else if (type == "text/html")
@@ -73,6 +80,9 @@ bool ClipboardBlackBerry::setData(const String& type, const String& text)
HashSet<String> ClipboardBlackBerry::types() const
{
+ if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable)
+ return HashSet<String>();
+
// We use hardcoded list here since there seems to be no API to get the list.
HashSet<String> ret;
ret.add("text/plain");
diff --git a/Source/WebCore/platform/blackberry/ClipboardBlackBerry.h b/Source/WebCore/platform/blackberry/ClipboardBlackBerry.h
index fed1627e0..17effce0f 100644
--- a/Source/WebCore/platform/blackberry/ClipboardBlackBerry.h
+++ b/Source/WebCore/platform/blackberry/ClipboardBlackBerry.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Research In Motion Limited. All rights reserved.
+ * Copyright (C) 2010, 2012 Research In Motion Limited. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -27,7 +27,10 @@ namespace WebCore {
class ClipboardBlackBerry : public Clipboard, public CachedResourceClient {
WTF_MAKE_FAST_ALLOCATED;
public:
- static PassRefPtr<ClipboardBlackBerry> create(ClipboardAccessPolicy, ClipboardType = CopyAndPaste);
+ static PassRefPtr<ClipboardBlackBerry> create(ClipboardAccessPolicy policy, ClipboardType clipboardType = CopyAndPaste)
+ {
+ return adoptRef(new ClipboardBlackBerry(policy, clipboardType));
+ }
virtual ~ClipboardBlackBerry();
void clearData(const String& type);
diff --git a/Source/WebCore/platform/blackberry/CookieDatabaseBackingStore/CookieDatabaseBackingStore.cpp b/Source/WebCore/platform/blackberry/CookieDatabaseBackingStore/CookieDatabaseBackingStore.cpp
index 7319cb045..a76c04184 100644
--- a/Source/WebCore/platform/blackberry/CookieDatabaseBackingStore/CookieDatabaseBackingStore.cpp
+++ b/Source/WebCore/platform/blackberry/CookieDatabaseBackingStore/CookieDatabaseBackingStore.cpp
@@ -71,7 +71,7 @@ CookieDatabaseBackingStore::CookieDatabaseBackingStore()
CookieDatabaseBackingStore::~CookieDatabaseBackingStore()
{
- delete m_dbTimerClient;
+ deleteGuardedObject(m_dbTimerClient);
m_dbTimerClient = 0;
// FIXME: This object will never be deleted due to the set up of CookieManager (it's a singleton)
CookieLog("CookieBackingStore - Destructing");
@@ -238,7 +238,7 @@ void CookieDatabaseBackingStore::invokeOpen(const String& cookieJar)
String updateQuery("UPDATE ");
updateQuery += m_tableName;
// The where statement is chosen to match CookieMap key.
- updateQuery += " SET name = ?1, value = ?2, host = ?3, path = ?4, expiry = ?5, lastAccessed = ?6, isSecure = ?7, isHttpOnly = ?8, creationTime = ?9, protocol = ?10 where protocol = ?10 and name = ?1 and host = ?3 and path = ?4;";
+ updateQuery += " SET name = ?1, value = ?2, host = ?3, path = ?4, expiry = ?5, lastAccessed = ?6, isSecure = ?7, isHttpOnly = ?8, creationTime = ?9, protocol = ?10 where name = ?1 and host = ?3 and path = ?4;";
m_updateStatement = new SQLiteStatement(m_db, updateQuery);
if (m_updateStatement->prepare()) {
@@ -416,7 +416,7 @@ void CookieDatabaseBackingStore::sendChangesToDatabase(int nextInterval)
CookieLog("CookieBackingStore - Starting one shot send to database");
m_dbTimer.start(nextInterval);
} else {
-#if !NDEBUG
+#ifndef NDEBUG
CookieLog("CookieBackingStore - Timer already running, skipping this request");
#endif
}
diff --git a/Source/WebCore/platform/blackberry/CookieManager.cpp b/Source/WebCore/platform/blackberry/CookieManager.cpp
index 34b9ff05f..dd72e6794 100644
--- a/Source/WebCore/platform/blackberry/CookieManager.cpp
+++ b/Source/WebCore/platform/blackberry/CookieManager.cpp
@@ -33,7 +33,6 @@
#include "CookieDatabaseBackingStore.h"
#include "CookieParser.h"
-#include "CurrentTime.h"
#include "FileSystem.h"
#include "Logging.h"
#include "WebSettings.h"
@@ -42,6 +41,7 @@
#include <BlackBerryPlatformMessageClient.h>
#include <BlackBerryPlatformNavigatorHandler.h>
#include <stdlib.h>
+#include <wtf/CurrentTime.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>
#include <wtf/text/WTFString.h>
@@ -167,10 +167,12 @@ bool CookieManager::shouldRejectForSecurityReason(const ParsedCookie* cookie, co
if (!cookie->domain().length())
return true;
- if (!cookie->hasDefaultDomain()) {
+ // If an explicitly specified value does not start with a dot, the user agent supplies. (RFC 2965 3.2.2)
+ // Domain: Defaults to the effective request-host. There is no dot at the beginning of request-host. (RFC 2965 3.3.1)
+ if (cookie->domain()[0] == '.') {
// Check if the domain contains an embedded dot.
- int dotPosition = cookie->domain().find(".", 1);
- if (dotPosition == -1 || static_cast<unsigned int>(dotPosition) == cookie->domain().length()) {
+ size_t dotPosition = cookie->domain().find(".", 1);
+ if (dotPosition == notFound || dotPosition == cookie->domain().length()) {
LOG_ERROR("Cookie %s is rejected because its domain does not contain an embedded dot.\n", cookie->toString().utf8().data());
return true;
}
@@ -182,7 +184,7 @@ bool CookieManager::shouldRejectForSecurityReason(const ParsedCookie* cookie, co
// a.b.com matches b.com, a.b.com matches .B.com and a.b.com matches .A.b.Com
// and so on.
String hostDomainName = url.host();
- hostDomainName = hostDomainName.startsWith(".") ? hostDomainName : "." + hostDomainName;
+ hostDomainName = hostDomainName.startsWith('.') ? hostDomainName : "." + hostDomainName;
if (!hostDomainName.endsWith(cookie->domain(), false)) {
LOG_ERROR("Cookie %s is rejected because its domain does not domain match the URL %s\n", cookie->toString().utf8().data(), url.string().utf8().data());
return true;
@@ -575,7 +577,7 @@ void CookieManager::initiateCookieLimitCleanUp()
CookieLog("CookieManager - Starting a timer for cookie cleanup");
m_limitTimer.startOneShot(s_delayToStartCookieCleanup);
} else {
-#if !NDEBUG
+#ifndef NDEBUG
CookieLog("CookieManager - Cookie cleanup timer already running");
#endif
}
diff --git a/Source/WebCore/platform/blackberry/CookieManager.h b/Source/WebCore/platform/blackberry/CookieManager.h
index 4dcd3f477..904551eba 100644
--- a/Source/WebCore/platform/blackberry/CookieManager.h
+++ b/Source/WebCore/platform/blackberry/CookieManager.h
@@ -115,7 +115,7 @@ private:
friend CookieManager& cookieManager();
CookieManager();
- ~CookieManager();
+ virtual ~CookieManager();
void checkAndTreatCookie(ParsedCookie*, BackingStoreRemovalPolicy);
diff --git a/Source/WebCore/platform/blackberry/CookieMap.cpp b/Source/WebCore/platform/blackberry/CookieMap.cpp
index b217b2e48..e354e8bed 100644
--- a/Source/WebCore/platform/blackberry/CookieMap.cpp
+++ b/Source/WebCore/platform/blackberry/CookieMap.cpp
@@ -80,7 +80,7 @@ ParsedCookie* CookieMap::addOrReplaceCookie(ParsedCookie* cookie)
ParsedCookie* CookieMap::removeCookieAtIndex(int position, const ParsedCookie* cookie)
{
- ASSERT(0 <= position && position < m_cookieVector.size());
+ ASSERT(0 <= position && static_cast<unsigned>(position) < m_cookieVector.size());
ParsedCookie* prevCookie = m_cookieVector[position];
m_cookieVector.remove(position);
diff --git a/Source/WebCore/platform/blackberry/CookieMap.h b/Source/WebCore/platform/blackberry/CookieMap.h
index 86968576d..1f2841545 100644
--- a/Source/WebCore/platform/blackberry/CookieMap.h
+++ b/Source/WebCore/platform/blackberry/CookieMap.h
@@ -27,9 +27,9 @@
#ifndef CookieMap_h
#define CookieMap_h
-#include "HashMap.h"
#include "PlatformString.h"
-#include "Vector.h"
+#include <wtf/HashMap.h>
+#include <wtf/Vector.h>
#include <wtf/text/StringHash.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/blackberry/CookieParser.cpp b/Source/WebCore/platform/blackberry/CookieParser.cpp
index e1eb44aa4..b2177c665 100644
--- a/Source/WebCore/platform/blackberry/CookieParser.cpp
+++ b/Source/WebCore/platform/blackberry/CookieParser.cpp
@@ -27,9 +27,9 @@
#include "config.h"
#include "CookieParser.h"
-#include "CurrentTime.h"
#include "Logging.h"
#include "ParsedCookie.h"
+#include <wtf/CurrentTime.h>
#include <wtf/text/CString.h>
namespace WebCore {
@@ -324,7 +324,7 @@ ParsedCookie* CookieParser::parseOneCookie(const String& cookie, unsigned start,
// If no domain was provided, set it to the host
if (!res->domain())
- res->setDefaultDomain(m_defaultCookieURL);
+ res->setDomain(m_defaultCookieURL.host());
// According to the Cookie Specificaiton (RFC6265, section 4.1.2.4 and 5.2.4, http://tools.ietf.org/html/rfc6265),
// If no path was provided or the first character of the path value is not '/', set it to the host's path
diff --git a/Source/WebCore/platform/blackberry/CookieParser.h b/Source/WebCore/platform/blackberry/CookieParser.h
index 92e48d36e..66455420d 100644
--- a/Source/WebCore/platform/blackberry/CookieParser.h
+++ b/Source/WebCore/platform/blackberry/CookieParser.h
@@ -28,7 +28,7 @@
#define CookieParser_h
#include "KURL.h"
-#include "Vector.h"
+#include <wtf/Vector.h>
namespace WTF {
class String;
diff --git a/Source/WebCore/platform/blackberry/DragImageBlackBerry.cpp b/Source/WebCore/platform/blackberry/DragImageBlackBerry.cpp
index 0bd29db87..404e8f2b4 100644
--- a/Source/WebCore/platform/blackberry/DragImageBlackBerry.cpp
+++ b/Source/WebCore/platform/blackberry/DragImageBlackBerry.cpp
@@ -26,7 +26,7 @@
namespace WebCore {
-void* createDragImageFromImage(Image*)
+void* createDragImageFromImage(Image*, RespectImageOrientationEnum)
{
notImplemented();
return 0;
diff --git a/Source/WebCore/platform/blackberry/EventLoopBlackBerry.cpp b/Source/WebCore/platform/blackberry/EventLoopBlackBerry.cpp
index 1bffb44b5..18528bcc7 100644
--- a/Source/WebCore/platform/blackberry/EventLoopBlackBerry.cpp
+++ b/Source/WebCore/platform/blackberry/EventLoopBlackBerry.cpp
@@ -24,10 +24,6 @@
namespace WebCore {
-void EventLoop::platformInit()
-{
-}
-
void EventLoop::cycle()
{
ASSERT(BlackBerry::Platform::webKitThreadMessageClient());
diff --git a/Source/WebCore/platform/blackberry/FileSystemBlackBerry.cpp b/Source/WebCore/platform/blackberry/FileSystemBlackBerry.cpp
index e4e562e59..4765c01e0 100644
--- a/Source/WebCore/platform/blackberry/FileSystemBlackBerry.cpp
+++ b/Source/WebCore/platform/blackberry/FileSystemBlackBerry.cpp
@@ -39,9 +39,4 @@ bool unloadModule(PlatformModule)
return false;
}
-String openTemporaryFile(const String&, PlatformFileHandle&)
-{
- return "";
-}
-
} // namespace WebCore
diff --git a/Source/WebCore/platform/blackberry/LocalizedStringsBlackBerry.cpp b/Source/WebCore/platform/blackberry/LocalizedStringsBlackBerry.cpp
index 7f5bef726..2207f3aa2 100644
--- a/Source/WebCore/platform/blackberry/LocalizedStringsBlackBerry.cpp
+++ b/Source/WebCore/platform/blackberry/LocalizedStringsBlackBerry.cpp
@@ -398,6 +398,12 @@ String AXDefinitionListTermText()
return String();
}
+String AXFooterRoleDescriptionText()
+{
+ notImplemented();
+ return String();
+}
+
String AXLinkActionVerb()
{
notImplemented();
diff --git a/Source/WebCore/platform/blackberry/MIMETypeRegistryBlackBerry.cpp b/Source/WebCore/platform/blackberry/MIMETypeRegistryBlackBerry.cpp
index 71e48d01a..ba8e16bf8 100644
--- a/Source/WebCore/platform/blackberry/MIMETypeRegistryBlackBerry.cpp
+++ b/Source/WebCore/platform/blackberry/MIMETypeRegistryBlackBerry.cpp
@@ -66,8 +66,6 @@ static const ExtensionMap extensionMap[] = {
{ "xpm", "image/x-xpm" },
{ "xsl", "text/xsl" },
{ "xhtml", "application/xhtml+xml" },
- { "wml", "text/vnd.wap.wml" },
- { "wmlc", "application/vnd.wap.wmlc" },
{ "m4a", "audio/m4a" },
{ "midi", "audio/midi" },
{ "mid", "audio/mid" },
diff --git a/Source/WebCore/platform/blackberry/PageClientBlackBerry.h b/Source/WebCore/platform/blackberry/PageClientBlackBerry.h
index 3abd89a97..8f959dcdd 100644
--- a/Source/WebCore/platform/blackberry/PageClientBlackBerry.h
+++ b/Source/WebCore/platform/blackberry/PageClientBlackBerry.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2010, 2011 Research In Motion Limited. All rights reserved.
+ * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -19,6 +19,7 @@
#ifndef PageClientBlackBerry_h
#define PageClientBlackBerry_h
+#include "Credential.h"
#include "Cursor.h"
#include "WebPageClient.h"
@@ -34,12 +35,20 @@ namespace BlackBerry {
namespace WebCore {
class IntRect;
class IntSize;
+ class KURL;
class PluginView;
+ class ProtectionSpace;
}
class PageClientBlackBerry {
public:
- virtual void setCursor(WebCore::PlatformCursorHandle) = 0;
+ enum SaveCredentialType {
+ SaveCredentialNeverForThisSite = 0,
+ SaveCredentialNotNow,
+ SaveCredentialYes
+ };
+
+ virtual void setCursor(WebCore::PlatformCursor) = 0;
virtual BlackBerry::Platform::NetworkStreamFactory* networkStreamFactory() = 0;
virtual BlackBerry::Platform::Graphics::Window* platformWindow() const = 0;
virtual void setPreventsScreenDimming(bool) = 0;
@@ -60,6 +69,9 @@ public:
virtual WebCore::IntSize viewportSize() const = 0;
virtual int showAlertDialog(BlackBerry::WebKit::WebPageClient::AlertType) = 0;
virtual bool isActive() const = 0;
+ virtual bool isVisible() const = 0;
+ virtual WebCore::Credential authenticationChallenge(const WebCore::KURL&, const WebCore::ProtectionSpace&) = 0;
+ virtual SaveCredentialType notifyShouldSaveCredential(bool) = 0;
};
#endif // PageClientBlackBerry_h
diff --git a/Source/WebCore/platform/blackberry/ParsedCookie.cpp b/Source/WebCore/platform/blackberry/ParsedCookie.cpp
index 1ff7fe600..5e310e90a 100644
--- a/Source/WebCore/platform/blackberry/ParsedCookie.cpp
+++ b/Source/WebCore/platform/blackberry/ParsedCookie.cpp
@@ -28,7 +28,7 @@
#include "ParsedCookie.h"
#include "CookieManager.h"
-#include "CurrentTime.h"
+#include <wtf/CurrentTime.h>
#include "KURL.h"
#include "Logging.h"
#include <curl/curl.h>
@@ -38,11 +38,9 @@
namespace WebCore {
ParsedCookie::ParsedCookie(double currentTime)
- : m_expiry(0)
+ : m_expiry(-1)
, m_creationTime(currentTime)
, m_lastAccessed(currentTime)
- , m_isMaxAgeSet(false)
- , m_hasDefaultDomain(false)
, m_isSecure(false)
, m_isHttpOnly(false)
, m_isSession(true)
@@ -59,8 +57,6 @@ ParsedCookie::ParsedCookie(const String& name, const String& value, const String
, m_expiry(expiry)
, m_creationTime(creationTime)
, m_lastAccessed(lastAccessed)
- , m_isMaxAgeSet(false)
- , m_hasDefaultDomain(false)
, m_isSecure(isSecure)
, m_isHttpOnly(isHttpOnly)
, m_isSession(false)
@@ -77,8 +73,6 @@ ParsedCookie::ParsedCookie(const ParsedCookie* cookie)
, m_expiry(cookie->m_expiry)
, m_creationTime(cookie->m_creationTime)
, m_lastAccessed(cookie->m_lastAccessed)
- , m_isMaxAgeSet(cookie->m_isMaxAgeSet)
- , m_hasDefaultDomain(cookie->m_hasDefaultDomain)
, m_isSecure(cookie->m_isSecure)
, m_isHttpOnly(cookie->m_isHttpOnly)
, m_isSession(cookie->m_isSession)
@@ -94,7 +88,7 @@ void ParsedCookie::setExpiry(const String& expiry)
{
// If a cookie has both the Max-Age and the Expires attribute,
// the Max-Age attribute has precedence and controls the expiration date of the cookie.
- if (m_isMaxAgeSet || expiry.isEmpty())
+ if (m_expiry != -1 || expiry.isEmpty())
return;
m_isSession = false;
@@ -126,7 +120,6 @@ void ParsedCookie::setMaxAge(const String& maxAge)
return;
}
m_expiry = value;
- m_isMaxAgeSet = true;
m_isSession = false;
// If maxAge value is not positive, let expiry-time be the earliest representable time.
@@ -136,12 +129,6 @@ void ParsedCookie::setMaxAge(const String& maxAge)
m_expiry = 0;
}
-void ParsedCookie::setDefaultDomain(const KURL& requestURL)
-{
- setDomain(requestURL.host());
- m_hasDefaultDomain = true;
-}
-
bool ParsedCookie::hasExpired() const
{
// Session cookies do not expire, they will just not be saved to the backing store.
@@ -185,6 +172,8 @@ String ParsedCookie::toNameValuePair() const
void ParsedCookie::appendWebCoreCookie(Vector<Cookie>& cookieVector) const
{
cookieVector.append(Cookie(String(m_name), String(m_value), String(m_domain),
- String(m_path), m_expiry, m_isHttpOnly, m_isSecure, m_isSession));
+ // We multiply m_expiry by 1000 to convert from seconds to milliseconds.
+ // This value is passed to Web Inspector and used in the JavaScript Date constructor.
+ String(m_path), (m_expiry * 1000), m_isHttpOnly, m_isSecure, m_isSession));
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/blackberry/ParsedCookie.h b/Source/WebCore/platform/blackberry/ParsedCookie.h
index ca343d13f..db29e7afa 100644
--- a/Source/WebCore/platform/blackberry/ParsedCookie.h
+++ b/Source/WebCore/platform/blackberry/ParsedCookie.h
@@ -68,10 +68,6 @@ public:
const String& protocol() const { return m_protocol; }
void setProtocol(const String& protocol) { m_protocol = protocol; }
- // This is a special method used to set the domain to the request's url.
- void setDefaultDomain(const KURL&);
- bool hasDefaultDomain() const { return m_hasDefaultDomain; }
-
double expiry() const { return m_expiry; }
void setExpiry(const String&);
void forceExpire() { m_isForceExpired = true; }
@@ -110,8 +106,6 @@ private:
// This is used for the LRU replacement policy.
double m_lastAccessed;
- bool m_isMaxAgeSet;
- bool m_hasDefaultDomain;
bool m_isSecure;
bool m_isHttpOnly;
bool m_isSession;
diff --git a/Source/WebCore/platform/blackberry/PlatformKeyboardEventBlackBerry.cpp b/Source/WebCore/platform/blackberry/PlatformKeyboardEventBlackBerry.cpp
index 607126b7d..8ffd8e36b 100644
--- a/Source/WebCore/platform/blackberry/PlatformKeyboardEventBlackBerry.cpp
+++ b/Source/WebCore/platform/blackberry/PlatformKeyboardEventBlackBerry.cpp
@@ -24,6 +24,7 @@
#include <BlackBerryPlatformKeyboardEvent.h>
#include <BlackBerryPlatformLog.h>
+#include <wtf/CurrentTime.h>
#include <wtf/text/CString.h>
namespace WebCore {
@@ -436,11 +437,11 @@ static inline PlatformKeyboardEvent::Type toWebCorePlatformKeyboardEventType(con
}
}
-PlatformKeyboardEvent::PlatformKeyboardEvent(BlackBerry::Platform::KeyboardEvent event)
- : PlatformEvent(toWebCorePlatformKeyboardEventType(event.type()), event.shiftActive() || (event.character() == KEYCODE_BACK_TAB), event.ctrlActive(), event.altActive(), false)
+PlatformKeyboardEvent::PlatformKeyboardEvent(const BlackBerry::Platform::KeyboardEvent& event)
+ : PlatformEvent(toWebCorePlatformKeyboardEventType(event.type()), event.shiftActive() || (event.character() == KEYCODE_BACK_TAB), event.ctrlActive(), event.altActive(), false, currentTime())
, m_keyIdentifier(keyIdentifierForBlackBerryCharacter(event.character()))
- , m_autoRepeat(false)
, m_windowsVirtualKeyCode(windowsKeyCodeForBlackBerryCharacter(event.character()))
+ , m_autoRepeat(false)
, m_isKeypad(false)
, m_unmodifiedCharacter(event.character())
{
@@ -448,6 +449,9 @@ PlatformKeyboardEvent::PlatformKeyboardEvent(BlackBerry::Platform::KeyboardEvent
m_text = String(&character, 1);
m_unmodifiedText = m_text;
+ if (event.character() == KEYCODE_BACK_TAB)
+ m_modifiers |= ShiftKey; // BackTab should be treated as Shift + Tab.
+
BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "Keyboard event received text=%lc, keyIdentifier=%s, windowsVirtualKeyCode=%d", event.character(), m_keyIdentifier.latin1().data(), m_windowsVirtualKeyCode);
}
diff --git a/Source/WebCore/platform/blackberry/PlatformMouseEventBlackBerry.cpp b/Source/WebCore/platform/blackberry/PlatformMouseEventBlackBerry.cpp
index f5645920e..a8d960995 100644
--- a/Source/WebCore/platform/blackberry/PlatformMouseEventBlackBerry.cpp
+++ b/Source/WebCore/platform/blackberry/PlatformMouseEventBlackBerry.cpp
@@ -23,25 +23,15 @@
namespace WebCore {
-PlatformMouseEvent::PlatformMouseEvent(const IntPoint& eventPos, const IntPoint& globalPos, const MouseEventType type, int clickCount, MouseButton button, MouseInputMethod method)
- : m_position(eventPos)
- , m_globalPosition(globalPos)
+PlatformMouseEvent::PlatformMouseEvent(const IntPoint& eventPosition, const IntPoint& globalPosition, const PlatformEvent::Type type, int clickCount, MouseButton button, MouseInputMethod method)
+ : PlatformEvent(type, false, false, false, false, currentTime())
+ , m_position(eventPosition)
+ , m_globalPosition(globalPosition)
, m_button(button)
- , m_eventType(type)
, m_clickCount(clickCount)
- , m_shiftKey(false)
- , m_ctrlKey(false)
- , m_altKey(false)
- , m_metaKey(false)
- , m_timestamp(currentTime())
, m_inputMethod(method)
{
- ASSERT(type != MouseEventScroll);
-}
-
-void PlatformMouseEvent::setClickCount(int count)
-{
- m_clickCount = count;
+ ASSERT(type != MouseScroll);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/blackberry/PlatformTouchEventBlackBerry.cpp b/Source/WebCore/platform/blackberry/PlatformTouchEventBlackBerry.cpp
index 5f5dbbcb2..d15b65873 100644
--- a/Source/WebCore/platform/blackberry/PlatformTouchEventBlackBerry.cpp
+++ b/Source/WebCore/platform/blackberry/PlatformTouchEventBlackBerry.cpp
@@ -24,6 +24,8 @@
#include <BlackBerryPlatformTouchEvent.h>
+#include <wtf/CurrentTime.h>
+
#if ENABLE(TOUCH_EVENTS)
namespace WebCore {
@@ -48,13 +50,12 @@ static PlatformEvent::Type touchEventType(BlackBerry::Platform::TouchEvent* even
}
PlatformTouchEvent::PlatformTouchEvent(BlackBerry::Platform::TouchEvent* event)
- : PlatformEvent(touchEventType(event), false, event->m_altKey, event->m_shiftKey, false)
+ : PlatformEvent(touchEventType(event), false, event->m_altKey, event->m_shiftKey, false, currentTime())
, m_rotation(0)
, m_scale(1)
, m_doubleTap(false)
, m_touchHold(false)
{
-
for (unsigned i = 0; i < event->m_points.size(); ++i)
m_touchPoints.append(PlatformTouchPoint(event->m_points[i]));
diff --git a/Source/WebCore/platform/blackberry/RenderThemeBlackBerry.cpp b/Source/WebCore/platform/blackberry/RenderThemeBlackBerry.cpp
index c57813f1c..70c4389b9 100644
--- a/Source/WebCore/platform/blackberry/RenderThemeBlackBerry.cpp
+++ b/Source/WebCore/platform/blackberry/RenderThemeBlackBerry.cpp
@@ -23,6 +23,7 @@
#include "CSSValueKeywords.h"
#include "Frame.h"
+#include "HTMLMediaElement.h"
#include "MediaControlElements.h"
#include "MediaPlayerPrivateBlackBerry.h"
#include "PaintInfo.h"
@@ -214,13 +215,13 @@ void RenderThemeBlackBerry::setButtonStyle(RenderStyle* style) const
style->setPaddingBottom(vertPadding);
}
-void RenderThemeBlackBerry::adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeBlackBerry::adjustButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
setButtonStyle(style);
style->setCursor(CURSOR_WEBKIT_GRAB);
}
-void RenderThemeBlackBerry::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeBlackBerry::adjustTextAreaStyle(StyleResolver*, RenderStyle* style, Element*) const
{
setButtonStyle(style);
}
@@ -230,7 +231,7 @@ bool RenderThemeBlackBerry::paintTextArea(RenderObject* object, const PaintInfo&
return paintTextFieldOrTextAreaOrSearchField(object, info, rect);
}
-void RenderThemeBlackBerry::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeBlackBerry::adjustTextFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
{
setButtonStyle(style);
}
@@ -256,7 +257,8 @@ bool RenderThemeBlackBerry::paintTextFieldOrTextAreaOrSearchField(RenderObject*
if (object->style()->appearance() == SearchFieldPart) {
// We force the fill color to White so as to match the background color of the search cancel button graphic.
context->setFillColor(Color::white, ColorSpaceDeviceRGB);
- context->drawPath(textFieldRoundedRectangle);
+ context->fillPath(textFieldRoundedRectangle);
+ context->strokePath(textFieldRoundedRectangle);
} else
context->strokePath(textFieldRoundedRectangle);
context->restore();
@@ -268,12 +270,12 @@ bool RenderThemeBlackBerry::paintTextField(RenderObject* object, const PaintInfo
return paintTextFieldOrTextAreaOrSearchField(object, info, rect);
}
-void RenderThemeBlackBerry::adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeBlackBerry::adjustSearchFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
{
setButtonStyle(style);
}
-void RenderThemeBlackBerry::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeBlackBerry::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
static const float defaultControlFontPixelSize = 13;
static const float defaultCancelButtonSize = 9;
@@ -318,7 +320,7 @@ bool RenderThemeBlackBerry::paintSearchFieldCancelButton(RenderObject* object, c
return false;
}
-void RenderThemeBlackBerry::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeBlackBerry::adjustMenuListButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// These seem to be reasonable padding values from observation.
const int paddingLeft = 8;
@@ -405,7 +407,8 @@ bool RenderThemeBlackBerry::paintButton(RenderObject* object, const PaintInfo& i
FloatSize smallCorner(smallRadius, smallRadius);
Path path;
path.addRoundedRect(rect, smallCorner);
- info.context->drawPath(path);
+ info.context->fillPath(path);
+ info.context->strokePath(path);
if (isChecked(object)) {
Path checkPath;
@@ -417,7 +420,8 @@ bool RenderThemeBlackBerry::paintButton(RenderObject* object, const PaintInfo& i
info.context->setLineCap(RoundCap);
info.context->setStrokeColor(blackPen, ColorSpaceDeviceRGB);
info.context->setStrokeThickness(rect2.width() / checkboxStrokeThickness);
- info.context->drawPath(checkPath);
+ info.context->fillPath(checkPath);
+ info.context->strokePath(checkPath);
}
break;
}
@@ -436,13 +440,15 @@ bool RenderThemeBlackBerry::paintButton(RenderObject* object, const PaintInfo& i
FloatSize largeCorner(largeRadius, largeRadius);
Path path;
path.addRoundedRect(rect, largeCorner);
- info.context->drawPath(path);
+ info.context->fillPath(path);
+ info.context->strokePath(path);
break;
}
case SquareButtonPart: {
Path path;
path.addRect(rect);
- info.context->drawPath(path);
+ info.context->fillPath(path);
+ info.context->strokePath(path);
break;
}
default:
@@ -454,12 +460,12 @@ bool RenderThemeBlackBerry::paintButton(RenderObject* object, const PaintInfo& i
return false;
}
-void RenderThemeBlackBerry::adjustMenuListStyle(CSSStyleSelector* css, RenderStyle* style, Element* element) const
+void RenderThemeBlackBerry::adjustMenuListStyle(StyleResolver* css, RenderStyle* style, Element* element) const
{
adjustMenuListButtonStyle(css, style, element);
}
-void RenderThemeBlackBerry::adjustCheckboxStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeBlackBerry::adjustCheckboxStyle(StyleResolver*, RenderStyle* style, Element*) const
{
setCheckboxSize(style);
style->setBoxShadow(nullptr);
@@ -469,7 +475,7 @@ void RenderThemeBlackBerry::adjustCheckboxStyle(CSSStyleSelector*, RenderStyle*
style->setCursor(CURSOR_WEBKIT_GRAB);
}
-void RenderThemeBlackBerry::adjustRadioStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeBlackBerry::adjustRadioStyle(StyleResolver*, RenderStyle* style, Element*) const
{
setRadioSize(style);
style->setBoxShadow(nullptr);
diff --git a/Source/WebCore/platform/blackberry/RenderThemeBlackBerry.h b/Source/WebCore/platform/blackberry/RenderThemeBlackBerry.h
index 62cb739d8..c975687bf 100644
--- a/Source/WebCore/platform/blackberry/RenderThemeBlackBerry.h
+++ b/Source/WebCore/platform/blackberry/RenderThemeBlackBerry.h
@@ -45,7 +45,7 @@ public:
virtual void setRadioSize(RenderStyle*) const;
virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&);
void calculateButtonSize(RenderStyle*) const;
- virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual void adjustSliderThumbSize(RenderStyle*) const;
virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
@@ -58,21 +58,21 @@ public:
virtual Color platformFocusRingColor() const;
virtual bool supportsFocusRing(const RenderStyle* style) const { return style->hasAppearance(); }
- virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
- virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual void adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
- virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
- virtual void adjustCheckboxStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
- virtual void adjustRadioStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual void adjustCheckboxStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual void adjustRadioStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&);
diff --git a/Source/WebCore/platform/blackberry/SSLKeyGeneratorBlackBerry.cpp b/Source/WebCore/platform/blackberry/SSLKeyGeneratorBlackBerry.cpp
index 539835ca9..3dc4d91c4 100644
--- a/Source/WebCore/platform/blackberry/SSLKeyGeneratorBlackBerry.cpp
+++ b/Source/WebCore/platform/blackberry/SSLKeyGeneratorBlackBerry.cpp
@@ -22,7 +22,7 @@
#include "KURL.h"
#include "NotImplemented.h"
#include "PlatformString.h"
-#include "Vector.h"
+#include <wtf/Vector.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/blackberry/ScrollAnimatorBlackBerry.cpp b/Source/WebCore/platform/blackberry/ScrollAnimatorBlackBerry.cpp
new file mode 100644
index 000000000..62f090837
--- /dev/null
+++ b/Source/WebCore/platform/blackberry/ScrollAnimatorBlackBerry.cpp
@@ -0,0 +1,50 @@
+
+#include "config.h"
+
+#if ENABLE(SMOOTH_SCROLLING)
+
+#include "ScrollAnimatorBlackBerry.h"
+
+#include "ScrollableArea.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+PassOwnPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea)
+{
+ if (scrollableArea && scrollableArea->scrollAnimatorEnabled())
+ return adoptPtr(new ScrollAnimatorBlackBerry(scrollableArea));
+ return adoptPtr(new ScrollAnimator(scrollableArea));
+}
+
+ScrollAnimatorBlackBerry::ScrollAnimatorBlackBerry(ScrollableArea* scrollableArea)
+ : ScrollAnimatorNone(scrollableArea)
+ , m_disableConstrainsScrollingToContentEdgeWhileAnimating(false)
+ , m_originalConstransScrollingToContentEdge(true)
+{
+}
+
+void ScrollAnimatorBlackBerry::animationWillStart()
+{
+ if (m_disableConstrainsScrollingToContentEdgeWhileAnimating) {
+ m_originalConstransScrollingToContentEdge = scrollableArea()->constrainsScrollingToContentEdge();
+ scrollableArea()->setConstrainsScrollingToContentEdge(false);
+ }
+}
+
+void ScrollAnimatorBlackBerry::animationDidFinish()
+{
+ if (m_disableConstrainsScrollingToContentEdgeWhileAnimating) {
+ scrollableArea()->setConstrainsScrollingToContentEdge(m_originalConstransScrollingToContentEdge);
+ m_disableConstrainsScrollingToContentEdgeWhileAnimating = false;
+ }
+}
+
+void ScrollAnimatorBlackBerry::setDisableConstrainsScrollingToContentEdgeWhileAnimating(bool value)
+{
+ m_disableConstrainsScrollingToContentEdgeWhileAnimating = value;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SMOOTH_SCROLLING)
diff --git a/Source/WebCore/platform/blackberry/ScrollAnimatorBlackBerry.h b/Source/WebCore/platform/blackberry/ScrollAnimatorBlackBerry.h
new file mode 100644
index 000000000..a7cf65c66
--- /dev/null
+++ b/Source/WebCore/platform/blackberry/ScrollAnimatorBlackBerry.h
@@ -0,0 +1,33 @@
+
+#ifndef ScrollAnimatorBlackBerry_h
+#define ScrollAnimatorBlackberry_h
+
+#if ENABLE(SMOOTH_SCROLLING)
+
+#include "ScrollAnimator.h"
+#include "ScrollAnimatorNone.h"
+
+namespace WebCore {
+
+class ScrollableArea;
+
+class ScrollAnimatorBlackBerry : public ScrollAnimatorNone {
+public:
+ ScrollAnimatorBlackBerry(ScrollableArea*);
+
+ void setDisableConstrainsScrollingToContentEdgeWhileAnimating(bool);
+
+protected:
+ virtual void animationWillStart();
+ virtual void animationDidFinish();
+
+private:
+ bool m_disableConstrainsScrollingToContentEdgeWhileAnimating;
+ bool m_originalConstransScrollingToContentEdge;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SMOOTH_SCROLLING)
+
+#endif // ScrollAnimatorBlackBerry_h
diff --git a/Source/WebCore/platform/blackberry/SharedTimerBlackBerry.cpp b/Source/WebCore/platform/blackberry/SharedTimerBlackBerry.cpp
index 175c4ed7c..fa1537fd4 100644
--- a/Source/WebCore/platform/blackberry/SharedTimerBlackBerry.cpp
+++ b/Source/WebCore/platform/blackberry/SharedTimerBlackBerry.cpp
@@ -19,7 +19,7 @@
#include "config.h"
#include "SharedTimer.h"
-#include "CurrentTime.h"
+#include <wtf/CurrentTime.h>
#include <BlackBerryPlatformTimer.h>
diff --git a/Source/WebCore/platform/cf/BinaryPropertyList.cpp b/Source/WebCore/platform/cf/BinaryPropertyList.cpp
index 4b823b12b..4bc7c2e60 100644
--- a/Source/WebCore/platform/cf/BinaryPropertyList.cpp
+++ b/Source/WebCore/platform/cf/BinaryPropertyList.cpp
@@ -204,7 +204,7 @@ void BinaryPropertyListPlan::writeInteger(int integer)
return;
m_integerZeroObjectReference = m_currentObjectReference;
} else {
- if (!m_integers.add(integer, m_currentObjectReference).second)
+ if (!m_integers.add(integer, m_currentObjectReference).isNewEntry)
return;
}
++m_currentObjectReference;
@@ -214,7 +214,7 @@ void BinaryPropertyListPlan::writeInteger(int integer)
void BinaryPropertyListPlan::writeString(const String& string)
{
++m_currentAggregateSize;
- if (!m_strings.add(string, m_currentObjectReference).second)
+ if (!m_strings.add(string, m_currentObjectReference).isNewEntry)
return;
++m_currentObjectReference;
writeStringObject(string);
@@ -224,12 +224,12 @@ void BinaryPropertyListPlan::writeIntegerArray(const int* integers, size_t size)
{
size_t savedAggregateSize = ++m_currentAggregateSize;
ASSERT(size);
- pair<IntegerArrayMap::iterator, bool> addResult = m_integerArrays.add(IntegerArray(integers, size), 0);
- if (!addResult.second)
+ IntegerArrayMap::AddResult addResult = m_integerArrays.add(IntegerArray(integers, size), 0);
+ if (!addResult.isNewEntry)
return;
for (size_t i = 0; i < size; ++i)
writeInteger(integers[i]);
- addResult.first->second = m_currentObjectReference++;
+ addResult.iterator->second = m_currentObjectReference++;
writeArrayObject(size);
m_currentAggregateSize = savedAggregateSize;
}
diff --git a/Source/WebCore/platform/cf/FileSystemCF.cpp b/Source/WebCore/platform/cf/FileSystemCF.cpp
index a4b422bc2..261882026 100644
--- a/Source/WebCore/platform/cf/FileSystemCF.cpp
+++ b/Source/WebCore/platform/cf/FileSystemCF.cpp
@@ -26,12 +26,12 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#import "config.h"
-#import "FileSystem.h"
+#include "config.h"
+#include "FileSystem.h"
-#import "PlatformString.h"
-#import <wtf/RetainPtr.h>
-#import <wtf/text/CString.h>
+#include "PlatformString.h"
+#include <wtf/RetainPtr.h>
+#include <wtf/text/CString.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/chromium/ChromiumDataObject.cpp b/Source/WebCore/platform/chromium/ChromiumDataObject.cpp
index c1b7aa281..e656f44b2 100644
--- a/Source/WebCore/platform/chromium/ChromiumDataObject.cpp
+++ b/Source/WebCore/platform/chromium/ChromiumDataObject.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
+ * Copyright (c) 2008, 2009, 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -33,248 +33,219 @@
#include "ClipboardMimeTypes.h"
#include "ClipboardUtilitiesChromium.h"
-#include "DataTransferItemListChromium.h"
-#include "Pasteboard.h"
+#include "DataTransferItem.h"
+#include "ExceptionCode.h"
+#include "ExceptionCodePlaceholder.h"
#include "PlatformSupport.h"
namespace WebCore {
-// Per RFC 2483, the line separator for "text/..." MIME types is CR-LF.
-static char const* const textMIMETypeLineSeparator = "\r\n";
-
-void ChromiumDataObject::clearData(const String& type)
+PassRefPtr<ChromiumDataObject> ChromiumDataObject::createFromPasteboard()
{
- if (type == mimeTypeTextPlain) {
- m_plainText = "";
- return;
- }
-
- if (type == mimeTypeURL || type == mimeTypeTextURIList) {
- m_uriList = "";
- m_url = KURL();
- m_urlTitle = "";
- return;
- }
-
- if (type == mimeTypeTextHTML) {
- m_textHtml = "";
- m_htmlBaseUrl = KURL();
- return;
- }
-
- if (type == mimeTypeDownloadURL) {
- m_downloadMetadata = "";
- return;
- }
+ RefPtr<ChromiumDataObject> dataObject = create();
+ uint64_t sequenceNumber = PlatformSupport::clipboardSequenceNumber(currentPasteboardBuffer());
+ bool ignored;
+ HashSet<String> types = PlatformSupport::clipboardReadAvailableTypes(currentPasteboardBuffer(), &ignored);
+ for (HashSet<String>::const_iterator it = types.begin(); it != types.end(); ++it)
+ dataObject->m_itemList.append(ChromiumDataObjectItem::createFromPasteboard(*it, sequenceNumber));
+ return dataObject.release();
}
-void ChromiumDataObject::clearAll()
+PassRefPtr<ChromiumDataObject> ChromiumDataObject::create()
{
- clearAllExceptFiles();
- m_filenames.clear();
+ return adoptRef(new ChromiumDataObject());
}
-void ChromiumDataObject::clearAllExceptFiles()
+PassRefPtr<ChromiumDataObject> ChromiumDataObject::copy() const
{
- m_urlTitle = "";
- m_url = KURL();
- m_uriList = "";
- m_downloadMetadata = "";
- m_fileExtension = "";
- m_plainText = "";
- m_textHtml = "";
- m_htmlBaseUrl = KURL();
- m_fileContentFilename = "";
- if (m_fileContent)
- m_fileContent->clear();
+ return adoptRef(new ChromiumDataObject(*this));
}
-bool ChromiumDataObject::hasData() const
+size_t ChromiumDataObject::length() const
{
- return !m_url.isEmpty()
- || !m_uriList.isEmpty()
- || !m_downloadMetadata.isEmpty()
- || !m_fileExtension.isEmpty()
- || !m_filenames.isEmpty()
- || !m_plainText.isEmpty()
- || !m_textHtml.isEmpty()
- || m_fileContent;
+ return m_itemList.size();
}
-HashSet<String> ChromiumDataObject::types() const
+PassRefPtr<ChromiumDataObjectItem> ChromiumDataObject::item(unsigned long index)
{
- if (m_storageMode == Pasteboard) {
- bool ignoredContainsFilenames;
- return PlatformSupport::clipboardReadAvailableTypes(currentPasteboardBuffer(),
- &ignoredContainsFilenames);
- }
-
- HashSet<String> results;
-
- if (!m_plainText.isEmpty()) {
- results.add(mimeTypeText);
- results.add(mimeTypeTextPlain);
- }
+ if (index >= length())
+ return 0;
+ return m_itemList[index];
+}
- if (!m_uriList.isEmpty())
- results.add(mimeTypeTextURIList);
+void ChromiumDataObject::deleteItem(unsigned long index)
+{
+ if (index >= length())
+ return;
+ m_itemList.remove(index);
+}
- if (!m_textHtml.isEmpty())
- results.add(mimeTypeTextHTML);
+void ChromiumDataObject::clearAll()
+{
+ m_itemList.clear();
+}
- if (!m_downloadMetadata.isEmpty())
- results.add(mimeTypeDownloadURL);
+void ChromiumDataObject::add(const String& data, const String& type, ExceptionCode& ec)
+{
+ if (!internalAddStringItem(ChromiumDataObjectItem::createFromString(type, data)))
+ ec = NOT_SUPPORTED_ERR;
+}
- for (HashMap<String, String>::const_iterator::Keys it = m_customData.begin().keys();
- it != m_customData.end().keys(); ++it) {
- results.add(*it);
- }
+void ChromiumDataObject::add(PassRefPtr<File> file, ScriptExecutionContext* context)
+{
+ if (!file)
+ return;
- return results;
+ m_itemList.append(ChromiumDataObjectItem::createFromFile(file));
}
-String ChromiumDataObject::getData(const String& type, bool& success) const
+void ChromiumDataObject::clearData(const String& type)
{
- if (type == mimeTypeTextPlain) {
- if (m_storageMode == Pasteboard) {
- String text = PlatformSupport::clipboardReadPlainText(currentPasteboardBuffer());
- success = !text.isEmpty();
- return text;
+ for (size_t i = 0; i < m_itemList.size(); ++i) {
+ if (m_itemList[i]->kind() == DataTransferItem::kindString && m_itemList[i]->type() == type) {
+ // Per the spec, type must be unique among all items of kind 'string'.
+ m_itemList.remove(i);
+ return;
}
- success = !m_plainText.isEmpty();
- return m_plainText;
- }
-
- if (type == mimeTypeURL) {
- success = !m_uriList.isEmpty();
- return m_url.string();
- }
-
- if (type == mimeTypeTextURIList) {
- success = !m_uriList.isEmpty();
- return m_uriList;
}
+}
- if (type == mimeTypeTextHTML) {
- if (m_storageMode == Pasteboard) {
- String htmlText;
- KURL sourceURL;
- unsigned ignored;
- PlatformSupport::clipboardReadHTML(currentPasteboardBuffer(), &htmlText, &sourceURL, &ignored, &ignored);
- success = !htmlText.isEmpty();
- return htmlText;
+void ChromiumDataObject::clearAllExceptFiles()
+{
+ for (size_t i = 0; i < m_itemList.size(); ) {
+ if (m_itemList[i]->kind() != DataTransferItem::kindFile) {
+ m_itemList.remove(i);
+ continue;
}
- success = !m_textHtml.isEmpty();
- return m_textHtml;
- }
-
- if (type == mimeTypeDownloadURL) {
- success = !m_downloadMetadata.isEmpty();
- return m_downloadMetadata;
+ ++i;
}
+}
- if (m_storageMode == Pasteboard) {
- String data = PlatformSupport::clipboardReadCustomData(currentPasteboardBuffer(), type);
- success = !data.isEmpty();
- return data;
- }
+HashSet<String> ChromiumDataObject::types() const
+{
+ HashSet<String> results;
+ bool containsFiles = false;
+ for (size_t i = 0; i < m_itemList.size(); ++i) {
+ if (m_itemList[i]->kind() == DataTransferItem::kindString)
+ results.add(m_itemList[i]->type());
+ else if (m_itemList[i]->kind() == DataTransferItem::kindFile)
+ containsFiles = true;
+ else
+ ASSERT_NOT_REACHED();
+ }
+ if (containsFiles)
+ results.add(mimeTypeFiles);
+ return results;
+}
- HashMap<String, String>::const_iterator it = m_customData.find(type);
- if (it != m_customData.end()) {
- success = true;
- return it->second;
+String ChromiumDataObject::getData(const String& type) const
+{
+ for (size_t i = 0; i < m_itemList.size(); ++i) {
+ if (m_itemList[i]->kind() == DataTransferItem::kindString && m_itemList[i]->type() == type)
+ return m_itemList[i]->internalGetAsString();
}
-
- success = false;
return String();
}
bool ChromiumDataObject::setData(const String& type, const String& data)
{
- if (type == mimeTypeTextPlain) {
- m_plainText = data;
- return true;
- }
-
- if (type == mimeTypeURL || type == mimeTypeTextURIList) {
- m_url = KURL();
- Vector<String> uriList;
- // Line separator is \r\n per RFC 2483 - however, for compatibility
- // reasons we also allow just \n here.
- data.split('\n', uriList);
- // Process the input and copy the first valid URL into the url member.
- // In case no URLs can be found, subsequent calls to getData("URL")
- // will get an empty string. This is in line with the HTML5 spec (see
- // "The DragEvent and DataTransfer interfaces").
- for (size_t i = 0; i < uriList.size(); ++i) {
- String& line = uriList[i];
- line = line.stripWhiteSpace();
- if (line.isEmpty()) {
- continue;
- }
- if (line[0] == '#')
- continue;
- KURL url = KURL(ParsedURLString, line);
- if (url.isValid()) {
- m_url = url;
- break;
- }
- }
- m_uriList = data;
- return true;
- }
+ clearData(type);
+ add(data, type, ASSERT_NO_EXCEPTION);
+ return true;
+}
- if (type == mimeTypeTextHTML) {
- m_textHtml = data;
- m_htmlBaseUrl = KURL();
- return true;
- }
+void ChromiumDataObject::urlAndTitle(String& url, String* title) const
+{
+ RefPtr<ChromiumDataObjectItem> item = findStringItem(mimeTypeTextURIList);
+ if (!item)
+ return;
+ url = convertURIListToURL(item->internalGetAsString());
+ if (title)
+ *title = item->title();
+}
- if (type == mimeTypeDownloadURL) {
- m_downloadMetadata = data;
- return true;
- }
+void ChromiumDataObject::setURLAndTitle(const String& url, const String& title)
+{
+ clearData(mimeTypeTextURIList);
+ internalAddStringItem(ChromiumDataObjectItem::createFromURL(url, title));
+}
- if (type.isEmpty())
- return false;
+void ChromiumDataObject::htmlAndBaseURL(String& html, KURL& baseURL) const
+{
+ RefPtr<ChromiumDataObjectItem> item = findStringItem(mimeTypeTextHTML);
+ if (!item)
+ return;
+ html = item->internalGetAsString();
+ baseURL = item->baseURL();
+}
- m_customData.set(type, data);
- return true;
+void ChromiumDataObject::setHTMLAndBaseURL(const String& html, const KURL& baseURL)
+{
+ clearData(mimeTypeTextHTML);
+ internalAddStringItem(ChromiumDataObjectItem::createFromHTML(html, baseURL));
}
bool ChromiumDataObject::containsFilenames() const
{
- bool containsFilenames;
- if (m_storageMode == Pasteboard) {
- HashSet<String> ignoredResults =
- PlatformSupport::clipboardReadAvailableTypes(currentPasteboardBuffer(),
- &containsFilenames);
- } else
- containsFilenames = !m_filenames.isEmpty();
- return containsFilenames;
+ for (size_t i = 0; i < m_itemList.size(); ++i)
+ if (m_itemList[i]->isFilename())
+ return true;
+ return false;
+}
+
+Vector<String> ChromiumDataObject::filenames() const
+{
+ Vector<String> results;
+ for (size_t i = 0; i < m_itemList.size(); ++i)
+ if (m_itemList[i]->isFilename())
+ results.append(static_cast<File*>(m_itemList[i]->getAsFile().get())->path());
+ return results;
+}
+
+void ChromiumDataObject::addFilename(const String& filename, const String& displayName)
+{
+ internalAddFileItem(ChromiumDataObjectItem::createFromFile(File::createWithName(filename, displayName)));
+}
+
+void ChromiumDataObject::addSharedBuffer(const String& name, PassRefPtr<SharedBuffer> buffer)
+{
+ internalAddFileItem(ChromiumDataObjectItem::createFromSharedBuffer(name, buffer));
}
-ChromiumDataObject::ChromiumDataObject(StorageMode storageMode)
- : m_storageMode(storageMode)
+ChromiumDataObject::ChromiumDataObject()
{
}
ChromiumDataObject::ChromiumDataObject(const ChromiumDataObject& other)
: RefCounted<ChromiumDataObject>()
- , m_storageMode(other.m_storageMode)
- , m_urlTitle(other.m_urlTitle)
- , m_downloadMetadata(other.m_downloadMetadata)
- , m_fileExtension(other.m_fileExtension)
- , m_filenames(other.m_filenames)
- , m_plainText(other.m_plainText)
- , m_textHtml(other.m_textHtml)
- , m_htmlBaseUrl(other.m_htmlBaseUrl)
- , m_fileContentFilename(other.m_fileContentFilename)
- , m_url(other.m_url)
- , m_uriList(other.m_uriList)
+ , m_itemList(other.m_itemList)
+{
+}
+
+PassRefPtr<ChromiumDataObjectItem> ChromiumDataObject::findStringItem(const String& type) const
+{
+ for (size_t i = 0; i < m_itemList.size(); ++i) {
+ if (m_itemList[i]->kind() == DataTransferItem::kindString && m_itemList[i]->type() == type)
+ return m_itemList[i];
+ }
+ return 0;
+}
+
+bool ChromiumDataObject::internalAddStringItem(PassRefPtr<ChromiumDataObjectItem> item)
+{
+ ASSERT(item->kind() == DataTransferItem::kindString);
+ for (size_t i = 0; i < m_itemList.size(); ++i)
+ if (m_itemList[i]->kind() == DataTransferItem::kindString && m_itemList[i]->type() == item->type())
+ return false;
+
+ m_itemList.append(item);
+ return true;
+}
+
+void ChromiumDataObject::internalAddFileItem(PassRefPtr<ChromiumDataObjectItem> item)
{
- if (other.m_fileContent.get())
- m_fileContent = other.m_fileContent->copy();
+ ASSERT(item->kind() == DataTransferItem::kindFile);
+ m_itemList.append(item);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/ChromiumDataObject.h b/Source/WebCore/platform/chromium/ChromiumDataObject.h
index 7e675bf93..1a5d7898a 100644
--- a/Source/WebCore/platform/chromium/ChromiumDataObject.h
+++ b/Source/WebCore/platform/chromium/ChromiumDataObject.h
@@ -31,10 +31,9 @@
#ifndef ChromiumDataObject_h
#define ChromiumDataObject_h
-#include "KURL.h"
+#include "ChromiumDataObjectItem.h"
#include "PlatformString.h"
-#include "SharedBuffer.h"
-#include <wtf/HashMap.h>
+#include "Supplementable.h"
#include <wtf/HashSet.h>
#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
@@ -42,95 +41,60 @@
namespace WebCore {
+class KURL;
+class SharedBuffer;
+
+typedef int ExceptionCode;
+
// A data object for holding data that would be in a clipboard or moved
// during a drag-n-drop operation. This is the data that WebCore is aware
// of and is not specific to a platform.
-class ChromiumDataObject : public RefCounted<ChromiumDataObject> {
+class ChromiumDataObject : public RefCounted<ChromiumDataObject>, public Supplementable<ChromiumDataObject> {
public:
- enum StorageMode {
- Buffered,
- Pasteboard,
- };
-
- static PassRefPtr<ChromiumDataObject> createFromPasteboard()
- {
- return adoptRef(new ChromiumDataObject(Pasteboard));
- }
-
- static PassRefPtr<ChromiumDataObject> create()
- {
- return adoptRef(new ChromiumDataObject(Buffered));
- }
+ static PassRefPtr<ChromiumDataObject> createFromPasteboard();
+ static PassRefPtr<ChromiumDataObject> create();
- PassRefPtr<ChromiumDataObject> copy() const
- {
- return adoptRef(new ChromiumDataObject(*this));
- }
+ PassRefPtr<ChromiumDataObject> copy() const;
- StorageMode storageMode() const { return m_storageMode; }
+ // DataTransferItemList support.
+ size_t length() const;
+ PassRefPtr<ChromiumDataObjectItem> item(unsigned long index);
+ // FIXME: Implement V8DataTransferItemList::indexedPropertyDeleter to get this called.
+ void deleteItem(unsigned long index);
+ void clearAll();
+ void add(const String& data, const String& type, ExceptionCode&);
+ void add(PassRefPtr<File>, ScriptExecutionContext*);
+ // WebCore helpers.
void clearData(const String& type);
- void clearAll();
void clearAllExceptFiles();
- bool hasData() const;
-
HashSet<String> types() const;
- String getData(const String& type, bool& success) const;
+ String getData(const String& type) const;
bool setData(const String& type, const String& data);
- // Special handlers for URL/HTML metadata.
- String urlTitle() const { return m_urlTitle; }
- void setUrlTitle(const String& urlTitle) { m_urlTitle = urlTitle; }
- KURL htmlBaseUrl() const { return m_htmlBaseUrl; }
- void setHtmlBaseUrl(const KURL& url) { m_htmlBaseUrl = url; }
+ void urlAndTitle(String& url, String* title = 0) const;
+ void setURLAndTitle(const String& url, const String& title);
+ void htmlAndBaseURL(String& html, KURL& baseURL) const;
+ void setHTMLAndBaseURL(const String& html, const KURL& baseURL);
- // Used to handle files being dragged in and out.
+ // Used for dragging in files from the desktop.
bool containsFilenames() const;
- const Vector<String>& filenames() const { return m_filenames; }
- void setFilenames(const Vector<String>& filenames) { m_filenames = filenames; }
-
- // Used to handle files being dragged out.
- void addFilename(const String& filename) { m_filenames.append(filename); }
+ Vector<String> filenames() const;
+ void addFilename(const String& filename, const String& displayName);
// Used to handle files (images) being dragged out.
- String fileExtension() const { return m_fileExtension; }
- void setFileExtension(const String& fileExtension) { m_fileExtension = fileExtension; }
- String fileContentFilename() const { return m_fileContentFilename; }
- void setFileContentFilename(const String& fileContentFilename) { m_fileContentFilename = fileContentFilename; }
- PassRefPtr<SharedBuffer> fileContent() const { return m_fileContent; }
- void setFileContent(PassRefPtr<SharedBuffer> fileContent) { m_fileContent = fileContent; }
- const HashMap<String, String>& customData() const { return m_customData; }
- HashMap<String, String>& customData() { return m_customData; }
+ void addSharedBuffer(const String& name, PassRefPtr<SharedBuffer>);
private:
- explicit ChromiumDataObject(StorageMode);
+ ChromiumDataObject();
explicit ChromiumDataObject(const ChromiumDataObject&);
- StorageMode m_storageMode;
-
- String m_urlTitle;
-
- String m_downloadMetadata;
-
- String m_fileExtension;
- Vector<String> m_filenames;
-
- String m_plainText;
-
- String m_textHtml;
- KURL m_htmlBaseUrl;
-
- String m_fileContentFilename;
- RefPtr<SharedBuffer> m_fileContent;
-
- HashMap<String, String> m_customData;
+ PassRefPtr<ChromiumDataObjectItem> findStringItem(const String& type) const;
+ bool internalAddStringItem(PassRefPtr<ChromiumDataObjectItem>);
+ void internalAddFileItem(PassRefPtr<ChromiumDataObjectItem>);
- // These two are linked. Setting m_url will set m_uriList to the same
- // string value; setting m_uriList will cause its contents to be parsed
- // according to RFC 2483 and the first URL found will be set in m_url.
- KURL m_url;
- String m_uriList;
+ Vector<RefPtr<ChromiumDataObjectItem> > m_itemList;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/ChromiumDataObjectItem.cpp b/Source/WebCore/platform/chromium/ChromiumDataObjectItem.cpp
new file mode 100644
index 000000000..5db3603d4
--- /dev/null
+++ b/Source/WebCore/platform/chromium/ChromiumDataObjectItem.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ChromiumDataObjectItem.h"
+
+#if ENABLE(DATA_TRANSFER_ITEMS)
+
+#include "Blob.h"
+#include "Clipboard.h"
+#include "ClipboardChromium.h"
+#include "ClipboardMimeTypes.h"
+#include "ClipboardUtilitiesChromium.h"
+#include "DataTransferItem.h"
+#include "File.h"
+#include "PlatformSupport.h"
+#include "SharedBuffer.h"
+#include "StringCallback.h"
+
+namespace WebCore {
+
+PassRefPtr<ChromiumDataObjectItem> ChromiumDataObjectItem::createFromString(const String& type, const String& data)
+{
+ RefPtr<ChromiumDataObjectItem> item = adoptRef(new ChromiumDataObjectItem(DataTransferItem::kindString, type));
+ item->m_data = data;
+ return item.release();
+}
+
+PassRefPtr<ChromiumDataObjectItem> ChromiumDataObjectItem::createFromFile(PassRefPtr<File> file)
+{
+ RefPtr<ChromiumDataObjectItem> item = adoptRef(new ChromiumDataObjectItem(DataTransferItem::kindFile, file->type()));
+ item->m_file = file;
+ return item.release();
+}
+
+PassRefPtr<ChromiumDataObjectItem> ChromiumDataObjectItem::createFromURL(const String& url, const String& title)
+{
+ RefPtr<ChromiumDataObjectItem> item = adoptRef(new ChromiumDataObjectItem(DataTransferItem::kindString, mimeTypeTextURIList));
+ item->m_data = url;
+ item->m_title = title;
+ return item.release();
+}
+
+PassRefPtr<ChromiumDataObjectItem> ChromiumDataObjectItem::createFromHTML(const String& html, const KURL& baseURL)
+{
+ RefPtr<ChromiumDataObjectItem> item = adoptRef(new ChromiumDataObjectItem(DataTransferItem::kindString, mimeTypeTextHTML));
+ item->m_data = html;
+ item->m_baseURL = baseURL;
+ return item.release();
+}
+
+PassRefPtr<ChromiumDataObjectItem> ChromiumDataObjectItem::createFromSharedBuffer(const String& name, PassRefPtr<SharedBuffer> buffer)
+{
+ RefPtr<ChromiumDataObjectItem> item = adoptRef(new ChromiumDataObjectItem(DataTransferItem::kindFile, String()));
+ item->m_sharedBuffer = buffer;
+ item->m_title = name;
+ return item.release();
+}
+
+PassRefPtr<ChromiumDataObjectItem> ChromiumDataObjectItem::createFromPasteboard(const String& type, uint64_t sequenceNumber)
+{
+ if (type == mimeTypeImagePng)
+ return adoptRef(new ChromiumDataObjectItem(DataTransferItem::kindFile, type, sequenceNumber));
+ return adoptRef(new ChromiumDataObjectItem(DataTransferItem::kindString, type, sequenceNumber));
+}
+
+ChromiumDataObjectItem::ChromiumDataObjectItem(const String& kind, const String& type)
+ : m_source(InternalSource)
+ , m_kind(kind)
+ , m_type(type)
+ , m_sequenceNumber(0)
+{
+}
+
+ChromiumDataObjectItem::ChromiumDataObjectItem(const String& kind, const String& type, uint64_t sequenceNumber)
+ : m_source(PasteboardSource)
+ , m_kind(kind)
+ , m_type(type)
+ , m_sequenceNumber(sequenceNumber)
+{
+}
+
+void ChromiumDataObjectItem::getAsString(PassRefPtr<StringCallback> callback, ScriptExecutionContext* context) const
+{
+ if (!callback || kind() != DataTransferItem::kindString)
+ return;
+
+ callback->scheduleCallback(context, internalGetAsString());
+}
+
+PassRefPtr<Blob> ChromiumDataObjectItem::getAsFile() const
+{
+ if (kind() != DataTransferItem::kindFile)
+ return 0;
+
+ if (m_source == InternalSource) {
+ if (m_file)
+ return m_file;
+ ASSERT(m_sharedBuffer);
+ // FIXME: This code is currently impossible--we never populate m_sharedBuffer when dragging
+ // in. At some point though, we may need to support correctly converting a shared buffer
+ // into a file.
+ return 0;
+ }
+
+ ASSERT(m_source == PasteboardSource);
+ if (type() == mimeTypeImagePng) {
+ // FIXME: This is pretty inefficient. We copy the data from the browser
+ // to the renderer. We then place it in a blob in WebKit, which
+ // registers it and copies it *back* to the browser. When a consumer
+ // wants to read the data, we then copy the data back into the renderer.
+ // https://bugs.webkit.org/show_bug.cgi?id=58107 has been filed to track
+ // improvements to this code (in particular, add a registerClipboardBlob
+ // method to the blob registry; that way the data is only copied over
+ // into the renderer when it's actually read, not when the blob is
+ // initially constructed).
+ RefPtr<SharedBuffer> data = PlatformSupport::clipboardReadImage(PasteboardPrivate::StandardBuffer);
+ RefPtr<RawData> rawData = RawData::create();
+ rawData->mutableData()->append(data->data(), data->size());
+ OwnPtr<BlobData> blobData = BlobData::create();
+ blobData->appendData(rawData, 0, -1);
+ blobData->setContentType(mimeTypeImagePng);
+ return Blob::create(blobData.release(), data->size());
+ }
+
+ return 0;
+}
+
+String ChromiumDataObjectItem::internalGetAsString() const
+{
+ ASSERT(m_kind == DataTransferItem::kindString);
+
+ if (m_source == InternalSource)
+ return m_data;
+
+ ASSERT(m_source == PasteboardSource);
+
+ String data;
+ // This is ugly but there's no real alternative.
+ if (m_type == mimeTypeTextPlain)
+ data = PlatformSupport::clipboardReadPlainText(currentPasteboardBuffer());
+ else if (m_type == mimeTypeTextHTML) {
+ KURL ignoredSourceURL;
+ unsigned ignored;
+ PlatformSupport::clipboardReadHTML(currentPasteboardBuffer(), &data, &ignoredSourceURL, &ignored, &ignored);
+ } else
+ data = PlatformSupport::clipboardReadCustomData(currentPasteboardBuffer(), m_type);
+
+ return PlatformSupport::clipboardSequenceNumber(currentPasteboardBuffer()) == m_sequenceNumber ? data : String();
+}
+
+bool ChromiumDataObjectItem::isFilename() const
+{
+ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=81261: When we properly support File dragout,
+ // we'll need to make sure this works as expected for DragDataChromium.
+ return m_kind == DataTransferItem::kindFile && m_file;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(DATA_TRANSFER_ITEMS)
diff --git a/Source/WebCore/platform/chromium/ChromiumDataObjectItem.h b/Source/WebCore/platform/chromium/ChromiumDataObjectItem.h
new file mode 100644
index 000000000..e49a82f38
--- /dev/null
+++ b/Source/WebCore/platform/chromium/ChromiumDataObjectItem.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ChromiumDataObjectItem_h
+#define ChromiumDataObjectItem_h
+
+#if ENABLE(DATA_TRANSFER_ITEMS)
+
+#include "File.h"
+#include "KURL.h"
+#include "SharedBuffer.h"
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class Blob;
+class ScriptExecutionContext;
+class StringCallback;
+
+class ChromiumDataObjectItem : public RefCounted<ChromiumDataObjectItem> {
+public:
+ static PassRefPtr<ChromiumDataObjectItem> createFromString(const String& type, const String& data);
+ static PassRefPtr<ChromiumDataObjectItem> createFromFile(PassRefPtr<File>);
+ static PassRefPtr<ChromiumDataObjectItem> createFromURL(const String& url, const String& title);
+ static PassRefPtr<ChromiumDataObjectItem> createFromHTML(const String& html, const KURL& baseURL);
+ static PassRefPtr<ChromiumDataObjectItem> createFromSharedBuffer(const String& filename, PassRefPtr<SharedBuffer>);
+ static PassRefPtr<ChromiumDataObjectItem> createFromPasteboard(const String& type, uint64_t sequenceNumber);
+
+ String kind() const { return m_kind; }
+ String type() const { return m_type; }
+ void getAsString(PassRefPtr<StringCallback>, ScriptExecutionContext*) const;
+ PassRefPtr<Blob> getAsFile() const;
+
+ // Used to support legacy DataTransfer APIs and renderer->browser serialization.
+ String internalGetAsString() const;
+ PassRefPtr<SharedBuffer> sharedBuffer() const { return m_sharedBuffer; }
+ String title() const { return m_title; }
+ KURL baseURL() const { return m_baseURL; }
+ bool isFilename() const;
+
+private:
+ enum DataSource {
+ PasteboardSource,
+ InternalSource,
+ };
+
+ ChromiumDataObjectItem(const String& kind, const String& type);
+ ChromiumDataObjectItem(const String& kind, const String& type, uint64_t sequenceNumber);
+
+ DataSource m_source;
+ String m_kind;
+ String m_type;
+
+ String m_data;
+ RefPtr<File> m_file;
+ RefPtr<SharedBuffer> m_sharedBuffer;
+ // Optional metadata. Currently used for URL, HTML, and dragging files in.
+ String m_title;
+ KURL m_baseURL;
+
+ uint64_t m_sequenceNumber; // Only valid when m_source == PasteboardSource
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(DATA_TRANSFER_ITEMS)
+
+#endif // ChromiumDataObjectItem_h
diff --git a/Source/WebCore/platform/chromium/ClipboardChromium.cpp b/Source/WebCore/platform/chromium/ClipboardChromium.cpp
index e238b2dfd..25e89c31e 100644
--- a/Source/WebCore/platform/chromium/ClipboardChromium.cpp
+++ b/Source/WebCore/platform/chromium/ClipboardChromium.cpp
@@ -29,10 +29,10 @@
#include "CachedImage.h"
#include "ChromiumDataObject.h"
+#include "ChromiumDataObjectItem.h"
#include "ClipboardMimeTypes.h"
#include "ClipboardUtilitiesChromium.h"
-#include "DataTransferItemChromium.h"
-#include "DataTransferItemListChromium.h"
+#include "DataTransferItemList.h"
#include "Document.h"
#include "DragData.h"
#include "Element.h"
@@ -57,65 +57,52 @@ namespace WebCore {
namespace {
-// These wrapper classes invalidate a DataTransferItem/DataTransferItemList when the associated
-// Clipboard object goes out of scope.
+// A wrapper class that invalidates a DataTransferItemList when the associated Clipboard object goes out of scope.
class DataTransferItemListPolicyWrapper : public DataTransferItemList {
public:
- static PassRefPtr<DataTransferItemListPolicyWrapper> create(
- PassRefPtr<ClipboardChromium>, PassRefPtr<DataTransferItemListChromium>);
+ static PassRefPtr<DataTransferItemListPolicyWrapper> create(PassRefPtr<ClipboardChromium>, PassRefPtr<ChromiumDataObject>);
+ virtual ~DataTransferItemListPolicyWrapper();
virtual size_t length() const;
- virtual PassRefPtr<DataTransferItem> item(unsigned long index);
- virtual void deleteItem(unsigned long index, ExceptionCode&);
- virtual void clear();
- virtual void add(const String& data, const String& type, ExceptionCode&);
- virtual void add(PassRefPtr<File>);
+ virtual PassRefPtr<DataTransferItem> item(unsigned long index) OVERRIDE;
+ virtual void deleteItem(unsigned long index, ExceptionCode&) OVERRIDE;
+ virtual void clear() OVERRIDE;
+ virtual void add(const String& data, const String& type, ExceptionCode&) OVERRIDE;
+ virtual void add(PassRefPtr<File>) OVERRIDE;
private:
- DataTransferItemListPolicyWrapper(PassRefPtr<ClipboardChromium>, PassRefPtr<DataTransferItemListChromium>);
+ DataTransferItemListPolicyWrapper(PassRefPtr<ClipboardChromium>, PassRefPtr<ChromiumDataObject>);
RefPtr<ClipboardChromium> m_clipboard;
- RefPtr<DataTransferItemListChromium> m_list;
+ RefPtr<ChromiumDataObject> m_dataObject;
};
-class DataTransferItemPolicyWrapper : public DataTransferItem {
-public:
- static PassRefPtr<DataTransferItemPolicyWrapper> create(
- PassRefPtr<ClipboardChromium>, PassRefPtr<DataTransferItem>);
-
- virtual String kind() const;
- virtual String type() const;
-
- virtual void getAsString(PassRefPtr<StringCallback>) const;
- virtual PassRefPtr<Blob> getAsFile() const;
-
-private:
- DataTransferItemPolicyWrapper(PassRefPtr<ClipboardChromium>, PassRefPtr<DataTransferItem>);
-
- RefPtr<ClipboardChromium> m_clipboard;
- RefPtr<DataTransferItem> m_item;
-};
PassRefPtr<DataTransferItemListPolicyWrapper> DataTransferItemListPolicyWrapper::create(
- PassRefPtr<ClipboardChromium> clipboard, PassRefPtr<DataTransferItemListChromium> list)
+ PassRefPtr<ClipboardChromium> clipboard, PassRefPtr<ChromiumDataObject> list)
{
return adoptRef(new DataTransferItemListPolicyWrapper(clipboard, list));
}
+DataTransferItemListPolicyWrapper::~DataTransferItemListPolicyWrapper()
+{
+}
+
size_t DataTransferItemListPolicyWrapper::length() const
{
if (m_clipboard->policy() == ClipboardNumb)
return 0;
- return m_list->length();
+ return m_dataObject->length();
}
PassRefPtr<DataTransferItem> DataTransferItemListPolicyWrapper::item(unsigned long index)
{
if (m_clipboard->policy() == ClipboardNumb)
return 0;
- RefPtr<DataTransferItem> item = m_list->item(index);
+ RefPtr<ChromiumDataObjectItem> item = m_dataObject->item(index);
if (!item)
return 0;
+
return DataTransferItemPolicyWrapper::create(m_clipboard, item);
}
@@ -125,44 +112,49 @@ void DataTransferItemListPolicyWrapper::deleteItem(unsigned long index, Exceptio
ec = INVALID_STATE_ERR;
return;
}
- // FIXME: We handle all the exceptions here, so we don't need to propogate ec.
- m_list->deleteItem(index, ec);
+ m_dataObject->deleteItem(index);
}
void DataTransferItemListPolicyWrapper::clear()
{
if (m_clipboard->policy() != ClipboardWritable)
return;
- m_list->clear();
+ m_dataObject->clearAll();
}
void DataTransferItemListPolicyWrapper::add(const String& data, const String& type, ExceptionCode& ec)
{
if (m_clipboard->policy() != ClipboardWritable)
return;
- m_list->add(data, type, ec);
+ m_dataObject->add(data, type, ec);
}
void DataTransferItemListPolicyWrapper::add(PassRefPtr<File> file)
{
if (m_clipboard->policy() != ClipboardWritable)
return;
- m_list->add(file);
+ m_dataObject->add(file, m_clipboard->frame()->document()->scriptExecutionContext());
}
DataTransferItemListPolicyWrapper::DataTransferItemListPolicyWrapper(
- PassRefPtr<ClipboardChromium> clipboard, PassRefPtr<DataTransferItemListChromium> list)
+ PassRefPtr<ClipboardChromium> clipboard, PassRefPtr<ChromiumDataObject> dataObject)
: m_clipboard(clipboard)
- , m_list(list)
+ , m_dataObject(dataObject)
{
}
+} // namespace
+
PassRefPtr<DataTransferItemPolicyWrapper> DataTransferItemPolicyWrapper::create(
- PassRefPtr<ClipboardChromium> clipboard, PassRefPtr<DataTransferItem> item)
+ PassRefPtr<ClipboardChromium> clipboard, PassRefPtr<ChromiumDataObjectItem> item)
{
return adoptRef(new DataTransferItemPolicyWrapper(clipboard, item));
}
+DataTransferItemPolicyWrapper::~DataTransferItemPolicyWrapper()
+{
+}
+
String DataTransferItemPolicyWrapper::kind() const
{
if (m_clipboard->policy() == ClipboardNumb)
@@ -182,7 +174,7 @@ void DataTransferItemPolicyWrapper::getAsString(PassRefPtr<StringCallback> callb
if (m_clipboard->policy() != ClipboardReadable && m_clipboard->policy() != ClipboardWritable)
return;
- m_item->getAsString(callback);
+ m_item->getAsString(callback, m_clipboard->frame()->document()->scriptExecutionContext());
}
PassRefPtr<Blob> DataTransferItemPolicyWrapper::getAsFile() const
@@ -194,24 +186,27 @@ PassRefPtr<Blob> DataTransferItemPolicyWrapper::getAsFile() const
}
DataTransferItemPolicyWrapper::DataTransferItemPolicyWrapper(
- PassRefPtr<ClipboardChromium> clipboard, PassRefPtr<DataTransferItem> item)
+ PassRefPtr<ClipboardChromium> clipboard, PassRefPtr<ChromiumDataObjectItem> item)
: m_clipboard(clipboard)
, m_item(item)
{
}
-} // namespace
-
using namespace HTMLNames;
// We provide the IE clipboard types (URL and Text), and the clipboard types specified in the WHATWG Web Applications 1.0 draft
// see http://www.whatwg.org/specs/web-apps/current-work/ Section 6.3.5.3
-static String normalizeType(const String& type)
+static String normalizeType(const String& type, bool* convertToURL = 0)
{
String cleanType = type.stripWhiteSpace().lower();
if (cleanType == mimeTypeText || cleanType.startsWith(mimeTypeTextPlainEtc))
return mimeTypeTextPlain;
+ if (cleanType == mimeTypeURL) {
+ if (convertToURL)
+ *convertToURL = true;
+ return mimeTypeTextURIList;
+ }
return cleanType;
}
@@ -227,8 +222,6 @@ ClipboardChromium::ClipboardChromium(ClipboardType clipboardType,
: Clipboard(policy, clipboardType)
, m_dataObject(dataObject)
, m_frame(frame)
- , m_originalSequenceNumber(PlatformSupport::clipboardSequenceNumber(currentPasteboardBuffer()))
- , m_dragStorageUpdated(true)
{
}
@@ -244,10 +237,9 @@ PassRefPtr<ClipboardChromium> ClipboardChromium::create(ClipboardType clipboardT
void ClipboardChromium::clearData(const String& type)
{
- if (policy() != ClipboardWritable || !m_dataObject)
+ if (policy() != ClipboardWritable)
return;
- m_dragStorageUpdated = true;
m_dataObject->clearData(normalizeType(type));
ASSERT_NOT_REACHED();
@@ -258,20 +250,40 @@ void ClipboardChromium::clearAllData()
if (policy() != ClipboardWritable)
return;
- m_dragStorageUpdated = true;
m_dataObject->clearAll();
}
String ClipboardChromium::getData(const String& type) const
{
- bool ignoredSuccess = false;
- if (policy() != ClipboardReadable || !m_dataObject)
+ if (policy() != ClipboardReadable)
return String();
- if (isForCopyAndPaste() && platformClipboardChanged())
- return String();
+ bool convertToURL = false;
+ String data = m_dataObject->getData(normalizeType(type, &convertToURL));
+ if (!convertToURL)
+ return data;
+ return convertURIListToURL(data);
+
+ Vector<String> uriList;
+ // Line separator is \r\n per RFC 2483 - howver, for compatiblity
+ // reasons we also allow just \n here.
+ data.split('\n', uriList);
+ // Process the input and return the first valid RUL. In case no URLs can
+ // be found, return an empty string. This is in line with the HTML5
+ // spec (see "The DragEvent and DataTransfer interfaces").
+ for (size_t i = 0; i < uriList.size(); ++i) {
+ String& line = uriList[i];
+ line = line.stripWhiteSpace();
+ if (line.isEmpty())
+ continue;
+ if (line[0] == '#')
+ continue;
+ KURL url = KURL(ParsedURLString, line);
+ if (url.isValid())
+ return url;
+ }
- return m_dataObject->getData(normalizeType(type), ignoredSuccess);
+ return String();
}
bool ClipboardChromium::setData(const String& type, const String& data)
@@ -279,47 +291,33 @@ bool ClipboardChromium::setData(const String& type, const String& data)
if (policy() != ClipboardWritable)
return false;
- m_dragStorageUpdated = true;
return m_dataObject->setData(normalizeType(type), data);
}
-bool ClipboardChromium::platformClipboardChanged() const
-{
- return PlatformSupport::clipboardSequenceNumber(currentPasteboardBuffer()) != m_originalSequenceNumber;
-}
-
// extensions beyond IE's API
HashSet<String> ClipboardChromium::types() const
{
- HashSet<String> results;
if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable)
- return results;
-
- if (!m_dataObject)
- return results;
-
- results = m_dataObject->types();
+ return HashSet<String>();
- if (m_dataObject->containsFilenames())
- results.add(mimeTypeFiles);
-
- return results;
+ return m_dataObject->types();
}
PassRefPtr<FileList> ClipboardChromium::files() const
{
+ RefPtr<FileList> files = FileList::create();
if (policy() != ClipboardReadable)
- return FileList::create();
-
- if (!m_dataObject)
- return FileList::create();
+ return files.release();
- const Vector<String>& filenames = m_dataObject->filenames();
- RefPtr<FileList> fileList = FileList::create();
- for (size_t i = 0; i < filenames.size(); ++i)
- fileList->append(File::create(filenames.at(i)));
+ for (size_t i = 0; i < m_dataObject->length(); ++i) {
+ if (m_dataObject->item(i)->kind() == DataTransferItem::kindFile) {
+ RefPtr<Blob> blob = m_dataObject->item(i)->getAsFile();
+ if (blob && blob->isFile())
+ files->append(static_cast<File*>(blob.get()));
+ }
+ }
- return fileList.release();
+ return files.release();
}
void ClipboardChromium::setDragImage(CachedImage* image, Node* node, const IntPoint& loc)
@@ -389,8 +387,6 @@ static void writeImageToDataObject(ChromiumDataObject* dataObject, Element* elem
if (!imageBuffer || !imageBuffer->size())
return;
- dataObject->setFileContent(imageBuffer);
-
// Determine the filename for the file contents of the image.
String filename = cachedImage->response().suggestedFilename();
if (filename.isEmpty())
@@ -410,8 +406,7 @@ static void writeImageToDataObject(ChromiumDataObject* dataObject, Element* elem
ClipboardChromium::validateFilename(filename, extension);
- dataObject->setFileContentFilename(filename + extension);
- dataObject->setFileExtension(extension);
+ dataObject->addSharedBuffer(filename + extension, imageBuffer);
}
void ClipboardChromium::declareAndWriteDragImage(Element* element, const KURL& url, const String& title, Frame* frame)
@@ -419,9 +414,7 @@ void ClipboardChromium::declareAndWriteDragImage(Element* element, const KURL& u
if (!m_dataObject)
return;
- m_dragStorageUpdated = true;
- m_dataObject->setData(mimeTypeURL, url);
- m_dataObject->setUrlTitle(title);
+ m_dataObject->setURLAndTitle(url, title);
// Write the bytes in the image to the file format.
writeImageToDataObject(m_dataObject.get(), element, url);
@@ -436,16 +429,13 @@ void ClipboardChromium::writeURL(const KURL& url, const String& title, Frame*)
return;
ASSERT(!url.isEmpty());
- m_dragStorageUpdated = true;
- m_dataObject->setData(mimeTypeURL, url);
- m_dataObject->setUrlTitle(title);
+ m_dataObject->setURLAndTitle(url, title);
// The URL can also be used as plain text.
m_dataObject->setData(mimeTypeTextPlain, url.string());
// The URL can also be used as an HTML fragment.
- m_dataObject->setData(mimeTypeTextHTML, urlToMarkup(url, title));
- m_dataObject->setHtmlBaseUrl(url);
+ m_dataObject->setHTMLAndBaseURL(urlToMarkup(url, title), url);
}
void ClipboardChromium::writeRange(Range* selectedRange, Frame* frame)
@@ -454,9 +444,7 @@ void ClipboardChromium::writeRange(Range* selectedRange, Frame* frame)
if (!m_dataObject)
return;
- m_dragStorageUpdated = true;
- m_dataObject->setData(mimeTypeTextHTML, createMarkup(selectedRange, 0, AnnotateForInterchange, false, ResolveNonLocalURLs));
- m_dataObject->setHtmlBaseUrl(frame->document()->url());
+ m_dataObject->setHTMLAndBaseURL(createMarkup(selectedRange, 0, AnnotateForInterchange, false, ResolveNonLocalURLs), frame->document()->url());
String str = frame->editor()->selectedText();
#if OS(WINDOWS)
@@ -477,76 +465,24 @@ void ClipboardChromium::writePlainText(const String& text)
#endif
replaceNBSPWithSpace(str);
- m_dragStorageUpdated = true;
m_dataObject->setData(mimeTypeTextPlain, str);
}
bool ClipboardChromium::hasData()
{
ASSERT(isForDragAndDrop());
- if (!m_dataObject)
- return false;
- return m_dataObject->hasData();
+ return m_dataObject->length() > 0;
}
#if ENABLE(DATA_TRANSFER_ITEMS)
PassRefPtr<DataTransferItemList> ClipboardChromium::items()
{
- if (!m_dataObject)
- // Return an unassociated empty list.
- return DataTransferItemListChromium::create(this, m_frame->document()->scriptExecutionContext());
-
- if (!m_itemList)
- m_itemList = DataTransferItemListChromium::create(this, m_frame->document()->scriptExecutionContext());
-
// FIXME: According to the spec, we are supposed to return the same collection of items each
// time. We now return a wrapper that always wraps the *same* set of items, so JS shouldn't be
// able to tell, but we probably still want to fix this.
- return DataTransferItemListPolicyWrapper::create(this, m_itemList);
-}
-
-// FIXME: integrate ChromiumDataObject and DataTransferItemList rather than holding them separately and keeping them synced.
-void ClipboardChromium::mayUpdateItems(Vector<RefPtr<DataTransferItem> >& items)
-{
- if (!items.isEmpty() && !storageHasUpdated())
- return;
-
- items.clear();
-
- ScriptExecutionContext* scriptExecutionContext = m_frame->document()->scriptExecutionContext();
-
- if (isForCopyAndPaste() && policy() == ClipboardReadable) {
- // Iterate through the types and add them.
- HashSet<String> types = m_dataObject->types();
- for (HashSet<String>::const_iterator it = types.begin(); it != types.end(); ++it)
- items.append(DataTransferItemChromium::createFromPasteboard(this, scriptExecutionContext, *it));
- return;
- }
-
- bool success = false;
- String plainText = m_dataObject->getData(mimeTypeTextPlain, success);
- if (success)
- items.append(DataTransferItemChromium::create(this, scriptExecutionContext, plainText, mimeTypeTextPlain));
-
- success = false;
- String htmlText = m_dataObject->getData(mimeTypeTextHTML, success);
- if (success)
- items.append(DataTransferItemChromium::create(this, scriptExecutionContext, htmlText, mimeTypeTextHTML));
-
- if (m_dataObject->containsFilenames()) {
- const Vector<String>& filenames = m_dataObject->filenames();
- for (Vector<String>::const_iterator it = filenames.begin(); it != filenames.end(); ++it)
- items.append(DataTransferItemChromium::create(this, scriptExecutionContext, File::create(*it)));
- }
- m_dragStorageUpdated = false;
+ return DataTransferItemListPolicyWrapper::create(this, m_dataObject);
}
-
-bool ClipboardChromium::storageHasUpdated() const
-{
- return (isForCopyAndPaste() && platformClipboardChanged()) || (isForDragAndDrop() && m_dragStorageUpdated);
-}
-
#endif
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/ClipboardChromium.h b/Source/WebCore/platform/chromium/ClipboardChromium.h
index 3777ad5c9..526cfa8d5 100644
--- a/Source/WebCore/platform/chromium/ClipboardChromium.h
+++ b/Source/WebCore/platform/chromium/ClipboardChromium.h
@@ -33,16 +33,37 @@
#include "CachedImage.h"
#include "ChromiumDataObject.h"
#include "Clipboard.h"
+#include "DataTransferItem.h"
namespace WebCore {
class CachedImage;
- class ChromiumDataObject;
- class DataTransferItem;
- class DataTransferItemListChromium;
+ class ChromiumDataObjectItem;
+ class ClipboardChromium;
class Frame;
class IntPoint;
+ // A wrapper class that invalidates a DataTransferItem when the associated Clipboard object goes out of scope.
+ class DataTransferItemPolicyWrapper : public DataTransferItem {
+ public:
+ static PassRefPtr<DataTransferItemPolicyWrapper> create(PassRefPtr<ClipboardChromium>, PassRefPtr<ChromiumDataObjectItem>);
+ virtual ~DataTransferItemPolicyWrapper();
+
+ virtual String kind() const OVERRIDE;
+ virtual String type() const OVERRIDE;
+ virtual void getAsString(PassRefPtr<StringCallback>) const OVERRIDE;
+ virtual PassRefPtr<Blob> getAsFile() const OVERRIDE;
+
+ ClipboardChromium* clipboard() { return m_clipboard.get(); }
+ ChromiumDataObjectItem* dataObjectItem() { return m_item.get(); }
+
+ private:
+ DataTransferItemPolicyWrapper(PassRefPtr<ClipboardChromium>, PassRefPtr<ChromiumDataObjectItem>);
+
+ RefPtr<ClipboardChromium> m_clipboard;
+ RefPtr<ChromiumDataObjectItem> m_item;
+ };
+
class ClipboardChromium : public Clipboard, public CachedImageClient {
WTF_MAKE_FAST_ALLOCATED;
public:
@@ -84,11 +105,8 @@ namespace WebCore {
#if ENABLE(DATA_TRANSFER_ITEMS)
virtual PassRefPtr<DataTransferItemList> items();
-
- // Internal routines to keep the list returned by items() (i.e. m_itemList) synchronized with the content of the clipboard data.
- void mayUpdateItems(Vector<RefPtr<DataTransferItem> >& items);
- bool storageHasUpdated() const;
#endif
+ Frame* frame() const { return m_frame; }
private:
ClipboardChromium(ClipboardType, PassRefPtr<ChromiumDataObject>, ClipboardAccessPolicy, Frame*);
@@ -97,13 +115,6 @@ namespace WebCore {
void setDragImage(CachedImage*, Node*, const IntPoint&);
RefPtr<ChromiumDataObject> m_dataObject;
Frame* m_frame;
-
-#if ENABLE(DATA_TRANSFER_ITEMS)
- RefPtr<DataTransferItemListChromium> m_itemList;
-#endif
-
- uint64_t m_originalSequenceNumber;
- bool m_dragStorageUpdated;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/ClipboardUtilitiesChromium.cpp b/Source/WebCore/platform/chromium/ClipboardUtilitiesChromium.cpp
index 47572c5b8..62cf99ce0 100644
--- a/Source/WebCore/platform/chromium/ClipboardUtilitiesChromium.cpp
+++ b/Source/WebCore/platform/chromium/ClipboardUtilitiesChromium.cpp
@@ -60,4 +60,26 @@ void replaceNBSPWithSpace(String& str)
str.replace(NonBreakingSpaceCharacter, SpaceCharacter);
}
+String convertURIListToURL(const String& uriList)
+{
+ Vector<String> items;
+ // Line separator is \r\n per RFC 2483 - however, for compatibility
+ // reasons we allow just \n here.
+ uriList.split('\n', items);
+ // Process the input and return the first valid URL. In case no URLs can
+ // be found, return an empty string. This is in line with the HTML5 spec.
+ for (size_t i = 0; i < items.size(); ++i) {
+ String& line = items[i];
+ line = line.stripWhiteSpace();
+ if (line.isEmpty())
+ continue;
+ if (line[0] == '#')
+ continue;
+ KURL url = KURL(ParsedURLString, line);
+ if (url.isValid())
+ return url;
+ }
+ return String();
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/ClipboardUtilitiesChromium.h b/Source/WebCore/platform/chromium/ClipboardUtilitiesChromium.h
index 7ae50043a..49a483870 100644
--- a/Source/WebCore/platform/chromium/ClipboardUtilitiesChromium.h
+++ b/Source/WebCore/platform/chromium/ClipboardUtilitiesChromium.h
@@ -44,6 +44,7 @@ PasteboardPrivate::ClipboardBuffer currentPasteboardBuffer();
void replaceNewlinesWithWindowsStyleNewlines(String&);
#endif
void replaceNBSPWithSpace(String&);
+String convertURIListToURL(const String& uriList);
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/DataTransferItemChromium.cpp b/Source/WebCore/platform/chromium/DataTransferItemChromium.cpp
deleted file mode 100644
index 696ee653e..000000000
--- a/Source/WebCore/platform/chromium/DataTransferItemChromium.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "DataTransferItemChromium.h"
-
-#if ENABLE(DATA_TRANSFER_ITEMS)
-
-#include "Blob.h"
-#include "Clipboard.h"
-#include "ClipboardChromium.h"
-#include "ClipboardMimeTypes.h"
-#include "ClipboardUtilitiesChromium.h"
-#include "DataTransferItemListChromium.h"
-#include "File.h"
-#include "PlatformSupport.h"
-#include "SharedBuffer.h"
-#include "StringCallback.h"
-
-namespace WebCore {
-
-PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::createFromPasteboard(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context, const String& type)
-{
- if (type == mimeTypeTextPlain || type == mimeTypeTextHTML)
- return adoptRef(new DataTransferItemChromium(owner, context, PasteboardSource, DataTransferItem::kindString, type, String()));
- return adoptRef(new DataTransferItemChromium(owner, context, PasteboardSource, DataTransferItem::kindFile, type, ""));
-}
-
-PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::create(PassRefPtr<Clipboard> owner,
- ScriptExecutionContext* context,
- const String& data,
- const String& type)
-{
- return adoptRef(new DataTransferItemChromium(owner, context, DataTransferItemChromium::InternalSource, kindString, type, data));
-}
-
-PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::create(PassRefPtr<Clipboard> owner,
- ScriptExecutionContext* context,
- PassRefPtr<File> file)
-{
- return adoptRef(new DataTransferItemChromium(owner, context, DataTransferItemChromium::InternalSource, file));
-}
-
-DataTransferItemChromium::DataTransferItemChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context, DataSource source, const String& kind, const String& type, const String& data)
- : m_context(context)
- , m_owner(owner)
- , m_kind(kind)
- , m_type(type)
- , m_source(source)
- , m_data(data)
-{
-}
-
-DataTransferItemChromium::DataTransferItemChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context, DataSource source, PassRefPtr<File> file)
- : m_context(context)
- , m_owner(owner)
- , m_kind(kindFile)
- , m_type(file.get() ? file->type() : String())
- , m_source(source)
- , m_file(file)
-{
-}
-
-void DataTransferItemChromium::getAsString(PassRefPtr<StringCallback> callback) const
-{
- if (kind() != kindString)
- return;
-
- if (clipboardChromium()->storageHasUpdated())
- return;
-
- if (m_source == InternalSource) {
- callback->scheduleCallback(m_context, m_data);
- return;
- }
-
- ASSERT(m_source == PasteboardSource);
-
- // This is ugly but there's no real alternative.
- if (type() == mimeTypeTextPlain) {
- callback->scheduleCallback(m_context, PlatformSupport::clipboardReadPlainText(currentPasteboardBuffer()));
- return;
- }
- if (type() == mimeTypeTextHTML) {
- String html;
- KURL ignoredSourceURL;
- unsigned ignored;
- PlatformSupport::clipboardReadHTML(currentPasteboardBuffer(), &html, &ignoredSourceURL, &ignored, &ignored);
- callback->scheduleCallback(m_context, html);
- return;
- }
- ASSERT_NOT_REACHED();
-}
-
-PassRefPtr<Blob> DataTransferItemChromium::getAsFile() const
-{
- if (kind() != kindFile || clipboardChromium()->storageHasUpdated())
- return 0;
-
- if (m_source == InternalSource)
- return m_file;
-
- ASSERT(m_source == PasteboardSource);
- if (type() == mimeTypeImagePng) {
- // FIXME: This is pretty inefficient. We copy the data from the browser
- // to the renderer. We then place it in a blob in WebKit, which
- // registers it and copies it *back* to the browser. When a consumer
- // wants to read the data, we then copy the data back into the renderer.
- // https://bugs.webkit.org/show_bug.cgi?id=58107 has been filed to track
- // improvements to this code (in particular, add a registerClipboardBlob
- // method to the blob registry; that way the data is only copied over
- // into the renderer when it's actually read, not when the blob is
- // initially constructed).
- RefPtr<SharedBuffer> data = PlatformSupport::clipboardReadImage(PasteboardPrivate::StandardBuffer);
- RefPtr<RawData> rawData = RawData::create();
- rawData->mutableData()->append(data->data(), data->size());
- OwnPtr<BlobData> blobData = BlobData::create();
- blobData->appendData(rawData, 0, -1);
- blobData->setContentType(mimeTypeImagePng);
- return Blob::create(blobData.release(), data->size());
- }
- return 0;
-}
-
-ClipboardChromium* DataTransferItemChromium::clipboardChromium() const
-{
- return static_cast<ClipboardChromium*>(m_owner.get());
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(DATA_TRANSFER_ITEMS)
diff --git a/Source/WebCore/platform/chromium/DataTransferItemChromium.h b/Source/WebCore/platform/chromium/DataTransferItemChromium.h
deleted file mode 100644
index 2a919006b..000000000
--- a/Source/WebCore/platform/chromium/DataTransferItemChromium.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DataTransferItemChromium_h
-#define DataTransferItemChromium_h
-
-#if ENABLE(DATA_TRANSFER_ITEMS)
-
-#include "DataTransferItem.h"
-#include <wtf/RefPtr.h>
-#include <wtf/text/WTFString.h>
-
-namespace WebCore {
-
-class Clipboard;
-class ClipboardChromium;
-class File;
-class ScriptExecutionContext;
-
-class DataTransferItemChromium : public DataTransferItem {
-public:
- static PassRefPtr<DataTransferItemChromium> create(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, const String& data, const String& type);
- static PassRefPtr<DataTransferItemChromium> create(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, PassRefPtr<File>);
- static PassRefPtr<DataTransferItemChromium> createFromPasteboard(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, const String& type);
-
- virtual String kind() const { return m_kind; }
- virtual String type() const { return m_type; }
- virtual void getAsString(PassRefPtr<StringCallback>) const;
- virtual PassRefPtr<Blob> getAsFile() const;
-
-private:
- friend class DataTransferItemListChromium;
-
- enum DataSource {
- PasteboardSource,
- InternalSource,
- };
-
- DataTransferItemChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, DataSource, const String& kind, const String& type, const String& data);
- DataTransferItemChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, DataSource, PassRefPtr<File>);
-
- ClipboardChromium* clipboardChromium() const;
-
- ScriptExecutionContext* m_context;
- const RefPtr<Clipboard> m_owner;
- const String m_kind;
- const String m_type;
- const DataSource m_source;
- const String m_data;
- RefPtr<File> m_file;
-};
-
-} // namespace WebCore
-
-#endif // ENABLE(DATA_TRANSFER_ITEMS)
-
-#endif // DataTransferItem_h
diff --git a/Source/WebCore/platform/chromium/DataTransferItemListChromium.cpp b/Source/WebCore/platform/chromium/DataTransferItemListChromium.cpp
deleted file mode 100644
index 3a280fe3b..000000000
--- a/Source/WebCore/platform/chromium/DataTransferItemListChromium.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "DataTransferItemListChromium.h"
-
-#if ENABLE(DATA_TRANSFER_ITEMS)
-
-#include "BlobURL.h"
-#include "ChromiumDataObject.h"
-#include "ClipboardChromium.h"
-#include "ClipboardMimeTypes.h"
-#include "DataTransferItemChromium.h"
-#include "ExceptionCode.h"
-#include "File.h"
-#include "KURL.h"
-#include "ScriptExecutionContext.h"
-#include "ThreadableBlobRegistry.h"
-#include <wtf/text/StringBuilder.h>
-
-namespace WebCore {
-
-PassRefPtr<DataTransferItemListChromium> DataTransferItemListChromium::create(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context)
-{
- return adoptRef(new DataTransferItemListChromium(owner, context));
-}
-
-DataTransferItemListChromium::DataTransferItemListChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context)
- : m_owner(owner)
- , m_context(context)
-{
-}
-
-size_t DataTransferItemListChromium::length() const
-{
- clipboardChromium()->mayUpdateItems(m_items);
- return m_items.size();
-}
-
-PassRefPtr<DataTransferItem> DataTransferItemListChromium::item(unsigned long index)
-{
- clipboardChromium()->mayUpdateItems(m_items);
- if (index >= length())
- return 0;
- return m_items[index];
-}
-
-void DataTransferItemListChromium::deleteItem(unsigned long index, ExceptionCode& ec)
-{
- clipboardChromium()->mayUpdateItems(m_items);
- if (index >= length())
- return;
- RefPtr<DataTransferItem> item = m_items[index];
-
- RefPtr<ChromiumDataObject> dataObject = clipboardChromium()->dataObject();
- if (!dataObject)
- return;
-
- if (item->kind() == DataTransferItem::kindString) {
- m_items.remove(index);
- dataObject->clearData(item->type());
- return;
- }
-
- ASSERT(item->kind() == DataTransferItem::kindFile);
- RefPtr<Blob> blob = item->getAsFile();
- if (!blob || !blob->isFile())
- return;
-
- m_items.clear();
- const Vector<String>& filenames = dataObject->filenames();
- Vector<String> copiedFilenames;
- for (size_t i = 0; i < filenames.size(); ++i) {
- if (filenames[i] != static_cast<File*>(blob.get())->path())
- copiedFilenames.append(static_cast<File*>(blob.get())->path());
- }
- dataObject->setFilenames(copiedFilenames);
-}
-
-void DataTransferItemListChromium::clear()
-{
- m_items.clear();
- clipboardChromium()->clearAllData();
-}
-
-void DataTransferItemListChromium::add(const String& data, const String& type, ExceptionCode& ec)
-{
- RefPtr<ChromiumDataObject> dataObject = clipboardChromium()->dataObject();
- if (!dataObject)
- return;
-
- bool success = false;
- dataObject->getData(type, success);
- if (success) {
- // Adding data with the same type should fail with NOT_SUPPORTED_ERR.
- ec = NOT_SUPPORTED_ERR;
- return;
- }
-
- m_items.clear();
- dataObject->setData(type, data);
-}
-
-void DataTransferItemListChromium::add(PassRefPtr<File> file)
-{
- if (!file)
- return;
-
- RefPtr<ChromiumDataObject> dataObject = clipboardChromium()->dataObject();
- if (!dataObject)
- return;
-
- m_items.clear();
-
- // Updating dataObject's fileset so that we will be seeing the consistent list even if we reconstruct the items later.
- dataObject->addFilename(file->path());
-
- // FIXME: Allow multiple files to be dragged out at once if more than one file is added to the storage. For now we manually set up drag-out download URL only if it has not been set yet.
- bool success = false;
- dataObject->getData(mimeTypeDownloadURL, success);
- if (success)
- return;
-
- KURL urlForDownload = BlobURL::createPublicURL(m_context->securityOrigin());
- ThreadableBlobRegistry::registerBlobURL(urlForDownload, file->url());
-
- StringBuilder downloadUrl;
- downloadUrl.append(file->type());
- downloadUrl.append(":");
- downloadUrl.append(encodeWithURLEscapeSequences(file->name()));
- downloadUrl.append(":");
- downloadUrl.append(urlForDownload.string());
- dataObject->setData(mimeTypeDownloadURL, downloadUrl.toString());
-}
-
-ClipboardChromium* DataTransferItemListChromium::clipboardChromium() const
-{
- return static_cast<ClipboardChromium*>(m_owner.get());
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(DATA_TRANSFER_ITEMS)
diff --git a/Source/WebCore/platform/chromium/DragDataChromium.cpp b/Source/WebCore/platform/chromium/DragDataChromium.cpp
index 3d94a19b2..009a3a08a 100644
--- a/Source/WebCore/platform/chromium/DragDataChromium.cpp
+++ b/Source/WebCore/platform/chromium/DragDataChromium.cpp
@@ -57,12 +57,9 @@ bool DragData::containsURL(Frame*, FilenameConversionPolicy filenamePolicy) cons
String DragData::asURL(Frame*, FilenameConversionPolicy filenamePolicy, String* title) const
{
String url;
- if (m_platformDragData->types().contains(mimeTypeTextURIList)) {
- bool ignoredSuccess;
- url = m_platformDragData->getData(mimeTypeURL, ignoredSuccess);
- if (title)
- *title = m_platformDragData->urlTitle();
- } else if (filenamePolicy == ConvertFilenames && containsFiles()) {
+ if (m_platformDragData->types().contains(mimeTypeTextURIList))
+ m_platformDragData->urlAndTitle(url, title);
+ else if (filenamePolicy == ConvertFilenames && containsFiles()) {
url = PlatformSupport::filePathToURL(PlatformSupport::getAbsolutePath(m_platformDragData->filenames()[0]));
}
return url;
@@ -92,8 +89,7 @@ bool DragData::containsPlainText() const
String DragData::asPlainText(Frame*) const
{
- bool ignoredSuccess;
- return m_platformDragData->getData(mimeTypeTextPlain, ignoredSuccess);
+ return m_platformDragData->getData(mimeTypeTextPlain);
}
bool DragData::containsColor() const
@@ -142,9 +138,10 @@ PassRefPtr<DocumentFragment> DragData::asFragment(Frame* frame, PassRefPtr<Range
}
if (m_platformDragData->types().contains(mimeTypeTextHTML)) {
- bool ignoredSuccess;
- RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(),
- m_platformDragData->getData(mimeTypeTextHTML, ignoredSuccess), m_platformDragData->htmlBaseUrl(), FragmentScriptingNotAllowed);
+ String html;
+ KURL baseURL;
+ m_platformDragData->htmlAndBaseURL(html, baseURL);
+ RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), html, baseURL, FragmentScriptingNotAllowed);
return fragment.release();
}
diff --git a/Source/WebCore/platform/chromium/DragImageChromiumMac.cpp b/Source/WebCore/platform/chromium/DragImageChromiumMac.cpp
index a0c2e2004..e12780f7e 100644
--- a/Source/WebCore/platform/chromium/DragImageChromiumMac.cpp
+++ b/Source/WebCore/platform/chromium/DragImageChromiumMac.cpp
@@ -98,7 +98,7 @@ DragImageRef dissolveDragImageToFraction(DragImageRef image, float delta)
return dissolvedImage;
}
-DragImageRef createDragImageFromImage(Image* image)
+DragImageRef createDragImageFromImage(Image* image, RespectImageOrientationEnum)
{
if (!image)
return 0;
diff --git a/Source/WebCore/platform/chromium/DragImageChromiumSkia.cpp b/Source/WebCore/platform/chromium/DragImageChromiumSkia.cpp
index e5ca1757a..40f8925a5 100644
--- a/Source/WebCore/platform/chromium/DragImageChromiumSkia.cpp
+++ b/Source/WebCore/platform/chromium/DragImageChromiumSkia.cpp
@@ -34,11 +34,12 @@
#include "Image.h"
#include "NativeImageSkia.h"
#include "NotImplemented.h"
-#include "RefPtr.h"
#include "SkBitmap.h"
#include "skia/ext/image_operations.h"
+#include <wtf/RefPtr.h>
+
namespace WebCore {
IntSize dragImageSize(DragImageRef image)
@@ -91,7 +92,7 @@ DragImageRef dissolveDragImageToFraction(DragImageRef image, float fraction)
return image;
}
-DragImageRef createDragImageFromImage(Image* image)
+DragImageRef createDragImageFromImage(Image* image, RespectImageOrientationEnum)
{
if (!image)
return 0;
diff --git a/Source/WebCore/platform/chromium/GamepadsChromium.cpp b/Source/WebCore/platform/chromium/GamepadsChromium.cpp
index fb6a47eb9..b1a2839eb 100644
--- a/Source/WebCore/platform/chromium/GamepadsChromium.cpp
+++ b/Source/WebCore/platform/chromium/GamepadsChromium.cpp
@@ -29,7 +29,8 @@
#if ENABLE(GAMEPAD)
#include "GamepadList.h"
-#include "PlatformSupport.h"
+
+#include <public/Platform.h>
namespace WebCore {
@@ -37,7 +38,25 @@ class GamepadList;
void sampleGamepads(GamepadList* into)
{
- PlatformSupport::sampleGamepads(into);
+ WebKit::WebGamepads gamepads;
+
+ WebKit::Platform::current()->sampleGamepads(gamepads);
+
+ for (unsigned i = 0; i < WebKit::WebGamepads::itemsLengthCap; ++i) {
+ WebKit::WebGamepad& webGamepad = gamepads.items[i];
+ if (i < gamepads.length && webGamepad.connected) {
+ RefPtr<Gamepad> gamepad = into->item(i);
+ if (!gamepad)
+ gamepad = Gamepad::create();
+ gamepad->id(webGamepad.id);
+ gamepad->index(i);
+ gamepad->timestamp(webGamepad.timestamp);
+ gamepad->axes(webGamepad.axesLength, webGamepad.axes);
+ gamepad->buttons(webGamepad.buttonsLength, webGamepad.buttons);
+ into->set(i, gamepad);
+ } else
+ into->set(i, 0);
+ }
}
}
diff --git a/Source/WebCore/platform/chromium/HistogramSupportChromium.cpp b/Source/WebCore/platform/chromium/HistogramSupportChromium.cpp
index 6ddb0146d..52e0b5ec8 100644
--- a/Source/WebCore/platform/chromium/HistogramSupportChromium.cpp
+++ b/Source/WebCore/platform/chromium/HistogramSupportChromium.cpp
@@ -31,13 +31,18 @@
#include "config.h"
#include "HistogramSupport.h"
-#include "PlatformSupport.h"
+#include <public/Platform.h>
namespace WebCore {
void HistogramSupport::histogramEnumeration(const char* name, int sample, int boundaryValue)
{
- PlatformSupport::histogramEnumeration(name, sample, boundaryValue);
+ WebKit::Platform::current()->histogramEnumeration(name, sample, boundaryValue);
+}
+
+void HistogramSupport::histogramCustomCounts(const char* name, int sample, int min, int max, int bucketCount)
+{
+ WebKit::Platform::current()->histogramCustomCounts(name, sample, min, max, bucketCount);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/KeyCodeConversionAndroid.cpp b/Source/WebCore/platform/chromium/KeyCodeConversionAndroid.cpp
index b53616862..e0579510d 100644
--- a/Source/WebCore/platform/chromium/KeyCodeConversionAndroid.cpp
+++ b/Source/WebCore/platform/chromium/KeyCodeConversionAndroid.cpp
@@ -34,8 +34,51 @@
#include <android/keycodes.h>
// The Android NDK does not provide values for these yet:
-#define AKEYCODE_MEDIA_PAUSE 127
-#define AKEYCODE_VOLUME_MUTE 164
+enum {
+ AKEYCODE_ESCAPE = 111,
+ AKEYCODE_FORWARD_DEL = 112,
+ AKEYCODE_CTRL_LEFT = 113,
+ AKEYCODE_CTRL_RIGHT = 114,
+ AKEYCODE_CAPS_LOCK = 115,
+ AKEYCODE_SCROLL_LOCK = 116,
+ AKEYCODE_META_LEFT = 117,
+ AKEYCODE_META_RIGHT = 118,
+ AKEYCODE_BREAK = 121,
+ AKEYCODE_INSERT = 124,
+ AKEYCODE_MEDIA_PLAY = 126,
+ AKEYCODE_MEDIA_PAUSE = 127,
+ AKEYCODE_F1 = 131,
+ AKEYCODE_F2 = 132,
+ AKEYCODE_F3 = 133,
+ AKEYCODE_F4 = 134,
+ AKEYCODE_F5 = 135,
+ AKEYCODE_F6 = 136,
+ AKEYCODE_F7 = 137,
+ AKEYCODE_F8 = 138,
+ AKEYCODE_F9 = 139,
+ AKEYCODE_F10 = 140,
+ AKEYCODE_F11 = 141,
+ AKEYCODE_F12 = 142,
+ AKEYCODE_NUM_LOCK = 143,
+ AKEYCODE_NUMPAD_0 = 144,
+ AKEYCODE_NUMPAD_1 = 145,
+ AKEYCODE_NUMPAD_2 = 146,
+ AKEYCODE_NUMPAD_3 = 147,
+ AKEYCODE_NUMPAD_4 = 148,
+ AKEYCODE_NUMPAD_5 = 149,
+ AKEYCODE_NUMPAD_6 = 150,
+ AKEYCODE_NUMPAD_7 = 151,
+ AKEYCODE_NUMPAD_8 = 152,
+ AKEYCODE_NUMPAD_9 = 153,
+ AKEYCODE_NUMPAD_DIVIDE = 154,
+ AKEYCODE_NUMPAD_MULTIPLY = 155,
+ AKEYCODE_NUMPAD_SUBTRACT = 156,
+ AKEYCODE_NUMPAD_ADD = 157,
+ AKEYCODE_NUMPAD_DOT = 158,
+ AKEYCODE_VOLUME_MUTE = 164,
+ AKEYCODE_CHANNEL_UP = 166,
+ AKEYCODE_CHANNEL_DOWN = 167,
+};
namespace WebCore {
@@ -176,6 +219,105 @@ int windowsKeyCodeForKeyEvent(unsigned int keyCode)
case AKEYCODE_MUTE:
case AKEYCODE_VOLUME_MUTE:
return VKEY_VOLUME_MUTE;
+ case AKEYCODE_ESCAPE:
+ return VKEY_ESCAPE;
+ case AKEYCODE_MEDIA_PLAY:
+ case AKEYCODE_MEDIA_PLAY_PAUSE:
+ return VKEY_MEDIA_PLAY_PAUSE;
+ case AKEYCODE_CALL:
+ return VKEY_END;
+ case AKEYCODE_ALT_LEFT:
+ case AKEYCODE_ALT_RIGHT:
+ return VKEY_MENU;
+ case AKEYCODE_GRAVE:
+ return VKEY_OEM_3;
+ case AKEYCODE_APOSTROPHE:
+ return VKEY_OEM_3;
+ case AKEYCODE_MEDIA_REWIND:
+ return VKEY_OEM_103;
+ case AKEYCODE_MEDIA_FAST_FORWARD:
+ return VKEY_OEM_104;
+ case AKEYCODE_PAGE_UP:
+ return VKEY_PRIOR;
+ case AKEYCODE_PAGE_DOWN:
+ return VKEY_NEXT;
+ case AKEYCODE_FORWARD_DEL:
+ return VKEY_DELETE;
+ case AKEYCODE_CTRL_LEFT:
+ case AKEYCODE_CTRL_RIGHT:
+ return VKEY_CONTROL;
+ case AKEYCODE_CAPS_LOCK:
+ return VKEY_CAPITAL;
+ case AKEYCODE_SCROLL_LOCK:
+ return VKEY_SCROLL;
+ case AKEYCODE_META_LEFT:
+ return VKEY_LWIN;
+ case AKEYCODE_META_RIGHT:
+ return VKEY_RWIN;
+ case AKEYCODE_BREAK:
+ return VKEY_PAUSE;
+ case AKEYCODE_INSERT:
+ return VKEY_INSERT;
+ case AKEYCODE_F1:
+ return VKEY_F1;
+ case AKEYCODE_F2:
+ return VKEY_F2;
+ case AKEYCODE_F3:
+ return VKEY_F3;
+ case AKEYCODE_F4:
+ return VKEY_F4;
+ case AKEYCODE_F5:
+ return VKEY_F5;
+ case AKEYCODE_F6:
+ return VKEY_F6;
+ case AKEYCODE_F7:
+ return VKEY_F7;
+ case AKEYCODE_F8:
+ return VKEY_F8;
+ case AKEYCODE_F9:
+ return VKEY_F9;
+ case AKEYCODE_F10:
+ return VKEY_F10;
+ case AKEYCODE_F11:
+ return VKEY_F11;
+ case AKEYCODE_F12:
+ return VKEY_F12;
+ case AKEYCODE_NUM_LOCK:
+ return VKEY_NUMLOCK;
+ case AKEYCODE_NUMPAD_0:
+ return VKEY_NUMPAD0;
+ case AKEYCODE_NUMPAD_1:
+ return VKEY_NUMPAD1;
+ case AKEYCODE_NUMPAD_2:
+ return VKEY_NUMPAD2;
+ case AKEYCODE_NUMPAD_3:
+ return VKEY_NUMPAD3;
+ case AKEYCODE_NUMPAD_4:
+ return VKEY_NUMPAD4;
+ case AKEYCODE_NUMPAD_5:
+ return VKEY_NUMPAD5;
+ case AKEYCODE_NUMPAD_6:
+ return VKEY_NUMPAD6;
+ case AKEYCODE_NUMPAD_7:
+ return VKEY_NUMPAD7;
+ case AKEYCODE_NUMPAD_8:
+ return VKEY_NUMPAD8;
+ case AKEYCODE_NUMPAD_9:
+ return VKEY_NUMPAD9;
+ case AKEYCODE_NUMPAD_DIVIDE:
+ return VKEY_DIVIDE;
+ case AKEYCODE_NUMPAD_MULTIPLY:
+ return VKEY_MULTIPLY;
+ case AKEYCODE_NUMPAD_SUBTRACT:
+ return VKEY_SUBTRACT;
+ case AKEYCODE_NUMPAD_ADD:
+ return VKEY_ADD;
+ case AKEYCODE_NUMPAD_DOT:
+ return VKEY_DECIMAL;
+ case AKEYCODE_CHANNEL_UP:
+ return VKEY_PRIOR;
+ case AKEYCODE_CHANNEL_DOWN:
+ return VKEY_NEXT;
default:
return 0;
}
diff --git a/Source/WebCore/platform/chromium/KeyboardCodes.h b/Source/WebCore/platform/chromium/KeyboardCodes.h
index a58ba35b2..0f045495d 100644
--- a/Source/WebCore/platform/chromium/KeyboardCodes.h
+++ b/Source/WebCore/platform/chromium/KeyboardCodes.h
@@ -514,6 +514,12 @@ namespace WebCore {
// VKEY_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard
VKEY_OEM_102 = VK_OEM_102,
+ // VKEY_OEM_103 (E3) GTV KEYCODE_MEDIA_REWIND
+ VKEY_OEM_103 = 0xE3,
+
+ // VKEY_OEM_104 (E4) GTV KEYCODE_MEDIA_FAST_FORWARD
+ VKEY_OEM_104 = 0xE4,
+
// VKEY_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key
VKEY_PROCESSKEY = VK_PROCESSKEY,
diff --git a/Source/WebCore/platform/chromium/LanguageChromium.cpp b/Source/WebCore/platform/chromium/LanguageChromium.cpp
index d23f19cf1..410ec8214 100644
--- a/Source/WebCore/platform/chromium/LanguageChromium.cpp
+++ b/Source/WebCore/platform/chromium/LanguageChromium.cpp
@@ -32,7 +32,7 @@
#include "Language.h"
#include "PlatformString.h"
-#include "PlatformSupport.h"
+#include <public/Platform.h>
#include <wtf/Vector.h>
namespace WebCore {
@@ -41,7 +41,7 @@ static String platformLanguage()
{
DEFINE_STATIC_LOCAL(String, computedDefaultLanguage, ());
if (computedDefaultLanguage.isEmpty())
- computedDefaultLanguage.append(PlatformSupport::computedDefaultLanguage());
+ computedDefaultLanguage.append(WebKit::Platform::current()->defaultLocale());
return computedDefaultLanguage;
}
diff --git a/Source/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp b/Source/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp
index 20395af7d..ee2d5617e 100644
--- a/Source/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp
+++ b/Source/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp
@@ -32,26 +32,28 @@
#include "MIMETypeRegistry.h"
#include "MediaPlayer.h"
-#include "PlatformSupport.h"
#include "PluginDataChromium.h"
+
+#include <public/Platform.h>
+#include <public/WebMimeRegistry.h>
#include <wtf/text/CString.h>
// NOTE: Unlike other ports, we don't use the shared implementation in
// MIMETypeRegistry.cpp. Instead, we need to route most functions via
-// the PlatformSupport to the embedder.
+// Platform.h to the embedder.
namespace WebCore {
String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
{
- return PlatformSupport::mimeTypeForExtension(ext);
+ return WebKit::Platform::current()->mimeRegistry()->mimeTypeForExtension(ext);
}
#if ENABLE(FILE_SYSTEM)
String MIMETypeRegistry::getWellKnownMIMETypeForExtension(const String &ext)
{
// This method must be thread safe and should not consult the OS/registry.
- return PlatformSupport::wellKnownMimeTypeForExtension(ext);
+ return WebKit::Platform::current()->mimeRegistry()->wellKnownMimeTypeForExtension(ext);
}
#endif
@@ -63,7 +65,7 @@ String MIMETypeRegistry::getPreferredExtensionForMIMEType(const String& type)
// FIXME: Is this really necessary??
String mimeType = type.substring(0, static_cast<unsigned>(type.find(';')));
- String ext = PlatformSupport::preferredExtensionForMIMEType(type);
+ String ext = WebKit::Platform::current()->mimeRegistry()->preferredExtensionForMIMEType(type);
if (!ext.isEmpty() && ext[0] == '.')
ext = ext.substring(1);
@@ -89,7 +91,8 @@ String MIMETypeRegistry::getMIMETypeForPath(const String& path)
bool MIMETypeRegistry::isSupportedImageMIMEType(const String& mimeType)
{
- return PlatformSupport::isSupportedImageMIMEType(mimeType);
+ return WebKit::Platform::current()->mimeRegistry()->supportsImageMIMEType(mimeType)
+ != WebKit::WebMimeRegistry::IsNotSupported;
}
bool MIMETypeRegistry::isSupportedImageResourceMIMEType(const String& mimeType)
@@ -110,12 +113,14 @@ bool MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(const String& mimeTyp
bool MIMETypeRegistry::isSupportedJavaScriptMIMEType(const String& mimeType)
{
- return PlatformSupport::isSupportedJavaScriptMIMEType(mimeType);
+ return WebKit::Platform::current()->mimeRegistry()->supportsJavaScriptMIMEType(mimeType)
+ != WebKit::WebMimeRegistry::IsNotSupported;
}
bool MIMETypeRegistry::isSupportedNonImageMIMEType(const String& mimeType)
{
- return PlatformSupport::isSupportedNonImageMIMEType(mimeType);
+ return WebKit::Platform::current()->mimeRegistry()->supportsNonImageMIMEType(mimeType)
+ != WebKit::WebMimeRegistry::IsNotSupported;
}
bool MIMETypeRegistry::isSupportedMediaMIMEType(const String& mimeType)
diff --git a/Source/WebCore/platform/chromium/MemoryUsageSupportChromium.cpp b/Source/WebCore/platform/chromium/MemoryUsageSupportChromium.cpp
new file mode 100644
index 000000000..0c3553eae
--- /dev/null
+++ b/Source/WebCore/platform/chromium/MemoryUsageSupportChromium.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MemoryUsageSupport.h"
+
+#include <public/Platform.h>
+
+namespace WebCore {
+
+int MemoryUsageSupport::memoryUsageMB()
+{
+ return WebKit::Platform::current()->memoryUsageMB();
+}
+
+int MemoryUsageSupport::actualMemoryUsageMB()
+{
+ return WebKit::Platform::current()->actualMemoryUsageMB();
+}
+
+int MemoryUsageSupport::lowMemoryUsageMB()
+{
+ return WebKit::Platform::current()->lowMemoryUsageMB();
+}
+
+int MemoryUsageSupport::highMemoryUsageMB()
+{
+ return WebKit::Platform::current()->highMemoryUsageMB();
+}
+
+int MemoryUsageSupport::highUsageDeltaMB()
+{
+ return WebKit::Platform::current()->highUsageDeltaMB();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/PlatformCursor.h b/Source/WebCore/platform/chromium/PlatformCursor.h
index 328cdb6fb..3d1ebbd06 100644
--- a/Source/WebCore/platform/chromium/PlatformCursor.h
+++ b/Source/WebCore/platform/chromium/PlatformCursor.h
@@ -33,7 +33,7 @@
#include "Image.h"
#include "IntPoint.h"
-#include "RefPtr.h"
+#include <wtf/RefPtr.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/chromium/PlatformSupport.h b/Source/WebCore/platform/chromium/PlatformSupport.h
index 128d2a3e9..baeab05ec 100644
--- a/Source/WebCore/platform/chromium/PlatformSupport.h
+++ b/Source/WebCore/platform/chromium/PlatformSupport.h
@@ -38,12 +38,12 @@
#include "FileSystem.h"
#include "ImageSource.h"
#include "LinkHash.h"
-#include "PassRefPtr.h"
#include "PasteboardPrivate.h"
#include "PluginData.h"
#include <wtf/Forward.h>
#include <wtf/HashSet.h>
+#include <wtf/PassRefPtr.h>
#include <wtf/Vector.h>
typedef struct NPObject NPObject;
@@ -66,12 +66,12 @@ typedef struct HFONT__* HFONT;
namespace WebCore {
+class AsyncFileSystem;
class Clipboard;
class Color;
class Cursor;
class Document;
class Frame;
-class GamepadList;
class GeolocationServiceBridge;
class GeolocationServiceChromium;
class GraphicsContext;
@@ -93,9 +93,6 @@ struct FontRenderStyle;
class PlatformSupport {
public:
- // Cache --------------------------------------------------------------
- static void cacheMetadata(const KURL&, double responseTime, const Vector<char>&);
-
// Clipboard ----------------------------------------------------------
static uint64_t clipboardSequenceNumber(PasteboardPrivate::ClipboardBuffer);
@@ -124,9 +121,6 @@ public:
static void deleteCookie(const Document*, const KURL&, const String& cookieName);
static bool cookiesEnabled(const Document*);
- // DNS ----------------------------------------------------------------
- static void prefetchDNS(const String& hostname);
-
// File ---------------------------------------------------------------
static void revealFolderInOS(const String&);
static bool fileExists(const String&);
@@ -147,6 +141,11 @@ public:
static int readFromFile(PlatformFileHandle, char* data, int length);
static int writeToFile(PlatformFileHandle, const char* data, int length);
+#if ENABLE(FILE_SYSTEM)
+ static String createIsolatedFileSystemName(const String& storageIdentifier, const String& filesystemId);
+ static PassOwnPtr<AsyncFileSystem> createIsolatedFileSystem(const String& originString, const String& filesystemId);
+#endif
+
// Font ---------------------------------------------------------------
#if OS(WINDOWS)
static bool ensureFontLoaded(HFONT);
@@ -185,44 +184,13 @@ public:
// Injects key via keyPath into value. Returns true on success.
static PassRefPtr<SerializedScriptValue> injectIDBKeyIntoSerializedValue(PassRefPtr<IDBKey>, PassRefPtr<SerializedScriptValue>, const String& keyPath);
- // Gamepad -----------------------------------------------------------
- static void sampleGamepads(GamepadList* into);
-
// JavaScript ---------------------------------------------------------
static void notifyJSOutOfMemory(Frame*);
static bool allowScriptDespiteSettings(const KURL& documentURL);
- // Keygen -------------------------------------------------------------
- static String signedPublicKeyAndChallengeString(unsigned keySizeIndex, const String& challenge, const KURL&);
-
- // Language -----------------------------------------------------------
- static String computedDefaultLanguage();
-
// LayoutTestMode -----------------------------------------------------
static bool layoutTestMode();
- // Memory -------------------------------------------------------------
- // Returns the current space allocated for the pagefile, in MB.
- // That is committed size for Windows and virtual memory size for POSIX
- static int memoryUsageMB();
- // Same as above, but always returns actual value, without any caches.
- static int actualMemoryUsageMB();
- // If memory usage is below this threshold, do not bother forcing GC.
- static int lowMemoryUsageMB();
- // If memory usage is above this threshold, force GC more aggressively.
- static int highMemoryUsageMB();
- // Delta of memory usage growth (vs. last actualMemoryUsageMB()) to force GC when memory usage is high.
- static int highUsageDeltaMB();
-
- // MimeType -----------------------------------------------------------
- static bool isSupportedImageMIMEType(const String& mimeType);
- static bool isSupportedJavaScriptMIMEType(const String& mimeType);
- static bool isSupportedNonImageMIMEType(const String& mimeType);
- static String mimeTypeForExtension(const String& fileExtension);
- static String wellKnownMimeTypeForExtension(const String& fileExtension);
- static String mimeTypeFromFile(const String& filePath);
- static String preferredExtensionForMIMEType(const String& mimeType);
-
// Plugin -------------------------------------------------------------
static bool plugins(bool refresh, Vector<PluginInfo>*);
static NPObject* pluginScriptableObject(Widget*);
@@ -232,13 +200,9 @@ public:
static PassRefPtr<Image> loadPlatformImageResource(const char* name);
#if ENABLE(WEB_AUDIO)
- static PassOwnPtr<AudioBus> loadPlatformAudioResource(const char* name, double sampleRate);
static PassOwnPtr<AudioBus> decodeAudioFileData(const char* data, size_t, double sampleRate);
#endif
- // Sandbox ------------------------------------------------------------
- static bool sandboxEnabled();
-
// Screen -------------------------------------------------------------
static int screenHorizontalDPI(Widget*);
static int screenVerticalDPI(Widget*);
@@ -251,16 +215,6 @@ public:
// SharedTimers -------------------------------------------------------
static void setSharedTimerFiredFunction(void (*func)());
static void setSharedTimerFireInterval(double);
- static void stopSharedTimer();
-
- // StatsCounters ------------------------------------------------------
- static void decrementStatsCounter(const char* name);
- static void incrementStatsCounter(const char* name);
- static void histogramCustomCounts(const char* name, int sample, int min, int max, int bucketCount);
- static void histogramEnumeration(const char* name, int sample, int boundaryValue);
-
- // Sudden Termination
- static void suddenTerminationChanged(bool enabled);
// Theming ------------------------------------------------------------
#if OS(WINDOWS)
@@ -435,6 +389,8 @@ public:
static void didStartWorkerRunLoop(WorkerRunLoop*);
static void didStopWorkerRunLoop(WorkerRunLoop*);
+
+ static bool canAccelerate2dCanvas();
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/PopupContainer.cpp b/Source/WebCore/platform/chromium/PopupContainer.cpp
index e231b8506..825716d08 100644
--- a/Source/WebCore/platform/chromium/PopupContainer.cpp
+++ b/Source/WebCore/platform/chromium/PopupContainer.cpp
@@ -134,7 +134,7 @@ IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, co
IntSize targetSize(m_listBox->width() + kBorderSize * 2,
m_listBox->height() + kBorderSize * 2);
- IntRect widgetRect;
+ IntRect widgetRectInScreen;
ChromeClientChromium* chromeClient = chromeClientChromium();
if (chromeClient) {
// If the popup would extend past the bottom of the screen, open upwards
@@ -142,44 +142,44 @@ IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, co
FloatRect screen = screenAvailableRect(m_frameView.get());
// Use popupInitialCoordinate.x() + rightOffset because RTL position
// needs to be considered.
- widgetRect = chromeClient->rootViewToScreen(IntRect(popupInitialCoordinate.x() + rightOffset, popupInitialCoordinate.y(), targetSize.width(), targetSize.height()));
+ widgetRectInScreen = chromeClient->rootViewToScreen(IntRect(popupInitialCoordinate.x() + rightOffset, popupInitialCoordinate.y(), targetSize.width(), targetSize.height()));
// If we have multiple screens and the browser rect is in one screen, we have
// to clip the window width to the screen width.
// When clipping, we also need to set a maximum width for the list box.
FloatRect windowRect = chromeClient->windowRect();
- if (windowRect.x() >= screen.x() && windowRect.maxX() <= screen.maxX() && (widgetRect.x() < screen.x() || widgetRect.maxX() > screen.maxX())) {
+ if (windowRect.x() >= screen.x() && windowRect.maxX() <= screen.maxX() && (widgetRectInScreen.x() < screen.x() || widgetRectInScreen.maxX() > screen.maxX())) {
// First, inverse the popup alignment if it does not fit the screen - this might fix things (or make them better).
- IntRect inverseWidgetRect = chromeClient->rootViewToScreen(IntRect(popupInitialCoordinate.x() + (isRTL ? 0 : rtlOffset), popupInitialCoordinate.y(), targetSize.width(), targetSize.height()));
+ IntRect inverseWidgetRectInScreen = chromeClient->rootViewToScreen(IntRect(popupInitialCoordinate.x() + (isRTL ? 0 : rtlOffset), popupInitialCoordinate.y(), targetSize.width(), targetSize.height()));
IntRect enclosingScreen = enclosingIntRect(screen);
- unsigned originalCutoff = max(enclosingScreen.x() - widgetRect.x(), 0) + max(widgetRect.maxX() - enclosingScreen.maxX(), 0);
- unsigned inverseCutoff = max(enclosingScreen.x() - inverseWidgetRect.x(), 0) + max(inverseWidgetRect.maxX() - enclosingScreen.maxX(), 0);
+ unsigned originalCutoff = max(enclosingScreen.x() - widgetRectInScreen.x(), 0) + max(widgetRectInScreen.maxX() - enclosingScreen.maxX(), 0);
+ unsigned inverseCutoff = max(enclosingScreen.x() - inverseWidgetRectInScreen.x(), 0) + max(inverseWidgetRectInScreen.maxX() - enclosingScreen.maxX(), 0);
// Accept the inverse popup alignment if the trimmed content gets shorter than that in the original alignment case.
if (inverseCutoff < originalCutoff)
- widgetRect = inverseWidgetRect;
-
- if (widgetRect.x() < screen.x()) {
- unsigned widgetRight = widgetRect.maxX();
- widgetRect.setWidth(widgetRect.maxX() - screen.x());
- widgetRect.setX(widgetRight - widgetRect.width());
- listBox()->setMaxWidthAndLayout(max(widgetRect.width() - kBorderSize * 2, 0));
- } else if (widgetRect.maxX() > screen.maxX()) {
- widgetRect.setWidth(screen.maxX() - widgetRect.x());
- listBox()->setMaxWidthAndLayout(max(widgetRect.width() - kBorderSize * 2, 0));
+ widgetRectInScreen = inverseWidgetRectInScreen;
+
+ if (widgetRectInScreen.x() < screen.x()) {
+ unsigned widgetRight = widgetRectInScreen.maxX();
+ widgetRectInScreen.setWidth(widgetRectInScreen.maxX() - screen.x());
+ widgetRectInScreen.setX(widgetRight - widgetRectInScreen.width());
+ listBox()->setMaxWidthAndLayout(max(widgetRectInScreen.width() - kBorderSize * 2, 0));
+ } else if (widgetRectInScreen.maxX() > screen.maxX()) {
+ widgetRectInScreen.setWidth(screen.maxX() - widgetRectInScreen.x());
+ listBox()->setMaxWidthAndLayout(max(widgetRectInScreen.width() - kBorderSize * 2, 0));
}
}
// Calculate Y axis size.
- if (widgetRect.maxY() > static_cast<int>(screen.maxY())) {
- if (widgetRect.y() - widgetRect.height() - targetControlHeight > 0) {
+ if (widgetRectInScreen.maxY() > static_cast<int>(screen.maxY())) {
+ if (widgetRectInScreen.y() - widgetRectInScreen.height() - targetControlHeight > 0) {
// There is enough room to open upwards.
- widgetRect.move(0, -(widgetRect.height() + targetControlHeight));
+ widgetRectInScreen.move(0, -(widgetRectInScreen.height() + targetControlHeight));
} else {
// Figure whether upwards or downwards has more room and set the
// maximum number of items.
- int spaceAbove = widgetRect.y() - targetControlHeight;
- int spaceBelow = screen.maxY() - widgetRect.y();
+ int spaceAbove = widgetRectInScreen.y() - targetControlHeight;
+ int spaceBelow = screen.maxY() - widgetRectInScreen.y();
if (spaceAbove > spaceBelow)
m_listBox->setMaxHeight(spaceAbove);
else
@@ -189,15 +189,16 @@ IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, co
// We don't have to recompute X axis, so we only replace Y axis
// in widgetRect.
IntRect frameInScreen = chromeClient->rootViewToScreen(frameRect());
- widgetRect.setY(frameInScreen.y());
- widgetRect.setHeight(frameInScreen.height());
+ widgetRectInScreen.setY(frameInScreen.y());
+ widgetRectInScreen.setHeight(frameInScreen.height());
// And move upwards if necessary.
if (spaceAbove > spaceBelow)
- widgetRect.move(0, -(widgetRect.height() + targetControlHeight));
+ widgetRectInScreen.move(0, -(widgetRectInScreen.height() + targetControlHeight));
}
}
}
- return widgetRect;
+
+ return widgetRectInScreen;
}
void PopupContainer::showPopup(FrameView* view)
@@ -207,7 +208,7 @@ void PopupContainer::showPopup(FrameView* view)
ChromeClientChromium* chromeClient = chromeClientChromium();
if (chromeClient) {
- IntRect popupRect = frameRect();
+ IntRect popupRect = m_originalFrameRect;
chromeClient->popupOpened(this, layoutAndCalculateWidgetRect(popupRect.height(), popupRect.location()), false);
m_popupOpen = true;
}
@@ -400,32 +401,31 @@ void PopupContainer::showInRect(const IntRect& r, FrameView* v, int index)
location.move(0, r.height());
m_originalFrameRect = IntRect(location, r.size());
- setFrameRect(m_originalFrameRect);
+
+ // Position at (0, 0) since the frameRect().location() is relative to the parent WebWidget.
+ setFrameRect(IntRect(IntPoint(), r.size()));
showPopup(v);
}
-void PopupContainer::refresh(const IntRect& targetControlRect)
+IntRect PopupContainer::refresh(const IntRect& targetControlRect)
{
- IntPoint location = m_frameView->contentsToWindow(targetControlRect.location());
+ listBox()->setBaseWidth(max(m_originalFrameRect.width() - kBorderSize * 2, 0));
+ listBox()->updateFromElement();
+
+ IntPoint locationInWindow = m_frameView->contentsToWindow(targetControlRect.location());
+
// Move it below the select widget.
- location.move(0, targetControlRect.height());
+ locationInWindow.move(0, targetControlRect.height());
- listBox()->setBaseWidth(max(m_originalFrameRect.width() - kBorderSize * 2, 0));
+ IntRect widgetRectInScreen = layoutAndCalculateWidgetRect(targetControlRect.height(), locationInWindow);
- listBox()->updateFromElement();
- // Store the original size to check if we need to request the location.
- IntSize originalSize = size();
- IntRect widgetRect = layoutAndCalculateWidgetRect(targetControlRect.height(), location);
- if (originalSize != widgetRect.size()) {
- ChromeClientChromium* chromeClient = chromeClientChromium();
- if (chromeClient) {
- IntPoint widgetLocation = chromeClient->screenToRootView(widgetRect.location());
- widgetRect.setLocation(widgetLocation);
- setFrameRect(widgetRect);
- }
- }
+ // Reset the size (which can be set to the PopupListBox size in layoutAndGetRTLOffset(), exceeding the available widget rectangle.)
+ if (size() != widgetRectInScreen.size())
+ resize(widgetRectInScreen.size());
invalidate();
+
+ return widgetRectInScreen;
}
inline bool PopupContainer::isRTL() const
diff --git a/Source/WebCore/platform/chromium/PopupContainer.h b/Source/WebCore/platform/chromium/PopupContainer.h
index d776663f4..0c7d1843d 100644
--- a/Source/WebCore/platform/chromium/PopupContainer.h
+++ b/Source/WebCore/platform/chromium/PopupContainer.h
@@ -99,7 +99,7 @@ public:
int selectedIndex() const;
// Refresh the popup values from the PopupMenuClient.
- void refresh(const IntRect& targetControlRect);
+ IntRect refresh(const IntRect& targetControlRect);
// The menu per-item data.
const WTF::Vector<PopupItem*>& popupData() const;
@@ -138,7 +138,13 @@ private:
PopupContainerSettings m_settings;
PopupType m_popupType;
+
+ // This contains the "ideal" dimensions and position for the popup
+ // (PopupContainer's frameRect() location should always be (0, 0), since
+ // it is rendered inside (and relative to) a WebWidget, which should get
+ // the actual popup position through chromeClientChromium()).
IntRect m_originalFrameRect;
+
// Whether the popup is currently open.
bool m_popupOpen;
};
diff --git a/Source/WebCore/platform/chromium/PopupListBox.cpp b/Source/WebCore/platform/chromium/PopupListBox.cpp
index c980ad623..a7527ea93 100644
--- a/Source/WebCore/platform/chromium/PopupListBox.cpp
+++ b/Source/WebCore/platform/chromium/PopupListBox.cpp
@@ -44,6 +44,7 @@
#include "PopupMenuChromium.h"
#include "PopupMenuClient.h"
#include "RenderTheme.h"
+#include "RuntimeEnabledFeatures.h"
#include "ScrollbarTheme.h"
#include "StringTruncator.h"
#include "TextRun.h"
@@ -352,6 +353,7 @@ void PopupListBox::typeAheadFind(const PlatformKeyboardEvent& event)
void PopupListBox::paint(GraphicsContext* gc, const IntRect& rect)
{
+ int scale = m_settings.defaultDeviceScaleFactor;
// adjust coords for scrolled frame
IntRect r = intersection(rect, frameRect());
int tx = x() - scrollX();
@@ -366,6 +368,8 @@ void PopupListBox::paint(GraphicsContext* gc, const IntRect& rect)
// FIXME: Can we optimize scrolling to not require repainting the entire
// window? Should we?
+ if (scale != 1)
+ gc->scale(FloatSize(scale, scale));
for (int i = 0; i < numItems(); ++i)
paintRow(gc, r, i);
@@ -389,6 +393,19 @@ void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowInd
if (!rowRect.intersects(rect))
return;
+ int scale = m_settings.defaultDeviceScaleFactor;
+ // RowRect has already been scaled by the defaultDeviceScaleFactor.
+ // To avoid scaling it twice, we have to unscale it before drawing.
+ if (scale != 1) {
+ // Height and y should both be evenly divisible by scale.
+ ASSERT(!(rowRect.y() % scale));
+ rowRect.setY(rowRect.y() / scale);
+ ASSERT(!(rowRect.height() % scale));
+ rowRect.setHeight(rowRect.height() / scale);
+ rowRect.setWidth(ceilf(static_cast<float>(rowRect.width()) / scale));
+ // rowRect.x is always 0.
+ }
+
PopupMenuStyle style = m_popupClient->itemStyle(rowIndex);
// Paint background
@@ -436,9 +453,9 @@ void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowInd
int textX = 0;
int maxWidth = 0;
if (rightAligned)
- maxWidth = rowRect.width() - max(0, m_popupClient->clientPaddingRight() - m_popupClient->clientInsetRight());
+ maxWidth = rowRect.width() - max<int>(0, m_popupClient->clientPaddingRight() - m_popupClient->clientInsetRight());
else {
- textX = max(0, m_popupClient->clientPaddingLeft() - m_popupClient->clientInsetLeft());
+ textX = max<int>(0, m_popupClient->clientPaddingLeft() - m_popupClient->clientInsetLeft());
maxWidth = rowRect.width() - textX;
}
// Prepare text to be drawn.
@@ -474,7 +491,7 @@ void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowInd
// We are using the left padding as the right padding includes room for the scroll-bar which
// does not show in this case.
- int rightPadding = max(0, m_popupClient->clientPaddingLeft() - m_popupClient->clientInsetLeft());
+ int rightPadding = max<int>(0, m_popupClient->clientPaddingLeft() - m_popupClient->clientInsetLeft());
int remainingWidth = rowRect.width() - rightPadding;
// Draw the icon if applicable.
@@ -502,7 +519,7 @@ void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowInd
TextRun labelTextRun(itemLabel.characters(), itemLabel.length(), false, 0, 0, TextRun::AllowTrailingExpansion, style.textDirection(), style.hasTextDirectionOverride());
if (rightAligned)
- textX = max(0, m_popupClient->clientPaddingLeft() - m_popupClient->clientInsetLeft());
+ textX = max<int>(0, m_popupClient->clientPaddingLeft() - m_popupClient->clientInsetLeft());
else
textX = remainingWidth - itemFont.width(labelTextRun);
@@ -613,15 +630,16 @@ void PopupListBox::setOriginalIndex(int index)
int PopupListBox::getRowHeight(int index)
{
- if (index < 0)
- return PopupMenuChromium::minimumRowHeight();
-
- if (m_popupClient->itemStyle(index).isDisplayNone())
- return PopupMenuChromium::minimumRowHeight();
+ int scale = m_settings.defaultDeviceScaleFactor;
+ int paddingForTouch = 0;
+ if (RuntimeEnabledFeatures::touchEnabled())
+ paddingForTouch = PopupMenuChromium::optionPaddingForTouch();
+ if (index < 0 || m_popupClient->itemStyle(index).isDisplayNone())
+ return PopupMenuChromium::minimumRowHeight() * scale;
// Separator row height is the same size as itself.
if (m_popupClient->itemIsSeparator(index))
- return max(separatorHeight, PopupMenuChromium::minimumRowHeight());
+ return max(separatorHeight, (PopupMenuChromium::minimumRowHeight())) * scale;
String icon = m_popupClient->itemIcon(index);
RefPtr<Image> image(Image::loadPlatformResource(icon.utf8().data()));
@@ -631,7 +649,7 @@ int PopupListBox::getRowHeight(int index)
int linePaddingHeight = m_popupClient->menuStyle().menuType() == PopupMenuStyle::AutofillPopup ? kLinePaddingHeight : 0;
int calculatedRowHeight = max(fontHeight, iconHeight) + linePaddingHeight * 2;
- return max(calculatedRowHeight, PopupMenuChromium::minimumRowHeight());
+ return (max(calculatedRowHeight, PopupMenuChromium::minimumRowHeight()) + paddingForTouch) * scale;
}
IntRect PopupListBox::getRowBounds(int index)
@@ -830,9 +848,9 @@ void PopupListBox::layout()
baseWidth = max(baseWidth, width);
// FIXME: http://b/1210481 We should get the padding of individual option elements.
- paddingWidth = max(paddingWidth,
+ paddingWidth = max<int>(paddingWidth,
m_popupClient->clientPaddingLeft() + m_popupClient->clientPaddingRight());
- lineEndPaddingWidth = max(lineEndPaddingWidth,
+ lineEndPaddingWidth = max<int>(lineEndPaddingWidth,
isRightAligned ? m_popupClient->clientPaddingLeft() : m_popupClient->clientPaddingRight());
}
diff --git a/Source/WebCore/platform/chromium/PopupListBox.h b/Source/WebCore/platform/chromium/PopupListBox.h
index dd2e58ded..b685313cc 100644
--- a/Source/WebCore/platform/chromium/PopupListBox.h
+++ b/Source/WebCore/platform/chromium/PopupListBox.h
@@ -79,6 +79,8 @@ struct PopupContainerSettings {
// Whether we should restrict the width of the PopupListBox or not.
// Autocomplete popups are restricted, combo-boxes (select tags) aren't.
bool restrictWidthOfListBox;
+
+ int defaultDeviceScaleFactor;
};
// A container for the data for each menu item (e.g. represented by <option>
diff --git a/Source/WebCore/platform/chromium/PopupMenuChromium.cpp b/Source/WebCore/platform/chromium/PopupMenuChromium.cpp
index 3b2f2ae9f..62e1008fb 100644
--- a/Source/WebCore/platform/chromium/PopupMenuChromium.cpp
+++ b/Source/WebCore/platform/chromium/PopupMenuChromium.cpp
@@ -31,11 +31,17 @@
#include "config.h"
#include "PopupMenuChromium.h"
+
+#include "Frame.h"
+#include "FrameView.h"
+#include "Page.h"
#include "PopupContainer.h"
+#include "Settings.h"
namespace WebCore {
int PopupMenuChromium::s_minimumRowHeight = 0;
+int PopupMenuChromium::s_optionPaddingForTouch = 30;
// The settings used for the drop down menu.
// This is the delegate used if none is provided.
@@ -62,8 +68,14 @@ PopupMenuChromium::~PopupMenuChromium()
void PopupMenuChromium::show(const IntRect& r, FrameView* v, int index)
{
- if (!p.popup)
- p.popup = PopupContainer::create(client(), PopupContainer::Select, dropDownSettings);
+ if (!p.popup) {
+ PopupContainerSettings popupSettings = dropDownSettings;
+ popupSettings.defaultDeviceScaleFactor =
+ v->frame()->page()->settings()->defaultDeviceScaleFactor();
+ if (!popupSettings.defaultDeviceScaleFactor)
+ popupSettings.defaultDeviceScaleFactor = 1;
+ p.popup = PopupContainer::create(client(), PopupContainer::Select, popupSettings);
+ }
p.popup->showInRect(r, v, index);
}
diff --git a/Source/WebCore/platform/chromium/PopupMenuChromium.h b/Source/WebCore/platform/chromium/PopupMenuChromium.h
index 20be6e153..6e9aa88be 100644
--- a/Source/WebCore/platform/chromium/PopupMenuChromium.h
+++ b/Source/WebCore/platform/chromium/PopupMenuChromium.h
@@ -57,6 +57,9 @@ public:
static int minimumRowHeight() { return s_minimumRowHeight; }
static void setMinimumRowHeight(int minimumRowHeight) { s_minimumRowHeight = minimumRowHeight; }
+ static int optionPaddingForTouch() { return s_optionPaddingForTouch; }
+ static void setOptionPaddingForTouch(int optionPaddingForTouch) { s_optionPaddingForTouch = optionPaddingForTouch; }
+
private:
PopupMenuClient* client() const { return m_popupClient; }
@@ -64,6 +67,7 @@ private:
PopupMenuPrivate p;
static int s_minimumRowHeight;
+ static int s_optionPaddingForTouch;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/PopupMenuPrivate.h b/Source/WebCore/platform/chromium/PopupMenuPrivate.h
index fb8f85072..e81b3dab6 100644
--- a/Source/WebCore/platform/chromium/PopupMenuPrivate.h
+++ b/Source/WebCore/platform/chromium/PopupMenuPrivate.h
@@ -31,7 +31,7 @@
#ifndef PopupMenuPrivate_h
#define PopupMenuPrivate_h
-#include "RefPtr.h"
+#include <wtf/RefPtr.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/chromium/SSLKeyGeneratorChromium.cpp b/Source/WebCore/platform/chromium/SSLKeyGeneratorChromium.cpp
index 406af1ea7..defae9935 100644
--- a/Source/WebCore/platform/chromium/SSLKeyGeneratorChromium.cpp
+++ b/Source/WebCore/platform/chromium/SSLKeyGeneratorChromium.cpp
@@ -31,9 +31,12 @@
#include "config.h"
#include "SSLKeyGenerator.h"
-#include "PlatformSupport.h"
#include "PlatformString.h"
+#include <public/Platform.h>
+#include <public/WebString.h>
+#include <public/WebURL.h>
+
namespace WebCore {
// These are defined in webkit/api/src/LocalizedStrings.cpp.
@@ -49,7 +52,9 @@ void getSupportedKeySizes(Vector<String>& sizes)
String signedPublicKeyAndChallengeString(unsigned keySizeIndex, const String& challengeString, const KURL& url)
{
- return PlatformSupport::signedPublicKeyAndChallengeString(keySizeIndex, challengeString, url);
+ return WebKit::Platform::current()->signedPublicKeyAndChallengeString(keySizeIndex,
+ WebKit::WebString(challengeString),
+ WebKit::WebURL(url));
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm b/Source/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm
index d02b42125..acfbc1d97 100644
--- a/Source/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm
+++ b/Source/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm
@@ -129,6 +129,7 @@ bool ScrollbarThemeChromiumMac::paint(ScrollbarThemeClient* scrollbar, GraphicsC
CGFloat oldKnobAlpha = 0;
CGFloat oldTrackAlpha = 0;
+ BOOL oldIsExpanded = NO;
bool hasTickmarks = tickmarks.size() > 0 && scrollbar->orientation() == VerticalScrollbar;
ScrollbarPainter scrollbarPainter = painterForScrollbar(scrollbar);
if (hasTickmarks) {
@@ -136,6 +137,10 @@ bool ScrollbarThemeChromiumMac::paint(ScrollbarThemeClient* scrollbar, GraphicsC
[scrollbarPainter setKnobAlpha:1.0];
oldTrackAlpha = [scrollbarPainter trackAlpha];
[scrollbarPainter setTrackAlpha:1.0];
+ if ([scrollbarPainter respondsToSelector:@selector(setExpanded:)]) {
+ oldIsExpanded = [scrollbarPainter isExpanded];
+ [scrollbarPainter setExpanded:YES];
+ }
}
GraphicsContextStateSaver stateSaver(*context);
@@ -168,6 +173,8 @@ bool ScrollbarThemeChromiumMac::paint(ScrollbarThemeClient* scrollbar, GraphicsC
if (hasTickmarks) {
[scrollbarPainter setKnobAlpha:oldKnobAlpha];
[scrollbarPainter setTrackAlpha:oldTrackAlpha];
+ if ([scrollbarPainter respondsToSelector:@selector(setExpanded:)])
+ [scrollbarPainter setExpanded:oldIsExpanded];
}
return true;
diff --git a/Source/WebCore/platform/chromium/SharedTimerChromium.cpp b/Source/WebCore/platform/chromium/SharedTimerChromium.cpp
index 8d7c766d3..b3af4e5a4 100644
--- a/Source/WebCore/platform/chromium/SharedTimerChromium.cpp
+++ b/Source/WebCore/platform/chromium/SharedTimerChromium.cpp
@@ -28,6 +28,8 @@
#include "PlatformSupport.h"
+#include <public/Platform.h>
+
namespace WebCore {
void setSharedTimerFiredFunction(void (*f)())
@@ -42,7 +44,7 @@ void setSharedTimerFireInterval(double fireTime)
void stopSharedTimer()
{
- PlatformSupport::stopSharedTimer();
+ WebKit::Platform::current()->stopSharedTimer();
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/StatsCounterChromium.cpp b/Source/WebCore/platform/chromium/StatsCounterChromium.cpp
new file mode 100644
index 000000000..dec4d773a
--- /dev/null
+++ b/Source/WebCore/platform/chromium/StatsCounterChromium.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "StatsCounter.h"
+
+#include <public/Platform.h>
+
+namespace WebCore {
+
+void StatsCounter::incrementStatsCounter(const char* counterName)
+{
+ WebKit::Platform::current()->incrementStatsCounter(counterName);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/SuddenTerminationChromium.cpp b/Source/WebCore/platform/chromium/SuddenTerminationChromium.cpp
index cc77c89e4..dce7892a8 100644
--- a/Source/WebCore/platform/chromium/SuddenTerminationChromium.cpp
+++ b/Source/WebCore/platform/chromium/SuddenTerminationChromium.cpp
@@ -31,18 +31,18 @@
#include "config.h"
#include "SuddenTermination.h"
-#include "PlatformSupport.h"
+#include <public/Platform.h>
namespace WebCore {
void disableSuddenTermination()
{
- PlatformSupport::suddenTerminationChanged(false);
+ WebKit::Platform::current()->suddenTerminationChanged(false);
}
void enableSuddenTermination()
{
- PlatformSupport::suddenTerminationChanged(true);
+ WebKit::Platform::current()->suddenTerminationChanged(true);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/ThemeChromiumMac.mm b/Source/WebCore/platform/chromium/ThemeChromiumMac.mm
index 3911a51c2..69cb74a4c 100644
--- a/Source/WebCore/platform/chromium/ThemeChromiumMac.mm
+++ b/Source/WebCore/platform/chromium/ThemeChromiumMac.mm
@@ -500,14 +500,6 @@ static const IntSize* buttonSizes()
return sizes;
}
-#if ENABLE(DATALIST)
-static const IntSize* listButtonSizes()
-{
- static const IntSize sizes[3] = { IntSize(21, 21), IntSize(19, 18), IntSize(17, 16) };
- return sizes;
-}
-#endif
-
static const int* buttonMargins(NSControlSize controlSize)
{
static const int margins[3][4] =
@@ -531,12 +523,6 @@ static void setupButtonCell(NSButtonCell *&buttonCell, ControlPart part, Control
// Set the control size based off the rectangle we're painting into.
const IntSize* sizes = buttonSizes();
-#if ENABLE(DATALIST)
- if (part == ListButtonPart) {
- [buttonCell setBezelStyle:NSRoundedDisclosureBezelStyle];
- sizes = listButtonSizes();
- } else
-#endif
if (part == SquareButtonPart || zoomedRect.height() > buttonSizes()[NSRegularControlSize].height() * zoomFactor) {
// Use the square button
if ([buttonCell bezelStyle] != NSShadowlessSquareBezelStyle)
@@ -567,11 +553,7 @@ static void paintButton(ControlPart part, ControlStates states, GraphicsContext*
LocalCurrentGraphicsContext localContext(context);
NSControlSize controlSize = [buttonCell controlSize];
-#if ENABLE(DATALIST)
- IntSize zoomedSize = (part == ListButtonPart ? listButtonSizes() : buttonSizes())[controlSize];
-#else
IntSize zoomedSize = buttonSizes()[controlSize];
-#endif
zoomedSize.setWidth(zoomedRect.width()); // Buttons don't ever constrain width, so the zoomed width can just be honored.
zoomedSize.setHeight(zoomedSize.height() * zoomFactor);
IntRect inflatedRect = zoomedRect;
@@ -707,10 +689,6 @@ LengthSize ThemeChromiumMac::controlSize(ControlPart part, const Font& font, con
case PushButtonPart:
// Height is reset to auto so that specified heights can be ignored.
return sizeFromFont(font, LengthSize(zoomedSize.width(), Length()), zoomFactor, buttonSizes());
-#if ENABLE(DATALIST)
- case ListButtonPart:
- return sizeFromFont(font, LengthSize(zoomedSize.width(), Length()), zoomFactor, listButtonSizes());
-#endif
case InnerSpinButtonPart:
if (!zoomedSize.width().isIntrinsicOrAuto() && !zoomedSize.height().isIntrinsicOrAuto())
return zoomedSize;
@@ -726,7 +704,6 @@ LengthSize ThemeChromiumMac::minimumControlSize(ControlPart part, const Font& fo
case SquareButtonPart:
case DefaultButtonPart:
case ButtonPart:
- case ListButtonPart:
return LengthSize(Length(0, Fixed), Length(static_cast<int>(15 * zoomFactor), Fixed));
case InnerSpinButtonPart: {
IntSize base = stepperSizes()[NSMiniControlSize];
@@ -744,7 +721,6 @@ LengthBox ThemeChromiumMac::controlBorder(ControlPart part, const Font& font, co
case SquareButtonPart:
case DefaultButtonPart:
case ButtonPart:
- case ListButtonPart:
return LengthBox(0, zoomedBox.right().value(), 0, zoomedBox.left().value());
default:
return Theme::controlBorder(part, font, zoomedBox, zoomFactor);
@@ -837,7 +813,6 @@ void ThemeChromiumMac::paint(ControlPart part, ControlStates states, GraphicsCon
case DefaultButtonPart:
case ButtonPart:
case SquareButtonPart:
- case ListButtonPart:
paintButton(part, states, context, zoomedRect, zoomFactor, scrollView);
break;
case InnerSpinButtonPart:
diff --git a/Source/WebCore/platform/chromium/TraceEvent.h b/Source/WebCore/platform/chromium/TraceEvent.h
index 5bb600fb3..206d941f1 100644
--- a/Source/WebCore/platform/chromium/TraceEvent.h
+++ b/Source/WebCore/platform/chromium/TraceEvent.h
@@ -38,7 +38,7 @@
// doSomethingCostly()
// TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly")
// Note: our tools can't always determine the correct BEGIN/END pairs unless
-// these are used in the same scope. Use START/FINISH macros if you need them
+// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you need them
// to be in separate scopes.
//
// A common use case is to trace entire function scopes. This
@@ -58,28 +58,28 @@
// The trace system will automatically add to this information the
// current process id, thread id, and a timestamp in microseconds.
//
-// To trace an asynchronous procedure such as an IPC send/receive, use START and
-// FINISH:
+// To trace an asynchronous procedure such as an IPC send/receive, use ASYNC_BEGIN and
+// ASYNC_END:
// [single threaded sender code]
// static int send_count = 0;
// ++send_count;
-// TRACE_EVENT_START0("ipc", "message", send_count);
+// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count);
// Send(new MyMessage(send_count));
// [receive code]
// void OnMyMessage(send_count) {
-// TRACE_EVENT_FINISH0("ipc", "message", send_count);
+// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count);
// }
-// The third parameter is a unique ID to match START/FINISH pairs.
-// START and FINISH can occur on any thread of any traced process. Pointers can
+// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs.
+// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process. Pointers can
// be used for the ID parameter, and they will be mangled internally so that
// the same pointer on two different processes will not match. For example:
// class MyTracedClass {
// public:
// MyTracedClass() {
-// TRACE_EVENT_START0("category", "MyTracedClass", this);
+// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this);
// }
// ~MyTracedClass() {
-// TRACE_EVENT_FINISH0("category", "MyTracedClass", this);
+// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this);
// }
// }
//
@@ -163,9 +163,9 @@
#ifndef TraceEvent_h
#define TraceEvent_h
-#include "DynamicAnnotations.h"
#include "PlatformSupport.h"
+#include <wtf/DynamicAnnotations.h>
#include <wtf/text/CString.h>
// Issues begin trace event here and end trace event when the current scope ends.
@@ -361,62 +361,91 @@
value1_name, static_cast<int>(value1_val), \
value2_name, static_cast<int>(value2_val))
-// Records a single START event called "name" immediately, with 0, 1 or 2
+// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2
// associated arguments. If the category is not enabled, then this
// does nothing.
// - category and name strings must have application lifetime (statics or
// literals). They may not include " chars.
-// - |id| is used to match the START event with the FINISH event. It must either
-// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits
-// will be xored with a hash of the process ID so that the same pointer on
-// two different processes will not collide.
-#define TRACE_EVENT_START0(category, name, id) \
- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_START, \
+// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. ASYNC
+// events are considered to match if their category, name and id values all
+// match. |id| must either be a pointer or an integer value up to 64 bits. If
+// it's a pointer, the bits will be xored with a hash of the process ID so
+// that the same pointer on two different processes will not collide.
+// An asynchronous operation can consist of multiple phases. The first phase is
+// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the
+// ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END.
+// An async operation can span threads and processes, but all events in that
+// operation must use the same |name| and |id|. Each event can have its own
+// args.
+#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
category, name, id, TRACE_EVENT_FLAG_NONE)
-#define TRACE_EVENT_START1(category, name, id, arg1_name, arg1_val) \
- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_START, \
+#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
-#define TRACE_EVENT_START2(category, name, id, arg1_name, arg1_val, \
+#define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
arg2_name, arg2_val) \
- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_START, \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
category, name, id, TRACE_EVENT_FLAG_NONE, \
arg1_name, arg1_val, arg2_name, arg2_val)
-#define TRACE_EVENT_COPY_START0(category, name, id) \
- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_START, \
+#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
category, name, id, TRACE_EVENT_FLAG_COPY)
-#define TRACE_EVENT_COPY_START1(category, name, id, arg1_name, arg1_val) \
- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_START, \
+#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
category, name, id, TRACE_EVENT_FLAG_COPY, \
arg1_name, arg1_val)
-#define TRACE_EVENT_COPY_START2(category, name, id, arg1_name, arg1_val, \
+#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
arg2_name, arg2_val) \
- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_START, \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
category, name, id, TRACE_EVENT_FLAG_COPY, \
arg1_name, arg1_val, arg2_name, arg2_val)
-// Records a single FINISH event for "name" immediately. If the category
+// Records a single ASYNC_STEP event for |step| immediately. If the category
+// is not enabled, then this does nothing. The |name| and |id| must match the
+// ASYNC_BEGIN event above. The |step| param identifies this step within the
+// async event. This should be called at the beginning of the next phase of an
+// asynchronous operation.
+#define TRACE_EVENT_ASYNC_BEGIN_STEP0(category, name, id, step) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, "step", step)
+#define TRACE_EVENT_ASYNC_BEGIN_STEP1(category, name, id, step, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \
+ arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN_STEP0(category, name, id, step) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, "step", step)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN_STEP1(category, name, id, step, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, "step", step, \
+ arg1_name, arg1_val)
+
+// Records a single ASYNC_END event for "name" immediately. If the category
// is not enabled, then this does nothing.
-#define TRACE_EVENT_FINISH0(category, name, id) \
- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FINISH, \
+#define TRACE_EVENT_ASYNC_END0(category, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
category, name, id, TRACE_EVENT_FLAG_NONE)
-#define TRACE_EVENT_FINISH1(category, name, id, arg1_name, arg1_val) \
- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FINISH, \
+#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
-#define TRACE_EVENT_FINISH2(category, name, id, arg1_name, arg1_val, \
+#define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
arg2_name, arg2_val) \
- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FINISH, \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
category, name, id, TRACE_EVENT_FLAG_NONE, \
arg1_name, arg1_val, arg2_name, arg2_val)
-#define TRACE_EVENT_COPY_FINISH0(category, name, id) \
- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FINISH, \
+#define TRACE_EVENT_COPY_ASYNC_END0(category, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
category, name, id, TRACE_EVENT_FLAG_COPY)
-#define TRACE_EVENT_COPY_FINISH1(category, name, id, arg1_name, arg1_val) \
- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FINISH, \
+#define TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
category, name, id, TRACE_EVENT_FLAG_COPY, \
arg1_name, arg1_val)
-#define TRACE_EVENT_COPY_FINISH2(category, name, id, arg1_name, arg1_val, \
+#define TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
arg2_name, arg2_val) \
- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FINISH, \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
category, name, id, TRACE_EVENT_FLAG_COPY, \
arg1_name, arg1_val, arg2_name, arg2_val)
@@ -481,12 +510,14 @@
#define INTERNAL_TRACE_EVENT_ADD(ignore) ((void)0)
#else
#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...) \
- INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
- if (*INTERNALTRACEEVENTUID(catstatic)) { \
- WebCore::TraceEvent::addTraceEvent( \
- phase, INTERNALTRACEEVENTUID(catstatic), name, \
- WebCore::TraceEvent::noEventId, flags, ##__VA_ARGS__); \
- }
+ do { \
+ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
+ if (*INTERNALTRACEEVENTUID(catstatic)) { \
+ WebCore::TraceEvent::addTraceEvent( \
+ phase, INTERNALTRACEEVENTUID(catstatic), name, \
+ WebCore::TraceEvent::noEventId, flags, ##__VA_ARGS__); \
+ } \
+ } while (0)
#endif
// Implementation detail: internal macro to create static category and add begin
@@ -541,16 +572,18 @@
#else
#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, flags, \
...) \
- INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
- if (*INTERNALTRACEEVENTUID(catstatic)) { \
- unsigned char traceEventFlags = flags | TRACE_EVENT_FLAG_HAS_ID; \
- WebCore::TraceEvent::TraceID traceEventTraceID( \
- id, &traceEventFlags); \
- WebCore::TraceEvent::addTraceEvent( \
- phase, INTERNALTRACEEVENTUID(catstatic), \
- name, traceEventTraceID.data(), traceEventFlags, \
- ##__VA_ARGS__); \
- }
+ do { \
+ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
+ if (*INTERNALTRACEEVENTUID(catstatic)) { \
+ unsigned char traceEventFlags = flags | TRACE_EVENT_FLAG_HAS_ID; \
+ WebCore::TraceEvent::TraceID traceEventTraceID( \
+ id, &traceEventFlags); \
+ WebCore::TraceEvent::addTraceEvent( \
+ phase, INTERNALTRACEEVENTUID(catstatic), \
+ name, traceEventTraceID.data(), traceEventFlags, \
+ ##__VA_ARGS__); \
+ } \
+ } while (0)
#endif
// Notes regarding the following definitions:
@@ -562,8 +595,9 @@
#define TRACE_EVENT_PHASE_BEGIN ('B')
#define TRACE_EVENT_PHASE_END ('E')
#define TRACE_EVENT_PHASE_INSTANT ('I')
-#define TRACE_EVENT_PHASE_START ('S')
-#define TRACE_EVENT_PHASE_FINISH ('F')
+#define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S')
+#define TRACE_EVENT_PHASE_ASYNC_STEP ('T')
+#define TRACE_EVENT_PHASE_ASYNC_END ('F')
#define TRACE_EVENT_PHASE_METADATA ('M')
#define TRACE_EVENT_PHASE_COUNTER ('C')
diff --git a/Source/WebCore/platform/chromium/WidgetChromium.cpp b/Source/WebCore/platform/chromium/WidgetChromium.cpp
index ac522448f..018e7c5a5 100644
--- a/Source/WebCore/platform/chromium/WidgetChromium.cpp
+++ b/Source/WebCore/platform/chromium/WidgetChromium.cpp
@@ -31,7 +31,7 @@
#include "config.h"
#include "Widget.h"
-#include "Assertions.h"
+#include <wtf/Assertions.h>
#include "HostWindow.h"
#include "ScrollView.h"
diff --git a/Source/WebCore/platform/chromium/support/WebAudioBus.cpp b/Source/WebCore/platform/chromium/support/WebAudioBus.cpp
new file mode 100644
index 000000000..b373e0982
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebAudioBus.cpp
@@ -0,0 +1,132 @@
+/*
+ * 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 INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include <public/WebAudioBus.h>
+
+#if ENABLE(WEB_AUDIO)
+#include "AudioBus.h"
+#else
+namespace WebCore {
+class AudioBus {
+};
+} // namespace WebCore
+#endif
+
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+class WebAudioBusPrivate : public AudioBus {
+};
+
+void WebAudioBus::initialize(unsigned numberOfChannels, size_t length, double sampleRate)
+{
+#if ENABLE(WEB_AUDIO)
+ AudioBus* audioBus = new AudioBus(numberOfChannels, length);
+ audioBus->setSampleRate(sampleRate);
+
+ if (m_private)
+ delete m_private;
+ m_private = static_cast<WebAudioBusPrivate*>(audioBus);
+#else
+ ASSERT_NOT_REACHED();
+#endif
+}
+
+void WebAudioBus::reset()
+{
+#if ENABLE(WEB_AUDIO)
+ delete m_private;
+ m_private = 0;
+#else
+ ASSERT_NOT_REACHED();
+#endif
+}
+
+unsigned WebAudioBus::numberOfChannels() const
+{
+#if ENABLE(WEB_AUDIO)
+ if (!m_private)
+ return 0;
+ return m_private->numberOfChannels();
+#else
+ ASSERT_NOT_REACHED();
+ return 0;
+#endif
+}
+
+size_t WebAudioBus::length() const
+{
+#if ENABLE(WEB_AUDIO)
+ if (!m_private)
+ return 0;
+ return m_private->length();
+#else
+ ASSERT_NOT_REACHED();
+ return 0;
+#endif
+}
+
+double WebAudioBus::sampleRate() const
+{
+#if ENABLE(WEB_AUDIO)
+ if (!m_private)
+ return 0;
+ return m_private->sampleRate();
+#else
+ ASSERT_NOT_REACHED();
+ return 0;
+#endif
+}
+
+float* WebAudioBus::channelData(unsigned channelIndex)
+{
+#if ENABLE(WEB_AUDIO)
+ if (!m_private)
+ return 0;
+ ASSERT(channelIndex < numberOfChannels());
+ return m_private->channel(channelIndex)->mutableData();
+#else
+ ASSERT_NOT_REACHED();
+ return 0;
+#endif
+}
+
+PassOwnPtr<AudioBus> WebAudioBus::release()
+{
+#if ENABLE(WEB_AUDIO)
+ OwnPtr<AudioBus> audioBus(adoptPtr(static_cast<AudioBus*>(m_private)));
+ m_private = 0;
+ return audioBus.release();
+#else
+ ASSERT_NOT_REACHED();
+ return nullptr;
+#endif
+}
+
+} // namespace WebKit
diff --git a/Source/WebCore/platform/chromium/support/WebData.cpp b/Source/WebCore/platform/chromium/support/WebData.cpp
new file mode 100644
index 000000000..c4c4f69aa
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebData.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include <public/WebData.h>
+
+#include "SharedBuffer.h"
+
+using namespace WebCore;
+
+namespace WebKit {
+
+class WebDataPrivate : public SharedBuffer {
+};
+
+void WebData::reset()
+{
+ if (m_private) {
+ m_private->deref();
+ m_private = 0;
+ }
+}
+
+void WebData::assign(const WebData& other)
+{
+ WebDataPrivate* p = const_cast<WebDataPrivate*>(other.m_private);
+ if (p)
+ p->ref();
+ assign(p);
+}
+
+void WebData::assign(const char* data, size_t size)
+{
+ assign(static_cast<WebDataPrivate*>(
+ SharedBuffer::create(data, size).leakRef()));
+}
+
+size_t WebData::size() const
+{
+ if (!m_private)
+ return 0;
+ return const_cast<WebDataPrivate*>(m_private)->size();
+}
+
+const char* WebData::data() const
+{
+ if (!m_private)
+ return 0;
+ return const_cast<WebDataPrivate*>(m_private)->data();
+}
+
+WebData::WebData(const PassRefPtr<SharedBuffer>& buffer)
+ : m_private(static_cast<WebDataPrivate*>(buffer.leakRef()))
+{
+}
+
+WebData& WebData::operator=(const PassRefPtr<SharedBuffer>& buffer)
+{
+ assign(static_cast<WebDataPrivate*>(buffer.leakRef()));
+ return *this;
+}
+
+WebData::operator PassRefPtr<SharedBuffer>() const
+{
+ return PassRefPtr<SharedBuffer>(const_cast<WebDataPrivate*>(m_private));
+}
+
+void WebData::assign(WebDataPrivate* p)
+{
+ // p is already ref'd for us by the caller
+ if (m_private)
+ m_private->deref();
+ m_private = p;
+}
+
+} // namespace WebKit
diff --git a/Source/WebCore/platform/chromium/support/WebFilterOperations.cpp b/Source/WebCore/platform/chromium/support/WebFilterOperations.cpp
new file mode 100644
index 000000000..d60d9287a
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebFilterOperations.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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"
+
+#include "FilterOperations.h"
+
+#include <public/WebFilterOperation.h>
+#include <public/WebFilterOperations.h>
+#include <wtf/RefPtr.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+void WebFilterOperations::initialize()
+{
+ m_private.reset(new FilterOperations());
+}
+
+void WebFilterOperations::append(const WebFilterOperation& filter)
+{
+ switch (filter.type) {
+ case WebFilterOperation::FilterTypeBasicColorMatrix: {
+ const WebBasicColorMatrixFilterOperation& colorFilter = static_cast<const WebBasicColorMatrixFilterOperation&>(filter);
+ m_private->operations().append(BasicColorMatrixFilterOperation::create(colorFilter.amount, static_cast<FilterOperation::OperationType>(colorFilter.subtype)));
+ break;
+ }
+ case WebFilterOperation::FilterTypeBasicComponentTransfer: {
+ const WebBasicComponentTransferFilterOperation& componentFilter = static_cast<const WebBasicComponentTransferFilterOperation&>(filter);
+ m_private->operations().append(BasicComponentTransferFilterOperation::create(componentFilter.amount, static_cast<FilterOperation::OperationType>(componentFilter.subtype)));
+ break;
+ }
+ case WebFilterOperation::FilterTypeBlur: {
+ const WebBlurFilterOperation& blurFilter = static_cast<const WebBlurFilterOperation&>(filter);
+ m_private->operations().append(BlurFilterOperation::create(Length(blurFilter.pixelRadius, Fixed), FilterOperation::BLUR));
+ break;
+ }
+ case WebFilterOperation::FilterTypeDropShadow: {
+ const WebDropShadowFilterOperation& shadowFilter = static_cast<const WebDropShadowFilterOperation&>(filter);
+ m_private->operations().append(DropShadowFilterOperation::create(IntPoint(shadowFilter.x, shadowFilter.y), shadowFilter.stdDeviation, shadowFilter.color, FilterOperation::DROP_SHADOW));
+ break;
+ }
+ }
+}
+
+void WebFilterOperations::clear()
+{
+ m_private->operations().clear();
+}
+
+const FilterOperations& WebFilterOperations::toFilterOperations() const
+{
+ return *m_private.get();
+}
+
+} // namespace WebKit
diff --git a/Source/WebCore/platform/chromium/support/WebHTTPBody.cpp b/Source/WebCore/platform/chromium/support/WebHTTPBody.cpp
new file mode 100644
index 000000000..d183af123
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebHTTPBody.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include <public/WebHTTPBody.h>
+
+#include "FormData.h"
+
+using namespace WebCore;
+
+namespace WebKit {
+
+class WebHTTPBodyPrivate : public FormData {
+};
+
+void WebHTTPBody::initialize()
+{
+ assign(static_cast<WebHTTPBodyPrivate*>(FormData::create().leakRef()));
+}
+
+void WebHTTPBody::reset()
+{
+ assign(0);
+}
+
+void WebHTTPBody::assign(const WebHTTPBody& other)
+{
+ WebHTTPBodyPrivate* p = const_cast<WebHTTPBodyPrivate*>(other.m_private);
+ if (p)
+ p->ref();
+ assign(p);
+}
+
+size_t WebHTTPBody::elementCount() const
+{
+ ASSERT(!isNull());
+ return m_private->elements().size();
+}
+
+bool WebHTTPBody::elementAt(size_t index, Element& result) const
+{
+ ASSERT(!isNull());
+
+ if (index >= m_private->elements().size())
+ return false;
+
+ const FormDataElement& element = m_private->elements()[index];
+
+ result.data.reset();
+ result.filePath.reset();
+ result.fileStart = 0;
+ result.fileLength = 0;
+ result.modificationTime = 0.0;
+ result.blobURL = KURL();
+
+ switch (element.m_type) {
+ case FormDataElement::data:
+ result.type = Element::TypeData;
+ result.data.assign(element.m_data.data(), element.m_data.size());
+ break;
+ case FormDataElement::encodedFile:
+ result.type = Element::TypeFile;
+ result.filePath = element.m_filename;
+#if ENABLE(BLOB)
+ result.fileStart = element.m_fileStart;
+ result.fileLength = element.m_fileLength;
+ result.modificationTime = element.m_expectedFileModificationTime;
+#endif
+ break;
+#if ENABLE(BLOB)
+ case FormDataElement::encodedBlob:
+ result.type = Element::TypeBlob;
+ result.blobURL = element.m_blobURL;
+ break;
+#endif
+ default:
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+
+ return true;
+}
+
+void WebHTTPBody::appendData(const WebData& data)
+{
+ ensureMutable();
+ // FIXME: FormDataElement::m_data should be a SharedBuffer<char>. Then we
+ // could avoid this buffer copy.
+ m_private->appendData(data.data(), data.size());
+}
+
+void WebHTTPBody::appendFile(const WebString& filePath)
+{
+ ensureMutable();
+ m_private->appendFile(filePath);
+}
+
+void WebHTTPBody::appendFileRange(const WebString& filePath, long long fileStart, long long fileLength, double modificationTime)
+{
+#if ENABLE(BLOB)
+ ensureMutable();
+ m_private->appendFileRange(filePath, fileStart, fileLength, modificationTime);
+#endif
+}
+
+void WebHTTPBody::appendBlob(const WebURL& blobURL)
+{
+#if ENABLE(BLOB)
+ ensureMutable();
+ m_private->appendBlob(blobURL);
+#endif
+}
+
+long long WebHTTPBody::identifier() const
+{
+ ASSERT(!isNull());
+ return m_private->identifier();
+}
+
+void WebHTTPBody::setIdentifier(long long identifier)
+{
+ ensureMutable();
+ return m_private->setIdentifier(identifier);
+}
+
+bool WebHTTPBody::containsPasswordData() const
+{
+ return m_private->containsPasswordData();
+}
+
+void WebHTTPBody::setContainsPasswordData(bool containsPasswordData)
+{
+ m_private->setContainsPasswordData(containsPasswordData);
+}
+
+WebHTTPBody::WebHTTPBody(const PassRefPtr<FormData>& data)
+ : m_private(static_cast<WebHTTPBodyPrivate*>(data.leakRef()))
+{
+}
+
+WebHTTPBody& WebHTTPBody::operator=(const PassRefPtr<FormData>& data)
+{
+ assign(static_cast<WebHTTPBodyPrivate*>(data.leakRef()));
+ return *this;
+}
+
+WebHTTPBody::operator PassRefPtr<FormData>() const
+{
+ return m_private;
+}
+
+void WebHTTPBody::assign(WebHTTPBodyPrivate* p)
+{
+ // p is already ref'd for us by the caller
+ if (m_private)
+ m_private->deref();
+ m_private = p;
+}
+
+void WebHTTPBody::ensureMutable()
+{
+ ASSERT(!isNull());
+ if (!m_private->hasOneRef())
+ assign(static_cast<WebHTTPBodyPrivate*>(m_private->copy().leakRef()));
+}
+
+} // namespace WebKit
diff --git a/Source/WebCore/platform/chromium/support/WebHTTPLoadInfo.cpp b/Source/WebCore/platform/chromium/support/WebHTTPLoadInfo.cpp
new file mode 100644
index 000000000..d7d57f212
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebHTTPLoadInfo.cpp
@@ -0,0 +1,147 @@
+/*
+ * 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include <public/WebHTTPLoadInfo.h>
+
+#include "ResourceLoadInfo.h"
+#include "ResourceResponse.h"
+#include <public/WebHTTPHeaderVisitor.h>
+#include <public/WebString.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+void WebHTTPLoadInfo::initialize()
+{
+ m_private = adoptRef(new ResourceLoadInfo());
+}
+
+void WebHTTPLoadInfo::reset()
+{
+ m_private.reset();
+}
+
+void WebHTTPLoadInfo::assign(const WebHTTPLoadInfo& r)
+{
+ m_private = r.m_private;
+}
+
+WebHTTPLoadInfo::WebHTTPLoadInfo(WTF::PassRefPtr<WebCore::ResourceLoadInfo> value)
+{
+ m_private = value;
+}
+
+WebHTTPLoadInfo::operator WTF::PassRefPtr<WebCore::ResourceLoadInfo>() const
+{
+ return m_private.get();
+}
+
+int WebHTTPLoadInfo::httpStatusCode() const
+{
+ ASSERT(!m_private.isNull());
+ return m_private->httpStatusCode;
+}
+
+void WebHTTPLoadInfo::setHTTPStatusCode(int statusCode)
+{
+ ASSERT(!m_private.isNull());
+ m_private->httpStatusCode = statusCode;
+}
+
+WebString WebHTTPLoadInfo::httpStatusText() const
+{
+ ASSERT(!m_private.isNull());
+ return m_private->httpStatusText;
+}
+
+void WebHTTPLoadInfo::setHTTPStatusText(const WebString& statusText)
+{
+ ASSERT(!m_private.isNull());
+ m_private->httpStatusText = statusText;
+}
+
+long long WebHTTPLoadInfo::encodedDataLength() const
+{
+ ASSERT(!m_private.isNull());
+ return m_private->encodedDataLength;
+}
+
+void WebHTTPLoadInfo::setEncodedDataLength(long long encodedDataLength)
+{
+ ASSERT(!m_private.isNull());
+ m_private->encodedDataLength = encodedDataLength;
+}
+
+static void addHeader(HTTPHeaderMap* map, const WebString& name, const WebString& value)
+{
+ HTTPHeaderMap::AddResult result = map->add(name, value);
+ if (!result.isNewEntry)
+ result.iterator->second += ", " + String(value);
+}
+
+void WebHTTPLoadInfo::addRequestHeader(const WebString& name, const WebString& value)
+{
+ ASSERT(!m_private.isNull());
+ addHeader(&m_private->requestHeaders, name, value);
+}
+
+void WebHTTPLoadInfo::addResponseHeader(const WebString& name, const WebString& value)
+{
+ ASSERT(!m_private.isNull());
+ addHeader(&m_private->responseHeaders, name, value);
+}
+
+WebString WebHTTPLoadInfo::requestHeadersText() const
+{
+ ASSERT(!m_private.isNull());
+ return m_private->requestHeadersText;
+}
+
+void WebHTTPLoadInfo::setRequestHeadersText(const WebString& headersText)
+{
+ ASSERT(!m_private.isNull());
+ m_private->requestHeadersText = headersText;
+}
+
+WebString WebHTTPLoadInfo::responseHeadersText() const
+{
+ ASSERT(!m_private.isNull());
+ return m_private->responseHeadersText;
+}
+
+void WebHTTPLoadInfo::setResponseHeadersText(const WebString& headersText)
+{
+ ASSERT(!m_private.isNull());
+ m_private->responseHeadersText = headersText;
+}
+
+} // namespace WebKit
diff --git a/Source/WebCore/platform/chromium/support/WebICECandidateDescriptor.cpp b/Source/WebCore/platform/chromium/support/WebICECandidateDescriptor.cpp
new file mode 100644
index 000000000..04b87b440
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebICECandidateDescriptor.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include <public/WebICECandidateDescriptor.h>
+
+#include "IceCandidateDescriptor.h"
+#include <public/WebString.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+WebICECandidateDescriptor::WebICECandidateDescriptor(IceCandidateDescriptor* iceCandidate)
+ : m_private(iceCandidate)
+{
+}
+
+WebICECandidateDescriptor::WebICECandidateDescriptor(PassRefPtr<IceCandidateDescriptor> iceCandidate)
+ : m_private(iceCandidate)
+{
+}
+
+void WebICECandidateDescriptor::assign(const WebICECandidateDescriptor& other)
+{
+ m_private = other.m_private;
+}
+
+void WebICECandidateDescriptor::reset()
+{
+ m_private.reset();
+}
+
+void WebICECandidateDescriptor::initialize(const WebString& label, const WebString& candidateLine)
+{
+ m_private = IceCandidateDescriptor::create(label, candidateLine);
+}
+
+WebICECandidateDescriptor::operator PassRefPtr<WebCore::IceCandidateDescriptor>() const
+{
+ return m_private.get();
+}
+
+WebString WebICECandidateDescriptor::label() const
+{
+ ASSERT(!m_private.isNull());
+ return m_private.get()->label();
+}
+
+WebString WebICECandidateDescriptor::candidateLine() const
+{
+ ASSERT(!m_private.isNull());
+ return m_private.get()->candidateLine();
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(MEDIA_STREAM)
+
diff --git a/Source/WebCore/platform/chromium/support/WebICEOptions.cpp b/Source/WebCore/platform/chromium/support/WebICEOptions.cpp
new file mode 100644
index 000000000..580809a20
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebICEOptions.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include <public/WebICEOptions.h>
+
+#include "IceOptions.h"
+
+using namespace WebCore;
+
+namespace WebKit {
+
+WebICEOptions::WebICEOptions(const PassRefPtr<IceOptions>& mediaHints)
+ : m_private(mediaHints)
+{
+}
+
+void WebICEOptions::assign(const WebICEOptions& other)
+{
+ m_private = other.m_private;
+}
+
+void WebICEOptions::initialize(CandidateType candidateType)
+{
+ ASSERT(isNull());
+ m_private = IceOptions::create(static_cast<IceOptions::UseCandidatesOption>(candidateType));
+}
+
+void WebICEOptions::reset()
+{
+ m_private.reset();
+}
+
+WebICEOptions::CandidateType WebICEOptions::candidateTypeToUse() const
+{
+ ASSERT(!isNull());
+ return static_cast<CandidateType>(m_private->useCandidates());
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(MEDIA_STREAM)
+
diff --git a/Source/WebCore/platform/chromium/support/WebMediaHints.cpp b/Source/WebCore/platform/chromium/support/WebMediaHints.cpp
new file mode 100644
index 000000000..de9727ab1
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebMediaHints.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include <public/WebMediaHints.h>
+
+#include "MediaHints.h"
+
+using namespace WebCore;
+
+namespace WebKit {
+
+WebMediaHints::WebMediaHints(const PassRefPtr<MediaHints>& mediaHints)
+ : m_private(mediaHints)
+{
+}
+
+void WebMediaHints::assign(const WebMediaHints& other)
+{
+ m_private = other.m_private;
+}
+
+void WebMediaHints::initialize(bool audio, bool video)
+{
+ ASSERT(isNull());
+ m_private = MediaHints::create(audio, video);
+}
+
+void WebMediaHints::reset()
+{
+ m_private.reset();
+}
+
+bool WebMediaHints::audio() const
+{
+ ASSERT(!isNull());
+ return m_private->audio();
+}
+
+bool WebMediaHints::video() const
+{
+ ASSERT(!isNull());
+ return m_private->video();
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(MEDIA_STREAM)
+
diff --git a/Source/WebCore/platform/chromium/support/WebMediaStreamComponent.cpp b/Source/WebCore/platform/chromium/support/WebMediaStreamComponent.cpp
new file mode 100644
index 000000000..982fdda41
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebMediaStreamComponent.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include <public/WebMediaStreamComponent.h>
+
+#include "MediaStreamComponent.h"
+#include <public/WebMediaStreamSource.h>
+#include <public/WebString.h>
+#include <wtf/Vector.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+WebMediaStreamComponent::WebMediaStreamComponent(WebCore::MediaStreamComponent* mediaStreamComponent)
+ : m_private(mediaStreamComponent)
+{
+}
+
+WebMediaStreamComponent& WebMediaStreamComponent::operator=(WebCore::MediaStreamComponent* mediaStreamComponent)
+{
+ m_private = mediaStreamComponent;
+ return *this;
+}
+
+void WebMediaStreamComponent::reset()
+{
+ m_private.reset();
+}
+
+WebMediaStreamComponent::operator PassRefPtr<MediaStreamComponent>() const
+{
+ return m_private.get();
+}
+
+WebMediaStreamComponent::operator MediaStreamComponent*() const
+{
+ return m_private.get();
+}
+
+bool WebMediaStreamComponent::isEnabled() const
+{
+ ASSERT(!m_private.isNull());
+ return m_private.get()->enabled();
+}
+
+WebMediaStreamSource WebMediaStreamComponent::source() const
+{
+ ASSERT(!m_private.isNull());
+ return WebMediaStreamSource(m_private.get()->source());
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(MEDIA_STREAM)
+
diff --git a/Source/WebCore/platform/chromium/support/WebMediaStreamDescriptor.cpp b/Source/WebCore/platform/chromium/support/WebMediaStreamDescriptor.cpp
new file mode 100644
index 000000000..f7e3c6b1a
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebMediaStreamDescriptor.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include <public/WebMediaStreamDescriptor.h>
+
+#include "MediaStreamComponent.h"
+#include "MediaStreamDescriptor.h"
+#include "MediaStreamSource.h"
+#include <public/WebMediaStreamComponent.h>
+#include <public/WebMediaStreamSource.h>
+#include <public/WebString.h>
+#include <wtf/Vector.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+WebMediaStreamDescriptor::WebMediaStreamDescriptor(const PassRefPtr<WebCore::MediaStreamDescriptor>& mediaStreamDescriptor)
+ : m_private(mediaStreamDescriptor)
+{
+}
+
+WebMediaStreamDescriptor::WebMediaStreamDescriptor(WebCore::MediaStreamDescriptor* mediaStreamDescriptor)
+ : m_private(mediaStreamDescriptor)
+{
+}
+
+void WebMediaStreamDescriptor::reset()
+{
+ m_private.reset();
+}
+
+WebString WebMediaStreamDescriptor::label() const
+{
+ return m_private->label();
+}
+
+// FIXME: Cleanup when the chromium code has switched to the split sources implementation.
+void WebMediaStreamDescriptor::sources(WebVector<WebMediaStreamSource>& webSources) const
+{
+ size_t numberOfAudioSources = m_private->numberOfAudioComponents();
+ size_t numberOfVideoSources = m_private->numberOfVideoComponents();
+ WebVector<WebMediaStreamSource> result(numberOfAudioSources + numberOfVideoSources);
+ size_t i = 0;
+ for (size_t j = 0; j < numberOfAudioSources; ++i, ++j)
+ result[i] = m_private->audioComponent(j)->source();
+ for (size_t j = 0; j < numberOfVideoSources; ++i, ++j)
+ result[i] = m_private->videoComponent(j)->source();
+ webSources.swap(result);
+}
+
+void WebMediaStreamDescriptor::audioSources(WebVector<WebMediaStreamComponent>& webSources) const
+{
+ size_t numberOfSources = m_private->numberOfAudioComponents();
+ WebVector<WebMediaStreamComponent> result(numberOfSources);
+ for (size_t i = 0; i < numberOfSources; ++i)
+ result[i] = m_private->audioComponent(i);
+ webSources.swap(result);
+}
+
+void WebMediaStreamDescriptor::videoSources(WebVector<WebMediaStreamComponent>& webSources) const
+{
+ size_t numberOfSources = m_private->numberOfVideoComponents();
+ WebVector<WebMediaStreamComponent> result(numberOfSources);
+ for (size_t i = 0; i < numberOfSources; ++i)
+ result[i] = m_private->videoComponent(i);
+ webSources.swap(result);
+}
+
+WebMediaStreamDescriptor& WebMediaStreamDescriptor::operator=(const PassRefPtr<WebCore::MediaStreamDescriptor>& mediaStreamDescriptor)
+{
+ m_private = mediaStreamDescriptor;
+ return *this;
+}
+
+WebMediaStreamDescriptor::operator PassRefPtr<WebCore::MediaStreamDescriptor>() const
+{
+ return m_private.get();
+}
+
+WebMediaStreamDescriptor::operator WebCore::MediaStreamDescriptor*() const
+{
+ return m_private.get();
+}
+
+// FIXME: Cleanup when the chromium code has switched to the split sources implementation.
+void WebMediaStreamDescriptor::initialize(const WebString& label, const WebVector<WebMediaStreamSource>& sources)
+{
+ MediaStreamSourceVector audio, video;
+ for (size_t i = 0; i < sources.size(); ++i) {
+ MediaStreamSource* curr = sources[i];
+ if (curr->type() == MediaStreamSource::TypeAudio)
+ audio.append(curr);
+ else if (curr->type() == MediaStreamSource::TypeVideo)
+ video.append(curr);
+ }
+ m_private = MediaStreamDescriptor::create(label, audio, video);
+}
+
+void WebMediaStreamDescriptor::initialize(const WebString& label, const WebVector<WebMediaStreamSource>& audioSources, const WebVector<WebMediaStreamSource>& videoSources)
+{
+ MediaStreamSourceVector audio, video;
+ for (size_t i = 0; i < audioSources.size(); ++i) {
+ MediaStreamSource* curr = audioSources[i];
+ audio.append(curr);
+ }
+ for (size_t i = 0; i < videoSources.size(); ++i) {
+ MediaStreamSource* curr = videoSources[i];
+ video.append(curr);
+ }
+ m_private = MediaStreamDescriptor::create(label, audio, video);
+}
+
+void WebMediaStreamDescriptor::assign(const WebMediaStreamDescriptor& other)
+{
+ m_private = other.m_private;
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(MEDIA_STREAM)
+
diff --git a/Source/WebCore/platform/chromium/DataTransferItemListChromium.h b/Source/WebCore/platform/chromium/support/WebMediaStreamSource.cpp
index 61bd167c7..3f877f54c 100644
--- a/Source/WebCore/platform/chromium/DataTransferItemListChromium.h
+++ b/Source/WebCore/platform/chromium/support/WebMediaStreamSource.cpp
@@ -28,49 +28,75 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef DataTransferItemListChromium_h
-#define DataTransferItemListChromium_h
+#include "config.h"
-#if ENABLE(DATA_TRANSFER_ITEMS)
+#if ENABLE(MEDIA_STREAM)
-#include "DataTransferItemList.h"
-#include <wtf/RefPtr.h>
+#include <public/WebMediaStreamSource.h>
+
+#include "MediaStreamSource.h"
+#include <public/WebString.h>
#include <wtf/Vector.h>
-namespace WebCore {
+using namespace WebCore;
+
+namespace WebKit {
+
+WebMediaStreamSource::WebMediaStreamSource(const PassRefPtr<MediaStreamSource>& mediaStreamSource)
+ : m_private(mediaStreamSource)
+{
+}
+
+WebMediaStreamSource& WebMediaStreamSource::operator=(WebCore::MediaStreamSource* mediaStreamSource)
+{
+ m_private = mediaStreamSource;
+ return *this;
+}
+
+void WebMediaStreamSource::assign(const WebMediaStreamSource& other)
+{
+ m_private = other.m_private;
+}
+
+void WebMediaStreamSource::reset()
+{
+ m_private.reset();
+}
-class Clipboard;
-class ClipboardChromium;
-class File;
-class ScriptExecutionContext;
+WebMediaStreamSource::operator PassRefPtr<MediaStreamSource>() const
+{
+ return m_private.get();
+}
-typedef int ExceptionCode;
+WebMediaStreamSource::operator MediaStreamSource*() const
+{
+ return m_private.get();
+}
-class DataTransferItemListChromium : public DataTransferItemList {
-public:
- static PassRefPtr<DataTransferItemListChromium> create(PassRefPtr<Clipboard>, ScriptExecutionContext*);
+void WebMediaStreamSource::initialize(const WebString& id, Type type, const WebString& name)
+{
+ m_private = MediaStreamSource::create(id, static_cast<MediaStreamSource::Type>(type), name);
+}
- virtual size_t length() const;
- virtual PassRefPtr<DataTransferItem> item(unsigned long index);
- // FIXME: Implement V8DataTransferItemList::indexedPropertyDeleter to get this called.
- virtual void deleteItem(unsigned long index, ExceptionCode&);
- virtual void clear();
- virtual void add(const String& data, const String& type, ExceptionCode&);
- virtual void add(PassRefPtr<File>);
+WebString WebMediaStreamSource::id() const
+{
+ ASSERT(!m_private.isNull());
+ return m_private.get()->id();
+}
-private:
- DataTransferItemListChromium(PassRefPtr<Clipboard>, ScriptExecutionContext*);
- ClipboardChromium* clipboardChromium() const;
+WebMediaStreamSource::Type WebMediaStreamSource::type() const
+{
+ ASSERT(!m_private.isNull());
+ return static_cast<Type>(m_private.get()->type());
+}
- RefPtr<Clipboard> m_owner;
- // Indirectly owned by our parent.
- ScriptExecutionContext* m_context;
- // FIXME: m_items should not be mutable. This will be fixed by https://bugs.webkit.org/show_bug.cgi?id=76598
- mutable Vector<RefPtr<DataTransferItem> > m_items;
-};
+WebString WebMediaStreamSource::name() const
+{
+ ASSERT(!m_private.isNull());
+ return m_private.get()->name();
+}
-} // namespace WebCore
+} // namespace WebKit
-#endif // ENABLE(DATA_TRANSFER_ITEMS)
+#endif // ENABLE(MEDIA_STREAM)
-#endif // DataTransferItemListChromium_h
diff --git a/Source/WebCore/platform/chromium/support/WebMediaStreamSourcesRequest.cpp b/Source/WebCore/platform/chromium/support/WebMediaStreamSourcesRequest.cpp
new file mode 100644
index 000000000..ccd27f026
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebMediaStreamSourcesRequest.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include <public/WebMediaStreamSourcesRequest.h>
+
+#include "MediaStreamSource.h"
+#include "MediaStreamSourcesQueryClient.h"
+#include <public/WebMediaStreamSource.h>
+#include <public/WebVector.h>
+#include <wtf/Vector.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+WebMediaStreamSourcesRequest::WebMediaStreamSourcesRequest(const PassRefPtr<WebCore::MediaStreamSourcesQueryClient>& queryClient)
+ : m_private(queryClient)
+{
+}
+
+void WebMediaStreamSourcesRequest::reset()
+{
+ m_private.reset();
+}
+
+bool WebMediaStreamSourcesRequest::audio() const
+{
+ ASSERT(!isNull());
+ return m_private->audio();
+}
+
+bool WebMediaStreamSourcesRequest::video() const
+{
+ ASSERT(!isNull());
+ return m_private->video();
+}
+
+void WebMediaStreamSourcesRequest::didCompleteQuery(const WebVector<WebMediaStreamSource>& audioSources, const WebVector<WebMediaStreamSource>& videoSources) const
+{
+ ASSERT(!isNull());
+ MediaStreamSourceVector audio;
+ for (size_t i = 0; i < audioSources.size(); ++i) {
+ MediaStreamSource* curr = audioSources[i];
+ audio.append(curr);
+ }
+ MediaStreamSourceVector video;
+ for (size_t i = 0; i < videoSources.size(); ++i) {
+ MediaStreamSource* curr = videoSources[i];
+ video.append(curr);
+ }
+ m_private->didCompleteQuery(audio, video);
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(MEDIA_STREAM)
+
diff --git a/Source/WebCore/platform/chromium/support/WebThreadSafeData.cpp b/Source/WebCore/platform/chromium/support/WebThreadSafeData.cpp
new file mode 100755
index 000000000..8e11209b4
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebThreadSafeData.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include <public/WebThreadSafeData.h>
+
+#include "BlobData.h"
+
+using namespace WebCore;
+
+namespace WebKit {
+
+void WebThreadSafeData::reset()
+{
+ m_private.reset();
+}
+
+void WebThreadSafeData::assign(const WebThreadSafeData& other)
+{
+ m_private = other.m_private;
+}
+
+size_t WebThreadSafeData::size() const
+{
+ if (m_private.isNull())
+ return 0;
+ return m_private->length();
+}
+
+const char* WebThreadSafeData::data() const
+{
+ if (m_private.isNull())
+ return 0;
+ return m_private->data();
+}
+
+WebThreadSafeData::WebThreadSafeData(const PassRefPtr<RawData>& data)
+ : m_private(data.leakRef())
+{
+}
+
+WebThreadSafeData& WebThreadSafeData::operator=(const PassRefPtr<RawData>& data)
+{
+ m_private = data;
+ return *this;
+}
+
+} // namespace WebKit
diff --git a/Source/WebCore/platform/chromium/support/WebURL.cpp b/Source/WebCore/platform/chromium/support/WebURL.cpp
new file mode 100644
index 000000000..f7a168df3
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebURL.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include <public/WebURL.h>
+
+#include "KURL.h"
+
+namespace WebKit {
+
+WebURL::WebURL(const WebCore::KURL& url)
+ : m_spec(url.utf8String())
+ , m_parsed(url.parsed())
+ , m_isValid(url.isValid())
+{
+}
+
+WebURL& WebURL::operator=(const WebCore::KURL& url)
+{
+ m_spec = url.utf8String();
+ m_parsed = url.parsed();
+ m_isValid = url.isValid();
+ return *this;
+}
+
+WebURL::operator WebCore::KURL() const
+{
+ return WebCore::KURL(m_spec, m_parsed, m_isValid);
+}
+
+} // namespace WebKit
diff --git a/Source/WebCore/platform/chromium/support/WebURLError.cpp b/Source/WebCore/platform/chromium/support/WebURLError.cpp
new file mode 100644
index 000000000..1341deee6
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebURLError.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include <public/WebURLError.h>
+
+#include "KURL.h"
+#include "ResourceError.h"
+#include <wtf/text/CString.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+WebURLError::WebURLError(const ResourceError& error)
+{
+ *this = error;
+}
+
+WebURLError& WebURLError::operator=(const ResourceError& error)
+{
+ if (error.isNull())
+ *this = WebURLError();
+ else {
+ domain = error.domain();
+ reason = error.errorCode();
+ unreachableURL = KURL(ParsedURLString, error.failingURL());
+ isCancellation = error.isCancellation();
+ localizedDescription = error.localizedDescription();
+ }
+ return *this;
+}
+
+WebURLError::operator ResourceError() const
+{
+ if (!reason)
+ return ResourceError();
+ CString spec = unreachableURL.spec();
+ ResourceError resourceError = ResourceError(domain, reason,
+ String::fromUTF8(spec.data(),
+ spec.length()),
+ localizedDescription);
+ resourceError.setIsCancellation(isCancellation);
+ return resourceError;
+}
+
+} // namespace WebKit
diff --git a/Source/WebCore/platform/chromium/support/WebURLRequest.cpp b/Source/WebCore/platform/chromium/support/WebURLRequest.cpp
new file mode 100644
index 000000000..f437b5164
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebURLRequest.cpp
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include <public/WebURLRequest.h>
+
+#include "ResourceRequest.h"
+#include "WebURLRequestPrivate.h"
+#include <public/WebHTTPBody.h>
+#include <public/WebHTTPHeaderVisitor.h>
+#include <public/WebURL.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+namespace {
+
+class ExtraDataContainer : public ResourceRequest::ExtraData {
+public:
+ static PassRefPtr<ExtraDataContainer> create(WebURLRequest::ExtraData* extraData) { return adoptRef(new ExtraDataContainer(extraData)); }
+
+ virtual ~ExtraDataContainer() { }
+
+ WebURLRequest::ExtraData* extraData() const { return m_extraData.get(); }
+
+private:
+ explicit ExtraDataContainer(WebURLRequest::ExtraData* extraData)
+ : m_extraData(adoptPtr(extraData))
+ {
+ }
+
+ OwnPtr<WebURLRequest::ExtraData> m_extraData;
+};
+
+} // namespace
+
+// The standard implementation of WebURLRequestPrivate, which maintains
+// ownership of a ResourceRequest instance.
+class WebURLRequestPrivateImpl : public WebURLRequestPrivate {
+public:
+ WebURLRequestPrivateImpl()
+ {
+ m_resourceRequest = &m_resourceRequestAllocation;
+ }
+
+ WebURLRequestPrivateImpl(const WebURLRequestPrivate* p)
+ : m_resourceRequestAllocation(*p->m_resourceRequest)
+ {
+ m_resourceRequest = &m_resourceRequestAllocation;
+ m_allowStoredCredentials = p->m_allowStoredCredentials;
+ }
+
+ virtual void dispose() { delete this; }
+
+private:
+ virtual ~WebURLRequestPrivateImpl() { }
+
+ ResourceRequest m_resourceRequestAllocation;
+};
+
+void WebURLRequest::initialize()
+{
+ assign(new WebURLRequestPrivateImpl());
+}
+
+void WebURLRequest::reset()
+{
+ assign(0);
+}
+
+void WebURLRequest::assign(const WebURLRequest& r)
+{
+ if (&r != this)
+ assign(r.m_private ? new WebURLRequestPrivateImpl(r.m_private) : 0);
+}
+
+bool WebURLRequest::isNull() const
+{
+ return !m_private || m_private->m_resourceRequest->isNull();
+}
+
+WebURL WebURLRequest::url() const
+{
+ return m_private->m_resourceRequest->url();
+}
+
+void WebURLRequest::setURL(const WebURL& url)
+{
+ m_private->m_resourceRequest->setURL(url);
+}
+
+WebURL WebURLRequest::firstPartyForCookies() const
+{
+ return m_private->m_resourceRequest->firstPartyForCookies();
+}
+
+void WebURLRequest::setFirstPartyForCookies(const WebURL& firstPartyForCookies)
+{
+ m_private->m_resourceRequest->setFirstPartyForCookies(firstPartyForCookies);
+}
+
+bool WebURLRequest::allowCookies() const
+{
+ return m_private->m_resourceRequest->allowCookies();
+}
+
+void WebURLRequest::setAllowCookies(bool allowCookies)
+{
+ m_private->m_resourceRequest->setAllowCookies(allowCookies);
+}
+
+bool WebURLRequest::allowStoredCredentials() const
+{
+ return m_private->m_allowStoredCredentials;
+}
+
+void WebURLRequest::setAllowStoredCredentials(bool allowStoredCredentials)
+{
+ m_private->m_allowStoredCredentials = allowStoredCredentials;
+}
+
+WebURLRequest::CachePolicy WebURLRequest::cachePolicy() const
+{
+ return static_cast<WebURLRequest::CachePolicy>(
+ m_private->m_resourceRequest->cachePolicy());
+}
+
+void WebURLRequest::setCachePolicy(CachePolicy cachePolicy)
+{
+ m_private->m_resourceRequest->setCachePolicy(
+ static_cast<ResourceRequestCachePolicy>(cachePolicy));
+}
+
+WebString WebURLRequest::httpMethod() const
+{
+ return m_private->m_resourceRequest->httpMethod();
+}
+
+void WebURLRequest::setHTTPMethod(const WebString& httpMethod)
+{
+ m_private->m_resourceRequest->setHTTPMethod(httpMethod);
+}
+
+WebString WebURLRequest::httpHeaderField(const WebString& name) const
+{
+ return m_private->m_resourceRequest->httpHeaderField(name);
+}
+
+void WebURLRequest::setHTTPHeaderField(const WebString& name, const WebString& value)
+{
+ m_private->m_resourceRequest->setHTTPHeaderField(name, value);
+}
+
+void WebURLRequest::addHTTPHeaderField(const WebString& name, const WebString& value)
+{
+ m_private->m_resourceRequest->addHTTPHeaderField(name, value);
+}
+
+void WebURLRequest::clearHTTPHeaderField(const WebString& name)
+{
+ // FIXME: Add a clearHTTPHeaderField method to ResourceRequest.
+ const HTTPHeaderMap& map = m_private->m_resourceRequest->httpHeaderFields();
+ const_cast<HTTPHeaderMap*>(&map)->remove(name);
+}
+
+void WebURLRequest::visitHTTPHeaderFields(WebHTTPHeaderVisitor* visitor) const
+{
+ const HTTPHeaderMap& map = m_private->m_resourceRequest->httpHeaderFields();
+ for (HTTPHeaderMap::const_iterator it = map.begin(); it != map.end(); ++it)
+ visitor->visitHeader(it->first, it->second);
+}
+
+WebHTTPBody WebURLRequest::httpBody() const
+{
+ return WebHTTPBody(m_private->m_resourceRequest->httpBody());
+}
+
+void WebURLRequest::setHTTPBody(const WebHTTPBody& httpBody)
+{
+ m_private->m_resourceRequest->setHTTPBody(httpBody);
+}
+
+bool WebURLRequest::reportUploadProgress() const
+{
+ return m_private->m_resourceRequest->reportUploadProgress();
+}
+
+void WebURLRequest::setReportUploadProgress(bool reportUploadProgress)
+{
+ m_private->m_resourceRequest->setReportUploadProgress(reportUploadProgress);
+}
+
+bool WebURLRequest::reportLoadTiming() const
+{
+ return m_private->m_resourceRequest->reportLoadTiming();
+}
+
+void WebURLRequest::setReportRawHeaders(bool reportRawHeaders)
+{
+ m_private->m_resourceRequest->setReportRawHeaders(reportRawHeaders);
+}
+
+bool WebURLRequest::reportRawHeaders() const
+{
+ return m_private->m_resourceRequest->reportRawHeaders();
+}
+
+void WebURLRequest::setReportLoadTiming(bool reportLoadTiming)
+{
+ m_private->m_resourceRequest->setReportLoadTiming(reportLoadTiming);
+}
+
+WebURLRequest::TargetType WebURLRequest::targetType() const
+{
+ // FIXME: Temporary special case until downstream chromium.org knows of the new TargetTypes.
+ TargetType targetType = static_cast<TargetType>(m_private->m_resourceRequest->targetType());
+ if (targetType == TargetIsTextTrack || targetType == TargetIsUnspecified)
+ return TargetIsSubresource;
+ return targetType;
+}
+
+bool WebURLRequest::hasUserGesture() const
+{
+ return m_private->m_resourceRequest->hasUserGesture();
+}
+
+void WebURLRequest::setHasUserGesture(bool hasUserGesture)
+{
+ m_private->m_resourceRequest->setHasUserGesture(hasUserGesture);
+}
+
+void WebURLRequest::setTargetType(TargetType targetType)
+{
+ m_private->m_resourceRequest->setTargetType(
+ static_cast<ResourceRequest::TargetType>(targetType));
+}
+
+int WebURLRequest::requestorID() const
+{
+ return m_private->m_resourceRequest->requestorID();
+}
+
+void WebURLRequest::setRequestorID(int requestorID)
+{
+ m_private->m_resourceRequest->setRequestorID(requestorID);
+}
+
+int WebURLRequest::requestorProcessID() const
+{
+ return m_private->m_resourceRequest->requestorProcessID();
+}
+
+void WebURLRequest::setRequestorProcessID(int requestorProcessID)
+{
+ m_private->m_resourceRequest->setRequestorProcessID(requestorProcessID);
+}
+
+int WebURLRequest::appCacheHostID() const
+{
+ return m_private->m_resourceRequest->appCacheHostID();
+}
+
+void WebURLRequest::setAppCacheHostID(int appCacheHostID)
+{
+ m_private->m_resourceRequest->setAppCacheHostID(appCacheHostID);
+}
+
+bool WebURLRequest::downloadToFile() const
+{
+ return m_private->m_resourceRequest->downloadToFile();
+}
+
+void WebURLRequest::setDownloadToFile(bool downloadToFile)
+{
+ m_private->m_resourceRequest->setDownloadToFile(downloadToFile);
+}
+
+WebURLRequest::ExtraData* WebURLRequest::extraData() const
+{
+ RefPtr<ResourceRequest::ExtraData> data = m_private->m_resourceRequest->extraData();
+ if (!data)
+ return 0;
+ return static_cast<ExtraDataContainer*>(data.get())->extraData();
+}
+
+void WebURLRequest::setExtraData(WebURLRequest::ExtraData* extraData)
+{
+ m_private->m_resourceRequest->setExtraData(ExtraDataContainer::create(extraData));
+}
+
+ResourceRequest& WebURLRequest::toMutableResourceRequest()
+{
+ ASSERT(m_private);
+ ASSERT(m_private->m_resourceRequest);
+
+ return *m_private->m_resourceRequest;
+}
+
+const ResourceRequest& WebURLRequest::toResourceRequest() const
+{
+ ASSERT(m_private);
+ ASSERT(m_private->m_resourceRequest);
+
+ return *m_private->m_resourceRequest;
+}
+
+void WebURLRequest::assign(WebURLRequestPrivate* p)
+{
+ // Subclasses may call this directly so a self-assignment check is needed
+ // here as well as in the public assign method.
+ if (m_private == p)
+ return;
+ if (m_private)
+ m_private->dispose();
+ m_private = p;
+}
+
+} // namespace WebKit
diff --git a/Source/WebCore/platform/chromium/support/WebURLRequestPrivate.h b/Source/WebCore/platform/chromium/support/WebURLRequestPrivate.h
new file mode 100644
index 000000000..1c1b69608
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebURLRequestPrivate.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebURLRequestPrivate_h
+#define WebURLRequestPrivate_h
+
+namespace WebCore { class ResourceRequest; }
+
+namespace WebKit {
+
+class WebURLRequestPrivate {
+public:
+ WebURLRequestPrivate()
+ : m_resourceRequest(0)
+ , m_allowStoredCredentials(true) { }
+
+ // Called by WebURLRequest when it no longer needs this object.
+ virtual void dispose() = 0;
+
+ WebCore::ResourceRequest* m_resourceRequest;
+ bool m_allowStoredCredentials;
+};
+
+} // namespace WebKit
+
+#endif
diff --git a/Source/WebCore/platform/chromium/support/WebURLResponse.cpp b/Source/WebCore/platform/chromium/support/WebURLResponse.cpp
new file mode 100644
index 000000000..05658050d
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebURLResponse.cpp
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include <public/WebURLResponse.h>
+
+#include "ResourceLoadTiming.h"
+#include "ResourceResponse.h"
+#include "WebURLResponsePrivate.h"
+#include <public/WebHTTPHeaderVisitor.h>
+#include <public/WebHTTPLoadInfo.h>
+#include <public/WebString.h>
+#include <public/WebURL.h>
+#include <public/WebURLLoadTiming.h>
+#include <wtf/RefPtr.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+namespace {
+
+class ExtraDataContainer : public ResourceResponse::ExtraData {
+public:
+ static PassRefPtr<ExtraDataContainer> create(WebURLResponse::ExtraData* extraData) { return adoptRef(new ExtraDataContainer(extraData)); }
+
+ virtual ~ExtraDataContainer() { }
+
+ WebURLResponse::ExtraData* extraData() const { return m_extraData.get(); }
+
+private:
+ explicit ExtraDataContainer(WebURLResponse::ExtraData* extraData)
+ : m_extraData(adoptPtr(extraData))
+ {
+ }
+
+ OwnPtr<WebURLResponse::ExtraData> m_extraData;
+};
+
+} // namespace
+
+// The standard implementation of WebURLResponsePrivate, which maintains
+// ownership of a ResourceResponse instance.
+class WebURLResponsePrivateImpl : public WebURLResponsePrivate {
+public:
+ WebURLResponsePrivateImpl()
+ {
+ m_resourceResponse = &m_resourceResponseAllocation;
+ }
+
+ WebURLResponsePrivateImpl(const WebURLResponsePrivate* p)
+ : m_resourceResponseAllocation(*p->m_resourceResponse)
+ {
+ m_resourceResponse = &m_resourceResponseAllocation;
+ }
+
+ virtual void dispose() { delete this; }
+
+private:
+ virtual ~WebURLResponsePrivateImpl() { }
+
+ ResourceResponse m_resourceResponseAllocation;
+};
+
+void WebURLResponse::initialize()
+{
+ assign(new WebURLResponsePrivateImpl());
+}
+
+void WebURLResponse::reset()
+{
+ assign(0);
+}
+
+void WebURLResponse::assign(const WebURLResponse& r)
+{
+ if (&r != this)
+ assign(r.m_private ? new WebURLResponsePrivateImpl(r.m_private) : 0);
+}
+
+bool WebURLResponse::isNull() const
+{
+ return !m_private || m_private->m_resourceResponse->isNull();
+}
+
+WebURL WebURLResponse::url() const
+{
+ return m_private->m_resourceResponse->url();
+}
+
+void WebURLResponse::setURL(const WebURL& url)
+{
+ m_private->m_resourceResponse->setURL(url);
+}
+
+unsigned WebURLResponse::connectionID() const
+{
+ return m_private->m_resourceResponse->connectionID();
+}
+
+void WebURLResponse::setConnectionID(unsigned connectionID)
+{
+ m_private->m_resourceResponse->setConnectionID(connectionID);
+}
+
+bool WebURLResponse::connectionReused() const
+{
+ return m_private->m_resourceResponse->connectionReused();
+}
+
+void WebURLResponse::setConnectionReused(bool connectionReused)
+{
+ m_private->m_resourceResponse->setConnectionReused(connectionReused);
+}
+
+WebURLLoadTiming WebURLResponse::loadTiming()
+{
+ return WebURLLoadTiming(m_private->m_resourceResponse->resourceLoadTiming());
+}
+
+void WebURLResponse::setLoadTiming(const WebURLLoadTiming& timing)
+{
+ RefPtr<ResourceLoadTiming> loadTiming = PassRefPtr<ResourceLoadTiming>(timing);
+ m_private->m_resourceResponse->setResourceLoadTiming(loadTiming.release());
+}
+
+WebHTTPLoadInfo WebURLResponse::httpLoadInfo()
+{
+ return WebHTTPLoadInfo(m_private->m_resourceResponse->resourceLoadInfo());
+}
+
+void WebURLResponse::setHTTPLoadInfo(const WebHTTPLoadInfo& value)
+{
+ m_private->m_resourceResponse->setResourceLoadInfo(value);
+}
+
+double WebURLResponse::responseTime() const
+{
+ return m_private->m_resourceResponse->responseTime();
+}
+
+void WebURLResponse::setResponseTime(double responseTime)
+{
+ m_private->m_resourceResponse->setResponseTime(responseTime);
+}
+
+WebString WebURLResponse::mimeType() const
+{
+ return m_private->m_resourceResponse->mimeType();
+}
+
+void WebURLResponse::setMIMEType(const WebString& mimeType)
+{
+ m_private->m_resourceResponse->setMimeType(mimeType);
+}
+
+long long WebURLResponse::expectedContentLength() const
+{
+ return m_private->m_resourceResponse->expectedContentLength();
+}
+
+void WebURLResponse::setExpectedContentLength(long long expectedContentLength)
+{
+ m_private->m_resourceResponse->setExpectedContentLength(expectedContentLength);
+}
+
+WebString WebURLResponse::textEncodingName() const
+{
+ return m_private->m_resourceResponse->textEncodingName();
+}
+
+void WebURLResponse::setTextEncodingName(const WebString& textEncodingName)
+{
+ m_private->m_resourceResponse->setTextEncodingName(textEncodingName);
+}
+
+WebString WebURLResponse::suggestedFileName() const
+{
+ return m_private->m_resourceResponse->suggestedFilename();
+}
+
+void WebURLResponse::setSuggestedFileName(const WebString& suggestedFileName)
+{
+ m_private->m_resourceResponse->setSuggestedFilename(suggestedFileName);
+}
+
+int WebURLResponse::httpStatusCode() const
+{
+ return m_private->m_resourceResponse->httpStatusCode();
+}
+
+void WebURLResponse::setHTTPStatusCode(int httpStatusCode)
+{
+ m_private->m_resourceResponse->setHTTPStatusCode(httpStatusCode);
+}
+
+WebString WebURLResponse::httpStatusText() const
+{
+ return m_private->m_resourceResponse->httpStatusText();
+}
+
+void WebURLResponse::setHTTPStatusText(const WebString& httpStatusText)
+{
+ m_private->m_resourceResponse->setHTTPStatusText(httpStatusText);
+}
+
+WebString WebURLResponse::httpHeaderField(const WebString& name) const
+{
+ return m_private->m_resourceResponse->httpHeaderField(name);
+}
+
+void WebURLResponse::setHTTPHeaderField(const WebString& name, const WebString& value)
+{
+ m_private->m_resourceResponse->setHTTPHeaderField(name, value);
+}
+
+void WebURLResponse::addHTTPHeaderField(const WebString& name, const WebString& value)
+{
+ if (name.isNull() || value.isNull())
+ return;
+ // FIXME: Add an addHTTPHeaderField method to ResourceResponse.
+ const HTTPHeaderMap& map = m_private->m_resourceResponse->httpHeaderFields();
+ String valueStr(value);
+ HTTPHeaderMap::AddResult result =
+ const_cast<HTTPHeaderMap*>(&map)->add(name, valueStr);
+ if (!result.isNewEntry)
+ result.iterator->second += ", " + valueStr;
+}
+
+void WebURLResponse::clearHTTPHeaderField(const WebString& name)
+{
+ // FIXME: Add a clearHTTPHeaderField method to ResourceResponse.
+ const HTTPHeaderMap& map = m_private->m_resourceResponse->httpHeaderFields();
+ const_cast<HTTPHeaderMap*>(&map)->remove(name);
+}
+
+void WebURLResponse::visitHTTPHeaderFields(WebHTTPHeaderVisitor* visitor) const
+{
+ const HTTPHeaderMap& map = m_private->m_resourceResponse->httpHeaderFields();
+ for (HTTPHeaderMap::const_iterator it = map.begin(); it != map.end(); ++it)
+ visitor->visitHeader(it->first, it->second);
+}
+
+double WebURLResponse::lastModifiedDate() const
+{
+ return static_cast<double>(m_private->m_resourceResponse->lastModifiedDate());
+}
+
+void WebURLResponse::setLastModifiedDate(double lastModifiedDate)
+{
+ m_private->m_resourceResponse->setLastModifiedDate(static_cast<time_t>(lastModifiedDate));
+}
+
+long long WebURLResponse::appCacheID() const
+{
+ return m_private->m_resourceResponse->appCacheID();
+}
+
+void WebURLResponse::setAppCacheID(long long appCacheID)
+{
+ m_private->m_resourceResponse->setAppCacheID(appCacheID);
+}
+
+WebURL WebURLResponse::appCacheManifestURL() const
+{
+ return m_private->m_resourceResponse->appCacheManifestURL();
+}
+
+void WebURLResponse::setAppCacheManifestURL(const WebURL& url)
+{
+ m_private->m_resourceResponse->setAppCacheManifestURL(url);
+}
+
+WebCString WebURLResponse::securityInfo() const
+{
+ // FIXME: getSecurityInfo is misnamed.
+ return m_private->m_resourceResponse->getSecurityInfo();
+}
+
+void WebURLResponse::setSecurityInfo(const WebCString& securityInfo)
+{
+ m_private->m_resourceResponse->setSecurityInfo(securityInfo);
+}
+
+ResourceResponse& WebURLResponse::toMutableResourceResponse()
+{
+ ASSERT(m_private);
+ ASSERT(m_private->m_resourceResponse);
+
+ return *m_private->m_resourceResponse;
+}
+
+const ResourceResponse& WebURLResponse::toResourceResponse() const
+{
+ ASSERT(m_private);
+ ASSERT(m_private->m_resourceResponse);
+
+ return *m_private->m_resourceResponse;
+}
+
+bool WebURLResponse::wasCached() const
+{
+ return m_private->m_resourceResponse->wasCached();
+}
+
+void WebURLResponse::setWasCached(bool value)
+{
+ m_private->m_resourceResponse->setWasCached(value);
+}
+
+bool WebURLResponse::wasFetchedViaSPDY() const
+{
+ return m_private->m_resourceResponse->wasFetchedViaSPDY();
+}
+
+void WebURLResponse::setWasFetchedViaSPDY(bool value)
+{
+ m_private->m_resourceResponse->setWasFetchedViaSPDY(value);
+}
+
+bool WebURLResponse::wasNpnNegotiated() const
+{
+ return m_private->m_resourceResponse->wasNpnNegotiated();
+}
+
+void WebURLResponse::setWasNpnNegotiated(bool value)
+{
+ m_private->m_resourceResponse->setWasNpnNegotiated(value);
+}
+
+bool WebURLResponse::wasAlternateProtocolAvailable() const
+{
+ return m_private->m_resourceResponse->wasAlternateProtocolAvailable();
+}
+
+void WebURLResponse::setWasAlternateProtocolAvailable(bool value)
+{
+ m_private->m_resourceResponse->setWasAlternateProtocolAvailable(value);
+}
+
+bool WebURLResponse::wasFetchedViaProxy() const
+{
+ return m_private->m_resourceResponse->wasFetchedViaProxy();
+}
+
+void WebURLResponse::setWasFetchedViaProxy(bool value)
+{
+ m_private->m_resourceResponse->setWasFetchedViaProxy(value);
+}
+
+bool WebURLResponse::isMultipartPayload() const
+{
+ return m_private->m_resourceResponse->isMultipartPayload();
+}
+
+void WebURLResponse::setIsMultipartPayload(bool value)
+{
+ m_private->m_resourceResponse->setIsMultipartPayload(value);
+}
+
+WebString WebURLResponse::downloadFilePath() const
+{
+ const File* downloadedFile = m_private->m_resourceResponse->downloadedFile();
+ if (downloadedFile)
+ return downloadedFile->path();
+ return WebString();
+}
+
+void WebURLResponse::setDownloadFilePath(const WebString& downloadFilePath)
+{
+ m_private->m_resourceResponse->setDownloadedFile(downloadFilePath.isEmpty() ? 0 : File::create(downloadFilePath));
+}
+
+WebString WebURLResponse::remoteIPAddress() const
+{
+ return m_private->m_resourceResponse->remoteIPAddress();
+}
+
+void WebURLResponse::setRemoteIPAddress(const WebString& remoteIPAddress)
+{
+ m_private->m_resourceResponse->setRemoteIPAddress(remoteIPAddress);
+}
+
+unsigned short WebURLResponse::remotePort() const
+{
+ return m_private->m_resourceResponse->remotePort();
+}
+
+void WebURLResponse::setRemotePort(unsigned short remotePort)
+{
+ m_private->m_resourceResponse->setRemotePort(remotePort);
+}
+
+WebURLResponse::ExtraData* WebURLResponse::extraData() const
+{
+ RefPtr<ResourceResponse::ExtraData> data = m_private->m_resourceResponse->extraData();
+ if (!data)
+ return 0;
+ return static_cast<ExtraDataContainer*>(data.get())->extraData();
+}
+
+void WebURLResponse::setExtraData(WebURLResponse::ExtraData* extraData)
+{
+ m_private->m_resourceResponse->setExtraData(ExtraDataContainer::create(extraData));
+}
+
+void WebURLResponse::assign(WebURLResponsePrivate* p)
+{
+ // Subclasses may call this directly so a self-assignment check is needed
+ // here as well as in the public assign method.
+ if (m_private == p)
+ return;
+ if (m_private)
+ m_private->dispose();
+ m_private = p;
+}
+
+} // namespace WebKit
diff --git a/Source/WebCore/platform/chromium/support/WebURLResponsePrivate.h b/Source/WebCore/platform/chromium/support/WebURLResponsePrivate.h
new file mode 100644
index 000000000..a52621b03
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WebURLResponsePrivate.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebURLResponsePrivate_h
+#define WebURLResponsePrivate_h
+
+#include <public/WebString.h>
+
+namespace WebCore { class ResourceResponse; }
+
+namespace WebKit {
+
+class WebURLResponsePrivate {
+public:
+ WebURLResponsePrivate() : m_resourceResponse(0) { }
+
+ // Called by WebURLResponse when it no longer needs this object.
+ virtual void dispose() = 0;
+
+ WebCore::ResourceResponse* m_resourceResponse;
+};
+
+} // namespace WebKit
+
+#endif
diff --git a/Source/WebCore/platform/chromium/support/WrappedResourceRequest.h b/Source/WebCore/platform/chromium/support/WrappedResourceRequest.h
new file mode 100644
index 000000000..17ed4fea5
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WrappedResourceRequest.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WrappedResourceRequest_h
+#define WrappedResourceRequest_h
+
+#include "WebURLRequestPrivate.h"
+#include <public/WebURLRequest.h>
+
+namespace WebKit {
+
+class WrappedResourceRequest : public WebURLRequest {
+public:
+ ~WrappedResourceRequest()
+ {
+ reset(); // Need to drop reference to m_handle
+ }
+
+ WrappedResourceRequest() { }
+
+ WrappedResourceRequest(WebCore::ResourceRequest& resourceRequest)
+ {
+ bind(resourceRequest);
+ }
+
+ WrappedResourceRequest(const WebCore::ResourceRequest& resourceRequest)
+ {
+ bind(resourceRequest);
+ }
+
+ void bind(WebCore::ResourceRequest& resourceRequest)
+ {
+ m_handle.m_resourceRequest = &resourceRequest;
+ assign(&m_handle);
+ }
+
+ void bind(const WebCore::ResourceRequest& resourceRequest)
+ {
+ bind(*const_cast<WebCore::ResourceRequest*>(&resourceRequest));
+ }
+
+private:
+ class Handle : public WebURLRequestPrivate {
+ public:
+ virtual void dispose() { m_resourceRequest = 0; }
+ };
+
+ Handle m_handle;
+};
+
+} // namespace WebKit
+
+#endif
diff --git a/Source/WebCore/platform/chromium/support/WrappedResourceResponse.h b/Source/WebCore/platform/chromium/support/WrappedResourceResponse.h
new file mode 100644
index 000000000..104eaa5a2
--- /dev/null
+++ b/Source/WebCore/platform/chromium/support/WrappedResourceResponse.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WrappedResourceResponse_h
+#define WrappedResourceResponse_h
+
+#include "WebURLResponsePrivate.h"
+#include <public/WebURLResponse.h>
+
+namespace WebKit {
+
+class WrappedResourceResponse : public WebURLResponse {
+public:
+ ~WrappedResourceResponse()
+ {
+ reset(); // Need to drop reference to m_handle
+ }
+
+ WrappedResourceResponse() { }
+
+ WrappedResourceResponse(WebCore::ResourceResponse& resourceResponse)
+ {
+ bind(resourceResponse);
+ }
+
+ WrappedResourceResponse(const WebCore::ResourceResponse& resourceResponse)
+ {
+ bind(resourceResponse);
+ }
+
+ void bind(WebCore::ResourceResponse& resourceResponse)
+ {
+ m_handle.m_resourceResponse = &resourceResponse;
+ assign(&m_handle);
+ }
+
+ void bind(const WebCore::ResourceResponse& resourceResponse)
+ {
+ bind(*const_cast<WebCore::ResourceResponse*>(&resourceResponse));
+ }
+
+private:
+ class Handle : public WebURLResponsePrivate {
+ public:
+ virtual void dispose() { m_resourceResponse = 0; }
+ };
+
+ Handle m_handle;
+};
+
+} // namespace WebKit
+
+#endif
diff --git a/Source/WebCore/platform/clutter/GRefPtrClutter.h b/Source/WebCore/platform/clutter/GRefPtrClutter.h
index 091d27a85..bdec65481 100644
--- a/Source/WebCore/platform/clutter/GRefPtrClutter.h
+++ b/Source/WebCore/platform/clutter/GRefPtrClutter.h
@@ -20,7 +20,7 @@
#ifndef GRefPtrClutter_h
#define GRefPtrClutter_h
-#include "GRefPtr.h"
+#include <wtf/gobject/GRefPtr.h>
typedef struct _ClutterActor ClutterActor;
diff --git a/Source/WebCore/platform/efl/ColorChooserEfl.cpp b/Source/WebCore/platform/efl/ColorChooserEfl.cpp
new file mode 100644
index 000000000..8003be1e5
--- /dev/null
+++ b/Source/WebCore/platform/efl/ColorChooserEfl.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Intel Corporation nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(INPUT_TYPE_COLOR)
+
+#include "ColorChooserEfl.h"
+
+#include "ChromeClientEfl.h"
+
+namespace WebCore {
+
+ColorChooserEfl::ColorChooserEfl(ChromeClientEfl* chromeClient)
+ : m_chromeClient(chromeClient)
+{
+ ASSERT(m_chromeClient);
+}
+
+ColorChooserEfl::~ColorChooserEfl()
+{
+}
+
+void ColorChooserEfl::setSelectedColor(const Color& color)
+{
+ m_chromeClient->updateColorChooser(color);
+}
+
+void ColorChooserEfl::endChooser()
+{
+ m_chromeClient->removeColorChooser();
+}
+
+}
+
+#endif // ENABLE(INPUT_TYPE_COLOR)
diff --git a/Source/WebCore/platform/efl/ColorChooserEfl.h b/Source/WebCore/platform/efl/ColorChooserEfl.h
new file mode 100644
index 000000000..c1c8d062d
--- /dev/null
+++ b/Source/WebCore/platform/efl/ColorChooserEfl.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Intel Corporation nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ColorChooserEfl_h
+#define ColorChooserEfl_h
+
+#include "Color.h"
+#include "ColorChooser.h"
+
+#include <Evas.h>
+
+namespace WebCore {
+
+class ChromeClientEfl;
+
+class ColorChooserEfl : public ColorChooser {
+public:
+ ColorChooserEfl(ChromeClientEfl*);
+ ~ColorChooserEfl();
+
+ // ColorChooser implementation.
+ virtual void setSelectedColor(const Color&);
+ virtual void endChooser();
+
+private:
+ ChromeClientEfl* m_chromeClient;
+};
+
+}
+
+#endif // ColorChooserEfl_h
diff --git a/Source/WebCore/platform/efl/ContextMenuEfl.cpp b/Source/WebCore/platform/efl/ContextMenuEfl.cpp
index 4c4f77034..5110abde2 100644
--- a/Source/WebCore/platform/efl/ContextMenuEfl.cpp
+++ b/Source/WebCore/platform/efl/ContextMenuEfl.cpp
@@ -20,6 +20,9 @@
*/
#include "config.h"
+
+#if ENABLE(CONTEXT_MENUS)
+
#include "ContextMenu.h"
#include "NotImplemented.h"
@@ -101,3 +104,4 @@ Vector<ContextMenuItem> contextMenuItemVector(const Vector<ContextMenuItem>* ite
#endif
}
+#endif // ENABLE(CONTEXT_MENUS)
diff --git a/Source/WebCore/platform/efl/ContextMenuItemEfl.cpp b/Source/WebCore/platform/efl/ContextMenuItemEfl.cpp
index 6d3f13994..b8b62010d 100644
--- a/Source/WebCore/platform/efl/ContextMenuItemEfl.cpp
+++ b/Source/WebCore/platform/efl/ContextMenuItemEfl.cpp
@@ -28,6 +28,9 @@
*/
#include "config.h"
+
+#if ENABLE(CONTEXT_MENUS)
+
#include "ContextMenuItem.h"
#include "NotImplemented.h"
@@ -129,3 +132,4 @@ PlatformMenuDescription ContextMenuItem::platformSubMenu() const
}
#endif
}
+#endif // ENABLE(CONTEXT_MENUS)
diff --git a/Source/WebCore/platform/efl/DragImageEfl.cpp b/Source/WebCore/platform/efl/DragImageEfl.cpp
index 4b0f41709..4c19da74a 100644
--- a/Source/WebCore/platform/efl/DragImageEfl.cpp
+++ b/Source/WebCore/platform/efl/DragImageEfl.cpp
@@ -50,7 +50,7 @@ DragImageRef dissolveDragImageToFraction(DragImageRef image, float)
return image;
}
-DragImageRef createDragImageFromImage(Image*)
+DragImageRef createDragImageFromImage(Image*, RespectImageOrientationEnum)
{
notImplemented();
return 0;
diff --git a/Source/WebCore/platform/efl/EflKeyboardUtilities.cpp b/Source/WebCore/platform/efl/EflKeyboardUtilities.cpp
index 35ef84ccb..aa1b5e869 100644
--- a/Source/WebCore/platform/efl/EflKeyboardUtilities.cpp
+++ b/Source/WebCore/platform/efl/EflKeyboardUtilities.cpp
@@ -76,6 +76,8 @@ static void createKeyMap()
keyMap().set("Delete", "U+007F");
keyMap().set("Tab", "U+0009");
keyMap().set("ISO_Left_Tab", "U+0009");
+ keyMap().set("BackSpace", "U+0008");
+ keyMap().set("space", "U+0020");
}
static void createWindowsKeyMap()
@@ -98,7 +100,7 @@ static void createWindowsKeyMap()
windowsKeyMap().set("Tab", VK_TAB);
windowsKeyMap().set("ISO_Left_Tab", VK_TAB);
windowsKeyMap().set("BackSpace", VK_BACK);
- windowsKeyMap().set("Space", VK_SPACE);
+ windowsKeyMap().set("space", VK_SPACE);
windowsKeyMap().set("Next", VK_NEXT);
windowsKeyMap().set("Prior", VK_PRIOR);
windowsKeyMap().set("Home", VK_HOME);
@@ -162,7 +164,7 @@ static void createWindowsKeyMap()
// Set F_XX keys to the windowsKeyMap.
for (unsigned int i = 1; i < 25; i++) {
String key = "F" + String::number(i);
- windowsKeyMap().set(key, VK_F1 + i);
+ windowsKeyMap().set(key, VK_F1 + i - 1);
}
}
diff --git a/Source/WebCore/platform/efl/FileSystemEfl.cpp b/Source/WebCore/platform/efl/FileSystemEfl.cpp
index d521d5404..d4adb169b 100644
--- a/Source/WebCore/platform/efl/FileSystemEfl.cpp
+++ b/Source/WebCore/platform/efl/FileSystemEfl.cpp
@@ -65,28 +65,6 @@ CString fileSystemRepresentation(const String& path)
#endif
}
-String openTemporaryFile(const String& prefix, PlatformFileHandle& handle)
-{
- char buffer[PATH_MAX];
- const char* tmpDir = getenv("TMPDIR");
-
- if (!tmpDir)
- tmpDir = "/tmp";
-
- if (snprintf(buffer, PATH_MAX, "%s/%sXXXXXX", tmpDir, prefix.utf8().data()) >= PATH_MAX)
- goto end;
-
- handle = mkstemp(buffer);
- if (handle < 0)
- goto end;
-
- return String::fromUTF8(buffer);
-
-end:
- handle = invalidPlatformFileHandle;
- return String();
-}
-
bool unloadModule(PlatformModule module)
{
// caution, closing handle will make memory vanish and any remaining
diff --git a/Source/WebCore/platform/efl/LocalizedStringsEfl.cpp b/Source/WebCore/platform/efl/LocalizedStringsEfl.cpp
index 27240e82b..32aefe1a3 100644
--- a/Source/WebCore/platform/efl/LocalizedStringsEfl.cpp
+++ b/Source/WebCore/platform/efl/LocalizedStringsEfl.cpp
@@ -379,6 +379,11 @@ String AXDefinitionListDefinitionText()
return String::fromUTF8("definition");
}
+String AXFooterRoleDescriptionText()
+{
+ return String::fromUTF8("footer");
+}
+
String AXButtonActionVerb()
{
return String::fromUTF8("press");
diff --git a/Source/WebCore/platform/efl/RefPtrEfl.h b/Source/WebCore/platform/efl/RefPtrEfl.h
index f5c2c8e51..48152842d 100644
--- a/Source/WebCore/platform/efl/RefPtrEfl.h
+++ b/Source/WebCore/platform/efl/RefPtrEfl.h
@@ -20,7 +20,7 @@
#ifndef RefPtrEfl_h
#define RefPtrEfl_h
-#include "RefPtr.h"
+#include <wtf/RefPtr.h>
typedef struct _Evas_Object Evas_Object;
diff --git a/Source/WebCore/platform/efl/RenderThemeEfl.cpp b/Source/WebCore/platform/efl/RenderThemeEfl.cpp
index 2140fe8be..5851a6041 100644
--- a/Source/WebCore/platform/efl/RenderThemeEfl.cpp
+++ b/Source/WebCore/platform/efl/RenderThemeEfl.cpp
@@ -175,6 +175,9 @@ struct RenderThemeEfl::ThemePartCacheEntry* RenderThemeEfl::cacheThemePartNew(Fo
return 0;
}
+ // By default EFL creates buffers without alpha.
+ ecore_evas_alpha_set(entry->ee, EINA_TRUE);
+
entry->o = edje_object_add(ecore_evas_get(entry->ee));
ASSERT(entry->o);
if (!themePartCacheEntryReset(entry, type)) {
@@ -841,10 +844,10 @@ bool RenderThemeEfl::paintSliderTrack(RenderObject* object, const PaintInfo& inf
return paintThemePart(object, SliderVertical, info, rect);
}
-void RenderThemeEfl::adjustSliderTrackStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeEfl::adjustSliderTrackStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
if (!m_page && element && element->document()->page()) {
- static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSliderTrackStyle(selector, style, element);
+ static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSliderTrackStyle(styleResolver, style, element);
return;
}
@@ -858,10 +861,10 @@ void RenderThemeEfl::adjustSliderTrackStyle(CSSStyleSelector* selector, RenderSt
style->setHeight(desc->min.height());
}
-void RenderThemeEfl::adjustSliderThumbStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeEfl::adjustSliderThumbStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
- RenderTheme::adjustSliderThumbStyle(selector, style, element);
- adjustSliderTrackStyle(selector, style, element);
+ RenderTheme::adjustSliderThumbStyle(styleResolver, style, element);
+ adjustSliderTrackStyle(styleResolver, style, element);
}
void RenderThemeEfl::adjustSliderThumbSize(RenderStyle* style) const
@@ -885,10 +888,10 @@ bool RenderThemeEfl::paintSliderThumb(RenderObject* object, const PaintInfo& inf
return false;
}
-void RenderThemeEfl::adjustCheckboxStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeEfl::adjustCheckboxStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
if (!m_page && element && element->document()->page()) {
- static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustCheckboxStyle(selector, style, element);
+ static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustCheckboxStyle(styleResolver, style, element);
return;
}
adjustSizeConstraints(style, CheckBox);
@@ -906,10 +909,10 @@ bool RenderThemeEfl::paintCheckbox(RenderObject* object, const PaintInfo& info,
return paintThemePart(object, CheckBox, info, rect);
}
-void RenderThemeEfl::adjustRadioStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeEfl::adjustRadioStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
if (!m_page && element && element->document()->page()) {
- static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustRadioStyle(selector, style, element);
+ static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustRadioStyle(styleResolver, style, element);
return;
}
adjustSizeConstraints(style, RadioButton);
@@ -927,10 +930,10 @@ bool RenderThemeEfl::paintRadio(RenderObject* object, const PaintInfo& info, con
return paintThemePart(object, RadioButton, info, rect);
}
-void RenderThemeEfl::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeEfl::adjustButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
if (!m_page && element && element->document()->page()) {
- static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustButtonStyle(selector, style, element);
+ static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustButtonStyle(styleResolver, style, element);
return;
}
@@ -950,10 +953,10 @@ bool RenderThemeEfl::paintButton(RenderObject* object, const PaintInfo& info, co
return paintThemePart(object, Button, info, rect);
}
-void RenderThemeEfl::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeEfl::adjustMenuListStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
if (!m_page && element && element->document()->page()) {
- static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustMenuListStyle(selector, style, element);
+ static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustMenuListStyle(styleResolver, style, element);
return;
}
adjustSizeConstraints(style, ComboBox);
@@ -968,9 +971,9 @@ bool RenderThemeEfl::paintMenuList(RenderObject* object, const PaintInfo& info,
return paintThemePart(object, ComboBox, info, rect);
}
-void RenderThemeEfl::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeEfl::adjustMenuListButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
- adjustMenuListStyle(selector, style, element);
+ adjustMenuListStyle(styleResolver, style, element);
}
bool RenderThemeEfl::paintMenuListButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
@@ -978,10 +981,10 @@ bool RenderThemeEfl::paintMenuListButton(RenderObject* object, const PaintInfo&
return paintMenuList(object, info, rect);
}
-void RenderThemeEfl::adjustTextFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeEfl::adjustTextFieldStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
if (!m_page && element && element->document()->page()) {
- static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustTextFieldStyle(selector, style, element);
+ static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustTextFieldStyle(styleResolver, style, element);
return;
}
adjustSizeConstraints(style, TextField);
@@ -996,9 +999,9 @@ bool RenderThemeEfl::paintTextField(RenderObject* object, const PaintInfo& info,
return paintThemePart(object, TextField, info, rect);
}
-void RenderThemeEfl::adjustTextAreaStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeEfl::adjustTextAreaStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
- adjustTextFieldStyle(selector, style, element);
+ adjustTextFieldStyle(styleResolver, style, element);
}
bool RenderThemeEfl::paintTextArea(RenderObject* object, const PaintInfo& info, const IntRect& rect)
@@ -1006,10 +1009,10 @@ bool RenderThemeEfl::paintTextArea(RenderObject* object, const PaintInfo& info,
return paintTextField(object, info, rect);
}
-void RenderThemeEfl::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeEfl::adjustSearchFieldDecorationStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
if (!m_page && element && element->document()->page()) {
- static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldDecorationStyle(selector, style, element);
+ static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldDecorationStyle(styleResolver, style, element);
return;
}
adjustSizeConstraints(style, SearchFieldDecoration);
@@ -1022,10 +1025,10 @@ bool RenderThemeEfl::paintSearchFieldDecoration(RenderObject* object, const Pain
return paintThemePart(object, SearchFieldDecoration, info, rect);
}
-void RenderThemeEfl::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeEfl::adjustSearchFieldResultsButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
if (!m_page && element && element->document()->page()) {
- static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldResultsButtonStyle(selector, style, element);
+ static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldResultsButtonStyle(styleResolver, style, element);
return;
}
adjustSizeConstraints(style, SearchFieldResultsButton);
@@ -1038,10 +1041,10 @@ bool RenderThemeEfl::paintSearchFieldResultsButton(RenderObject* object, const P
return paintThemePart(object, SearchFieldResultsButton, info, rect);
}
-void RenderThemeEfl::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeEfl::adjustSearchFieldResultsDecorationStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
if (!m_page && element && element->document()->page()) {
- static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldResultsDecorationStyle(selector, style, element);
+ static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldResultsDecorationStyle(styleResolver, style, element);
return;
}
adjustSizeConstraints(style, SearchFieldResultsDecoration);
@@ -1054,10 +1057,10 @@ bool RenderThemeEfl::paintSearchFieldResultsDecoration(RenderObject* object, con
return paintThemePart(object, SearchFieldResultsDecoration, info, rect);
}
-void RenderThemeEfl::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeEfl::adjustSearchFieldCancelButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
if (!m_page && element && element->document()->page()) {
- static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldCancelButtonStyle(selector, style, element);
+ static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldCancelButtonStyle(styleResolver, style, element);
return;
}
adjustSizeConstraints(style, SearchFieldCancelButton);
@@ -1070,10 +1073,10 @@ bool RenderThemeEfl::paintSearchFieldCancelButton(RenderObject* object, const Pa
return paintThemePart(object, SearchFieldCancelButton, info, rect);
}
-void RenderThemeEfl::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeEfl::adjustSearchFieldStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
if (!m_page && element && element->document()->page()) {
- static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldStyle(selector, style, element);
+ static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldStyle(styleResolver, style, element);
return;
}
adjustSizeConstraints(style, SearchField);
@@ -1109,7 +1112,7 @@ void RenderThemeEfl::systemFont(int propId, FontDescription& fontDescription) co
}
#if ENABLE(PROGRESS_TAG)
-void RenderThemeEfl::adjustProgressBarStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeEfl::adjustProgressBarStyle(StyleResolver*, RenderStyle* style, Element*) const
{
style->setBoxShadow(nullptr);
}
@@ -1152,7 +1155,7 @@ bool RenderThemeEfl::emitMediaButtonSignal(FormType formType, MediaControlElemen
edje_object_signal_emit(entry->o, "seekforward", "");
else if (mediaElementType == MediaSeekBackButton)
edje_object_signal_emit(entry->o, "seekbackward", "");
- else if (mediaElementType == MediaFullscreenButton)
+ else if (mediaElementType == MediaEnterFullscreenButton)
edje_object_signal_emit(entry->o, "fullscreen", "");
else
return false;
@@ -1176,7 +1179,7 @@ bool RenderThemeEfl::paintMediaFullscreenButton(RenderObject* object, const Pain
if (!mediaNode || (!mediaNode->hasTagName(videoTag)))
return false;
- if (!emitMediaButtonSignal(FullScreenButton, MediaFullscreenButton, rect))
+ if (!emitMediaButtonSignal(FullScreenButton, MediaEnterFullscreenButton, rect))
return false;
return paintThemePart(object, FullScreenButton, info, rect);
diff --git a/Source/WebCore/platform/efl/RenderThemeEfl.h b/Source/WebCore/platform/efl/RenderThemeEfl.h
index cef32b85f..d15ee0bce 100644
--- a/Source/WebCore/platform/efl/RenderThemeEfl.h
+++ b/Source/WebCore/platform/efl/RenderThemeEfl.h
@@ -117,46 +117,46 @@ public:
// System fonts.
virtual void systemFont(int propId, FontDescription&) const;
- virtual void adjustCheckboxStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustCheckboxStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintCheckbox(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustRadioStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustRadioStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintRadio(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSliderTrackStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSliderThumbStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual void adjustSliderThumbSize(RenderStyle*) const;
@@ -165,7 +165,7 @@ public:
static void setDefaultFontSize(int fontsize);
#if ENABLE(PROGRESS_TAG)
- virtual void adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&);
virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const;
virtual double animationDurationForProgressBar(RenderProgress*) const;
diff --git a/Source/WebCore/platform/efl/RunLoopEfl.cpp b/Source/WebCore/platform/efl/RunLoopEfl.cpp
index e820788d6..f299d8ecf 100644
--- a/Source/WebCore/platform/efl/RunLoopEfl.cpp
+++ b/Source/WebCore/platform/efl/RunLoopEfl.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2012 ProFUSION embedded systems. All rights reserved.
+ * Copyright (C) 2012 Samsung Electronics
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,23 +27,122 @@
#include "config.h"
#include "RunLoop.h"
-#include "NotImplemented.h"
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Ecore_File.h>
+#include <Edje.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+static const int ecorePipeMessageSize = 1;
+static const char wakupEcorePipeMessage[] = "W";
namespace WebCore {
RunLoop::RunLoop()
+ : m_initEfl(false)
{
- notImplemented();
+ if (!ecore_init()) {
+ LOG_ERROR("could not init ecore.");
+ return;
+ }
+
+ if (!ecore_evas_init()) {
+ LOG_ERROR("could not init ecore_evas.");
+ goto errorEcoreEvas;
+ }
+
+ if (!ecore_file_init()) {
+ LOG_ERROR("could not init ecore_file.");
+ goto errorEcoreFile;
+ }
+
+ if (!edje_init()) {
+ LOG_ERROR("could not init edje.");
+ goto errorEdje;
+ }
+
+ m_pipe = adoptPtr(ecore_pipe_add(wakeUpEvent, this));
+ m_initEfl = true;
+
+ return;
+
+errorEdje:
+ ecore_file_shutdown();
+errorEcoreFile:
+ ecore_evas_shutdown();
+errorEcoreEvas:
+ ecore_shutdown();
}
RunLoop::~RunLoop()
{
- notImplemented();
+ if (m_initEfl) {
+ edje_shutdown();
+ ecore_file_shutdown();
+ ecore_evas_shutdown();
+ ecore_shutdown();
+ }
+}
+
+void RunLoop::run()
+{
+ ecore_main_loop_begin();
+}
+
+void RunLoop::stop()
+{
+ ecore_main_loop_quit();
+}
+
+void RunLoop::wakeUpEvent(void* data, void*, unsigned int)
+{
+ static_cast<RunLoop*>(data)->performWork();
}
void RunLoop::wakeUp()
{
- notImplemented();
+ ecore_pipe_write(m_pipe.get(), wakupEcorePipeMessage, ecorePipeMessageSize);
+}
+
+RunLoop::TimerBase::TimerBase(RunLoop*)
+ : m_isRepeating(false)
+{
+}
+
+RunLoop::TimerBase::~TimerBase()
+{
+ stop();
+}
+
+bool RunLoop::TimerBase::timerFired(void* data)
+{
+ RunLoop::TimerBase* timer = static_cast<RunLoop::TimerBase*>(data);
+
+ timer->fired();
+
+ if (!timer->m_isRepeating) {
+ timer->m_timer = nullptr;
+ return ECORE_CALLBACK_CANCEL;
+ }
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+void RunLoop::TimerBase::start(double nextFireInterval, bool repeat)
+{
+ m_isRepeating = repeat;
+ m_timer = adoptPtr(ecore_timer_add(nextFireInterval, reinterpret_cast<Ecore_Task_Cb>(timerFired), this));
+}
+
+void RunLoop::TimerBase::stop()
+{
+ m_timer = nullptr;
+}
+
+bool RunLoop::TimerBase::isActive() const
+{
+ return (m_timer) ? true : false;
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/BitmapImage.cpp b/Source/WebCore/platform/graphics/BitmapImage.cpp
index a8957601f..55a98c96f 100644
--- a/Source/WebCore/platform/graphics/BitmapImage.cpp
+++ b/Source/WebCore/platform/graphics/BitmapImage.cpp
@@ -73,6 +73,17 @@ BitmapImage::~BitmapImage()
stopAnimation();
}
+bool BitmapImage::isBitmapImage() const
+{
+ return true;
+}
+
+bool BitmapImage::hasSingleSecurityOrigin() const
+{
+ return true;
+}
+
+
void BitmapImage::destroyDecodedData(bool destroyAll)
{
int framesCleared = 0;
@@ -128,6 +139,7 @@ void BitmapImage::cacheFrame(size_t index)
if (numFrames == 1 && m_frames[index].m_frame)
checkForSolidColor();
+ m_frames[index].m_orientation = m_source.orientationAtIndex(index);
m_frames[index].m_haveMetadata = true;
m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index);
if (repetitionCount(false) != cAnimationNone)
@@ -171,12 +183,24 @@ IntSize BitmapImage::size() const
{
if (m_sizeAvailable && !m_haveSize) {
m_size = m_source.size();
+ m_sizeRespectingOrientation = m_source.size(RespectImageOrientation);
m_haveSize = true;
didDecodeProperties();
}
return m_size;
}
+IntSize BitmapImage::sizeRespectingOrientation() const
+{
+ if (m_sizeAvailable && !m_haveSize) {
+ m_size = m_source.size();
+ m_sizeRespectingOrientation = m_source.size(RespectImageOrientation);
+ m_haveSize = true;
+ didDecodeProperties();
+ }
+ return m_sizeRespectingOrientation;
+}
+
IntSize BitmapImage::currentFrameSize() const
{
if (!m_currentFrame || m_hasUniformFrameSize)
@@ -257,50 +281,75 @@ bool BitmapImage::isSizeAvailable()
return m_sizeAvailable;
}
-NativeImagePtr BitmapImage::frameAtIndex(size_t index)
+bool BitmapImage::ensureFrameIsCached(size_t index)
{
if (index >= frameCount())
- return 0;
+ return false;
if (index >= m_frames.size() || !m_frames[index].m_frame)
cacheFrame(index);
+ return true;
+}
+NativeImagePtr BitmapImage::frameAtIndex(size_t index)
+{
+ if (!ensureFrameIsCached(index))
+ return 0;
return m_frames[index].m_frame;
}
bool BitmapImage::frameIsCompleteAtIndex(size_t index)
{
- if (index >= frameCount())
- return true;
-
- if (index >= m_frames.size() || !m_frames[index].m_haveMetadata)
- cacheFrame(index);
-
+ if (!ensureFrameIsCached(index))
+ return true; // Why would an invalid index return true here?
return m_frames[index].m_isComplete;
}
float BitmapImage::frameDurationAtIndex(size_t index)
{
- if (index >= frameCount())
+ if (!ensureFrameIsCached(index))
return 0;
-
- if (index >= m_frames.size() || !m_frames[index].m_haveMetadata)
- cacheFrame(index);
-
return m_frames[index].m_duration;
}
+NativeImagePtr BitmapImage::nativeImageForCurrentFrame()
+{
+ return frameAtIndex(currentFrame());
+}
+
bool BitmapImage::frameHasAlphaAtIndex(size_t index)
{
- if (index >= frameCount())
- return true;
+ if (!ensureFrameIsCached(index))
+ return true; // Why does an invalid index mean alpha?
+ return m_frames[index].m_hasAlpha;
+}
- if (index >= m_frames.size() || !m_frames[index].m_haveMetadata)
- cacheFrame(index);
+bool BitmapImage::currentFrameHasAlpha()
+{
+ return frameHasAlphaAtIndex(currentFrame());
+}
- return m_frames[index].m_hasAlpha;
+ImageOrientation BitmapImage::currentFrameOrientation()
+{
+ return frameOrientationAtIndex(currentFrame());
+}
+
+ImageOrientation BitmapImage::frameOrientationAtIndex(size_t index)
+{
+ if (!ensureFrameIsCached(index))
+ return DefaultImageOrientation;
+ return m_frames[index].m_orientation;
}
+#if !ASSERT_DISABLED
+bool BitmapImage::notSolidColor()
+{
+ return size().width() != 1 || size().height() != 1 || frameCount() > 1;
+}
+#endif
+
+
+
int BitmapImage::repetitionCount(bool imageKnownToBeComplete)
{
if ((m_repetitionCountStatus == Unknown) || ((m_repetitionCountStatus == Uncertain) && imageKnownToBeComplete)) {
@@ -436,6 +485,13 @@ void BitmapImage::resetAnimation()
destroyDecodedDataIfNecessary(true);
}
+unsigned BitmapImage::decodedSize() const
+{
+ return m_decodedSize;
+}
+
+
+
void BitmapImage::advanceAnimation(Timer<BitmapImage>*)
{
internalAdvanceAnimation(false);
@@ -484,4 +540,29 @@ bool BitmapImage::internalAdvanceAnimation(bool skippingFrames)
return advancedAnimation;
}
+bool BitmapImage::mayFillWithSolidColor()
+{
+ if (!m_checkedForSolidColor && frameCount() > 0) {
+ checkForSolidColor();
+ // WINCE PORT: checkForSolidColor() doesn't set m_checkedForSolidColor until
+ // it gets enough information to make final decision.
+#if !OS(WINCE)
+ ASSERT(m_checkedForSolidColor);
+#endif
+ }
+ return m_isSolidColor && !m_currentFrame;
+}
+
+Color BitmapImage::solidColor() const
+{
+ return m_solidColor;
+}
+
+#if !USE(CG)
+void BitmapImage::draw(GraphicsContext* ctx, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator op, RespectImageOrientationEnum)
+{
+ draw(ctx, dstRect, srcRect, styleColorSpace, op);
+}
+#endif
+
}
diff --git a/Source/WebCore/platform/graphics/BitmapImage.h b/Source/WebCore/platform/graphics/BitmapImage.h
index 00802f69f..00f0c5e40 100644
--- a/Source/WebCore/platform/graphics/BitmapImage.h
+++ b/Source/WebCore/platform/graphics/BitmapImage.h
@@ -30,6 +30,7 @@
#include "Image.h"
#include "Color.h"
+#include "ImageOrientation.h"
#include "IntSize.h"
#if PLATFORM(MAC)
@@ -41,15 +42,18 @@ OBJC_CLASS NSImage;
typedef struct HBITMAP__ *HBITMAP;
#endif
+#if PLATFORM(WX)
+class wxBitmap;
+#endif
+
namespace WebCore {
struct FrameData;
}
namespace WTF {
- // FIXME: This declaration gives FrameData a default constructor that zeroes
- // all its data members, even though FrameData's default constructor defined
- // below does not zero all its data members. One of these must be wrong!
- template<> struct VectorTraits<WebCore::FrameData> : public SimpleClassVectorTraits { };
+ template<> struct VectorTraits<WebCore::FrameData> : public SimpleClassVectorTraits {
+ static const bool canInitializeWithMemset = false; // Not all FrameData members initialize to 0.
+ };
}
namespace WebCore {
@@ -65,6 +69,7 @@ struct FrameData {
public:
FrameData()
: m_frame(0)
+ , m_orientation(DefaultImageOrientation)
, m_duration(0)
, m_haveMetadata(false)
, m_isComplete(false)
@@ -82,6 +87,7 @@ public:
bool clear(bool clearMetadata);
NativeImagePtr m_frame;
+ ImageOrientation m_orientation;
float m_duration;
bool m_haveMetadata : 1;
bool m_isComplete : 1;
@@ -108,11 +114,12 @@ public:
}
~BitmapImage();
- virtual bool isBitmapImage() const { return true; }
+ virtual bool isBitmapImage() const;
- virtual bool hasSingleSecurityOrigin() const { return true; }
+ virtual bool hasSingleSecurityOrigin() const;
virtual IntSize size() const;
+ IntSize sizeRespectingOrientation() const;
IntSize currentFrameSize() const;
virtual bool getHotSpot(IntPoint&) const;
@@ -124,8 +131,8 @@ public:
// automatically pause once all observers no longer want to render the image anywhere.
virtual void stopAnimation();
virtual void resetAnimation();
-
- virtual unsigned decodedSize() const { return m_decodedSize; }
+
+ virtual unsigned decodedSize() const;
#if PLATFORM(MAC)
// Accessors for native image formats.
@@ -142,24 +149,34 @@ public:
#if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS))
static PassRefPtr<BitmapImage> create(HBITMAP);
#endif
+#if PLATFORM(WX)
+ static PassRefPtr<BitmapImage> create(const wxBitmap& bitmap)
+ {
+ return adoptRef(new BitmapImage(bitmap));
+ }
+#endif
#if PLATFORM(WIN)
virtual bool getHBITMAP(HBITMAP);
virtual bool getHBITMAPOfSize(HBITMAP, LPSIZE);
#endif
+#if USE(CAIRO)
+ static PassRefPtr<BitmapImage> create(cairo_surface_t*);
+#endif
+
#if PLATFORM(GTK)
virtual GdkPixbuf* getGdkPixbuf();
#endif
- virtual NativeImagePtr nativeImageForCurrentFrame() { return frameAtIndex(currentFrame()); }
+ virtual NativeImagePtr nativeImageForCurrentFrame();
bool frameHasAlphaAtIndex(size_t);
- virtual bool currentFrameHasAlpha() { return frameHasAlphaAtIndex(currentFrame()); }
+ virtual bool currentFrameHasAlpha();
+
+ ImageOrientation currentFrameOrientation();
+ ImageOrientation frameOrientationAtIndex(size_t);
#if !ASSERT_DISABLED
- virtual bool notSolidColor()
- {
- return size().width() != 1 || size().height() != 1 || frameCount() > 1;
- }
+ virtual bool notSolidColor();
#endif
protected:
@@ -171,11 +188,15 @@ protected:
BitmapImage(NativeImagePtr, ImageObserver* = 0);
BitmapImage(ImageObserver* = 0);
+#if PLATFORM(WX)
+ BitmapImage(const wxBitmap&);
+#endif
#if PLATFORM(WIN)
virtual void drawFrameMatchingSourceSize(GraphicsContext*, const FloatRect& dstRect, const IntSize& srcSize, ColorSpace styleColorSpace, CompositeOperator);
#endif
virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator);
+ void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator, RespectImageOrientationEnum);
#if (OS(WINCE) && !PLATFORM(QT))
virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform,
@@ -190,6 +211,8 @@ protected:
// Decodes and caches a frame. Never accessed except internally.
void cacheFrame(size_t index);
+ // Called before accessing m_frames[index]. Returns false on index out of bounds.
+ bool ensureFrameIsCached(size_t index);
// Called to invalidate cached data. When |destroyAll| is true, we wipe out
// the entire frame buffer cache and tell the image source to destroy
@@ -239,22 +262,12 @@ protected:
// changed.
void checkForSolidColor();
- virtual bool mayFillWithSolidColor()
- {
- if (!m_checkedForSolidColor && frameCount() > 0) {
- checkForSolidColor();
- // WINCE PORT: checkForSolidColor() doesn't set m_checkedForSolidColor until
- // it gets enough information to make final decision.
-#if !OS(WINCE)
- ASSERT(m_checkedForSolidColor);
-#endif
- }
- return m_isSolidColor && m_currentFrame == 0;
- }
- virtual Color solidColor() const { return m_solidColor; }
+ virtual bool mayFillWithSolidColor();
+ virtual Color solidColor() const;
ImageSource m_source;
mutable IntSize m_size; // The size to use for the overall image (will just be the size of the first image).
+ mutable IntSize m_sizeRespectingOrientation;
size_t m_currentFrame; // The index of the current frame of animation.
Vector<FrameData> m_frames; // An array of the cached frames of the animation. We have to ref frames to pin them in the cache.
diff --git a/Source/WebCore/platform/graphics/Color.h b/Source/WebCore/platform/graphics/Color.h
index 235f671c4..ddfe20f06 100644
--- a/Source/WebCore/platform/graphics/Color.h
+++ b/Source/WebCore/platform/graphics/Color.h
@@ -79,7 +79,7 @@ class Color {
WTF_MAKE_FAST_ALLOCATED;
public:
Color() : m_color(0), m_valid(false) { }
- Color(RGBA32 col) : m_color(col), m_valid(true) { }
+ Color(RGBA32 color, bool valid = true) : m_color(color), m_valid(valid) { ASSERT(!m_color || m_valid); }
Color(int r, int g, int b) : m_color(makeRGB(r, g, b)), m_valid(true) { }
Color(int r, int g, int b, int a) : m_color(makeRGBA(r, g, b, a)), m_valid(true) { }
// Color is currently limited to 32bit RGBA, perhaps some day we'll support better colors
diff --git a/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp b/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp
index 23c3f7251..27699070f 100644
--- a/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp
+++ b/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp
@@ -53,7 +53,7 @@ void DisplayRefreshMonitorClient::fireDisplayRefreshIfNeeded(double timestamp)
}
DisplayRefreshMonitor::DisplayRefreshMonitor(PlatformDisplayID displayID)
- : m_timestamp(0)
+ : m_monotonicAnimationStartTime(0)
, m_active(true)
, m_scheduled(false)
, m_previousFrameDone(true)
@@ -61,6 +61,9 @@ DisplayRefreshMonitor::DisplayRefreshMonitor(PlatformDisplayID displayID)
#if PLATFORM(MAC)
, m_displayLink(0)
#endif
+#if PLATFORM(BLACKBERRY)
+ , m_animationClient(0)
+#endif
{
}
@@ -72,15 +75,15 @@ void DisplayRefreshMonitor::refreshDisplayOnMainThread(void* data)
void DisplayRefreshMonitor::notifyClients()
{
- double timestamp;
+ double monotonicAnimationStartTime;
{
MutexLocker lock(m_mutex);
m_scheduled = false;
- timestamp = m_timestamp;
+ monotonicAnimationStartTime = m_monotonicAnimationStartTime;
}
for (size_t i = 0; i < m_clients.size(); ++i)
- m_clients[i]->fireDisplayRefreshIfNeeded(timestamp);
+ m_clients[i]->fireDisplayRefreshIfNeeded(monotonicAnimationStartTime);
{
MutexLocker lock(m_mutex);
diff --git a/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h b/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h
index 79df0d18f..0ee8101a2 100644
--- a/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h
+++ b/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h
@@ -31,6 +31,9 @@
#include "PlatformScreen.h"
#include <wtf/Threading.h>
#include <wtf/Vector.h>
+#if PLATFORM(BLACKBERRY)
+#include <BlackBerryPlatformAnimation.h>
+#endif
#if PLATFORM(MAC)
typedef struct __CVDisplayLink *CVDisplayLinkRef;
@@ -68,6 +71,17 @@ private:
PlatformDisplayID m_displayID;
};
+#if PLATFORM(BLACKBERRY)
+class DisplayAnimationClient : public BlackBerry::Platform::AnimationFrameRateClient {
+public:
+ DisplayAnimationClient(DisplayRefreshMonitor *);
+ ~DisplayAnimationClient() { }
+private:
+ virtual void animationFrameChanged();
+ DisplayRefreshMonitor *m_monitor;
+};
+#endif
+
//
// Monitor for display refresh messages for a given screen
//
@@ -97,8 +111,9 @@ public:
private:
void notifyClients();
-
- double m_timestamp;
+ static void refreshDisplayOnMainThread(void* data);
+
+ double m_monotonicAnimationStartTime;
bool m_active;
bool m_scheduled;
bool m_previousFrameDone;
@@ -106,13 +121,18 @@ private:
DisplayRefreshMonitorManager* m_manager;
Mutex m_mutex;
Vector<DisplayRefreshMonitorClient*> m_clients;
-
+#if PLATFORM(BLACKBERRY)
+public:
+ void displayLinkFired();
+private:
+ DisplayAnimationClient *m_animationClient;
+ void startAnimationClient();
+ void stopAnimationClient();
+#endif
#if PLATFORM(MAC)
public:
void displayLinkFired(double nowSeconds, double outputTimeSeconds);
private:
- static void refreshDisplayOnMainThread(void* data);
-
CVDisplayLinkRef m_displayLink;
#endif
};
diff --git a/Source/WebCore/platform/graphics/FloatQuad.h b/Source/WebCore/platform/graphics/FloatQuad.h
index b5e2a8ca4..bfb794def 100644
--- a/Source/WebCore/platform/graphics/FloatQuad.h
+++ b/Source/WebCore/platform/graphics/FloatQuad.h
@@ -88,6 +88,13 @@ public:
// from transformed rects.
bool containsQuad(const FloatQuad&) const;
+ // The center of the quad. If the quad is the result of a affine-transformed rectangle this is the same as the original center transformed.
+ FloatPoint center() const
+ {
+ return FloatPoint((m_p1.x() + m_p2.x() + m_p3.x() + m_p4.x()) / 4.0,
+ (m_p1.y() + m_p2.y() + m_p3.y() + m_p4.y()) / 4.0);
+ }
+
FloatRect boundingBox() const;
IntRect enclosingBoundingBox() const
{
diff --git a/Source/WebCore/platform/graphics/FloatRect.cpp b/Source/WebCore/platform/graphics/FloatRect.cpp
index 737473c3f..b43fc74a2 100644
--- a/Source/WebCore/platform/graphics/FloatRect.cpp
+++ b/Source/WebCore/platform/graphics/FloatRect.cpp
@@ -77,7 +77,7 @@ bool FloatRect::contains(const FloatPoint& point, ContainsMode containsMode) con
{
if (containsMode == InsideOrOnStroke)
return contains(point.x(), point.y());
- return x() < point.x() && maxX() > point.x() && y() < point.y() && maxY() > y();
+ return x() < point.x() && maxX() > point.x() && y() < point.y() && maxY() > point.y();
}
void FloatRect::intersect(const FloatRect& other)
@@ -236,6 +236,11 @@ IntRect enclosedIntRect(const FloatRect& rect)
return IntRect(x, y, width, height);
}
+IntRect roundedIntRect(const FloatRect& rect)
+{
+ return IntRect(roundedIntPoint(rect.location()), roundedIntSize(rect.size()));
+}
+
FloatRect mapRect(const FloatRect& r, const FloatRect& srcRect, const FloatRect& destRect)
{
if (srcRect.width() == 0 || srcRect.height() == 0)
diff --git a/Source/WebCore/platform/graphics/FloatRect.h b/Source/WebCore/platform/graphics/FloatRect.h
index 66b29f84b..725012fd7 100644
--- a/Source/WebCore/platform/graphics/FloatRect.h
+++ b/Source/WebCore/platform/graphics/FloatRect.h
@@ -288,6 +288,8 @@ IntRect enclosingIntRect(const FloatRect&);
// Returns a valid IntRect contained within the given FloatRect.
IntRect enclosedIntRect(const FloatRect&);
+IntRect roundedIntRect(const FloatRect&);
+
// Map rect r from srcRect to an equivalent rect in destRect.
FloatRect mapRect(const FloatRect& r, const FloatRect& srcRect, const FloatRect& destRect);
diff --git a/Source/WebCore/platform/graphics/FloatSize.h b/Source/WebCore/platform/graphics/FloatSize.h
index 3b35510be..050fbd0d9 100644
--- a/Source/WebCore/platform/graphics/FloatSize.h
+++ b/Source/WebCore/platform/graphics/FloatSize.h
@@ -178,6 +178,11 @@ inline IntSize roundedIntSize(const FloatSize& p)
return IntSize(static_cast<int>(roundf(p.width())), static_cast<int>(roundf(p.height())));
}
+inline IntSize flooredIntSize(const FloatSize& p)
+{
+ return IntSize(static_cast<int>(p.width()), static_cast<int>(p.height()));
+}
+
inline IntSize expandedIntSize(const FloatSize& p)
{
return IntSize(clampToInteger(ceilf(p.width())), clampToInteger(ceilf(p.height())));
diff --git a/Source/WebCore/platform/graphics/Font.cpp b/Source/WebCore/platform/graphics/Font.cpp
index 50eee53a7..de74a2b9b 100644
--- a/Source/WebCore/platform/graphics/Font.cpp
+++ b/Source/WebCore/platform/graphics/Font.cpp
@@ -27,9 +27,6 @@
#include "FloatRect.h"
#include "FontCache.h"
#include "FontTranscoder.h"
-#if PLATFORM(QT) && HAVE(QRAWFONT)
-#include "GraphicsContext.h"
-#endif
#include "IntPoint.h"
#include "GlyphBuffer.h"
#include "TextRun.h"
@@ -151,11 +148,6 @@ void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoi
CodePath codePathToUse = codePath(run);
-#if PLATFORM(QT) && HAVE(QRAWFONT)
- if (context->textDrawingMode() & TextModeStroke)
- codePathToUse = Complex;
-#endif
-
if (codePathToUse != Complex)
return drawSimpleText(context, run, point, from, to);
@@ -274,17 +266,27 @@ Font::CodePath Font::codePath(const TextRun& run) const
if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings()->size() > 0)
return Complex;
+
+ if (run.length() > 1 && typesettingFeatures())
+ return Complex;
- CodePath result = Simple;
+ if (!run.characterScanForCodePath())
+ return Simple;
- // Start from 0 since drawing and highlighting also measure the characters before run->from
+ // Start from 0 since drawing and highlighting also measure the characters before run->from.
+ return characterRangeCodePath(run.characters(), run.length());
+}
+
+Font::CodePath Font::characterRangeCodePath(const UChar* characters, unsigned len)
+{
// FIXME: Should use a UnicodeSet in ports where ICU is used. Note that we
// can't simply use UnicodeCharacter Property/class because some characters
// are not 'combining', but still need to go to the complex path.
// Alternatively, we may as well consider binary search over a sorted
// list of ranges.
- for (int i = 0; i < run.length(); i++) {
- const UChar c = run[i];
+ CodePath result = Simple;
+ for (unsigned i = 0; i < len; i++) {
+ const UChar c = characters[i];
if (c < 0x2E5) // U+02E5 through U+02E9 (Modifier Letters : Tone letters)
continue;
if (c <= 0x2E9)
@@ -391,10 +393,10 @@ Font::CodePath Font::codePath(const TextRun& run) const
if (c <= 0xDBFF) {
// High surrogate
- if (i == run.length() - 1)
+ if (i == len - 1)
continue;
- UChar next = run[++i];
+ UChar next = characters[++i];
if (!U16_IS_TRAIL(next))
continue;
@@ -426,10 +428,6 @@ Font::CodePath Font::codePath(const TextRun& run) const
if (c <= 0xFE2F)
return Complex;
}
-
- if (run.length() > 1 && typesettingFeatures())
- return Complex;
-
return result;
}
diff --git a/Source/WebCore/platform/graphics/Font.h b/Source/WebCore/platform/graphics/Font.h
index d15a77f3c..5b73404e6 100644
--- a/Source/WebCore/platform/graphics/Font.h
+++ b/Source/WebCore/platform/graphics/Font.h
@@ -36,8 +36,13 @@
#include <wtf/unicode/CharacterNames.h>
#if PLATFORM(QT)
+#if HAVE(QRAWFONT)
+#include <QRawFont>
+class QTextLayout;
+#else
#include <QFont>
#endif
+#endif
namespace WebCore {
@@ -175,15 +180,21 @@ public:
static unsigned expansionOpportunityCount(const UChar*, size_t length, TextDirection, bool& isAfterExpansion);
#if PLATFORM(QT)
+#if HAVE(QRAWFONT)
+ QRawFont rawFont() const;
+#else
QFont font() const;
#endif
+ QFont syntheticFont() const;
+#endif
static void setShouldUseSmoothing(bool);
static bool shouldUseSmoothing();
enum CodePath { Auto, Simple, Complex, SimpleWithGlyphOverflow };
CodePath codePath(const TextRun&) const;
-
+ static CodePath characterRangeCodePath(const UChar*, unsigned len);
+
private:
enum ForTextEmphasisOrNot { NotForTextEmphasis, ForTextEmphasis };
@@ -229,7 +240,7 @@ public:
FontSelector* fontSelector() const;
static bool treatAsSpace(UChar c) { return c == ' ' || c == '\t' || c == '\n' || c == noBreakSpace; }
static bool treatAsZeroWidthSpace(UChar c) { return treatAsZeroWidthSpaceInComplexScript(c) || c == 0x200c || c == 0x200d; }
- static bool treatAsZeroWidthSpaceInComplexScript(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || c == softHyphen || (c >= 0x200e && c <= 0x200f) || (c >= 0x202a && c <= 0x202e) || c == zeroWidthNoBreakSpace || c == objectReplacementCharacter; }
+ static bool treatAsZeroWidthSpaceInComplexScript(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || c == softHyphen || c == zeroWidthSpace || (c >= 0x200e && c <= 0x200f) || (c >= 0x202a && c <= 0x202e) || c == zeroWidthNoBreakSpace || c == objectReplacementCharacter; }
static bool canReceiveTextEmphasis(UChar32 c);
static inline UChar normalizeSpaces(UChar character)
@@ -253,6 +264,9 @@ private:
{
return m_fontList && m_fontList->loadingCustomFonts();
}
+#if PLATFORM(QT) && HAVE(QRAWFONT)
+ void initFormatForTextLayout(QTextLayout*) const;
+#endif
FontDescription m_fontDescription;
mutable RefPtr<FontFallbackList> m_fontList;
diff --git a/Source/WebCore/platform/graphics/FontCache.h b/Source/WebCore/platform/graphics/FontCache.h
index ed399bbc8..9063ca7a2 100644
--- a/Source/WebCore/platform/graphics/FontCache.h
+++ b/Source/WebCore/platform/graphics/FontCache.h
@@ -130,6 +130,9 @@ private:
// Don't purge if this count is > 0;
int m_purgePreventCount;
+#if USE(CORE_TEXT) || OS(ANDROID)
+ friend class ComplexTextController;
+#endif
friend class SimpleFontData; // For getCachedFontData(const FontPlatformData*)
friend class FontFallbackList;
};
diff --git a/Source/WebCore/platform/graphics/FontDescription.cpp b/Source/WebCore/platform/graphics/FontDescription.cpp
index 46d108fe1..7c3bc65a5 100644
--- a/Source/WebCore/platform/graphics/FontDescription.cpp
+++ b/Source/WebCore/platform/graphics/FontDescription.cpp
@@ -32,6 +32,18 @@
namespace WebCore {
+struct SameSizeAsFontDescription {
+ FontFamily familyList;
+ void* settings;
+ RefPtr<FontFeatureSettings> m_featureSettings;
+ float sizes[2];
+ // FXIME: Make them fit into one word.
+ uint32_t bitfields;
+ uint32_t bitfields2 : 8;
+};
+
+COMPILE_ASSERT(sizeof(FontDescription) == sizeof(SameSizeAsFontDescription), FontDescription_should_stay_small);
+
FontWeight FontDescription::lighterWeight(void) const
{
// FIXME: Should actually return the CSS weight corresponding to next lightest
diff --git a/Source/WebCore/platform/graphics/FontDescription.h b/Source/WebCore/platform/graphics/FontDescription.h
index e8329763d..86b8dfb8d 100644
--- a/Source/WebCore/platform/graphics/FontDescription.h
+++ b/Source/WebCore/platform/graphics/FontDescription.h
@@ -182,11 +182,11 @@ private:
unsigned m_italic : 1; // FontItalic
unsigned m_smallCaps : 1; // FontSmallCaps
- bool m_isAbsoluteSize : 1; // Whether or not CSS specified an explicit size
- // (logical sizes like "medium" don't count).
+ unsigned m_isAbsoluteSize : 1; // Whether or not CSS specified an explicit size
+ // (logical sizes like "medium" don't count).
unsigned m_weight : 8; // FontWeight
unsigned m_genericFamily : 3; // GenericFamilyType
- bool m_usePrinterFont : 1;
+ unsigned m_usePrinterFont : 1;
unsigned m_renderingMode : 1; // Used to switch between CG and GDI text on Windows.
unsigned m_kerning : 2; // Kerning
@@ -201,7 +201,7 @@ private:
unsigned m_fontSmoothing : 2; // FontSmoothingMode
unsigned m_textRendering : 2; // TextRenderingMode
- bool m_isSpecifiedFont : 1; // True if a web page specifies a non-generic font family as the first font family.
+ unsigned m_isSpecifiedFont : 1; // True if a web page specifies a non-generic font family as the first font family.
UScriptCode m_script; // Used to help choose an appropriate font for generic font families.
};
diff --git a/Source/WebCore/platform/graphics/FontPlatformData.cpp b/Source/WebCore/platform/graphics/FontPlatformData.cpp
index 5a61cdf01..a1d274aa8 100644
--- a/Source/WebCore/platform/graphics/FontPlatformData.cpp
+++ b/Source/WebCore/platform/graphics/FontPlatformData.cpp
@@ -39,6 +39,10 @@ FontPlatformData::FontPlatformData(const FontPlatformData& source)
, m_size(source.m_size)
, m_widthVariant(source.m_widthVariant)
, m_isColorBitmapFont(source.m_isColorBitmapFont)
+ , m_isCompositeFontReference(source.m_isCompositeFontReference)
+#if OS(DARWIN)
+ , m_isPrinterFont(source.m_isPrinterFont)
+#endif
{
platformDataInit(source);
}
@@ -56,6 +60,10 @@ const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& othe
m_size = other.m_size;
m_widthVariant = other.m_widthVariant;
m_isColorBitmapFont = other.m_isColorBitmapFont;
+ m_isCompositeFontReference = other.m_isCompositeFontReference;
+#if OS(DARWIN)
+ m_isPrinterFont = other.m_isPrinterFont;
+#endif
return platformDataAssign(other);
}
diff --git a/Source/WebCore/platform/graphics/FontPlatformData.h b/Source/WebCore/platform/graphics/FontPlatformData.h
index 705c58897..e822e506d 100644
--- a/Source/WebCore/platform/graphics/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/FontPlatformData.h
@@ -23,7 +23,7 @@
*/
// FIXME: This is temporary until all ports switch to using this file.
-#if PLATFORM(CHROMIUM) && !OS(DARWIN)
+#if (PLATFORM(CHROMIUM) && !OS(DARWIN)) || PLATFORM(BLACKBERRY)
#include "chromium/FontPlatformData.h"
#elif PLATFORM(QT)
#include "qt/FontPlatformData.h"
@@ -50,7 +50,7 @@
#endif
#if USE(CAIRO)
-#include "HashFunctions.h"
+#include <wtf/HashFunctions.h>
#include <cairo.h>
#endif
@@ -91,6 +91,7 @@ typedef UInt32 ATSFontRef;
namespace WebCore {
class FontDescription;
+class SharedBuffer;
#if OS(DARWIN)
inline CTFontRef toCTFontRef(NSFont *nsFont) { return reinterpret_cast<CTFontRef>(nsFont); }
@@ -116,6 +117,10 @@ public:
, m_scaledFont(hashTableDeletedFontValue())
#endif
, m_isColorBitmapFont(false)
+ , m_isCompositeFontReference(false)
+#if OS(DARWIN)
+ , m_isPrinterFont(false)
+#endif
#if PLATFORM(WIN)
, m_useGDI(false)
#endif
@@ -138,6 +143,10 @@ public:
, m_scaledFont(0)
#endif
, m_isColorBitmapFont(false)
+ , m_isCompositeFontReference(false)
+#if OS(DARWIN)
+ , m_isPrinterFont(false)
+#endif
#if PLATFORM(WIN)
, m_useGDI(false)
#endif
@@ -163,6 +172,10 @@ public:
, m_scaledFont(0)
#endif
, m_isColorBitmapFont(false)
+ , m_isCompositeFontReference(false)
+#if OS(DARWIN)
+ , m_isPrinterFont(false)
+#endif
#if PLATFORM(WIN)
, m_useGDI(false)
#endif
@@ -170,8 +183,8 @@ public:
}
#if OS(DARWIN)
- FontPlatformData(NSFont*, float size, bool syntheticBold = false, bool syntheticOblique = false, FontOrientation = Horizontal,
- TextOrientation = TextOrientationVerticalRight, FontWidthVariant = RegularWidth);
+ FontPlatformData(NSFont*, float size, bool isPrinterFont = false, bool syntheticBold = false, bool syntheticOblique = false,
+ FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight, FontWidthVariant = RegularWidth);
#if USE(CG) || USE(SKIA_ON_MAC_CHROMIUM)
FontPlatformData(CGFontRef cgFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation,
TextOrientation textOrientation, FontWidthVariant widthVariant)
@@ -184,6 +197,8 @@ public:
, m_font(0)
, m_cgFont(cgFont)
, m_isColorBitmapFont(false)
+ , m_isCompositeFontReference(false)
+ , m_isPrinterFont(false)
{
}
#endif
@@ -226,6 +241,10 @@ public:
bool syntheticBold() const { return m_syntheticBold; }
bool syntheticOblique() const { return m_syntheticOblique; }
bool isColorBitmapFont() const { return m_isColorBitmapFont; }
+ bool isCompositeFontReference() const { return m_isCompositeFontReference; }
+#if OS(DARWIN)
+ bool isPrinterFont() const { return m_isPrinterFont; }
+#endif
FontOrientation orientation() const { return m_orientation; }
TextOrientation textOrientation() const { return m_textOrientation; }
FontWidthVariant widthVariant() const { return m_widthVariant; }
@@ -244,7 +263,7 @@ public:
#if USE(CG) || USE(SKIA_ON_MAC_CHROMIUM)
ASSERT(m_font || !m_cgFont);
#endif
- uintptr_t hashCodes[3] = { (uintptr_t)m_font, m_widthVariant, m_textOrientation << 3 | m_orientation << 2 | m_syntheticBold << 1 | m_syntheticOblique };
+ uintptr_t hashCodes[3] = { (uintptr_t)m_font, m_widthVariant, m_isPrinterFont << 4 | m_textOrientation << 3 | m_orientation << 2 | m_syntheticBold << 1 | m_syntheticOblique };
return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
#elif USE(CAIRO)
return PtrHash<cairo_scaled_font_t*>::hash(m_scaledFont);
@@ -260,6 +279,10 @@ public:
&& m_syntheticBold == other.m_syntheticBold
&& m_syntheticOblique == other.m_syntheticOblique
&& m_isColorBitmapFont == other.m_isColorBitmapFont
+ && m_isCompositeFontReference == other.m_isCompositeFontReference
+#if OS(DARWIN)
+ && m_isPrinterFont == other.m_isPrinterFont
+#endif
&& m_orientation == other.m_orientation
&& m_textOrientation == other.m_textOrientation
&& m_widthVariant == other.m_widthVariant;
@@ -276,6 +299,9 @@ public:
#endif
}
+#if PLATFORM(WIN) && (USE(CG) || USE(CAIRO))
+ PassRefPtr<SharedBuffer> openTypeTable(uint32_t table) const;
+#endif
#ifndef NDEBUG
String description() const;
@@ -335,6 +361,10 @@ private:
#endif
bool m_isColorBitmapFont;
+ bool m_isCompositeFontReference;
+#if OS(DARWIN)
+ bool m_isPrinterFont;
+#endif
#if PLATFORM(WIN)
bool m_useGDI;
diff --git a/Source/WebCore/platform/graphics/FractionalLayoutPoint.h b/Source/WebCore/platform/graphics/FractionalLayoutPoint.h
index c9863fa5b..55eea5f1a 100644
--- a/Source/WebCore/platform/graphics/FractionalLayoutPoint.h
+++ b/Source/WebCore/platform/graphics/FractionalLayoutPoint.h
@@ -43,6 +43,7 @@ public:
FractionalLayoutPoint(FractionalLayoutUnit x, FractionalLayoutUnit y) : m_x(x), m_y(y) { }
FractionalLayoutPoint(const IntPoint& point) : m_x(point.x()), m_y(point.y()) { }
explicit FractionalLayoutPoint(const FloatPoint& size) : m_x(size.x()), m_y(size.y()) { }
+ explicit FractionalLayoutPoint(const FractionalLayoutSize& size) : m_x(size.width()), m_y(size.height()) { }
static FractionalLayoutPoint zero() { return FractionalLayoutPoint(); }
diff --git a/Source/WebCore/platform/graphics/FractionalLayoutRect.cpp b/Source/WebCore/platform/graphics/FractionalLayoutRect.cpp
index 62986e977..9f723bbd8 100644
--- a/Source/WebCore/platform/graphics/FractionalLayoutRect.cpp
+++ b/Source/WebCore/platform/graphics/FractionalLayoutRect.cpp
@@ -139,9 +139,13 @@ IntRect enclosingIntRect(const FractionalLayoutRect& rect)
FractionalLayoutRect enclosingFractionalLayoutRect(const FloatRect& rect)
{
+#if ENABLE(SUBPIXEL_LAYOUT)
return FractionalLayoutRect(rect.x(), rect.y(),
rect.maxX() - rect.x() + FractionalLayoutUnit::epsilon(),
rect.maxY() - rect.y() + FractionalLayoutUnit::epsilon());
+#else
+ return enclosingIntRect(rect);
+#endif
}
IntRect pixelSnappedIntRect(const FractionalLayoutRect& rect)
diff --git a/Source/WebCore/platform/graphics/FractionalLayoutRect.h b/Source/WebCore/platform/graphics/FractionalLayoutRect.h
index e64feb8b1..67dfb4593 100644
--- a/Source/WebCore/platform/graphics/FractionalLayoutRect.h
+++ b/Source/WebCore/platform/graphics/FractionalLayoutRect.h
@@ -55,6 +55,9 @@ public:
FractionalLayoutPoint location() const { return m_location; }
FractionalLayoutSize size() const { return m_size; }
+ IntPoint pixelSnappedLocation() const { return roundedIntPoint(m_location); }
+ IntSize pixelSnappedSize() const { return pixelSnappedIntSize(m_size, m_location); }
+
void setLocation(const FractionalLayoutPoint& location) { m_location = location; }
void setSize(const FractionalLayoutSize& size) { m_size = size; }
diff --git a/Source/WebCore/platform/graphics/Gradient.h b/Source/WebCore/platform/graphics/Gradient.h
index 01e497da8..60a45381d 100644
--- a/Source/WebCore/platform/graphics/Gradient.h
+++ b/Source/WebCore/platform/graphics/Gradient.h
@@ -61,6 +61,9 @@ typedef cairo_pattern_t* PlatformGradient;
class SkShader;
typedef class SkShader* PlatformGradient;
typedef class SkShader* PlatformPattern;
+#elif PLATFORM(WX)
+class wxGraphicsBrush;
+typedef wxGraphicsBrush* PlatformGradient;
#else
typedef void* PlatformGradient;
#endif
diff --git a/Source/WebCore/platform/graphics/GraphicsContext.cpp b/Source/WebCore/platform/graphics/GraphicsContext.cpp
index 8f7f4cd1c..26b1bb753 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext.cpp
+++ b/Source/WebCore/platform/graphics/GraphicsContext.cpp
@@ -27,6 +27,7 @@
#include "GraphicsContext.h"
#include "BidiResolver.h"
+#include "BitmapImage.h"
#include "Font.h"
#include "Generator.h"
#include "ImageBuffer.h"
@@ -437,27 +438,27 @@ void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run,
fillRect(font.selectionRectForText(run, point, h, from, to), backgroundColor, colorSpace);
}
-void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op)
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation)
{
- drawImage(image, styleColorSpace, p, IntRect(0, 0, -1, -1), op);
+ drawImage(image, styleColorSpace, p, IntRect(0, 0, -1, -1), op, shouldRespectImageOrientation);
}
-void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& r, CompositeOperator op, bool useLowQualityScale)
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& r, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation, bool useLowQualityScale)
{
- drawImage(image, styleColorSpace, r, IntRect(0, 0, -1, -1), op, useLowQualityScale);
+ drawImage(image, styleColorSpace, r, IntRect(0, 0, -1, -1), op, shouldRespectImageOrientation, useLowQualityScale);
}
-void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op)
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation)
{
- drawImage(image, styleColorSpace, IntRect(dest, srcRect.size()), srcRect, op);
+ drawImage(image, styleColorSpace, IntRect(dest, srcRect.size()), srcRect, op, shouldRespectImageOrientation);
}
-void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, bool useLowQualityScale)
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation, bool useLowQualityScale)
{
- drawImage(image, styleColorSpace, FloatRect(dest), srcRect, op, useLowQualityScale);
+ drawImage(image, styleColorSpace, FloatRect(dest), srcRect, op, shouldRespectImageOrientation, useLowQualityScale);
}
-void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op, bool useLowQualityScale)
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation, bool useLowQualityScale)
{
if (paintingDisabled() || !image)
return;
@@ -477,14 +478,21 @@ void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const
if (th == -1)
th = image->height();
+ InterpolationQuality previousInterpolationQuality = InterpolationDefault;
+
if (useLowQualityScale) {
- InterpolationQuality previousInterpolationQuality = imageInterpolationQuality();
- // FIXME: Should be InterpolationLow
+ previousInterpolationQuality = imageInterpolationQuality();
+ // FIXME (49002): Should be InterpolationLow
setImageInterpolationQuality(InterpolationNone);
+ }
+
+ if (image->isBitmapImage())
+ static_cast<BitmapImage*>(image)->draw(this, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), styleColorSpace, op, shouldRespectImageOrientation);
+ else
image->draw(this, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), styleColorSpace, op);
+
+ if (useLowQualityScale)
setImageInterpolationQuality(previousInterpolationQuality);
- } else
- image->draw(this, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), styleColorSpace, op);
}
void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op, bool useLowQualityScale)
@@ -564,7 +572,7 @@ void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorS
if (useLowQualityScale) {
InterpolationQuality previousInterpolationQuality = imageInterpolationQuality();
- // FIXME: Should be InterpolationLow
+ // FIXME (49002): Should be InterpolationLow
setImageInterpolationQuality(InterpolationNone);
image->draw(this, styleColorSpace, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), op, useLowQualityScale);
setImageInterpolationQuality(previousInterpolationQuality);
@@ -765,7 +773,7 @@ PassOwnPtr<ImageBuffer> GraphicsContext::createCompatibleBuffer(const IntSize& s
}
#if !USE(CG)
-void GraphicsContext::platformApplyDeviceScaleFactor()
+void GraphicsContext::platformApplyDeviceScaleFactor(float)
{
}
#endif
@@ -773,7 +781,49 @@ void GraphicsContext::platformApplyDeviceScaleFactor()
void GraphicsContext::applyDeviceScaleFactor(float deviceScaleFactor)
{
scale(FloatSize(deviceScaleFactor, deviceScaleFactor));
- platformApplyDeviceScaleFactor();
+ platformApplyDeviceScaleFactor(deviceScaleFactor);
+}
+
+void GraphicsContext::fillEllipse(const FloatRect& ellipse)
+{
+ platformFillEllipse(ellipse);
+}
+
+void GraphicsContext::strokeEllipse(const FloatRect& ellipse)
+{
+ platformStrokeEllipse(ellipse);
+}
+
+void GraphicsContext::fillEllipseAsPath(const FloatRect& ellipse)
+{
+ Path path;
+ path.addEllipse(ellipse);
+ fillPath(path);
+}
+
+void GraphicsContext::strokeEllipseAsPath(const FloatRect& ellipse)
+{
+ Path path;
+ path.addEllipse(ellipse);
+ strokePath(path);
+}
+
+#if !USE(CG) && !USE(SKIA) // append && !USE(MYPLATFORM) here to optimize ellipses on your platform.
+void GraphicsContext::platformFillEllipse(const FloatRect& ellipse)
+{
+ if (paintingDisabled())
+ return;
+
+ fillEllipseAsPath(ellipse);
}
+void GraphicsContext::platformStrokeEllipse(const FloatRect& ellipse)
+{
+ if (paintingDisabled())
+ return;
+
+ strokeEllipseAsPath(ellipse);
+}
+#endif
+
}
diff --git a/Source/WebCore/platform/graphics/GraphicsContext.h b/Source/WebCore/platform/graphics/GraphicsContext.h
index f7bef4f95..1c81891e1 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext.h
+++ b/Source/WebCore/platform/graphics/GraphicsContext.h
@@ -32,6 +32,7 @@
#include "FloatRect.h"
#include "Gradient.h"
#include "Image.h"
+#include "ImageOrientation.h"
#include "Path.h"
#include "Pattern.h"
#include <wtf/Noncopyable.h>
@@ -260,8 +261,8 @@ namespace WebCore {
void applyStrokePattern();
void applyFillPattern();
void drawPath(const Path&);
-
- void drawNativeImage(NativeImagePtr, const FloatSize& selfSize, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator = CompositeSourceOver);
+
+ void drawNativeImage(NativeImagePtr, const FloatSize& selfSize, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator = CompositeSourceOver, ImageOrientation = DefaultImageOrientation);
// Allow font smoothing (LCD antialiasing). Not part of the graphics state.
void setAllowsFontSmoothing(bool);
@@ -288,6 +289,9 @@ namespace WebCore {
void fillPath(const Path&);
void strokePath(const Path&);
+ void fillEllipse(const FloatRect&);
+ void strokeEllipse(const FloatRect&);
+
// Arc drawing (used by border-radius in CSS) just supports stroking at the moment.
void strokeArc(const IntRect&, int startAngle, int angleSpan);
@@ -303,12 +307,12 @@ namespace WebCore {
void strokeRect(const FloatRect&, float lineWidth);
- void drawImage(Image*, ColorSpace styleColorSpace, const IntPoint&, CompositeOperator = CompositeSourceOver);
- void drawImage(Image*, ColorSpace styleColorSpace, const IntRect&, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
- void drawImage(Image*, ColorSpace styleColorSpace, const IntPoint& destPoint, const IntRect& srcRect, CompositeOperator = CompositeSourceOver);
- void drawImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntRect& srcRect, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
+ void drawImage(Image*, ColorSpace styleColorSpace, const IntPoint&, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation);
+ void drawImage(Image*, ColorSpace styleColorSpace, const IntRect&, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation, bool useLowQualityScale = false);
+ void drawImage(Image*, ColorSpace styleColorSpace, const IntPoint& destPoint, const IntRect& srcRect, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation);
+ void drawImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntRect& srcRect, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation, bool useLowQualityScale = false);
void drawImage(Image*, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1),
- CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
+ CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation, bool useLowQualityScale = false);
void drawTiledImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize,
CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
void drawTiledImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntRect& srcRect,
@@ -352,12 +356,13 @@ namespace WebCore {
FloatRect roundToDevicePixels(const FloatRect&, RoundingMode = RoundAllSides);
void drawLineForText(const FloatPoint&, float width, bool printing);
- enum TextCheckingLineStyle {
- TextCheckingSpellingLineStyle,
- TextCheckingGrammarLineStyle,
- TextCheckingReplacementLineStyle
+ enum DocumentMarkerLineStyle {
+ DocumentMarkerSpellingLineStyle,
+ DocumentMarkerGrammarLineStyle,
+ DocumentMarkerAutocorrectionReplacementLineStyle,
+ DocumentMarkerDictationAlternativesLineStyle
};
- void drawLineForTextChecking(const FloatPoint&, float width, TextCheckingLineStyle);
+ void drawLineForDocumentMarker(const FloatPoint&, float width, DocumentMarkerLineStyle);
bool paintingDisabled() const;
void setPaintingDisabled(bool);
@@ -423,7 +428,7 @@ namespace WebCore {
// This function applies the device scale factor to the context, making the context capable of
// acting as a base-level context for a HiDPI environment.
void applyDeviceScaleFactor(float);
- void platformApplyDeviceScaleFactor();
+ void platformApplyDeviceScaleFactor(float);
#if OS(WINCE) && !PLATFORM(QT)
void setBitmap(PassRefPtr<SharedBitmap>);
@@ -547,6 +552,12 @@ namespace WebCore {
void endPlatformTransparencyLayer();
static bool supportsTransparencyLayers();
+ void fillEllipseAsPath(const FloatRect&);
+ void strokeEllipseAsPath(const FloatRect&);
+
+ void platformFillEllipse(const FloatRect&);
+ void platformStrokeEllipse(const FloatRect&);
+
GraphicsContextPlatformPrivate* m_data;
GraphicsContextState m_state;
diff --git a/Source/WebCore/platform/graphics/GraphicsContext3D.cpp b/Source/WebCore/platform/graphics/GraphicsContext3D.cpp
index 431fa9362..c1b36f604 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext3D.cpp
+++ b/Source/WebCore/platform/graphics/GraphicsContext3D.cpp
@@ -202,7 +202,7 @@ bool GraphicsContext3D::extractImageData(ImageData* imageData,
int height = imageData->height();
int dataBytes = width * height * 4;
data.resize(dataBytes);
- if (!packPixels(imageData->data()->data()->data(),
+ if (!packPixels(imageData->data()->data(),
SourceFormatRGBA8,
width,
height,
@@ -471,8 +471,8 @@ void unpackOneRowOfABGR8ToRGBA8(const uint8_t* source, uint8_t* destination, uns
void unpackOneRowOfBGRA8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
{
- const uint32_t* source32 = reinterpret_cast<const uint32_t*>(source);
- uint32_t* destination32 = reinterpret_cast<uint32_t*>(destination);
+ const uint32_t* source32 = reinterpret_cast_ptr<const uint32_t*>(source);
+ uint32_t* destination32 = reinterpret_cast_ptr<uint32_t*>(destination);
for (unsigned int i = 0; i < pixelsPerRow; ++i) {
uint32_t bgra = source32[i];
#if CPU(BIG_ENDIAN)
@@ -1348,7 +1348,7 @@ static void doPacking(const void* sourceData,
break;
}
default:
- ASSERT(false);
+ ASSERT_NOT_REACHED();
}
}
diff --git a/Source/WebCore/platform/graphics/GraphicsContext3D.h b/Source/WebCore/platform/graphics/GraphicsContext3D.h
index 455ffe2bc..2ab07ab93 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext3D.h
+++ b/Source/WebCore/platform/graphics/GraphicsContext3D.h
@@ -439,7 +439,6 @@ public:
, stencil(false)
, antialias(true)
, premultipliedAlpha(true)
- , canRecoverFromContextLoss(true)
, preserveDrawingBuffer(false)
, noExtensions(false)
, shareResources(true)
@@ -452,7 +451,6 @@ public:
bool stencil;
bool antialias;
bool premultipliedAlpha;
- bool canRecoverFromContextLoss;
bool preserveDrawingBuffer;
bool noExtensions;
bool shareResources;
@@ -711,10 +709,7 @@ public:
void getRenderbufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value);
void getShaderiv(Platform3DObject, GC3Denum pname, GC3Dint* value);
String getShaderInfoLog(Platform3DObject);
-
- // TBD
- // void glGetShaderPrecisionFormat (GC3Denum shadertype, GC3Denum precisiontype, GC3Dint* range, GC3Dint* precision);
-
+ void getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, GC3Dint* range, GC3Dint* precision);
String getShaderSource(Platform3DObject);
String getString(GC3Denum name);
void getTexParameterfv(GC3Denum target, GC3Denum pname, GC3Dfloat* value);
@@ -912,6 +907,7 @@ public:
// Read rendering results into a pixel array with the same format as the
// backbuffer.
void readRenderingResults(unsigned char* pixels, int pixelsSize);
+ void readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels);
#endif
bool reshapeFBOs(const IntSize&);
diff --git a/Source/WebCore/platform/graphics/GraphicsLayer.cpp b/Source/WebCore/platform/graphics/GraphicsLayer.cpp
index 30eb41da1..10d7b7fc8 100644
--- a/Source/WebCore/platform/graphics/GraphicsLayer.cpp
+++ b/Source/WebCore/platform/graphics/GraphicsLayer.cpp
@@ -63,10 +63,6 @@ void KeyframeValueList::insert(const AnimationValue* value)
m_values.append(value);
}
-#ifndef NDEBUG
-static bool s_inPaintContents = false;
-#endif
-
GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client)
: m_client(client)
, m_anchorPoint(0.5f, 0.5f, 0)
@@ -91,12 +87,30 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client)
, m_replicatedLayer(0)
, m_repaintCount(0)
{
- ASSERT(!s_inPaintContents);
+#ifndef NDEBUG
+ if (m_client)
+ m_client->verifyNotPainting();
+#endif
}
GraphicsLayer::~GraphicsLayer()
{
- ASSERT(!s_inPaintContents);
+ ASSERT(!m_parent); // willBeDestroyed should have been called already.
+}
+
+void GraphicsLayer::willBeDestroyed()
+{
+#ifndef NDEBUG
+ if (m_client)
+ m_client->verifyNotPainting();
+#endif
+
+ if (m_replicaLayer)
+ m_replicaLayer->setReplicatedLayer(0);
+
+ if (m_replicatedLayer)
+ m_replicatedLayer->setReplicatedByLayer(0);
+
removeAllChildren();
removeFromParent();
}
@@ -257,6 +271,12 @@ void GraphicsLayer::noteDeviceOrPageScaleFactorChangedIncludingDescendants()
void GraphicsLayer::setReplicatedByLayer(GraphicsLayer* layer)
{
+ if (m_replicaLayer == layer)
+ return;
+
+ if (m_replicaLayer)
+ m_replicaLayer->setReplicatedLayer(0);
+
if (layer)
layer->setReplicatedLayer(this);
@@ -288,9 +308,6 @@ void GraphicsLayer::clearBackgroundColor()
void GraphicsLayer::paintGraphicsLayerContents(GraphicsContext& context, const IntRect& clip)
{
-#ifndef NDEBUG
- s_inPaintContents = true;
-#endif
if (m_client) {
LayoutSize offset = offsetFromRenderer();
context.translate(-offset);
@@ -300,9 +317,6 @@ void GraphicsLayer::paintGraphicsLayerContents(GraphicsContext& context, const I
m_client->paintContents(this, context, m_paintingPhase, pixelSnappedIntRect(clipRect));
}
-#ifndef NDEBUG
- s_inPaintContents = false;
-#endif
}
String GraphicsLayer::animationNameForTransition(AnimatedPropertyID property)
@@ -495,6 +509,14 @@ int GraphicsLayer::validateTransformOperations(const KeyframeValueList& valueLis
return firstIndex;
}
+double GraphicsLayer::backingStoreArea() const
+{
+ if (!drawsContent())
+ return 0;
+
+ // Effects of page and device scale are ignored; subclasses should override to take these into account.
+ return static_cast<double>(size().width()) * size().height();
+}
static void writeIndent(TextStream& ts, int indent)
{
diff --git a/Source/WebCore/platform/graphics/GraphicsLayer.h b/Source/WebCore/platform/graphics/GraphicsLayer.h
index b41ea0618..16c73a483 100644
--- a/Source/WebCore/platform/graphics/GraphicsLayer.h
+++ b/Source/WebCore/platform/graphics/GraphicsLayer.h
@@ -95,6 +95,7 @@ class FloatPoint3D;
class GraphicsContext;
class Image;
class TextStream;
+class TiledBacking;
class TimingFunction;
// Base class for animation values (also used for transitions). Here to
@@ -343,7 +344,6 @@ public:
virtual void setNeedsDisplay() = 0;
// mark the given rect (in layer coords) as needing dispay. Never goes deep.
virtual void setNeedsDisplayInRect(const FloatRect&) = 0;
- virtual bool needsDisplay() const { return false; }
virtual void setContentsNeedsDisplay() { };
@@ -426,10 +426,12 @@ public:
// pointers for the layers and timing data will be included in the returned string.
String layerTreeAsText(LayerTreeAsTextBehavior = LayerTreeAsTextBehaviorNormal) const;
+ // Return an estimate of the backing store area (in pixels). May be incorrect for tiled layers.
+ virtual double backingStoreArea() const;
+
bool usingTiledLayer() const { return m_usingTiledLayer; }
- // Called whenever the visible rect of the given GraphicsLayer changed.
- virtual void visibleRectChanged(const IntRect&) { }
+ virtual TiledBacking* tiledBacking() { return 0; }
#if PLATFORM(QT) || PLATFORM(GTK)
// This allows several alternative GraphicsLayer implementations in the same port,
@@ -439,6 +441,9 @@ public:
#endif
protected:
+ // Should be called from derived class destructors. Should call willBeDestroyed() on super.
+ virtual void willBeDestroyed();
+
#if ENABLE(CSS_FILTERS)
// This method is used by platform GraphicsLayer classes to clear the filters
// when compositing is not done in hardware. It is not virtual, so the caller
diff --git a/Source/WebCore/platform/graphics/GraphicsLayerClient.h b/Source/WebCore/platform/graphics/GraphicsLayerClient.h
index 4058b65f0..36a7f4365 100644
--- a/Source/WebCore/platform/graphics/GraphicsLayerClient.h
+++ b/Source/WebCore/platform/graphics/GraphicsLayerClient.h
@@ -74,6 +74,15 @@ public:
virtual bool showDebugBorders(const GraphicsLayer*) const = 0;
virtual bool showRepaintCounter(const GraphicsLayer*) const = 0;
+
+#ifndef NDEBUG
+ // RenderLayerBacking overrides this to verify that it is not
+ // currently painting contents. An ASSERT fails, if it is.
+ // This is executed in GraphicsLayer construction and destruction
+ // to verify that we don't create or destroy GraphicsLayers
+ // while painting.
+ virtual void verifyNotPainting() { }
+#endif
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/ImageBuffer.cpp b/Source/WebCore/platform/graphics/ImageBuffer.cpp
index e4a9fd857..bc3d36129 100644
--- a/Source/WebCore/platform/graphics/ImageBuffer.cpp
+++ b/Source/WebCore/platform/graphics/ImageBuffer.cpp
@@ -72,16 +72,16 @@ void ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstCo
inline void ImageBuffer::genericConvertToLuminanceMask()
{
IntRect luminanceRect(IntPoint(), internalSize());
- RefPtr<ByteArray> srcPixelArray = getUnmultipliedImageData(luminanceRect);
+ RefPtr<Uint8ClampedArray> srcPixelArray = getUnmultipliedImageData(luminanceRect);
unsigned pixelArrayLength = srcPixelArray->length();
for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) {
- unsigned char a = srcPixelArray->get(pixelOffset + 3);
+ unsigned char a = srcPixelArray->item(pixelOffset + 3);
if (!a)
continue;
- unsigned char r = srcPixelArray->get(pixelOffset);
- unsigned char g = srcPixelArray->get(pixelOffset + 1);
- unsigned char b = srcPixelArray->get(pixelOffset + 2);
+ unsigned char r = srcPixelArray->item(pixelOffset);
+ unsigned char g = srcPixelArray->item(pixelOffset + 1);
+ unsigned char b = srcPixelArray->item(pixelOffset + 2);
double luma = (r * 0.2125 + g * 0.7154 + b * 0.0721) * ((double)a / 255.0);
srcPixelArray->set(pixelOffset + 3, luma);
diff --git a/Source/WebCore/platform/graphics/ImageBuffer.h b/Source/WebCore/platform/graphics/ImageBuffer.h
index 53e86db48..d1988ab47 100644
--- a/Source/WebCore/platform/graphics/ImageBuffer.h
+++ b/Source/WebCore/platform/graphics/ImageBuffer.h
@@ -38,11 +38,11 @@
#include "GraphicsTypes.h"
#include "IntSize.h"
#include "ImageBufferData.h"
-#include <wtf/ByteArray.h>
#include <wtf/Forward.h>
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/PassRefPtr.h>
+#include <wtf/Uint8ClampedArray.h>
#include <wtf/Vector.h>
namespace WebCore {
@@ -80,17 +80,9 @@ namespace WebCore {
static PassOwnPtr<ImageBuffer> create(const IntSize& size, float resolutionScale = 1, ColorSpace colorSpace = ColorSpaceDeviceRGB, RenderingMode renderingMode = Unaccelerated, DeferralMode deferralMode = NonDeferred)
{
bool success = false;
- float scaledWidth = ceilf(resolutionScale * size.width());
- float scaledHeight = ceilf(resolutionScale * size.height());
- IntSize internalSize(scaledWidth, scaledHeight);
-
- OwnPtr<ImageBuffer> buf = adoptPtr(new ImageBuffer(internalSize, colorSpace, renderingMode, deferralMode, success));
+ OwnPtr<ImageBuffer> buf = adoptPtr(new ImageBuffer(size, resolutionScale, colorSpace, renderingMode, deferralMode, success));
if (!success)
return nullptr;
-
- buf->m_logicalSize = size;
- buf->m_resolutionScale = resolutionScale;
- buf->context()->scale(FloatSize(resolutionScale, resolutionScale));
return buf.release();
}
@@ -104,14 +96,16 @@ namespace WebCore {
PassRefPtr<Image> copyImage(BackingStoreCopy = CopyBackingStore) const;
- PassRefPtr<ByteArray> getUnmultipliedImageData(const IntRect&) const;
- PassRefPtr<ByteArray> getPremultipliedImageData(const IntRect&) const;
+ enum CoordinateSystem { LogicalCoordinateSystem, BackingStoreCoordinateSystem };
+
+ PassRefPtr<Uint8ClampedArray> getUnmultipliedImageData(const IntRect&, CoordinateSystem = LogicalCoordinateSystem) const;
+ PassRefPtr<Uint8ClampedArray> getPremultipliedImageData(const IntRect&, CoordinateSystem = LogicalCoordinateSystem) const;
- void putByteArray(Multiply multiplied, ByteArray*, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint);
+ void putByteArray(Multiply multiplied, Uint8ClampedArray*, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem = LogicalCoordinateSystem);
void convertToLuminanceMask();
- String toDataURL(const String& mimeType, const double* quality = 0) const;
+ String toDataURL(const String& mimeType, const double* quality = 0, CoordinateSystem = LogicalCoordinateSystem) const;
#if !USE(CG)
AffineTransform baseTransform() const { return AffineTransform(); }
void transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstColorSpace);
@@ -153,7 +147,7 @@ namespace WebCore {
// This constructor will place its success into the given out-variable
// so that create() knows when it should return failure.
- ImageBuffer(const IntSize&, ColorSpace, RenderingMode, DeferralMode, bool& success);
+ ImageBuffer(const IntSize&, float resolutionScale, ColorSpace, RenderingMode, DeferralMode, bool& success);
};
#if USE(CG) || USE(SKIA)
diff --git a/Source/WebCore/platform/graphics/ImageOrientation.cpp b/Source/WebCore/platform/graphics/ImageOrientation.cpp
new file mode 100644
index 000000000..8a5854e63
--- /dev/null
+++ b/Source/WebCore/platform/graphics/ImageOrientation.cpp
@@ -0,0 +1,60 @@
+
+/*
+ * 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"
+#include "ImageOrientation.h"
+
+#include "AffineTransform.h"
+
+namespace WebCore {
+
+AffineTransform ImageOrientation::transformFromDefault(const FloatSize& drawnSize) const
+{
+ float w = drawnSize.width();
+ float h = drawnSize.height();
+ switch (m_orientation) {
+ case OriginTopLeft:
+ return AffineTransform();
+ case OriginBottomRight:
+ return AffineTransform(-1, 0, 0, -1, w, h);
+ case OriginLeftBottom:
+ return AffineTransform( 0, 1, -1, 0, w, 0);
+ case OriginRightTop:
+ return AffineTransform( 0, -1, 1, 0, 0, h);
+ case OriginTopRight:
+ return AffineTransform(-1, 0, 0, 1, w, 0);
+ case OriginBottomLeft:
+ return AffineTransform( 1, 0, 0, -1, 0, h);
+ case OriginLeftTop:
+ return AffineTransform( 0, -1, -1, 0, w, h);
+ case OriginRightBottom:
+ return AffineTransform( 0, 1, 1, 0, 0, 0);
+ }
+ ASSERT_NOT_REACHED();
+ return AffineTransform();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/ImageOrientation.h b/Source/WebCore/platform/graphics/ImageOrientation.h
new file mode 100644
index 000000000..86be5fe77
--- /dev/null
+++ b/Source/WebCore/platform/graphics/ImageOrientation.h
@@ -0,0 +1,91 @@
+/*
+ * 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 ImageOrientation_h
+#define ImageOrientation_h
+
+namespace WebCore {
+
+class AffineTransform;
+class FloatSize;
+
+// This enum intentionally matches the orientation values from the EXIF spec.
+// See JEITA CP-3451, page 18. http://www.exif.org/Exif2-2.PDF
+enum ImageOrientationEnum {
+ // "TopLeft" means that the 0 row starts at the Top, the 0 column starts at the Left.
+ OriginTopLeft = 1, // default
+ OriginTopRight = 2, // mirror along y-axes
+ OriginBottomRight = 3, // 180 degree rotation
+ OriginBottomLeft = 4, // mirror along the x-axes
+ OriginLeftTop = 5, // -90 degree rotation + mirror along x-axes
+ OriginRightTop = 6, // 90 degree rotation
+ OriginRightBottom = 7, // 90 degree rotation + mirror along x-axes
+ OriginLeftBottom = 8, // -90 degree rotation
+ // All other values are "reserved" as of EXIF 2.2
+ DefaultImageOrientation = OriginTopLeft,
+};
+
+enum RespectImageOrientationEnum {
+ DoNotRespectImageOrientation = 0,
+ RespectImageOrientation = 1
+};
+
+class ImageOrientation {
+public:
+ ImageOrientation(ImageOrientationEnum orientation = DefaultImageOrientation)
+ : m_orientation(orientation)
+ {
+ }
+
+ bool usesWidthAsHeight() const
+ {
+ // Values 5 through 8 all flip the width/height.
+ return m_orientation >= OriginLeftTop;
+ }
+
+ // ImageOrientationEnum currently matches EXIF values, however code outside
+ // this function should never assume that.
+ static ImageOrientation fromEXIFValue(int exifValue)
+ {
+ // Values direct from images may be invalid, in which case we use the default.
+ if (exifValue < OriginTopLeft || exifValue > OriginLeftBottom)
+ return DefaultImageOrientation;
+ return static_cast<ImageOrientationEnum>(exifValue);
+ }
+
+ // This transform can be used for drawing an image according to the orientation.
+ AffineTransform transformFromDefault(const FloatSize& drawnSize) const;
+
+ inline bool operator==(const ImageOrientation& other) const { return other.m_orientation == m_orientation; }
+ inline bool operator!=(const ImageOrientation& other) const { return !(*this == other); }
+
+private:
+ // FIXME: This only needs to be one byte.
+ ImageOrientationEnum m_orientation;
+};
+
+} // namespace WebCore
+
+#endif // ImageOrientation_h
diff --git a/Source/WebCore/platform/graphics/ImageSource.cpp b/Source/WebCore/platform/graphics/ImageSource.cpp
index f4495edbc..ff9fe0d9f 100644
--- a/Source/WebCore/platform/graphics/ImageSource.cpp
+++ b/Source/WebCore/platform/graphics/ImageSource.cpp
@@ -35,6 +35,9 @@
#include "ImageDecoder.h"
#endif
+#include "ImageOrientation.h"
+#include "NotImplemented.h"
+
namespace WebCore {
#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
@@ -100,13 +103,21 @@ bool ImageSource::isSizeAvailable()
return m_decoder && m_decoder->isSizeAvailable();
}
-IntSize ImageSource::size() const
+IntSize ImageSource::size(RespectImageOrientationEnum shouldRespectOrientation) const
{
+ // The JPEG and TIFF decoders need to be taught how to read EXIF, XMP, or IPTC data.
+ if (shouldRespectOrientation == RespectImageOrientation)
+ notImplemented();
+
return m_decoder ? m_decoder->size() : IntSize();
}
-IntSize ImageSource::frameSizeAtIndex(size_t index) const
+IntSize ImageSource::frameSizeAtIndex(size_t index, RespectImageOrientationEnum shouldRespectOrientation) const
{
+ // The JPEG and TIFF decoders need to be taught how to read EXIF, XMP, or IPTC data.
+ if (shouldRespectOrientation == RespectImageOrientation)
+ notImplemented();
+
return m_decoder ? m_decoder->frameSizeAtIndex(index) : IntSize();
}
@@ -168,6 +179,13 @@ float ImageSource::frameDurationAtIndex(size_t index)
return duration;
}
+ImageOrientation ImageSource::orientationAtIndex(size_t index) const
+{
+ // The JPEG and TIFF decoders need to be taught how to read EXIF, XMP, or IPTC data.
+ notImplemented();
+ return DefaultImageOrientation;
+}
+
bool ImageSource::frameHasAlphaAtIndex(size_t index)
{
// When a frame has not finished decoding, always mark it as having alpha.
diff --git a/Source/WebCore/platform/graphics/ImageSource.h b/Source/WebCore/platform/graphics/ImageSource.h
index 1d0220257..307737f20 100644
--- a/Source/WebCore/platform/graphics/ImageSource.h
+++ b/Source/WebCore/platform/graphics/ImageSource.h
@@ -27,6 +27,8 @@
#ifndef ImageSource_h
#define ImageSource_h
+#include "ImageOrientation.h"
+
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
#include <wtf/Vector.h>
@@ -44,8 +46,7 @@ QT_BEGIN_NAMESPACE
class QPixmap;
QT_END_NAMESPACE
#elif USE(CAIRO)
-struct _cairo_surface;
-typedef struct _cairo_surface cairo_surface_t;
+#include "NativeImageCairo.h"
#elif USE(SKIA)
namespace WebCore {
class NativeImageSkia;
@@ -56,6 +57,7 @@ class NativeImageSkia;
namespace WebCore {
+class ImageOrientation;
class IntPoint;
class IntSize;
class SharedBuffer;
@@ -87,7 +89,7 @@ typedef wxGraphicsBitmap* NativeImagePtr;
typedef wxBitmap* NativeImagePtr;
#endif
#elif USE(CAIRO)
-typedef cairo_surface_t* NativeImagePtr;
+typedef WebCore::NativeImageCairo* NativeImagePtr;
#elif USE(SKIA)
typedef WebCore::NativeImageSkia* NativeImagePtr;
#elif OS(WINCE)
@@ -131,9 +133,9 @@ public:
};
#if USE(CG)
- enum ShouldSkipMetaData {
- DoNotSkipMetaData,
- SkipMetaData
+ enum ShouldSkipMetadata {
+ DoNotSkipMetadata,
+ SkipMetadata
};
#endif
@@ -172,8 +174,9 @@ public:
String filenameExtension() const;
bool isSizeAvailable();
- IntSize size() const;
- IntSize frameSizeAtIndex(size_t) const;
+ IntSize size(RespectImageOrientationEnum = DoNotRespectImageOrientation) const;
+ IntSize frameSizeAtIndex(size_t, RespectImageOrientationEnum = DoNotRespectImageOrientation) const;
+
bool getHotSpot(IntPoint&) const;
size_t bytesDecodedToDetermineProperties() const;
@@ -189,6 +192,7 @@ public:
float frameDurationAtIndex(size_t);
bool frameHasAlphaAtIndex(size_t); // Whether or not the frame actually used any alpha.
bool frameIsCompleteAtIndex(size_t); // Whether or not the frame is completely decoded.
+ ImageOrientation orientationAtIndex(size_t) const; // EXIF image orientation
#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
static unsigned maxPixelsPerDecodedImage() { return s_maxPixelsPerDecodedImage; }
diff --git a/Source/WebCore/platform/graphics/IntPoint.h b/Source/WebCore/platform/graphics/IntPoint.h
index ddc41b423..0af6e8570 100644
--- a/Source/WebCore/platform/graphics/IntPoint.h
+++ b/Source/WebCore/platform/graphics/IntPoint.h
@@ -111,6 +111,8 @@ public:
m_y < other.m_y ? m_y : other.m_y);
}
+ int distanceSquaredToPoint(const IntPoint&) const;
+
void clampNegativeToZero()
{
*this = expandedTo(zero());
@@ -222,6 +224,11 @@ inline IntSize toSize(const IntPoint& a)
return IntSize(a.x(), a.y());
}
+inline int IntPoint::distanceSquaredToPoint(const IntPoint& point) const
+{
+ return ((*this) - point).diagonalLengthSquared();
+}
+
#if PLATFORM(QT)
inline QDataStream& operator<<(QDataStream& stream, const IntPoint& point)
{
diff --git a/Source/WebCore/platform/graphics/IntRect.cpp b/Source/WebCore/platform/graphics/IntRect.cpp
index 03c35e83b..dfa2f91f1 100644
--- a/Source/WebCore/platform/graphics/IntRect.cpp
+++ b/Source/WebCore/platform/graphics/IntRect.cpp
@@ -132,6 +132,35 @@ void IntRect::scale(float s)
m_size.setHeight((int)(height() * s));
}
+static inline int distanceToInterval(int pos, int start, int end)
+{
+ if (pos < start)
+ return start - pos;
+ if (pos > end)
+ return end - pos;
+ return 0;
+}
+
+IntSize IntRect::differenceToPoint(const IntPoint& point) const
+{
+ int xdistance = distanceToInterval(point.x(), x(), maxX());
+ int ydistance = distanceToInterval(point.y(), y(), maxY());
+ return IntSize(xdistance, ydistance);
+}
+
+IntSize IntRect::differenceFromCenterLineToPoint(const IntPoint& point) const
+{
+ // The center-line is the natural center of a rectangle. It has an equal distance to all sides of the rectangle.
+ IntPoint centerPoint = center();
+ int xdistance = centerPoint.x() - point.x();
+ int ydistance = centerPoint.y() - point.y();
+ if (width() > height())
+ xdistance = distanceToInterval(point.x(), x() + (height() / 2), maxX() - (height() / 2));
+ else
+ ydistance = distanceToInterval(point.y(), y() + (width() / 2), maxY() - (width() / 2));
+ return IntSize(xdistance, ydistance);
+}
+
IntRect unionRect(const Vector<IntRect>& rects)
{
IntRect result;
diff --git a/Source/WebCore/platform/graphics/IntRect.h b/Source/WebCore/platform/graphics/IntRect.h
index 600c21d0d..9a9a7f7e5 100644
--- a/Source/WebCore/platform/graphics/IntRect.h
+++ b/Source/WebCore/platform/graphics/IntRect.h
@@ -111,6 +111,8 @@ public:
int pixelSnappedMaxY() const { return y() + height(); }
int pixelSnappedWidth() const { return m_size.width(); }
int pixelSnappedHeight() const { return m_size.height(); }
+ IntPoint pixelSnappedLocation() const { return location(); }
+ IntSize pixelSnappedSize() const { return size(); }
void setX(int x) { m_location.setX(x); }
void setY(int y) { m_location.setY(y); }
@@ -186,6 +188,11 @@ public:
void inflate(int d) { inflateX(d); inflateY(d); }
void scale(float s);
+ IntSize differenceToPoint(const IntPoint&) const;
+ IntSize differenceFromCenterLineToPoint(const IntPoint&) const;
+ int distanceSquaredToPoint(const IntPoint& p) const { return differenceToPoint(p).diagonalLengthSquared(); }
+ int distanceSquaredFromCenterLineToPoint(const IntPoint& p) const { return differenceFromCenterLineToPoint(p).diagonalLengthSquared(); }
+
IntRect transposedRect() const { return IntRect(m_location.transposedPoint(), m_size.transposedSize()); }
#if PLATFORM(WX)
@@ -265,6 +272,13 @@ inline bool operator!=(const IntRect& a, const IntRect& b)
return a.location() != b.location() || a.size() != b.size();
}
+// FIXME: This method is here only to ease the transition to sub-pixel layout. It should
+// be removed when we close http://webkit.org/b/60318
+inline IntRect enclosingIntRect(const IntRect& rect)
+{
+ return rect;
+}
+
#if USE(CG) || USE(SKIA_ON_MAC_CHROMIUM)
IntRect enclosingIntRect(const CGRect&);
#endif
diff --git a/Source/WebCore/platform/graphics/IntSize.h b/Source/WebCore/platform/graphics/IntSize.h
index 163984766..c8a549dd7 100644
--- a/Source/WebCore/platform/graphics/IntSize.h
+++ b/Source/WebCore/platform/graphics/IntSize.h
@@ -80,13 +80,18 @@ public:
m_width += width;
m_height += height;
}
+
+ void scale(float widthScale, float heightScale)
+ {
+ m_width = static_cast<int>(static_cast<float>(m_width) * widthScale);
+ m_height = static_cast<int>(static_cast<float>(m_height) * heightScale);
+ }
void scale(float scale)
{
- m_width = static_cast<int>(static_cast<float>(m_width) * scale);
- m_height = static_cast<int>(static_cast<float>(m_height) * scale);
+ this->scale(scale, scale);
}
-
+
IntSize expandedTo(const IntSize& other) const
{
return IntSize(m_width > other.m_width ? m_width : other.m_width,
@@ -104,6 +109,24 @@ public:
*this = expandedTo(IntSize());
}
+ void clampToMinimumSize(const IntSize& minimumSize)
+ {
+ if (m_width < minimumSize.width())
+ m_width = minimumSize.width();
+ if (m_height < minimumSize.height())
+ m_height = minimumSize.height();
+ }
+
+ int area() const
+ {
+ return m_width * m_height;
+ }
+
+ int diagonalLengthSquared() const
+ {
+ return m_width * m_width + m_height * m_height;
+ }
+
IntSize transposedSize() const
{
return IntSize(m_height, m_width);
diff --git a/Source/WebCore/platform/graphics/MediaPlayer.cpp b/Source/WebCore/platform/graphics/MediaPlayer.cpp
index ed6a13fa8..d873ec5ec 100644
--- a/Source/WebCore/platform/graphics/MediaPlayer.cpp
+++ b/Source/WebCore/platform/graphics/MediaPlayer.cpp
@@ -72,6 +72,9 @@
#elif PLATFORM(CHROMIUM)
#include "MediaPlayerPrivateChromium.h"
#define PlatformMediaEngineClassName MediaPlayerPrivate
+#elif PLATFORM(BLACKBERRY)
+#include "MediaPlayerPrivateBlackBerry.h"
+#define PlatformMediaEngineClassName MediaPlayerPrivate
#endif
namespace WebCore {
@@ -146,9 +149,17 @@ public:
virtual bool hasSingleSecurityOrigin() const { return true; }
#if ENABLE(MEDIA_SOURCE)
+ virtual MediaPlayer::AddIdStatus sourceAddId(const String& id, const String& type) { return MediaPlayer::NotSupported; }
+ virtual bool sourceRemoveId(const String& id) { return false; }
virtual bool sourceAppend(const unsigned char*, unsigned) { return false; }
virtual void sourceEndOfStream(MediaPlayer::EndOfStreamStatus status) { }
#endif
+
+#if ENABLE(ENCRYPTED_MEDIA)
+ virtual MediaPlayer::MediaKeyException generateKeyRequest(const String&, const unsigned char*, unsigned) OVERRIDE { return MediaPlayer::InvalidPlayerState; }
+ virtual MediaPlayer::MediaKeyException addKey(const String&, const unsigned char*, unsigned, const unsigned char*, unsigned, const String&) OVERRIDE { return MediaPlayer::InvalidPlayerState; }
+ virtual MediaPlayer::MediaKeyException cancelKeyRequest(const String&, const String&) OVERRIDE { return MediaPlayer::InvalidPlayerState; }
+#endif
};
static PassOwnPtr<MediaPlayerPrivateInterface> createNullMediaPlayer(MediaPlayer* player)
@@ -183,7 +194,7 @@ public:
};
static void addMediaEngine(CreateMediaEnginePlayer, MediaEngineSupportedTypes, MediaEngineSupportsType, MediaEngineGetSitesInMediaCache, MediaEngineClearMediaCache, MediaEngineClearMediaCacheForSite);
-static MediaPlayerFactory* bestMediaEngineForTypeAndCodecs(const String& type, const String& codecs, MediaPlayerFactory* current = 0);
+static MediaPlayerFactory* bestMediaEngineForTypeAndCodecs(const String& type, const String& codecs, const String& keySystem, MediaPlayerFactory* current = 0);
static MediaPlayerFactory* nextMediaEngine(MediaPlayerFactory* current);
static Vector<MediaPlayerFactory*>& installedMediaEngines()
@@ -240,7 +251,7 @@ static const AtomicString& codecs()
return codecs;
}
-static MediaPlayerFactory* bestMediaEngineForTypeAndCodecs(const String& type, const String& codecs, MediaPlayerFactory* current)
+static MediaPlayerFactory* bestMediaEngineForTypeAndCodecs(const String& type, const String& codecs, const String& keySystem, MediaPlayerFactory* current)
{
if (type.isEmpty())
return 0;
@@ -266,7 +277,13 @@ static MediaPlayerFactory* bestMediaEngineForTypeAndCodecs(const String& type, c
current = 0;
continue;
}
+#if ENABLE(ENCRYPTED_MEDIA)
+ MediaPlayer::SupportsType engineSupport = engines[ndx]->supportsTypeAndCodecs(type, codecs, keySystem);
+#else
+ UNUSED_PARAM(keySystem);
+ ASSERT(keySystem.isEmpty());
MediaPlayer::SupportsType engineSupport = engines[ndx]->supportsTypeAndCodecs(type, codecs);
+#endif
if (engineSupport > supported) {
supported = engineSupport;
engine = engines[ndx];
@@ -328,7 +345,7 @@ MediaPlayer::~MediaPlayer()
m_mediaPlayerClient = 0;
}
-bool MediaPlayer::load(const KURL& url, const ContentType& contentType)
+bool MediaPlayer::load(const KURL& url, const ContentType& contentType, const String& keySystem)
{
String type = contentType.type().lower();
String typeCodecs = contentType.parameter(codecs());
@@ -353,6 +370,7 @@ bool MediaPlayer::load(const KURL& url, const ContentType& contentType)
m_url = urlString;
m_contentMIMEType = type;
m_contentTypeCodecs = typeCodecs;
+ m_keySystem = keySystem.lower();
loadWithNextMediaEngine(0);
return m_currentMediaEngine;
}
@@ -365,7 +383,7 @@ void MediaPlayer::loadWithNextMediaEngine(MediaPlayerFactory* current)
if (m_contentMIMEType.isEmpty())
engine = nextMediaEngine(current);
else
- engine = bestMediaEngineForTypeAndCodecs(m_contentMIMEType, m_contentTypeCodecs, current);
+ engine = bestMediaEngineForTypeAndCodecs(m_contentMIMEType, m_contentTypeCodecs, m_keySystem, current);
// Don't delete and recreate the player unless it comes from a different engine.
if (!engine) {
@@ -440,6 +458,17 @@ void MediaPlayer::pause()
}
#if ENABLE(MEDIA_SOURCE)
+
+MediaPlayer::AddIdStatus MediaPlayer::sourceAddId(const String& id, const String& type)
+{
+ return m_private->sourceAddId(id, type);
+}
+
+bool MediaPlayer::sourceRemoveId(const String& id)
+{
+ return m_private->sourceRemoveId(id);
+}
+
bool MediaPlayer::sourceAppend(const unsigned char* data, unsigned length)
{
return m_private->sourceAppend(data, length);
@@ -451,6 +480,23 @@ void MediaPlayer::sourceEndOfStream(MediaPlayer::EndOfStreamStatus status)
}
#endif
+#if ENABLE(ENCRYPTED_MEDIA)
+MediaPlayer::MediaKeyException MediaPlayer::generateKeyRequest(const String& keySystem, const unsigned char* initData, unsigned initDataLength)
+{
+ return m_private->generateKeyRequest(keySystem.lower(), initData, initDataLength);
+}
+
+MediaPlayer::MediaKeyException MediaPlayer::addKey(const String& keySystem, const unsigned char* key, unsigned keyLength, const unsigned char* initData, unsigned initDataLength, const String& sessionId)
+{
+ return m_private->addKey(keySystem.lower(), key, keyLength, initData, initDataLength, sessionId);
+}
+
+MediaPlayer::MediaKeyException MediaPlayer::cancelKeyRequest(const String& keySystem, const String& sessionId)
+{
+ return m_private->cancelKeyRequest(keySystem.lower(), sessionId);
+}
+#endif
+
float MediaPlayer::duration() const
{
return m_private->duration();
@@ -664,21 +710,29 @@ void MediaPlayer::paintCurrentFrameInContext(GraphicsContext* p, const IntRect&
m_private->paintCurrentFrameInContext(p, r);
}
-MediaPlayer::SupportsType MediaPlayer::supportsType(const ContentType& contentType)
+MediaPlayer::SupportsType MediaPlayer::supportsType(const ContentType& contentType, const String& keySystem)
{
String type = contentType.type().lower();
+ // The codecs string is not lower-cased because MP4 values are case sensitive
+ // per http://tools.ietf.org/html/rfc4281#page-7.
String typeCodecs = contentType.parameter(codecs());
+ String system = keySystem.lower();
// 4.8.10.3 MIME types - The canPlayType(type) method must return the empty string if type is a type that the
// user agent knows it cannot render or is the type "application/octet-stream"
if (type == applicationOctetStream())
return IsNotSupported;
- MediaPlayerFactory* engine = bestMediaEngineForTypeAndCodecs(type, typeCodecs);
+ MediaPlayerFactory* engine = bestMediaEngineForTypeAndCodecs(type, typeCodecs, system);
if (!engine)
return IsNotSupported;
+#if ENABLE(ENCRYPTED_MEDIA)
+ return engine->supportsTypeAndCodecs(type, typeCodecs, system);
+#else
+ ASSERT(system.isEmpty());
return engine->supportsTypeAndCodecs(type, typeCodecs);
+#endif
}
void MediaPlayer::getSupportedTypes(HashSet<String>& types)
@@ -712,17 +766,19 @@ void MediaPlayer::setMediaPlayerProxy(WebMediaPlayerProxy* proxy)
void MediaPlayer::setControls(bool controls)
{
m_private->setControls(controls);
-}
+}
+#endif
-void MediaPlayer::enterFullscreen()
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) || USE(NATIVE_FULLSCREEN_VIDEO)
+bool MediaPlayer::enterFullscreen() const
{
- m_private->enterFullscreen();
-}
+ return m_private->enterFullscreen();
+}
void MediaPlayer::exitFullscreen()
{
m_private->exitFullscreen();
-}
+}
#endif
#if USE(ACCELERATED_COMPOSITING)
@@ -845,7 +901,7 @@ void MediaPlayer::networkStateChanged()
if (m_private->networkState() >= FormatError
&& m_private->readyState() < HaveMetadata
&& installedMediaEngines().size() > 1) {
- if ( m_contentMIMEType.isEmpty() || bestMediaEngineForTypeAndCodecs(m_contentMIMEType, m_contentTypeCodecs, m_currentMediaEngine)) {
+ if (m_contentMIMEType.isEmpty() || bestMediaEngineForTypeAndCodecs(m_contentMIMEType, m_contentTypeCodecs, m_keySystem, m_currentMediaEngine)) {
m_reloadTimer.startOneShot(0);
return;
}
@@ -928,7 +984,33 @@ AudioSourceProvider* MediaPlayer::audioSourceProvider()
return m_private->audioSourceProvider();
}
#endif // WEB_AUDIO
-
+
+#if ENABLE(ENCRYPTED_MEDIA)
+void MediaPlayer::keyAdded(const String& keySystem, const String& sessionId)
+{
+ if (m_mediaPlayerClient)
+ m_mediaPlayerClient->mediaPlayerKeyAdded(this, keySystem, sessionId);
+}
+
+void MediaPlayer::keyError(const String& keySystem, const String& sessionId, MediaPlayerClient::MediaKeyErrorCode errorCode, unsigned short systemCode)
+{
+ if (m_mediaPlayerClient)
+ m_mediaPlayerClient->mediaPlayerKeyError(this, keySystem, sessionId, errorCode, systemCode);
+}
+
+void MediaPlayer::keyMessage(const String& keySystem, const String& sessionId, const unsigned char* message, unsigned messageLength)
+{
+ if (m_mediaPlayerClient)
+ m_mediaPlayerClient->mediaPlayerKeyMessage(this, keySystem, sessionId, message, messageLength);
+}
+
+void MediaPlayer::keyNeeded(const String& keySystem, const String& sessionId, const unsigned char* initData, unsigned initDataLength)
+{
+ if (m_mediaPlayerClient)
+ m_mediaPlayerClient->mediaPlayerKeyNeeded(this, keySystem, sessionId, initData, initDataLength);
+}
+#endif
+
String MediaPlayer::referrer() const
{
if (!m_mediaPlayerClient)
diff --git a/Source/WebCore/platform/graphics/MediaPlayer.h b/Source/WebCore/platform/graphics/MediaPlayer.h
index bc10fc306..00ca06450 100644
--- a/Source/WebCore/platform/graphics/MediaPlayer.h
+++ b/Source/WebCore/platform/graphics/MediaPlayer.h
@@ -168,6 +168,14 @@ public:
virtual String mediaPlayerSourceURL() const { return "x-media-source-unsupported:"; }
#endif
+#if ENABLE(ENCRYPTED_MEDIA)
+ enum MediaKeyErrorCode { UnknownError = 1, ClientError, ServiceError, OutputError, HardwareChangeError, DomainError };
+ virtual void mediaPlayerKeyAdded(MediaPlayer*, const String& keySystem, const String& sessionId) { }
+ virtual void mediaPlayerKeyError(MediaPlayer*, const String& keySystem, const String& sessionId, MediaKeyErrorCode errorCode, unsigned short systemCode) { }
+ virtual void mediaPlayerKeyMessage(MediaPlayer*, const String& keySystem, const String& sessionId, const unsigned char* message, unsigned messageLength) { }
+ virtual void mediaPlayerKeyNeeded(MediaPlayer*, const String& keySystem, const String& sessionId, const unsigned char* initData, unsigned initDataLength) { }
+#endif
+
virtual String mediaPlayerReferrer() const { return String(); }
virtual String mediaPlayerUserAgent() const { return String(); }
};
@@ -184,7 +192,7 @@ public:
// Media engine support.
enum SupportsType { IsNotSupported, IsSupported, MayBeSupported };
- static MediaPlayer::SupportsType supportsType(const ContentType&);
+ static MediaPlayer::SupportsType supportsType(const ContentType&, const String& keySystem);
static void getSupportedTypes(HashSet<String>&);
static bool isAvailable();
static void getSitesInMediaCache(Vector<String>&);
@@ -210,7 +218,7 @@ public:
IntSize size() const { return m_size; }
void setSize(const IntSize& size);
- bool load(const KURL& url, const ContentType&);
+ bool load(const KURL&, const ContentType&, const String& keySystem);
void cancelLoad();
bool visible() const;
@@ -221,11 +229,24 @@ public:
void pause();
#if ENABLE(MEDIA_SOURCE)
+ enum AddIdStatus { Ok, NotSupported, ReachedIdLimit };
+ AddIdStatus sourceAddId(const String& id, const String& type);
+ bool sourceRemoveId(const String& id);
bool sourceAppend(const unsigned char* data, unsigned length);
enum EndOfStreamStatus { EosNoError, EosNetworkError, EosDecodeError };
void sourceEndOfStream(EndOfStreamStatus);
#endif
+#if ENABLE(ENCRYPTED_MEDIA)
+ // Represents synchronous exceptions that can be thrown from the Encrypted Media methods.
+ // This is different from the asynchronous MediaKeyError.
+ enum MediaKeyException { NoError, InvalidPlayerState, KeySystemNotSupported };
+
+ MediaKeyException generateKeyRequest(const String& keySystem, const unsigned char* initData, unsigned initDataLength);
+ MediaKeyException addKey(const String& keySystem, const unsigned char* key, unsigned keyLength, const unsigned char* initData, unsigned initDataLength, const String& sessionId);
+ MediaKeyException cancelKeyRequest(const String& keySystem, const String& sessionId);
+#endif
+
bool paused() const;
bool seeking() const;
@@ -303,7 +324,10 @@ public:
void deliverNotification(MediaPlayerProxyNotificationType notification);
void setMediaPlayerProxy(WebMediaPlayerProxy* proxy);
void setControls(bool);
- void enterFullscreen();
+#endif
+
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) || USE(NATIVE_FULLSCREEN_VIDEO)
+ bool enterFullscreen() const;
void exitFullscreen();
#endif
@@ -336,6 +360,13 @@ public:
String sourceURL() const;
#endif
+#if ENABLE(ENCRYPTED_MEDIA)
+ void keyAdded(const String& keySystem, const String& sessionId);
+ void keyError(const String& keySystem, const String& sessionId, MediaPlayerClient::MediaKeyErrorCode, unsigned short systemCode);
+ void keyMessage(const String& keySystem, const String& sessionId, const unsigned char* message, unsigned messageLength);
+ void keyNeeded(const String& keySystem, const String& sessionId, const unsigned char* initData, unsigned initDataLength);
+#endif
+
String referrer() const;
String userAgent() const;
@@ -353,6 +384,7 @@ private:
String m_url;
String m_contentMIMEType;
String m_contentTypeCodecs;
+ String m_keySystem;
FrameView* m_frameView;
IntSize m_size;
Preload m_preload;
@@ -370,7 +402,11 @@ private:
typedef PassOwnPtr<MediaPlayerPrivateInterface> (*CreateMediaEnginePlayer)(MediaPlayer*);
typedef void (*MediaEngineSupportedTypes)(HashSet<String>& types);
+#if ENABLE(ENCRYPTED_MEDIA)
+typedef MediaPlayer::SupportsType (*MediaEngineSupportsType)(const String& type, const String& codecs, const String& keySystem);
+#else
typedef MediaPlayer::SupportsType (*MediaEngineSupportsType)(const String& type, const String& codecs);
+#endif
typedef void (*MediaEngineGetSitesInMediaCache)(Vector<String>&);
typedef void (*MediaEngineClearMediaCache)();
typedef void (*MediaEngineClearMediaCacheForSite)(const String&);
diff --git a/Source/WebCore/platform/graphics/MediaPlayerPrivate.h b/Source/WebCore/platform/graphics/MediaPlayerPrivate.h
index 6c527d7e5..175d7c5bc 100644
--- a/Source/WebCore/platform/graphics/MediaPlayerPrivate.h
+++ b/Source/WebCore/platform/graphics/MediaPlayerPrivate.h
@@ -115,7 +115,10 @@ public:
virtual void deliverNotification(MediaPlayerProxyNotificationType) = 0;
virtual void setMediaPlayerProxy(WebMediaPlayerProxy*) = 0;
virtual void setControls(bool) { }
- virtual void enterFullscreen() { }
+#endif
+
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) || USE(NATIVE_FULLSCREEN_VIDEO)
+ virtual bool enterFullscreen() const { return false; }
virtual void exitFullscreen() { }
#endif
@@ -158,9 +161,17 @@ public:
#endif
#if ENABLE(MEDIA_SOURCE)
+ virtual MediaPlayer::AddIdStatus sourceAddId(const String&, const String&) { return MediaPlayer::NotSupported; }
+ virtual bool sourceRemoveId(const String&) { return false; }
virtual bool sourceAppend(const unsigned char*, unsigned) { return false; }
virtual void sourceEndOfStream(MediaPlayer::EndOfStreamStatus) { };
#endif
+
+#if ENABLE(ENCRYPTED_MEDIA)
+ virtual MediaPlayer::MediaKeyException addKey(const String& keySystem, const unsigned char* key, unsigned keyLength, const unsigned char* initData, unsigned initDataLength, const String& sessionId) { return MediaPlayer::KeySystemNotSupported; }
+ virtual MediaPlayer::MediaKeyException generateKeyRequest(const String& keySystem, const unsigned char* initData, unsigned initDataLength) { return MediaPlayer::KeySystemNotSupported; }
+ virtual MediaPlayer::MediaKeyException cancelKeyRequest(const String& keySystem, const String& sessionId) { return MediaPlayer::KeySystemNotSupported; }
+#endif
};
}
diff --git a/Source/WebCore/platform/graphics/Path.cpp b/Source/WebCore/platform/graphics/Path.cpp
index 128d92a1a..52153e571 100644
--- a/Source/WebCore/platform/graphics/Path.cpp
+++ b/Source/WebCore/platform/graphics/Path.cpp
@@ -97,7 +97,7 @@ void Path::addRoundedRect(const RoundedRect& r)
addRoundedRect(r.rect(), r.radii().topLeft(), r.radii().topRight(), r.radii().bottomLeft(), r.radii().bottomRight());
}
-void Path::addRoundedRect(const FloatRect& rect, const FloatSize& roundingRadii)
+void Path::addRoundedRect(const FloatRect& rect, const FloatSize& roundingRadii, RoundedRectStrategy strategy)
{
if (rect.isEmpty())
return;
@@ -115,10 +115,10 @@ void Path::addRoundedRect(const FloatRect& rect, const FloatSize& roundingRadii)
if (radius.height() > halfSize.height())
radius.setHeight(halfSize.height());
- addBeziersForRoundedRect(rect, radius, radius, radius, radius);
+ addPathForRoundedRect(rect, radius, radius, radius, radius, strategy);
}
-void Path::addRoundedRect(const FloatRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius)
+void Path::addRoundedRect(const FloatRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius, RoundedRectStrategy strategy)
{
if (rect.isEmpty())
return;
@@ -132,7 +132,21 @@ void Path::addRoundedRect(const FloatRect& rect, const FloatSize& topLeftRadius,
return;
}
+ addPathForRoundedRect(rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius, strategy);
+}
+
+void Path::addPathForRoundedRect(const FloatRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius, RoundedRectStrategy strategy)
+{
+ if (strategy == PreferBezierRoundedRect) {
+ addBeziersForRoundedRect(rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
+ return;
+ }
+
+#if USE(CG)
+ platformAddPathForRoundedRect(rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
+#else
addBeziersForRoundedRect(rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
+#endif
}
// Approximation of control point positions on a bezier to simulate a quarter of a circle.
diff --git a/Source/WebCore/platform/graphics/Path.h b/Source/WebCore/platform/graphics/Path.h
index 69ba93ef6..96c810425 100644
--- a/Source/WebCore/platform/graphics/Path.h
+++ b/Source/WebCore/platform/graphics/Path.h
@@ -135,8 +135,14 @@ namespace WebCore {
void addArc(const FloatPoint&, float radius, float startAngle, float endAngle, bool anticlockwise);
void addRect(const FloatRect&);
void addEllipse(const FloatRect&);
- void addRoundedRect(const FloatRect&, const FloatSize& roundingRadii);
- void addRoundedRect(const FloatRect&, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius);
+
+ enum RoundedRectStrategy {
+ PreferNativeRoundedRect,
+ PreferBezierRoundedRect
+ };
+
+ void addRoundedRect(const FloatRect&, const FloatSize& roundingRadii, RoundedRectStrategy = PreferNativeRoundedRect);
+ void addRoundedRect(const FloatRect&, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius, RoundedRectStrategy = PreferNativeRoundedRect);
void addRoundedRect(const RoundedRect&);
void translate(const FloatSize&);
@@ -146,8 +152,13 @@ namespace WebCore {
void apply(void* info, PathApplierFunction) const;
void transform(const AffineTransform&);
+ void addPathForRoundedRect(const FloatRect&, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius, RoundedRectStrategy = PreferNativeRoundedRect);
void addBeziersForRoundedRect(const FloatRect&, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius);
+#if USE(CG)
+ void platformAddPathForRoundedRect(const FloatRect&, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius);
+#endif
+
private:
PlatformPathPtr m_path;
};
diff --git a/Source/WebCore/platform/graphics/Pattern.h b/Source/WebCore/platform/graphics/Pattern.h
index 0909584a0..7ed5c0f47 100644
--- a/Source/WebCore/platform/graphics/Pattern.h
+++ b/Source/WebCore/platform/graphics/Pattern.h
@@ -96,7 +96,7 @@ private:
AffineTransform m_patternSpaceTransformation;
PlatformPatternPtr m_pattern;
#if USE(SKIA)
- size_t m_externalMemoryAllocated;
+ int m_externalMemoryAllocated;
#endif
};
diff --git a/Source/WebCore/platform/graphics/Region.cpp b/Source/WebCore/platform/graphics/Region.cpp
index 3f093ebdc..c4d2f5600 100644
--- a/Source/WebCore/platform/graphics/Region.cpp
+++ b/Source/WebCore/platform/graphics/Region.cpp
@@ -67,14 +67,38 @@ Vector<IntRect> Region::rects() const
bool Region::contains(const Region& region) const
{
+ if (!m_bounds.contains(region.m_bounds))
+ return false;
+
return WebCore::intersect(region, *this) == region;
}
bool Region::contains(const IntPoint& point) const
{
- // FIXME: This is inefficient. We should be able to iterate over the spans and find
- // out if the region contains the point.
- return contains(IntRect(point, IntSize(1, 1)));
+ if (!m_bounds.contains(point))
+ return false;
+
+ for (Shape::SpanIterator span = m_shape.spans_begin(), end = m_shape.spans_end(); span != end && span + 1 != end; ++span) {
+ int y = span->y;
+ int maxY = (span + 1)->y;
+
+ if (y > point.y())
+ break;
+ if (maxY <= point.y())
+ continue;
+
+ for (Shape::SegmentIterator segment = m_shape.segments_begin(span), end = m_shape.segments_end(span); segment != end && segment + 1 != end; segment += 2) {
+ int x = *segment;
+ int maxX = *(segment + 1);
+
+ if (x > point.x())
+ break;
+ if (maxX > point.x())
+ return true;
+ }
+ }
+
+ return false;
}
bool Region::intersects(const Region& region) const
@@ -479,6 +503,11 @@ void Region::unite(const Region& region)
void Region::subtract(const Region& region)
{
+ if (region.isEmpty())
+ return;
+ if (!m_bounds.intersects(region.m_bounds))
+ return;
+
Shape subtractedShape = Shape::subtractShapes(m_shape, region.m_shape);
m_shape.swap(subtractedShape);
diff --git a/Source/WebCore/platform/graphics/ShadowBlur.cpp b/Source/WebCore/platform/graphics/ShadowBlur.cpp
index 3b8a956b0..30f77e8b8 100644
--- a/Source/WebCore/platform/graphics/ShadowBlur.cpp
+++ b/Source/WebCore/platform/graphics/ShadowBlur.cpp
@@ -826,7 +826,7 @@ void ShadowBlur::blurShadowBuffer(const IntSize& templateSize)
return;
IntRect blurRect(IntPoint(), templateSize);
- RefPtr<ByteArray> layerData = m_layerImage->getUnmultipliedImageData(blurRect);
+ RefPtr<Uint8ClampedArray> layerData = m_layerImage->getUnmultipliedImageData(blurRect);
blurLayerImage(layerData->data(), blurRect.size(), blurRect.width() * 4);
m_layerImage->putByteArray(Unmultiplied, layerData.get(), blurRect.size(), blurRect, IntPoint());
}
diff --git a/Source/WebCore/platform/graphics/SimpleFontData.cpp b/Source/WebCore/platform/graphics/SimpleFontData.cpp
index 4537ab90c..222e43312 100644
--- a/Source/WebCore/platform/graphics/SimpleFontData.cpp
+++ b/Source/WebCore/platform/graphics/SimpleFontData.cpp
@@ -217,6 +217,21 @@ SimpleFontData::DerivedFontData::~DerivedFontData()
GlyphPageTreeNode::pruneTreeCustomFontData(verticalRightOrientation.get());
if (uprightOrientation)
GlyphPageTreeNode::pruneTreeCustomFontData(uprightOrientation.get());
+#if PLATFORM(MAC)
+ if (compositeFontReferences) {
+ CFDictionaryRef dictionary = CFDictionaryRef(compositeFontReferences.get());
+ CFIndex count = CFDictionaryGetCount(dictionary);
+ if (count > 0) {
+ Vector<SimpleFontData*, 2> stash(count);
+ SimpleFontData** fonts = stash.data();
+ CFDictionaryGetKeysAndValues(dictionary, 0, (const void **)fonts);
+ while (count-- > 0 && *fonts) {
+ OwnPtr<SimpleFontData> afont = adoptPtr(*fonts++);
+ GlyphPageTreeNode::pruneTreeCustomFontData(afont.get());
+ }
+ }
+ }
+#endif
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/SimpleFontData.h b/Source/WebCore/platform/graphics/SimpleFontData.h
index dd86f004e..6fc918a43 100644
--- a/Source/WebCore/platform/graphics/SimpleFontData.h
+++ b/Source/WebCore/platform/graphics/SimpleFontData.h
@@ -54,7 +54,11 @@ typedef struct OpaqueATSUStyle* ATSUStyle;
#endif
#if PLATFORM(QT)
+#if !HAVE(QRAWFONT)
#include <QFont>
+#else
+#include <QRawFont>
+#endif
#endif
namespace WebCore {
@@ -118,6 +122,7 @@ public:
FontMetrics& fontMetrics() { return m_fontMetrics; }
const FontMetrics& fontMetrics() const { return m_fontMetrics; }
+ float sizePerUnit() const { return platformData().size() / (fontMetrics().unitsPerEm() ? fontMetrics().unitsPerEm() : 1); }
float maxCharWidth() const { return m_maxCharWidth; }
void setMaxCharWidth(float maxCharWidth) { m_maxCharWidth = maxCharWidth; }
@@ -164,8 +169,10 @@ public:
#endif
#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN))
+ const SimpleFontData* getCompositeFontReferenceFontData(NSFont *key) const;
NSFont* getNSFont() const { return m_platformData.font(); }
#elif (PLATFORM(WX) && OS(DARWIN))
+ const SimpleFontData* getCompositeFontReferenceFontData(NSFont *key) const;
NSFont* getNSFont() const { return m_platformData.nsFont(); }
#endif
@@ -188,7 +195,11 @@ public:
#endif
#if PLATFORM(QT)
+#if !HAVE(QRAWFONT)
QFont getQtFont() const { return m_platformData.font(); }
+#else
+ QRawFont getQtRawFont() const { return m_platformData.rawFont(); }
+#endif // !HAVE(QRAWFONT)
#endif
#if PLATFORM(WIN) || (OS(WINDOWS) && PLATFORM(WX))
@@ -262,7 +273,10 @@ private:
OwnPtr<SimpleFontData> brokenIdeograph;
OwnPtr<SimpleFontData> verticalRightOrientation;
OwnPtr<SimpleFontData> uprightOrientation;
-
+#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN))
+ mutable RetainPtr<CFMutableDictionaryRef> compositeFontReferences;
+#endif
+
private:
DerivedFontData(bool custom)
: forCustomFont(custom)
@@ -341,7 +355,7 @@ ALWAYS_INLINE float SimpleFontData::widthForGlyph(Glyph glyph) const
m_glyphToWidthMap.setMetricsForGlyph(glyph, width);
return width;
}
-#endif
+#endif // HAVE(QRAWFONT)
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/TextRun.cpp b/Source/WebCore/platform/graphics/TextRun.cpp
index b41bc873d..3ab810833 100644
--- a/Source/WebCore/platform/graphics/TextRun.cpp
+++ b/Source/WebCore/platform/graphics/TextRun.cpp
@@ -28,6 +28,20 @@
namespace WebCore {
+class ExpectedTextRunSize {
+ const void* pointer;;
+ int integers[2];
+ float float1;
+#if ENABLE(SVG)
+ float float2;
+#endif
+ float float3;
+ uint32_t bitfields : 9;
+ RefPtr<TextRun::RenderingContext> renderingContext;
+};
+
+COMPILE_ASSERT(sizeof(TextRun) == sizeof(ExpectedTextRunSize), TextRun_is_not_of_expected_size);
+
bool TextRun::s_allowsRoundingHacks = false;
void TextRun::setAllowsRoundingHacks(bool allowsRoundingHacks)
diff --git a/Source/WebCore/platform/graphics/TextRun.h b/Source/WebCore/platform/graphics/TextRun.h
index 029c708a6..c2d86d6e5 100644
--- a/Source/WebCore/platform/graphics/TextRun.h
+++ b/Source/WebCore/platform/graphics/TextRun.h
@@ -58,38 +58,40 @@ public:
typedef unsigned RoundingHacks;
- TextRun(const UChar* c, int len, bool allowTabs = false, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, RoundingHacks roundingHacks = RunRounding | WordRounding)
+ TextRun(const UChar* c, int len, bool allowTabs = false, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, bool characterScanForCodePath = true, RoundingHacks roundingHacks = RunRounding | WordRounding)
: m_characters(c)
, m_charactersLength(len)
, m_len(len)
, m_xpos(xpos)
- , m_expansion(expansion)
- , m_expansionBehavior(expansionBehavior)
#if ENABLE(SVG)
, m_horizontalGlyphStretch(1)
#endif
+ , m_expansion(expansion)
+ , m_expansionBehavior(expansionBehavior)
, m_allowTabs(allowTabs)
, m_direction(direction)
, m_directionalOverride(directionalOverride)
+ , m_characterScanForCodePath(characterScanForCodePath)
, m_applyRunRounding((roundingHacks & RunRounding) && s_allowsRoundingHacks)
, m_applyWordRounding((roundingHacks & WordRounding) && s_allowsRoundingHacks)
, m_disableSpacing(false)
{
}
- TextRun(const String& s, bool allowTabs = false, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, RoundingHacks roundingHacks = RunRounding | WordRounding)
+ TextRun(const String& s, bool allowTabs = false, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, bool characterScanForCodePath = true, RoundingHacks roundingHacks = RunRounding | WordRounding)
: m_characters(s.characters())
, m_charactersLength(s.length())
, m_len(s.length())
, m_xpos(xpos)
- , m_expansion(expansion)
- , m_expansionBehavior(expansionBehavior)
#if ENABLE(SVG)
, m_horizontalGlyphStretch(1)
#endif
+ , m_expansion(expansion)
+ , m_expansionBehavior(expansionBehavior)
, m_allowTabs(allowTabs)
, m_direction(direction)
, m_directionalOverride(directionalOverride)
+ , m_characterScanForCodePath(characterScanForCodePath)
, m_applyRunRounding((roundingHacks & RunRounding) && s_allowsRoundingHacks)
, m_applyWordRounding((roundingHacks & WordRounding) && s_allowsRoundingHacks)
, m_disableSpacing(false)
@@ -118,10 +120,11 @@ public:
float expansion() const { return m_expansion; }
bool allowsLeadingExpansion() const { return m_expansionBehavior & AllowLeadingExpansion; }
bool allowsTrailingExpansion() const { return m_expansionBehavior & AllowTrailingExpansion; }
- TextDirection direction() const { return m_direction; }
+ TextDirection direction() const { return static_cast<TextDirection>(m_direction); }
bool rtl() const { return m_direction == RTL; }
bool ltr() const { return m_direction == LTR; }
bool directionalOverride() const { return m_directionalOverride; }
+ bool characterScanForCodePath() const { return m_characterScanForCodePath; }
bool applyRunRounding() const { return m_applyRunRounding; }
bool applyWordRounding() const { return m_applyWordRounding; }
bool spacingDisabled() const { return m_disableSpacing; }
@@ -130,6 +133,7 @@ public:
void disableRoundingHacks() { m_applyRunRounding = m_applyWordRounding = false; }
void setDirection(TextDirection direction) { m_direction = direction; }
void setDirectionalOverride(bool override) { m_directionalOverride = override; }
+ void setCharacterScanForCodePath(bool scan) { m_characterScanForCodePath = scan; }
class RenderingContext : public RefCounted<RenderingContext> {
public:
@@ -159,17 +163,18 @@ private:
// start of the containing block. In the case of right alignment or center alignment, left start of
// the text line is not the same as left start of the containing block.
float m_xpos;
- float m_expansion;
- ExpansionBehavior m_expansionBehavior;
#if ENABLE(SVG)
float m_horizontalGlyphStretch;
#endif
- bool m_allowTabs;
- TextDirection m_direction;
- bool m_directionalOverride; // Was this direction set by an override character.
- bool m_applyRunRounding;
- bool m_applyWordRounding;
- bool m_disableSpacing;
+ float m_expansion;
+ ExpansionBehavior m_expansionBehavior : 2;
+ unsigned m_allowTabs : 1;
+ unsigned m_direction : 1;
+ unsigned m_directionalOverride : 1; // Was this direction set by an override character.
+ unsigned m_characterScanForCodePath : 1;
+ unsigned m_applyRunRounding : 1;
+ unsigned m_applyWordRounding : 1;
+ unsigned m_disableSpacing : 1;
RefPtr<RenderingContext> m_renderingContext;
};
diff --git a/Source/WebCore/platform/graphics/TiledBacking.h b/Source/WebCore/platform/graphics/TiledBacking.h
new file mode 100644
index 000000000..acdcf5e78
--- /dev/null
+++ b/Source/WebCore/platform/graphics/TiledBacking.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TiledBacking_h
+#define TiledBacking_h
+
+namespace WebCore {
+
+class IntRect;
+
+class TiledBacking {
+public:
+ virtual ~TiledBacking() { }
+
+ virtual void visibleRectChanged(const IntRect&) = 0;
+ virtual void setIsInWindow(bool) = 0;
+ virtual void setCanHaveScrollbars(bool) = 0;
+};
+
+} // namespace WebCore
+
+#endif // TiledBacking_h
diff --git a/Source/WebCore/platform/graphics/TiledBackingStore.cpp b/Source/WebCore/platform/graphics/TiledBackingStore.cpp
index 9bd424c94..8484da971 100644
--- a/Source/WebCore/platform/graphics/TiledBackingStore.cpp
+++ b/Source/WebCore/platform/graphics/TiledBackingStore.cpp
@@ -69,13 +69,17 @@ void TiledBackingStore::setTileCreationDelay(double delay)
void TiledBackingStore::coverWithTilesIfNeeded(const FloatPoint& trajectoryVector)
{
IntRect visibleRect = this->visibleRect();
- if (m_trajectoryVector == trajectoryVector && m_visibleRect == visibleRect)
+
+ FloatPoint normalizedVector = trajectoryVector;
+ normalizedVector.normalize();
+
+ if (m_trajectoryVector == normalizedVector && m_visibleRect == visibleRect)
return;
- m_trajectoryVector = trajectoryVector;
+ m_trajectoryVector = normalizedVector;
m_visibleRect = visibleRect;
- startBackingStoreUpdateTimer();
+ createTiles();
}
void TiledBackingStore::invalidate(const IntRect& contentsDirtyRect)
@@ -162,9 +166,14 @@ void TiledBackingStore::paint(GraphicsContext* context, const IntRect& rect)
context->restore();
}
+IntRect TiledBackingStore::visibleContentsRect() const
+{
+ return intersection(m_client->tiledBackingStoreVisibleRect(), m_client->tiledBackingStoreContentsRect());
+}
+
IntRect TiledBackingStore::visibleRect() const
{
- return mapFromContents(intersection(m_client->tiledBackingStoreVisibleRect(), m_client->tiledBackingStoreContentsRect()));
+ return mapFromContents(visibleContentsRect());
}
void TiledBackingStore::setContentsScale(float scale)
@@ -223,7 +232,7 @@ float TiledBackingStore::coverageRatio(const WebCore::IntRect& contentsRect) con
bool TiledBackingStore::visibleAreaIsCovered() const
{
- return coverageRatio(visibleRect()) == 1.0f;
+ return coverageRatio(visibleContentsRect()) == 1.0f;
}
void TiledBackingStore::createTiles()
@@ -340,8 +349,7 @@ void TiledBackingStore::computeCoverAndKeepRect(const IntRect& visibleRect, IntR
coverRect.inflateY(visibleRect.height() * (m_coverAreaMultiplier - 1) / 2);
keepRect = coverRect;
- float trajectoryVectorNorm = sqrt(pow(m_trajectoryVector.x(), 2) + pow(m_trajectoryVector.y(), 2));
- if (trajectoryVectorNorm) {
+ if (m_trajectoryVector != FloatPoint::zero()) {
// A null trajectory vector (no motion) means that tiles for the coverArea will be created.
// A non-null trajectory vector will shrink the covered rect to visibleRect plus its expansion from its
// center toward the cover area edges in the direction of the given vector.
@@ -356,8 +364,8 @@ void TiledBackingStore::computeCoverAndKeepRect(const IntRect& visibleRect, IntR
// Unite the visible rect with a "ghost" of the visible rect moved in the direction of the trajectory vector.
coverRect = visibleRect;
- coverRect.move(coverRect.width() * m_trajectoryVector.x() / trajectoryVectorNorm * trajectoryVectorMultiplier,
- coverRect.height() * m_trajectoryVector.y() / trajectoryVectorNorm * trajectoryVectorMultiplier);
+ coverRect.move(coverRect.width() * m_trajectoryVector.x() * trajectoryVectorMultiplier,
+ coverRect.height() * m_trajectoryVector.y() * trajectoryVectorMultiplier);
coverRect.unite(visibleRect);
}
diff --git a/Source/WebCore/platform/graphics/TiledBackingStore.h b/Source/WebCore/platform/graphics/TiledBackingStore.h
index 3c6ac9350..8d662e4c4 100644
--- a/Source/WebCore/platform/graphics/TiledBackingStore.h
+++ b/Source/WebCore/platform/graphics/TiledBackingStore.h
@@ -100,6 +100,7 @@ private:
void setTile(const Tile::Coordinate& coordinate, PassRefPtr<Tile> tile);
void removeTile(const Tile::Coordinate& coordinate);
+ IntRect visibleContentsRect() const;
IntRect visibleRect() const;
float coverageRatio(const IntRect&) const;
diff --git a/Source/WebCore/platform/graphics/TiledBackingStoreBackend.h b/Source/WebCore/platform/graphics/TiledBackingStoreBackend.h
index ae5844e86..6b7fe8ac5 100644
--- a/Source/WebCore/platform/graphics/TiledBackingStoreBackend.h
+++ b/Source/WebCore/platform/graphics/TiledBackingStoreBackend.h
@@ -22,8 +22,8 @@
#if USE(TILED_BACKING_STORE)
-#include "PassOwnPtr.h"
#include "Tile.h"
+#include <wtf/PassOwnPtr.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/graphics/TiledBackingStoreClient.h b/Source/WebCore/platform/graphics/TiledBackingStoreClient.h
index 206f1aa5c..0e0214777 100644
--- a/Source/WebCore/platform/graphics/TiledBackingStoreClient.h
+++ b/Source/WebCore/platform/graphics/TiledBackingStoreClient.h
@@ -29,6 +29,7 @@ class GraphicsContext;
class TiledBackingStoreClient {
public:
+ virtual ~TiledBackingStoreClient() { }
virtual void tiledBackingStorePaintBegin() = 0;
virtual void tiledBackingStorePaint(GraphicsContext*, const IntRect&) = 0;
virtual void tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea) = 0;
diff --git a/Source/WebCore/platform/graphics/WOFFFileFormat.cpp b/Source/WebCore/platform/graphics/WOFFFileFormat.cpp
index f556221b6..d9a9e6e42 100644
--- a/Source/WebCore/platform/graphics/WOFFFileFormat.cpp
+++ b/Source/WebCore/platform/graphics/WOFFFileFormat.cpp
@@ -63,7 +63,7 @@ static bool readUInt32(SharedBuffer* buffer, size_t& offset, uint32_t& value)
if (buffer->size() - offset < sizeof(value))
return false;
- value = ntohl(*reinterpret_cast<const uint32_t*>(buffer->data() + offset));
+ value = ntohl(*reinterpret_cast_ptr<const uint32_t*>(buffer->data() + offset));
offset += sizeof(value);
return true;
@@ -75,7 +75,7 @@ static bool readUInt16(SharedBuffer* buffer, size_t& offset, uint16_t& value)
if (buffer->size() - offset < sizeof(value))
return false;
- value = ntohs(*reinterpret_cast<const uint16_t*>(buffer->data() + offset));
+ value = ntohs(*reinterpret_cast_ptr<const uint16_t*>(buffer->data() + offset));
offset += sizeof(value);
return true;
@@ -84,13 +84,13 @@ static bool readUInt16(SharedBuffer* buffer, size_t& offset, uint16_t& value)
static bool writeUInt32(Vector<char>& vector, uint32_t value)
{
uint32_t bigEndianValue = htonl(value);
- return vector.tryAppend(reinterpret_cast<char*>(&bigEndianValue), sizeof(bigEndianValue));
+ return vector.tryAppend(reinterpret_cast_ptr<char*>(&bigEndianValue), sizeof(bigEndianValue));
}
static bool writeUInt16(Vector<char>& vector, uint16_t value)
{
uint16_t bigEndianValue = htons(value);
- return vector.tryAppend(reinterpret_cast<char*>(&bigEndianValue), sizeof(bigEndianValue));
+ return vector.tryAppend(reinterpret_cast_ptr<char*>(&bigEndianValue), sizeof(bigEndianValue));
}
static const uint32_t woffSignature = 0x774f4646; /* 'wOFF' */
@@ -210,7 +210,7 @@ bool convertWOFFToSfnt(SharedBuffer* woff, Vector<char>& sfnt)
return false;
// Write an sfnt table directory entry.
- uint32_t* sfntTableDirectoryPtr = reinterpret_cast<uint32_t*>(sfnt.data() + sfntTableDirectoryCursor);
+ uint32_t* sfntTableDirectoryPtr = reinterpret_cast_ptr<uint32_t*>(sfnt.data() + sfntTableDirectoryCursor);
*sfntTableDirectoryPtr++ = htonl(tableTag);
*sfntTableDirectoryPtr++ = htonl(tableOrigChecksum);
*sfntTableDirectoryPtr++ = htonl(sfnt.size());
diff --git a/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp b/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp
index 32c85cd8f..875d12dfb 100644
--- a/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp
+++ b/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp
@@ -160,7 +160,8 @@ private:
virtual bool platformCALayerContentsOpaque() const { return false; }
virtual bool platformCALayerDrawsContent() const { return false; }
virtual void platformCALayerLayerDidDisplay(PlatformLayer*) { }
- virtual void platformCALayerDidCreateTiles() { }
+ virtual void platformCALayerDidCreateTiles(const Vector<FloatRect>&) { }
+ virtual float platformCALayerDeviceScaleFactor() { return 1; }
AVFWrapper* m_parent;
};
diff --git a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm
index d8f1fe8dc..9e8653497 100644
--- a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm
+++ b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm
@@ -657,7 +657,7 @@ RetainPtr<CGImageRef> MediaPlayerPrivateAVFoundationObjC::createImageForTimeInRe
#endif
[m_imageGenerator.get() setMaximumSize:CGSize(rect.size())];
- CGImageRef image = [m_imageGenerator.get() copyCGImageAtTime:CMTimeMakeWithSeconds(time, 600) actualTime:nil error:nil];
+ RetainPtr<CGImageRef> image = adoptCF([m_imageGenerator.get() copyCGImageAtTime:CMTimeMakeWithSeconds(time, 600) actualTime:nil error:nil]);
#if !LOG_DISABLED
double duration = WTF::currentTime() - start;
diff --git a/Source/WebCore/platform/graphics/blackberry/CanvasLayerWebKitThread.cpp b/Source/WebCore/platform/graphics/blackberry/CanvasLayerWebKitThread.cpp
index 4d2032679..be558864e 100644
--- a/Source/WebCore/platform/graphics/blackberry/CanvasLayerWebKitThread.cpp
+++ b/Source/WebCore/platform/graphics/blackberry/CanvasLayerWebKitThread.cpp
@@ -19,36 +19,31 @@
#include "config.h"
#include "CanvasLayerWebKitThread.h"
-#if USE(ACCELERATED_COMPOSITING) && ENABLE(SKIA_GPU_CANVAS)
+#if USE(ACCELERATED_COMPOSITING) && ENABLE(ACCELERATED_2D_CANVAS)
-#include "HTMLCanvasElement.h"
-#include "PlatformContextSkia.h"
-
-#include <BlackBerryPlatformGraphics.h>
+#include "SharedGraphicsContext3D.h"
#include <GLES2/gl2.h>
-#include <GrGLTexture.h>
#include <SkGpuDevice.h>
namespace WebCore {
-CanvasLayerWebKitThread::CanvasLayerWebKitThread(HTMLCanvasElement* canvas)
- : LayerWebKitThread(Layer, 0)
+CanvasLayerWebKitThread::CanvasLayerWebKitThread(SkGpuDevice* device)
+ : LayerWebKitThread(CanvasLayer, 0)
{
- setCanvas(canvas);
+ setDevice(device);
}
CanvasLayerWebKitThread::~CanvasLayerWebKitThread()
{
if (m_texID) {
- BlackBerry::Platform::Graphics::makeSharedResourceContextCurrent(BlackBerry::Platform::Graphics::GLES2);
+ SharedGraphicsContext3D::get()->makeContextCurrent();
glDeleteTextures(1, &m_texID);
}
}
-void CanvasLayerWebKitThread::setCanvas(HTMLCanvasElement* canvas)
+void CanvasLayerWebKitThread::setDevice(SkGpuDevice* device)
{
- m_canvas = canvas;
- setNeedsTexture(isDrawable() && canvas);
+ m_device = device;
setLayerProgramShader(LayerProgramShaderRGBA);
setNeedsDisplay();
}
@@ -61,21 +56,11 @@ void CanvasLayerWebKitThread::setNeedsDisplay()
void CanvasLayerWebKitThread::updateTextureContentsIfNeeded()
{
- if (!m_needsDisplay)
+ if (!m_needsDisplay || !m_device)
return;
m_needsDisplay = false;
-
- if (!m_canvas || !m_canvas->drawingContext())
- return;
-
- SkGpuDevice* gpuDevice = static_cast<SkGpuDevice*>(m_canvas->drawingContext()->platformContext()->canvas()->getDevice());
- gpuDevice->makeRenderTargetCurrent();
- // We know this is a GrGLTexture
- if (GrGLTexture* deviceTexture = (GrGLTexture*)gpuDevice->accessTexture()) {
- m_texWidth = deviceTexture->allocWidth();
- m_texHeight = deviceTexture->allocHeight();
- }
+ m_device->makeRenderTargetCurrent();
GLint previousTexture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &previousTexture);
@@ -87,18 +72,19 @@ void CanvasLayerWebKitThread::updateTextureContentsIfNeeded()
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_canvas->width(), m_canvas->height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_device->width(), m_device->height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
createFrontBufferLock();
}
pthread_mutex_lock(m_frontBufferLock);
glBindTexture(GL_TEXTURE_2D, m_texID);
- glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, m_texWidth, m_texHeight, 0);
+ glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, m_device->width(), m_device->height(), 0);
+ glFinish(); // This might be implicit in the CopyTexImage2D, but explicit Finish is required on some architectures
glBindTexture(GL_TEXTURE_2D, previousTexture);
pthread_mutex_unlock(m_frontBufferLock);
}
}
-#endif // USE(ACCELERATED_COMPOSITING) && ENABLE(SKIA_GPU_CANVAS)
+#endif // USE(ACCELERATED_COMPOSITING) && ENABLE(ACCELERATED_2D_CANVAS)
diff --git a/Source/WebCore/platform/graphics/blackberry/CanvasLayerWebKitThread.h b/Source/WebCore/platform/graphics/blackberry/CanvasLayerWebKitThread.h
index 9a731ce82..eac6b8238 100644
--- a/Source/WebCore/platform/graphics/blackberry/CanvasLayerWebKitThread.h
+++ b/Source/WebCore/platform/graphics/blackberry/CanvasLayerWebKitThread.h
@@ -19,24 +19,26 @@
#ifndef CanvasLayerWebKitThread_h
#define CanvasLayerWebKitThread_h
-#if USE(ACCELERATED_COMPOSITING) && ENABLE(SKIA_GPU_CANVAS)
+#if USE(ACCELERATED_COMPOSITING) && ENABLE(ACCELERATED_2D_CANVAS)
#include "LayerWebKitThread.h"
+class SkGpuDevice;
+
namespace WebCore {
class HTMLCanvasElement;
class CanvasLayerWebKitThread : public LayerWebKitThread {
public:
- static PassRefPtr<CanvasLayerWebKitThread> create(HTMLCanvasElement* canvas)
+ static PassRefPtr<CanvasLayerWebKitThread> create(SkGpuDevice* device)
{
- return adoptRef(new CanvasLayerWebKitThread(canvas));
+ return adoptRef(new CanvasLayerWebKitThread(device));
}
virtual ~CanvasLayerWebKitThread();
- void setCanvas(HTMLCanvasElement*);
+ void setDevice(SkGpuDevice*);
virtual void setNeedsDisplay();
@@ -44,12 +46,13 @@ protected:
virtual void updateTextureContentsIfNeeded();
private:
- CanvasLayerWebKitThread(HTMLCanvasElement*);
+ CanvasLayerWebKitThread(SkGpuDevice*);
bool m_needsDisplay;
+ SkGpuDevice* m_device;
};
}
-#endif // USE(ACCELERATED_COMPOSITING) && ENABLE(SKIA_GPU_CANVAS)
+#endif // USE(ACCELERATED_COMPOSITING) && ENABLE(ACCELERATED_2D_CANVAS)
#endif // CanvasLayerWebKitThread_h
diff --git a/Source/WebCore/platform/graphics/blackberry/DisplayRefreshMonitorBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/DisplayRefreshMonitorBlackBerry.cpp
new file mode 100644
index 000000000..daf2b3960
--- /dev/null
+++ b/Source/WebCore/platform/graphics/blackberry/DisplayRefreshMonitorBlackBerry.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2010, 2011 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+
+#include "DisplayRefreshMonitor.h"
+
+#include <wtf/CurrentTime.h>
+#include <wtf/MainThread.h>
+
+namespace WebCore {
+
+DisplayAnimationClient::DisplayAnimationClient(DisplayRefreshMonitor *monitor)
+ : m_monitor(monitor)
+{
+}
+
+void DisplayAnimationClient::animationFrameChanged()
+{
+ m_monitor->displayLinkFired();
+}
+
+DisplayRefreshMonitor::~DisplayRefreshMonitor()
+{
+ stopAnimationClient();
+ cancelCallOnMainThread(DisplayRefreshMonitor::refreshDisplayOnMainThread, this);
+}
+
+void DisplayRefreshMonitor::startAnimationClient()
+{
+ if (m_animationClient)
+ return;
+
+ m_animationClient = new DisplayAnimationClient(this);
+ BlackBerry::Platform::AnimationFrameRateController::instance()->addClient(m_animationClient);
+}
+
+void DisplayRefreshMonitor::stopAnimationClient()
+{
+ if (!m_animationClient)
+ return;
+
+ BlackBerry::Platform::AnimationFrameRateController::instance()->removeClient(m_animationClient);
+ delete m_animationClient;
+ m_animationClient = 0;
+}
+
+bool DisplayRefreshMonitor::requestRefreshCallback()
+{
+ MutexLocker lock(m_mutex);
+
+ startAnimationClient();
+
+ m_scheduled = true;
+ return true;
+}
+
+void DisplayRefreshMonitor::displayLinkFired()
+{
+ MutexLocker lock(m_mutex);
+
+ if (!m_scheduled || !m_previousFrameDone)
+ return;
+
+ m_previousFrameDone = false;
+
+ m_monotonicAnimationStartTime = monotonicallyIncreasingTime();
+
+ callOnMainThread(refreshDisplayOnMainThread, this);
+}
+
+}
+
+#endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
diff --git a/Source/WebCore/platform/graphics/blackberry/DrawingBufferBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/DrawingBufferBlackBerry.cpp
index c53108c00..8dfd6f3f7 100644
--- a/Source/WebCore/platform/graphics/blackberry/DrawingBufferBlackBerry.cpp
+++ b/Source/WebCore/platform/graphics/blackberry/DrawingBufferBlackBerry.cpp
@@ -67,6 +67,8 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context, const IntSize& size)
: m_context(context)
, m_size(size)
, m_fbo(context->createFramebuffer())
+ , m_frontColorBuffer(0)
+ , m_separateFrontTexture(false)
{
m_internal = adoptPtr(new DrawingBufferInternal);
@@ -85,25 +87,6 @@ DrawingBuffer::~DrawingBuffer()
clear();
}
-#if USE(ACCELERATED_COMPOSITING)
-void DrawingBuffer::publishToPlatformLayer()
-{
- if (!m_context)
- return;
-
- if (m_callback)
- m_callback->willPublish();
-
- // FIXME: We do the copy in the canvas' (child) context so that it executes in the correct order relative to
- // other commands in the child context. This ensures that the parent texture always contains a complete
- // frame and not some intermediate result. However, there is no synchronization to ensure that this copy
- // 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();
- m_context->flush();
-}
-#endif
-
bool DrawingBuffer::reset(const IntSize& newSize)
{
if (!m_context)
@@ -125,6 +108,20 @@ PlatformLayer* DrawingBuffer::platformLayer()
{
return m_internal->platformLayer.get();
}
+
+void DrawingBuffer::prepareBackBuffer()
+{
+}
+
+bool DrawingBuffer::requiresCopyFromBackToFrontBuffer() const
+{
+ return false;
+}
+
+unsigned DrawingBuffer::frontColorBuffer() const
+{
+ return colorBuffer();
+}
#endif
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/blackberry/GraphicsContext3DBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/GraphicsContext3DBlackBerry.cpp
index 56a585e04..73f0bdfc5 100644
--- a/Source/WebCore/platform/graphics/blackberry/GraphicsContext3DBlackBerry.cpp
+++ b/Source/WebCore/platform/graphics/blackberry/GraphicsContext3DBlackBerry.cpp
@@ -187,21 +187,26 @@ void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imag
canvasBitmap.setConfig(SkBitmap::kARGB_8888_Config, canvasWidth, canvasHeight);
canvasBitmap.allocPixels(0, 0);
- bool rc = canvasBitmap.copyPixelsFrom(static_cast<void*>(const_cast<unsigned char*>(tempPixels)), imageWidth * imageHeight * 4);
+ canvasBitmap.lockPixels();
+ memcpy(canvasBitmap.getPixels(), tempPixels, imageWidth * imageHeight * 4);
+ canvasBitmap.unlockPixels();
delete [] tempPixels;
FloatRect src(0, 0, canvasWidth, canvasHeight);
FloatRect dst(0, 0, imageWidth, imageHeight);
RefPtr<BitmapImageSingleFrameSkia> bitmapImage = BitmapImageSingleFrameSkia::create(canvasBitmap, false);
- if (rc)
- context->drawImage(bitmapImage.get(), ColorSpaceDeviceRGB, dst, src, CompositeCopy, false);
+ context->drawImage(bitmapImage.get(), ColorSpaceDeviceRGB, dst, src, CompositeCopy, DoNotRespectImageOrientation, false);
}
void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>)
{
}
+void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<ErrorMessageCallback>)
+{
+}
+
} // namespace WebCore
#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp
index 135257a03..1b81f54dd 100644
--- a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp
+++ b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp
@@ -92,6 +92,12 @@ GraphicsLayerBlackBerry::GraphicsLayerBlackBerry(GraphicsLayerClient* client)
GraphicsLayerBlackBerry::~GraphicsLayerBlackBerry()
{
+ // Do cleanup while we can still safely call methods on the derived class.
+ willBeDestroyed();
+}
+
+void GraphicsLayerBlackBerry::willBeDestroyed()
+{
if (m_layer)
m_layer->setOwner(0);
if (m_contentsLayer)
diff --git a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.h b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.h
index ef7cddaeb..c266947af 100644
--- a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.h
+++ b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.h
@@ -123,6 +123,8 @@ public:
bool contentsVisible(const IntRect& contentRect) const;
private:
+ virtual void willBeDestroyed();
+
void updateOpacityOnLayer();
LayerWebKitThread* primaryLayer() const { return m_transformLayer.get() ? m_transformLayer.get() : m_layer.get(); }
diff --git a/Source/WebCore/platform/graphics/blackberry/InstrumentedPlatformCanvas.h b/Source/WebCore/platform/graphics/blackberry/InstrumentedPlatformCanvas.h
index 1629ff107..927b5990d 100644
--- a/Source/WebCore/platform/graphics/blackberry/InstrumentedPlatformCanvas.h
+++ b/Source/WebCore/platform/graphics/blackberry/InstrumentedPlatformCanvas.h
@@ -34,14 +34,14 @@
namespace WebCore {
-class InstrumentedPlatformCanvas : public skia::PlatformCanvas {
+class InstrumentedPlatformCanvas : public SkCanvas {
public:
- InstrumentedPlatformCanvas(int width, int height, bool is_opaque, SkDeviceFactory* factory)
- : skia::PlatformCanvas(width, height, is_opaque, factory)
- , m_size(width, height)
+ InstrumentedPlatformCanvas(int width, int height)
+ : m_size(width, height)
, m_isSolidColor(true)
, m_solidColor(0, 0, 0, 0)
{
+ setDevice(new SkDevice(SkBitmap::kARGB_8888_Config, width, height))->unref();
}
virtual ~InstrumentedPlatformCanvas() { }
@@ -53,76 +53,76 @@ public:
virtual int save(SaveFlags flags)
{
WRAPCANVAS_LOG_ENTRY("");
- return skia::PlatformCanvas::save(flags);
+ return SkCanvas::save(flags);
}
virtual int saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags)
{
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = false;
- return skia::PlatformCanvas::saveLayer(bounds, paint, flags);
+ return SkCanvas::saveLayer(bounds, paint, flags);
}
virtual void restore()
{
WRAPCANVAS_LOG_ENTRY("");
- skia::PlatformCanvas::restore();
+ SkCanvas::restore();
}
virtual bool translate(SkScalar dx, SkScalar dy)
{
WRAPCANVAS_LOG_ENTRY("");
- return skia::PlatformCanvas::translate(dx, dy);
+ return SkCanvas::translate(dx, dy);
}
virtual bool scale(SkScalar sx, SkScalar sy)
{
WRAPCANVAS_LOG_ENTRY("");
- return skia::PlatformCanvas::scale(sx, sy);
+ return SkCanvas::scale(sx, sy);
}
virtual bool rotate(SkScalar degrees)
{
WRAPCANVAS_LOG_ENTRY("");
- return skia::PlatformCanvas::rotate(degrees);
+ return SkCanvas::rotate(degrees);
}
virtual bool skew(SkScalar sx, SkScalar sy)
{
WRAPCANVAS_LOG_ENTRY("");
- return skia::PlatformCanvas::skew(sx, sy);
+ return SkCanvas::skew(sx, sy);
}
virtual bool concat(const SkMatrix& matrix)
{
WRAPCANVAS_LOG_ENTRY("");
- return skia::PlatformCanvas::concat(matrix);
+ return SkCanvas::concat(matrix);
}
virtual void setMatrix(const SkMatrix& matrix)
{
WRAPCANVAS_LOG_ENTRY("");
- skia::PlatformCanvas::setMatrix(matrix);
+ SkCanvas::setMatrix(matrix);
}
virtual bool clipRect(const SkRect& rect, SkRegion::Op op)
{
WRAPCANVAS_LOG_ENTRY("");
- return skia::PlatformCanvas::clipRect(rect, op);
+ return SkCanvas::clipRect(rect, op);
}
virtual bool clipPath(const SkPath& path, SkRegion::Op op)
{
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = false;
- return skia::PlatformCanvas::clipPath(path, op);
+ return SkCanvas::clipPath(path, op);
}
virtual bool clipRegion(const SkRegion& region, SkRegion::Op op)
{
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = false;
- return skia::PlatformCanvas::clipRegion(region, op);
+ return SkCanvas::clipRegion(region, op);
}
virtual void clear(SkColor color)
@@ -130,14 +130,14 @@ public:
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = true;
m_solidColor = Color(color);
- skia::PlatformCanvas::clear(color);
+ SkCanvas::clear(color);
}
virtual void drawPaint(const SkPaint& paint)
{
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = false;
- skia::PlatformCanvas::drawPaint(paint);
+ SkCanvas::drawPaint(paint);
}
virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
@@ -145,7 +145,7 @@ public:
{
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = false;
- skia::PlatformCanvas::drawPoints(mode, count, pts, paint);
+ SkCanvas::drawPoints(mode, count, pts, paint);
}
virtual void drawRect(const SkRect& rect, const SkPaint& paint)
@@ -165,14 +165,14 @@ public:
m_isSolidColor = false;
} else
m_isSolidColor = false;
- skia::PlatformCanvas::drawRect(rect, paint);
+ SkCanvas::drawRect(rect, paint);
}
virtual void drawPath(const SkPath& path, const SkPaint& paint)
{
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = false;
- skia::PlatformCanvas::drawPath(path, paint);
+ SkCanvas::drawPath(path, paint);
}
virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left,
@@ -180,7 +180,7 @@ public:
{
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = false;
- skia::PlatformCanvas::drawBitmap(bitmap, left, top, paint);
+ SkCanvas::drawBitmap(bitmap, left, top, paint);
}
virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
@@ -188,7 +188,7 @@ public:
{
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = false;
- skia::PlatformCanvas::drawBitmapRect(bitmap, src, dst, paint);
+ SkCanvas::drawBitmapRect(bitmap, src, dst, paint);
}
virtual void drawBitmapMatrix(const SkBitmap& bitmap,
@@ -196,7 +196,15 @@ public:
{
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = false;
- skia::PlatformCanvas::drawBitmapMatrix(bitmap, matrix, paint);
+ SkCanvas::drawBitmapMatrix(bitmap, matrix, paint);
+ }
+
+ virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
+ const SkRect& dst, const SkPaint* paint = 0)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ SkCanvas::drawBitmapNine(bitmap, center, dst, paint);
}
virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
@@ -204,7 +212,7 @@ public:
{
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = false;
- skia::PlatformCanvas::drawSprite(bitmap, left, top, paint);
+ SkCanvas::drawSprite(bitmap, left, top, paint);
}
virtual void drawText(const void* text, size_t byteLength, SkScalar x,
@@ -212,7 +220,7 @@ public:
{
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = false;
- skia::PlatformCanvas::drawText(text, byteLength, x, y, paint);
+ SkCanvas::drawText(text, byteLength, x, y, paint);
}
virtual void drawPosText(const void* text, size_t byteLength,
@@ -220,7 +228,7 @@ public:
{
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = false;
- skia::PlatformCanvas::drawPosText(text, byteLength, pos, paint);
+ SkCanvas::drawPosText(text, byteLength, pos, paint);
}
virtual void drawPosTextH(const void* text, size_t byteLength,
@@ -228,7 +236,7 @@ public:
{
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = false;
- skia::PlatformCanvas::drawPosTextH(text, byteLength, xpos, constY, paint);
+ SkCanvas::drawPosTextH(text, byteLength, xpos, constY, paint);
}
virtual void drawTextOnPath(const void* text, size_t byteLength,
@@ -236,14 +244,14 @@ public:
{
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = false;
- skia::PlatformCanvas::drawTextOnPath(text, byteLength, path, matrix, paint);
+ SkCanvas::drawTextOnPath(text, byteLength, path, matrix, paint);
}
virtual void drawPicture(SkPicture& picture)
{
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = false;
- skia::PlatformCanvas::drawPicture(picture);
+ SkCanvas::drawPicture(picture);
}
virtual void drawVertices(VertexMode mode, int vertexCount,
@@ -253,14 +261,14 @@ public:
{
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = false;
- skia::PlatformCanvas::drawVertices(mode, vertexCount, vertices, texs, colors, xfermode, indices, indexCount, paint);
+ SkCanvas::drawVertices(mode, vertexCount, vertices, texs, colors, xfermode, indices, indexCount, paint);
}
virtual void drawData(const void* data, size_t size)
{
WRAPCANVAS_LOG_ENTRY("");
m_isSolidColor = false;
- skia::PlatformCanvas::drawData(data, size);
+ SkCanvas::drawData(data, size);
}
private:
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerAnimation.cpp b/Source/WebCore/platform/graphics/blackberry/LayerAnimation.cpp
new file mode 100644
index 000000000..f46afbafd
--- /dev/null
+++ b/Source/WebCore/platform/graphics/blackberry/LayerAnimation.cpp
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2011, 2012 Research In Motion Limited. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LayerAnimation.h"
+
+#include "IdentityTransformOperation.h"
+#include "LayerCompositingThread.h"
+#include "TransformationMatrix.h"
+#include "UnitBezier.h"
+
+#include <algorithm>
+
+namespace WebCore {
+
+using namespace std;
+
+// FIXME: Some functions below are copied from AnimationBase and KeyframeAnimation.
+// We need to refactor these code to increase code reuse.
+// https://bugs.webkit.org/show_bug.cgi?id=82293
+
+// The epsilon value we pass to UnitBezier::solve given that the animation is going to run over |dur| seconds. The longer the
+// animation, the more precision we need in the timing function result to avoid ugly discontinuities.
+static inline double solveEpsilon(double duration)
+{
+ return 1.0 / (200.0 * duration);
+}
+
+static inline double solveCubicBezierFunction(double p1x, double p1y, double p2x, double p2y, double t, double duration)
+{
+ // Convert from input time to parametric value in curve, then from
+ // that to output time.
+ UnitBezier bezier(p1x, p1y, p2x, p2y);
+ return bezier.solve(t, solveEpsilon(duration));
+}
+
+static inline double solveStepsFunction(int numSteps, bool stepAtStart, double t)
+{
+ if (stepAtStart)
+ return min(1.0, (floor(numSteps * t) + 1) / numSteps);
+ return floor(numSteps * t) / numSteps;
+}
+
+static const TimingFunction* timingFunctionForAnimationValue(const AnimationValue* animValue, const LayerAnimation* anim)
+{
+ if (animValue->timingFunction())
+ return animValue->timingFunction();
+ if (anim->timingFunction())
+ return anim->timingFunction();
+
+ return CubicBezierTimingFunction::defaultTimingFunction();
+}
+
+static double progress(double elapsedTime, const LayerAnimation* layerAnimation, double scale, double offset, const TimingFunction* tf)
+{
+ double dur = layerAnimation->duration();
+ if (layerAnimation->iterationCount() > 0)
+ dur *= layerAnimation->iterationCount();
+
+ if (!layerAnimation->duration())
+ return 1.0;
+ if (layerAnimation->iterationCount() > 0 && elapsedTime >= dur)
+ return (layerAnimation->iterationCount() % 2) ? 1.0 : 0.0;
+
+ // Compute the fractional time, taking into account direction.
+ // There is no need to worry about iterations, we assume that we would have
+ // short circuited above if we were done.
+ double fractionalTime = elapsedTime / layerAnimation->duration();
+ int integralTime = static_cast<int>(fractionalTime);
+ fractionalTime -= integralTime;
+
+ if ((layerAnimation->direction() == Animation::AnimationDirectionAlternate) && (integralTime & 1))
+ fractionalTime = 1 - fractionalTime;
+
+ if (scale != 1 || offset)
+ fractionalTime = (fractionalTime - offset) * scale;
+
+ if (!tf)
+ tf = layerAnimation->timingFunction();
+
+ if (tf->isCubicBezierTimingFunction()) {
+ const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(tf);
+ return solveCubicBezierFunction(ctf->x1(), ctf->y1(), ctf->x2(), ctf->y2(), fractionalTime, layerAnimation->duration());
+ }
+
+ if (tf->isStepsTimingFunction()) {
+ const StepsTimingFunction* stf = static_cast<const StepsTimingFunction*>(tf);
+ return solveStepsFunction(stf->numberOfSteps(), stf->stepAtStart(), fractionalTime);
+ }
+
+ return fractionalTime;
+}
+
+static void fetchIntervalEndpoints(double elapsedTime, const LayerAnimation* layerAnimation, const AnimationValue*& fromValue, const AnimationValue*& toValue, double& prog)
+{
+ // Find the first key.
+ if (layerAnimation->duration() && layerAnimation->iterationCount() != Animation::IterationCountInfinite)
+ elapsedTime = min(elapsedTime, layerAnimation->duration() * layerAnimation->iterationCount());
+
+ double fractionalTime = layerAnimation->duration() ? (elapsedTime / layerAnimation->duration()) : 1;
+
+ // FIXME: startTime can be before the current animation "frame" time. This is to sync with the frame time
+ // concept in AnimationTimeController. So we need to somehow sync the two. Until then, the possible
+ // error is small and will probably not be noticeable. Until we fix this, remove the assert.
+ // https://bugs.webkit.org/show_bug.cgi?id=52037
+ // ASSERT(fractionalTime >= 0);
+ if (fractionalTime < 0)
+ fractionalTime = 0;
+
+ // FIXME: share this code with AnimationBase::progress().
+ int iteration = static_cast<int>(fractionalTime);
+ if (layerAnimation->iterationCount() != Animation::IterationCountInfinite)
+ iteration = min(iteration, layerAnimation->iterationCount() - 1);
+
+ fractionalTime -= iteration;
+
+ bool reversing = (layerAnimation->direction() == Animation::AnimationDirectionAlternate) && (iteration & 1);
+ if (reversing)
+ fractionalTime = 1 - fractionalTime;
+
+ size_t numKeyframes = layerAnimation->valueCount();
+ if (!numKeyframes)
+ return;
+
+ ASSERT(!layerAnimation->valueAt(0)->keyTime());
+ ASSERT(layerAnimation->valueAt(layerAnimation->valueCount() - 1)->keyTime() == 1);
+
+ int prevIndex = -1;
+ int nextIndex = -1;
+
+ // FIXME: with a lot of keys, this linear search will be slow. We could binary search.
+ for (size_t i = 0; i < numKeyframes; ++i) {
+ const AnimationValue* currKeyframe = layerAnimation->valueAt(i);
+
+ if (fractionalTime < currKeyframe->keyTime()) {
+ nextIndex = i;
+ break;
+ }
+
+ prevIndex = i;
+ }
+
+ double scale = 1;
+ double offset = 0;
+
+ if (prevIndex == -1)
+ prevIndex = 0;
+
+ if (nextIndex == -1)
+ nextIndex = layerAnimation->valueCount() - 1;
+
+ const AnimationValue* prevKeyframe = layerAnimation->valueAt(prevIndex);
+ const AnimationValue* nextKeyframe = layerAnimation->valueAt(nextIndex);
+
+ fromValue = prevKeyframe;
+ toValue = nextKeyframe;
+
+ offset = prevKeyframe->keyTime();
+ scale = 1.0 / (nextKeyframe->keyTime() - prevKeyframe->keyTime());
+
+ const TimingFunction* timingFunction = timingFunctionForAnimationValue(prevKeyframe, layerAnimation);
+
+ prog = progress(elapsedTime, layerAnimation, scale, offset, timingFunction);
+}
+
+void LayerAnimation::apply(LayerCompositingThread* layer, double elapsedTime)
+{
+ const AnimationValue* from = 0;
+ const AnimationValue* to = 0;
+ double progress = 0.0;
+
+ fetchIntervalEndpoints(elapsedTime, this, from, to, progress);
+
+ switch (property()) {
+ case AnimatedPropertyWebkitTransform:
+ layer->setTransform(blendTransform(static_cast<const TransformAnimationValue*>(from)->value(), static_cast<const TransformAnimationValue*>(to)->value(), progress));
+ break;
+ case AnimatedPropertyOpacity:
+ layer->setOpacity(blendOpacity(static_cast<const FloatAnimationValue*>(from)->value(), static_cast<const FloatAnimationValue*>(to)->value(), progress));
+ break;
+ case AnimatedPropertyBackgroundColor:
+ case AnimatedPropertyWebkitFilter:
+ case AnimatedPropertyInvalid:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+}
+
+TransformationMatrix LayerAnimation::blendTransform(const TransformOperations* from, const TransformOperations* to, double progress) const
+{
+ TransformationMatrix t;
+
+ if (m_transformFunctionListValid) {
+ // A trick to avoid touching the refcount of shared TransformOperations on the wrong thread.
+ // Since TransforOperation is not ThreadSafeRefCounted, we are only allowed to touch the ref
+ // count of shared operations when the WebKit thread and compositing thread are in sync.
+ Vector<TransformOperation*> result;
+ Vector<RefPtr<TransformOperation> > owned;
+
+ unsigned fromSize = from->operations().size();
+ unsigned toSize = to->operations().size();
+ unsigned size = max(fromSize, toSize);
+ for (unsigned i = 0; i < size; i++) {
+ TransformOperation* fromOp = (i < fromSize) ? from->operations()[i].get() : 0;
+ TransformOperation* toOp = (i < toSize) ? to->operations()[i].get() : 0;
+ RefPtr<TransformOperation> blendedOp = toOp ? toOp->blend(fromOp, progress) : (fromOp ? fromOp->blend(0, progress, true) : PassRefPtr<TransformOperation>(0));
+ if (blendedOp) {
+ result.append(blendedOp.get());
+ owned.append(blendedOp);
+ } else {
+ RefPtr<TransformOperation> identityOp = IdentityTransformOperation::create();
+ owned.append(identityOp);
+ if (progress > 0.5)
+ result.append(toOp ? toOp : identityOp.get());
+ else
+ result.append(fromOp ? fromOp : identityOp.get());
+ }
+ }
+
+ IntSize sz = boxSize();
+ for (unsigned i = 0; i < result.size(); ++i)
+ result[i]->apply(t, sz);
+ } else {
+ // Convert the TransformOperations into matrices.
+ TransformationMatrix fromT;
+ from->apply(boxSize(), fromT);
+ to->apply(boxSize(), t);
+
+ t.blend(fromT, progress);
+ }
+
+ return t;
+}
+
+float LayerAnimation::blendOpacity(float from, float to, double progress) const
+{
+ float opacity = from + (to - from) * progress;
+
+ return max(0.0f, min(opacity, 1.0f));
+}
+
+void LayerAnimation::validateTransformLists()
+{
+ m_transformFunctionListValid = false;
+
+ if (m_values.size() < 2 || property() != AnimatedPropertyWebkitTransform)
+ return;
+
+ // Empty transforms match anything, so find the first non-empty entry as the reference.
+ size_t numKeyframes = m_values.size();
+ size_t firstNonEmptyTransformKeyframeIndex = numKeyframes;
+
+ for (size_t i = 0; i < numKeyframes; ++i) {
+ const TransformAnimationValue* currentKeyframe = static_cast<const TransformAnimationValue*>(m_values.at(i));
+ if (currentKeyframe->value()->size()) {
+ firstNonEmptyTransformKeyframeIndex = i;
+ break;
+ }
+ }
+
+ if (firstNonEmptyTransformKeyframeIndex == numKeyframes)
+ return;
+
+ const TransformOperations* firstVal = static_cast<const TransformAnimationValue*>(m_values.at(firstNonEmptyTransformKeyframeIndex))->value();
+
+ // See if the keyframes are valid.
+ for (size_t i = firstNonEmptyTransformKeyframeIndex + 1; i < numKeyframes; ++i) {
+ const TransformAnimationValue* currentKeyframe = static_cast<const TransformAnimationValue*>(m_values.at(i));
+ const TransformOperations* val = currentKeyframe->value();
+
+ // A null transform matches anything.
+ if (val->operations().isEmpty())
+ continue;
+
+ // If the sizes of the function lists don't match, the lists don't match.
+ if (firstVal->operations().size() != val->operations().size())
+ return;
+
+ // If the types of each function are not the same, the lists don't match.
+ for (size_t j = 0; j < firstVal->operations().size(); ++j) {
+ if (!firstVal->operations()[j]->isSameType(*val->operations()[j]))
+ return;
+ }
+ }
+
+ // Keyframes are valid.
+ m_transformFunctionListValid = true;
+}
+
+}
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerAnimation.h b/Source/WebCore/platform/graphics/blackberry/LayerAnimation.h
new file mode 100644
index 000000000..104477082
--- /dev/null
+++ b/Source/WebCore/platform/graphics/blackberry/LayerAnimation.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2011, 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU 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 LayerAnimation_h
+#define LayerAnimation_h
+
+#include "GraphicsLayer.h"
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+#define DEBUG_LAYER_ANIMATION 0
+
+namespace WebCore {
+
+class Animation;
+class LayerCompositingThread;
+class TransformationMatrix;
+
+// This class uses non-threadsafe refcounting in the WebCore::Animation and
+// WebCore::String members, so using threadsafe refcounting here would be a big
+// cover-up. Instead, you must be careful to use ref/deref this class only on
+// the WebKit thread, or when the WebKit and compositing threads are in sync.
+class LayerAnimation : public RefCounted<LayerAnimation> {
+public:
+ // WebKit thread only
+ // Because the refcounting done in constructor and destructor is not thread safe,
+ // the LayerAnimation must be created or destroyed on the WebKit thread, or when
+ // the WebKit and compositing threads are in sync.
+ // Also, the name property is using a String which has non-threadsafe refcounting.
+ // The setStartTime method is not threadsafe and must only be called on a newly
+ // created LayerAnimation before sending it off to the compositing thread.
+ static PassRefPtr<LayerAnimation> create(const KeyframeValueList& values, const IntSize& boxSize, const Animation* animation, const String& name, double timeOffset)
+ {
+ return adoptRef(new LayerAnimation(values, boxSize, animation, name, timeOffset));
+ }
+
+ PassRefPtr<LayerAnimation> clone(double timeOffset)
+ {
+ LayerAnimation* animation = new LayerAnimation(*this);
+ // The cloned animation should get a different timeOffset if it's paused.
+ animation->m_timeOffset = timeOffset;
+
+ return adoptRef(animation);
+ }
+
+ ~LayerAnimation()
+ {
+ }
+
+ const String& name() const { return m_name; }
+ void setStartTime(double time) { m_startTime = time; }
+
+ // These functions are thread safe (immutable state).
+ static int idFromAnimation(const Animation* animation) { return reinterpret_cast<int>(animation); }
+ bool isEqualToAnimation(const Animation* animation) const { return idFromAnimation(animation) == id(); }
+ int id() const { return m_id; }
+ AnimatedPropertyID property() const { return m_values.property(); }
+ IntSize boxSize() const { return m_boxSize; }
+ double timeOffset() const { return m_timeOffset; }
+ double startTime() const { return m_startTime; }
+ size_t valueCount() const { return m_values.size(); }
+
+ // NOTE: Don't try to ref a TimingFunction, that's not a threadsafe operation.
+ const TimingFunction* timingFunction() const { return m_timingFunction.get(); }
+ double duration() const { return m_duration; }
+ int iterationCount() const { return m_iterationCount; }
+ Animation::AnimationDirection direction() const { return m_direction; }
+
+ // NOTE: Don't try to clone() an AnimationValue, that's not a threadsafe operation since it mutates refcounts.
+ const AnimationValue* valueAt(size_t i) const { return m_values.at(i); }
+
+ TransformationMatrix blendTransform(const TransformOperations* from, const TransformOperations*, double progress) const;
+ float blendOpacity(float from, float to, double progress) const;
+ void apply(LayerCompositingThread*, double elapsedTime);
+
+private:
+ LayerAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* animation, const String& name, double timeOffset)
+ : m_id(reinterpret_cast<int>(animation))
+ , m_values(values)
+ , m_boxSize(boxSize)
+ , m_name(name)
+ , m_timeOffset(timeOffset)
+ , m_startTime(0)
+ , m_timingFunction(0)
+ , m_duration(animation->duration())
+ , m_iterationCount(animation->iterationCount())
+ , m_direction(animation->direction())
+ {
+ if (animation->isTimingFunctionSet())
+ m_timingFunction = animation->timingFunction();
+
+ validateTransformLists();
+ }
+
+ LayerAnimation(const LayerAnimation& other)
+ : RefCounted<LayerAnimation>()
+ , m_id(other.m_id)
+ , m_values(other.m_values)
+ , m_boxSize(other.m_boxSize)
+ , m_name(other.m_name)
+ , m_timeOffset(other.m_timeOffset)
+ , m_startTime(other.m_startTime)
+ , m_transformFunctionListValid(other.m_transformFunctionListValid)
+ , m_timingFunction(other.m_timingFunction)
+ , m_duration(other.m_duration)
+ , m_iterationCount(other.m_iterationCount)
+ , m_direction(other.m_direction)
+ {
+ }
+
+ void validateTransformLists();
+
+ int m_id;
+
+ // NOTE: Don't expose the KeyframeValueList directly, since its copy
+ // constructor mutates refcounts and thus is not thread safe.
+ KeyframeValueList m_values;
+ IntSize m_boxSize;
+ String m_name;
+ double m_timeOffset;
+ double m_startTime;
+ bool m_transformFunctionListValid;
+
+ RefPtr<TimingFunction> m_timingFunction;
+ double m_duration;
+ int m_iterationCount;
+ Animation::AnimationDirection m_direction;
+};
+
+}
+
+#endif // LayerAnimation_h
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp b/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp
new file mode 100644
index 000000000..adf8ecef0
--- /dev/null
+++ b/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp
@@ -0,0 +1,511 @@
+/*
+ * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerCompositingThread.h"
+
+#include "LayerMessage.h"
+#include "LayerRenderer.h"
+#include "LayerWebKitThread.h"
+#if ENABLE(VIDEO)
+#include "MediaPlayer.h"
+#include "MediaPlayerPrivateBlackBerry.h"
+#endif
+#include "PluginView.h"
+#include "TextureCacheCompositingThread.h"
+
+#include <BlackBerryPlatformGraphics.h>
+#include <BlackBerryPlatformLog.h>
+#include <wtf/Assertions.h>
+
+#define DEBUG_VIDEO_CLIPPING 0
+
+namespace WebCore {
+
+PassRefPtr<LayerCompositingThread> LayerCompositingThread::create(LayerType type, PassRefPtr<LayerTiler> tiler)
+{
+ return adoptRef(new LayerCompositingThread(type, tiler));
+}
+
+LayerCompositingThread::LayerCompositingThread(LayerType type, PassRefPtr<LayerTiler> tiler)
+ : LayerData(type)
+ , m_layerRenderer(0)
+ , m_superlayer(0)
+ , m_pluginBuffer(0)
+ , m_drawOpacity(0)
+ , m_visible(false)
+ , m_commitScheduled(false)
+ , m_tiler(tiler)
+{
+}
+
+LayerCompositingThread::~LayerCompositingThread()
+{
+ ASSERT(isCompositingThread());
+
+ m_tiler->layerCompositingThreadDestroyed();
+
+ ASSERT(!superlayer());
+
+ // Remove the superlayer reference from all sublayers.
+ while (m_sublayers.size())
+ m_sublayers[0]->removeFromSuperlayer();
+
+ // Delete all allocated textures
+ deleteTextures();
+
+ // We just deleted all our textures, no need for the
+ // layer renderer to track us anymore
+ if (m_layerRenderer)
+ m_layerRenderer->removeLayer(this);
+}
+
+void LayerCompositingThread::setLayerRenderer(LayerRenderer* renderer)
+{
+ // It's not expected that layers will ever switch renderers.
+ ASSERT(!renderer || !m_layerRenderer || renderer == m_layerRenderer);
+
+ m_layerRenderer = renderer;
+ if (m_layerRenderer)
+ m_layerRenderer->addLayer(this);
+}
+
+void LayerCompositingThread::deleteTextures()
+{
+ releaseTextureResources();
+
+ m_tiler->deleteTextures();
+}
+
+void LayerCompositingThread::setDrawTransform(const TransformationMatrix& matrix)
+{
+ m_drawTransform = matrix;
+
+ float bx = m_bounds.width() / 2.0;
+ float by = m_bounds.height() / 2.0;
+ m_transformedBounds.setP1(matrix.mapPoint(FloatPoint(-bx, -by)));
+ m_transformedBounds.setP2(matrix.mapPoint(FloatPoint(-bx, by)));
+ m_transformedBounds.setP3(matrix.mapPoint(FloatPoint(bx, by)));
+ m_transformedBounds.setP4(matrix.mapPoint(FloatPoint(bx, -by)));
+
+ m_drawRect = m_transformedBounds.boundingBox();
+}
+
+static FloatQuad getTransformedRect(const IntSize& bounds, const IntRect& rect, const TransformationMatrix& drawTransform)
+{
+ float x = -bounds.width() / 2.0 + rect.x();
+ float y = -bounds.height() / 2.0 + rect.y();
+ float w = rect.width();
+ float h = rect.height();
+ FloatQuad result;
+ result.setP1(drawTransform.mapPoint(FloatPoint(x, y)));
+ result.setP2(drawTransform.mapPoint(FloatPoint(x, y + h)));
+ result.setP3(drawTransform.mapPoint(FloatPoint(x + w, y + h)));
+ result.setP4(drawTransform.mapPoint(FloatPoint(x + w, y)));
+
+ return result;
+}
+
+
+FloatQuad LayerCompositingThread::getTransformedHolePunchRect() const
+{
+ // FIXME: the following line disables clipping a video in an iframe i.e. the fix associated with PR 99638.
+ // Some revised test case (e.g. video-iframe.html) show that the original fix works correctly when scrolling
+ // the contents of the frame, but fails to clip correctly if the page (main frame) is scrolled.
+ static bool enableVideoClipping = false;
+
+ if (!mediaPlayer() || !enableVideoClipping) {
+ // m_holePunchClipRect is valid only when there's a media player.
+ return getTransformedRect(m_bounds, m_holePunchRect, m_drawTransform);
+ }
+
+ // The hole punch rectangle may need to be clipped,
+ // e.g. if the <video> is on a layer that's included and clipped by an <iframe>.
+
+ // In order to clip we need to determine the current position of this layer, which
+ // is encoded in the m_drawTransform value, which was used to initialize m_drawRect.
+ IntRect drawRect = m_layerRenderer->toWebKitDocumentCoordinates(m_drawRect);
+
+ // Assert that in this case, where the hole punch rectangle equals the size of the layer,
+ // the drawRect has the same size as the hole punch.
+ // ASSERT(drawRect.size() == m_holePunchRect.size());
+ // Don't assert it programtically though because there may be off-by-one error due to rounding when there's zooming.
+
+ // The difference between drawRect and m_holePunchRect is that drawRect has an accurate position
+ // in WebKit document coordinates, whereas the m_holePunchRect location is (0,0) i.e. it's relative to this layer.
+
+ // Clip the drawRect.
+ // Both drawRect and m_holePunchClipRect already have correct locations, in WebKit document coordinates.
+ IntPoint location = drawRect.location();
+ drawRect.intersect(m_holePunchClipRect);
+
+ // Shift the clipped drawRect to have the same kind of located-at-zero position as the original holePunchRect.
+ drawRect.move(-location.x(), -location.y());
+
+#if DEBUG_VIDEO_CLIPPING
+ IntRect drawRectInWebKitDocumentCoordination = m_layerRenderer->toWebKitDocumentCoordinates(m_drawRect);
+ BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "LayerCompositingThread::getTransformedHolePunchRect() - drawRect=(x=%d,y=%d,width=%d,height=%d) clipRect=(x=%d,y=%d,width=%d,height=%d) clippedRect=(x=%d,y=%d,width=%d,height=%d).",
+ drawRectInWebKitDocumentCoordination.x(), drawRectInWebKitDocumentCoordination.y(), drawRectInWebKitDocumentCoordination.width(), drawRectInWebKitDocumentCoordination.height(),
+ m_holePunchClipRect.x(), m_holePunchClipRect.y(), m_holePunchClipRect.width(), m_holePunchClipRect.height(),
+ drawRect.x(), drawRect.y(), drawRect.width(), drawRect.height());
+#endif
+
+ return getTransformedRect(m_bounds, drawRect, m_drawTransform);
+}
+
+void LayerCompositingThread::drawTextures(int positionLocation, int texCoordLocation, const FloatRect& visibleRect)
+{
+ float texcoords[4 * 2] = { 0, 0, 0, 1, 1, 1, 1, 0 };
+
+ if (m_pluginView) {
+ if (m_isVisible) {
+ // The layer contains Flash, video, or other plugin contents.
+ m_pluginBuffer = m_pluginView->lockFrontBufferForRead();
+
+ if (!m_pluginBuffer)
+ return;
+
+ if (!BlackBerry::Platform::Graphics::lockAndBindBufferGLTexture(m_pluginBuffer, GL_TEXTURE_2D)) {
+ m_pluginView->unlockFrontBuffer();
+ return;
+ }
+
+ m_layerRenderer->addLayerToReleaseTextureResourcesList(this);
+
+ glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, &m_transformedBounds);
+ glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, texcoords);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
+ return;
+ }
+#if ENABLE(VIDEO)
+ if (m_mediaPlayer) {
+ if (m_isVisible) {
+ // We need to specify the media player location in contents coordinates. The 'visibleRect'
+ // specifies the content region covered by our viewport. So we transform from our
+ // normalized device coordinates [-1, 1] to the 'visibleRect'.
+ float vrw2 = visibleRect.width() / 2.0;
+ float vrh2 = visibleRect.height() / 2.0;
+ float x = m_transformedBounds.p1().x() * vrw2 + vrw2 + visibleRect.x();
+ float y = -m_transformedBounds.p1().y() * vrh2 + vrh2 + visibleRect.y();
+ m_mediaPlayer->paint(0, IntRect((int)(x + 0.5), (int)(y + 0.5), m_bounds.width(), m_bounds.height()));
+ MediaPlayerPrivate* mpp = static_cast<MediaPlayerPrivate*>(m_mediaPlayer->platformMedia().media.qnxMediaPlayer);
+ mpp->drawBufferingAnimation(m_drawTransform, positionLocation, texCoordLocation);
+ }
+ return;
+ }
+#endif
+#if ENABLE(WEBGL)
+ if (layerType() == LayerData::WebGLLayer) {
+ m_layerRenderer->addLayerToReleaseTextureResourcesList(this);
+ pthread_mutex_lock(m_frontBufferLock);
+ glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, &m_transformedBounds);
+ float canvasWidthRatio = 1.0f;
+ float canvasHeightRatio = 1.0f;
+ float upsideDown[4 * 2] = { 0, 1, 0, 1 - canvasHeightRatio, canvasWidthRatio, 1 - canvasHeightRatio, canvasWidthRatio, 1 };
+ // Flip the texture Y axis because OpenGL and Skia have different origins
+ glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, upsideDown);
+ glBindTexture(GL_TEXTURE_2D, m_texID);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ // FIXME: If the canvas/texture is larger than 2048x2048, then we'll die here
+ return;
+ }
+#endif
+ if (m_texID) {
+ m_layerRenderer->addLayerToReleaseTextureResourcesList(this);
+ pthread_mutex_lock(m_frontBufferLock);
+
+ glDisable(GL_SCISSOR_TEST);
+ glBindTexture(GL_TEXTURE_2D, m_texID);
+ glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, &m_transformedBounds);
+ float upsideDown[4 * 2] = { 0, 1, 0, 0, 1, 0, 1, 1 };
+ glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, upsideDown);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ return;
+ }
+
+ m_tiler->drawTextures(this, positionLocation, texCoordLocation);
+}
+
+void LayerCompositingThread::drawSurface(const TransformationMatrix& drawTransform, LayerCompositingThread* mask, int positionLocation, int texCoordLocation)
+{
+ if (m_layerRenderer->layerAlreadyOnSurface(this)) {
+ unsigned texID = layerRendererSurface()->texture()->textureId();
+ if (!texID) {
+ ASSERT_NOT_REACHED();
+ return;
+ }
+ textureCacheCompositingThread()->textureAccessed(layerRendererSurface()->texture());
+ glBindTexture(GL_TEXTURE_2D, texID);
+
+ if (mask) {
+ glActiveTexture(GL_TEXTURE1);
+ mask->bindContentsTexture();
+ glActiveTexture(GL_TEXTURE0);
+ }
+
+ FloatQuad surfaceQuad = getTransformedRect(m_bounds, IntRect(IntPoint::zero(), m_bounds), drawTransform);
+ glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, &surfaceQuad);
+
+ float texcoords[4 * 2] = { 0, 0, 0, 1, 1, 1, 1, 0 };
+ glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, texcoords);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
+}
+
+void LayerCompositingThread::drawMissingTextures(int positionLocation, int texCoordLocation, const FloatRect& visibleRect)
+{
+ if (m_pluginView || m_texID)
+ return;
+
+#if ENABLE(VIDEO)
+ if (m_mediaPlayer)
+ return;
+#endif
+
+ m_tiler->drawMissingTextures(this, positionLocation, texCoordLocation);
+}
+
+void LayerCompositingThread::releaseTextureResources()
+{
+ if (m_pluginView && m_pluginBuffer) {
+ BlackBerry::Platform::Graphics::releaseBufferGLTexture(m_pluginBuffer);
+ m_pluginBuffer = 0;
+ m_pluginView->unlockFrontBuffer();
+ }
+ if (m_texID && m_frontBufferLock)
+ pthread_mutex_unlock(m_frontBufferLock);
+}
+
+void LayerCompositingThread::setPluginView(PluginView* pluginView)
+{
+ if (!isCompositingThread()) {
+ dispatchSyncCompositingMessage(BlackBerry::Platform::createMethodCallMessage(
+ &LayerCompositingThread::setPluginView,
+ this,
+ pluginView));
+ return;
+ }
+
+ m_pluginView = pluginView;
+}
+
+#if ENABLE(VIDEO)
+void LayerCompositingThread::setMediaPlayer(MediaPlayer* mediaPlayer)
+{
+ if (!isCompositingThread()) {
+ dispatchSyncCompositingMessage(BlackBerry::Platform::createMethodCallMessage(
+ &LayerCompositingThread::setMediaPlayer,
+ this,
+ mediaPlayer));
+ return;
+ }
+
+ m_mediaPlayer = mediaPlayer;
+}
+#endif
+
+void LayerCompositingThread::clearAnimations()
+{
+ // Animations don't use thread safe refcounting, and must only be
+ // touched when the two threads are in sync.
+ if (!isCompositingThread()) {
+ dispatchSyncCompositingMessage(BlackBerry::Platform::createMethodCallMessage(
+ &LayerCompositingThread::clearAnimations,
+ this));
+ return;
+ }
+
+ m_runningAnimations.clear();
+ m_suspendedAnimations.clear();
+}
+
+void LayerCompositingThread::removeSublayer(LayerCompositingThread* sublayer)
+{
+ ASSERT(isCompositingThread());
+
+ int foundIndex = indexOfSublayer(sublayer);
+ if (foundIndex == -1)
+ return;
+
+ sublayer->setSuperlayer(0);
+ m_sublayers.remove(foundIndex);
+}
+
+int LayerCompositingThread::indexOfSublayer(const LayerCompositingThread* reference)
+{
+ for (size_t i = 0; i < m_sublayers.size(); i++) {
+ if (m_sublayers[i] == reference)
+ return i;
+ }
+ return -1;
+}
+
+const LayerCompositingThread* LayerCompositingThread::rootLayer() const
+{
+ const LayerCompositingThread* layer = this;
+ for (LayerCompositingThread* superlayer = layer->superlayer(); superlayer; layer = superlayer, superlayer = superlayer->superlayer()) { }
+ return layer;
+}
+
+void LayerCompositingThread::removeFromSuperlayer()
+{
+ if (m_superlayer)
+ m_superlayer->removeSublayer(this);
+}
+
+void LayerCompositingThread::setSublayers(const Vector<RefPtr<LayerCompositingThread> >& sublayers)
+{
+ if (sublayers == m_sublayers)
+ return;
+
+ while (m_sublayers.size()) {
+ RefPtr<LayerCompositingThread> layer = m_sublayers[0].get();
+ ASSERT(layer->superlayer());
+ layer->removeFromSuperlayer();
+ }
+
+ m_sublayers.clear();
+
+ size_t listSize = sublayers.size();
+ for (size_t i = 0; i < listSize; i++) {
+ RefPtr<LayerCompositingThread> sublayer = sublayers[i];
+ sublayer->removeFromSuperlayer();
+ sublayer->setSuperlayer(this);
+ m_sublayers.insert(i, sublayer);
+ }
+}
+
+void LayerCompositingThread::updateTextureContentsIfNeeded()
+{
+ if (m_texID || pluginView())
+ return;
+
+#if ENABLE(VIDEO)
+ if (mediaPlayer())
+ return;
+#endif
+
+ m_tiler->uploadTexturesIfNeeded();
+}
+
+void LayerCompositingThread::setVisible(bool visible)
+{
+ if (visible == m_visible)
+ return;
+
+ m_visible = visible;
+
+ if (m_texID || pluginView())
+ return;
+
+#if ENABLE(VIDEO)
+ if (mediaPlayer())
+ return;
+#endif
+
+ m_tiler->layerVisibilityChanged(visible);
+}
+
+void LayerCompositingThread::setNeedsCommit()
+{
+ if (m_layerRenderer)
+ m_layerRenderer->setNeedsCommit();
+}
+
+void LayerCompositingThread::scheduleCommit()
+{
+ if (!isWebKitThread()) {
+ if (m_commitScheduled)
+ return;
+
+ m_commitScheduled = true;
+
+ dispatchWebKitMessage(BlackBerry::Platform::createMethodCallMessage(&LayerCompositingThread::scheduleCommit, this));
+ return;
+ }
+
+ m_commitScheduled = false;
+
+ // FIXME: The only way to get at our LayerWebKitThread is to go through the tiler.
+ if (LayerWebKitThread* layer = m_tiler->layer())
+ layer->setNeedsCommit();
+}
+
+bool LayerCompositingThread::updateAnimations(double currentTime)
+{
+ // The commit mechanism always overwrites our state with state from the
+ // WebKit thread. This means we have to restore the last animated value for
+ // suspended animations.
+ for (size_t i = 0; i < m_suspendedAnimations.size(); ++i) {
+ LayerAnimation* animation = m_suspendedAnimations[i].get();
+ // From looking at the WebCore code, it appears that when the animation
+ // is paused, the timeOffset is modified so it will be an appropriate
+ // elapsedTime.
+ double elapsedTime = animation->timeOffset();
+ animation->apply(this, elapsedTime);
+ }
+
+ for (size_t i = 0; i < m_runningAnimations.size(); ++i) {
+ LayerAnimation* animation = m_runningAnimations[i].get();
+ double elapsedTime = (m_suspendTime ? m_suspendTime : currentTime) - animation->startTime() + animation->timeOffset();
+ animation->apply(this, elapsedTime);
+ }
+
+ return !m_runningAnimations.isEmpty();
+}
+
+bool LayerCompositingThread::hasVisibleHolePunchRect() const
+{
+ if (m_pluginView && !m_isVisible)
+ return false;
+
+#if ENABLE(VIDEO)
+ if (m_mediaPlayer && !m_isVisible)
+ return false;
+#endif
+
+ return hasHolePunchRect();
+}
+
+void LayerCompositingThread::createLayerRendererSurface()
+{
+ ASSERT(!m_layerRendererSurface);
+ m_layerRendererSurface = adoptPtr(new LayerRendererSurface(m_layerRenderer, this));
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.h b/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.h
new file mode 100644
index 000000000..b8470094f
--- /dev/null
+++ b/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.h
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved.
+ * 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef LayerCompositingThread_h
+#define LayerCompositingThread_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "FloatQuad.h"
+#include "LayerData.h"
+#include "LayerRendererSurface.h"
+#include "LayerTiler.h"
+
+#include <BlackBerryPlatformGuardedPointer.h>
+#include <GuardedPointerDeleter.h>
+
+namespace BlackBerry {
+namespace Platform {
+namespace Graphics {
+class Buffer;
+}
+}
+}
+
+namespace WebCore {
+
+class LayerRenderer;
+
+class LayerCompositingThread : public ThreadSafeRefCounted<LayerCompositingThread>, public LayerData, public BlackBerry::Platform::GuardedPointerBase {
+public:
+ static PassRefPtr<LayerCompositingThread> create(LayerType, PassRefPtr<LayerTiler>);
+
+ // Thread safe
+ void setPluginView(PluginView*);
+#if ENABLE(VIDEO)
+ void setMediaPlayer(MediaPlayer*);
+#endif
+ void clearAnimations();
+
+ // Not thread safe
+
+ // Returns true if we have an animation
+ bool updateAnimations(double currentTime);
+ void updateTextureContentsIfNeeded();
+ void bindContentsTexture()
+ {
+ if (m_tiler)
+ m_tiler->bindContentsTexture();
+ }
+
+ const LayerCompositingThread* rootLayer() const;
+ void setSublayers(const Vector<RefPtr<LayerCompositingThread> >&);
+ const Vector<RefPtr<LayerCompositingThread> >& getSublayers() const { return m_sublayers; }
+ void setSuperlayer(LayerCompositingThread* superlayer) { m_superlayer = superlayer; }
+ LayerCompositingThread* superlayer() const { return m_superlayer; }
+
+ // The layer renderer must be set if the layer has been rendered
+ void setLayerRenderer(LayerRenderer*);
+
+ void setDrawTransform(const TransformationMatrix&);
+ const TransformationMatrix& drawTransform() const { return m_drawTransform; }
+
+ void setDrawOpacity(float opacity) { m_drawOpacity = opacity; }
+ float drawOpacity() const { return m_drawOpacity; }
+
+ void createLayerRendererSurface();
+ LayerRendererSurface* layerRendererSurface() const { return m_layerRendererSurface.get(); }
+ void clearLayerRendererSurface() { m_layerRendererSurface.clear(); }
+
+ void setMaskLayer(LayerCompositingThread* maskLayer) { m_maskLayer = maskLayer; }
+ LayerCompositingThread* maskLayer() const { return m_maskLayer.get(); }
+
+ void setReplicaLayer(LayerCompositingThread* layer) { m_replicaLayer = layer; }
+ LayerCompositingThread* replicaLayer() const { return m_replicaLayer.get(); }
+
+ FloatRect getDrawRect() const { return m_drawRect; }
+ const FloatQuad& getTransformedBounds() const { return m_transformedBounds; }
+ FloatQuad getTransformedHolePunchRect() const;
+
+ void deleteTextures();
+
+ void drawTextures(int positionLocation, int texCoordLocation, const FloatRect& visibleRect);
+ bool hasMissingTextures() const { return m_tiler ? m_tiler->hasMissingTextures() : false; }
+ void drawMissingTextures(int positionLocation, int texCoordLocation, const FloatRect& visibleRect);
+ void drawSurface(const TransformationMatrix&, LayerCompositingThread* mask, int positionLocation, int texCoordLocation);
+ bool isDirty() const { return m_tiler ? m_tiler->hasDirtyTiles() : false; }
+
+ void releaseTextureResources();
+
+ // Layer visibility is determined by the LayerRenderer when drawing.
+ // So we don't have an accurate value for visibility until it's too late,
+ // but the attribute still is useful.
+ bool isVisible() const { return m_visible; }
+ void setVisible(bool);
+
+ // This will cause a commit of the whole layer tree on the WebKit thread,
+ // sometime after rendering is finished. Used when rendering results in a
+ // need for commit, for example when a dirty layer becomes visible.
+ void setNeedsCommit();
+
+ // Normally you would schedule a commit from the webkit thread, but
+ // this allows you to do it from the compositing thread.
+ void scheduleCommit();
+
+ // These two functions are used to update animated properties in LayerAnimation.
+ void setOpacity(float opacity) { m_opacity = opacity; }
+ void setTransform(const TransformationMatrix& matrix) { m_transform = matrix; }
+
+ bool hasRunningAnimations() const { return !m_runningAnimations.isEmpty(); }
+
+ bool hasVisibleHolePunchRect() const;
+
+protected:
+ virtual ~LayerCompositingThread();
+
+private:
+ LayerCompositingThread(LayerType, PassRefPtr<LayerTiler>);
+
+ void updateTileContents(const IntRect& tile);
+
+ void removeFromSuperlayer();
+
+ size_t numSublayers() const { return m_sublayers.size(); }
+
+ // Returns the index of the sublayer or -1 if not found.
+ int indexOfSublayer(const LayerCompositingThread*);
+
+ // This should only be called from removeFromSuperlayer.
+ void removeSublayer(LayerCompositingThread*);
+
+ LayerRenderer* m_layerRenderer;
+
+ typedef Vector<RefPtr<LayerCompositingThread> > LayerList;
+ LayerList m_sublayers;
+ LayerCompositingThread* m_superlayer;
+
+ // Vertex data for the bounds of this layer
+ FloatQuad m_transformedBounds;
+ // The bounding rectangle of the transformed layer
+ FloatRect m_drawRect;
+
+ OwnPtr<LayerRendererSurface> m_layerRendererSurface;
+
+ RefPtr<LayerCompositingThread> m_maskLayer;
+ RefPtr<LayerCompositingThread> m_replicaLayer;
+
+ BlackBerry::Platform::Graphics::Buffer* m_pluginBuffer;
+
+ // The global property values, after concatenation with parent values
+ TransformationMatrix m_drawTransform;
+ float m_drawOpacity;
+
+ bool m_visible;
+ bool m_commitScheduled;
+
+ RefPtr<LayerTiler> m_tiler;
+};
+
+} // namespace WebCore
+
+namespace WTF {
+
+// LayerCompositingThread objects must be destroyed on the compositing thread.
+// But it's possible for the last reference to be held by the WebKit thread.
+// So we create a custom specialization of ThreadSafeRefCounted which calls a
+// function that ensures the destructor is called on the correct thread, rather
+// than calling delete directly.
+template<>
+inline void ThreadSafeRefCounted<WebCore::LayerCompositingThread>::deref()
+{
+ if (derefBase()) {
+ // Delete on the compositing thread.
+ BlackBerry::Platform::GuardedPointerDeleter::deleteOnThread(
+ BlackBerry::Platform::userInterfaceThreadMessageClient(),
+ static_cast<WebCore::LayerCompositingThread*>(this));
+ }
+}
+
+} // namespace WTF
+
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerData.h b/Source/WebCore/platform/graphics/blackberry/LayerData.h
index 57746fa64..2a55bcfe5 100644
--- a/Source/WebCore/platform/graphics/blackberry/LayerData.h
+++ b/Source/WebCore/platform/graphics/blackberry/LayerData.h
@@ -54,7 +54,7 @@ class MediaPlayer;
class LayerData {
public:
- enum LayerType { Layer, TransformLayer, WebGLLayer };
+ enum LayerType { Layer, TransformLayer, WebGLLayer, CanvasLayer };
enum FilterType { Linear, Nearest, Trilinear, Lanczos };
enum LayerProgramShader { LayerProgramShaderRGBA = 0,
LayerProgramShaderBGRA,
@@ -74,14 +74,11 @@ public:
, m_mediaPlayer(0)
#endif
, m_texID(0)
- , m_texWidth(0)
- , m_texHeight(0)
- , m_canvas(0)
, m_frontBufferLock(0)
, m_suspendTime(0)
, m_doubleSided(true)
, m_masksToBounds(false)
- , m_opaque(true)
+ , m_isOpaque(false)
, m_preserves3D(false)
, m_needsDisplayOnBoundsChange(false)
, m_needsTexture(false)
@@ -116,7 +113,7 @@ public:
float opacity() const { return m_opacity; }
- bool opaque() const { return m_opaque; }
+ bool isOpaque() const { return m_isOpaque; }
FloatPoint position() const { return m_position; }
@@ -130,7 +127,7 @@ public:
unsigned getTextureID() const { return m_texID; }
void setTextureID(unsigned int value) { m_texID = value; }
- bool needsTexture() const { return m_layerType == WebGLLayer ? true : m_needsTexture; }
+ bool needsTexture() const { return m_layerType == WebGLLayer || m_layerType == CanvasLayer || m_needsTexture; }
LayerProgramShader layerProgramShader() const { return m_layerProgramShader; }
@@ -147,8 +144,6 @@ public:
MediaPlayer* mediaPlayer() const { return m_mediaPlayer; }
#endif
- HTMLCanvasElement* canvas() const { return m_canvas; }
-
void replicate(LayerData *to) const { *to = *this; }
LayerType layerType() const { return m_layerType; }
@@ -193,10 +188,6 @@ protected:
IntRect m_holePunchRect;
unsigned m_texID;
- unsigned m_texWidth;
- unsigned m_texHeight;
-
- HTMLCanvasElement* m_canvas;
pthread_mutex_t* m_frontBufferLock;
@@ -206,7 +197,7 @@ protected:
unsigned m_doubleSided : 1;
unsigned m_masksToBounds : 1;
- unsigned m_opaque : 1;
+ unsigned m_isOpaque : 1;
unsigned m_preserves3D : 1;
unsigned m_needsDisplayOnBoundsChange : 1;
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerRenderer.cpp b/Source/WebCore/platform/graphics/blackberry/LayerRenderer.cpp
index 4012e46f7..3235a92b8 100644
--- a/Source/WebCore/platform/graphics/blackberry/LayerRenderer.cpp
+++ b/Source/WebCore/platform/graphics/blackberry/LayerRenderer.cpp
@@ -166,14 +166,15 @@ LayerRenderer::LayerRenderer(GLES2Context* context)
LayerRenderer::~LayerRenderer()
{
- makeContextCurrent();
- if (m_fbo)
- glDeleteFramebuffers(1, &m_fbo);
- glDeleteProgram(m_colorProgramObject);
- glDeleteProgram(m_checkerProgramObject);
- for (int i = 0; i < LayerData::NumberOfLayerProgramShaders; ++i)
- glDeleteProgram(m_layerProgramObject[i]);
if (m_hardwareCompositing) {
+ makeContextCurrent();
+ if (m_fbo)
+ glDeleteFramebuffers(1, &m_fbo);
+ glDeleteProgram(m_colorProgramObject);
+ glDeleteProgram(m_checkerProgramObject);
+ for (int i = 0; i < LayerData::NumberOfLayerProgramShaders; ++i)
+ glDeleteProgram(m_layerProgramObject[i]);
+
// Free up all GL textures.
while (m_layers.begin() != m_layers.end()) {
LayerSet::iterator iter = m_layers.begin();
@@ -210,6 +211,8 @@ static inline bool compareLayerZ(const LayerCompositingThread* a, const LayerCom
void LayerRenderer::drawLayers(const FloatRect& visibleRect, const IntRect& layoutRect, const IntSize& contentsSize, const IntRect& dstRect)
{
ASSERT(m_hardwareCompositing);
+ if (!m_hardwareCompositing)
+ return;
bool wasEmpty = m_lastRenderingResults.isEmpty();
m_lastRenderingResults = LayerRenderingResults();
@@ -268,7 +271,13 @@ void LayerRenderer::drawLayers(const FloatRect& visibleRect, const IntRect& layo
return;
// Okay, we're going to do some drawing.
- makeContextCurrent();
+ if (!makeContextCurrent())
+ return;
+
+ // Get rid of any bound buffer that might affect the interpretation of our
+ // glVertexAttribPointer calls.
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(m_positionLocation);
glEnableVertexAttribArray(m_texCoordLocation);
@@ -309,10 +318,12 @@ void LayerRenderer::drawLayers(const FloatRect& visibleRect, const IntRect& layo
#endif
glClearStencil(0);
+ glClearColor(0, 0, 0, 0);
+ GLenum buffersToClear = GL_STENCIL_BUFFER_BIT;
if (m_clearSurfaceOnDrawLayers) {
- glClearColor(0, 0, 0, 0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ buffersToClear |= GL_COLOR_BUFFER_BIT;
}
+ glClear(buffersToClear);
// Don't render the root layer, the BlackBerry port uses the BackingStore to draw the
// root layer.
@@ -322,6 +333,11 @@ void LayerRenderer::drawLayers(const FloatRect& visibleRect, const IntRect& layo
compositeLayersRecursive(sublayers[i].get(), currentStencilValue, clipRect);
}
+ // We need to make sure that all texture resource usage is finished before
+ // unlocking the texture resources, so force a glFinish() in that case.
+ if (m_layersLockingTextureResources.size())
+ glFinish();
+
m_context->swapBuffers();
#if ENABLE_SCISSOR
@@ -329,6 +345,12 @@ void LayerRenderer::drawLayers(const FloatRect& visibleRect, const IntRect& layo
#endif
glDisable(GL_STENCIL_TEST);
+ // PR 147254, the EGL implementation crashes when the last bound texture
+ // was an EGLImage, and you try to bind another texture and the pixmap
+ // backing the EGLImage was deleted in between. Make this easier for the
+ // driver by unbinding early (when the pixmap is hopefully still around).
+ glBindTexture(GL_TEXTURE_2D, 0);
+
LayerSet::iterator iter = m_layersLockingTextureResources.begin();
for (; iter != m_layersLockingTextureResources.end(); ++iter)
(*iter)->releaseTextureResources();
@@ -974,7 +996,8 @@ bool LayerRenderer::initializeSharedGLObjects()
tmp.replace("GRID", String::format("%.3f", (float)checkerSize));
CString checkerFragmentShaderString = tmp.latin1();
- makeContextCurrent();
+ if (!makeContextCurrent())
+ return false;
m_layerProgramObject[LayerData::LayerProgramShaderRGBA] =
loadShaderProgram(vertexShaderString, fragmentShaderStringRGBA);
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerTile.cpp b/Source/WebCore/platform/graphics/blackberry/LayerTile.cpp
index f21ea948e..dec19d48b 100644
--- a/Source/WebCore/platform/graphics/blackberry/LayerTile.cpp
+++ b/Source/WebCore/platform/graphics/blackberry/LayerTile.cpp
@@ -47,9 +47,9 @@ void LayerTile::setContentsToColor(const Color& color)
setTexture(textureCacheCompositingThread()->textureForColor(color));
}
-void LayerTile::updateContents(const SkBitmap& contents, const IntRect& dirtyRect, const IntRect& tileRect)
+void LayerTile::updateContents(const SkBitmap& contents, const IntRect& dirtyRect, const IntRect& tileRect, bool isOpaque)
{
- setTexture(textureCacheCompositingThread()->updateContents(m_texture, contents, dirtyRect, tileRect));
+ setTexture(textureCacheCompositingThread()->updateContents(m_texture, contents, dirtyRect, tileRect, isOpaque));
}
void LayerTile::discardContents()
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerTile.h b/Source/WebCore/platform/graphics/blackberry/LayerTile.h
index 0eddcdaae..af4403dff 100644
--- a/Source/WebCore/platform/graphics/blackberry/LayerTile.h
+++ b/Source/WebCore/platform/graphics/blackberry/LayerTile.h
@@ -63,7 +63,7 @@ public:
void setContents(const SkBitmap& contents, const IntRect& tileRect, const TileIndex&, bool isOpaque);
void setContentsToColor(const Color&);
- void updateContents(const SkBitmap& contents, const IntRect& dirtyRect, const IntRect& tileRect);
+ void updateContents(const SkBitmap& contents, const IntRect& dirtyRect, const IntRect& tileRect, bool isOpaque);
void discardContents();
// The current texture is an accurate preview of this layer, but a more
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerTiler.cpp b/Source/WebCore/platform/graphics/blackberry/LayerTiler.cpp
index 3dad399d6..d517aaa7b 100644
--- a/Source/WebCore/platform/graphics/blackberry/LayerTiler.cpp
+++ b/Source/WebCore/platform/graphics/blackberry/LayerTiler.cpp
@@ -175,7 +175,7 @@ void LayerTiler::updateTextureContentsIfNeeded(double scale)
if (image->isBitmapImage())
isOpaque = !static_cast<BitmapImage*>(image)->currentFrameHasAlpha();
if (NativeImagePtr nativeImage = image->nativeImageForCurrentFrame()) {
- SkBitmap bitmap = SkBitmap(*nativeImage);
+ SkBitmap bitmap = SkBitmap(nativeImage->bitmap());
addTextureJob(TextureJob::setContents(bitmap, isOpaque));
}
} else {
@@ -202,7 +202,7 @@ void LayerTiler::updateTextureContentsIfNeeded(double scale)
if (isSolidColor)
addTextureJob(TextureJob::setContentsToColor(color, *it));
else
- addTextureJob(TextureJob::updateContents(bitmap, tileRect));
+ addTextureJob(TextureJob::updateContents(bitmap, tileRect, m_layer->isOpaque()));
}
finishedJobs.add(*it);
@@ -229,7 +229,7 @@ void LayerTiler::updateTextureContentsIfNeeded(double scale)
// No point in tiling an image layer, the image is already stored as an SkBitmap
NativeImagePtr nativeImage = m_layer->contents()->nativeImageForCurrentFrame();
if (nativeImage) {
- SkBitmap bitmap = SkBitmap(*nativeImage);
+ SkBitmap bitmap = SkBitmap(nativeImage->bitmap());
addTextureJob(TextureJob::setContents(bitmap, isOpaque));
}
return;
@@ -297,7 +297,7 @@ void LayerTiler::updateTextureContentsIfNeeded(double scale)
if (isSolidColor)
addTextureJob(TextureJob::setContentsToColor(color, index));
else
- addTextureJob(TextureJob::updateContents(bitmap, tileRect));
+ addTextureJob(TextureJob::updateContents(bitmap, tileRect, m_layer->isOpaque()));
}
}
}
@@ -428,18 +428,18 @@ void LayerTiler::processTextureJob(const TextureJob& job, TileJobsMap& tileJobsM
void LayerTiler::addTileJob(const TileIndex& index, const TextureJob& job, TileJobsMap& tileJobsMap)
{
// HashMap::add always returns a valid iterator even the key already exists.
- pair<TileJobsMap::iterator, bool> result = tileJobsMap.add(index, &job);
+ TileJobsMap::AddResult result = tileJobsMap.add(index, &job);
// Successfully added the new job.
- if (result.second)
+ if (result.isNewEntry)
return;
// In this case we leave the previous job.
- if (job.m_type == TextureJob::DirtyContents && result.first->second->m_type == TextureJob::DiscardContents)
+ if (job.m_type == TextureJob::DirtyContents && result.iterator->second->m_type == TextureJob::DiscardContents)
return;
// Override the previous job.
- result.first->second = &job;
+ result.iterator->second = &job;
}
void LayerTiler::performTileJob(LayerTile* tile, const TextureJob& job, const IntRect& tileRect)
@@ -452,7 +452,7 @@ void LayerTiler::performTileJob(LayerTile* tile, const TextureJob& job, const In
tile->setContents(job.m_contents, tileRect, indexOfTile(tileRect.location()), job.m_isOpaque);
return;
case TextureJob::UpdateContents:
- tile->updateContents(job.m_contents, job.m_dirtyRect, tileRect);
+ tile->updateContents(job.m_contents, job.m_dirtyRect, tileRect, job.m_isOpaque);
return;
case TextureJob::DiscardContents:
tile->discardContents();
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerTiler.h b/Source/WebCore/platform/graphics/blackberry/LayerTiler.h
index eda9e61d3..376662955 100644
--- a/Source/WebCore/platform/graphics/blackberry/LayerTiler.h
+++ b/Source/WebCore/platform/graphics/blackberry/LayerTiler.h
@@ -100,7 +100,7 @@ private:
ASSERT(type == DiscardContents || type == DirtyContents);
}
- TextureJob(Type type, const SkBitmap& contents, const IntRect& dirtyRect, bool isOpaque = false)
+ TextureJob(Type type, const SkBitmap& contents, const IntRect& dirtyRect, bool isOpaque)
: m_type(type)
, m_contents(contents)
, m_isOpaque(isOpaque)
@@ -121,7 +121,7 @@ private:
static TextureJob setContents(const SkBitmap& contents, bool isOpaque) { return TextureJob(SetContents, contents, IntRect(IntPoint::zero(), IntSize(contents.width(), contents.height())), isOpaque); }
static TextureJob setContentsToColor(const Color& color, const TileIndex& index) { return TextureJob(SetContentsToColor, color, index); }
- static TextureJob updateContents(const SkBitmap& contents, const IntRect& dirtyRect) { return TextureJob(UpdateContents, contents, dirtyRect); }
+ static TextureJob updateContents(const SkBitmap& contents, const IntRect& dirtyRect, bool isOpaque) { return TextureJob(UpdateContents, contents, dirtyRect, isOpaque); }
static TextureJob discardContents(const IntRect& dirtyRect) { return TextureJob(DiscardContents, dirtyRect); }
static TextureJob resizeContents(const IntSize& newSize) { return TextureJob(ResizeContents, newSize); }
static TextureJob dirtyContents(const IntRect& dirtyRect) { return TextureJob(DirtyContents, dirtyRect); }
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp b/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp
index 6cadf359d..6c5438267 100644
--- a/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp
+++ b/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp
@@ -108,7 +108,7 @@ SkBitmap LayerWebKitThread::paintContents(const IntRect& contentsRect, double sc
if (drawsContent()) { // Layer contents must be drawn into a canvas.
IntRect untransformedContentsRect = contentsRect;
- canvas = adoptPtr(new InstrumentedPlatformCanvas(contentsRect.width(), contentsRect.height(), false, 0));
+ canvas = adoptPtr(new InstrumentedPlatformCanvas(contentsRect.width(), contentsRect.height()));
PlatformContextSkia skiaContext(canvas.get());
GraphicsContext graphicsContext(&skiaContext);
@@ -191,7 +191,7 @@ void LayerWebKitThread::setDrawable(bool isDrawable)
m_isDrawable = isDrawable;
- setNeedsTexture(m_isDrawable && (drawsContent() || contents() || pluginView() || mediaPlayer() || canvas()));
+ setNeedsTexture(m_isDrawable && (drawsContent() || contents() || pluginView() || mediaPlayer() || m_texID));
setNeedsCommit();
}
@@ -306,8 +306,8 @@ void LayerWebKitThread::addSublayer(PassRefPtr<LayerWebKitThread> sublayer)
void LayerWebKitThread::insertSublayer(PassRefPtr<LayerWebKitThread> sublayer, size_t index)
{
- index = min(index, m_sublayers.size());
sublayer->removeFromSuperlayer();
+ index = min(index, m_sublayers.size());
sublayer->setSuperlayer(this);
m_sublayers.insert(index, sublayer);
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.h b/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.h
index f4c7441cd..848c184a6 100644
--- a/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.h
+++ b/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.h
@@ -95,7 +95,7 @@ public:
void setOpacity(float opacity) { m_opacity = opacity; setNeedsCommit(); }
- void setOpaque(bool opaque) { m_opaque = opaque; setNeedsCommit(); }
+ void setOpaque(bool isOpaque) { m_isOpaque = isOpaque; setNeedsCommit(); }
void setPosition(const FloatPoint& position) { m_position = position; setNeedsCommit(); }
diff --git a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp
index 1d8bd3af5..30de0d3f7 100644
--- a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp
+++ b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Research In Motion Limited. All rights reserved.
+ * Copyright (C) 2011, 2012 Research In Motion Limited. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -97,11 +97,6 @@ void MediaPlayerPrivate::setCertificatePath(const String& caPath)
MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
: m_webCorePlayer(player)
-#if USE(ACCELERATED_COMPOSITING)
- , m_platformPlayer(new MMRPlayer(this, true))
-#else
- , m_platformPlayer(new MMRPlayer(this, false))
-#endif
, m_networkState(MediaPlayer::Empty)
, m_readyState(MediaPlayer::HaveNothing)
, m_fullscreenWebPageClient(0)
@@ -112,7 +107,17 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
#endif
, m_userDrivenSeekTimer(this, &MediaPlayerPrivate::userDrivenSeekTimerFired)
, m_lastSeekTime(0)
+ , m_waitMetadataTimer(this, &MediaPlayerPrivate::waitMetadataTimerFired)
+ , m_waitMetadataPopDialogCounter(0)
{
+ void* tabId = 0;
+ if (frameView() && frameView()->hostWindow())
+ tabId = frameView()->hostWindow()->platformPageClient();
+#if USE(ACCELERATED_COMPOSITING)
+ m_platformPlayer = new MMRPlayer(this, tabId, true);
+#else
+ m_platformPlayer = new MMRPlayer(this, tabId, false);
+#endif
}
MediaPlayerPrivate::~MediaPlayerPrivate()
@@ -127,7 +132,7 @@ MediaPlayerPrivate::~MediaPlayerPrivate()
static_cast<VideoLayerWebKitThread*>(m_platformLayer.get())->setMediaPlayer(0);
#endif
- delete m_platformPlayer;
+ deleteGuardedObject(m_platformPlayer);
}
void MediaPlayerPrivate::load(const String& url)
@@ -601,6 +606,50 @@ void MediaPlayerPrivate::onPauseNotified()
element->pause();
}
+static const int popupDialogInterval = 10;
+static const double checkMetadataReadyInterval = 0.5;
+void MediaPlayerPrivate::onWaitMetadataNotified(bool hasFinished, int timeWaited)
+{
+ if (!hasFinished) {
+ if (!m_waitMetadataTimer.isActive()) {
+ // Make sure to popup dialog every 10 seconds after metadata start to load.
+ // This should be set only once at the first time when user press the play button.
+ m_waitMetadataPopDialogCounter = static_cast<int>(timeWaited / checkMetadataReadyInterval);
+ m_waitMetadataTimer.startOneShot(checkMetadataReadyInterval);
+ }
+ } else if (m_waitMetadataTimer.isActive()) {
+ m_waitMetadataTimer.stop();
+ m_waitMetadataPopDialogCounter = 0;
+ }
+}
+
+void MediaPlayerPrivate::waitMetadataTimerFired(Timer<MediaPlayerPrivate>*)
+{
+ if (m_platformPlayer->isMetadataReady()) {
+ m_platformPlayer->playWithMetadataReady();
+ m_waitMetadataPopDialogCounter = 0;
+ return;
+ }
+
+ static const int hitTimeToPopupDialog = static_cast<int>(popupDialogInterval / checkMetadataReadyInterval);
+ m_waitMetadataPopDialogCounter++;
+ if (m_waitMetadataPopDialogCounter < hitTimeToPopupDialog) {
+ m_waitMetadataTimer.startOneShot(checkMetadataReadyInterval);
+ return;
+ }
+ m_waitMetadataPopDialogCounter = 0;
+
+ int wait = showErrorDialog(MMRPlayer::MediaMetaDataTimeoutError);
+ if (!wait)
+ onPauseNotified();
+ else {
+ if (m_platformPlayer->isMetadataReady())
+ m_platformPlayer->playWithMetadataReady();
+ else
+ m_waitMetadataTimer.startOneShot(checkMetadataReadyInterval);
+ }
+}
+
#if USE(ACCELERATED_COMPOSITING)
void MediaPlayerPrivate::onBuffering(bool flag)
{
@@ -644,10 +693,8 @@ int MediaPlayerPrivate::showErrorDialog(MMRPlayer::Error type)
}
int rc = 0;
- HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient());
- Document* topdoc = element->document()->topDocument();
- if (topdoc->view() && topdoc->view()->hostWindow())
- rc = topdoc->view()->hostWindow()->platformPageClient()->showAlertDialog(atype);
+ if (frameView() && frameView()->hostWindow())
+ rc = frameView()->hostWindow()->platformPageClient()->showAlertDialog(atype);
return rc;
}
@@ -675,6 +722,13 @@ bool MediaPlayerPrivate::isFullscreen() const
return m_fullscreenWebPageClient;
}
+bool MediaPlayerPrivate::isTabVisible() const
+{
+ if (frameView() && frameView()->hostWindow())
+ return frameView()->hostWindow()->platformPageClient()->isVisible();
+ return true;
+}
+
#if USE(ACCELERATED_COMPOSITING)
static const double BufferingAnimationDelay = 1.0 / 24;
static char* s_bufferingImageData = 0;
@@ -709,15 +763,15 @@ static void loadBufferingImageData()
return;
loaded = true;
- nativeImage->lockPixels();
+ nativeImage->bitmap().lockPixels();
- int bufSize = nativeImage->width() * nativeImage->height() * 4;
- s_bufferingImageWidth = nativeImage->width();
- s_bufferingImageHeight = nativeImage->height();
+ int bufSize = nativeImage->bitmap().width() * nativeImage->bitmap().height() * 4;
+ s_bufferingImageWidth = nativeImage->bitmap().width();
+ s_bufferingImageHeight = nativeImage->bitmap().height();
s_bufferingImageData = static_cast<char*>(malloc(bufSize));
- memcpy(s_bufferingImageData, nativeImage->getPixels(), bufSize);
+ memcpy(s_bufferingImageData, nativeImage->bitmap().getPixels(), bufSize);
- nativeImage->unlockPixels();
+ nativeImage->bitmap().unlockPixels();
bufferingIcon->deref();
}
}
diff --git a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h
index 5b7f43299..186d77c30 100644
--- a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h
+++ b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h
@@ -126,11 +126,13 @@ public:
virtual void onSizeChanged();
virtual void onPlayNotified();
virtual void onPauseNotified();
+ virtual void onWaitMetadataNotified(bool hasFinished, int timeWaited);
#if USE(ACCELERATED_COMPOSITING)
virtual void onBuffering(bool);
#endif
virtual bool isFullscreen() const;
+ virtual bool isTabVisible() const;
virtual int showErrorDialog(BlackBerry::Platform::MMRPlayer::Error);
virtual BlackBerry::Platform::Graphics::Window* platformWindow();
@@ -161,6 +163,9 @@ private:
void userDrivenSeekTimerFired(Timer<MediaPlayerPrivate>*);
Timer<MediaPlayerPrivate> m_userDrivenSeekTimer;
float m_lastSeekTime;
+ void waitMetadataTimerFired(Timer<MediaPlayerPrivate>*);
+ Timer<MediaPlayerPrivate> m_waitMetadataTimer;
+ int m_waitMetadataPopDialogCounter;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/blackberry/Texture.h b/Source/WebCore/platform/graphics/blackberry/Texture.h
index 4e996d0d3..6dc4fdbcc 100644
--- a/Source/WebCore/platform/graphics/blackberry/Texture.h
+++ b/Source/WebCore/platform/graphics/blackberry/Texture.h
@@ -61,7 +61,7 @@ public:
void unprotect() { --m_protectionCount; }
bool protect(const IntSize&);
- void updateContents(const SkBitmap& contents, const IntRect& dirtyRect, const IntRect& tile, bool isOpaque = false);
+ void updateContents(const SkBitmap& contents, const IntRect& dirtyRect, const IntRect& tile, bool isOpaque);
void setContentsToColor(const Color&);
IntSize size() const { return m_size; }
diff --git a/Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.cpp b/Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.cpp
index fe0c3da49..f9f65408a 100644
--- a/Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.cpp
+++ b/Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.cpp
@@ -254,7 +254,7 @@ PassRefPtr<Texture> TextureCacheCompositingThread::textureForColor(const Color&
return texture.release();
}
-PassRefPtr<Texture> TextureCacheCompositingThread::updateContents(const RefPtr<Texture>& textureIn, const SkBitmap& contents, const IntRect& dirtyRect, const IntRect& tileRect)
+PassRefPtr<Texture> TextureCacheCompositingThread::updateContents(const RefPtr<Texture>& textureIn, const SkBitmap& contents, const IntRect& dirtyRect, const IntRect& tileRect, bool isOpaque)
{
RefPtr<Texture> texture(textureIn);
@@ -266,7 +266,7 @@ PassRefPtr<Texture> TextureCacheCompositingThread::updateContents(const RefPtr<T
// Protect newly created texture from being evicted.
TextureProtector protector(texture.get());
- texture->updateContents(contents, dirtyRect, tileRect);
+ texture->updateContents(contents, dirtyRect, tileRect, isOpaque);
return texture.release();
}
diff --git a/Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.h b/Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.h
index 82905b991..df7792fa2 100644
--- a/Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.h
+++ b/Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.h
@@ -54,7 +54,7 @@ public:
PassRefPtr<Texture> textureForColor(const Color&);
// Update contents of an existing texture, or create a new one if texture is 0.
- PassRefPtr<Texture> updateContents(const RefPtr<Texture>&, const SkBitmap& contents, const IntRect& dirtyRect, const IntRect& tileRect);
+ PassRefPtr<Texture> updateContents(const RefPtr<Texture>&, const SkBitmap& contents, const IntRect& dirtyRect, const IntRect& tileRect, bool isOpaque);
size_t memoryUsage() const { return m_memoryUsage; }
size_t memoryLimit() const { return m_memoryLimit; }
diff --git a/Source/WebCore/platform/graphics/blackberry/skia/ImageBufferData.h b/Source/WebCore/platform/graphics/blackberry/skia/ImageBufferDataSkia.h
index 409197ea6..d2246c09d 100644
--- a/Source/WebCore/platform/graphics/blackberry/skia/ImageBufferData.h
+++ b/Source/WebCore/platform/graphics/blackberry/skia/ImageBufferDataSkia.h
@@ -29,13 +29,14 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ImageBufferData_h
-#define ImageBufferData_h
+#ifndef ImageBufferDataSkia_h
+#define ImageBufferDataSkia_h
#include "BlackBerryPlatformGraphics.h"
#include "PlatformContextSkia.h"
-
-#include "skia/ext/platform_canvas.h"
+#if USE(ACCELERATED_COMPOSITING)
+#include "CanvasLayerWebKitThread.h"
+#endif
namespace WebCore {
@@ -45,9 +46,11 @@ public:
OwnPtr<SkCanvas> m_canvas;
PlatformContextSkia m_platformContext;
- BlackBerry::Platform::Graphics::Buffer* m_buffer;
+#if USE(ACCELERATED_COMPOSITING)
+ RefPtr<CanvasLayerWebKitThread> m_platformLayer;
+#endif
};
} // namespace WebCore
-#endif // ImageBufferData_h
+#endif // ImageBufferDataSkia_h
diff --git a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
index 47235367c..6d89f545d 100644
--- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
+++ b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
@@ -243,7 +243,7 @@ static bool animationHasStepsTimingFunction(const KeyframeValueList& valueList,
return false;
}
-#if ENABLE(CSS_FILTERS)
+#if ENABLE(CSS_FILTERS) || !ASSERT_DISABLED
static inline bool supportsAcceleratedFilterAnimations()
{
// <rdar://problem/10907251> - WebKit2 doesn't support CA animations of CI filters on Lion and below
@@ -279,6 +279,12 @@ GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client)
GraphicsLayerCA::~GraphicsLayerCA()
{
+ // Do cleanup while we can still safely call methods on the derived class.
+ willBeDestroyed();
+}
+
+void GraphicsLayerCA::willBeDestroyed()
+{
// We release our references to the PlatformCALayers 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.
@@ -294,6 +300,8 @@ GraphicsLayerCA::~GraphicsLayerCA()
m_structuralLayer->setOwner(0);
removeCloneLayers();
+
+ GraphicsLayer::willBeDestroyed();
}
void GraphicsLayerCA::setName(const String& name)
@@ -596,6 +604,13 @@ void GraphicsLayerCA::setOpacity(float opacity)
bool GraphicsLayerCA::setFilters(const FilterOperations& filterOperations)
{
bool canCompositeFilters = PlatformCALayer::filtersCanBeComposited(filterOperations);
+
+ if (m_filters == filterOperations)
+ return canCompositeFilters;
+
+ // Filters cause flattening, so we should never have filters on a layer with preserves3D().
+ ASSERT(!filterOperations.size() || !preserves3D());
+
if (canCompositeFilters) {
GraphicsLayer::setFilters(filterOperations);
noteLayerPropertyChanged(FiltersChanged);
@@ -669,6 +684,14 @@ bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const Int
if (animationHasStepsTimingFunction(valueList, anim))
return false;
+#if PLATFORM(WIN)
+ // CoreAnimation on Windows does not handle a reverse direction. Fall
+ // back to software animation in that case.
+ // https://bugs.webkit.org/show_bug.cgi?id=85121
+ if (!anim->directionIsForwards())
+ return false;
+#endif
+
bool createdAnimations = false;
if (valueList.property() == AnimatedPropertyWebkitTransform)
createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, animationName, timeOffset, boxSize);
@@ -873,9 +896,9 @@ void GraphicsLayerCA::syncCompositingStateForThisLayerOnly()
commitLayerChangesAfterSublayers();
}
-void GraphicsLayerCA::visibleRectChanged(const IntRect& visibleRect)
+TiledBacking* GraphicsLayerCA::tiledBacking()
{
- m_layer->visibleRectChanged(visibleRect);
+ return m_layer->tiledBacking();
}
void GraphicsLayerCA::recursiveCommitChanges(const TransformState& state, float pageScaleFactor, const FloatPoint& positionRelativeToBase, bool affectedByPageScale)
@@ -963,15 +986,23 @@ void GraphicsLayerCA::platformCALayerPaintContents(GraphicsContext& context, con
paintGraphicsLayerContents(context, clip);
}
-void GraphicsLayerCA::platformCALayerDidCreateTiles()
+void GraphicsLayerCA::platformCALayerDidCreateTiles(const Vector<FloatRect>& dirtyRects)
{
ASSERT(m_layer->layerType() == PlatformCALayer::LayerTypeTileCacheLayer);
+ for (size_t i = 0; i < dirtyRects.size(); ++i)
+ setNeedsDisplayInRect(dirtyRects[i]);
+
// Ensure that the layout is up to date before any individual tiles are painted by telling the client
// that it needs to sync its layer state, which will end up scheduling the layer flusher.
client()->notifySyncRequired(this);
}
+float GraphicsLayerCA::platformCALayerDeviceScaleFactor()
+{
+ return deviceScaleFactor();
+}
+
void GraphicsLayerCA::commitLayerChangesBeforeSublayers(float pageScaleFactor, const FloatPoint& positionRelativeToBase)
{
if (!m_uncommittedChanges)
@@ -1033,7 +1064,12 @@ void GraphicsLayerCA::commitLayerChangesBeforeSublayers(float pageScaleFactor, c
if (m_uncommittedChanges & AnimationChanged)
updateLayerAnimations();
-
+
+ // Updating the contents scale can cause parts of the layer to be invalidated,
+ // so make sure to update the contents scale before updating the dirty rects.
+ if (m_uncommittedChanges & ContentsScaleChanged)
+ updateContentsScale(pageScaleFactor, positionRelativeToBase);
+
if (m_uncommittedChanges & DirtyRectsChanged)
repaintLayerDirtyRects();
@@ -1048,9 +1084,6 @@ void GraphicsLayerCA::commitLayerChangesBeforeSublayers(float pageScaleFactor, c
if (m_uncommittedChanges & AcceleratesDrawingChanged)
updateAcceleratesDrawing();
-
- if (m_uncommittedChanges & ContentsScaleChanged)
- updateContentsScale(pageScaleFactor, positionRelativeToBase);
}
void GraphicsLayerCA::commitLayerChangesAfterSublayers()
@@ -1925,8 +1958,7 @@ bool GraphicsLayerCA::createFilterAnimationsFromKeyframes(const KeyframeValueLis
const FilterOperations* operations = static_cast<const FilterAnimationValue*>(valueList.at(listIndex))->value();
int numAnimations = operations->size();
- // FIXME: We can't currently hardware animate shadows. There is an open question about removing shadows from filters
- // entirely, in which case this issue is moot.
+ // FIXME: We can't currently hardware animate shadows.
for (int i = 0; i < numAnimations; ++i) {
if (operations->at(i)->getOperationType() == FilterOperation::DROP_SHADOW)
return false;
@@ -1964,7 +1996,7 @@ void GraphicsLayerCA::setupAnimation(PlatformCAAnimation* propertyAnim, const An
float repeatCount = anim->iterationCount();
if (repeatCount == Animation::IterationCountInfinite)
repeatCount = numeric_limits<float>::max();
- else if (anim->direction() == Animation::AnimationDirectionAlternate)
+ else if (anim->direction() == Animation::AnimationDirectionAlternate || anim->direction() == Animation::AnimationDirectionAlternateReverse)
repeatCount /= 2;
PlatformCAAnimation::FillModeType fillMode = PlatformCAAnimation::NoFillMode;
@@ -1985,7 +2017,7 @@ void GraphicsLayerCA::setupAnimation(PlatformCAAnimation* propertyAnim, const An
propertyAnim->setDuration(duration);
propertyAnim->setRepeatCount(repeatCount);
- propertyAnim->setAutoreverses(anim->direction());
+ propertyAnim->setAutoreverses(anim->direction() == Animation::AnimationDirectionAlternate || anim->direction() == Animation::AnimationDirectionAlternateReverse);
propertyAnim->setRemovedOnCompletion(false);
propertyAnim->setAdditive(additive);
propertyAnim->setFillMode(fillMode);
@@ -2001,12 +2033,17 @@ const TimingFunction* GraphicsLayerCA::timingFunctionForAnimationValue(const Ani
return CubicBezierTimingFunction::defaultTimingFunction();
}
-bool GraphicsLayerCA::setAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* basicAnim)
+bool GraphicsLayerCA::setAnimationEndpoints(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* basicAnim)
{
+ bool forwards = animation->directionIsForwards();
+
+ unsigned fromIndex = !forwards;
+ unsigned toIndex = forwards;
+
switch (valueList.property()) {
case AnimatedPropertyOpacity: {
- basicAnim->setFromValue(static_cast<const FloatAnimationValue*>(valueList.at(0))->value());
- basicAnim->setToValue(static_cast<const FloatAnimationValue*>(valueList.at(1))->value());
+ basicAnim->setFromValue(static_cast<const FloatAnimationValue*>(valueList.at(fromIndex))->value());
+ basicAnim->setToValue(static_cast<const FloatAnimationValue*>(valueList.at(toIndex))->value());
break;
}
default:
@@ -2015,23 +2052,26 @@ bool GraphicsLayerCA::setAnimationEndpoints(const KeyframeValueList& valueList,
}
// This codepath is used for 2-keyframe animations, so we still need to look in the start
- // for a timing function.
- const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), anim);
+ // for a timing function. Even in the reversing animation case, the first keyframe provides the timing function.
+ const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), animation);
if (timingFunction)
- basicAnim->setTimingFunction(timingFunction);
+ basicAnim->setTimingFunction(timingFunction, !forwards);
return true;
}
-bool GraphicsLayerCA::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* keyframeAnim)
+bool GraphicsLayerCA::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim)
{
Vector<float> keyTimes;
Vector<float> values;
Vector<const TimingFunction*> timingFunctions;
+
+ bool forwards = animation->directionIsForwards();
for (unsigned i = 0; i < valueList.size(); ++i) {
- const AnimationValue* curValue = valueList.at(i);
- keyTimes.append(curValue->keyTime());
+ unsigned index = forwards ? i : (valueList.size() - i - 1);
+ const AnimationValue* curValue = valueList.at(index);
+ keyTimes.append(forwards ? curValue->keyTime() : (1 - curValue->keyTime()));
switch (valueList.property()) {
case AnimatedPropertyOpacity: {
@@ -2044,24 +2084,28 @@ bool GraphicsLayerCA::setAnimationKeyframes(const KeyframeValueList& valueList,
break;
}
- timingFunctions.append(timingFunctionForAnimationValue(curValue, anim));
+ if (i < (valueList.size() - 1))
+ timingFunctions.append(timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), animation));
}
- // We toss the last tfArray value because it has to one shorter than the others.
- timingFunctions.removeLast();
-
keyframeAnim->setKeyTimes(keyTimes);
keyframeAnim->setValues(values);
- keyframeAnim->setTimingFunctions(timingFunctions);
+ keyframeAnim->setTimingFunctions(timingFunctions, !forwards);
return true;
}
-bool GraphicsLayerCA::setTransformAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* basicAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize)
+bool GraphicsLayerCA::setTransformAnimationEndpoints(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* basicAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize)
{
ASSERT(valueList.size() == 2);
- const TransformAnimationValue* startValue = static_cast<const TransformAnimationValue*>(valueList.at(0));
- const TransformAnimationValue* endValue = static_cast<const TransformAnimationValue*>(valueList.at(1));
+
+ bool forwards = animation->directionIsForwards();
+
+ unsigned fromIndex = !forwards;
+ unsigned toIndex = forwards;
+
+ const TransformAnimationValue* startValue = static_cast<const TransformAnimationValue*>(valueList.at(fromIndex));
+ const TransformAnimationValue* endValue = static_cast<const TransformAnimationValue*>(valueList.at(toIndex));
if (isMatrixAnimation) {
TransformationMatrix fromTransform, toTransform;
@@ -2103,9 +2147,9 @@ bool GraphicsLayerCA::setTransformAnimationEndpoints(const KeyframeValueList& va
}
// This codepath is used for 2-keyframe animations, so we still need to look in the start
- // for a timing function.
- const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), anim);
- basicAnim->setTimingFunction(timingFunction);
+ // for a timing function. Even in the reversing animation case, the first keyframe provides the timing function.
+ const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), animation);
+ basicAnim->setTimingFunction(timingFunction, !forwards);
PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType);
if (valueFunction != PlatformCAAnimation::NoValueFunction)
@@ -2122,9 +2166,12 @@ bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& va
Vector<TransformationMatrix> transformationMatrixValues;
Vector<const TimingFunction*> timingFunctions;
+ bool forwards = animation->directionIsForwards();
+
for (unsigned i = 0; i < valueList.size(); ++i) {
- const TransformAnimationValue* curValue = static_cast<const TransformAnimationValue*>(valueList.at(i));
- keyTimes.append(curValue->keyTime());
+ unsigned index = forwards ? i : (valueList.size() - i - 1);
+ const TransformAnimationValue* curValue = static_cast<const TransformAnimationValue*>(valueList.at(index));
+ keyTimes.append(forwards ? curValue->keyTime() : (1 - curValue->keyTime()));
if (isMatrixAnimation) {
TransformationMatrix transform;
@@ -2152,13 +2199,10 @@ bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& va
}
}
- const TimingFunction* timingFunction = timingFunctionForAnimationValue(curValue, animation);
- timingFunctions.append(timingFunction);
+ if (i < (valueList.size() - 1))
+ timingFunctions.append(timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), animation));
}
- // We toss the last tfArray value because it has to one shorter than the others.
- timingFunctions.removeLast();
-
keyframeAnim->setKeyTimes(keyTimes);
if (isTransformTypeNumber(transformOpType))
@@ -2168,7 +2212,7 @@ bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& va
else
keyframeAnim->setValues(transformationMatrixValues);
- keyframeAnim->setTimingFunctions(timingFunctions);
+ keyframeAnim->setTimingFunctions(timingFunctions, !forwards);
PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType);
if (valueFunction != PlatformCAAnimation::NoValueFunction)
@@ -2181,34 +2225,39 @@ bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& va
bool GraphicsLayerCA::setFilterAnimationEndpoints(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* basicAnim, int functionIndex, int internalFilterPropertyIndex)
{
ASSERT(valueList.size() == 2);
-
- const FilterAnimationValue* fromValue = static_cast<const FilterAnimationValue*>(valueList.at(0));
- const FilterAnimationValue* toValue = static_cast<const FilterAnimationValue*>(valueList.at(1));
-
+
+ bool forwards = animation->directionIsForwards();
+
+ unsigned fromIndex = !forwards;
+ unsigned toIndex = forwards;
+
+ const FilterAnimationValue* fromValue = static_cast<const FilterAnimationValue*>(valueList.at(fromIndex));
+ const FilterAnimationValue* toValue = static_cast<const FilterAnimationValue*>(valueList.at(toIndex));
+
const FilterOperation* fromOperation = fromValue->value()->at(functionIndex);
const FilterOperation* toOperation = toValue->value()->at(functionIndex);
-
+
RefPtr<DefaultFilterOperation> defaultFromOperation;
RefPtr<DefaultFilterOperation> defaultToOperation;
-
+
ASSERT(fromOperation || toOperation);
-
+
if (!fromOperation) {
defaultFromOperation = DefaultFilterOperation::create(toOperation->getOperationType());
fromOperation = defaultFromOperation.get();
}
-
+
if (!toOperation) {
defaultToOperation = DefaultFilterOperation::create(fromOperation->getOperationType());
toOperation = defaultToOperation.get();
}
-
+
basicAnim->setFromValue(fromOperation, internalFilterPropertyIndex);
basicAnim->setToValue(toOperation, internalFilterPropertyIndex);
-
- // This codepath is used for 2-keyframe animations, so we still need to look in the start for a timing function.
- const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), animation);
- basicAnim->setTimingFunction(timingFunction);
+
+ // This codepath is used for 2-keyframe animations, so we still need to look in the start
+ // for a timing function. Even in the reversing animation case, the first keyframe provides the timing function.
+ basicAnim->setTimingFunction(timingFunctionForAnimationValue(valueList.at(0), animation), !forwards);
return true;
}
@@ -2220,9 +2269,12 @@ bool GraphicsLayerCA::setFilterAnimationKeyframes(const KeyframeValueList& value
Vector<const TimingFunction*> timingFunctions;
RefPtr<DefaultFilterOperation> defaultOperation;
+ bool forwards = animation->directionIsForwards();
+
for (unsigned i = 0; i < valueList.size(); ++i) {
- const FilterAnimationValue* curValue = static_cast<const FilterAnimationValue*>(valueList.at(i));
- keyTimes.append(curValue->keyTime());
+ unsigned index = forwards ? i : (valueList.size() - i - 1);
+ const FilterAnimationValue* curValue = static_cast<const FilterAnimationValue*>(valueList.at(index));
+ keyTimes.append(forwards ? curValue->keyTime() : (1 - curValue->keyTime()));
if (curValue->value()->operations().size() > static_cast<size_t>(functionIndex))
values.append(curValue->value()->operations()[functionIndex]);
@@ -2232,16 +2284,13 @@ bool GraphicsLayerCA::setFilterAnimationKeyframes(const KeyframeValueList& value
values.append(defaultOperation);
}
- const TimingFunction* timingFunction = timingFunctionForAnimationValue(curValue, animation);
- timingFunctions.append(timingFunction);
+ if (i < (valueList.size() - 1))
+ timingFunctions.append(timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), animation));
}
- // We toss the last timing function because it has to be one shorter than the others.
- timingFunctions.removeLast();
-
keyframeAnim->setKeyTimes(keyTimes);
keyframeAnim->setValues(values, internalFilterPropertyIndex);
- keyframeAnim->setTimingFunctions(timingFunctions);
+ keyframeAnim->setTimingFunctions(timingFunctions, !forwards);
return true;
}
@@ -2480,16 +2529,16 @@ PassRefPtr<PlatformCALayer> GraphicsLayerCA::findOrMakeClone(CloneID cloneID, Pl
// Add with a dummy value to get an iterator for the insertion position, and a boolean that tells
// us whether there's an item there. This technique avoids two hash lookups.
RefPtr<PlatformCALayer> dummy;
- pair<LayerMap::iterator, bool> addResult = clones->add(cloneID, dummy);
- if (!addResult.second) {
+ LayerMap::AddResult addResult = clones->add(cloneID, dummy);
+ if (!addResult.isNewEntry) {
// Value was not added, so it exists already.
- resultLayer = addResult.first->second.get();
+ resultLayer = addResult.iterator->second.get();
} else {
resultLayer = cloneLayer(sourceLayer, cloneLevel);
#ifndef NDEBUG
resultLayer->setName(String::format("Clone %d of layer %p", cloneID[0U], sourceLayer->platformLayer()));
#endif
- addResult.first->second = resultLayer;
+ addResult.iterator->second = resultLayer;
}
return resultLayer;
@@ -2785,6 +2834,15 @@ void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags)
m_uncommittedChanges |= flags;
}
+double GraphicsLayerCA::backingStoreArea() const
+{
+ if (!drawsContent())
+ return 0;
+
+ // contentsLayer is given to us, so we don't really know anything about its contents.
+ return static_cast<double>(size().width()) * size().height() * m_layer->contentsScale();
+}
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h
index cce1ffd06..4d5f01b9d 100644
--- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h
+++ b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h
@@ -103,7 +103,6 @@ public:
virtual void setNeedsDisplay();
virtual void setNeedsDisplayInRect(const FloatRect&);
- virtual bool needsDisplay() const OVERRIDE { return !m_dirtyRects.isEmpty(); }
virtual void setContentsNeedsDisplay();
virtual void setContentsRect(const IntRect&);
@@ -135,7 +134,7 @@ public:
virtual void syncCompositingState(const FloatRect&);
virtual void syncCompositingStateForThisLayerOnly();
- virtual void visibleRectChanged(const IntRect&) OVERRIDE;
+ virtual TiledBacking* tiledBacking() OVERRIDE;
bool allowTiledLayer() const { return m_allowTiledLayer; }
virtual void setAllowTiledLayer(bool b);
@@ -144,6 +143,8 @@ protected:
virtual void setOpacityInternal(float);
private:
+ virtual void willBeDestroyed();
+
// PlatformCALayerClient overrides
virtual void platformCALayerLayoutSublayersOfLayer(PlatformCALayer*) { }
virtual bool platformCALayerRespondsToLayoutChanges() const { return false; }
@@ -158,7 +159,10 @@ private:
virtual bool platformCALayerContentsOpaque() const { return contentsOpaque(); }
virtual bool platformCALayerDrawsContent() const { return drawsContent(); }
virtual void platformCALayerLayerDidDisplay(PlatformLayer* layer) { return layerDidDisplay(layer); }
- virtual void platformCALayerDidCreateTiles() OVERRIDE;
+ virtual void platformCALayerDidCreateTiles(const Vector<FloatRect>& dirtyRects) OVERRIDE;
+ virtual float platformCALayerDeviceScaleFactor() OVERRIDE;
+
+ virtual double backingStoreArea() const;
void updateOpacityOnLayer();
diff --git a/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h b/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h
index 280d763b3..6c1263114 100644
--- a/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h
+++ b/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h
@@ -93,7 +93,7 @@ public:
FillModeType fillMode() const;
void setFillMode(FillModeType);
- void setTimingFunction(const TimingFunction*);
+ void setTimingFunction(const TimingFunction*, bool reverse = false);
void copyTimingFunctionFrom(const PlatformCAAnimation*);
bool isRemovedOnCompletion() const;
@@ -137,7 +137,7 @@ public:
void setKeyTimes(const Vector<float>&);
void copyKeyTimesFrom(const PlatformCAAnimation*);
- void setTimingFunctions(const Vector<const TimingFunction*>&);
+ void setTimingFunctions(const Vector<const TimingFunction*>&, bool reverse = false);
void copyTimingFunctionsFrom(const PlatformCAAnimation*);
#if ENABLE(CSS_FILTERS)
diff --git a/Source/WebCore/platform/graphics/ca/PlatformCALayer.h b/Source/WebCore/platform/graphics/ca/PlatformCALayer.h
index 3aff7c261..f7f2d52b3 100644
--- a/Source/WebCore/platform/graphics/ca/PlatformCALayer.h
+++ b/Source/WebCore/platform/graphics/ca/PlatformCALayer.h
@@ -203,7 +203,7 @@ public:
float contentsScale() const;
void setContentsScale(float);
- void visibleRectChanged(const IntRect&);
+ TiledBacking* tiledBacking();
#if PLATFORM(WIN)
HashMap<String, RefPtr<PlatformCAAnimation> >& animations() { return m_animations; }
diff --git a/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h b/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h
index be8e459d8..938976c52 100644
--- a/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h
+++ b/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h
@@ -59,7 +59,8 @@ public:
virtual bool platformCALayerDrawsContent() const = 0;
virtual void platformCALayerLayerDidDisplay(PlatformLayer*) = 0;
- virtual void platformCALayerDidCreateTiles() = 0;
+ virtual void platformCALayerDidCreateTiles(const Vector<FloatRect>& dirtyRects) = 0;
+ virtual float platformCALayerDeviceScaleFactor() = 0;
protected:
virtual ~PlatformCALayerClient() {}
diff --git a/Source/WebCore/platform/graphics/ca/mac/LayerFlushSchedulerMac.cpp b/Source/WebCore/platform/graphics/ca/mac/LayerFlushSchedulerMac.cpp
index 73df4b2c6..01805e701 100644
--- a/Source/WebCore/platform/graphics/ca/mac/LayerFlushSchedulerMac.cpp
+++ b/Source/WebCore/platform/graphics/ca/mac/LayerFlushSchedulerMac.cpp
@@ -29,6 +29,8 @@
#include "LayerFlushScheduler.h"
+#include "AutodrainedPool.h"
+
namespace WebCore {
static const CFIndex CoreAnimationRunLoopOrder = 2000000;
@@ -56,6 +58,7 @@ void LayerFlushScheduler::runLoopObserverCallback()
ASSERT(m_runLoopObserver);
ASSERT(!m_isSuspended);
+ AutodrainedPool pool;
if (m_client->flushLayers())
invalidate();
}
diff --git a/Source/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm b/Source/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm
index 11be28883..cd856692b 100644
--- a/Source/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm
+++ b/Source/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm
@@ -30,6 +30,7 @@
#import "PlatformCAAnimation.h"
#import "FloatConversion.h"
+#import "LengthFunctions.h"
#import "PlatformString.h"
#import "TimingFunction.h"
#import <QuartzCore/QuartzCore.h>
@@ -133,13 +134,19 @@ static PlatformCAAnimation::ValueFunctionType fromCAValueFunctionType(NSString*
}
#endif
-static CAMediaTimingFunction* toCAMediaTimingFunction(const TimingFunction* timingFunction)
+static CAMediaTimingFunction* toCAMediaTimingFunction(const TimingFunction* timingFunction, bool reverse)
{
ASSERT(timingFunction);
if (timingFunction->isCubicBezierTimingFunction()) {
const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(timingFunction);
- return [CAMediaTimingFunction functionWithControlPoints:static_cast<float>(ctf->x1()) :static_cast<float>(ctf->y1())
- :static_cast<float>(ctf->x2()) :static_cast<float>(ctf->y2())];
+ float x1 = static_cast<float>(ctf->x1());
+ float y1 = static_cast<float>(ctf->y1());
+ float x2 = static_cast<float>(ctf->x2());
+ float y2 = static_cast<float>(ctf->y2());
+ return [CAMediaTimingFunction functionWithControlPoints:(reverse ? 1 - x2 : x1)
+ :(reverse ? 1 - y2 : y1)
+ :(reverse ? 1 - x1 : x2)
+ :(reverse ? 1 - y1 : y2)];
}
return [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
@@ -305,9 +312,9 @@ void PlatformCAAnimation::setFillMode(FillModeType value)
[m_animation.get() setFillMode:toCAFillModeType(value)];
}
-void PlatformCAAnimation::setTimingFunction(const TimingFunction* value)
+void PlatformCAAnimation::setTimingFunction(const TimingFunction* value, bool reverse)
{
- [m_animation.get() setTimingFunction:toCAMediaTimingFunction(value)];
+ [m_animation.get() setTimingFunction:toCAMediaTimingFunction(value, reverse)];
}
void PlatformCAAnimation::copyTimingFunctionFrom(const PlatformCAAnimation* value)
@@ -502,7 +509,7 @@ static RetainPtr<id> filterValueForOperation(const FilterOperation* operation, i
if (!operation->isDefault()) {
const BlurFilterOperation* op = static_cast<const BlurFilterOperation*>(operation);
- amount = op->stdDeviation().calcFloatValue(0);
+ amount = floatValueForLength(op->stdDeviation(), 0);
}
value.adoptNS([[NSNumber numberWithDouble:amount] retain]);
@@ -693,12 +700,12 @@ void PlatformCAAnimation::copyKeyTimesFrom(const PlatformCAAnimation* value)
[static_cast<CAKeyframeAnimation*>(m_animation.get()) setKeyTimes:[other keyTimes]];
}
-void PlatformCAAnimation::setTimingFunctions(const Vector<const TimingFunction*>& value)
+void PlatformCAAnimation::setTimingFunctions(const Vector<const TimingFunction*>& value, bool reverse)
{
NSMutableArray* array = [NSMutableArray array];
for (size_t i = 0; i < value.size(); ++i)
- [array addObject:toCAMediaTimingFunction(value[i])];
+ [array addObject:toCAMediaTimingFunction(value[i], reverse)];
[static_cast<CAKeyframeAnimation*>(m_animation.get()) setTimingFunctions:array];
}
diff --git a/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm b/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm
index e124a1647..4c3623a63 100644
--- a/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm
+++ b/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm
@@ -34,6 +34,7 @@
#import "FloatConversion.h"
#import "GraphicsContext.h"
#import "GraphicsLayerCA.h"
+#import "LengthFunctions.h"
#import "WebLayer.h"
#import "WebTiledLayer.h"
#import "WebTileCacheLayer.h"
@@ -238,7 +239,10 @@ PlatformCALayer::~PlatformCALayer()
setOwner(0);
// Remove the owner pointer from the delegate in case there is a pending animationStarted event.
- [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:nil];
+ [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:nil];
+
+ if (m_layerType == LayerTypeTileCacheLayer)
+ [static_cast<WebTileCacheLayer *>(m_layer.get()) invalidate];
}
PlatformCALayer* PlatformCALayer::platformCALayer(void* platformLayer)
@@ -708,7 +712,13 @@ void PlatformCALayer::setOpacity(float value)
void PlatformCALayer::setFilters(const FilterOperations& filters)
{
if (!filters.size()) {
- [m_layer.get() setFilters:0];
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setFilters:nil];
+ [m_layer.get() setShadowOffset:CGSizeZero];
+ [m_layer.get() setShadowColor:nil];
+ [m_layer.get() setShadowRadius:0];
+ [m_layer.get() setShadowOpacity:0];
+ END_BLOCK_OBJC_EXCEPTIONS
return;
}
@@ -823,7 +833,7 @@ void PlatformCALayer::setFilters(const FilterOperations& filters)
const BlurFilterOperation* op = static_cast<const BlurFilterOperation*>(filterOperation);
CIFilter* caFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
[caFilter setDefaults];
- [caFilter setValue:[NSNumber numberWithFloat:op->stdDeviation().calcFloatValue(0)] forKey:@"inputRadius"];
+ [caFilter setValue:[NSNumber numberWithFloat:floatValueForLength(op->stdDeviation(), 0)] forKey:@"inputRadius"];
[caFilter setName:filterName];
[array.get() addObject:caFilter];
break;
@@ -956,13 +966,13 @@ void PlatformCALayer::setContentsScale(float value)
#endif
}
-void PlatformCALayer::visibleRectChanged(const IntRect& visibleRect)
+TiledBacking* PlatformCALayer::tiledBacking()
{
if (m_layerType != LayerTypeTileCacheLayer)
- return;
+ return 0;
WebTileCacheLayer *tileCacheLayer = static_cast<WebTileCacheLayer *>(m_layer.get());
- [tileCacheLayer visibleRectChanged:visibleRect];
+ return [tileCacheLayer tiledBacking];
}
#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
diff --git a/Source/WebCore/platform/graphics/ca/mac/TileCache.h b/Source/WebCore/platform/graphics/ca/mac/TileCache.h
index 714d3c90b..61f30500b 100644
--- a/Source/WebCore/platform/graphics/ca/mac/TileCache.h
+++ b/Source/WebCore/platform/graphics/ca/mac/TileCache.h
@@ -28,6 +28,7 @@
#include "IntPointHash.h"
#include "IntRect.h"
+#include "TiledBacking.h"
#include "Timer.h"
#include <wtf/HashMap.h>
#include <wtf/Noncopyable.h>
@@ -44,7 +45,7 @@ class FloatRect;
class IntPoint;
class IntRect;
-class TileCache {
+class TileCache : public TiledBacking {
WTF_MAKE_NONCOPYABLE(TileCache);
public:
@@ -55,7 +56,7 @@ public:
void setNeedsDisplay();
void setNeedsDisplayInRect(const IntRect&);
- void drawLayer(WebTileLayer*, CGContextRef);
+ void drawLayer(WebTileLayer *, CGContextRef);
void setScale(CGFloat);
@@ -63,32 +64,35 @@ public:
void setAcceleratesDrawing(bool);
CALayer *tileContainerLayer() const { return m_tileContainerLayer.get(); }
- void visibleRectChanged(const IntRect&);
- float tileDebugBorderWidth() const { return m_tileDebugBorderWidth; }
void setTileDebugBorderWidth(float);
-
- CGColorRef tileDebugBorderColor() const { return m_tileDebugBorderColor.get(); }
void setTileDebugBorderColor(CGColorRef);
private:
- typedef IntPoint TileIndex;
-
TileCache(WebTileCacheLayer*, const IntSize& tileSize);
+ // TiledBacking member functions.
+ virtual void visibleRectChanged(const IntRect&) OVERRIDE;
+ virtual void setIsInWindow(bool) OVERRIDE;
+ virtual void setCanHaveScrollbars(bool) OVERRIDE;
+
IntRect bounds() const;
+ typedef IntPoint TileIndex;
IntRect rectForTileIndex(const TileIndex&) const;
void getTileIndexRangeForRect(const IntRect&, TileIndex& topLeft, TileIndex& bottomRight);
- void scheduleTileRevalidation();
+ IntRect tileCoverageRect() const;
+
+ void scheduleTileRevalidation(double interval);
void tileRevalidationTimerFired(Timer<TileCache>*);
void revalidateTiles();
WebTileLayer* tileLayerAtIndex(const TileIndex&) const;
- RetainPtr<WebTileLayer> createTileLayer();
+ RetainPtr<WebTileLayer> createTileLayer(const IntRect&);
bool shouldShowRepaintCounters() const;
+ void drawRepaintCounter(WebTileLayer *, CGContextRef);
WebTileCacheLayer* m_tileCacheLayer;
RetainPtr<CALayer> m_tileContainerLayer;
@@ -101,7 +105,10 @@ private:
IntRect m_tileCoverageRect;
CGFloat m_scale;
+ CGFloat m_deviceScaleFactor;
+ bool m_isInWindow;
+ bool m_canHaveScrollbars;
bool m_acceleratesDrawing;
RetainPtr<CGColorRef> m_tileDebugBorderColor;
diff --git a/Source/WebCore/platform/graphics/ca/mac/TileCache.mm b/Source/WebCore/platform/graphics/ca/mac/TileCache.mm
index fbb5ddc71..9fa6a48c0 100644
--- a/Source/WebCore/platform/graphics/ca/mac/TileCache.mm
+++ b/Source/WebCore/platform/graphics/ca/mac/TileCache.mm
@@ -55,6 +55,9 @@ TileCache::TileCache(WebTileCacheLayer* tileCacheLayer, const IntSize& tileSize)
, m_tileSize(tileSize)
, m_tileRevalidationTimer(this, &TileCache::tileRevalidationTimerFired)
, m_scale(1)
+ , m_deviceScaleFactor(1)
+ , m_isInWindow(true)
+ , m_canHaveScrollbars(true)
, m_acceleratesDrawing(false)
, m_tileDebugBorderWidth(0)
{
@@ -78,7 +81,7 @@ void TileCache::tileCacheLayerBoundsChanged()
return;
}
- scheduleTileRevalidation();
+ scheduleTileRevalidation(0);
}
void TileCache::setNeedsDisplay()
@@ -120,7 +123,7 @@ void TileCache::setNeedsDisplayInRect(const IntRect& rect)
}
}
-void TileCache::drawLayer(WebTileLayer* layer, CGContextRef context)
+void TileCache::drawLayer(WebTileLayer *layer, CGContextRef context)
{
PlatformCALayer* platformLayer = PlatformCALayer::platformCALayer(m_tileCacheLayer);
if (!platformLayer)
@@ -135,54 +138,41 @@ void TileCache::drawLayer(WebTileLayer* layer, CGContextRef context)
CGContextRestoreGState(context);
- unsigned repaintCount = [layer incrementRepaintCount];
- if (!shouldShowRepaintCounters())
- return;
-
- // FIXME: Some of this code could be shared with WebLayer.
- char text[16]; // that's a lot of repaints
- snprintf(text, sizeof(text), "%d", repaintCount);
-
- CGRect indicatorBox = [layer bounds];
- indicatorBox.size.width = 12 + 10 * strlen(text);
- indicatorBox.size.height = 27;
- CGContextSaveGState(context);
-
- CGContextSetAlpha(context, 0.5f);
- CGContextBeginTransparencyLayerWithRect(context, indicatorBox, 0);
-
- CGContextSetFillColorWithColor(context, m_tileDebugBorderColor.get());
- CGContextFillRect(context, indicatorBox);
-
- if (platformLayer->acceleratesDrawing())
- CGContextSetRGBFillColor(context, 1, 0, 0, 1);
- else
- CGContextSetRGBFillColor(context, 1, 1, 1, 1);
-
- CGContextSetTextMatrix(context, CGAffineTransformMakeScale(1, -1));
- CGContextSelectFont(context, "Helvetica", 22, kCGEncodingMacRoman);
- CGContextShowTextAtPoint(context, indicatorBox.origin.x + 5, indicatorBox.origin.y + 22, text, strlen(text));
-
- CGContextEndTransparencyLayer(context);
- CGContextRestoreGState(context);
+ drawRepaintCounter(layer, context);
}
void TileCache::setScale(CGFloat scale)
{
- if (m_scale == scale)
+ PlatformCALayer* platformLayer = PlatformCALayer::platformCALayer(m_tileCacheLayer);
+ float deviceScaleFactor = platformLayer->owner()->platformCALayerDeviceScaleFactor();
+
+ // The scale we get is the produce of the page scale factor and device scale factor.
+ // Divide by the device scale factor so we'll get the page scale factor.
+ scale /= deviceScaleFactor;
+
+ if (m_scale == scale && m_deviceScaleFactor == deviceScaleFactor)
return;
#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+ Vector<FloatRect> dirtyRects;
+
+ m_deviceScaleFactor = deviceScaleFactor;
m_scale = scale;
[m_tileContainerLayer.get() setTransform:CATransform3DMakeScale(1 / m_scale, 1 / m_scale, 1)];
revalidateTiles();
- for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it)
- [it->second.get() setNeedsDisplay];
+ for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) {
+ [it->second.get() setContentsScale:deviceScaleFactor];
- PlatformCALayer* platformLayer = PlatformCALayer::platformCALayer(m_tileCacheLayer);
- platformLayer->owner()->platformCALayerDidCreateTiles();
+ IntRect tileRect = rectForTileIndex(it->first);
+ FloatRect scaledTileRect = tileRect;
+
+ scaledTileRect.scale(1 / m_scale);
+ dirtyRects.append(scaledTileRect);
+ }
+
+ platformLayer->owner()->platformCALayerDidCreateTiles(dirtyRects);
#endif
}
@@ -210,6 +200,29 @@ void TileCache::visibleRectChanged(const IntRect& visibleRect)
revalidateTiles();
}
+void TileCache::setIsInWindow(bool isInWindow)
+{
+ if (m_isInWindow == isInWindow)
+ return;
+
+ m_isInWindow = isInWindow;
+
+ if (!m_isInWindow) {
+ // Schedule a timeout to drop tiles that are outside of the visible rect in 4 seconds.
+ const double tileRevalidationTimeout = 4;
+ scheduleTileRevalidation(tileRevalidationTimeout);
+ }
+}
+
+void TileCache::setCanHaveScrollbars(bool canHaveScrollbars)
+{
+ if (m_canHaveScrollbars == canHaveScrollbars)
+ return;
+
+ m_canHaveScrollbars = canHaveScrollbars;
+ scheduleTileRevalidation(0);
+}
+
void TileCache::setTileDebugBorderWidth(float borderWidth)
{
if (m_tileDebugBorderWidth == borderWidth)
@@ -237,7 +250,13 @@ IntRect TileCache::bounds() const
IntRect TileCache::rectForTileIndex(const TileIndex& tileIndex) const
{
- return IntRect(IntPoint(tileIndex.x() * m_tileSize.width(), tileIndex.y() * m_tileSize.height()), m_tileSize);
+ IntRect rect(tileIndex.x() * m_tileSize.width(), tileIndex.y() * m_tileSize.height(), m_tileSize.width(), m_tileSize.height());
+ IntRect scaledBounds(bounds());
+ scaledBounds.scale(m_scale);
+
+ rect.intersect(scaledBounds);
+
+ return rect;
}
void TileCache::getTileIndexRangeForRect(const IntRect& rect, TileIndex& topLeft, TileIndex& bottomRight)
@@ -252,12 +271,27 @@ void TileCache::getTileIndexRangeForRect(const IntRect& rect, TileIndex& topLeft
bottomRight.setY(max(clampedRect.maxY() / m_tileSize.height(), 0));
}
-void TileCache::scheduleTileRevalidation()
+IntRect TileCache::tileCoverageRect() const
{
- if (m_tileRevalidationTimer.isActive())
+ IntRect tileCoverageRect = m_visibleRect;
+
+ if (m_isInWindow) {
+ // Inflate the coverage rect so that it covers 2x of the visible width and 3x of the visible height.
+ // These values were chosen because it's more common to have tall pages and to scroll vertically,
+ // so we keep more tiles above and below the current area.
+ tileCoverageRect.inflateX(tileCoverageRect.width() / 2);
+ tileCoverageRect.inflateY(tileCoverageRect.height());
+ }
+
+ return tileCoverageRect;
+}
+
+void TileCache::scheduleTileRevalidation(double interval)
+{
+ if (m_tileRevalidationTimer.isActive() && m_tileRevalidationTimer.nextFireInterval() < interval)
return;
- m_tileRevalidationTimer.startOneShot(0);
+ m_tileRevalidationTimer.startOneShot(interval);
}
void TileCache::tileRevalidationTimerFired(Timer<TileCache>*)
@@ -276,13 +310,7 @@ void TileCache::revalidateTiles()
if (m_visibleRect.isEmpty() || bounds().isEmpty())
return;
- IntRect tileCoverageRect = m_visibleRect;
-
- // Inflate the coverage rect so that it covers 2x of the visible width and 3x of the visible height.
- // These values were chosen because it's more common to have tall pages and to scroll vertically,
- // so we keep more tiles above and below the current area.
- tileCoverageRect.inflateX(tileCoverageRect.width() / 2);
- tileCoverageRect.inflateY(tileCoverageRect.height());
+ IntRect tileCoverageRect = this->tileCoverageRect();
Vector<TileIndex> tilesToRemove;
@@ -310,25 +338,27 @@ void TileCache::revalidateTiles()
TileIndex bottomRight;
getTileIndexRangeForRect(tileCoverageRect, topLeft, bottomRight);
- bool didCreateNewTiles = false;
+ Vector<FloatRect> dirtyRects;
for (int y = topLeft.y(); y <= bottomRight.y(); ++y) {
for (int x = topLeft.x(); x <= bottomRight.x(); ++x) {
TileIndex tileIndex(x, y);
- RetainPtr<WebTileLayer>& tileLayer = m_tiles.add(tileIndex, 0).first->second;
- if (tileLayer) {
- // We already have a layer for this tile.
- continue;
+ IntRect tileRect = rectForTileIndex(tileIndex);
+ RetainPtr<WebTileLayer>& tileLayer = m_tiles.add(tileIndex, 0).iterator->second;
+ if (!tileLayer) {
+ tileLayer = createTileLayer(tileRect);
+ [m_tileContainerLayer.get() addSublayer:tileLayer.get()];
+ } else {
+ // We already have a layer for this tile. Ensure that its size is correct.
+ if (CGSizeEqualToSize([tileLayer.get() frame].size, tileRect.size()))
+ continue;
+ [tileLayer.get() setFrame:tileRect];
}
- didCreateNewTiles = true;
-
- tileLayer = createTileLayer();
-
- [tileLayer.get() setNeedsDisplay];
- [tileLayer.get() setPosition:CGPointMake(x * m_tileSize.width(), y * m_tileSize.height())];
- [m_tileContainerLayer.get() addSublayer:tileLayer.get()];
+ FloatRect scaledTileRect = tileRect;
+ scaledTileRect.scale(1 / m_scale);
+ dirtyRects.append(scaledTileRect);
}
}
@@ -339,10 +369,7 @@ void TileCache::revalidateTiles()
m_tileCoverageRect.unite(rectForTileIndex(tileIndex));
}
- if (!didCreateNewTiles)
- return;
-
- platformLayer->owner()->platformCALayerDidCreateTiles();
+ platformLayer->owner()->platformCALayerDidCreateTiles(dirtyRects);
}
WebTileLayer* TileCache::tileLayerAtIndex(const TileIndex& index) const
@@ -350,17 +377,19 @@ WebTileLayer* TileCache::tileLayerAtIndex(const TileIndex& index) const
return m_tiles.get(index).get();
}
-RetainPtr<WebTileLayer> TileCache::createTileLayer()
+RetainPtr<WebTileLayer> TileCache::createTileLayer(const IntRect& tileRect)
{
RetainPtr<WebTileLayer> layer = adoptNS([[WebTileLayer alloc] init]);
- [layer.get() setBounds:CGRectMake(0, 0, m_tileSize.width(), m_tileSize.height())];
[layer.get() setAnchorPoint:CGPointZero];
+ [layer.get() setFrame:tileRect];
[layer.get() setTileCache:this];
[layer.get() setBorderColor:m_tileDebugBorderColor.get()];
[layer.get() setBorderWidth:m_tileDebugBorderWidth];
[layer.get() setEdgeAntialiasingMask:0];
+ [layer.get() setOpaque:YES];
#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+ [layer.get() setContentsScale:m_deviceScaleFactor];
[layer.get() setAcceleratesDrawing:m_acceleratesDrawing];
#endif
@@ -381,4 +410,40 @@ bool TileCache::shouldShowRepaintCounters() const
return layerContents->platformCALayerShowRepaintCounter();
}
+void TileCache::drawRepaintCounter(WebTileLayer *layer, CGContextRef context)
+{
+ unsigned repaintCount = [layer incrementRepaintCount];
+ if (!shouldShowRepaintCounters())
+ return;
+
+ // FIXME: Some of this code could be shared with WebLayer.
+ char text[16]; // that's a lot of repaints
+ snprintf(text, sizeof(text), "%d", repaintCount);
+
+ CGRect indicatorBox = [layer bounds];
+ indicatorBox.size.width = 12 + 10 * strlen(text);
+ indicatorBox.size.height = 27;
+ CGContextSaveGState(context);
+
+ CGContextSetAlpha(context, 0.5f);
+ CGContextBeginTransparencyLayerWithRect(context, indicatorBox, 0);
+
+ CGContextSetFillColorWithColor(context, m_tileDebugBorderColor.get());
+ CGContextFillRect(context, indicatorBox);
+
+ PlatformCALayer* platformLayer = PlatformCALayer::platformCALayer(m_tileCacheLayer);
+
+ if (platformLayer->acceleratesDrawing())
+ CGContextSetRGBFillColor(context, 1, 0, 0, 1);
+ else
+ CGContextSetRGBFillColor(context, 1, 1, 1, 1);
+
+ CGContextSetTextMatrix(context, CGAffineTransformMakeScale(1, -1));
+ CGContextSelectFont(context, "Helvetica", 22, kCGEncodingMacRoman);
+ CGContextShowTextAtPoint(context, indicatorBox.origin.x + 5, indicatorBox.origin.y + 22, text, strlen(text));
+
+ CGContextEndTransparencyLayer(context);
+ CGContextRestoreGState(context);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.h b/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.h
index 208884bf7..d44f9e1ee 100644
--- a/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.h
+++ b/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.h
@@ -29,6 +29,7 @@
namespace WebCore {
class IntRect;
class TileCache;
+ class TiledBacking;
}
@interface WebTileCacheLayer : CALayer {
@@ -36,6 +37,7 @@ namespace WebCore {
}
- (CALayer *)tileContainerLayer;
-- (void)visibleRectChanged:(const WebCore::IntRect&)visibleRect;
+- (WebCore::TiledBacking*)tiledBacking;
+- (void)invalidate;
@end
diff --git a/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm b/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm
index 83abb72a8..d3e27274b 100644
--- a/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm
+++ b/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm
@@ -48,12 +48,7 @@ using namespace WebCore;
- (void)dealloc
{
- if (!isMainThread()) {
- TileCache* tileCache = _tileCache.leakPtr();
- dispatch_async(dispatch_get_main_queue(), ^{
- delete tileCache;
- });
- }
+ ASSERT(!_tileCache);
[super dealloc];
}
@@ -111,14 +106,16 @@ using namespace WebCore;
return _tileCache->tileContainerLayer();
}
-- (void)visibleRectChanged:(const IntRect&)visibleRect
+- (WebCore::TiledBacking*)tiledBacking
{
- _tileCache->visibleRectChanged(visibleRect);
+ return _tileCache.get();
}
-- (CGColorRef)borderColor
+- (void)invalidate
{
- return _tileCache->tileDebugBorderColor();
+ ASSERT(isMainThread());
+ ASSERT(_tileCache);
+ _tileCache = nullptr;
}
- (void)setBorderColor:(CGColorRef)borderColor
@@ -126,11 +123,6 @@ using namespace WebCore;
_tileCache->setTileDebugBorderColor(borderColor);
}
-- (CGFloat)borderWidth
-{
- return _tileCache->tileDebugBorderWidth();
-}
-
- (void)setBorderWidth:(CGFloat)borderWidth
{
_tileCache->setTileDebugBorderWidth(borderWidth);
diff --git a/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.cpp b/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.cpp
index 00c63080d..b4feaee68 100644
--- a/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.cpp
+++ b/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.cpp
@@ -49,7 +49,7 @@ LayerChangesFlusher::LayerChangesFlusher()
void LayerChangesFlusher::flushPendingLayerChangesSoon(AbstractCACFLayerTreeHost* host)
{
- if (!m_hostsWithChangesToFlush.add(host).second || m_hook)
+ if (!m_hostsWithChangesToFlush.add(host).isNewEntry || m_hook)
return;
setHook();
diff --git a/Source/WebCore/platform/graphics/ca/win/PlatformCAAnimationWin.cpp b/Source/WebCore/platform/graphics/ca/win/PlatformCAAnimationWin.cpp
index 944288ca7..4a71fe5f2 100644
--- a/Source/WebCore/platform/graphics/ca/win/PlatformCAAnimationWin.cpp
+++ b/Source/WebCore/platform/graphics/ca/win/PlatformCAAnimationWin.cpp
@@ -288,8 +288,9 @@ void PlatformCAAnimation::setFillMode(FillModeType value)
CACFAnimationSetFillMode(m_animation.get(), toCACFFillModeType(value));
}
-void PlatformCAAnimation::setTimingFunction(const TimingFunction* value)
+void PlatformCAAnimation::setTimingFunction(const TimingFunction* value, bool reverse)
{
+ UNUSED_PARAM(reverse);
CACFAnimationSetTimingFunction(m_animation.get(), toCACFTimingFunction(value).get());
}
@@ -533,8 +534,9 @@ void PlatformCAAnimation::copyKeyTimesFrom(const PlatformCAAnimation* value)
CACFAnimationSetKeyTimes(m_animation.get(), CACFAnimationGetKeyTimes(value->platformAnimation()));
}
-void PlatformCAAnimation::setTimingFunctions(const Vector<const TimingFunction*>& value)
+void PlatformCAAnimation::setTimingFunctions(const Vector<const TimingFunction*>& value, bool reverse)
{
+ UNUSED_PARAM(reverse);
if (animationType() != Keyframe)
return;
diff --git a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp
index ca73001d5..48b20d0b8 100644
--- a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp
+++ b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp
@@ -633,8 +633,9 @@ void PlatformCALayer::setContentsScale(float)
{
}
-void PlatformCALayer::visibleRectChanged(const IntRect&)
+TiledBacking* PlatformCALayer::tiledBacking()
{
+ return 0;
}
#ifndef NDEBUG
diff --git a/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp b/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp
new file mode 100644
index 000000000..979dfed1b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "BitmapImage.h"
+
+#include "ImageObserver.h"
+#include "NativeImageCairo.h"
+#include "PlatformContextCairo.h"
+#include <cairo.h>
+
+namespace WebCore {
+
+PassRefPtr<BitmapImage> BitmapImage::create(cairo_surface_t* surface)
+{
+ return BitmapImage::create(new NativeImageCairo(surface));
+}
+
+BitmapImage::BitmapImage(NativeImageCairo* nativeImage, ImageObserver* observer)
+ : Image(observer)
+ , m_currentFrame(0)
+ , m_frames(0)
+ , m_frameTimer(0)
+ , m_repetitionCount(cAnimationNone)
+ , m_repetitionCountStatus(Unknown)
+ , m_repetitionsComplete(0)
+ , m_decodedSize(0)
+ , m_frameCount(1)
+ , m_isSolidColor(false)
+ , m_checkedForSolidColor(false)
+ , m_animationFinished(true)
+ , m_allDataReceived(true)
+ , m_haveSize(true)
+ , m_sizeAvailable(true)
+ , m_haveFrameCount(true)
+{
+ initPlatformData();
+
+ cairo_surface_t* surface = nativeImage->surface();
+ int width = cairo_image_surface_get_width(surface);
+ int height = cairo_image_surface_get_height(surface);
+ m_decodedSize = width * height * 4;
+ m_size = IntSize(width, height);
+
+ m_frames.grow(1);
+ m_frames[0].m_frame = nativeImage;
+ m_frames[0].m_hasAlpha = cairo_surface_get_content(surface) != CAIRO_CONTENT_COLOR;
+ m_frames[0].m_haveMetadata = true;
+ checkForSolidColor();
+}
+
+void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
+{
+ FloatRect srcRect(src);
+ FloatRect dstRect(dst);
+
+ if (!dstRect.width() || !dstRect.height() || !srcRect.width() || !srcRect.height())
+ return;
+
+ startAnimation();
+
+ NativeImageCairo* nativeImage = frameAtIndex(m_currentFrame);
+ if (!nativeImage) // If it's too early we won't have an image yet.
+ return;
+
+ if (mayFillWithSolidColor()) {
+ fillWithSolidColor(context, dstRect, solidColor(), styleColorSpace, op);
+ return;
+ }
+
+ context->save();
+
+ // Set the compositing operation.
+ if (op == CompositeSourceOver && !frameHasAlphaAtIndex(m_currentFrame))
+ context->setCompositeOperation(CompositeCopy);
+ else
+ context->setCompositeOperation(op);
+ context->platformContext()->drawSurfaceToContext(nativeImage->surface(), dstRect, srcRect, context);
+
+ context->restore();
+
+ if (imageObserver())
+ imageObserver()->didDraw(this);
+}
+
+void BitmapImage::checkForSolidColor()
+{
+ m_isSolidColor = false;
+ m_checkedForSolidColor = true;
+
+ if (frameCount() > 1)
+ return;
+
+ NativeImageCairo* nativeImage = frameAtIndex(m_currentFrame);
+ if (!nativeImage) // If it's too early we won't have an image yet.
+ return;
+
+ cairo_surface_t* surface = nativeImage->surface();
+ ASSERT(cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE);
+
+ int width = cairo_image_surface_get_width(surface);
+ int height = cairo_image_surface_get_height(surface);
+
+ if (width != 1 || height != 1)
+ return;
+
+ unsigned* pixelColor = reinterpret_cast<unsigned*>(cairo_image_surface_get_data(surface));
+ m_solidColor = colorFromPremultipliedARGB(*pixelColor);
+
+ m_isSolidColor = true;
+}
+
+bool FrameData::clear(bool clearMetadata)
+{
+ if (clearMetadata)
+ m_haveMetadata = false;
+
+ if (m_frame) {
+ delete m_frame;
+ m_frame = 0;
+ return true;
+ }
+ return false;
+}
+
+} // namespace WebCore
+
diff --git a/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp b/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp
index a640357f2..ad5388e0b 100644
--- a/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp
+++ b/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp
@@ -120,13 +120,11 @@ cairo_operator_t toCairoOperator(CompositeOperator op)
case CompositeXOR:
return CAIRO_OPERATOR_XOR;
case CompositePlusDarker:
-#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0)
return CAIRO_OPERATOR_DARKEN;
-#else
- return CAIRO_OPERATOR_SATURATE;
-#endif
case CompositePlusLighter:
return CAIRO_OPERATOR_ADD;
+ case CompositeDifference:
+ return CAIRO_OPERATOR_DIFFERENCE;
default:
return CAIRO_OPERATOR_SOURCE;
}
diff --git a/Source/WebCore/platform/graphics/cairo/DrawingBufferCairo.cpp b/Source/WebCore/platform/graphics/cairo/DrawingBufferCairo.cpp
index 067b9c7b3..114c7e171 100644
--- a/Source/WebCore/platform/graphics/cairo/DrawingBufferCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/DrawingBufferCairo.cpp
@@ -37,10 +37,13 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
const IntSize& size,
bool multisampleExtensionSupported,
bool packedDepthStencilExtensionSupported,
- bool separateBackingTexture)
- : m_separateBackingTexture(separateBackingTexture)
+ PreserveDrawingBuffer preserveDrawingBuffer,
+ AlphaRequirement alpha)
+ : m_preserveDrawingBuffer(preserveDrawingBuffer)
+ , m_alpha(alpha)
, m_scissorEnabled(false)
, m_texture2DBinding(0)
+ , m_framebufferBinding(0)
, m_activeTextureUnit(GraphicsContext3D::TEXTURE0)
, m_context(context)
, m_size(-1, -1)
@@ -48,15 +51,14 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
, m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupported)
, m_fbo(context->createFramebuffer())
, m_colorBuffer(0)
+ , m_frontColorBuffer(0)
+ , m_separateFrontTexture(false)
, m_depthStencilBuffer(0)
, m_depthBuffer(0)
, m_stencilBuffer(0)
, m_multisampleFBO(0)
, m_multisampleColorBuffer(0)
{
- // Support for a separate backing texture has only been enabled for
- // the chromium port.
- ASSERT(!m_separateBackingTexture);
ASSERT(m_fbo);
if (!m_fbo) {
clear();
@@ -81,12 +83,21 @@ DrawingBuffer::~DrawingBuffer()
clear();
}
-Platform3DObject DrawingBuffer::platformColorBuffer() const
+#if USE(ACCELERATED_COMPOSITING)
+void DrawingBuffer::prepareBackBuffer()
{
- return m_colorBuffer;
}
-#if USE(ACCELERATED_COMPOSITING)
+bool DrawingBuffer::requiresCopyFromBackToFrontBuffer() const
+{
+ return false;
+}
+
+unsigned DrawingBuffer::frontColorBuffer() const
+{
+ return colorBuffer();
+}
+
void DrawingBuffer::paintCompositedResultsToCanvas(CanvasRenderingContext* context)
{
}
diff --git a/Source/WebCore/platform/graphics/cairo/FontCairo.cpp b/Source/WebCore/platform/graphics/cairo/FontCairo.cpp
index 35d1e5b7d..d6e43eb98 100644
--- a/Source/WebCore/platform/graphics/cairo/FontCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/FontCairo.cpp
@@ -85,7 +85,8 @@ static void drawGlyphsShadow(GraphicsContext* graphicsContext, const FloatPoint&
cairo_text_extents_t extents;
cairo_scaled_font_glyph_extents(font->platformData().scaledFont(), glyphs, numGlyphs, &extents);
- FloatRect fontExtentsRect(point.x(), point.y() - extents.height, extents.width, extents.height);
+ FloatRect fontExtentsRect(point.x() + extents.x_bearing, point.y() + extents.y_bearing, extents.width, extents.height);
+
if (GraphicsContext* shadowContext = shadow.beginShadowLayer(graphicsContext, fontExtentsRect)) {
drawGlyphsToContext(shadowContext->platformContext()->cr(), font, glyphs, numGlyphs);
shadow.endShadowLayer(graphicsContext);
diff --git a/Source/WebCore/platform/graphics/cairo/GLContext.cpp b/Source/WebCore/platform/graphics/cairo/GLContext.cpp
new file mode 100644
index 000000000..c70307e8e
--- /dev/null
+++ b/Source/WebCore/platform/graphics/cairo/GLContext.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2011, 2012 Igalia, S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "GLContext.h"
+
+#if USE(OPENGL)
+
+#if USE(GLX)
+#include "GLContextGLX.h"
+#endif
+
+namespace WebCore {
+
+GLContext::GLContext()
+{
+}
+
+GLContext* GLContext::createOffscreenContext(GLContext* sharing)
+{
+ if (sharing)
+ return sharing->createOffscreenSharingContext();
+
+#if USE(GLX)
+ return GLContextGLX::createContext(0, 0);
+#endif
+}
+
+// FIXME: This should be a thread local eventually if we
+// want to support using GLContexts from multiple threads.
+static GLContext* gCurrentContext = 0;
+
+GLContext::~GLContext()
+{
+ if (this == gCurrentContext)
+ gCurrentContext = 0;
+}
+
+bool GLContext::makeContextCurrent()
+{
+ gCurrentContext = this;
+ return true;
+}
+
+GLContext* GLContext::getCurrent()
+{
+ return gCurrentContext;
+}
+
+} // namespace WebCore
+
+#endif // USE(OPENGL)
+
diff --git a/Source/WebCore/platform/graphics/cairo/GLContext.h b/Source/WebCore/platform/graphics/cairo/GLContext.h
index 0a39cec58..8b2eee7ca 100644
--- a/Source/WebCore/platform/graphics/cairo/GLContext.h
+++ b/Source/WebCore/platform/graphics/cairo/GLContext.h
@@ -25,60 +25,27 @@
#include <wtf/Noncopyable.h>
#include <wtf/PassOwnPtr.h>
-#if defined(XP_UNIX)
-typedef struct __GLXcontextRec* GLXContext;
-typedef struct _XDisplay Display;
-typedef struct __GLXcontextRec *GLXContext;
-typedef unsigned long GLXPbuffer;
-typedef unsigned long GLXPixmap;
-typedef unsigned char GLubyte;
-typedef unsigned long Pixmap;
-typedef unsigned long XID;
-typedef void* ContextKeyType;
-#endif
-
namespace WebCore {
class GLContext {
WTF_MAKE_NONCOPYABLE(GLContext);
public:
- static GLContext* createSharingContext(GLContext* shareContext);
static GLContext* getContextForWidget(PlatformWidget);
+ static GLContext* createOffscreenContext(GLContext* sharing = 0);
static GLContext* getCurrent();
- static void removeActiveContext(GLContext*);
- static void removeActiveContextForWidget(PlatformWidget);
+ GLContext();
virtual ~GLContext();
- bool makeContextCurrent();
- void swapBuffers();
- bool canRenderToDefaultFramebuffer();
+ virtual GLContext* createOffscreenSharingContext() = 0;
+ virtual bool makeContextCurrent();
+ virtual void swapBuffers() = 0;
+ virtual bool canRenderToDefaultFramebuffer() = 0;
#if ENABLE(WEBGL)
- PlatformGraphicsContext3D platformContext();
-#endif
-
-private:
- static void addActiveContext(GLContext*);
- static void cleanupActiveContextsAtExit();
-
-#if defined(XP_UNIX)
- GLContext(GLXContext);
- GLContext(GLXContext, Pixmap, GLXPixmap);
- static GLContext* createContext(XID, GLXContext sharingContext = 0);
- static GLContext* createWindowContext(XID window, GLXContext sharingContext);
- static GLContext* createPbufferContext(GLXContext sharingContext);
- static GLContext* createPixmapContext(GLXContext sharingContext);
-
- GLXContext m_context;
- Display* m_display;
-
- XID m_window;
- GLXPbuffer m_pbuffer;
- Pixmap m_pixmap;
- GLXPixmap m_glxPixmap;
+ virtual PlatformGraphicsContext3D platformContext() = 0;
#endif
};
-}
+} // namespace WebCore
#endif // GLContext_h
diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp
index ad7db41d3..8d3969214 100644
--- a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp
@@ -157,9 +157,9 @@ bool GraphicsContext3D::getImageData(Image* image, unsigned int format, unsigned
decoder.setData(image->data(), true);
if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0))
return false;
- imageSurface = decoder.createFrameAtIndex(0);
+ imageSurface = decoder.createFrameAtIndex(0)->surface();
} else {
- imageSurface = image->nativeImageForCurrentFrame();
+ imageSurface = image->nativeImageForCurrentFrame()->surface();
if (!premultiplyAlpha)
alphaOp = AlphaDoUnmultiply;
}
diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DPrivate.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DPrivate.cpp
index 69eef6efc..94d40ec5a 100644
--- a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DPrivate.cpp
+++ b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DPrivate.cpp
@@ -40,16 +40,15 @@ GraphicsContext3DPrivate::GraphicsContext3DPrivate(GraphicsContext3D* context, H
: m_context(context)
, m_window(window)
#if PLATFORM(GTK)
- , m_glContext(GLContext::createSharingContext(GLContext::getContextForWidget(m_window->platformPageClient())))
+ , m_glContext(GLContext::createOffscreenContext(GLContext::getContextForWidget(m_window->platformPageClient())))
#else
- , m_glContext(GLContext::createContext(0, 0))
+ , m_glContext(GLContext::createOffscreenContext())
#endif
{
}
GraphicsContext3DPrivate::~GraphicsContext3DPrivate()
{
- GLContext::removeActiveContext(m_glContext);
}
bool GraphicsContext3DPrivate::makeContextCurrent()
@@ -87,7 +86,8 @@ void GraphicsContext3DPrivate::paintToTextureMapper(TextureMapper* textureMapper
TextureMapperGL* texmapGL = static_cast<TextureMapperGL*>(textureMapper);
TextureMapperGL::Flags flags = TextureMapperGL::ShouldFlipTexture | (m_context->m_attrs.alpha ? TextureMapperGL::SupportsBlending : 0);
- texmapGL->drawTexture(m_context->m_texture, flags, FloatSize(1, 1), targetRect, matrix, opacity, mask);
+ IntSize textureSize(m_context->m_currentWidth, m_context->m_currentHeight);
+ texmapGL->drawTexture(m_context->m_texture, flags, textureSize, targetRect, matrix, opacity, mask);
}
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index ba886a03c..7a804b0a1 100644
--- a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -77,7 +77,6 @@ static inline void fillRectWithColor(cairo_t* cr, const FloatRect& rect, const C
return;
setSourceRGBAFromColor(cr, color);
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
- cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
cairo_fill(cr);
}
@@ -682,7 +681,7 @@ void GraphicsContext::drawLineForText(const FloatPoint& origin, float width, boo
#include "DrawErrorUnderline.h"
#endif
-void GraphicsContext::drawLineForTextChecking(const FloatPoint& origin, float width, TextCheckingLineStyle style)
+void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& origin, float width, DocumentMarkerLineStyle style)
{
if (paintingDisabled())
return;
@@ -691,10 +690,10 @@ void GraphicsContext::drawLineForTextChecking(const FloatPoint& origin, float wi
cairo_save(cr);
switch (style) {
- case TextCheckingSpellingLineStyle:
+ case DocumentMarkerSpellingLineStyle:
cairo_set_source_rgb(cr, 1, 0, 0);
break;
- case TextCheckingGrammarLineStyle:
+ case DocumentMarkerGrammarLineStyle:
cairo_set_source_rgb(cr, 0, 1, 0);
break;
default:
diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
index 96df0938f..af157a297 100644
--- a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
@@ -54,9 +54,10 @@ ImageBufferData::ImageBufferData(const IntSize& size)
{
}
-ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode, DeferralMode, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, float /* resolutionScale */, ColorSpace, RenderingMode, DeferralMode, bool& success)
: m_data(size)
, m_size(size)
+ , m_logicalSize(size)
{
success = false; // Make early return mean error.
m_data.m_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
@@ -98,7 +99,7 @@ void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, con
{
// BitmapImage will release the passed in surface on destruction
RefPtr<Image> image = BitmapImage::create(cairo_surface_reference(m_data.m_surface));
- context->drawImage(image.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
+ context->drawImage(image.get(), styleColorSpace, destRect, srcRect, op, DoNotRespectImageOrientation, useLowQualityScale);
}
void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform,
@@ -131,16 +132,16 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
}
template <Multiply multiplied>
-PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& data, const IntSize& size)
+PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBufferData& data, const IntSize& size)
{
ASSERT(cairo_surface_get_type(data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE);
- RefPtr<ByteArray> result = ByteArray::create(rect.width() * rect.height() * 4);
+ RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4);
unsigned char* dataSrc = cairo_image_surface_get_data(data.m_surface);
unsigned char* dataDst = result->data();
if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > size.width() || (rect.y() + rect.height()) > size.height())
- memset(dataDst, 0, result->length());
+ result->zeroFill();
int originx = rect.x();
int destx = 0;
@@ -189,17 +190,17 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& d
return result.release();
}
-PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect, CoordinateSystem) const
{
return getImageData<Unmultiplied>(rect, m_data, m_size);
}
-PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem) const
{
return getImageData<Premultiplied>(rect, m_data, m_size);
}
-void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
+void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem)
{
ASSERT(cairo_surface_get_type(m_data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE);
@@ -257,31 +258,34 @@ void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const Int
}
#if !PLATFORM(GTK)
-static cairo_status_t writeFunction(void* closure, const unsigned char* data, unsigned int length)
+static cairo_status_t writeFunction(void* output, const unsigned char* data, unsigned int length)
{
- Vector<char>* in = reinterpret_cast<Vector<char>*>(closure);
- in->append(data, length);
+ if (!reinterpret_cast<Vector<unsigned char>*>(output)->tryAppend(data, length))
+ return CAIRO_STATUS_WRITE_ERROR;
return CAIRO_STATUS_SUCCESS;
}
-String ImageBuffer::toDataURL(const String& mimeType, const double*) const
+static bool encodeImage(cairo_surface_t* image, const String& mimeType, Vector<char>* output)
{
- cairo_surface_t* image = cairo_get_target(context()->platformContext()->cr());
- if (!image)
- return "data:,";
+ ASSERT(mimeType == "image/png"); // Only PNG output is supported for now.
+
+ return cairo_surface_write_to_png_stream(image, writeFunction, output) == CAIRO_STATUS_SUCCESS;
+}
- String actualMimeType("image/png");
- if (MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType))
- actualMimeType = mimeType;
+String ImageBuffer::toDataURL(const String& mimeType, const double*, CoordinateSystem) const
+{
+ ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
+
+ cairo_surface_t* image = cairo_get_target(context()->platformContext()->cr());
- Vector<char> in;
- // Only PNG output is supported for now.
- cairo_surface_write_to_png_stream(image, writeFunction, &in);
+ Vector<char> encodedImage;
+ if (!image || !encodeImage(image, mimeType, &encodedImage))
+ return "data:,";
- Vector<char> out;
- base64Encode(in, out);
+ Vector<char> base64Data;
+ base64Encode(encodedImage, base64Data);
- return "data:" + actualMimeType + ";base64," + String(out.data(), out.size());
+ return "data:" + mimeType + ";base64," + base64Data;
}
#endif
diff --git a/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp
index 0084b4234..51ca64396 100644
--- a/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp
@@ -26,147 +26,36 @@
*/
#include "config.h"
-#include "BitmapImage.h"
+#include "Image.h"
#if USE(CAIRO)
#include "AffineTransform.h"
#include "CairoUtilities.h"
#include "Color.h"
-#include "FloatRect.h"
#include "GraphicsContext.h"
-#include "PlatformContextCairo.h"
-#include "ImageBuffer.h"
#include "ImageObserver.h"
-#include "RefPtrCairo.h"
+#include "NativeImageCairo.h"
+#include "PlatformContextCairo.h"
#include <cairo.h>
#include <math.h>
-#include <wtf/OwnPtr.h>
namespace WebCore {
-bool FrameData::clear(bool clearMetadata)
-{
- if (clearMetadata)
- m_haveMetadata = false;
-
- if (m_frame) {
- cairo_surface_destroy(m_frame);
- m_frame = 0;
- return true;
- }
- return false;
-}
-
-BitmapImage::BitmapImage(cairo_surface_t* surface, ImageObserver* observer)
- : Image(observer)
- , m_currentFrame(0)
- , m_frames(0)
- , m_frameTimer(0)
- , m_repetitionCount(cAnimationNone)
- , m_repetitionCountStatus(Unknown)
- , m_repetitionsComplete(0)
- , m_decodedSize(0)
- , m_frameCount(1)
- , m_isSolidColor(false)
- , m_checkedForSolidColor(false)
- , m_animationFinished(true)
- , m_allDataReceived(true)
- , m_haveSize(true)
- , m_sizeAvailable(true)
- , m_haveFrameCount(true)
-{
- initPlatformData();
-
- // TODO: check to be sure this is an image surface
-
- int width = cairo_image_surface_get_width(surface);
- int height = cairo_image_surface_get_height(surface);
- m_decodedSize = width * height * 4;
- m_size = IntSize(width, height);
-
- m_frames.grow(1);
- m_frames[0].m_frame = surface;
- m_frames[0].m_hasAlpha = cairo_surface_get_content(surface) != CAIRO_CONTENT_COLOR;
- m_frames[0].m_haveMetadata = true;
- checkForSolidColor();
-}
-
-void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
-{
- FloatRect srcRect(src);
- FloatRect dstRect(dst);
-
- if (dstRect.width() == 0.0f || dstRect.height() == 0.0f ||
- srcRect.width() == 0.0f || srcRect.height() == 0.0f)
- return;
-
- startAnimation();
-
- cairo_surface_t* image = frameAtIndex(m_currentFrame);
- if (!image) // If it's too early we won't have an image yet.
- return;
-
- if (mayFillWithSolidColor()) {
- fillWithSolidColor(context, dstRect, solidColor(), styleColorSpace, op);
- return;
- }
-
- context->save();
-
- // Set the compositing operation.
- if (op == CompositeSourceOver && !frameHasAlphaAtIndex(m_currentFrame))
- context->setCompositeOperation(CompositeCopy);
- else
- context->setCompositeOperation(op);
- context->platformContext()->drawSurfaceToContext(image, dstRect, srcRect, context);
-
- context->restore();
-
- if (imageObserver())
- imageObserver()->didDraw(this);
-}
-
void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const AffineTransform& patternTransform,
const FloatPoint& phase, ColorSpace colorSpace, CompositeOperator op, const FloatRect& destRect)
{
- cairo_surface_t* image = nativeImageForCurrentFrame();
+ NativeImageCairo* image = nativeImageForCurrentFrame();
if (!image) // If it's too early we won't have an image yet.
return;
cairo_t* cr = context->platformContext()->cr();
- drawPatternToCairoContext(cr, image, size(), tileRect, patternTransform, phase, toCairoOperator(op), destRect);
+ drawPatternToCairoContext(cr, image->surface(), size(), tileRect, patternTransform, phase, toCairoOperator(op), destRect);
if (imageObserver())
imageObserver()->didDraw(this);
}
-void BitmapImage::checkForSolidColor()
-{
- m_isSolidColor = false;
- m_checkedForSolidColor = true;
-
- if (frameCount() > 1)
- return;
-
- cairo_surface_t* frameSurface = frameAtIndex(0);
- if (!frameSurface)
- return;
-
- ASSERT(cairo_surface_get_type(frameSurface) == CAIRO_SURFACE_TYPE_IMAGE);
-
- int width = cairo_image_surface_get_width(frameSurface);
- int height = cairo_image_surface_get_height(frameSurface);
-
- if (width != 1 || height != 1)
- return;
-
- unsigned* pixelColor = reinterpret_cast<unsigned*>(cairo_image_surface_get_data(frameSurface));
- m_solidColor = colorFromPremultipliedARGB(*pixelColor);
-
- m_isSolidColor = true;
-}
-
}
#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/NativeImageCairo.cpp b/Source/WebCore/platform/graphics/cairo/NativeImageCairo.cpp
new file mode 100644
index 000000000..af674d471
--- /dev/null
+++ b/Source/WebCore/platform/graphics/cairo/NativeImageCairo.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ * Copyright (c) 2012, Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "NativeImageCairo.h"
+
+namespace WebCore {
+
+NativeImageCairo::NativeImageCairo()
+{
+}
+
+NativeImageCairo::NativeImageCairo(cairo_surface_t* surface)
+ : m_surface(adoptRef(surface))
+{
+}
+
+NativeImageCairo::~NativeImageCairo()
+{
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/cairo/NativeImageCairo.h b/Source/WebCore/platform/graphics/cairo/NativeImageCairo.h
new file mode 100644
index 000000000..79dc1dbb2
--- /dev/null
+++ b/Source/WebCore/platform/graphics/cairo/NativeImageCairo.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ * Copyright (c) 2012, Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NativeImageCairo_h
+#define NativeImageCairo_h
+
+#include "RefPtrCairo.h"
+
+namespace WebCore {
+
+class NativeImageCairo {
+public:
+ NativeImageCairo();
+ ~NativeImageCairo();
+ explicit NativeImageCairo(cairo_surface_t*);
+ cairo_surface_t* surface () { return m_surface.get(); }
+
+private:
+ RefPtr<cairo_surface_t> m_surface;
+};
+
+}
+#endif // NativeImageCairo_h
+
diff --git a/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h b/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h
index bd517b24a..3704b6a17 100644
--- a/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h
+++ b/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h
@@ -20,8 +20,8 @@
#ifndef OwnPtrCairo_h
#define OwnPtrCairo_h
-#include "OwnPtr.h"
-#include "PassOwnPtr.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
#if USE(FREETYPE)
typedef struct _FcObjectSet FcObjectSet;
diff --git a/Source/WebCore/platform/graphics/cairo/PatternCairo.cpp b/Source/WebCore/platform/graphics/cairo/PatternCairo.cpp
index b067acc20..22368b8c0 100644
--- a/Source/WebCore/platform/graphics/cairo/PatternCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/PatternCairo.cpp
@@ -28,18 +28,17 @@
#include "AffineTransform.h"
#include "GraphicsContext.h"
-
#include <cairo.h>
namespace WebCore {
cairo_pattern_t* Pattern::createPlatformPattern(const AffineTransform&) const
{
- cairo_surface_t* surface = tileImage()->nativeImageForCurrentFrame();
- if (!surface)
+ NativeImageCairo* image = tileImage()->nativeImageForCurrentFrame();
+ if (!image)
return 0;
- cairo_pattern_t* pattern = cairo_pattern_create_for_surface(surface);
+ cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image->surface());
// cairo merges patter space and user space itself
cairo_matrix_t matrix = m_patternSpaceTransformation;
diff --git a/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h b/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h
index 6bc5b2bf5..0e1baf50a 100644
--- a/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h
+++ b/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h
@@ -20,7 +20,7 @@
#ifndef RefPtrCairo_h
#define RefPtrCairo_h
-#include "RefPtr.h"
+#include <wtf/RefPtr.h>
typedef struct _cairo cairo_t;
typedef struct _cairo_surface cairo_surface_t;
diff --git a/Source/WebCore/platform/graphics/cairo/rgb24-hacks.txt b/Source/WebCore/platform/graphics/cairo/rgb24-hacks.txt
deleted file mode 100644
index 59f8070bb..000000000
--- a/Source/WebCore/platform/graphics/cairo/rgb24-hacks.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-Index: cairo/src/cairo-win32-surface.c
-===================================================================
---- cairo/src/cairo-win32-surface.c (revision 14498)
-+++ cairo/src/cairo-win32-surface.c (working copy)
-@@ -824,8 +824,13 @@
- * to figure out when we can use GDI. We don't have that checking
- * anywhere at the moment, so just bail and use the fallback
- * paths. */
-- if (surface->format != CAIRO_FORMAT_RGB24)
-- return CAIRO_INT_STATUS_UNSUPPORTED;
-+ //if (surface->format != CAIRO_FORMAT_RGB24)
-+ // return CAIRO_INT_STATUS_UNSUPPORTED;
-+ // FIXME: We'll go ahead and optimize this now and just assume we're ok if
-+ // the color has no alpha. Probably need to check various composite operators to
-+ // get this exactly right.
-+ if (color->alpha != 1.0)
-+ return CAIRO_INT_STATUS_UNSUPPORTED;
-
- /* Optimize for no destination alpha (surface->pixman_image is non-NULL for all
- * surfaces with alpha.)
-@@ -1016,8 +1021,9 @@
-
- /* We can only handle operator SOURCE or OVER with the destination
- * having no alpha */
-- if ((op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER) ||
-- (dst->format != CAIRO_FORMAT_RGB24))
-+ if ((op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER))
-+ // FIXME: It's not clear why ExtTextOut can't be called when the
-+ // destination has alpha. Remove the RGB24 restriction. || (dst->format != CAIRO_FORMAT_RGB24))
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- /* If we have a fallback mask clip set on the dst, we have
diff --git a/Source/WebCore/platform/graphics/cairo/scale-removal.txt b/Source/WebCore/platform/graphics/cairo/scale-removal.txt
deleted file mode 100644
index 47c0d70a4..000000000
--- a/Source/WebCore/platform/graphics/cairo/scale-removal.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-Index: cairo/src/cairo-win32-private.h
-===================================================================
---- cairo/src/cairo-win32-private.h (revision 14582)
-+++ cairo/src/cairo-win32-private.h (working copy)
-@@ -39,7 +39,7 @@
- #include <cairo-win32.h>
- #include <cairoint.h>
-
--#define WIN32_FONT_LOGICAL_SCALE 32
-+#define WIN32_FONT_LOGICAL_SCALE 1
-
- typedef struct _cairo_win32_surface {
- cairo_surface_t base;
diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index 09caf5dae..a6c94e5fc 100644
--- a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -32,6 +32,7 @@
#include "FloatConversion.h"
#include "GraphicsContextPlatformPrivateCG.h"
#include "ImageBuffer.h"
+#include "ImageOrientation.h"
#include "KURL.h"
#include "Path.h"
#include "Pattern.h"
@@ -65,9 +66,9 @@
#endif
-// Undocumented CGContextSetCTM function, available at least since 10.4.
extern "C" {
CG_EXTERN void CGContextSetCTM(CGContextRef, CGAffineTransform);
+ CG_EXTERN CGAffineTransform CGContextGetBaseCTM(CGContextRef);
};
using namespace std;
@@ -170,11 +171,12 @@ void GraphicsContext::restorePlatformState()
m_data->m_userToDeviceTransformKnownToBeIdentity = false;
}
-void GraphicsContext::drawNativeImage(NativeImagePtr imagePtr, const FloatSize& imageSize, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op)
+void GraphicsContext::drawNativeImage(NativeImagePtr imagePtr, const FloatSize& imageSize, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, ImageOrientation orientation)
{
RetainPtr<CGImageRef> image(imagePtr);
- float currHeight = CGImageGetHeight(image.get());
+ float currHeight = orientation.usesWidthAsHeight() ? CGImageGetWidth(image.get()) : CGImageGetHeight(image.get());
+
if (currHeight <= srcRect.y())
return;
@@ -231,8 +233,18 @@ void GraphicsContext::drawNativeImage(NativeImagePtr imagePtr, const FloatSize&
setPlatformCompositeOperation(op);
// Flip the coords.
+ CGContextTranslateCTM(context, adjustedDestRect.x(), adjustedDestRect.maxY());
CGContextScaleCTM(context, 1, -1);
- adjustedDestRect.setY(-adjustedDestRect.maxY());
+ adjustedDestRect.setLocation(FloatPoint());
+
+ if (orientation != DefaultImageOrientation) {
+ CGContextConcatCTM(context, orientation.transformFromDefault(adjustedDestRect.size()));
+ if (orientation.usesWidthAsHeight()) {
+ // The destination rect will have it's width and height already reversed for the orientation of
+ // the image, as it was needed for page layout, so we need to reverse it back here.
+ adjustedDestRect = FloatRect(adjustedDestRect.x(), adjustedDestRect.y(), adjustedDestRect.height(), adjustedDestRect.width());
+ }
+ }
// Adjust the color space.
image = Image::imageWithColorSpace(image.get(), styleColorSpace);
@@ -1301,12 +1313,12 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect, RoundingMo
// we get the affine transform matrix and extract the scale.
if (m_data->m_userToDeviceTransformKnownToBeIdentity)
- return rect;
+ return roundedIntRect(rect);
CGAffineTransform deviceMatrix = CGContextGetUserSpaceToDeviceSpaceTransform(platformContext());
if (CGAffineTransformIsIdentity(deviceMatrix)) {
m_data->m_userToDeviceTransformKnownToBeIdentity = true;
- return rect;
+ return roundedIntRect(rect);
}
float deviceScaleX = sqrtf(deviceMatrix.a * deviceMatrix.a + deviceMatrix.b * deviceMatrix.b);
@@ -1628,12 +1640,42 @@ void GraphicsContext::setPlatformCompositeOperation(CompositeOperator mode)
CGContextSetBlendMode(platformContext(), target);
}
-void GraphicsContext::platformApplyDeviceScaleFactor()
+void GraphicsContext::platformApplyDeviceScaleFactor(float deviceScaleFactor)
{
// CoreGraphics expects the base CTM of a HiDPI context to have the scale factor applied to it.
// Failing to change the base level CTM will cause certain CG features, such as focus rings,
// to draw with a scale factor of 1 rather than the actual scale factor.
- wkSetBaseCTM(platformContext(), getCTM());
+ wkSetBaseCTM(platformContext(), CGAffineTransformScale(CGContextGetBaseCTM(platformContext()), deviceScaleFactor, deviceScaleFactor));
+}
+
+void GraphicsContext::platformFillEllipse(const FloatRect& ellipse)
+{
+ if (paintingDisabled())
+ return;
+
+ // CGContextFillEllipseInRect only supports solid colors.
+ if (m_state.fillGradient || m_state.fillPattern) {
+ fillEllipseAsPath(ellipse);
+ return;
+ }
+
+ CGContextRef context = platformContext();
+ CGContextFillEllipseInRect(context, ellipse);
+}
+
+void GraphicsContext::platformStrokeEllipse(const FloatRect& ellipse)
+{
+ if (paintingDisabled())
+ return;
+
+ // CGContextStrokeEllipseInRect only supports solid colors.
+ if (m_state.strokeGradient || m_state.strokePattern) {
+ strokeEllipseAsPath(ellipse);
+ return;
+ }
+
+ CGContextRef context = platformContext();
+ CGContextStrokeEllipseInRect(context, ellipse);
}
}
diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
index 646bd365d..30ece1ee3 100644
--- a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -107,17 +107,27 @@ static void releaseImageData(void*, const void* data, size_t)
fastFree(const_cast<void*>(data));
}
-ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, RenderingMode renderingMode, DeferralMode, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, float resolutionScale, ColorSpace imageColorSpace, RenderingMode renderingMode, DeferralMode, bool& success)
: m_data(size) // NOTE: The input here isn't important as ImageBufferDataCG's constructor just ignores it.
- , m_size(size)
+ , m_logicalSize(size)
+ , m_resolutionScale(resolutionScale)
{
+ float scaledWidth = ceilf(resolutionScale * size.width());
+ float scaledHeight = ceilf(resolutionScale * size.height());
+
+ // FIXME: Should we automatically use a lower resolution?
+ if (!FloatSize(scaledWidth, scaledHeight).isExpressibleAsIntSize())
+ return;
+
+ m_size = IntSize(scaledWidth, scaledHeight);
+
success = false; // Make early return mean failure.
bool accelerateRendering = renderingMode == Accelerated;
- if (size.width() <= 0 || size.height() <= 0)
+ if (m_size.width() <= 0 || m_size.height() <= 0)
return;
- Checked<int, RecordOverflow> width = size.width();
- Checked<int, RecordOverflow> height = size.height();
+ Checked<int, RecordOverflow> width = m_size.width();
+ Checked<int, RecordOverflow> height = m_size.height();
// Prevent integer overflows
m_data.m_bytesPerRow = 4 * width;
@@ -147,7 +157,7 @@ ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, Render
RetainPtr<CGContextRef> cgContext;
if (accelerateRendering) {
#if USE(IOSURFACE_CANVAS_BACKING_STORE)
- m_data.m_surface = createIOSurface(size);
+ m_data.m_surface = createIOSurface(m_size);
cgContext.adoptCF(wkIOSurfaceContextCreate(m_data.m_surface.get(), width.unsafeGet(), height.unsafeGet(), m_data.m_colorSpace));
#endif
if (!cgContext)
@@ -169,8 +179,9 @@ ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, Render
return;
m_context = adoptPtr(new GraphicsContext(cgContext.get()));
+ m_context->applyDeviceScaleFactor(m_resolutionScale);
m_context->scale(FloatSize(1, -1));
- m_context->translate(0, -height.unsafeGet());
+ m_context->translate(0, -size.height());
m_context->setIsAcceleratedContext(accelerateRendering);
#if defined(BUILDING_ON_LION)
m_data.m_lastFlushTime = currentTimeMS();
@@ -203,7 +214,16 @@ GraphicsContext* ImageBuffer::context() const
PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior) const
{
- RetainPtr<CGImageRef> image = copyNativeImage(copyBehavior);
+ RetainPtr<CGImageRef> image;
+ if (m_resolutionScale == 1)
+ image = copyNativeImage(copyBehavior);
+ else {
+ image.adoptCF(copyNativeImage(DontCopyBackingStore));
+ RetainPtr<CGContextRef> context(AdoptCF, CGBitmapContextCreate(0, logicalSize().width(), logicalSize().height(), 8, 4 * logicalSize().width(), deviceRGBColorSpaceRef(), kCGImageAlphaPremultipliedLast));
+ CGContextSetBlendMode(context.get(), kCGBlendModeCopy);
+ CGContextDrawImage(context.get(), CGRectMake(0, 0, logicalSize().width(), logicalSize().height()), image.get());
+ image = CGBitmapContextCreateImage(context.get());
+ }
if (!image)
return 0;
@@ -286,7 +306,7 @@ void ImageBuffer::clip(GraphicsContext* contextToClip, const FloatRect& rect) co
CGContextTranslateCTM(platformContextToClip, -rect.x(), -rect.y() - rect.height());
}
-PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect, CoordinateSystem coordinateSystem) const
{
if (m_context->isAcceleratedContext()) {
CGContextFlush(context()->platformContext());
@@ -294,10 +314,10 @@ PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect)
m_data.m_lastFlushTime = currentTimeMS();
#endif
}
- return m_data.getData(rect, internalSize(), m_context->isAcceleratedContext(), true);
+ return m_data.getData(rect, internalSize(), m_context->isAcceleratedContext(), true, coordinateSystem == LogicalCoordinateSystem ? m_resolutionScale : 1);
}
-PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem coordinateSystem) const
{
if (m_context->isAcceleratedContext()) {
CGContextFlush(context()->platformContext());
@@ -305,13 +325,13 @@ PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect
m_data.m_lastFlushTime = currentTimeMS();
#endif
}
- return m_data.getData(rect, internalSize(), m_context->isAcceleratedContext(), false);
+ return m_data.getData(rect, internalSize(), m_context->isAcceleratedContext(), false, coordinateSystem == LogicalCoordinateSystem ? m_resolutionScale : 1);
}
-void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
+void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem coordinateSystem)
{
if (!m_context->isAcceleratedContext()) {
- m_data.putData(source, sourceSize, sourceRect, destPoint, internalSize(), m_context->isAcceleratedContext(), multiplied == Unmultiplied);
+ m_data.putData(source, sourceSize, sourceRect, destPoint, internalSize(), m_context->isAcceleratedContext(), multiplied == Unmultiplied, coordinateSystem == LogicalCoordinateSystem ? m_resolutionScale : 1);
return;
}
@@ -322,12 +342,15 @@ void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const Int
if (!sourceCopy)
return;
- sourceCopy->m_data.putData(source, sourceSize, sourceRect, IntPoint(-sourceRect.x(), -sourceRect.y()), sourceCopy->internalSize(), sourceCopy->context()->isAcceleratedContext(), multiplied == Unmultiplied);
+ sourceCopy->m_data.putData(source, sourceSize, sourceRect, IntPoint(-sourceRect.x(), -sourceRect.y()), sourceCopy->internalSize(), sourceCopy->context()->isAcceleratedContext(), multiplied == Unmultiplied, 1);
// Set up context for using drawImage as a direct bit copy
CGContextRef destContext = context()->platformContext();
CGContextSaveGState(destContext);
- CGContextConcatCTM(destContext, AffineTransform(CGContextGetCTM(destContext)).inverse());
+ if (coordinateSystem == LogicalCoordinateSystem)
+ CGContextConcatCTM(destContext, AffineTransform(wkGetUserToBaseCTM(destContext)).inverse());
+ else
+ CGContextConcatCTM(destContext, AffineTransform(CGContextGetCTM(destContext)).inverse());
wkCGContextResetClip(destContext);
CGContextSetInterpolationQuality(destContext, kCGInterpolationNone);
CGContextSetAlpha(destContext, 1.0);
@@ -335,7 +358,7 @@ void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const Int
CGContextSetShadowWithColor(destContext, CGSizeZero, 0, 0);
// Draw the image in CG coordinate space
- IntPoint destPointInCGCoords(destPoint.x() + sourceRect.x(), internalSize().height() - (destPoint.y()+sourceRect.y()) - sourceRect.height());
+ IntPoint destPointInCGCoords(destPoint.x() + sourceRect.x(), (coordinateSystem == LogicalCoordinateSystem ? logicalSize() : internalSize()).height() - (destPoint.y() + sourceRect.y()) - sourceRect.height());
IntRect destRectInCGCoords(destPointInCGCoords, sourceCopySize);
RetainPtr<CGImageRef> sourceCopyImage(AdoptCF, sourceCopy->copyNativeImage());
CGContextDrawImage(destContext, destRectInCGCoords, sourceCopyImage.get());
@@ -378,6 +401,9 @@ static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType)
static String CGImageToDataURL(CGImageRef image, const String& mimeType, const double* quality)
{
+ if (!image)
+ return "data:,";
+
RetainPtr<CFMutableDataRef> data(AdoptCF, CFDataCreateMutable(kCFAllocatorDefault, 0));
if (!data)
return "data:,";
@@ -391,56 +417,58 @@ static String CGImageToDataURL(CGImageRef image, const String& mimeType, const d
RetainPtr<CFDictionaryRef> imageProperties = 0;
if (CFEqual(uti.get(), jpegUTI()) && quality && *quality >= 0.0 && *quality <= 1.0) {
- // Apply the compression quality to the image destination.
+ // Apply the compression quality to the JPEG image destination.
RetainPtr<CFNumberRef> compressionQuality(AdoptCF, CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, quality));
const void* key = kCGImageDestinationLossyCompressionQuality;
const void* value = compressionQuality.get();
imageProperties.adoptCF(CFDictionaryCreate(0, &key, &value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
}
- // Setting kCGImageDestinationBackgroundColor to black in imageProperties would allow saving some math in the
- // calling functions, but it doesn't seem to work.
+ // Setting kCGImageDestinationBackgroundColor to black for JPEG images in imageProperties would save some math
+ // in the calling functions, but it doesn't seem to work.
CGImageDestinationAddImage(destination.get(), image, imageProperties.get());
CGImageDestinationFinalize(destination.get());
- Vector<char> out;
- base64Encode(reinterpret_cast<const char*>(CFDataGetBytePtr(data.get())), CFDataGetLength(data.get()), out);
+ Vector<char> base64Data;
+ base64Encode(reinterpret_cast<const char*>(CFDataGetBytePtr(data.get())), CFDataGetLength(data.get()), base64Data);
- return "data:" + mimeType + ";base64," + out;
+ return "data:" + mimeType + ";base64," + base64Data;
}
-String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
+String ImageBuffer::toDataURL(const String& mimeType, const double* quality, CoordinateSystem) const
{
ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
- RetainPtr<CGImageRef> image;
+
RetainPtr<CFStringRef> uti = utiFromMIMEType(mimeType);
ASSERT(uti);
- RefPtr<ByteArray> arr;
+
+ RefPtr<Uint8ClampedArray> premultipliedData;
+ RetainPtr<CGImageRef> image;
if (CFEqual(uti.get(), jpegUTI())) {
// JPEGs don't have an alpha channel, so we have to manually composite on top of black.
- arr = getPremultipliedImageData(IntRect(IntPoint(0, 0), internalSize()));
-
- unsigned char *data = arr->data();
- for (int i = 0; i < internalSize().width() * internalSize().height(); i++)
- data[i * 4 + 3] = 255; // The image is already premultiplied, so we just need to make it opaque.
+ premultipliedData = getPremultipliedImageData(IntRect(IntPoint(0, 0), logicalSize()));
+ if (!premultipliedData)
+ return "data:,";
RetainPtr<CGDataProviderRef> dataProvider;
-
- dataProvider.adoptCF(CGDataProviderCreateWithData(0, data, 4 * internalSize().width() * internalSize().height(), 0));
-
+ dataProvider.adoptCF(CGDataProviderCreateWithData(0, premultipliedData->data(), 4 * logicalSize().width() * logicalSize().height(), 0));
if (!dataProvider)
return "data:,";
- image.adoptCF(CGImageCreate(internalSize().width(), internalSize().height(), 8, 32, 4 * internalSize().width(),
- CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrderDefault | kCGImageAlphaLast,
+ image.adoptCF(CGImageCreate(logicalSize().width(), logicalSize().height(), 8, 32, 4 * logicalSize().width(),
+ deviceRGBColorSpaceRef(), kCGBitmapByteOrderDefault | kCGImageAlphaNoneSkipLast,
dataProvider.get(), 0, false, kCGRenderingIntentDefault));
- } else
+ } else if (m_resolutionScale == 1)
image.adoptCF(copyNativeImage(CopyBackingStore));
-
- if (!image)
- return "data:,";
+ else {
+ image.adoptCF(copyNativeImage(DontCopyBackingStore));
+ RetainPtr<CGContextRef> context(AdoptCF, CGBitmapContextCreate(0, logicalSize().width(), logicalSize().height(), 8, 4 * logicalSize().width(), deviceRGBColorSpaceRef(), kCGImageAlphaPremultipliedLast));
+ CGContextSetBlendMode(context.get(), kCGBlendModeCopy);
+ CGContextDrawImage(context.get(), CGRectMake(0, 0, logicalSize().width(), logicalSize().height()), image.get());
+ image.adoptCF(CGBitmapContextCreateImage(context.get()));
+ }
return CGImageToDataURL(image.get(), mimeType, quality);
}
@@ -448,14 +476,13 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
String ImageDataToDataURL(const ImageData& source, const String& mimeType, const double* quality)
{
ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
-
- RetainPtr<CGImageRef> image;
- RetainPtr<CGDataProviderRef> dataProvider;
- unsigned char* data = source.data()->data()->data();
RetainPtr<CFStringRef> uti = utiFromMIMEType(mimeType);
ASSERT(uti);
+
+ unsigned char* data = source.data()->data();
Vector<uint8_t> dataVector;
+
if (CFEqual(uti.get(), jpegUTI())) {
// JPEGs don't have an alpha channel, so we have to manually composite on top of black.
dataVector.resize(4 * source.width() * source.height());
@@ -478,21 +505,18 @@ String ImageDataToDataURL(const ImageData& source, const String& mimeType, const
data = out;
}
-
- dataProvider.adoptCF(CGDataProviderCreateWithData(0, data,
- 4 * source.width() * source.height(), 0));
-
+
+ RetainPtr<CGDataProviderRef> dataProvider;
+ dataProvider.adoptCF(CGDataProviderCreateWithData(0, data, 4 * source.width() * source.height(), 0));
if (!dataProvider)
return "data:,";
+ RetainPtr<CGImageRef> image;
image.adoptCF(CGImageCreate(source.width(), source.height(), 8, 32, 4 * source.width(),
- CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrderDefault | kCGImageAlphaLast,
+ deviceRGBColorSpaceRef(), kCGBitmapByteOrderDefault | kCGImageAlphaLast,
dataProvider.get(), 0, false, kCGRenderingIntentDefault));
-
-
- if (!image)
- return "data:,";
return CGImageToDataURL(image.get(), mimeType, quality);
}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.cpp b/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.cpp
index e878e3874..5e3ae78a8 100644
--- a/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "ImageBufferData.h"
+#include <CoreGraphics/CoreGraphics.h>
#include <wtf/Assertions.h>
#if USE(ACCELERATE)
@@ -37,6 +38,8 @@
#include <dispatch/dispatch.h>
#endif
+using namespace std;
+
#if USE(ACCELERATE)
struct ScanlineData {
vImagePixelCount scanlineWidth;
@@ -113,41 +116,53 @@ static void premultitplyScanline(void* data, size_t tileNumber)
#endif // USE(IOSURFACE_CANVAS_BACKING_STORE)
#endif // USE(ACCELERATE)
-PassRefPtr<ByteArray> ImageBufferData::getData(const IntRect& rect, const IntSize& size, bool accelerateRendering, bool unmultiplied) const
+PassRefPtr<Uint8ClampedArray> ImageBufferData::getData(const IntRect& rect, const IntSize& size, bool accelerateRendering, bool unmultiplied, float resolutionScale) const
{
- float area = 4.0f * rect.width() * rect.height();
- if (area > static_cast<float>(std::numeric_limits<int>::max()))
+ Checked<unsigned, RecordOverflow> area = 4;
+ area *= rect.width();
+ area *= rect.height();
+ if (area.hasOverflowed())
return 0;
- RefPtr<ByteArray> result = ByteArray::create(rect.width() * rect.height() * 4);
+ RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::createUninitialized(area.unsafeGet());
unsigned char* data = result->data();
- if (rect.x() < 0 || rect.y() < 0 || rect.maxX() > size.width() || rect.maxY() > size.height())
- memset(data, 0, result->length());
+ Checked<int> endx = rect.maxX();
+ endx *= ceilf(resolutionScale);
+ Checked<int> endy = rect.maxY();
+ endy *= resolutionScale;
+ if (rect.x() < 0 || rect.y() < 0 || endx.unsafeGet() > size.width() || endy.unsafeGet() > size.height())
+ result->zeroFill();
int originx = rect.x();
int destx = 0;
+ int destw = rect.width();
if (originx < 0) {
+ destw += originx;
destx = -originx;
originx = 0;
}
- int endx = rect.maxX();
- if (endx > size.width())
+ destw = min<int>(destw, ceilf(size.width() / resolutionScale) - originx);
+ originx *= resolutionScale;
+ if (endx.unsafeGet() > size.width())
endx = size.width();
- int width = endx - originx;
+ Checked<int> width = endx - originx;
int originy = rect.y();
int desty = 0;
+ int desth = rect.height();
if (originy < 0) {
+ desth += originy;
desty = -originy;
originy = 0;
}
- int endy = rect.maxY();
- if (endy > size.height())
+ desth = min<int>(desth, ceilf(size.height() / resolutionScale) - originy);
+ originy *= resolutionScale;
+ if (endy.unsafeGet() > size.height())
endy = size.height();
- int height = endy - originy;
+ Checked<int> height = endy - originy;
- if (width <= 0 || height <= 0)
+ if (width.unsafeGet() <= 0 || height.unsafeGet() <= 0)
return result.release();
unsigned destBytesPerRow = 4 * rect.width();
@@ -163,24 +178,48 @@ PassRefPtr<ByteArray> ImageBufferData::getData(const IntRect& rect, const IntSiz
#if USE(ACCELERATE)
if (unmultiplied && haveVImageRoundingErrorFix()) {
vImage_Buffer src;
- src.height = height;
- src.width = width;
+ src.height = height.unsafeGet();
+ src.width = width.unsafeGet();
src.rowBytes = srcBytesPerRow;
src.data = srcRows;
vImage_Buffer dst;
- dst.height = height;
- dst.width = width;
+ dst.height = desth;
+ dst.width = destw;
dst.rowBytes = destBytesPerRow;
dst.data = destRows;
-
+
+ if (resolutionScale != 1) {
+ vImage_AffineTransform scaleTransform = { 1 / resolutionScale, 0, 0, 1 / resolutionScale, 0, 0 }; // FIXME: Add subpixel translation.
+ Pixel_8888 backgroundColor;
+ vImageAffineWarp_ARGB8888(&src, &dst, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend);
+ // The unpremultiplying will be done in-place.
+ src = dst;
+ }
+
vImageUnpremultiplyData_RGBA8888(&src, &dst, kvImageNoFlags);
return result.release();
}
#endif
+ if (resolutionScale != 1) {
+ RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width.unsafeGet(), height.unsafeGet(), 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast));
+ RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get()));
+ RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast));
+ CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy);
+ CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width.unsafeGet() / resolutionScale, height.unsafeGet() / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation.
+ if (!unmultiplied)
+ return result.release();
+
+ srcRows = destRows;
+ srcBytesPerRow = destBytesPerRow;
+ width = destw;
+ height = desth;
+ }
if (unmultiplied) {
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; x++) {
+ if ((width * 4).hasOverflowed())
+ CRASH();
+ for (int y = 0; y < height.unsafeGet(); ++y) {
+ for (int x = 0; x < width.unsafeGet(); x++) {
int basex = x * 4;
unsigned char alpha = srcRows[basex + 3];
if (alpha) {
@@ -195,8 +234,8 @@ PassRefPtr<ByteArray> ImageBufferData::getData(const IntRect& rect, const IntSiz
destRows += destBytesPerRow;
}
} else {
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width * 4; x += 4)
+ for (int y = 0; y < height.unsafeGet(); ++y) {
+ for (int x = 0; x < (width * 4).unsafeGet(); x += 4)
reinterpret_cast<uint32_t*>(destRows + x)[0] = reinterpret_cast<uint32_t*>(srcRows + x)[0];
srcRows += srcBytesPerRow;
destRows += destBytesPerRow;
@@ -210,47 +249,78 @@ PassRefPtr<ByteArray> ImageBufferData::getData(const IntRect& rect, const IntSiz
srcRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + originy * srcBytesPerRow + originx * 4;
#if USE(ACCELERATE)
+ vImage_Buffer src;
+ src.height = height.unsafeGet();
+ src.width = width.unsafeGet();
+ src.rowBytes = srcBytesPerRow;
+ src.data = srcRows;
+
+ vImage_Buffer dest;
+ dest.height = desth;
+ dest.width = destw;
+ dest.rowBytes = destBytesPerRow;
+ dest.data = destRows;
+
+ if (resolutionScale != 1) {
+ vImage_AffineTransform scaleTransform = { 1 / resolutionScale, 0, 0, 1 / resolutionScale, 0, 0 }; // FIXME: Add subpixel translation.
+ Pixel_8888 backgroundColor;
+ vImageAffineWarp_ARGB8888(&src, &dest, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend);
+ // The unpremultiplying and channel-swapping will be done in-place.
+ if (unmultiplied) {
+ srcRows = destRows;
+ width = destw;
+ height = desth;
+ srcBytesPerRow = destBytesPerRow;
+ } else
+ src = dest;
+ }
+
if (unmultiplied) {
ScanlineData scanlineData;
- scanlineData.scanlineWidth = width;
+ scanlineData.scanlineWidth = width.unsafeGet();
scanlineData.srcData = srcRows;
scanlineData.srcRowBytes = srcBytesPerRow;
scanlineData.destData = destRows;
scanlineData.destRowBytes = destBytesPerRow;
- dispatch_apply_f(height, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &scanlineData, unpremultitplyScanline);
+ dispatch_apply_f(height.unsafeGet(), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &scanlineData, unpremultitplyScanline);
} else {
- vImage_Buffer src;
- src.height = height;
- src.width = width;
- src.rowBytes = srcBytesPerRow;
- src.data = srcRows;
-
- vImage_Buffer dest;
- dest.height = height;
- dest.width = width;
- dest.rowBytes = destBytesPerRow;
- dest.data = destRows;
-
// Swap pixel channels from BGRA to RGBA.
const uint8_t map[4] = { 2, 1, 0, 3 };
vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags);
}
#else
+ if (resolutionScale != 1) {
+ RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width.unsafeGet(), height.unsafeGet(), 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast));
+ RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get()));
+ RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast));
+ CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy);
+ CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width.unsafeGet() / resolutionScale, height.unsafeGet() / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation.
+
+ srcRows = destRows;
+ srcBytesPerRow = destBytesPerRow;
+ width = destw;
+ height = desth;
+ }
+
+ if ((width * 4).hasOverflowed())
+ CRASH();
+
if (unmultiplied) {
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; x++) {
+ for (int y = 0; y < height.unsafeGet(); ++y) {
+ for (int x = 0; x < width.unsafeGet(); x++) {
int basex = x * 4;
+ unsigned char b = srcRows[basex];
unsigned char alpha = srcRows[basex + 3];
if (alpha) {
destRows[basex] = (srcRows[basex + 2] * 255) / alpha;
destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha;
- destRows[basex + 2] = (srcRows[basex] * 255) / alpha;
+ destRows[basex + 2] = (b * 255) / alpha;
destRows[basex + 3] = alpha;
} else {
destRows[basex] = srcRows[basex + 2];
destRows[basex + 1] = srcRows[basex + 1];
- destRows[basex + 2] = srcRows[basex];
+ destRows[basex + 2] = b;
destRows[basex + 3] = srcRows[basex + 3];
}
}
@@ -258,12 +328,13 @@ PassRefPtr<ByteArray> ImageBufferData::getData(const IntRect& rect, const IntSiz
destRows += destBytesPerRow;
}
} else {
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; x++) {
+ for (int y = 0; y < height.unsafeGet(); ++y) {
+ for (int x = 0; x < width.unsafeGet(); x++) {
int basex = x * 4;
+ unsigned char b = srcRows[basex];
destRows[basex] = srcRows[basex + 2];
destRows[basex + 1] = srcRows[basex + 1];
- destRows[basex + 2] = srcRows[basex];
+ destRows[basex + 2] = b;
destRows[basex + 3] = srcRows[basex + 3];
}
srcRows += srcBytesPerRow;
@@ -280,66 +351,96 @@ PassRefPtr<ByteArray> ImageBufferData::getData(const IntRect& rect, const IntSiz
return result.release();
}
-void ImageBufferData::putData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize& size, bool accelerateRendering, bool unmultiplied)
+void ImageBufferData::putData(Uint8ClampedArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize& size, bool accelerateRendering, bool unmultiplied, float resolutionScale)
{
ASSERT(sourceRect.width() > 0);
ASSERT(sourceRect.height() > 0);
- int originx = sourceRect.x();
- int destx = destPoint.x() + sourceRect.x();
- ASSERT(destx >= 0);
- ASSERT(destx < size.width());
- ASSERT(originx >= 0);
- ASSERT(originx <= sourceRect.maxX());
-
- int endx = destPoint.x() + sourceRect.maxX();
- ASSERT(endx <= size.width());
+ Checked<int> originx = sourceRect.x();
+ Checked<int> destx = (Checked<int>(destPoint.x()) + sourceRect.x());
+ destx *= resolutionScale;
+ ASSERT(destx.unsafeGet() >= 0);
+ ASSERT(destx.unsafeGet() < size.width());
+ ASSERT(originx.unsafeGet() >= 0);
+ ASSERT(originx.unsafeGet() <= sourceRect.maxX());
- int width = endx - destx;
+ Checked<int> endx = (Checked<int>(destPoint.x()) + sourceRect.maxX());
+ endx *= resolutionScale;
+ ASSERT(endx.unsafeGet() <= size.width());
- int originy = sourceRect.y();
- int desty = destPoint.y() + sourceRect.y();
- ASSERT(desty >= 0);
- ASSERT(desty < size.height());
- ASSERT(originy >= 0);
- ASSERT(originy <= sourceRect.maxY());
+ Checked<int> width = sourceRect.width();
+ Checked<int> destw = endx - destx;
+
+ Checked<int> originy = sourceRect.y();
+ Checked<int> desty = (Checked<int>(destPoint.y()) + sourceRect.y());
+ desty *= resolutionScale;
+ ASSERT(desty.unsafeGet() >= 0);
+ ASSERT(desty.unsafeGet() < size.height());
+ ASSERT(originy.unsafeGet() >= 0);
+ ASSERT(originy.unsafeGet() <= sourceRect.maxY());
- int endy = destPoint.y() + sourceRect.maxY();
- ASSERT(endy <= size.height());
- int height = endy - desty;
+ Checked<int> endy = (Checked<int>(destPoint.y()) + sourceRect.maxY());
+ endy *= resolutionScale;
+ ASSERT(endy.unsafeGet() <= size.height());
+
+ Checked<int> height = sourceRect.height();
+ Checked<int> desth = endy - desty;
if (width <= 0 || height <= 0)
return;
unsigned srcBytesPerRow = 4 * sourceSize.width();
- unsigned char* srcRows = source->data() + originy * srcBytesPerRow + originx * 4;
+ unsigned char* srcRows = source->data() + (originy * srcBytesPerRow + originx * 4).unsafeGet();
unsigned destBytesPerRow;
unsigned char* destRows;
if (!accelerateRendering) {
destBytesPerRow = 4 * size.width();
- destRows = reinterpret_cast<unsigned char*>(m_data) + desty * destBytesPerRow + destx * 4;
+ destRows = reinterpret_cast<unsigned char*>(m_data) + (desty * destBytesPerRow + destx * 4).unsafeGet();
-#if USE(ACCELERATE)
+#if USE(ACCELERATE)
if (haveVImageRoundingErrorFix() && unmultiplied) {
vImage_Buffer src;
- src.height = height;
- src.width = width;
+ src.height = height.unsafeGet();
+ src.width = width.unsafeGet();
src.rowBytes = srcBytesPerRow;
src.data = srcRows;
vImage_Buffer dst;
- dst.height = height;
- dst.width = width;
+ dst.height = desth.unsafeGet();
+ dst.width = destw.unsafeGet();
dst.rowBytes = destBytesPerRow;
dst.data = destRows;
-
+
+ if (resolutionScale != 1) {
+ vImage_AffineTransform scaleTransform = { resolutionScale, 0, 0, resolutionScale, 0, 0 }; // FIXME: Add subpixel translation.
+ Pixel_8888 backgroundColor;
+ vImageAffineWarp_ARGB8888(&src, &dst, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend);
+ // The premultiplying will be done in-place.
+ src = dst;
+ }
+
vImagePremultiplyData_RGBA8888(&src, &dst, kvImageNoFlags);
return;
}
#endif
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; x++) {
+ if (resolutionScale != 1) {
+ RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width.unsafeGet(), height.unsafeGet(), 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast));
+ RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get()));
+ RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw.unsafeGet(), desth.unsafeGet(), 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast));
+ CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy);
+ CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width.unsafeGet() / resolutionScale, height.unsafeGet() / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation.
+ if (!unmultiplied)
+ return;
+
+ srcRows = destRows;
+ srcBytesPerRow = destBytesPerRow;
+ width = destw;
+ height = desth;
+ }
+
+ for (int y = 0; y < height.unsafeGet(); ++y) {
+ for (int x = 0; x < width.unsafeGet(); x++) {
int basex = x * 4;
unsigned char alpha = srcRows[basex + 3];
if (unmultiplied && alpha != 255) {
@@ -358,49 +459,77 @@ void ImageBufferData::putData(ByteArray*& source, const IntSize& sourceSize, con
IOSurfaceRef surface = m_surface.get();
IOSurfaceLock(surface, 0, 0);
destBytesPerRow = IOSurfaceGetBytesPerRow(surface);
- destRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + desty * destBytesPerRow + destx * 4;
+ destRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + (desty * destBytesPerRow + destx * 4).unsafeGet();
#if USE(ACCELERATE)
+ vImage_Buffer src;
+ src.height = height.unsafeGet();
+ src.width = width.unsafeGet();
+ src.rowBytes = srcBytesPerRow;
+ src.data = srcRows;
+
+ vImage_Buffer dest;
+ dest.height = desth.unsafeGet();
+ dest.width = destw.unsafeGet();
+ dest.rowBytes = destBytesPerRow;
+ dest.data = destRows;
+
+ if (resolutionScale != 1) {
+ vImage_AffineTransform scaleTransform = { resolutionScale, 0, 0, resolutionScale, 0, 0 }; // FIXME: Add subpixel translation.
+ Pixel_8888 backgroundColor;
+ vImageAffineWarp_ARGB8888(&src, &dest, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend);
+ // The unpremultiplying and channel-swapping will be done in-place.
+ if (unmultiplied) {
+ srcRows = destRows;
+ width = destw;
+ height = desth;
+ srcBytesPerRow = destBytesPerRow;
+ } else
+ src = dest;
+ }
+
if (unmultiplied) {
ScanlineData scanlineData;
- scanlineData.scanlineWidth = width;
+ scanlineData.scanlineWidth = width.unsafeGet();
scanlineData.srcData = srcRows;
scanlineData.srcRowBytes = srcBytesPerRow;
scanlineData.destData = destRows;
scanlineData.destRowBytes = destBytesPerRow;
- dispatch_apply_f(height, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &scanlineData, premultitplyScanline);
+ dispatch_apply_f(height.unsafeGet(), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &scanlineData, premultitplyScanline);
} else {
- vImage_Buffer src;
- src.height = height;
- src.width = width;
- src.rowBytes = srcBytesPerRow;
- src.data = srcRows;
-
- vImage_Buffer dest;
- dest.height = height;
- dest.width = width;
- dest.rowBytes = destBytesPerRow;
- dest.data = destRows;
-
// Swap pixel channels from RGBA to BGRA.
const uint8_t map[4] = { 2, 1, 0, 3 };
vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags);
}
#else
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; x++) {
+ if (resolutionScale != 1) {
+ RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width.unsafeGet(), height.unsafeGet(), 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast));
+ RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get()));
+ RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw.unsafeGet(), desth.unsafeGet(), 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast));
+ CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy);
+ CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width.unsafeGet() / resolutionScale, height.unsafeGet() / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation.
+
+ srcRows = destRows;
+ srcBytesPerRow = destBytesPerRow;
+ width = destw;
+ height = desth;
+ }
+
+ for (int y = 0; y < height.unsafeGet(); ++y) {
+ for (int x = 0; x < width.unsafeGet(); x++) {
int basex = x * 4;
+ unsigned char b = srcRows[basex];
unsigned char alpha = srcRows[basex + 3];
if (unmultiplied && alpha != 255) {
destRows[basex] = (srcRows[basex + 2] * alpha + 254) / 255;
destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255;
- destRows[basex + 2] = (srcRows[basex] * alpha + 254) / 255;
+ destRows[basex + 2] = (b * alpha + 254) / 255;
destRows[basex + 3] = alpha;
} else {
destRows[basex] = srcRows[basex + 2];
destRows[basex + 1] = srcRows[basex + 1];
- destRows[basex + 2] = srcRows[basex];
+ destRows[basex + 2] = b;
destRows[basex + 3] = alpha;
}
}
diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h b/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h
index a148de6c2..6233c6c2c 100644
--- a/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h
+++ b/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h
@@ -25,10 +25,10 @@
*/
#include "Image.h"
-#include <wtf/ByteArray.h>
#include <wtf/CheckedArithmetic.h>
#include <wtf/RefPtr.h>
#include <wtf/RetainPtr.h>
+#include <wtf/Uint8ClampedArray.h>
#if (PLATFORM(MAC) && USE(CA) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD))
#define WTF_USE_IOSURFACE_CANVAS_BACKING_STORE 1
@@ -58,8 +58,8 @@ public:
mutable double m_lastFlushTime;
#endif
- PassRefPtr<ByteArray> getData(const IntRect& rect, const IntSize& size, bool accelerateRendering, bool unmultiplied) const;
- void putData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize& size, bool accelerateRendering, bool unmultiplied);
+ PassRefPtr<Uint8ClampedArray> getData(const IntRect&, const IntSize&, bool accelerateRendering, bool unmultiplied, float resolutionScale) const;
+ void putData(Uint8ClampedArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize&, bool accelerateRendering, bool unmultiplied, float resolutionScale);
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/cg/ImageCG.cpp b/Source/WebCore/platform/graphics/cg/ImageCG.cpp
index d81c7804b..559ba1f8e 100644
--- a/Source/WebCore/platform/graphics/cg/ImageCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageCG.cpp
@@ -54,6 +54,8 @@ bool FrameData::clear(bool clearMetadata)
if (clearMetadata)
m_haveMetadata = false;
+ m_orientation = DefaultImageOrientation;
+
if (m_frame) {
CGImageRelease(m_frame);
m_frame = 0;
@@ -95,6 +97,7 @@ BitmapImage::BitmapImage(CGImageRef cgImage, ImageObserver* observer)
m_frames[0].m_frame = cgImage;
m_frames[0].m_hasAlpha = true;
m_frames[0].m_haveMetadata = true;
+
checkForSolidColor();
}
@@ -182,7 +185,12 @@ RetainPtr<CFArrayRef> BitmapImage::getCGImageArray()
return RetainPtr<CFArrayRef>(AdoptCF, array);
}
-void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp)
+void BitmapImage::draw(GraphicsContext* ctx, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator op)
+{
+ draw(ctx, dstRect, srcRect, styleColorSpace, op, DoNotRespectImageOrientation);
+}
+
+void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp, RespectImageOrientationEnum shouldRespectImageOrientation)
{
startAnimation();
@@ -196,8 +204,12 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const F
}
FloatSize selfSize = currentFrameSize();
+ ImageOrientation orientation = DefaultImageOrientation;
+
+ if (shouldRespectImageOrientation == RespectImageOrientation)
+ orientation = frameOrientationAtIndex(m_currentFrame);
- ctxt->drawNativeImage(image.get(), selfSize, styleColorSpace, destRect, srcRect, compositeOp);
+ ctxt->drawNativeImage(image.get(), selfSize, styleColorSpace, destRect, srcRect, compositeOp, orientation);
if (imageObserver())
imageObserver()->didDraw(this);
diff --git a/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp
index 35b5bfe89..43353650c 100644
--- a/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp
@@ -29,6 +29,7 @@
#if USE(CG)
#include "ImageSourceCG.h"
+#include "ImageOrientation.h"
#include "IntPoint.h"
#include "IntSize.h"
#include "MIMETypeRegistry.h"
@@ -108,15 +109,25 @@ void ImageSource::clear(bool destroyAllFrames, size_t, SharedBuffer* data, bool
setData(data, allDataReceived);
}
-static CFDictionaryRef imageSourceOptions(ImageSource::ShouldSkipMetaData skipMetaData)
+static CFDictionaryRef imageSourceOptions(ImageSource::ShouldSkipMetadata skipMetadata)
{
static CFDictionaryRef options;
if (!options) {
const unsigned numOptions = 3;
- const CFBooleanRef imageSourceSkipMetaData = (skipMetaData == ImageSource::SkipMetaData) ? kCFBooleanTrue : kCFBooleanFalse;
+
+#if defined(BUILDING_ON_LION) || defined(BUILDING_ON_SNOW_LEOPARD)
+ // Lion and Snow Leopard only return Orientation when kCGImageSourceSkipMetaData is false,
+ // and incorrectly return cached metadata if an image is queried once with kCGImageSourceSkipMetaData true
+ // and then subsequently with kCGImageSourceSkipMetaData false.
+ // <rdar://problem/11148192>
+ UNUSED_PARAM(skipMetadata);
+ const CFBooleanRef imageSourceSkipMetadata = kCFBooleanFalse;
+#else
+ const CFBooleanRef imageSourceSkipMetadata = (skipMetadata == ImageSource::SkipMetadata) ? kCFBooleanTrue : kCFBooleanFalse;
+#endif
const void* keys[numOptions] = { kCGImageSourceShouldCache, kCGImageSourceShouldPreferRGB32, kCGImageSourceSkipMetaData };
- const void* values[numOptions] = { kCFBooleanTrue, kCFBooleanTrue, imageSourceSkipMetaData };
+ const void* values[numOptions] = { kCFBooleanTrue, kCFBooleanTrue, imageSourceSkipMetadata };
options = CFDictionaryCreate(NULL, keys, values, numOptions,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
}
@@ -174,7 +185,7 @@ bool ImageSource::isSizeAvailable()
// Ragnaros yells: TOO SOON! You have awakened me TOO SOON, Executus!
if (imageSourceStatus >= kCGImageStatusIncomplete) {
- RetainPtr<CFDictionaryRef> image0Properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions(SkipMetaData)));
+ RetainPtr<CFDictionaryRef> image0Properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions(SkipMetadata)));
if (image0Properties) {
CFNumberRef widthNumber = (CFNumberRef)CFDictionaryGetValue(image0Properties.get(), kCGImagePropertyPixelWidth);
CFNumberRef heightNumber = (CFNumberRef)CFDictionaryGetValue(image0Properties.get(), kCGImagePropertyPixelHeight);
@@ -185,31 +196,50 @@ bool ImageSource::isSizeAvailable()
return result;
}
-IntSize ImageSource::frameSizeAtIndex(size_t index) const
+IntSize ImageSource::frameSizeAtIndex(size_t index, RespectImageOrientationEnum shouldRespectOrientation) const
{
- IntSize result;
- RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions(SkipMetaData)));
- if (properties) {
- int w = 0, h = 0;
- CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelWidth);
- if (num)
- CFNumberGetValue(num, kCFNumberIntType, &w);
- num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelHeight);
- if (num)
- CFNumberGetValue(num, kCFNumberIntType, &h);
- result = IntSize(w, h);
- }
- return result;
+ RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions(SkipMetadata)));
+
+ if (!properties)
+ return IntSize();
+
+ int w = 0, h = 0;
+ CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelWidth);
+ if (num)
+ CFNumberGetValue(num, kCFNumberIntType, &w);
+ num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelHeight);
+ if (num)
+ CFNumberGetValue(num, kCFNumberIntType, &h);
+
+ if ((shouldRespectOrientation == RespectImageOrientation) && orientationAtIndex(index).usesWidthAsHeight())
+ return IntSize(h, w);
+
+ return IntSize(w, h);
+}
+
+ImageOrientation ImageSource::orientationAtIndex(size_t index) const
+{
+ RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions(SkipMetadata)));
+ if (!properties)
+ return DefaultImageOrientation;
+
+ CFNumberRef orientationProperty = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyOrientation);
+ if (!orientationProperty)
+ return DefaultImageOrientation;
+
+ int exifValue;
+ CFNumberGetValue(orientationProperty, kCFNumberIntType, &exifValue);
+ return ImageOrientation::fromEXIFValue(exifValue);
}
-IntSize ImageSource::size() const
+IntSize ImageSource::size(RespectImageOrientationEnum shouldRespectOrientation) const
{
- return frameSizeAtIndex(0);
+ return frameSizeAtIndex(0, shouldRespectOrientation);
}
bool ImageSource::getHotSpot(IntPoint& hotSpot) const
{
- RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions(SkipMetaData)));
+ RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions(SkipMetadata)));
if (!properties)
return false;
@@ -246,7 +276,7 @@ int ImageSource::repetitionCount()
if (!initialized())
return result;
- RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyProperties(m_decoder, imageSourceOptions(SkipMetaData)));
+ RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyProperties(m_decoder, imageSourceOptions(SkipMetadata)));
if (properties) {
CFDictionaryRef gifProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary);
if (gifProperties) {
@@ -274,7 +304,7 @@ CGImageRef ImageSource::createFrameAtIndex(size_t index)
if (!initialized())
return 0;
- RetainPtr<CGImageRef> image(AdoptCF, CGImageSourceCreateImageAtIndex(m_decoder, index, imageSourceOptions(SkipMetaData)));
+ RetainPtr<CGImageRef> image(AdoptCF, CGImageSourceCreateImageAtIndex(m_decoder, index, imageSourceOptions(SkipMetadata)));
CFStringRef imageUTI = CGImageSourceGetType(m_decoder);
static const CFStringRef xbmUTI = CFSTR("public.xbitmap-image");
if (!imageUTI || !CFEqual(imageUTI, xbmUTI))
@@ -315,7 +345,7 @@ float ImageSource::frameDurationAtIndex(size_t index)
return 0;
float duration = 0;
- RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions(SkipMetaData)));
+ RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions(SkipMetadata)));
if (properties) {
CFDictionaryRef typeProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary);
if (typeProperties) {
diff --git a/Source/WebCore/platform/graphics/cg/ImageSourceCGWin.cpp b/Source/WebCore/platform/graphics/cg/ImageSourceCGWin.cpp
index ef69e5e32..24949b93a 100644
--- a/Source/WebCore/platform/graphics/cg/ImageSourceCGWin.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageSourceCGWin.cpp
@@ -26,8 +26,8 @@
#include "config.h"
#include "ImageSourceCG.h"
-#include "StdLibExtras.h"
#include <wtf/HashMap.h>
+#include <wtf/StdLibExtras.h>
#include <wtf/text/StringHash.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/graphics/cg/PathCG.cpp b/Source/WebCore/platform/graphics/cg/PathCG.cpp
index 01f7ffe41..6cc937836 100644
--- a/Source/WebCore/platform/graphics/cg/PathCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/PathCG.cpp
@@ -39,6 +39,14 @@
#include <wtf/MathExtras.h>
#include <wtf/RetainPtr.h>
+#if PLATFORM(MAC) || PLATFORM(CHROMIUM)
+#include "WebCoreSystemInterface.h"
+#endif
+
+#if PLATFORM(WIN)
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
+#endif
+
namespace WebCore {
static size_t putBytesNowhere(void*, const void*, size_t count)
@@ -226,6 +234,21 @@ void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
CGPathAddArcToPoint(m_path, 0, p1.x(), p1.y(), p2.x(), p2.y(), radius);
}
+void Path::platformAddPathForRoundedRect(const FloatRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius)
+{
+#if PLATFORM(MAC) && (!defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD))
+ bool equalWidths = (topLeftRadius.width() == topRightRadius.width() && topRightRadius.width() == bottomLeftRadius.width() && bottomLeftRadius.width() == bottomRightRadius.width());
+ bool equalHeights = (topLeftRadius.height() == bottomLeftRadius.height() && bottomLeftRadius.height() == topRightRadius.height() && topRightRadius.height() == bottomRightRadius.height());
+
+ if (equalWidths && equalHeights) {
+ wkCGPathAddRoundedRect(m_path, 0, rect, topLeftRadius.width(), topLeftRadius.height());
+ return;
+ }
+#endif
+
+ addBeziersForRoundedRect(rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
+}
+
void Path::closeSubpath()
{
CGPathCloseSubpath(m_path);
diff --git a/Source/WebCore/platform/graphics/cg/PatternCG.cpp b/Source/WebCore/platform/graphics/cg/PatternCG.cpp
index 022e09486..ae9a01b36 100644
--- a/Source/WebCore/platform/graphics/cg/PatternCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/PatternCG.cpp
@@ -44,7 +44,7 @@ namespace WebCore {
static void patternCallback(void* info, CGContextRef context)
{
- CGImageRef platformImage = static_cast<Image*>(info)->getCGImageRef();
+ CGImageRef platformImage = static_cast<CGImageRef>(info);
if (!platformImage)
return;
@@ -55,7 +55,7 @@ static void patternCallback(void* info, CGContextRef context)
static void patternReleaseOnMainThreadCallback(void* info)
{
- static_cast<Image*>(info)->deref();
+ CGImageRelease(static_cast<CGImageRef>(info));
}
static void patternReleaseCallback(void* info)
@@ -84,12 +84,11 @@ CGPatternRef Pattern::createPlatformPattern(const AffineTransform& userSpaceTran
CGFloat xStep = m_repeatX ? tileRect.width() : (1 << 22);
CGFloat yStep = m_repeatY ? tileRect.height() : (1 << 22);
- // The pattern will release the tile when it's done rendering in patternReleaseCallback
- tileImage()->ref();
+ // The pattern will release the CGImageRef when it's done rendering in patternReleaseCallback
+ CGImageRef platformImage = CGImageRetain(tileImage()->getCGImageRef());
const CGPatternCallbacks patternCallbacks = { 0, patternCallback, patternReleaseCallback };
- return CGPatternCreate(tileImage(), tileRect, patternTransform, xStep, yStep,
- kCGPatternTilingConstantSpacing, TRUE, &patternCallbacks);
+ return CGPatternCreate(platformImage, tileRect, patternTransform, xStep, yStep, kCGPatternTilingConstantSpacing, TRUE, &patternCallbacks);
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp
index 00a3e463b..f55c06216 100644
--- a/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp
+++ b/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp
@@ -78,7 +78,7 @@ LayerTextureUpdater::SampledTexelFormat BitmapCanvasLayerTextureUpdater::sampled
LayerTextureUpdater::SampledTexelFormatRGBA : LayerTextureUpdater::SampledTexelFormatBGRA;
}
-void BitmapCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, int borderTexels, float contentsScale, IntRect* resultingOpaqueRect)
+void BitmapCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, int borderTexels, float contentsScale, IntRect& resultingOpaqueRect)
{
m_texSubImage.setSubImageSize(tileSize);
@@ -92,10 +92,7 @@ void BitmapCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect
borderTexels ? PlatformCanvas::Painter::GrayscaleText : PlatformCanvas::Painter::SubpixelText;
PlatformCanvas::Painter canvasPainter(&m_canvas, textOption);
canvasPainter.skiaContext()->setTrackOpaqueRegion(!layerIsOpaque);
- paintContents(*canvasPainter.context(), *canvasPainter.skiaContext(), contentRect, contentsScale);
-
- if (!layerIsOpaque)
- *resultingOpaqueRect = canvasPainter.skiaContext()->opaqueRegion().asRect();
+ paintContents(*canvasPainter.context(), *canvasPainter.skiaContext(), contentRect, contentsScale, resultingOpaqueRect);
}
void BitmapCanvasLayerTextureUpdater::updateTextureRect(GraphicsContext3D* context, TextureAllocator* allocator, ManagedTexture* texture, const IntRect& sourceRect, const IntRect& destRect)
diff --git a/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.h
index 4e162295b..04cc41a24 100644
--- a/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.h
+++ b/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.h
@@ -60,7 +60,7 @@ public:
virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(TextureManager*);
virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat);
- virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, int borderTexels, float contentsScale, IntRect* resultingOpaqueRect);
+ virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, int borderTexels, float contentsScale, IntRect& resultingOpaqueRect);
void updateTextureRect(GraphicsContext3D*, TextureAllocator*, ManagedTexture*, const IntRect& sourceRect, const IntRect& destRect);
virtual void setOpaque(bool);
diff --git a/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp
index 426c6568a..e9c2619b0 100644
--- a/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp
+++ b/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp
@@ -89,7 +89,7 @@ LayerTextureUpdater::SampledTexelFormat BitmapSkPictureCanvasLayerTextureUpdater
LayerTextureUpdater::SampledTexelFormatRGBA : LayerTextureUpdater::SampledTexelFormatBGRA;
}
-void BitmapSkPictureCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, int borderTexels, float contentsScale, IntRect* resultingOpaqueRect)
+void BitmapSkPictureCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, int borderTexels, float contentsScale, IntRect& resultingOpaqueRect)
{
m_texSubImage.setSubImageSize(tileSize);
SkPictureCanvasLayerTextureUpdater::prepareToUpdate(contentRect, tileSize, borderTexels, contentsScale, resultingOpaqueRect);
diff --git a/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h
index 0aeae0cd4..bb1431004 100644
--- a/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h
+++ b/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h
@@ -58,7 +58,7 @@ public:
virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(TextureManager*);
virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat);
- virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, int borderTexels, float contentsScale, IntRect* resultingOpaqueRect);
+ virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, int borderTexels, float contentsScale, IntRect& resultingOpaqueRect);
void paintContentsRect(SkCanvas*, const IntRect& sourceRect);
void updateTextureRect(GraphicsContext3D*, GC3Denum format, const IntRect& destRect, const uint8_t* pixels);
diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
index 5c79f0743..a479297b7 100644
--- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
@@ -34,43 +34,67 @@
#include "Canvas2DLayerChromium.h"
-#include "cc/CCCanvasLayerImpl.h"
-#include "cc/CCLayerTreeHost.h"
-#include "cc/CCTextureUpdater.h"
#include "Extensions3DChromium.h"
#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h" // For the GLC() macro
+#include "TextureCopier.h"
+#include "cc/CCLayerTreeHost.h"
+#include "cc/CCTextureLayerImpl.h"
+#include "cc/CCTextureUpdater.h"
#include "SkCanvas.h"
namespace WebCore {
-PassRefPtr<Canvas2DLayerChromium> Canvas2DLayerChromium::create(GraphicsContext3D* context, const IntSize& size)
+PassRefPtr<Canvas2DLayerChromium> Canvas2DLayerChromium::create(PassRefPtr<GraphicsContext3D> context, const IntSize& size, DeferralMode deferralMode)
{
- return adoptRef(new Canvas2DLayerChromium(context, size));
+ return adoptRef(new Canvas2DLayerChromium(context, size, deferralMode));
}
-Canvas2DLayerChromium::Canvas2DLayerChromium(GraphicsContext3D* context, const IntSize& size)
+Canvas2DLayerChromium::Canvas2DLayerChromium(PassRefPtr<GraphicsContext3D> context, const IntSize& size, DeferralMode deferralMode)
: CanvasLayerChromium()
, m_context(context)
+ , m_contextLost(false)
, m_size(size)
, m_backTextureId(0)
- , m_fbo(0)
- , m_useDoubleBuffering(CCProxy::hasImplThread())
, m_canvas(0)
+ , m_deferralMode(deferralMode)
{
- if (m_useDoubleBuffering)
- GLC(m_context, m_fbo = m_context->createFramebuffer());
+ // FIXME: We currently turn off double buffering when canvas rendering is
+ // deferred. What we should be doing is to use a smarter heuristic based
+ // on GPU resource monitoring and other factors to chose between single
+ // and double buffering.
+ m_useDoubleBuffering = CCProxy::hasImplThread() && deferralMode == NonDeferred;
+
+ // The threaded compositor is self rate-limiting when rendering
+ // to a single buffered canvas layer.
+ m_useRateLimiter = !CCProxy::hasImplThread() || m_useDoubleBuffering;
}
Canvas2DLayerChromium::~Canvas2DLayerChromium()
{
- if (m_useDoubleBuffering && m_fbo)
- GLC(m_context, m_context->deleteFramebuffer(m_fbo));
+ setTextureId(0);
+ if (m_context && m_useRateLimiter && layerTreeHost())
+ layerTreeHost()->stopRateLimiter(m_context.get());
+}
+
+bool Canvas2DLayerChromium::drawingIntoImplThreadTexture() const
+{
+ return !m_useDoubleBuffering && CCProxy::hasImplThread() && layerTreeHost();
}
void Canvas2DLayerChromium::setTextureId(unsigned textureId)
{
+ if (m_backTextureId == textureId)
+ return;
+
+ if (m_backTextureId && drawingIntoImplThreadTexture()) {
+ // The impl tree may be referencing the old m_backTexture, which may
+ // soon be deleted. We must make sure the layer tree on the impl thread
+ // is not drawn until the next commit, which will re-synchronize the
+ // layer trees.
+ layerTreeHost()->acquireLayerTextures();
+ }
m_backTextureId = textureId;
setNeedsCommit();
}
@@ -79,14 +103,14 @@ void Canvas2DLayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect)
{
LayerChromium::setNeedsDisplayRect(dirtyRect);
- if (layerTreeHost())
- layerTreeHost()->startRateLimiter(m_context);
+ if (m_useRateLimiter && layerTreeHost())
+ layerTreeHost()->startRateLimiter(m_context.get());
}
bool Canvas2DLayerChromium::drawsContent() const
{
return LayerChromium::drawsContent() && m_backTextureId && !m_size.isEmpty()
- && m_context && (m_context->getExtensions()->getGraphicsResetStatusARB() == GraphicsContext3D::NO_ERROR);
+ && !m_contextLost;
}
void Canvas2DLayerChromium::setCanvas(SkCanvas* canvas)
@@ -94,14 +118,21 @@ void Canvas2DLayerChromium::setCanvas(SkCanvas* canvas)
m_canvas = canvas;
}
-void Canvas2DLayerChromium::paintContentsIfDirty(const Region& /* occludedScreenSpace */)
+void Canvas2DLayerChromium::update(CCTextureUpdater& updater, const CCOcclusionTracker*)
{
- TRACE_EVENT("Canvas2DLayerChromium::paintContentsIfDirty", this, 0);
+ TRACE_EVENT0("cc", "Canvas2DLayerChromium::update");
if (!drawsContent())
return;
- if (m_useDoubleBuffering)
- m_frontTexture->reserve(m_size, GraphicsContext3D::RGBA);
+ if (m_useDoubleBuffering && layerTreeHost()) {
+ TextureManager* textureManager = layerTreeHost()->contentsTextureManager();
+ if (m_frontTexture)
+ m_frontTexture->setTextureManager(textureManager);
+ else
+ m_frontTexture = ManagedTexture::create(textureManager);
+ if (m_frontTexture->reserve(m_size, GraphicsContext3D::RGBA))
+ updater.appendManagedCopy(m_backTextureId, m_frontTexture.get(), m_size);
+ }
if (!needsDisplay())
return;
@@ -111,62 +142,40 @@ void Canvas2DLayerChromium::paintContentsIfDirty(const Region& /* occludedScreen
bool success = m_context->makeContextCurrent();
ASSERT_UNUSED(success, success);
+ m_contextLost = m_context->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR;
+ if (m_contextLost)
+ return;
+
if (m_canvas) {
- TRACE_EVENT("SkDeferredCanvas::flush", m_canvas, 0);
+ TRACE_EVENT0("cc", "SkCanvas::flush");
m_canvas->flush();
}
- TRACE_EVENT("GrContext::flush", m_context, 0);
+ TRACE_EVENT0("cc", "GraphicsContext3D::flush");
m_context->flush();
}
-void Canvas2DLayerChromium::setLayerTreeHost(CCLayerTreeHost* host)
+void Canvas2DLayerChromium::layerWillDraw(WillDrawCondition condition) const
{
- CanvasLayerChromium::setLayerTreeHost(host);
-
- if (m_useDoubleBuffering && host)
- setTextureManager(host->contentsTextureManager());
-}
-
-void Canvas2DLayerChromium::setTextureManager(TextureManager* textureManager)
-{
- if (m_frontTexture)
- m_frontTexture->setTextureManager(textureManager);
- else
- m_frontTexture = ManagedTexture::create(textureManager);
+ if (drawingIntoImplThreadTexture()) {
+ if (condition == WillDrawUnconditionally || m_deferralMode == NonDeferred)
+ layerTreeHost()->acquireLayerTextures();
+ }
}
-void Canvas2DLayerChromium::updateCompositorResources(GraphicsContext3D* context, CCTextureUpdater& updater)
-{
- if (!m_backTextureId || !m_frontTexture || !m_frontTexture->isValid(m_size, GraphicsContext3D::RGBA))
- return;
-
- m_frontTexture->bindTexture(context, updater.allocator());
-
- GLC(context, context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo));
- GLC(context, context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_backTextureId, 0));
- // FIXME: The copy operation will fail if the m_backTexture is allocated as BGRA since glCopyTex(Sub)Image2D doesn't
- // support the BGRA format. See bug https://bugs.webkit.org/show_bug.cgi?id=75142
- GLC(context, context->copyTexSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, 0, 0, m_size.width(), m_size.height()));
- GLC(context, context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
- GLC(context, context->flush());
-}
void Canvas2DLayerChromium::pushPropertiesTo(CCLayerImpl* layer)
{
CanvasLayerChromium::pushPropertiesTo(layer);
- CCCanvasLayerImpl* canvasLayer = static_cast<CCCanvasLayerImpl*>(layer);
- if (m_useDoubleBuffering)
- canvasLayer->setTextureId(m_frontTexture->textureId());
- else
- canvasLayer->setTextureId(m_backTextureId);
-}
-
-void Canvas2DLayerChromium::unreserveContentsTexture()
-{
- if (m_useDoubleBuffering)
- m_frontTexture->unreserve();
+ CCTextureLayerImpl* textureLayer = static_cast<CCTextureLayerImpl*>(layer);
+ if (m_useDoubleBuffering) {
+ if (m_frontTexture && m_frontTexture->isValid(m_size, GraphicsContext3D::RGBA))
+ textureLayer->setTextureId(m_frontTexture->textureId());
+ else
+ textureLayer->setTextureId(0);
+ } else
+ textureLayer->setTextureId(m_backTextureId);
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
index 035a2b37e..ad3c6865a 100644
--- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
@@ -35,6 +35,7 @@
#if USE(ACCELERATED_COMPOSITING)
#include "CanvasLayerChromium.h"
+#include "ImageBuffer.h"
#include "ManagedTexture.h"
class SkCanvas;
@@ -47,39 +48,41 @@ class Region;
// A layer containing an accelerated 2d canvas
class Canvas2DLayerChromium : public CanvasLayerChromium {
public:
- static PassRefPtr<Canvas2DLayerChromium> create(GraphicsContext3D*, const IntSize&);
+ enum WillDrawCondition {
+ WillDrawUnconditionally,
+ WillDrawIfLayerNotDeferred,
+ };
+
+ static PassRefPtr<Canvas2DLayerChromium> create(PassRefPtr<GraphicsContext3D>, const IntSize&, DeferralMode);
virtual ~Canvas2DLayerChromium();
void setTextureId(unsigned);
- virtual void setNeedsDisplayRect(const FloatRect&);
-
- virtual bool drawsContent() const;
- virtual void paintContentsIfDirty(const Region& occludedScreenSpace);
+ virtual void setNeedsDisplayRect(const FloatRect&) OVERRIDE;
- virtual void setLayerTreeHost(CCLayerTreeHost*);
- virtual void updateCompositorResources(GraphicsContext3D*, CCTextureUpdater&);
- virtual void pushPropertiesTo(CCLayerImpl*);
- virtual void unreserveContentsTexture();
+ virtual bool drawsContent() const OVERRIDE;
+ virtual void update(CCTextureUpdater&, const CCOcclusionTracker*) OVERRIDE;
+ virtual void pushPropertiesTo(CCLayerImpl*) OVERRIDE;
void setCanvas(SkCanvas*);
+ void layerWillDraw(WillDrawCondition) const;
private:
- Canvas2DLayerChromium(GraphicsContext3D*, const IntSize&);
-
- friend class Canvas2DLayerChromiumTest;
- void setTextureManager(TextureManager*);
+ Canvas2DLayerChromium(PassRefPtr<GraphicsContext3D>, const IntSize&, DeferralMode);
+ bool drawingIntoImplThreadTexture() const;
- GraphicsContext3D* m_context;
+ RefPtr<GraphicsContext3D> m_context;
+ bool m_contextLost;
IntSize m_size;
unsigned m_backTextureId;
- Platform3DObject m_fbo;
// When m_useDoubleBuffering is true, the compositor will draw using a copy of the
// canvas' backing texture. This option should be used with the compositor doesn't
// synchronize its draws with the canvas updates.
bool m_useDoubleBuffering;
OwnPtr<ManagedTexture> m_frontTexture;
SkCanvas* m_canvas;
+ bool m_useRateLimiter;
+ DeferralMode m_deferralMode;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp
index d533699af..4b6652384 100644
--- a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp
@@ -34,9 +34,7 @@
#include "CanvasLayerChromium.h"
-#include "cc/CCLayerImpl.h"
-#include "GraphicsContext3D.h"
-#include "LayerRendererChromium.h"
+#include "cc/CCTextureLayerImpl.h"
namespace WebCore {
@@ -47,7 +45,7 @@ CanvasLayerChromium::CanvasLayerChromium()
PassOwnPtr<CCLayerImpl> CanvasLayerChromium::createCCLayerImpl()
{
- return CCCanvasLayerImpl::create(m_layerId);
+ return CCTextureLayerImpl::create(m_layerId);
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h
index 722cc1a66..ace3d35f2 100644
--- a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h
@@ -41,7 +41,7 @@ namespace WebCore {
// Base class for WebGL and accelerated 2d canvases.
class CanvasLayerChromium : public LayerChromium {
public:
- virtual PassOwnPtr<CCLayerImpl> createCCLayerImpl();
+ virtual PassOwnPtr<CCLayerImpl> createCCLayerImpl() OVERRIDE;
protected:
CanvasLayerChromium();
diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.cpp
index ea1930365..cf8b293a7 100644
--- a/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.cpp
+++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.cpp
@@ -46,7 +46,7 @@ CanvasLayerTextureUpdater::~CanvasLayerTextureUpdater()
{
}
-void CanvasLayerTextureUpdater::paintContents(GraphicsContext& context, PlatformContextSkia& platformContext, const IntRect& contentRect, float contentsScale)
+void CanvasLayerTextureUpdater::paintContents(GraphicsContext& context, PlatformContextSkia& platformContext, const IntRect& contentRect, float contentsScale, IntRect& resultingOpaqueRect)
{
context.translate(-contentRect.x(), -contentRect.y());
{
@@ -63,12 +63,18 @@ void CanvasLayerTextureUpdater::paintContents(GraphicsContext& context, Platform
scaledContentRect = enclosingIntRect(rect);
}
- // Transform tracked opaque paints back to our layer's content space.
- ASSERT(context.getCTM().isInvertible());
- platformContext.setOpaqueRegionTransform(context.getCTM().inverse());
+ // Record transform prior to painting, as all opaque tracking will be
+ // relative to this current value.
+ AffineTransform canvasToContentTransform = context.getCTM().inverse();
m_painter->paint(context, scaledContentRect);
+ // Transform tracked opaque paints back to our layer's content space.
+ ASSERT(canvasToContentTransform.isInvertible());
+ ASSERT(canvasToContentTransform.preservesAxisAlignment());
+ FloatRect opaqueCanvasRect = platformContext.opaqueRegion().asRect();
+ resultingOpaqueRect = enclosedIntRect(canvasToContentTransform.mapRect(opaqueCanvasRect));
+
if (contentsScale != 1.0)
context.restore();
}
diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.h
index d491348ee..4fb4b8d01 100644
--- a/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.h
+++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.h
@@ -47,7 +47,7 @@ public:
protected:
explicit CanvasLayerTextureUpdater(PassOwnPtr<LayerPainterChromium>);
- void paintContents(GraphicsContext&, PlatformContextSkia&, const IntRect& contentRect, float contentsScale);
+ void paintContents(GraphicsContext&, PlatformContextSkia&, const IntRect& contentRect, float contentsScale, IntRect& resultingOpaqueRect);
const IntRect& contentRect() const { return m_contentRect; }
private:
diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
index 7a66984bd..ae8d3208b 100644
--- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
@@ -41,6 +41,7 @@
#include "LayerRendererChromium.h"
#include "PlatformSupport.h"
#include "cc/CCLayerTreeHost.h"
+#include <public/Platform.h>
#include <wtf/CurrentTime.h>
namespace WebCore {
@@ -61,8 +62,8 @@ public:
m_delegate->paintContents(context, contentRect);
double paintEnd = currentTime();
double pixelsPerSec = (contentRect.width() * contentRect.height()) / (paintEnd - paintStart);
- PlatformSupport::histogramCustomCounts("Renderer4.AccelContentPaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30);
- PlatformSupport::histogramCustomCounts("Renderer4.AccelContentPaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30);
+ WebKit::Platform::current()->histogramCustomCounts("Renderer4.AccelContentPaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30);
+ WebKit::Platform::current()->histogramCustomCounts("Renderer4.AccelContentPaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30);
}
private:
explicit ContentLayerPainter(ContentLayerDelegate* delegate)
@@ -93,32 +94,29 @@ bool ContentLayerChromium::drawsContent() const
return TiledLayerChromium::drawsContent() && m_delegate;
}
-void ContentLayerChromium::paintContentsIfDirty(const Region& occludedScreenSpace)
+void ContentLayerChromium::update(CCTextureUpdater& updater, const CCOcclusionTracker* occlusion)
{
updateTileSizeAndTilingOption();
createTextureUpdaterIfNeeded();
IntRect layerRect;
- // Always call prepareToUpdate() but with an empty layer rectangle when
+ // Always call updateLayerRect() but with an empty layer rectangle when
// layer doesn't draw contents.
if (drawsContent())
layerRect = visibleLayerRect();
- prepareToUpdate(layerRect, occludedScreenSpace);
+ updateLayerRect(updater, layerRect, occlusion);
m_needsDisplay = false;
}
-void ContentLayerChromium::idlePaintContentsIfDirty(const Region& occludedScreenSpace)
+void ContentLayerChromium::idleUpdate(CCTextureUpdater& updater, const CCOcclusionTracker* occlusion)
{
if (!drawsContent())
return;
- const IntRect& layerRect = visibleLayerRect();
- if (layerRect.isEmpty())
- return;
-
- prepareToUpdateIdle(layerRect, occludedScreenSpace);
+ const IntRect layerRect = visibleLayerRect();
+ idleUpdateLayerRect(updater, layerRect, occlusion);
if (needsIdlePaint(layerRect))
setNeedsCommit();
}
diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h
index fa5901e2a..0cd1d78d8 100644
--- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h
@@ -41,7 +41,6 @@ namespace WebCore {
class LayerTilerChromium;
class LayerTextureUpdater;
-class Region;
class ContentLayerDelegate {
public:
@@ -58,19 +57,19 @@ public:
void clearDelegate() { m_delegate = 0; }
- virtual bool drawsContent() const;
- virtual void paintContentsIfDirty(const Region& occludedScreenSpace);
- virtual void idlePaintContentsIfDirty(const Region& occludedScreenSpace);
+ virtual bool drawsContent() const OVERRIDE;
+ virtual void update(CCTextureUpdater&, const CCOcclusionTracker*) OVERRIDE;
+ virtual void idleUpdate(CCTextureUpdater&, const CCOcclusionTracker*) OVERRIDE;
- virtual void setOpaque(bool);
+ virtual void setOpaque(bool) OVERRIDE;
protected:
explicit ContentLayerChromium(ContentLayerDelegate*);
private:
- virtual LayerTextureUpdater* textureUpdater() const { return m_textureUpdater.get(); }
- virtual void createTextureUpdaterIfNeeded();
+ virtual LayerTextureUpdater* textureUpdater() const OVERRIDE { return m_textureUpdater.get(); }
+ virtual void createTextureUpdaterIfNeeded() OVERRIDE;
ContentLayerDelegate* m_delegate;
RefPtr<LayerTextureUpdater> m_textureUpdater;
diff --git a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm
index 41b9d0fcf..a27af4cbe 100644
--- a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm
+++ b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm
@@ -190,8 +190,7 @@ MemoryActivatedFont::~MemoryActivatedFont()
// Parameters:
// * nsFont - The font we wish to load.
// * fontSize - point size of the font we wish to load.
-// * outNSFont - The font that was actually loaded, may be different from nsFont
-// if a fallback font was used.
+// * outNSFont - The font that was actually loaded or null if loading failed.
// * cgFont - on output this contains the CGFontRef corresponding to the NSFont
// that was picked in the end. The caller is responsible for calling
// CFRelease() on this parameter when done with it.
@@ -204,7 +203,7 @@ void FontPlatformData::loadFont(NSFont* nsFont, float fontSize, NSFont*& outNSFo
// Release old CGFontRef since it points at the LastResort font which we don't want.
CFRelease(cgFont);
cgFont = 0;
-
+
// Font loading was blocked by the Sandbox.
m_inMemoryFont = loadFontFromBrowserProcess(outNSFont);
if (m_inMemoryFont) {
@@ -214,10 +213,8 @@ void FontPlatformData::loadFont(NSFont* nsFont, float fontSize, NSFont*& outNSFo
// are consistent.
CFRetain(cgFont);
} else {
- // If we still can't load the font, then return Times,
- // rather than the LastResort font.
- outNSFont = [NSFont fontWithName:@"Times" size:fontSize];
- cgFont = CTFontCopyGraphicsFont(toCTFontRef(outNSFont), 0);
+ // If we still can't load the font, set |outNSFont| to null so that FontPlatformData won't be used.
+ outNSFont = 0;
}
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
index 551adf769..e33dc27eb 100644
--- a/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
@@ -35,7 +35,12 @@
#include "CanvasRenderingContext.h"
#include "Extensions3DChromium.h"
#include "GraphicsContext3D.h"
-#include "WebGLLayerChromium.h"
+#include "TextureLayerChromium.h"
+#include "cc/CCProxy.h"
+#include "cc/CCTextureUpdater.h"
+#include <algorithm>
+
+using namespace std;
namespace WebCore {
@@ -46,8 +51,8 @@ static unsigned generateColorTexture(GraphicsContext3D* context, const IntSize&
return 0;
context->bindTexture(GraphicsContext3D::TEXTURE_2D, offscreenColorTexture);
- context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST);
- context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST);
+ context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
+ context->texParameteri(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->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, size.width(), size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE);
@@ -59,10 +64,13 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
const IntSize& size,
bool multisampleExtensionSupported,
bool packedDepthStencilExtensionSupported,
- bool separateBackingTexture)
- : m_separateBackingTexture(separateBackingTexture)
+ PreserveDrawingBuffer preserve,
+ AlphaRequirement alpha)
+ : m_preserveDrawingBuffer(preserve)
+ , m_alpha(alpha)
, m_scissorEnabled(false)
, m_texture2DBinding(0)
+ , m_framebufferBinding(0)
, m_activeTextureUnit(GraphicsContext3D::TEXTURE0)
, m_context(context)
, m_size(-1, -1)
@@ -70,7 +78,8 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
, m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupported)
, m_fbo(0)
, m_colorBuffer(0)
- , m_backingColorBuffer(0)
+ , m_frontColorBuffer(0)
+ , m_separateFrontTexture(m_preserveDrawingBuffer == Preserve || CCProxy::implThread())
, m_depthStencilBuffer(0)
, m_depthBuffer(0)
, m_stencilBuffer(0)
@@ -82,9 +91,6 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
DrawingBuffer::~DrawingBuffer()
{
- if (m_platformLayer)
- m_platformLayer->setDrawingBuffer(0);
-
if (!m_context)
return;
@@ -95,8 +101,8 @@ void DrawingBuffer::initialize(const IntSize& size)
{
m_fbo = m_context->createFramebuffer();
- if (m_separateBackingTexture)
- m_backingColorBuffer = generateColorTexture(m_context.get(), size);
+ if (m_separateFrontTexture)
+ m_frontColorBuffer = generateColorTexture(m_context.get(), size);
m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
m_colorBuffer = generateColorTexture(m_context.get(), size);
@@ -109,54 +115,91 @@ void DrawingBuffer::initialize(const IntSize& size)
}
#if USE(ACCELERATED_COMPOSITING)
-void DrawingBuffer::publishToPlatformLayer()
+void DrawingBuffer::prepareBackBuffer()
{
- if (!m_context)
- return;
-
m_context->makeContextCurrent();
+
if (multisample())
commit();
- if (m_separateBackingTexture) {
+ if (m_preserveDrawingBuffer == Discard && m_separateFrontTexture) {
+ swap(m_frontColorBuffer, m_colorBuffer);
+ // It appears safe to overwrite the context's framebuffer binding in the Discard case since there will always be a
+ // WebGLRenderingContext::clearIfComposited() call made before the next draw call which restores the framebuffer binding.
+ // If this stops being true at some point, we should track the current framebuffer binding in the DrawingBuffer and restore
+ // it after attaching the new back buffer here.
m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
-
- // This path always uses TEXTURE0, and restores its state below.
- m_context->activeTexture(GraphicsContext3D::TEXTURE0);
- m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_backingColorBuffer);
-
- unsigned colorFormat = m_context->getContextAttributes().alpha ? GraphicsContext3D::RGBA : GraphicsContext3D::RGB;
- m_context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, colorFormat, 0, 0, size().width(), size().height(), 0);
-
- m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_texture2DBinding);
- m_context->activeTexture(m_activeTextureUnit);
+ m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0);
}
if (multisample())
bind();
+}
- m_context->flush();
+bool DrawingBuffer::requiresCopyFromBackToFrontBuffer() const
+{
+ return m_separateFrontTexture && m_preserveDrawingBuffer == Preserve;
+}
+
+unsigned DrawingBuffer::frontColorBuffer() const
+{
+ return m_separateFrontTexture ? m_frontColorBuffer : m_colorBuffer;
}
#endif
+class DrawingBufferPrivate : public TextureLayerChromiumClient {
+ WTF_MAKE_NONCOPYABLE(DrawingBufferPrivate);
+public:
+ explicit DrawingBufferPrivate(DrawingBuffer* drawingBuffer)
+ : m_drawingBuffer(drawingBuffer)
+ , m_layer(TextureLayerChromium::create(this))
+ {
+ GraphicsContext3D::Attributes attributes = m_drawingBuffer->graphicsContext3D()->getContextAttributes();
+ m_layer->setOpaque(!attributes.alpha);
+ m_layer->setPremultipliedAlpha(attributes.premultipliedAlpha);
+ }
+
+ virtual ~DrawingBufferPrivate()
+ {
+ m_layer->clearClient();
+ }
+
+ virtual unsigned prepareTexture(CCTextureUpdater& updater) OVERRIDE
+ {
+ m_drawingBuffer->prepareBackBuffer();
+
+ context()->flush();
+ context()->markLayerComposited();
+
+ unsigned textureId = m_drawingBuffer->frontColorBuffer();
+ if (m_drawingBuffer->requiresCopyFromBackToFrontBuffer())
+ updater.appendCopy(m_drawingBuffer->colorBuffer(), textureId, m_drawingBuffer->size());
+
+ return textureId;
+ }
+
+ virtual GraphicsContext3D* context() OVERRIDE
+ {
+ return m_drawingBuffer->graphicsContext3D();
+ }
+
+ LayerChromium* layer() const { return m_layer.get(); }
+
+private:
+ DrawingBuffer* m_drawingBuffer;
+ RefPtr<TextureLayerChromium> m_layer;
+};
+
#if USE(ACCELERATED_COMPOSITING)
PlatformLayer* DrawingBuffer::platformLayer()
{
- if (!m_platformLayer) {
- m_platformLayer = WebGLLayerChromium::create();
- m_platformLayer->setDrawingBuffer(this);
- m_platformLayer->setOpaque(!m_context->getContextAttributes().alpha);
- }
+ if (!m_private)
+ m_private = adoptPtr(new DrawingBufferPrivate(this));
- return m_platformLayer.get();
+ return m_private->layer();
}
#endif
-Platform3DObject DrawingBuffer::platformColorBuffer() const
-{
- return m_separateBackingTexture ? m_backingColorBuffer : m_colorBuffer;
-}
-
Platform3DObject DrawingBuffer::framebuffer() const
{
return m_fbo;
@@ -165,8 +208,26 @@ Platform3DObject DrawingBuffer::framebuffer() const
#if USE(ACCELERATED_COMPOSITING)
void DrawingBuffer::paintCompositedResultsToCanvas(CanvasRenderingContext* context)
{
- if (m_platformLayer)
- m_platformLayer->paintRenderedResultsToCanvas(context->canvas()->buffer());
+ if (!m_context->makeContextCurrent() || m_context->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR)
+ return;
+
+ IntSize framebufferSize = m_context->getInternalFramebufferSize();
+
+ // Since we're using the same context as WebGL, we have to restore any state we change (in this case, just the framebuffer binding).
+ // FIXME: The WebGLRenderingContext tracks the current framebuffer binding, it would be slightly more efficient to use this value
+ // rather than querying it off of the context.
+ GC3Dint previousFramebuffer = 0;
+ m_context->getIntegerv(GraphicsContext3D::FRAMEBUFFER_BINDING, &previousFramebuffer);
+
+ Platform3DObject framebuffer = m_context->createFramebuffer();
+ m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, framebuffer);
+ m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, frontColorBuffer(), 0);
+
+ Extensions3DChromium* extensions = static_cast<Extensions3DChromium*>(m_context->getExtensions());
+ extensions->paintFramebufferToCanvas(framebuffer, framebufferSize.width(), framebufferSize.height(), !m_context->getContextAttributes().premultipliedAlpha, context->canvas()->buffer());
+ m_context->deleteFramebuffer(framebuffer);
+
+ m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, previousFramebuffer);
}
#endif
diff --git a/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h b/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h
index 53322f0f2..92821360b 100644
--- a/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h
@@ -46,8 +46,10 @@ public:
// GL_CHROMIUM_rate_limit_offscreen_context
// GL_CHROMIUM_paint_framebuffer_canvas
// GL_CHROMIUM_iosurface (Mac OS X specific)
+ // GL_CHROMIUM_command_buffer_query
// GL_ANGLE_texture_usage
// GL_EXT_texture_storage
+ // GL_EXT_occlusion_query_boolean
// Extensions3D methods.
virtual bool supports(const String&);
@@ -75,7 +77,17 @@ public:
GL_FRAMEBUFFER_ATTACHMENT_ANGLE = 0x93A3,
// GL_EXT_texture_storage
- BGRA8_EXT = 0x93A1
+ BGRA8_EXT = 0x93A1,
+
+ // GL_EXT_occlusion_query_boolean
+ ANY_SAMPLES_PASSED_EXT = 0x8C2F,
+ ANY_SAMPLES_PASSED_CONSERVATIVE_EXT = 0x8D6A,
+ CURRENT_QUERY_EXT = 0x8865,
+ QUERY_RESULT_EXT = 0x8866,
+ QUERY_RESULT_AVAILABLE_EXT = 0x8867,
+
+ // GL_CHROMIUM_command_buffer_query
+ COMMANDS_ISSUED_CHROMIUM = 0x84F2
};
// GL_CHROMIUM_post_sub_buffer
@@ -90,10 +102,25 @@ public:
// GL_CHROMIUM_set_visibility
void setVisibilityCHROMIUM(bool);
+ // GL_EXT_discard_framebuffer
+ virtual void discardFramebufferEXT(GC3Denum target, GC3Dsizei numAttachments, const GC3Denum* attachments);
+ virtual void ensureFramebufferCHROMIUM();
+
// GL_CHROMIUM_gpu_memory_manager
+ struct GpuMemoryAllocationCHROMIUM {
+ size_t gpuResourceSizeInBytes;
+ bool suggestHaveBackbuffer;
+
+ GpuMemoryAllocationCHROMIUM(size_t gpuResourceSizeInBytes, bool suggestHaveBackbuffer)
+ : gpuResourceSizeInBytes(gpuResourceSizeInBytes)
+ , suggestHaveBackbuffer(suggestHaveBackbuffer)
+ {
+ }
+ };
class GpuMemoryAllocationChangedCallbackCHROMIUM {
public:
- virtual void onGpuMemoryAllocationChanged(size_t gpuResourceSizeInBytes) = 0;
+
+ virtual void onGpuMemoryAllocationChanged(GpuMemoryAllocationCHROMIUM) = 0;
virtual ~GpuMemoryAllocationChangedCallbackCHROMIUM() { }
};
void setGpuMemoryAllocationChangedCallbackCHROMIUM(PassOwnPtr<GpuMemoryAllocationChangedCallbackCHROMIUM>);
@@ -120,6 +147,15 @@ public:
// GL_EXT_texture_storage
void texStorage2DEXT(unsigned target, int levels, unsigned internalformat, int width, int height);
+ // GL_EXT_occlusion_query
+ Platform3DObject createQueryEXT();
+ void deleteQueryEXT(Platform3DObject);
+ GC3Dboolean isQueryEXT(Platform3DObject);
+ void beginQueryEXT(GC3Denum, Platform3DObject);
+ void endQueryEXT(GC3Denum);
+ void getQueryivEXT(GC3Denum, GC3Denum, GC3Dint*);
+ void getQueryObjectuivEXT(Platform3DObject, GC3Denum, GC3Duint*);
+
private:
// Instances of this class are strictly owned by the GraphicsContext3D implementation and do not
// need to be instantiated by any other code.
diff --git a/Source/WebCore/platform/graphics/chromium/FontCacheAndroid.cpp b/Source/WebCore/platform/graphics/chromium/FontCacheAndroid.cpp
index 4acb5ff7c..6f047b9c8 100644
--- a/Source/WebCore/platform/graphics/chromium/FontCacheAndroid.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontCacheAndroid.cpp
@@ -39,7 +39,7 @@
#include "SimpleFontData.h"
#include "SkPaint.h"
-#include "SkTypeface.h"
+#include "SkTypeface_android.h"
#include "SkUtils.h"
#include <unicode/locid.h>
@@ -164,33 +164,46 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
if (fontDescription.italic())
style |= SkTypeface::kItalic;
- SkTypeface* typeface = SkTypeface::CreateFromName(name, SkTypeface::kNormal);
+ SkTypeface* typeface = 0;
FontPlatformData* result = 0;
-
- // CreateFromName always returns a typeface, falling back to a default font
- // if the one requested could not be found. Calling Equal() with a null
- // pointer will compare the returned font against the default, with the
- // caveat that the default is always of normal style. When that happens,
- // ignore the default font and allow WebCore to provide the next font on the
- // CSS fallback list. The only exception to this occurs when the family name
- // is a commonly used generic family, which is the case when called by
- // getSimilarFontPlatformData() or getLastResortFallbackFont(). In that case
- // the default font is an acceptable result.
-
- if (!SkTypeface::Equal(typeface, 0) || isFallbackFamily(family.string())) {
- if (style != SkTypeface::kNormal) {
- typeface->unref();
- typeface = SkTypeface::CreateFromName(name, static_cast<SkTypeface::Style>(style));
+ FallbackScripts fallbackScript = SkGetFallbackScriptFromID(name);
+ if (SkTypeface_ValidScript(fallbackScript)) {
+ typeface = SkCreateTypefaceForScript(fallbackScript);
+ if (typeface)
+ result = new FontPlatformData(typeface, name, fontDescription.computedSize(),
+ (style & SkTypeface::kBold) && !typeface->isBold(),
+ (style & SkTypeface::kItalic) && !typeface->isItalic(),
+ fontDescription.orientation(),
+ fontDescription.textOrientation());
+ } else {
+ typeface = SkTypeface::CreateFromName(name, SkTypeface::kNormal);
+
+ // CreateFromName always returns a typeface, falling back to a default font
+ // if the one requested could not be found. Calling Equal() with a null
+ // pointer will compare the returned font against the default, with the
+ // caveat that the default is always of normal style. When that happens,
+ // ignore the default font and allow WebCore to provide the next font on the
+ // CSS fallback list. The only exception to this occurs when the family name
+ // is a commonly used generic family, which is the case when called by
+ // getSimilarFontPlatformData() or getLastResortFallbackFont(). In that case
+ // the default font is an acceptable result.
+
+ if (!SkTypeface::Equal(typeface, 0) || isFallbackFamily(family.string())) {
+ // We had to use normal styling to see if this was a default font. If
+ // we need bold or italic, replace with the corrected typeface.
+ if (style != SkTypeface::kNormal) {
+ typeface->unref();
+ typeface = SkTypeface::CreateFromName(name, static_cast<SkTypeface::Style>(style));
+ }
+ result = new FontPlatformData(typeface, name, fontDescription.computedSize(),
+ (style & SkTypeface::kBold) && !typeface->isBold(),
+ (style & SkTypeface::kItalic) && !typeface->isItalic(),
+ fontDescription.orientation(),
+ fontDescription.textOrientation());
}
-
- result = new FontPlatformData(typeface, name, fontDescription.computedSize(),
- (style & SkTypeface::kBold) && !typeface->isBold(),
- (style & SkTypeface::kItalic) && !typeface->isItalic(),
- fontDescription.orientation(),
- fontDescription.textOrientation());
}
- typeface->unref();
+ SkSafeUnref(typeface);
return result;
}
diff --git a/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
index a50e6abc4..d4d592e1b 100644
--- a/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
@@ -34,12 +34,12 @@
#include "Font.h"
#include "FontUtilsChromiumWin.h"
-#include "HashMap.h"
-#include "HashSet.h"
#include "HWndDC.h"
#include "PlatformSupport.h"
#include "SimpleFontData.h"
#include <unicode/uniset.h>
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
#include <wtf/text/StringHash.h>
#include <windows.h>
diff --git a/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
index bc48e900a..3d30e18eb 100644
--- a/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
@@ -55,13 +55,6 @@ namespace WebCore {
#if !USE(SKIA_TEXT)
namespace {
-bool canvasHasMultipleLayers(const SkCanvas* canvas)
-{
- SkCanvas::LayerIter iter(const_cast<SkCanvas*>(canvas), false);
- iter.next(); // There is always at least one layer.
- return !iter.done(); // There is > 1 layer if the the iterator can stil advance.
-}
-
class TransparencyAwareFontPainter {
public:
TransparencyAwareFontPainter(GraphicsContext*, const FloatPoint&);
@@ -147,7 +140,7 @@ void TransparencyAwareFontPainter::initializeForGDI()
// this mode and it will apply the color.
m_transparency.setTextCompositeColor(color);
color = SkColorSetRGB(0, 0, 0);
- } else if (m_createdTransparencyLayer || canvasHasMultipleLayers(m_platformContext->canvas())) {
+ } else if (m_createdTransparencyLayer || m_platformContext->canvas()->isDrawingToLayer()) {
// When we're drawing a web page, we know the background is opaque,
// but if we're drawing to a layer, we still need extra work.
layerMode = TransparencyWin::OpaqueCompositeLayer;
diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp
index a89a18232..a6541ee1c 100644
--- a/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp
@@ -40,7 +40,7 @@
#include "PlatformSupport.h"
#include "SkTypeface_win.h"
#include "SkiaFontWin.h"
-#include "StdLibExtras.h"
+#include <wtf/StdLibExtras.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
index 711b896ac..cc52c52eb 100644
--- a/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
@@ -414,8 +414,8 @@ bool getDerivedFontData(const UChar* family,
// a font even if there's no font matching the name. Need to
// check it against what we actually want (as is done in
// FontCacheWin.cpp)
- pair<FontDataCache::iterator, bool> entry = fontDataCache.add(fontKey, FontData());
- derived = &entry.first->second;
+ FontDataCache::AddResult entry = fontDataCache.add(fontKey, FontData());
+ derived = &entry.iterator->second;
derived->hfont = CreateFontIndirect(logfont);
// GetAscent may return kUndefinedAscent, but we still want to
// cache it so that we won't have to call CreateFontIndirect once
diff --git a/Source/WebCore/platform/graphics/chromium/FrameBufferSkPictureCanvasLayerTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/FrameBufferSkPictureCanvasLayerTextureUpdater.cpp
index be217d9c1..0ca354d74 100644
--- a/Source/WebCore/platform/graphics/chromium/FrameBufferSkPictureCanvasLayerTextureUpdater.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FrameBufferSkPictureCanvasLayerTextureUpdater.cpp
@@ -49,7 +49,7 @@ static PassOwnPtr<SkCanvas> createAcceleratedCanvas(GraphicsContext3D* context,
textureDesc.fFlags = kRenderTarget_GrPlatformTextureFlag;
textureDesc.fWidth = canvasSize.width();
textureDesc.fHeight = canvasSize.height();
- textureDesc.fConfig = kRGBA_8888_GrPixelConfig;
+ textureDesc.fConfig = kSkia8888_PM_GrPixelConfig;
textureDesc.fTextureHandle = texture->textureId();
SkAutoTUnref<GrTexture> target(grContext->createPlatformTexture(textureDesc));
SkAutoTUnref<SkDevice> device(new SkGpuDevice(grContext, target.get()));
diff --git a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
index 4c81853b8..3c6d924bb 100644
--- a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
@@ -87,6 +87,12 @@ GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client)
GraphicsLayerChromium::~GraphicsLayerChromium()
{
+ // Do cleanup while we can still safely call methods on the derived class.
+ willBeDestroyed();
+}
+
+void GraphicsLayerChromium::willBeDestroyed()
+{
if (m_layer) {
m_layer->clearDelegate();
m_layer->clearRenderSurface();
@@ -104,6 +110,8 @@ GraphicsLayerChromium::~GraphicsLayerChromium()
// Be sure to reset the delegate, just in case.
m_transformLayer->setLayerAnimationDelegate(0);
}
+
+ GraphicsLayer::willBeDestroyed();
}
void GraphicsLayerChromium::setName(const String& inName)
@@ -412,14 +420,17 @@ void GraphicsLayerChromium::removeAnimation(const String& animationName)
primaryLayer()->removeAnimation(mapAnimationNameToId(animationName));
}
-void GraphicsLayerChromium::suspendAnimations(double time)
+void GraphicsLayerChromium::suspendAnimations(double wallClockTime)
{
- primaryLayer()->suspendAnimations(time);
+ // |wallClockTime| is in the wrong time base. Need to convert here.
+ // FIXME: find a more reliable way to do this.
+ double monotonicTime = wallClockTime + monotonicallyIncreasingTime() - currentTime();
+ primaryLayer()->suspendAnimations(monotonicTime);
}
void GraphicsLayerChromium::resumeAnimations()
{
- primaryLayer()->resumeAnimations();
+ primaryLayer()->resumeAnimations(monotonicallyIncreasingTime());
}
void GraphicsLayerChromium::setContentsToMedia(PlatformLayer* layer)
@@ -749,14 +760,9 @@ void GraphicsLayerChromium::notifyAnimationStarted(double startTime)
m_client->notifyAnimationStarted(this, startTime);
}
-void GraphicsLayerChromium::notifyAnimationFinished(int animationId)
+void GraphicsLayerChromium::notifyAnimationFinished(double)
{
- for (AnimationIdMap::iterator idIter = m_animationIdMap.begin(); idIter != m_animationIdMap.end(); ++idIter) {
- if (idIter->second == animationId) {
- m_animationIdMap.remove(idIter);
- return;
- }
- }
+ // Do nothing.
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
index 4cca82a88..be2b3ae65 100644
--- a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
@@ -102,7 +102,7 @@ public:
virtual bool addAnimation(const KeyframeValueList&, const IntSize& boxSize, const Animation*, const String&, double timeOffset);
virtual void pauseAnimation(const String& animationName, double timeOffset);
virtual void removeAnimation(const String& animationName);
- virtual void suspendAnimations(double time);
+ virtual void suspendAnimations(double wallClockTime);
virtual void resumeAnimations();
virtual PlatformLayer* platformLayer() const;
@@ -116,12 +116,14 @@ public:
// CCLayerAnimationDelegate implementation.
virtual void notifyAnimationStarted(double startTime);
- virtual void notifyAnimationFinished(int animationId);
+ virtual void notifyAnimationFinished(double finishTime);
// Exposed for tests.
LayerChromium* contentsLayer() const { return m_contentsLayer.get(); }
private:
+ virtual void willBeDestroyed();
+
typedef HashMap<String, int> AnimationIdMap;
LayerChromium* primaryLayer() const { return m_transformLayer.get() ? m_transformLayer.get() : m_layer.get(); }
diff --git a/Source/WebCore/platform/graphics/chromium/IOSurfaceLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/IOSurfaceLayerChromium.cpp
new file mode 100644
index 000000000..df6d6c82c
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/IOSurfaceLayerChromium.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 "IOSurfaceLayerChromium.h"
+
+#include "cc/CCIOSurfaceLayerImpl.h"
+
+namespace WebCore {
+
+PassRefPtr<IOSurfaceLayerChromium> IOSurfaceLayerChromium::create()
+{
+ return adoptRef(new IOSurfaceLayerChromium());
+}
+
+IOSurfaceLayerChromium::IOSurfaceLayerChromium()
+ : LayerChromium()
+ , m_ioSurfaceId(0)
+{
+}
+
+IOSurfaceLayerChromium::~IOSurfaceLayerChromium()
+{
+}
+
+void IOSurfaceLayerChromium::setIOSurfaceProperties(uint32_t ioSurfaceId, const IntSize& size)
+{
+ m_ioSurfaceId = ioSurfaceId;
+ m_ioSurfaceSize = size;
+ setNeedsCommit();
+}
+
+PassOwnPtr<CCLayerImpl> IOSurfaceLayerChromium::createCCLayerImpl()
+{
+ return CCIOSurfaceLayerImpl::create(m_layerId);
+}
+
+bool IOSurfaceLayerChromium::drawsContent() const
+{
+ return m_ioSurfaceId && LayerChromium::drawsContent();
+}
+
+void IOSurfaceLayerChromium::pushPropertiesTo(CCLayerImpl* layer)
+{
+ LayerChromium::pushPropertiesTo(layer);
+
+ CCIOSurfaceLayerImpl* textureLayer = static_cast<CCIOSurfaceLayerImpl*>(layer);
+ textureLayer->setIOSurfaceProperties(m_ioSurfaceId, m_ioSurfaceSize);
+}
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h b/Source/WebCore/platform/graphics/chromium/IOSurfaceLayerChromium.h
index 224da814f..17f943bfc 100644
--- a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/IOSurfaceLayerChromium.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,8 +24,8 @@
*/
-#ifndef PluginLayerChromium_h
-#define PluginLayerChromium_h
+#ifndef IOSurfaceLayerChromium_h
+#define IOSurfaceLayerChromium_h
#if USE(ACCELERATED_COMPOSITING)
@@ -33,37 +33,24 @@
namespace WebCore {
-// A Layer containing a the rendered output of a plugin instance.
-class PluginLayerChromium : public LayerChromium {
+class IOSurfaceLayerChromium : public LayerChromium {
public:
- static PassRefPtr<PluginLayerChromium> create();
+ static PassRefPtr<IOSurfaceLayerChromium> create();
+ virtual ~IOSurfaceLayerChromium();
- virtual PassOwnPtr<CCLayerImpl> createCCLayerImpl();
+ void setIOSurfaceProperties(uint32_t ioSurfaceId, const IntSize&);
- // Code path for plugins which supply their own texture ID.
- void setTextureId(unsigned textureId);
- unsigned textureId() const { return m_textureId; }
- void setFlipped(bool);
- bool flipped() const { return m_flipped; }
- void setUVRect(const FloatRect&);
- const FloatRect& uvRect() const { return m_uvRect; }
-
- // Code path for plugins which render via an IOSurface.
- void setIOSurfaceProperties(int width, int height, uint32_t ioSurfaceId);
- uint32_t getIOSurfaceId() const;
-
- virtual void pushPropertiesTo(CCLayerImpl*);
+ virtual PassOwnPtr<CCLayerImpl> createCCLayerImpl() OVERRIDE;
+ virtual bool drawsContent() const OVERRIDE;
+ virtual void pushPropertiesTo(CCLayerImpl*) OVERRIDE;
protected:
- PluginLayerChromium();
+ IOSurfaceLayerChromium();
private:
- unsigned m_textureId;
- bool m_flipped;
- FloatRect m_uvRect;
- int m_ioSurfaceWidth;
- int m_ioSurfaceHeight;
+
uint32_t m_ioSurfaceId;
+ IntSize m_ioSurfaceSize;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
index 611ab2a6a..d4a43012d 100644
--- a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
@@ -83,7 +83,7 @@ public:
LayerTextureUpdater::SampledTexelFormatRGBA : LayerTextureUpdater::SampledTexelFormatBGRA;
}
- virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, int /* borderTexels */, float /* contentsScale */, IntRect* /* resultingOpaqueRect */)
+ virtual void updateLayerRect(const IntRect& contentRect, const IntSize& tileSize, int /* borderTexels */, float /* contentsScale */, IntRect* /* resultingOpaqueRect */)
{
m_texSubImage.setSubImageSize(tileSize);
}
@@ -158,7 +158,7 @@ void ImageLayerChromium::setContents(Image* contents)
setNeedsDisplay();
}
-void ImageLayerChromium::paintContentsIfDirty(const Region& occludedScreenSpace)
+void ImageLayerChromium::update(CCTextureUpdater& updater, const CCOcclusionTracker* occlusion)
{
createTextureUpdaterIfNeeded();
if (m_needsDisplay) {
@@ -168,7 +168,7 @@ void ImageLayerChromium::paintContentsIfDirty(const Region& occludedScreenSpace)
m_needsDisplay = false;
}
- prepareToUpdate(visibleLayerRect(), occludedScreenSpace);
+ updateLayerRect(updater, visibleLayerRect(), occlusion);
}
void ImageLayerChromium::createTextureUpdaterIfNeeded()
diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h
index deafd37e7..f084d4cb7 100644
--- a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h
@@ -41,7 +41,6 @@ namespace WebCore {
class Image;
class ImageLayerTextureUpdater;
-class Region;
// A Layer that contains only an Image element.
class ImageLayerChromium : public TiledLayerChromium {
@@ -49,9 +48,9 @@ public:
static PassRefPtr<ImageLayerChromium> create();
virtual ~ImageLayerChromium();
- virtual bool drawsContent() const;
- virtual void paintContentsIfDirty(const Region& occludedScreenSpace);
- virtual bool needsContentsScale() const;
+ virtual bool drawsContent() const OVERRIDE;
+ virtual void update(CCTextureUpdater&, const CCOcclusionTracker*) OVERRIDE;
+ virtual bool needsContentsScale() const OVERRIDE;
void setContents(Image* image);
@@ -60,9 +59,9 @@ private:
void setTilingOption(TilingOption);
- virtual LayerTextureUpdater* textureUpdater() const;
- virtual void createTextureUpdaterIfNeeded();
- virtual IntSize contentBounds() const;
+ virtual LayerTextureUpdater* textureUpdater() const OVERRIDE;
+ virtual void createTextureUpdaterIfNeeded() OVERRIDE;
+ virtual IntSize contentBounds() const OVERRIDE;
NativeImagePtr m_imageForCurrentFrame;
RefPtr<Image> m_contents;
diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
index f973880fd..f94aad60e 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
@@ -57,16 +57,17 @@ PassRefPtr<LayerChromium> LayerChromium::create()
LayerChromium::LayerChromium()
: m_needsDisplay(false)
+ , m_stackingOrderChanged(false)
, m_layerId(s_nextLayerId++)
, m_parent(0)
- , m_layerAnimationController(CCLayerAnimationController::create())
+ , m_layerTreeHost(0)
+ , m_layerAnimationController(CCLayerAnimationController::create(this))
, m_scrollable(false)
, m_shouldScrollOnMainThread(false)
, m_haveWheelEventHandlers(false)
, m_nonFastScrollableRegionChanged(false)
, m_anchorPoint(0.5, 0.5)
, m_backgroundColor(0, 0, 0, 0)
- , m_backgroundCoversViewport(false)
, m_debugBorderWidth(0)
, m_opacity(1.0)
, m_anchorPointZ(0)
@@ -78,9 +79,13 @@ LayerChromium::LayerChromium()
, m_isNonCompositedContent(false)
, m_preserves3D(false)
, m_alwaysReserveTextures(false)
+ , m_drawCheckerboardForMissingTiles(false)
, m_replicaLayer(0)
, m_drawOpacity(0)
+ , m_drawOpacityIsAnimating(false)
, m_targetRenderSurface(0)
+ , m_drawTransformIsAnimating(false)
+ , m_screenSpaceTransformIsAnimating(false)
, m_contentsScale(1.0)
, m_layerAnimationDelegate(0)
{
@@ -96,70 +101,6 @@ LayerChromium::~LayerChromium()
removeAllChildren();
}
-bool LayerChromium::addAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* animation, int animationId, int groupId, double timeOffset)
-{
- if (!m_layerTreeHost || !m_layerTreeHost->settings().threadedAnimationEnabled)
- return false;
-
- bool addedAnimation = m_layerAnimationController->addAnimation(values, boxSize, animation, animationId, groupId, timeOffset);
- if (addedAnimation)
- setNeedsCommit();
- return addedAnimation;
-}
-
-void LayerChromium::pauseAnimation(int animationId, double timeOffset)
-{
- m_layerAnimationController->pauseAnimation(animationId, timeOffset);
- setNeedsCommit();
-}
-
-void LayerChromium::removeAnimation(int animationId)
-{
- m_layerAnimationController->removeAnimation(animationId);
- setNeedsCommit();
-}
-
-void LayerChromium::suspendAnimations(double time)
-{
- m_layerAnimationController->suspendAnimations(time);
- setNeedsCommit();
-}
-
-void LayerChromium::resumeAnimations()
-{
- m_layerAnimationController->resumeAnimations();
- setNeedsCommit();
-}
-
-void LayerChromium::setLayerAnimationController(PassOwnPtr<CCLayerAnimationController> layerAnimationController)
-{
- m_layerAnimationController = layerAnimationController;
- setNeedsCommit();
-}
-
-bool LayerChromium::hasActiveAnimation() const
-{
- return m_layerAnimationController->hasActiveAnimation();
-}
-
-void LayerChromium::setAnimationEvent(const CCAnimationEvent& event, double wallClockTime)
-{
- switch (event.type()) {
-
- case CCAnimationEvent::Started: {
- m_layerAnimationDelegate->notifyAnimationStarted(wallClockTime);
- break;
- }
-
- case CCAnimationEvent::Finished: {
- const CCAnimationFinishedEvent* finishedEvent = event.toAnimationFinishedEvent();
- m_layerAnimationDelegate->notifyAnimationFinished(finishedEvent->animationId());
- break;
- }
-
- }
-}
-
void LayerChromium::setIsNonCompositedContent(bool isNonCompositedContent)
{
m_isNonCompositedContent = isNonCompositedContent;
@@ -213,6 +154,7 @@ void LayerChromium::insertChild(PassRefPtr<LayerChromium> child, size_t index)
index = min(index, m_children.size());
child->removeFromParent();
child->setParent(this);
+ child->m_stackingOrderChanged = true;
m_children.insert(index, child);
setNeedsCommit();
}
@@ -331,14 +273,6 @@ void LayerChromium::setBackgroundColor(const Color& backgroundColor)
setNeedsCommit();
}
-void LayerChromium::setBackgroundCoversViewport(bool backgroundCoversViewport)
-{
- if (m_backgroundCoversViewport == backgroundCoversViewport)
- return;
- m_backgroundCoversViewport = backgroundCoversViewport;
- setNeedsCommit();
-}
-
void LayerChromium::setMasksToBounds(bool masksToBounds)
{
if (m_masksToBounds == masksToBounds)
@@ -355,7 +289,7 @@ void LayerChromium::setMaskLayer(LayerChromium* maskLayer)
m_maskLayer->setLayerTreeHost(0);
m_maskLayer = maskLayer;
if (m_maskLayer) {
- m_maskLayer->setLayerTreeHost(m_layerTreeHost.get());
+ m_maskLayer->setLayerTreeHost(m_layerTreeHost);
m_maskLayer->setIsMask(true);
}
setNeedsCommit();
@@ -369,7 +303,7 @@ void LayerChromium::setReplicaLayer(LayerChromium* layer)
m_replicaLayer->setLayerTreeHost(0);
m_replicaLayer = layer;
if (m_replicaLayer)
- m_replicaLayer->setLayerTreeHost(m_layerTreeHost.get());
+ m_replicaLayer->setLayerTreeHost(m_layerTreeHost);
setNeedsCommit();
}
@@ -379,6 +313,16 @@ void LayerChromium::setFilters(const FilterOperations& filters)
return;
m_filters = filters;
setNeedsCommit();
+ if (!filters.isEmpty())
+ CCLayerTreeHost::setNeedsFilterContext(true);
+}
+
+void LayerChromium::setBackgroundFilters(const FilterOperations& backgroundFilters)
+{
+ if (m_backgroundFilters == backgroundFilters)
+ return;
+ m_backgroundFilters = backgroundFilters;
+ setNeedsCommit();
}
void LayerChromium::setOpacity(float opacity)
@@ -389,6 +333,11 @@ void LayerChromium::setOpacity(float opacity)
setNeedsCommit();
}
+bool LayerChromium::opacityIsAnimating() const
+{
+ return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Opacity);
+}
+
void LayerChromium::setOpaque(bool opaque)
{
if (m_opaque == opaque)
@@ -421,6 +370,11 @@ void LayerChromium::setTransform(const TransformationMatrix& transform)
setNeedsCommit();
}
+bool LayerChromium::transformIsAnimating() const
+{
+ return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Transform);
+}
+
void LayerChromium::setScrollPosition(const IntPoint& scrollPosition)
{
if (m_scrollPosition == scrollPosition)
@@ -462,6 +416,14 @@ void LayerChromium::setNonFastScrollableRegion(const Region& region)
setNeedsCommit();
}
+void LayerChromium::setDrawCheckerboardForMissingTiles(bool checkerboard)
+{
+ if (m_drawCheckerboardForMissingTiles == checkerboard)
+ return;
+ m_drawCheckerboardForMissingTiles = checkerboard;
+ setNeedsCommit();
+}
+
void LayerChromium::setDoubleSided(bool doubleSided)
{
if (m_doubleSided == doubleSided)
@@ -502,15 +464,28 @@ void LayerChromium::pushPropertiesTo(CCLayerImpl* layer)
layer->setAnchorPoint(m_anchorPoint);
layer->setAnchorPointZ(m_anchorPointZ);
layer->setBackgroundColor(m_backgroundColor);
- layer->setBackgroundCoversViewport(m_backgroundCoversViewport);
layer->setBounds(m_bounds);
layer->setContentBounds(contentBounds());
layer->setDebugBorderColor(m_debugBorderColor);
layer->setDebugBorderWidth(m_debugBorderWidth);
layer->setDebugName(m_debugName.isolatedCopy()); // We have to use isolatedCopy() here to safely pass ownership to another thread.
layer->setDoubleSided(m_doubleSided);
+ layer->setDrawCheckerboardForMissingTiles(m_drawCheckerboardForMissingTiles);
layer->setDrawsContent(drawsContent());
+ if (CCProxy::hasImplThread()) {
+ // Since FilterOperations contains a vector of RefPtrs, we must deep copy the filters.
+ FilterOperations filtersCopy;
+ for (unsigned i = 0; i < m_filters.size(); ++i) {
+ RefPtr<FilterOperation> clone = m_filters.at(i)->clone();
+ if (clone)
+ filtersCopy.operations().append(clone);
+ }
+ layer->setFilters(filtersCopy);
+ } else
+ layer->setFilters(filters());
+
layer->setFilters(filters());
+ layer->setBackgroundFilters(backgroundFilters());
layer->setIsNonCompositedContent(m_isNonCompositedContent);
layer->setMasksToBounds(m_masksToBounds);
layer->setScrollable(m_scrollable);
@@ -523,25 +498,35 @@ void LayerChromium::pushPropertiesTo(CCLayerImpl* layer)
m_nonFastScrollableRegionChanged = false;
}
layer->setOpaque(m_opaque);
- layer->setOpacity(m_opacity);
+ if (!opacityIsAnimating())
+ layer->setOpacity(m_opacity);
layer->setPosition(m_position);
layer->setPreserves3D(preserves3D());
layer->setScrollPosition(m_scrollPosition);
layer->setSublayerTransform(m_sublayerTransform);
- layer->setTransform(m_transform);
+ if (!transformIsAnimating())
+ layer->setTransform(m_transform);
+
+ // If the main thread commits multiple times before the impl thread actually draws, then damage tracking
+ // will become incorrect if we simply clobber the updateRect here. The CCLayerImpl's updateRect needs to
+ // accumulate (i.e. union) any update changes that have occurred on the main thread.
+ m_updateRect.uniteIfNonZero(layer->updateRect());
layer->setUpdateRect(m_updateRect);
layer->setScrollDelta(layer->scrollDelta() - layer->sentScrollDelta());
layer->setSentScrollDelta(IntSize());
+ layer->setStackingOrderChanged(m_stackingOrderChanged);
+
if (maskLayer())
maskLayer()->pushPropertiesTo(layer->maskLayer());
if (replicaLayer())
replicaLayer()->pushPropertiesTo(layer->replicaLayer());
- m_layerAnimationController->synchronizeAnimations(layer->layerAnimationController());
+ m_layerAnimationController->pushAnimationUpdatesTo(layer->layerAnimationController());
// Reset any state that should be cleared for the next update.
+ m_stackingOrderChanged = false;
m_updateRect = FloatRect();
}
@@ -593,6 +578,86 @@ bool LayerChromium::descendantDrawsContent()
return false;
}
+void LayerChromium::setOpacityFromAnimation(float opacity)
+{
+ // This is called due to an ongoing accelerated animation. Since this animation is
+ // also being run on the impl thread, there is no need to request a commit to push
+ // this value over, so set the value directly rather than calling setOpacity.
+ m_opacity = opacity;
+}
+
+void LayerChromium::setTransformFromAnimation(const TransformationMatrix& transform)
+{
+ // This is called due to an ongoing accelerated animation. Since this animation is
+ // also being run on the impl thread, there is no need to request a commit to push
+ // this value over, so set this value directly rather than calling setTransform.
+ m_transform = transform;
+}
+
+bool LayerChromium::addAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* animation, int animationId, int groupId, double timeOffset)
+{
+ if (!m_layerTreeHost || !m_layerTreeHost->settings().threadedAnimationEnabled)
+ return false;
+
+ bool addedAnimation = m_layerAnimationController->addAnimation(values, boxSize, animation, animationId, groupId, timeOffset);
+ if (addedAnimation)
+ setNeedsCommit();
+ return addedAnimation;
+}
+
+void LayerChromium::pauseAnimation(int animationId, double timeOffset)
+{
+ m_layerAnimationController->pauseAnimation(animationId, timeOffset);
+ setNeedsCommit();
+}
+
+void LayerChromium::removeAnimation(int animationId)
+{
+ m_layerAnimationController->removeAnimation(animationId);
+ setNeedsCommit();
+}
+
+void LayerChromium::suspendAnimations(double monotonicTime)
+{
+ m_layerAnimationController->suspendAnimations(monotonicTime);
+ setNeedsCommit();
+}
+
+void LayerChromium::resumeAnimations(double monotonicTime)
+{
+ m_layerAnimationController->resumeAnimations(monotonicTime);
+ setNeedsCommit();
+}
+
+void LayerChromium::setLayerAnimationController(PassOwnPtr<CCLayerAnimationController> layerAnimationController)
+{
+ m_layerAnimationController = layerAnimationController;
+ setNeedsCommit();
+}
+
+bool LayerChromium::hasActiveAnimation() const
+{
+ return m_layerAnimationController->hasActiveAnimation();
+}
+
+void LayerChromium::notifyAnimationStarted(const CCAnimationEvent& event, double wallClockTime)
+{
+ m_layerAnimationController->notifyAnimationStarted(event);
+ m_layerAnimationDelegate->notifyAnimationStarted(wallClockTime);
+}
+
+void LayerChromium::notifyAnimationFinished(double wallClockTime)
+{
+ m_layerAnimationDelegate->notifyAnimationFinished(wallClockTime);
+}
+
+Region LayerChromium::visibleContentOpaqueRegion() const
+{
+ if (opaque())
+ return visibleLayerRect();
+ return Region();
+}
+
void sortLayers(Vector<RefPtr<LayerChromium> >::iterator, Vector<RefPtr<LayerChromium> >::iterator, void*)
{
// Currently we don't use z-order to decide what to paint, so there's no need to actually sort LayerChromiums.
diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerChromium.h
index 86fdf9515..9e7fce50c 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.h
@@ -43,6 +43,8 @@
#include "RenderSurfaceChromium.h"
#include "ShaderChromium.h"
#include "TransformationMatrix.h"
+#include "cc/CCLayerAnimationController.h"
+#include "cc/CCOcclusionTracker.h"
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
@@ -54,8 +56,7 @@
namespace WebCore {
-class CCAnimationEvent;
-class CCLayerAnimationController;
+struct CCAnimationEvent;
class CCLayerAnimationDelegate;
class CCLayerImpl;
class CCLayerTreeHost;
@@ -65,12 +66,20 @@ class ScrollbarLayerChromium;
// Base class for composited layers. Special layer types are derived from
// this class.
-class LayerChromium : public RefCounted<LayerChromium> {
+class LayerChromium : public RefCounted<LayerChromium>, public CCLayerAnimationControllerClient {
public:
static PassRefPtr<LayerChromium> create();
virtual ~LayerChromium();
+ // CCLayerAnimationControllerClient implementation
+ virtual int id() const OVERRIDE { return m_layerId; }
+ virtual void setOpacityFromAnimation(float) OVERRIDE;
+ virtual float opacity() const OVERRIDE { return m_opacity; }
+ virtual void setTransformFromAnimation(const TransformationMatrix&) OVERRIDE;
+ virtual const TransformationMatrix& transform() const OVERRIDE { return m_transform; }
+ virtual const IntSize& bounds() const OVERRIDE { return m_bounds; }
+
const LayerChromium* rootLayer() const;
LayerChromium* parent() const;
void addChild(PassRefPtr<LayerChromium>);
@@ -90,11 +99,7 @@ public:
void setBackgroundColor(const Color&);
Color backgroundColor() const { return m_backgroundColor; }
- void setBackgroundCoversViewport(bool);
- bool backgroundCoversViewport() const { return m_backgroundCoversViewport; }
-
void setBounds(const IntSize&);
- const IntSize& bounds() const { return m_bounds; }
virtual IntSize contentBounds() const { return bounds(); }
void setMasksToBounds(bool);
@@ -108,11 +113,16 @@ public:
virtual bool needsDisplay() const { return m_needsDisplay; }
void setOpacity(float);
- float opacity() const { return m_opacity; }
+ bool opacityIsAnimating() const;
void setFilters(const FilterOperations&);
const FilterOperations& filters() const { return m_filters; }
+ // Background filters are filters applied to what is behind this layer, when they are viewed through non-opaque
+ // regions in this layer. They are used through the WebLayer interface, and are not exposed to HTML.
+ void setBackgroundFilters(const FilterOperations&);
+ const FilterOperations& backgroundFilters() const { return m_backgroundFilters; }
+
virtual void setOpaque(bool);
bool opaque() const { return m_opaque; }
@@ -123,7 +133,7 @@ public:
const TransformationMatrix& sublayerTransform() const { return m_sublayerTransform; }
void setTransform(const TransformationMatrix&);
- const TransformationMatrix& transform() const { return m_transform; }
+ bool transformIsAnimating() const;
const IntRect& visibleLayerRect() const { return m_visibleLayerRect; }
void setVisibleLayerRect(const IntRect& visibleLayerRect) { m_visibleLayerRect = visibleLayerRect; }
@@ -134,7 +144,12 @@ public:
void setScrollable(bool);
void setShouldScrollOnMainThread(bool);
void setHaveWheelEventHandlers(bool);
+ const Region& nonFastScrollableRegion() { return m_nonFastScrollableRegion; }
void setNonFastScrollableRegion(const Region&);
+ void setNonFastScrollableRegionChanged() { m_nonFastScrollableRegionChanged = true; }
+
+ void setDrawCheckerboardForMissingTiles(bool);
+ bool drawCheckerboardForMissingTiles() const { return m_drawCheckerboardForMissingTiles; }
IntSize scrollDelta() const { return IntSize(); }
@@ -161,11 +176,9 @@ public:
// These methods typically need to be overwritten by derived classes.
virtual bool drawsContent() const { return m_isDrawable; }
- virtual void paintContentsIfDirty(const Region& /* occludedScreenSpace */) { }
- virtual void idlePaintContentsIfDirty(const Region& /* occludedScreenSpace */) { }
- virtual void updateCompositorResources(GraphicsContext3D*, CCTextureUpdater&) { }
+ virtual void update(CCTextureUpdater&, const CCOcclusionTracker*) { }
+ virtual void idleUpdate(CCTextureUpdater&, const CCOcclusionTracker*) { }
virtual void setIsMask(bool) { }
- virtual void unreserveContentsTexture() { }
virtual void bindContentsTexture() { }
virtual void protectVisibleTileTextures() { }
virtual bool needsContentsScale() const { return false; }
@@ -176,20 +189,26 @@ public:
virtual void pushPropertiesTo(CCLayerImpl*);
- typedef ProgramBinding<VertexShaderPos, FragmentShaderColor> BorderProgram;
-
- int id() const { return m_layerId; }
-
void clearRenderSurface() { m_renderSurface.clear(); }
RenderSurfaceChromium* renderSurface() const { return m_renderSurface.get(); }
void createRenderSurface();
float drawOpacity() const { return m_drawOpacity; }
void setDrawOpacity(float opacity) { m_drawOpacity = opacity; }
+
+ bool drawOpacityIsAnimating() const { return m_drawOpacityIsAnimating; }
+ void setDrawOpacityIsAnimating(bool drawOpacityIsAnimating) { m_drawOpacityIsAnimating = drawOpacityIsAnimating; }
+
const IntRect& clipRect() const { return m_clipRect; }
void setClipRect(const IntRect& clipRect) { m_clipRect = clipRect; }
RenderSurfaceChromium* targetRenderSurface() const { return m_targetRenderSurface; }
void setTargetRenderSurface(RenderSurfaceChromium* surface) { m_targetRenderSurface = surface; }
+
+ bool drawTransformIsAnimating() const { return m_drawTransformIsAnimating; }
+ void setDrawTransformIsAnimating(bool animating) { m_drawTransformIsAnimating = animating; }
+ bool screenSpaceTransformIsAnimating() const { return m_screenSpaceTransformIsAnimating; }
+ void setScreenSpaceTransformIsAnimating(bool animating) { m_screenSpaceTransformIsAnimating = animating; }
+
// This moves from layer space, with origin in the center to target space with origin in the top left
const TransformationMatrix& drawTransform() const { return m_drawTransform; }
void setDrawTransform(const TransformationMatrix& matrix) { m_drawTransform = matrix; }
@@ -204,7 +223,7 @@ public:
// Returns true if any of the layer's descendants has content to draw.
bool descendantDrawsContent();
- CCLayerTreeHost* layerTreeHost() const { return m_layerTreeHost.get(); }
+ CCLayerTreeHost* layerTreeHost() const { return m_layerTreeHost; }
// Reserve any textures needed for this layer.
virtual void reserveTextures() { }
@@ -216,8 +235,8 @@ public:
void pauseAnimation(int animationId, double timeOffset);
void removeAnimation(int animationId);
- void suspendAnimations(double time);
- void resumeAnimations();
+ void suspendAnimations(double monotonicTime);
+ void resumeAnimations(double monotonicTime);
CCLayerAnimationController* layerAnimationController() { return m_layerAnimationController.get(); }
void setLayerAnimationController(PassOwnPtr<CCLayerAnimationController>);
@@ -226,9 +245,10 @@ public:
bool hasActiveAnimation() const;
- void setAnimationEvent(const CCAnimationEvent&, double wallClockTime);
+ virtual void notifyAnimationStarted(const CCAnimationEvent&, double wallClockTime);
+ virtual void notifyAnimationFinished(double wallClockTime);
- virtual Region opaqueContentsRegion() const { return Region(); };
+ virtual Region visibleContentOpaqueRegion() const;
virtual ScrollbarLayerChromium* toScrollbarLayerChromium() { return 0; }
@@ -244,6 +264,9 @@ protected:
// This flag is set when layer need repainting/updating.
bool m_needsDisplay;
+ // Tracks whether this layer may have changed stacking order with its siblings.
+ bool m_stackingOrderChanged;
+
// The update rect is the region of the compositor resource that was actually updated by the compositor.
// For layers that may do updating outside the compositor's control (i.e. plugin layers), this information
// is not available and the update rect will remain empty.
@@ -271,7 +294,10 @@ private:
Vector<RefPtr<LayerChromium> > m_children;
LayerChromium* m_parent;
- RefPtr<CCLayerTreeHost> m_layerTreeHost;
+ // LayerChromium instances have a weak pointer to their CCLayerTreeHost.
+ // This pointer value is nil when a LayerChromium is not in a tree and is
+ // updated via setLayerTreeHost() if a layer moves between trees.
+ CCLayerTreeHost* m_layerTreeHost;
OwnPtr<CCLayerAnimationController> m_layerAnimationController;
@@ -287,12 +313,12 @@ private:
FloatPoint m_position;
FloatPoint m_anchorPoint;
Color m_backgroundColor;
- bool m_backgroundCoversViewport;
Color m_debugBorderColor;
float m_debugBorderWidth;
String m_debugName;
float m_opacity;
FilterOperations m_filters;
+ FilterOperations m_backgroundFilters;
float m_anchorPointZ;
bool m_isDrawable;
bool m_masksToBounds;
@@ -302,6 +328,7 @@ private:
bool m_isNonCompositedContent;
bool m_preserves3D;
bool m_alwaysReserveTextures;
+ bool m_drawCheckerboardForMissingTiles;
TransformationMatrix m_transform;
TransformationMatrix m_sublayerTransform;
@@ -312,10 +339,13 @@ private:
// Transient properties.
OwnPtr<RenderSurfaceChromium> m_renderSurface;
float m_drawOpacity;
+ bool m_drawOpacityIsAnimating;
IntRect m_clipRect;
RenderSurfaceChromium* m_targetRenderSurface;
TransformationMatrix m_drawTransform;
TransformationMatrix m_screenSpaceTransform;
+ bool m_drawTransformIsAnimating;
+ bool m_screenSpaceTransformIsAnimating;
IntRect m_drawableContentRect;
float m_contentsScale;
diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
index 4ed89fd9e..28f572098 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
@@ -34,39 +34,37 @@
#if USE(ACCELERATED_COMPOSITING)
#include "LayerRendererChromium.h"
-#include "Canvas2DLayerChromium.h"
-#include "CanvasLayerTextureUpdater.h"
+#include "Extensions3D.h"
#include "Extensions3DChromium.h"
#include "FloatQuad.h"
#include "GeometryBinding.h"
+#include "GrTexture.h"
#include "GraphicsContext3D.h"
-#include "LayerChromium.h"
-#include "LayerPainterChromium.h"
#include "ManagedTexture.h"
+#include "NativeImageSkia.h"
#include "NotImplemented.h"
#include "PlatformColor.h"
+#include "PlatformContextSkia.h"
#include "RenderSurfaceChromium.h"
-#include "TextStream.h"
+#include "TextureCopier.h"
#include "TextureManager.h"
#include "TraceEvent.h"
#include "TrackingTextureAllocator.h"
-#include "TreeSynchronizer.h"
-#include "WebGLLayerChromium.h"
-#include "cc/CCCanvasDrawQuad.h"
+#include "cc/CCCheckerboardDrawQuad.h"
#include "cc/CCDamageTracker.h"
#include "cc/CCDebugBorderDrawQuad.h"
+#include "cc/CCIOSurfaceDrawQuad.h"
#include "cc/CCLayerImpl.h"
#include "cc/CCLayerTreeHostCommon.h"
-#include "cc/CCPluginDrawQuad.h"
+#include "cc/CCMathUtil.h"
#include "cc/CCProxy.h"
#include "cc/CCRenderPass.h"
#include "cc/CCRenderSurfaceDrawQuad.h"
#include "cc/CCSolidColorDrawQuad.h"
+#include "cc/CCTextureDrawQuad.h"
#include "cc/CCTileDrawQuad.h"
#include "cc/CCVideoDrawQuad.h"
-#include "Extensions3D.h"
-#include "NativeImageSkia.h"
-#include "PlatformContextSkia.h"
+#include <public/WebVideoFrame.h>
#include <wtf/CurrentTime.h>
#include <wtf/MainThread.h>
@@ -168,6 +166,32 @@ private:
LayerRendererChromium* m_layerRenderer;
};
+class LayerRendererGpuMemoryAllocationChangedCallbackAdapter : public Extensions3DChromium::GpuMemoryAllocationChangedCallbackCHROMIUM {
+public:
+ static PassOwnPtr<LayerRendererGpuMemoryAllocationChangedCallbackAdapter> create(LayerRendererChromium* layerRenderer)
+ {
+ return adoptPtr(new LayerRendererGpuMemoryAllocationChangedCallbackAdapter(layerRenderer));
+ }
+ virtual ~LayerRendererGpuMemoryAllocationChangedCallbackAdapter() { }
+
+ virtual void onGpuMemoryAllocationChanged(Extensions3DChromium::GpuMemoryAllocationCHROMIUM allocation)
+ {
+ if (!allocation.suggestHaveBackbuffer)
+ m_layerRenderer->discardFramebuffer();
+ else
+ m_layerRenderer->ensureFramebuffer();
+ m_layerRenderer->m_client->setContentsMemoryAllocationLimitBytes(allocation.gpuResourceSizeInBytes);
+ }
+
+private:
+ explicit LayerRendererGpuMemoryAllocationChangedCallbackAdapter(LayerRendererChromium* layerRenderer)
+ : m_layerRenderer(layerRenderer)
+ {
+ }
+
+ LayerRendererChromium* m_layerRenderer;
+};
+
PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create(LayerRendererChromiumClient* client, PassRefPtr<GraphicsContext3D> context)
{
@@ -182,11 +206,13 @@ LayerRendererChromium::LayerRendererChromium(LayerRendererChromiumClient* client
PassRefPtr<GraphicsContext3D> context)
: m_client(client)
, m_currentRenderSurface(0)
+ , m_currentManagedTexture(0)
, m_offscreenFramebufferId(0)
, m_context(context)
, m_defaultRenderSurface(0)
, m_sharedGeometryQuad(FloatRect(-0.5f, -0.5f, 1.0f, 1.0f))
, m_isViewportChanged(false)
+ , m_isFramebufferDiscarded(false)
{
}
@@ -262,14 +288,23 @@ bool LayerRendererChromium::initialize()
if (m_capabilities.usingTextureStorageExtension)
extensions->ensureEnabled("GL_EXT_texture_storage");
- GLC(m_context.get(), m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_capabilities.maxTextureSize));
+ m_capabilities.usingGpuMemoryManager = extensions->supports("GL_CHROMIUM_gpu_memory_manager");
+ if (m_capabilities.usingGpuMemoryManager) {
+ extensions->ensureEnabled("GL_CHROMIUM_gpu_memory_manager");
+ Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
+ extensions3DChromium->setGpuMemoryAllocationChangedCallbackCHROMIUM(LayerRendererGpuMemoryAllocationChangedCallbackAdapter::create(this));
+ }
+
+ m_capabilities.usingDiscardFramebuffer = extensions->supports("GL_CHROMIUM_discard_framebuffer");
+ if (m_capabilities.usingDiscardFramebuffer)
+ extensions->ensureEnabled("GL_CHROMIUM_discard_framebuffer");
+
+ GLC(m_context, m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_capabilities.maxTextureSize));
m_capabilities.bestTextureFormat = PlatformColor::bestTextureFormat(m_context.get());
if (!initializeSharedObjects())
return false;
- m_headsUpDisplay = CCHeadsUpDisplay::create(this);
-
// Make sure the viewport and context gets initialized, even if it is to zero.
viewportChanged();
return true;
@@ -280,23 +315,10 @@ LayerRendererChromium::~LayerRendererChromium()
ASSERT(CCProxy::isImplThread());
Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(m_context->getExtensions());
extensions3DChromium->setSwapBuffersCompleteCallbackCHROMIUM(nullptr);
- m_headsUpDisplay.clear(); // Explicitly destroy the HUD before the TextureManager dies.
+ extensions3DChromium->setGpuMemoryAllocationChangedCallbackCHROMIUM(nullptr);
cleanupSharedObjects();
}
-void LayerRendererChromium::clearRenderSurfacesOnCCLayerImplRecursive(CCLayerImpl* layer)
-{
- for (size_t i = 0; i < layer->children().size(); ++i)
- clearRenderSurfacesOnCCLayerImplRecursive(layer->children()[i].get());
- layer->clearRenderSurface();
-}
-
-void LayerRendererChromium::close()
-{
- if (rootLayer())
- clearRenderSurfacesOnCCLayerImplRecursive(rootLayer());
-}
-
GraphicsContext3D* LayerRendererChromium::context()
{
return m_context.get();
@@ -346,37 +368,36 @@ void LayerRendererChromium::clearRenderSurface(CCRenderSurface* renderSurface, C
// of the screen.
if (renderSurface != rootRenderSurface)
- GLC(m_context.get(), m_context->clearColor(0, 0, 0, 0));
+ GLC(m_context, m_context->clearColor(0, 0, 0, 0));
else
- GLC(m_context.get(), m_context->clearColor(0, 0, 1, 1));
+ GLC(m_context, m_context->clearColor(0, 0, 1, 1));
if (m_capabilities.usingPartialSwap)
setScissorToRect(enclosingIntRect(surfaceDamageRect));
else
- GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
+ GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
#if defined(NDEBUG)
if (renderSurface != rootRenderSurface)
#endif
m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
- GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
+ GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST));
}
-void LayerRendererChromium::beginDrawingFrame()
+void LayerRendererChromium::beginDrawingFrame(CCRenderSurface* defaultRenderSurface)
{
- m_defaultRenderSurface = rootLayer()->renderSurface();
+ // FIXME: Remove this once framebuffer is automatically recreated on first use
+ ensureFramebuffer();
- // FIXME: use the frame begin time from the overall compositor scheduler.
- // This value is currently inaccessible because it is up in Chromium's
- // RenderWidget.
- m_headsUpDisplay->onFrameBegin(currentTime());
+ m_defaultRenderSurface = defaultRenderSurface;
+ ASSERT(m_defaultRenderSurface);
size_t contentsMemoryUseBytes = m_contentsTextureAllocator->currentMemoryUseBytes();
size_t maxLimit = TextureManager::highLimitBytes(viewportSize());
m_renderSurfaceTextureManager->setMaxMemoryLimitBytes(maxLimit - contentsMemoryUseBytes);
- if (viewportSize().isEmpty() || !rootLayer())
+ if (viewportSize().isEmpty())
return;
TRACE_EVENT("LayerRendererChromium::drawLayers", this, 0);
@@ -389,18 +410,20 @@ void LayerRendererChromium::beginDrawingFrame()
}
makeContextCurrent();
- // The GL viewport covers the entire visible area, including the scrollbars.
- GLC(m_context.get(), m_context->viewport(0, 0, viewportWidth(), viewportHeight()));
- m_windowMatrix = screenMatrix(0, 0, viewportWidth(), viewportHeight());
-
// Bind the common vertex attributes used for drawing all the layers.
m_sharedGeometry->prepareForDraw();
- GLC(m_context.get(), m_context->disable(GraphicsContext3D::DEPTH_TEST));
- GLC(m_context.get(), m_context->disable(GraphicsContext3D::CULL_FACE));
- GLC(m_context.get(), m_context->colorMask(true, true, true, true));
- GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND));
- GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
+ GLC(m_context, m_context->disable(GraphicsContext3D::DEPTH_TEST));
+ GLC(m_context, m_context->disable(GraphicsContext3D::CULL_FACE));
+ GLC(m_context, m_context->colorMask(true, true, true, true));
+ GLC(m_context, m_context->enable(GraphicsContext3D::BLEND));
+ GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
+}
+
+void LayerRendererChromium::doNoOp()
+{
+ GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
+ GLC(m_context, m_context->flush());
}
void LayerRendererChromium::drawRenderPass(const CCRenderPass* renderPass)
@@ -412,8 +435,8 @@ void LayerRendererChromium::drawRenderPass(const CCRenderPass* renderPass)
clearRenderSurface(renderSurface, m_defaultRenderSurface, renderPass->surfaceDamageRect());
const CCQuadList& quadList = renderPass->quadList();
- for (size_t i = 0; i < quadList.size(); ++i)
- drawQuad(quadList[i].get(), renderPass->surfaceDamageRect());
+ for (CCQuadList::constBackToFrontIterator it = quadList.backToFrontBegin(); it != quadList.backToFrontEnd(); ++it)
+ drawQuad(it->get(), renderPass->surfaceDamageRect());
}
void LayerRendererChromium::drawQuad(const CCDrawQuad* quad, const FloatRect& surfaceDamageRect)
@@ -430,47 +453,78 @@ void LayerRendererChromium::drawQuad(const CCDrawQuad* quad, const FloatRect& su
scissorRect = quad->clipRect();
if (scissorRect.isEmpty())
- GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
+ GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
else
setScissorToRect(scissorRect);
if (quad->needsBlending())
- GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND));
+ GLC(m_context, m_context->enable(GraphicsContext3D::BLEND));
else
- GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND));
+ GLC(m_context, m_context->disable(GraphicsContext3D::BLEND));
switch (quad->material()) {
case CCDrawQuad::Invalid:
ASSERT_NOT_REACHED();
break;
+ case CCDrawQuad::Checkerboard:
+ drawCheckerboardQuad(quad->toCheckerboardDrawQuad());
+ break;
case CCDrawQuad::DebugBorder:
drawDebugBorderQuad(quad->toDebugBorderDrawQuad());
break;
+ case CCDrawQuad::IOSurfaceContent:
+ drawIOSurfaceQuad(quad->toIOSurfaceDrawQuad());
+ break;
case CCDrawQuad::RenderSurface:
drawRenderSurfaceQuad(quad->toRenderSurfaceDrawQuad());
break;
case CCDrawQuad::SolidColor:
drawSolidColorQuad(quad->toSolidColorDrawQuad());
break;
+ case CCDrawQuad::TextureContent:
+ drawTextureQuad(quad->toTextureDrawQuad());
+ break;
case CCDrawQuad::TiledContent:
drawTileQuad(quad->toTileDrawQuad());
break;
- case CCDrawQuad::CanvasContent:
- drawCanvasQuad(quad->toCanvasDrawQuad());
- break;
case CCDrawQuad::VideoContent:
drawVideoQuad(quad->toVideoDrawQuad());
break;
- case CCDrawQuad::PluginContent:
- drawPluginQuad(quad->toPluginDrawQuad());
- break;
}
}
+void LayerRendererChromium::drawCheckerboardQuad(const CCCheckerboardDrawQuad* quad)
+{
+ const TileCheckerboardProgram* program = tileCheckerboardProgram();
+ ASSERT(program && program->initialized());
+ GLC(context(), context()->useProgram(program->program()));
+
+ IntRect tileRect = quad->quadRect();
+ TransformationMatrix tileTransform = quad->quadTransform();
+ tileTransform.translate(tileRect.x() + tileRect.width() / 2.0, tileRect.y() + tileRect.height() / 2.0);
+
+ float texOffsetX = tileRect.x();
+ float texOffsetY = tileRect.y();
+ float texScaleX = tileRect.width();
+ float texScaleY = tileRect.height();
+ GLC(context(), context()->uniform4f(program->fragmentShader().texTransformLocation(), texOffsetX, texOffsetY, texScaleX, texScaleY));
+
+ const int checkerboardWidth = 16;
+ float frequency = 1.0 / checkerboardWidth;
+
+ GLC(context(), context()->uniform1f(program->fragmentShader().frequencyLocation(), frequency));
+
+ float opacity = quad->opacity();
+ drawTexturedQuad(tileTransform,
+ tileRect.width(), tileRect.height(), opacity, FloatQuad(),
+ program->vertexShader().matrixLocation(),
+ program->fragmentShader().alphaLocation(), -1);
+}
+
void LayerRendererChromium::drawDebugBorderQuad(const CCDebugBorderDrawQuad* quad)
{
static float glMatrix[16];
- const LayerChromium::BorderProgram* program = borderProgram();
+ const SolidColorProgram* program = solidColorProgram();
ASSERT(program && program->initialized());
GLC(context(), context()->useProgram(program->program()));
@@ -481,7 +535,10 @@ void LayerRendererChromium::drawDebugBorderQuad(const CCDebugBorderDrawQuad* qua
LayerRendererChromium::toGLMatrix(&glMatrix[0], projectionMatrix() * renderMatrix);
GLC(context(), context()->uniformMatrix4fv(program->vertexShader().matrixLocation(), 1, false, &glMatrix[0]));
- GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), quad->color().red() / 255.0, quad->color().green() / 255.0, quad->color().blue() / 255.0, quad->color().alpha() / 255.0));
+ const Color& color = quad->color();
+ float alpha = color.alpha() / 255.0;
+
+ GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), (color.red() / 255.0) * alpha, (color.green() / 255.0) * alpha, (color.blue() / 255.0) * alpha, alpha));
GLC(context(), context()->lineWidth(quad->width()));
@@ -489,17 +546,80 @@ void LayerRendererChromium::drawDebugBorderQuad(const CCDebugBorderDrawQuad* qua
GLC(context(), context()->drawElements(GraphicsContext3D::LINE_LOOP, 4, GraphicsContext3D::UNSIGNED_SHORT, 6 * sizeof(unsigned short)));
}
+void LayerRendererChromium::drawBackgroundFilters(const CCRenderSurfaceDrawQuad* quad)
+{
+ // This method draws a background filter, which applies a filter to any pixels behind the quad and seen through its background.
+ // The algorithm works as follows:
+ // 1. Compute a bounding box around the pixels that will be visible through the quad.
+ // 2. Read the pixels in the bounding box into a buffer R.
+ // 3. Apply the background filter to R, so that it is applied in the pixels' coordinate space.
+ // 4. Apply the quad's inverse transform to map the pixels in R into the quad's content space. This implicitly
+ // clips R by the content bounds of the quad since the destination texture has bounds matching the quad's content.
+ // 5. Draw the background texture for the contents using the same transform as used to draw the contents itself. This is done
+ // without blending to replace the current background pixels with the new filtered background.
+ // 6. Draw the contents of the quad over drop of the new background with blending, as per usual. The filtered background
+ // pixels will show through any non-opaque pixels in this draws.
+ //
+ // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5.
+
+ CCRenderSurface* drawingSurface = quad->layer()->renderSurface();
+ if (drawingSurface->backgroundFilters().isEmpty())
+ return;
+
+ // FIXME: We only allow background filters on the root render surface because other surfaces may contain
+ // translucent pixels, and the contents behind those translucent pixels wouldn't have the filter applied.
+ if (!isCurrentRenderSurface(m_defaultRenderSurface))
+ return;
+
+ const TransformationMatrix& surfaceDrawTransform = quad->isReplica() ? drawingSurface->replicaDrawTransform() : drawingSurface->drawTransform();
+
+ // FIXME: Do a single readback for both the surface and replica and cache the filtered results (once filter textures are not reused).
+ IntRect deviceRect = drawingSurface->readbackDeviceContentRect(this, surfaceDrawTransform);
+ deviceRect.intersect(m_currentRenderSurface->contentRect());
+
+ OwnPtr<ManagedTexture> deviceBackgroundTexture = ManagedTexture::create(m_renderSurfaceTextureManager.get());
+ if (!getFramebufferTexture(deviceBackgroundTexture.get(), deviceRect))
+ return;
+
+ SkBitmap filteredDeviceBackground = drawingSurface->applyFilters(this, drawingSurface->backgroundFilters(), deviceBackgroundTexture.get());
+ if (!filteredDeviceBackground.getTexture())
+ return;
+
+ GrTexture* texture = reinterpret_cast<GrTexture*>(filteredDeviceBackground.getTexture());
+ int filteredDeviceBackgroundTextureId = texture->getTextureHandle();
+
+ if (!drawingSurface->prepareBackgroundTexture(this))
+ return;
+
+ // This must be computed before switching the target render surface to the background texture.
+ TransformationMatrix contentsDeviceTransform = drawingSurface->computeDeviceTransform(this, surfaceDrawTransform);
+
+ CCRenderSurface* targetRenderSurface = m_currentRenderSurface;
+ if (useManagedTexture(drawingSurface->backgroundTexture(), drawingSurface->contentRect())) {
+ drawingSurface->copyDeviceToBackgroundTexture(this, filteredDeviceBackgroundTextureId, deviceRect, contentsDeviceTransform);
+ useRenderSurface(targetRenderSurface);
+ }
+}
+
void LayerRendererChromium::drawRenderSurfaceQuad(const CCRenderSurfaceDrawQuad* quad)
{
CCLayerImpl* layer = quad->layer();
- layer->renderSurface()->draw(this, quad->surfaceDamageRect());
+
+ drawBackgroundFilters(quad);
+
+ layer->renderSurface()->setScissorRect(this, quad->surfaceDamageRect());
+ if (quad->isReplica())
+ layer->renderSurface()->drawReplica(this);
+ else
+ layer->renderSurface()->drawContents(this);
+ layer->renderSurface()->releaseBackgroundTexture();
layer->renderSurface()->releaseContentsTexture();
}
void LayerRendererChromium::drawSolidColorQuad(const CCSolidColorDrawQuad* quad)
{
- const LayerChromium::BorderProgram* solidColorProgram = borderProgram();
- GLC(context(), context()->useProgram(solidColorProgram->program()));
+ const SolidColorProgram* program = solidColorProgram();
+ GLC(context(), context()->useProgram(program->program()));
IntRect tileRect = quad->quadRect();
@@ -507,13 +627,14 @@ void LayerRendererChromium::drawSolidColorQuad(const CCSolidColorDrawQuad* quad)
tileTransform.translate(tileRect.x() + tileRect.width() / 2.0, tileRect.y() + tileRect.height() / 2.0);
const Color& color = quad->color();
+ float opacity = quad->opacity();
+ float alpha = (color.alpha() / 255.0) * opacity;
- GLC(context(), context()->uniform4f(solidColorProgram->fragmentShader().colorLocation(), color.red() / 255.0, color.green() / 255.0, color.blue() / 255.0, color.alpha() / 255.0));
+ GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), (color.red() / 255.0) * alpha, (color.green() / 255.0) * alpha, (color.blue() / 255.0) * alpha, alpha));
- float opacity = quad->opacity();
drawTexturedQuad(tileTransform,
- tileRect.width(), tileRect.height(), opacity, FloatQuad(),
- solidColorProgram->vertexShader().matrixLocation(),
+ tileRect.width(), tileRect.height(), 1.0, FloatQuad(),
+ program->vertexShader().matrixLocation(),
-1, -1);
}
@@ -542,37 +663,6 @@ static void tileUniformLocation(T program, TileProgramUniforms& uniforms)
uniforms.edgeLocation = program->fragmentShader().edgeLocation();
}
-static void findTileProgramUniforms(LayerRendererChromium* layerRenderer, const CCTileDrawQuad* quad, TileProgramUniforms& uniforms)
-{
- if (quad->isAntialiased()) {
- if (quad->swizzleContents()) {
- const CCTiledLayerImpl::ProgramSwizzleAA* program = layerRenderer->tilerProgramSwizzleAA();
- tileUniformLocation(program, uniforms);
- } else {
- const CCTiledLayerImpl::ProgramAA* program = layerRenderer->tilerProgramAA();
- tileUniformLocation(program, uniforms);
- }
- } else {
- if (quad->needsBlending()) {
- if (quad->swizzleContents()) {
- const CCTiledLayerImpl::ProgramSwizzle* program = layerRenderer->tilerProgramSwizzle();
- tileUniformLocation(program, uniforms);
- } else {
- const CCTiledLayerImpl::Program* program = layerRenderer->tilerProgram();
- tileUniformLocation(program, uniforms);
- }
- } else {
- if (quad->swizzleContents()) {
- const CCTiledLayerImpl::ProgramSwizzleOpaque* program = layerRenderer->tilerProgramSwizzleOpaque();
- tileUniformLocation(program, uniforms);
- } else {
- const CCTiledLayerImpl::ProgramOpaque* program = layerRenderer->tilerProgramOpaque();
- tileUniformLocation(program, uniforms);
- }
- }
- }
-}
-
void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad)
{
const IntRect& tileRect = quad->quadVisibleRect();
@@ -607,8 +697,36 @@ void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad)
float fragmentTexScaleX = clampRect.width() / textureSize.width();
float fragmentTexScaleY = clampRect.height() / textureSize.height();
+
+ FloatQuad localQuad;
+ TransformationMatrix deviceTransform = TransformationMatrix(windowMatrix() * projectionMatrix() * quad->quadTransform()).to2dTransform();
+ if (!deviceTransform.isInvertible())
+ return;
+
+ bool clipped = false;
+ FloatQuad deviceLayerQuad = CCMathUtil::mapQuad(deviceTransform, FloatQuad(quad->layerRect()), clipped);
+
TileProgramUniforms uniforms;
- findTileProgramUniforms(this, quad, uniforms);
+ // For now, we simply skip anti-aliasing with the quad is clipped. This only happens
+ // on perspective transformed layers that go partially behind the camera.
+ if (quad->isAntialiased() && !clipped) {
+ if (quad->swizzleContents())
+ tileUniformLocation(tileProgramSwizzleAA(), uniforms);
+ else
+ tileUniformLocation(tileProgramAA(), uniforms);
+ } else {
+ if (quad->needsBlending()) {
+ if (quad->swizzleContents())
+ tileUniformLocation(tileProgramSwizzle(), uniforms);
+ else
+ tileUniformLocation(tileProgram(), uniforms);
+ } else {
+ if (quad->swizzleContents())
+ tileUniformLocation(tileProgramSwizzleOpaque(), uniforms);
+ else
+ tileUniformLocation(tileProgramOpaque(), uniforms);
+ }
+ }
GLC(context(), context()->useProgram(uniforms.program));
GLC(context(), context()->uniform1i(uniforms.samplerLocation, 0));
@@ -617,13 +735,8 @@ void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad)
GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, quad->textureFilter()));
GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, quad->textureFilter()));
- FloatQuad localQuad;
- if (quad->isAntialiased()) {
- TransformationMatrix deviceTransform = TransformationMatrix(windowMatrix() * projectionMatrix() * quad->quadTransform()).to2dTransform();
- if (!deviceTransform.isInvertible())
- return;
- FloatQuad deviceLayerQuad = deviceTransform.mapQuad(FloatQuad(quad->layerRect()));
+ if (!clipped && quad->isAntialiased()) {
CCLayerQuad deviceLayerBounds = CCLayerQuad(FloatQuad(deviceLayerQuad.boundingBox()));
deviceLayerBounds.inflateAntiAliasingDistance();
@@ -656,13 +769,13 @@ void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad)
CCLayerQuad::Edge rightEdge(topRight, bottomRight);
// Only apply anti-aliasing to edges not clipped during culling.
- if (quad->topEdgeAA() && quad->quadVisibleRect().y() == quad->quadRect().y())
+ if (quad->topEdgeAA() && tileRect.y() == quad->quadRect().y())
topEdge = deviceLayerEdges.top();
- if (quad->leftEdgeAA() && quad->quadVisibleRect().x() == quad->quadRect().x())
+ if (quad->leftEdgeAA() && tileRect.x() == quad->quadRect().x())
leftEdge = deviceLayerEdges.left();
- if (quad->rightEdgeAA() && quad->quadVisibleRect().maxX() == quad->quadRect().maxX())
+ if (quad->rightEdgeAA() && tileRect.maxX() == quad->quadRect().maxX())
rightEdge = deviceLayerEdges.right();
- if (quad->bottomEdgeAA() && quad->quadVisibleRect().maxY() == quad->quadRect().maxY())
+ if (quad->bottomEdgeAA() && tileRect.maxY() == quad->quadRect().maxY())
bottomEdge = deviceLayerEdges.bottom();
float sign = FloatQuad(tileRect).isCounterclockwise() ? -1 : 1;
@@ -700,39 +813,14 @@ void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad)
drawTexturedQuad(quad->quadTransform(), tileRect.width(), tileRect.height(), quad->opacity(), localQuad, uniforms.matrixLocation, uniforms.alphaLocation, uniforms.pointLocation);
}
-void LayerRendererChromium::drawCanvasQuad(const CCCanvasDrawQuad* quad)
-{
- ASSERT(CCProxy::isImplThread());
- const CCCanvasLayerImpl::Program* program = canvasLayerProgram();
- ASSERT(program && program->initialized());
- GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
- GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quad->textureId()));
- GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
- GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
-
- if (quad->hasAlpha() && !quad->premultipliedAlpha())
- GLC(context(), context()->blendFunc(GraphicsContext3D::SRC_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
-
- const IntSize& bounds = quad->quadRect().size();
-
- GLC(context(), context()->useProgram(program->program()));
- GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
- drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), sharedGeometryQuad(),
- program->vertexShader().matrixLocation(),
- program->fragmentShader().alphaLocation(),
- -1);
-
- GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
-}
-
void LayerRendererChromium::drawYUV(const CCVideoDrawQuad* quad)
{
- const CCVideoLayerImpl::YUVProgram* program = videoLayerYUVProgram();
+ const VideoYUVProgram* program = videoYUVProgram();
ASSERT(program && program->initialized());
- const CCVideoLayerImpl::Texture& yTexture = quad->textures()[VideoFrameChromium::yPlane];
- const CCVideoLayerImpl::Texture& uTexture = quad->textures()[VideoFrameChromium::uPlane];
- const CCVideoLayerImpl::Texture& vTexture = quad->textures()[VideoFrameChromium::vPlane];
+ const CCVideoLayerImpl::Texture& yTexture = quad->textures()[WebKit::WebVideoFrame::yPlane];
+ const CCVideoLayerImpl::Texture& uTexture = quad->textures()[WebKit::WebVideoFrame::uPlane];
+ const CCVideoLayerImpl::Texture& vTexture = quad->textures()[WebKit::WebVideoFrame::vPlane];
GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE1));
GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, yTexture.m_texture->textureId()));
@@ -787,23 +875,22 @@ void LayerRendererChromium::drawSingleTextureVideoQuad(const CCVideoDrawQuad* qu
void LayerRendererChromium::drawRGBA(const CCVideoDrawQuad* quad)
{
- const CCVideoLayerImpl::RGBAProgram* program = videoLayerRGBAProgram();
- const CCVideoLayerImpl::Texture& texture = quad->textures()[VideoFrameChromium::rgbPlane];
+ const TextureProgram* program = textureProgram();
+ const CCVideoLayerImpl::Texture& texture = quad->textures()[WebKit::WebVideoFrame::rgbPlane];
float widthScaleFactor = static_cast<float>(texture.m_visibleSize.width()) / texture.m_texture->size().width();
drawSingleTextureVideoQuad(quad, program, widthScaleFactor, texture.m_texture->textureId(), GraphicsContext3D::TEXTURE_2D);
}
void LayerRendererChromium::drawNativeTexture2D(const CCVideoDrawQuad* quad)
{
- const CCVideoLayerImpl::NativeTextureProgram* program = videoLayerNativeTextureProgram();
- drawSingleTextureVideoQuad(quad, program, 1, quad->frame()->textureId(), GraphicsContext3D::TEXTURE_2D);
+ drawSingleTextureVideoQuad(quad, textureProgram(), 1, quad->frame()->textureId(), GraphicsContext3D::TEXTURE_2D);
}
void LayerRendererChromium::drawStreamTexture(const CCVideoDrawQuad* quad)
{
ASSERT(context()->getExtensions()->supports("GL_OES_EGL_image_external") && context()->getExtensions()->isEnabled("GL_OES_EGL_image_external"));
- const CCVideoLayerImpl::StreamTextureProgram* program = streamTextureLayerProgram();
+ const VideoStreamTextureProgram* program = videoStreamTextureProgram();
GLC(context(), context()->useProgram(program->program()));
ASSERT(quad->matrix());
GLC(context(), context()->uniformMatrix4fv(program->vertexShader().texMatrixLocation(), 1, false, const_cast<float*>(quad->matrix())));
@@ -813,12 +900,11 @@ void LayerRendererChromium::drawStreamTexture(const CCVideoDrawQuad* quad)
bool LayerRendererChromium::copyFrameToTextures(const CCVideoDrawQuad* quad)
{
- const VideoFrameChromium* frame = quad->frame();
+ const WebKit::WebVideoFrame* frame = quad->frame();
- for (unsigned plane = 0; plane < frame->planes(); ++plane) {
- ASSERT(quad->frame()->requiredTextureSize(plane) == quad->textures()[plane].m_texture->size());
+ for (unsigned plane = 0; plane < frame->planes(); ++plane)
copyPlaneToTexture(quad, frame->data(plane), plane);
- }
+
for (unsigned plane = frame->planes(); plane < CCVideoLayerImpl::MaxPlanes; ++plane) {
CCVideoLayerImpl::Texture* texture = &quad->textures()[plane];
texture->m_texture.clear();
@@ -875,7 +961,7 @@ void LayerRendererChromium::drawVideoQuad(const CCVideoDrawQuad* quad)
}
}
-struct PluginProgramBinding {
+struct TextureProgramBinding {
template<class Program> void set(Program* program)
{
ASSERT(program && program->initialized());
@@ -890,91 +976,103 @@ struct PluginProgramBinding {
int alphaLocation;
};
-struct TexStretchPluginProgramBinding : PluginProgramBinding {
- template<class Program> void set(Program* program)
- {
- PluginProgramBinding::set(program);
- offsetLocation = program->vertexShader().offsetLocation();
- scaleLocation = program->vertexShader().scaleLocation();
- }
- int offsetLocation;
- int scaleLocation;
-};
-
-struct TexTransformPluginProgramBinding : PluginProgramBinding {
+struct TexTransformTextureProgramBinding : TextureProgramBinding {
template<class Program> void set(Program* program)
{
- PluginProgramBinding::set(program);
+ TextureProgramBinding::set(program);
texTransformLocation = program->vertexShader().texTransformLocation();
}
int texTransformLocation;
};
-void LayerRendererChromium::drawPluginQuad(const CCPluginDrawQuad* quad)
+void LayerRendererChromium::drawTextureQuad(const CCTextureDrawQuad* quad)
{
ASSERT(CCProxy::isImplThread());
- if (quad->ioSurfaceTextureId()) {
- TexTransformPluginProgramBinding binding;
- if (quad->flipped())
- binding.set(pluginLayerTexRectProgramFlip());
- else
- binding.set(pluginLayerTexRectProgram());
-
- GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
- GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, quad->ioSurfaceTextureId()));
-
- GLC(context(), context()->useProgram(binding.programId));
- GLC(context(), context()->uniform1i(binding.samplerLocation, 0));
- // Note: this code path ignores quad->uvRect().
- GLC(context(), context()->uniform4f(binding.texTransformLocation, 0, 0, quad->ioSurfaceWidth(), quad->ioSurfaceHeight()));
- const IntSize& bounds = quad->quadRect().size();
- drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), sharedGeometryQuad(),
- binding.matrixLocation,
- binding.alphaLocation,
- -1);
- GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, 0));
- } else {
- TexStretchPluginProgramBinding binding;
- if (quad->flipped())
- binding.set(pluginLayerProgramFlip());
- else
- binding.set(pluginLayerProgram());
-
- GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
- GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quad->textureId()));
-
- // FIXME: setting the texture parameters every time is redundant. Move this code somewhere
- // where it will only happen once per texture.
- GLC(context, context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
- GLC(context, context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
- GLC(context, context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
- GLC(context, context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
-
- GLC(context, context()->useProgram(binding.programId));
- GLC(context, context()->uniform1i(binding.samplerLocation, 0));
- GLC(context, context()->uniform2f(binding.offsetLocation, quad->uvRect().x(), quad->uvRect().y()));
- GLC(context, context()->uniform2f(binding.scaleLocation, quad->uvRect().width(), quad->uvRect().height()));
- const IntSize& bounds = quad->quadRect().size();
- drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), sharedGeometryQuad(),
- binding.matrixLocation,
- binding.alphaLocation,
- -1);
- }
+ TexTransformTextureProgramBinding binding;
+ if (quad->flipped())
+ binding.set(textureProgramFlip());
+ else
+ binding.set(textureProgram());
+ GLC(context(), context()->useProgram(binding.programId));
+ GLC(context(), context()->uniform1i(binding.samplerLocation, 0));
+ const FloatRect& uvRect = quad->uvRect();
+ GLC(context(), context()->uniform4f(binding.texTransformLocation, uvRect.x(), uvRect.y(), uvRect.width(), uvRect.height()));
+
+ GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
+ GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quad->textureId()));
+
+ // FIXME: setting the texture parameters every time is redundant. Move this code somewhere
+ // where it will only happen once per texture.
+ GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
+ GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
+ GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
+ GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
+
+ if (!quad->premultipliedAlpha())
+ GLC(context(), context()->blendFunc(GraphicsContext3D::SRC_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
+
+ const IntSize& bounds = quad->quadRect().size();
+
+ drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), sharedGeometryQuad(), binding.matrixLocation, binding.alphaLocation, -1);
+
+ if (!quad->premultipliedAlpha())
+ GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
}
-void LayerRendererChromium::finishDrawingFrame()
+void LayerRendererChromium::drawIOSurfaceQuad(const CCIOSurfaceDrawQuad* quad)
{
- if (m_headsUpDisplay->enabled()) {
- GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND));
- GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
- GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
- useRenderSurface(m_defaultRenderSurface);
- m_headsUpDisplay->draw();
- }
+ ASSERT(CCProxy::isImplThread());
+ TexTransformTextureProgramBinding binding;
+ binding.set(textureIOSurfaceProgram());
+
+ GLC(context(), context()->useProgram(binding.programId));
+ GLC(context(), context()->uniform1i(binding.samplerLocation, 0));
+ GLC(context(), context()->uniform4f(binding.texTransformLocation, 0, 0, quad->ioSurfaceSize().width(), quad->ioSurfaceSize().height()));
- GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
- GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND));
+ GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
+ GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, quad->ioSurfaceTextureId()));
+
+ // FIXME: setting the texture parameters every time is redundant. Move this code somewhere
+ // where it will only happen once per texture.
+ GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
+ GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
+ GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
+ GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
+
+ const IntSize& bounds = quad->quadRect().size();
+
+ drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), sharedGeometryQuad(), binding.matrixLocation, binding.alphaLocation, -1);
+
+ GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, 0));
+}
+
+void LayerRendererChromium::drawHeadsUpDisplay(ManagedTexture* hudTexture, const IntSize& hudSize)
+{
+ 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->disable(GraphicsContext3D::SCISSOR_TEST));
+ useRenderSurface(m_defaultRenderSurface);
+
+ const HeadsUpDisplayProgram* program = headsUpDisplayProgram();
+ ASSERT(program && program->initialized());
+ GLC(m_context, m_context->activeTexture(GraphicsContext3D::TEXTURE0));
+ hudTexture->bindTexture(m_context.get(), renderSurfaceTextureAllocator());
+ GLC(m_context, m_context->useProgram(program->program()));
+ GLC(m_context, m_context->uniform1i(program->fragmentShader().samplerLocation(), 0));
+
+ TransformationMatrix matrix;
+ matrix.translate3d(hudSize.width() * 0.5, hudSize.height() * 0.5, 0);
+ drawTexturedQuad(matrix, hudSize.width(), hudSize.height(),
+ 1, sharedGeometryQuad(), program->vertexShader().matrixLocation(),
+ program->fragmentShader().alphaLocation(),
+ -1);
+}
+
+void LayerRendererChromium::finishDrawingFrame()
+{
+ GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
+ GLC(m_context, m_context->disable(GraphicsContext3D::BLEND));
size_t contentsMemoryUseBytes = m_contentsTextureAllocator->currentMemoryUseBytes();
size_t reclaimLimit = TextureManager::reclaimLimitBytes(viewportSize());
@@ -982,9 +1080,6 @@ void LayerRendererChromium::finishDrawingFrame()
m_renderSurfaceTextureManager->setPreferredMemoryLimitBytes(preferredLimit);
m_renderSurfaceTextureManager->reduceMemoryToLimit(preferredLimit);
m_renderSurfaceTextureManager->deleteEvictedTextures(m_renderSurfaceTextureAllocator.get());
-
- if (settings().compositeOffscreen)
- copyOffscreenTextureToDisplay();
}
void LayerRendererChromium::toGLMatrix(float* flattened, const TransformationMatrix& m)
@@ -1048,8 +1143,15 @@ void LayerRendererChromium::finish()
m_context->finish();
}
-void LayerRendererChromium::swapBuffers(const IntRect& subBuffer)
+bool LayerRendererChromium::swapBuffers(const IntRect& subBuffer)
{
+ // FIXME: Remove this once gpu process supports ignoring swap buffers command while framebuffer is discarded.
+ // Alternatively (preferably?), protect all cc code so as not to attempt a swap after a framebuffer discard.
+ if (m_isFramebufferDiscarded) {
+ m_client->setFullRootLayerDamage();
+ return false;
+ }
+
TRACE_EVENT("LayerRendererChromium::swapBuffers", this, 0);
// We're done! Time to swapbuffers!
@@ -1065,7 +1167,7 @@ void LayerRendererChromium::swapBuffers(const IntRect& subBuffer)
// consider exposing a different entry point on GraphicsContext3D.
m_context->prepareTexture();
- m_headsUpDisplay->onSwapBuffers();
+ return true;
}
void LayerRendererChromium::onSwapBuffersComplete()
@@ -1073,6 +1175,38 @@ void LayerRendererChromium::onSwapBuffersComplete()
m_client->onSwapBuffersComplete();
}
+void LayerRendererChromium::discardFramebuffer()
+{
+ if (m_isFramebufferDiscarded)
+ return;
+
+ if (!m_capabilities.usingDiscardFramebuffer)
+ return;
+
+ Extensions3D* extensions = m_context->getExtensions();
+ Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
+ // FIXME: Update attachments argument to appropriate values once they are no longer ignored.
+ extensions3DChromium->discardFramebufferEXT(GraphicsContext3D::TEXTURE_2D, 0, 0);
+ m_isFramebufferDiscarded = true;
+
+ // Damage tracker needs a full reset every time framebuffer is discarded.
+ m_client->setFullRootLayerDamage();
+}
+
+void LayerRendererChromium::ensureFramebuffer()
+{
+ if (!m_isFramebufferDiscarded)
+ return;
+
+ if (!m_capabilities.usingDiscardFramebuffer)
+ return;
+
+ Extensions3D* extensions = m_context->getExtensions();
+ Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
+ extensions3DChromium->ensureFramebufferCHROMIUM();
+ m_isFramebufferDiscarded = false;
+}
+
void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect)
{
ASSERT(rect.maxX() <= viewportWidth() && rect.maxY() <= viewportHeight());
@@ -1122,47 +1256,54 @@ void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& re
}
}
-ManagedTexture* LayerRendererChromium::getOffscreenLayerTexture()
+bool LayerRendererChromium::getFramebufferTexture(ManagedTexture* texture, const IntRect& deviceRect)
{
- return settings().compositeOffscreen && rootLayer() ? rootLayer()->renderSurface()->contentsTexture() : 0;
+ if (!texture->reserve(deviceRect.size(), GraphicsContext3D::RGB))
+ return false;
+
+ texture->bindTexture(m_context.get(), m_renderSurfaceTextureAllocator.get());
+ GLC(m_context, m_context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, texture->format(),
+ deviceRect.x(), deviceRect.y(), deviceRect.width(), deviceRect.height(), 0));
+ return true;
}
-void LayerRendererChromium::copyOffscreenTextureToDisplay()
+bool LayerRendererChromium::isCurrentRenderSurface(CCRenderSurface* renderSurface)
{
- if (settings().compositeOffscreen) {
- makeContextCurrent();
-
- useRenderSurface(0);
- TransformationMatrix drawTransform;
- drawTransform.translate3d(0.5 * m_defaultRenderSurface->contentRect().width(), 0.5 * m_defaultRenderSurface->contentRect().height(), 0);
- m_defaultRenderSurface->setDrawTransform(drawTransform);
- m_defaultRenderSurface->setDrawOpacity(1);
- m_defaultRenderSurface->draw(this, m_defaultRenderSurface->contentRect());
- }
+ // If renderSurface is 0, we can't tell if we are already using it, since m_currentRenderSurface is
+ // initialized to 0.
+ return m_currentRenderSurface == renderSurface && !m_currentManagedTexture;
}
bool LayerRendererChromium::useRenderSurface(CCRenderSurface* renderSurface)
{
- if (m_currentRenderSurface == renderSurface)
- return true;
-
m_currentRenderSurface = renderSurface;
+ m_currentManagedTexture = 0;
- if ((renderSurface == m_defaultRenderSurface && !settings().compositeOffscreen) || (!renderSurface && settings().compositeOffscreen)) {
- GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
- if (renderSurface)
- setDrawViewportRect(renderSurface->contentRect(), true);
- else
- setDrawViewportRect(m_defaultRenderSurface->contentRect(), true);
+ if (renderSurface == m_defaultRenderSurface) {
+ GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
+ setDrawViewportRect(renderSurface->contentRect(), true);
return true;
}
- GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId));
-
if (!renderSurface->prepareContentsTexture(this))
return false;
- renderSurface->contentsTexture()->framebufferTexture2D(m_context.get(), m_renderSurfaceTextureAllocator.get());
+ return bindFramebufferToTexture(renderSurface->contentsTexture(), renderSurface->contentRect());
+}
+
+bool LayerRendererChromium::useManagedTexture(ManagedTexture* texture, const IntRect& viewportRect)
+{
+ m_currentRenderSurface = 0;
+ m_currentManagedTexture = texture;
+
+ return bindFramebufferToTexture(texture, viewportRect);
+}
+
+bool LayerRendererChromium::bindFramebufferToTexture(ManagedTexture* texture, const IntRect& viewportRect)
+{
+ GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId));
+
+ texture->framebufferTexture2D(m_context.get(), m_renderSurfaceTextureAllocator.get());
#if !defined ( NDEBUG )
if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
@@ -1171,7 +1312,7 @@ bool LayerRendererChromium::useRenderSurface(CCRenderSurface* renderSurface)
}
#endif
- setDrawViewportRect(renderSurface->contentRect(), false);
+ setDrawViewportRect(viewportRect, false);
return true;
}
@@ -1182,7 +1323,7 @@ void LayerRendererChromium::setScissorToRect(const IntRect& scissorRect)
{
IntRect contentRect = (m_currentRenderSurface ? m_currentRenderSurface->contentRect() : m_defaultRenderSurface->contentRect());
- GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
+ GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST));
// 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.
@@ -1191,11 +1332,11 @@ void LayerRendererChromium::setScissorToRect(const IntRect& scissorRect)
// of the GL scissor is the bottom of our layer.
// But, if rendering to offscreen texture, we reverse our sense of 'upside down'.
int scissorY;
- if (m_currentRenderSurface == m_defaultRenderSurface && !settings().compositeOffscreen)
+ if (isCurrentRenderSurface(m_defaultRenderSurface))
scissorY = m_currentRenderSurface->contentRect().height() - (scissorRect.maxY() - m_currentRenderSurface->contentRect().y());
else
scissorY = scissorRect.y() - contentRect.y();
- GLC(m_context.get(), m_context->scissor(scissorX, scissorY, scissorRect.width(), scissorRect.height()));
+ GLC(m_context, m_context->scissor(scissorX, scissorY, scissorRect.width(), scissorRect.height()));
}
bool LayerRendererChromium::makeContextCurrent()
@@ -1212,7 +1353,7 @@ void LayerRendererChromium::setDrawViewportRect(const IntRect& drawRect, bool fl
m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.maxY(), drawRect.y());
else
m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.y(), drawRect.maxY());
- GLC(m_context.get(), m_context->viewport(0, 0, drawRect.width(), drawRect.height()));
+ GLC(m_context, m_context->viewport(0, 0, drawRect.width(), drawRect.height()));
m_windowMatrix = screenMatrix(0, 0, drawRect.width(), drawRect.height());
}
@@ -1223,20 +1364,22 @@ bool LayerRendererChromium::initializeSharedObjects()
makeContextCurrent();
// Create an FBO for doing offscreen rendering.
- GLC(m_context.get(), m_offscreenFramebufferId = m_context->createFramebuffer());
+ GLC(m_context, m_offscreenFramebufferId = m_context->createFramebuffer());
// We will always need these programs to render, so create the programs eagerly so that the shader compilation can
// start while we do other work. Other programs are created lazily on first access.
m_sharedGeometry = adoptPtr(new GeometryBinding(m_context.get()));
- m_renderSurfaceProgram = adoptPtr(new CCRenderSurface::Program(m_context.get()));
- m_tilerProgram = adoptPtr(new CCTiledLayerImpl::Program(m_context.get()));
- m_tilerProgramOpaque = adoptPtr(new CCTiledLayerImpl::ProgramOpaque(m_context.get()));
+ m_renderSurfaceProgram = adoptPtr(new RenderSurfaceProgram(m_context.get()));
+ m_tileProgram = adoptPtr(new TileProgram(m_context.get()));
+ m_tileProgramOpaque = adoptPtr(new TileProgramOpaque(m_context.get()));
- GLC(m_context.get(), m_context->flush());
+ GLC(m_context, m_context->flush());
m_renderSurfaceTextureManager = TextureManager::create(TextureManager::highLimitBytes(viewportSize()),
TextureManager::reclaimLimitBytes(viewportSize()),
m_capabilities.maxTextureSize);
+ m_textureCopier = AcceleratedTextureCopier::create(m_context.get());
+ m_textureUploader = AcceleratedTextureUploader::create(m_context.get());
m_contentsTextureAllocator = TrackingTextureAllocator::create(m_context.get());
m_renderSurfaceTextureAllocator = TrackingTextureAllocator::create(m_context.get());
if (m_capabilities.usingTextureUsageHint)
@@ -1249,21 +1392,32 @@ bool LayerRendererChromium::initializeSharedObjects()
return true;
}
-const LayerChromium::BorderProgram* LayerRendererChromium::borderProgram()
+const LayerRendererChromium::TileCheckerboardProgram* LayerRendererChromium::tileCheckerboardProgram()
{
- if (!m_borderProgram)
- m_borderProgram = adoptPtr(new LayerChromium::BorderProgram(m_context.get()));
- if (!m_borderProgram->initialized()) {
- TRACE_EVENT("LayerRendererChromium::borderProgram::initialize", this, 0);
- m_borderProgram->initialize(m_context.get());
+ if (!m_tileCheckerboardProgram)
+ m_tileCheckerboardProgram = adoptPtr(new TileCheckerboardProgram(m_context.get()));
+ if (!m_tileCheckerboardProgram->initialized()) {
+ TRACE_EVENT("LayerRendererChromium::checkerboardProgram::initalize", this, 0);
+ m_tileCheckerboardProgram->initialize(m_context.get());
}
- return m_borderProgram.get();
+ return m_tileCheckerboardProgram.get();
}
-const CCHeadsUpDisplay::Program* LayerRendererChromium::headsUpDisplayProgram()
+const LayerRendererChromium::SolidColorProgram* LayerRendererChromium::solidColorProgram()
+{
+ if (!m_solidColorProgram)
+ m_solidColorProgram = adoptPtr(new SolidColorProgram(m_context.get()));
+ if (!m_solidColorProgram->initialized()) {
+ TRACE_EVENT("LayerRendererChromium::solidColorProgram::initialize", this, 0);
+ m_solidColorProgram->initialize(m_context.get());
+ }
+ return m_solidColorProgram.get();
+}
+
+const LayerRendererChromium::HeadsUpDisplayProgram* LayerRendererChromium::headsUpDisplayProgram()
{
if (!m_headsUpDisplayProgram)
- m_headsUpDisplayProgram = adoptPtr(new CCHeadsUpDisplay::Program(m_context.get()));
+ m_headsUpDisplayProgram = adoptPtr(new HeadsUpDisplayProgram(m_context.get()));
if (!m_headsUpDisplayProgram->initialized()) {
TRACE_EVENT("LayerRendererChromium::headsUpDisplayProgram::initialize", this, 0);
m_headsUpDisplayProgram->initialize(m_context.get());
@@ -1271,7 +1425,7 @@ const CCHeadsUpDisplay::Program* LayerRendererChromium::headsUpDisplayProgram()
return m_headsUpDisplayProgram.get();
}
-const CCRenderSurface::Program* LayerRendererChromium::renderSurfaceProgram()
+const LayerRendererChromium::RenderSurfaceProgram* LayerRendererChromium::renderSurfaceProgram()
{
ASSERT(m_renderSurfaceProgram);
if (!m_renderSurfaceProgram->initialized()) {
@@ -1281,10 +1435,10 @@ const CCRenderSurface::Program* LayerRendererChromium::renderSurfaceProgram()
return m_renderSurfaceProgram.get();
}
-const CCRenderSurface::ProgramAA* LayerRendererChromium::renderSurfaceProgramAA()
+const LayerRendererChromium::RenderSurfaceProgramAA* LayerRendererChromium::renderSurfaceProgramAA()
{
if (!m_renderSurfaceProgramAA)
- m_renderSurfaceProgramAA = adoptPtr(new CCRenderSurface::ProgramAA(m_context.get()));
+ m_renderSurfaceProgramAA = adoptPtr(new RenderSurfaceProgramAA(m_context.get()));
if (!m_renderSurfaceProgramAA->initialized()) {
TRACE_EVENT("LayerRendererChromium::renderSurfaceProgramAA::initialize", this, 0);
m_renderSurfaceProgramAA->initialize(m_context.get());
@@ -1292,10 +1446,10 @@ const CCRenderSurface::ProgramAA* LayerRendererChromium::renderSurfaceProgramAA(
return m_renderSurfaceProgramAA.get();
}
-const CCRenderSurface::MaskProgram* LayerRendererChromium::renderSurfaceMaskProgram()
+const LayerRendererChromium::RenderSurfaceMaskProgram* LayerRendererChromium::renderSurfaceMaskProgram()
{
if (!m_renderSurfaceMaskProgram)
- m_renderSurfaceMaskProgram = adoptPtr(new CCRenderSurface::MaskProgram(m_context.get()));
+ m_renderSurfaceMaskProgram = adoptPtr(new RenderSurfaceMaskProgram(m_context.get()));
if (!m_renderSurfaceMaskProgram->initialized()) {
TRACE_EVENT("LayerRendererChromium::renderSurfaceMaskProgram::initialize", this, 0);
m_renderSurfaceMaskProgram->initialize(m_context.get());
@@ -1303,10 +1457,10 @@ const CCRenderSurface::MaskProgram* LayerRendererChromium::renderSurfaceMaskProg
return m_renderSurfaceMaskProgram.get();
}
-const CCRenderSurface::MaskProgramAA* LayerRendererChromium::renderSurfaceMaskProgramAA()
+const LayerRendererChromium::RenderSurfaceMaskProgramAA* LayerRendererChromium::renderSurfaceMaskProgramAA()
{
if (!m_renderSurfaceMaskProgramAA)
- m_renderSurfaceMaskProgramAA = adoptPtr(new CCRenderSurface::MaskProgramAA(m_context.get()));
+ m_renderSurfaceMaskProgramAA = adoptPtr(new RenderSurfaceMaskProgramAA(m_context.get()));
if (!m_renderSurfaceMaskProgramAA->initialized()) {
TRACE_EVENT("LayerRendererChromium::renderSurfaceMaskProgramAA::initialize", this, 0);
m_renderSurfaceMaskProgramAA->initialize(m_context.get());
@@ -1314,167 +1468,123 @@ const CCRenderSurface::MaskProgramAA* LayerRendererChromium::renderSurfaceMaskPr
return m_renderSurfaceMaskProgramAA.get();
}
-const CCTiledLayerImpl::Program* LayerRendererChromium::tilerProgram()
-{
- ASSERT(m_tilerProgram);
- if (!m_tilerProgram->initialized()) {
- TRACE_EVENT("LayerRendererChromium::tilerProgram::initialize", this, 0);
- m_tilerProgram->initialize(m_context.get());
- }
- return m_tilerProgram.get();
-}
-
-const CCTiledLayerImpl::ProgramOpaque* LayerRendererChromium::tilerProgramOpaque()
-{
- ASSERT(m_tilerProgramOpaque);
- if (!m_tilerProgramOpaque->initialized()) {
- TRACE_EVENT("LayerRendererChromium::tilerProgramOpaque::initialize", this, 0);
- m_tilerProgramOpaque->initialize(m_context.get());
- }
- return m_tilerProgramOpaque.get();
-}
-
-const CCTiledLayerImpl::ProgramAA* LayerRendererChromium::tilerProgramAA()
-{
- if (!m_tilerProgramAA)
- m_tilerProgramAA = adoptPtr(new CCTiledLayerImpl::ProgramAA(m_context.get()));
- if (!m_tilerProgramAA->initialized()) {
- TRACE_EVENT("LayerRendererChromium::tilerProgramAA::initialize", this, 0);
- m_tilerProgramAA->initialize(m_context.get());
- }
- return m_tilerProgramAA.get();
-}
-
-const CCTiledLayerImpl::ProgramSwizzle* LayerRendererChromium::tilerProgramSwizzle()
-{
- if (!m_tilerProgramSwizzle)
- m_tilerProgramSwizzle = adoptPtr(new CCTiledLayerImpl::ProgramSwizzle(m_context.get()));
- if (!m_tilerProgramSwizzle->initialized()) {
- TRACE_EVENT("LayerRendererChromium::tilerProgramSwizzle::initialize", this, 0);
- m_tilerProgramSwizzle->initialize(m_context.get());
- }
- return m_tilerProgramSwizzle.get();
-}
-
-const CCTiledLayerImpl::ProgramSwizzleOpaque* LayerRendererChromium::tilerProgramSwizzleOpaque()
+const LayerRendererChromium::TileProgram* LayerRendererChromium::tileProgram()
{
- if (!m_tilerProgramSwizzleOpaque)
- m_tilerProgramSwizzleOpaque = adoptPtr(new CCTiledLayerImpl::ProgramSwizzleOpaque(m_context.get()));
- if (!m_tilerProgramSwizzleOpaque->initialized()) {
- TRACE_EVENT("LayerRendererChromium::tilerProgramSwizzleOpaque::initialize", this, 0);
- m_tilerProgramSwizzleOpaque->initialize(m_context.get());
+ ASSERT(m_tileProgram);
+ if (!m_tileProgram->initialized()) {
+ TRACE_EVENT("LayerRendererChromium::tileProgram::initialize", this, 0);
+ m_tileProgram->initialize(m_context.get());
}
- return m_tilerProgramSwizzleOpaque.get();
+ return m_tileProgram.get();
}
-const CCTiledLayerImpl::ProgramSwizzleAA* LayerRendererChromium::tilerProgramSwizzleAA()
+const LayerRendererChromium::TileProgramOpaque* LayerRendererChromium::tileProgramOpaque()
{
- if (!m_tilerProgramSwizzleAA)
- m_tilerProgramSwizzleAA = adoptPtr(new CCTiledLayerImpl::ProgramSwizzleAA(m_context.get()));
- if (!m_tilerProgramSwizzleAA->initialized()) {
- TRACE_EVENT("LayerRendererChromium::tilerProgramSwizzleAA::initialize", this, 0);
- m_tilerProgramSwizzleAA->initialize(m_context.get());
+ ASSERT(m_tileProgramOpaque);
+ if (!m_tileProgramOpaque->initialized()) {
+ TRACE_EVENT("LayerRendererChromium::tileProgramOpaque::initialize", this, 0);
+ m_tileProgramOpaque->initialize(m_context.get());
}
- return m_tilerProgramSwizzleAA.get();
+ return m_tileProgramOpaque.get();
}
-const CCCanvasLayerImpl::Program* LayerRendererChromium::canvasLayerProgram()
+const LayerRendererChromium::TileProgramAA* LayerRendererChromium::tileProgramAA()
{
- if (!m_canvasLayerProgram)
- m_canvasLayerProgram = adoptPtr(new CCCanvasLayerImpl::Program(m_context.get()));
- if (!m_canvasLayerProgram->initialized()) {
- TRACE_EVENT("LayerRendererChromium::canvasLayerProgram::initialize", this, 0);
- m_canvasLayerProgram->initialize(m_context.get());
+ if (!m_tileProgramAA)
+ m_tileProgramAA = adoptPtr(new TileProgramAA(m_context.get()));
+ if (!m_tileProgramAA->initialized()) {
+ TRACE_EVENT("LayerRendererChromium::tileProgramAA::initialize", this, 0);
+ m_tileProgramAA->initialize(m_context.get());
}
- return m_canvasLayerProgram.get();
+ return m_tileProgramAA.get();
}
-const CCPluginLayerImpl::Program* LayerRendererChromium::pluginLayerProgram()
+const LayerRendererChromium::TileProgramSwizzle* LayerRendererChromium::tileProgramSwizzle()
{
- if (!m_pluginLayerProgram)
- m_pluginLayerProgram = adoptPtr(new CCPluginLayerImpl::Program(m_context.get()));
- if (!m_pluginLayerProgram->initialized()) {
- TRACE_EVENT("LayerRendererChromium::pluginLayerProgram::initialize", this, 0);
- m_pluginLayerProgram->initialize(m_context.get());
+ if (!m_tileProgramSwizzle)
+ m_tileProgramSwizzle = adoptPtr(new TileProgramSwizzle(m_context.get()));
+ if (!m_tileProgramSwizzle->initialized()) {
+ TRACE_EVENT("LayerRendererChromium::tileProgramSwizzle::initialize", this, 0);
+ m_tileProgramSwizzle->initialize(m_context.get());
}
- return m_pluginLayerProgram.get();
+ return m_tileProgramSwizzle.get();
}
-const CCPluginLayerImpl::ProgramFlip* LayerRendererChromium::pluginLayerProgramFlip()
+const LayerRendererChromium::TileProgramSwizzleOpaque* LayerRendererChromium::tileProgramSwizzleOpaque()
{
- if (!m_pluginLayerProgramFlip)
- m_pluginLayerProgramFlip = adoptPtr(new CCPluginLayerImpl::ProgramFlip(m_context.get()));
- if (!m_pluginLayerProgramFlip->initialized()) {
- TRACE_EVENT("LayerRendererChromium::pluginLayerProgramFlip::initialize", this, 0);
- m_pluginLayerProgramFlip->initialize(m_context.get());
+ if (!m_tileProgramSwizzleOpaque)
+ m_tileProgramSwizzleOpaque = adoptPtr(new TileProgramSwizzleOpaque(m_context.get()));
+ if (!m_tileProgramSwizzleOpaque->initialized()) {
+ TRACE_EVENT("LayerRendererChromium::tileProgramSwizzleOpaque::initialize", this, 0);
+ m_tileProgramSwizzleOpaque->initialize(m_context.get());
}
- return m_pluginLayerProgramFlip.get();
+ return m_tileProgramSwizzleOpaque.get();
}
-const CCPluginLayerImpl::TexRectProgram* LayerRendererChromium::pluginLayerTexRectProgram()
+const LayerRendererChromium::TileProgramSwizzleAA* LayerRendererChromium::tileProgramSwizzleAA()
{
- if (!m_pluginLayerTexRectProgram)
- m_pluginLayerTexRectProgram = adoptPtr(new CCPluginLayerImpl::TexRectProgram(m_context.get()));
- if (!m_pluginLayerTexRectProgram->initialized()) {
- TRACE_EVENT("LayerRendererChromium::pluginLayerTexRectProgram::initialize", this, 0);
- m_pluginLayerTexRectProgram->initialize(m_context.get());
+ if (!m_tileProgramSwizzleAA)
+ m_tileProgramSwizzleAA = adoptPtr(new TileProgramSwizzleAA(m_context.get()));
+ if (!m_tileProgramSwizzleAA->initialized()) {
+ TRACE_EVENT("LayerRendererChromium::tileProgramSwizzleAA::initialize", this, 0);
+ m_tileProgramSwizzleAA->initialize(m_context.get());
}
- return m_pluginLayerTexRectProgram.get();
+ return m_tileProgramSwizzleAA.get();
}
-const CCPluginLayerImpl::TexRectProgramFlip* LayerRendererChromium::pluginLayerTexRectProgramFlip()
+const LayerRendererChromium::TextureProgram* LayerRendererChromium::textureProgram()
{
- if (!m_pluginLayerTexRectProgramFlip)
- m_pluginLayerTexRectProgramFlip = adoptPtr(new CCPluginLayerImpl::TexRectProgramFlip(m_context.get()));
- if (!m_pluginLayerTexRectProgramFlip->initialized()) {
- TRACE_EVENT("LayerRendererChromium::pluginLayerTexRectProgramFlip::initialize", this, 0);
- m_pluginLayerTexRectProgramFlip->initialize(m_context.get());
+ if (!m_textureProgram)
+ m_textureProgram = adoptPtr(new TextureProgram(m_context.get()));
+ if (!m_textureProgram->initialized()) {
+ TRACE_EVENT("LayerRendererChromium::textureProgram::initialize", this, 0);
+ m_textureProgram->initialize(m_context.get());
}
- return m_pluginLayerTexRectProgramFlip.get();
+ return m_textureProgram.get();
}
-const CCVideoLayerImpl::RGBAProgram* LayerRendererChromium::videoLayerRGBAProgram()
+const LayerRendererChromium::TextureProgramFlip* LayerRendererChromium::textureProgramFlip()
{
- if (!m_videoLayerRGBAProgram)
- m_videoLayerRGBAProgram = adoptPtr(new CCVideoLayerImpl::RGBAProgram(m_context.get()));
- if (!m_videoLayerRGBAProgram->initialized()) {
- TRACE_EVENT("LayerRendererChromium::videoLayerRGBAProgram::initialize", this, 0);
- m_videoLayerRGBAProgram->initialize(m_context.get());
+ if (!m_textureProgramFlip)
+ m_textureProgramFlip = adoptPtr(new TextureProgramFlip(m_context.get()));
+ if (!m_textureProgramFlip->initialized()) {
+ TRACE_EVENT("LayerRendererChromium::textureProgramFlip::initialize", this, 0);
+ m_textureProgramFlip->initialize(m_context.get());
}
- return m_videoLayerRGBAProgram.get();
+ return m_textureProgramFlip.get();
}
-const CCVideoLayerImpl::YUVProgram* LayerRendererChromium::videoLayerYUVProgram()
+const LayerRendererChromium::TextureIOSurfaceProgram* LayerRendererChromium::textureIOSurfaceProgram()
{
- if (!m_videoLayerYUVProgram)
- m_videoLayerYUVProgram = adoptPtr(new CCVideoLayerImpl::YUVProgram(m_context.get()));
- if (!m_videoLayerYUVProgram->initialized()) {
- TRACE_EVENT("LayerRendererChromium::videoLayerYUVProgram::initialize", this, 0);
- m_videoLayerYUVProgram->initialize(m_context.get());
+ if (!m_textureIOSurfaceProgram)
+ m_textureIOSurfaceProgram = adoptPtr(new TextureIOSurfaceProgram(m_context.get()));
+ if (!m_textureIOSurfaceProgram->initialized()) {
+ TRACE_EVENT("LayerRendererChromium::textureIOSurfaceProgram::initialize", this, 0);
+ m_textureIOSurfaceProgram->initialize(m_context.get());
}
- return m_videoLayerYUVProgram.get();
+ return m_textureIOSurfaceProgram.get();
}
-const CCVideoLayerImpl::NativeTextureProgram* LayerRendererChromium::videoLayerNativeTextureProgram()
+const LayerRendererChromium::VideoYUVProgram* LayerRendererChromium::videoYUVProgram()
{
- if (!m_videoLayerNativeTextureProgram)
- m_videoLayerNativeTextureProgram = adoptPtr(new CCVideoLayerImpl::NativeTextureProgram(m_context.get()));
- if (!m_videoLayerNativeTextureProgram->initialized()) {
- TRACE_EVENT("LayerRendererChromium::videoLayerNativeTextureProgram::initialize", this, 0);
- m_videoLayerNativeTextureProgram->initialize(m_context.get());
+ if (!m_videoYUVProgram)
+ m_videoYUVProgram = adoptPtr(new VideoYUVProgram(m_context.get()));
+ if (!m_videoYUVProgram->initialized()) {
+ TRACE_EVENT("LayerRendererChromium::videoYUVProgram::initialize", this, 0);
+ m_videoYUVProgram->initialize(m_context.get());
}
- return m_videoLayerNativeTextureProgram.get();
+ return m_videoYUVProgram.get();
}
-const CCVideoLayerImpl::StreamTextureProgram* LayerRendererChromium::streamTextureLayerProgram()
+const LayerRendererChromium::VideoStreamTextureProgram* LayerRendererChromium::videoStreamTextureProgram()
{
- if (!m_streamTextureLayerProgram)
- m_streamTextureLayerProgram = adoptPtr(new CCVideoLayerImpl::StreamTextureProgram(m_context.get()));
- if (!m_streamTextureLayerProgram->initialized()) {
- TRACE_EVENT("LayerRendererChromium::streamTextureLayerProgram::initialize", this, 0);
- m_streamTextureLayerProgram->initialize(m_context.get());
+ if (!m_videoStreamTextureProgram)
+ m_videoStreamTextureProgram = adoptPtr(new VideoStreamTextureProgram(m_context.get()));
+ if (!m_videoStreamTextureProgram->initialized()) {
+ TRACE_EVENT("LayerRendererChromium::streamTextureProgram::initialize", this, 0);
+ m_videoStreamTextureProgram->initialize(m_context.get());
}
- return m_streamTextureLayerProgram.get();
+ return m_videoStreamTextureProgram.get();
}
void LayerRendererChromium::cleanupSharedObjects()
@@ -1483,32 +1593,21 @@ void LayerRendererChromium::cleanupSharedObjects()
m_sharedGeometry.clear();
- if (m_borderProgram)
- m_borderProgram->cleanup(m_context.get());
- if (m_headsUpDisplayProgram)
- m_headsUpDisplayProgram->cleanup(m_context.get());
- if (m_tilerProgram)
- m_tilerProgram->cleanup(m_context.get());
- if (m_tilerProgramOpaque)
- m_tilerProgramOpaque->cleanup(m_context.get());
- if (m_tilerProgramSwizzle)
- m_tilerProgramSwizzle->cleanup(m_context.get());
- if (m_tilerProgramSwizzleOpaque)
- m_tilerProgramSwizzleOpaque->cleanup(m_context.get());
- if (m_tilerProgramAA)
- m_tilerProgramAA->cleanup(m_context.get());
- if (m_tilerProgramSwizzleAA)
- m_tilerProgramSwizzleAA->cleanup(m_context.get());
- if (m_canvasLayerProgram)
- m_canvasLayerProgram->cleanup(m_context.get());
- if (m_pluginLayerProgram)
- m_pluginLayerProgram->cleanup(m_context.get());
- if (m_pluginLayerProgramFlip)
- m_pluginLayerProgramFlip->cleanup(m_context.get());
- if (m_pluginLayerTexRectProgram)
- m_pluginLayerTexRectProgram->cleanup(m_context.get());
- if (m_pluginLayerTexRectProgramFlip)
- m_pluginLayerTexRectProgramFlip->cleanup(m_context.get());
+ if (m_tileProgram)
+ m_tileProgram->cleanup(m_context.get());
+ if (m_tileProgramOpaque)
+ m_tileProgramOpaque->cleanup(m_context.get());
+ if (m_tileProgramSwizzle)
+ m_tileProgramSwizzle->cleanup(m_context.get());
+ if (m_tileProgramSwizzleOpaque)
+ m_tileProgramSwizzleOpaque->cleanup(m_context.get());
+ if (m_tileProgramAA)
+ m_tileProgramAA->cleanup(m_context.get());
+ if (m_tileProgramSwizzleAA)
+ m_tileProgramSwizzleAA->cleanup(m_context.get());
+ if (m_tileCheckerboardProgram)
+ m_tileCheckerboardProgram->cleanup(m_context.get());
+
if (m_renderSurfaceMaskProgram)
m_renderSurfaceMaskProgram->cleanup(m_context.get());
if (m_renderSurfaceProgram)
@@ -1517,60 +1616,32 @@ void LayerRendererChromium::cleanupSharedObjects()
m_renderSurfaceMaskProgramAA->cleanup(m_context.get());
if (m_renderSurfaceProgramAA)
m_renderSurfaceProgramAA->cleanup(m_context.get());
- if (m_videoLayerRGBAProgram)
- m_videoLayerRGBAProgram->cleanup(m_context.get());
- if (m_videoLayerYUVProgram)
- m_videoLayerYUVProgram->cleanup(m_context.get());
- if (m_videoLayerNativeTextureProgram)
- m_videoLayerNativeTextureProgram->cleanup(m_context.get());
- if (m_streamTextureLayerProgram)
- m_streamTextureLayerProgram->cleanup(m_context.get());
-
- m_borderProgram.clear();
- m_headsUpDisplayProgram.clear();
- m_tilerProgram.clear();
- m_tilerProgramOpaque.clear();
- m_tilerProgramSwizzle.clear();
- m_tilerProgramSwizzleOpaque.clear();
- m_tilerProgramAA.clear();
- m_tilerProgramSwizzleAA.clear();
- m_canvasLayerProgram.clear();
- m_pluginLayerProgram.clear();
- m_pluginLayerProgramFlip.clear();
- m_pluginLayerTexRectProgram.clear();
- m_pluginLayerTexRectProgramFlip.clear();
- m_renderSurfaceMaskProgram.clear();
- m_renderSurfaceProgram.clear();
- m_renderSurfaceMaskProgramAA.clear();
- m_renderSurfaceProgramAA.clear();
- m_videoLayerRGBAProgram.clear();
- m_videoLayerYUVProgram.clear();
- m_videoLayerNativeTextureProgram.clear();
- m_streamTextureLayerProgram.clear();
- if (m_offscreenFramebufferId)
- GLC(m_context.get(), m_context->deleteFramebuffer(m_offscreenFramebufferId));
- releaseRenderSurfaceTextures();
-}
+ if (m_textureProgram)
+ m_textureProgram->cleanup(m_context.get());
+ if (m_textureProgramFlip)
+ m_textureProgramFlip->cleanup(m_context.get());
+ if (m_textureIOSurfaceProgram)
+ m_textureIOSurfaceProgram->cleanup(m_context.get());
-String LayerRendererChromium::layerTreeAsText() const
-{
- TextStream ts;
- if (rootLayer()) {
- ts << rootLayer()->layerTreeAsText();
- ts << "RenderSurfaces:\n";
- dumpRenderSurfaces(ts, 1, rootLayer());
- }
- return ts.release();
-}
+ if (m_videoYUVProgram)
+ m_videoYUVProgram->cleanup(m_context.get());
+ if (m_videoStreamTextureProgram)
+ m_videoStreamTextureProgram->cleanup(m_context.get());
-void LayerRendererChromium::dumpRenderSurfaces(TextStream& ts, int indent, const CCLayerImpl* layer) const
-{
- if (layer->renderSurface())
- layer->renderSurface()->dumpSurface(ts, indent);
+ if (m_solidColorProgram)
+ m_solidColorProgram->cleanup(m_context.get());
- for (size_t i = 0; i < layer->children().size(); ++i)
- dumpRenderSurfaces(ts, indent, layer->children()[i].get());
+ if (m_headsUpDisplayProgram)
+ m_headsUpDisplayProgram->cleanup(m_context.get());
+
+ if (m_offscreenFramebufferId)
+ GLC(m_context, m_context->deleteFramebuffer(m_offscreenFramebufferId));
+
+ m_textureCopier.clear();
+ m_textureUploader.clear();
+
+ releaseRenderSurfaceTextures();
}
bool LayerRendererChromium::isContextLost()
diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h
index 91fcf6a51..530ba848e 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h
@@ -34,17 +34,12 @@
#if USE(ACCELERATED_COMPOSITING)
-#include "ContentLayerChromium.h"
#include "FloatQuad.h"
#include "IntRect.h"
-#include "LayerChromium.h"
+#include "TextureCopier.h"
+#include "TextureUploader.h"
#include "TrackingTextureAllocator.h"
-#include "VideoLayerChromium.h"
-#include "cc/CCCanvasLayerImpl.h"
-#include "cc/CCHeadsUpDisplay.h"
#include "cc/CCLayerTreeHost.h"
-#include "cc/CCPluginLayerImpl.h"
-#include "cc/CCVideoLayerImpl.h"
#include <wtf/HashMap.h>
#include <wtf/Noncopyable.h>
#include <wtf/PassOwnPtr.h>
@@ -53,22 +48,30 @@
namespace WebCore {
-class CCHeadsUpDisplay;
-class CCLayerImpl;
+class CCCheckerboardDrawQuad;
+class CCDebugBorderDrawQuad;
+class CCDrawQuad;
+class CCIOSurfaceDrawQuad;
class CCRenderPass;
+class CCRenderSurfaceDrawQuad;
+class CCSolidColorDrawQuad;
+class CCTextureDrawQuad;
+class CCTileDrawQuad;
+class CCVideoDrawQuad;
class GeometryBinding;
class GraphicsContext3D;
-class TrackingTextureAllocator;
+class LayerRendererGpuMemoryAllocationChangedCallbackAdapter;
class LayerRendererSwapBuffersCompleteCallbackAdapter;
+class ScopedEnsureFramebufferAllocation;
class LayerRendererChromiumClient {
public:
virtual const IntSize& viewportSize() const = 0;
virtual const CCSettings& settings() const = 0;
- virtual CCLayerImpl* rootLayer() = 0;
- virtual const CCLayerImpl* rootLayer() const = 0;
virtual void didLoseContext() = 0;
virtual void onSwapBuffersComplete() = 0;
+ virtual void setFullRootLayerDamage() = 0;
+ virtual void setContentsMemoryAllocationLimitBytes(size_t) = 0;
};
// Class that handles drawing of composited render layers using GL.
@@ -77,17 +80,11 @@ class LayerRendererChromium {
public:
static PassOwnPtr<LayerRendererChromium> create(LayerRendererChromiumClient*, PassRefPtr<GraphicsContext3D>);
- // Must be called in order to allow the LayerRendererChromium to destruct
- void close();
-
~LayerRendererChromium();
const CCSettings& settings() const { return m_client->settings(); }
const LayerRendererCapabilities& capabilities() const { return m_capabilities; }
- CCLayerImpl* rootLayer() { return m_client->rootLayer(); }
- const CCLayerImpl* rootLayer() const { return m_client->rootLayer(); }
-
GraphicsContext3D* context();
bool contextSupportsMapSub() const { return m_capabilities.usingMapSub; }
@@ -97,15 +94,18 @@ public:
void viewportChanged();
- void beginDrawingFrame();
+ void beginDrawingFrame(CCRenderSurface* defaultRenderSurface);
void drawRenderPass(const CCRenderPass*);
void finishDrawingFrame();
+ void drawHeadsUpDisplay(ManagedTexture*, const IntSize& hudSize);
+
// waits for rendering to finish
void finish();
+ void doNoOp();
// puts backbuffer onscreen
- void swapBuffers(const IntRect& subBuffer);
+ bool swapBuffers(const IntRect& subBuffer);
static void debugGLCall(GraphicsContext3D*, const char* command, const char* file, int line);
@@ -114,40 +114,19 @@ public:
const GeometryBinding* sharedGeometry() const { return m_sharedGeometry.get(); }
const FloatQuad& sharedGeometryQuad() const { return m_sharedGeometryQuad; }
- const LayerChromium::BorderProgram* borderProgram();
- const CCHeadsUpDisplay::Program* headsUpDisplayProgram();
- const CCRenderSurface::Program* renderSurfaceProgram();
- const CCRenderSurface::ProgramAA* renderSurfaceProgramAA();
- const CCRenderSurface::MaskProgram* renderSurfaceMaskProgram();
- const CCRenderSurface::MaskProgramAA* renderSurfaceMaskProgramAA();
- const CCTiledLayerImpl::Program* tilerProgram();
- const CCTiledLayerImpl::ProgramOpaque* tilerProgramOpaque();
- const CCTiledLayerImpl::ProgramAA* tilerProgramAA();
- const CCTiledLayerImpl::ProgramSwizzle* tilerProgramSwizzle();
- const CCTiledLayerImpl::ProgramSwizzleOpaque* tilerProgramSwizzleOpaque();
- const CCTiledLayerImpl::ProgramSwizzleAA* tilerProgramSwizzleAA();
- const CCCanvasLayerImpl::Program* canvasLayerProgram();
- const CCPluginLayerImpl::Program* pluginLayerProgram();
- const CCPluginLayerImpl::ProgramFlip* pluginLayerProgramFlip();
- const CCPluginLayerImpl::TexRectProgram* pluginLayerTexRectProgram();
- const CCPluginLayerImpl::TexRectProgramFlip* pluginLayerTexRectProgramFlip();
- const CCVideoLayerImpl::RGBAProgram* videoLayerRGBAProgram();
- const CCVideoLayerImpl::YUVProgram* videoLayerYUVProgram();
- const CCVideoLayerImpl::NativeTextureProgram* videoLayerNativeTextureProgram();
- const CCVideoLayerImpl::StreamTextureProgram* streamTextureLayerProgram();
+
void getFramebufferPixels(void *pixels, const IntRect&);
+ bool getFramebufferTexture(ManagedTexture*, const IntRect& deviceRect);
TextureManager* renderSurfaceTextureManager() const { return m_renderSurfaceTextureManager.get(); }
+ TextureCopier* textureCopier() const { return m_textureCopier.get(); }
+ TextureUploader* textureUploader() const { return m_textureUploader.get(); }
TextureAllocator* renderSurfaceTextureAllocator() const { return m_renderSurfaceTextureAllocator.get(); }
TextureAllocator* contentsTextureAllocator() const { return m_contentsTextureAllocator.get(); }
- CCHeadsUpDisplay* headsUpDisplay() { return m_headsUpDisplay.get(); }
-
void setScissorToRect(const IntRect&);
- String layerTreeAsText() const;
-
bool isContextLost();
void setVisible(bool);
@@ -159,20 +138,27 @@ public:
float width, float height, float opacity, const FloatQuad&,
int matrixLocation, int alphaLocation, int quadLocation);
-private:
+protected:
+ friend class LayerRendererGpuMemoryAllocationChangedCallbackAdapter;
+ void discardFramebuffer();
+ void ensureFramebuffer();
+ bool isFramebufferDiscarded() const { return m_isFramebufferDiscarded; }
+
LayerRendererChromium(LayerRendererChromiumClient*, PassRefPtr<GraphicsContext3D>);
bool initialize();
+private:
void drawQuad(const CCDrawQuad*, const FloatRect& surfaceDamageRect);
+ void drawCheckerboardQuad(const CCCheckerboardDrawQuad*);
void drawDebugBorderQuad(const CCDebugBorderDrawQuad*);
+ void drawBackgroundFilters(const CCRenderSurfaceDrawQuad*);
void drawRenderSurfaceQuad(const CCRenderSurfaceDrawQuad*);
void drawSolidColorQuad(const CCSolidColorDrawQuad*);
+ void drawTextureQuad(const CCTextureDrawQuad*);
+ void drawIOSurfaceQuad(const CCIOSurfaceDrawQuad*);
void drawTileQuad(const CCTileDrawQuad*);
- void drawCanvasQuad(const CCCanvasDrawQuad*);
void drawVideoQuad(const CCVideoDrawQuad*);
- void drawPluginQuad(const CCPluginDrawQuad*);
- ManagedTexture* getOffscreenLayerTexture();
void copyPlaneToTexture(const CCVideoDrawQuad*, const void* plane, int index);
bool copyFrameToTextures(const CCVideoDrawQuad*);
template<class Program> void drawSingleTextureVideoQuad(const CCVideoDrawQuad*, Program*, float widthScaleFactor, Platform3DObject textureId, GC3Denum target);
@@ -181,26 +167,24 @@ private:
void drawRGBA(const CCVideoDrawQuad*);
void drawYUV(const CCVideoDrawQuad*);
- void copyOffscreenTextureToDisplay();
-
void setDrawViewportRect(const IntRect&, bool flipY);
+ // The current drawing target is either a RenderSurface or ManagedTexture. Use these functions to switch to a new drawing target.
bool useRenderSurface(CCRenderSurface*);
+ bool useManagedTexture(ManagedTexture*, const IntRect& viewportRect);
+ bool isCurrentRenderSurface(CCRenderSurface*);
+
+ bool bindFramebufferToTexture(ManagedTexture*, const IntRect& viewportRect);
+
void clearRenderSurface(CCRenderSurface*, CCRenderSurface* rootRenderSurface, const FloatRect& surfaceDamageRect);
void releaseRenderSurfaceTextures();
bool makeContextCurrent();
- static bool compareLayerZ(const RefPtr<CCLayerImpl>&, const RefPtr<CCLayerImpl>&);
-
- void dumpRenderSurfaces(TextStream&, int indent, const CCLayerImpl*) const;
-
bool initializeSharedObjects();
void cleanupSharedObjects();
- void clearRenderSurfacesOnCCLayerImplRecursive(CCLayerImpl*);
-
friend class LayerRendererSwapBuffersCompleteCallbackAdapter;
void onSwapBuffersComplete();
@@ -212,41 +196,100 @@ private:
TransformationMatrix m_windowMatrix;
CCRenderSurface* m_currentRenderSurface;
+ ManagedTexture* m_currentManagedTexture;
unsigned m_offscreenFramebufferId;
- // 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
- // we cannot store these values in static variables.
OwnPtr<GeometryBinding> m_sharedGeometry;
- OwnPtr<LayerChromium::BorderProgram> m_borderProgram;
- OwnPtr<CCHeadsUpDisplay::Program> m_headsUpDisplayProgram;
- OwnPtr<CCTiledLayerImpl::Program> m_tilerProgram;
- OwnPtr<CCTiledLayerImpl::ProgramOpaque> m_tilerProgramOpaque;
- OwnPtr<CCTiledLayerImpl::ProgramSwizzle> m_tilerProgramSwizzle;
- OwnPtr<CCTiledLayerImpl::ProgramSwizzleOpaque> m_tilerProgramSwizzleOpaque;
- OwnPtr<CCTiledLayerImpl::ProgramAA> m_tilerProgramAA;
- OwnPtr<CCTiledLayerImpl::ProgramSwizzleAA> m_tilerProgramSwizzleAA;
- OwnPtr<CCCanvasLayerImpl::Program> m_canvasLayerProgram;
- OwnPtr<CCPluginLayerImpl::Program> m_pluginLayerProgram;
- OwnPtr<CCPluginLayerImpl::ProgramFlip> m_pluginLayerProgramFlip;
- OwnPtr<CCPluginLayerImpl::TexRectProgram> m_pluginLayerTexRectProgram;
- OwnPtr<CCPluginLayerImpl::TexRectProgramFlip> m_pluginLayerTexRectProgramFlip;
- OwnPtr<CCRenderSurface::MaskProgram> m_renderSurfaceMaskProgram;
- OwnPtr<CCRenderSurface::Program> m_renderSurfaceProgram;
- OwnPtr<CCRenderSurface::MaskProgramAA> m_renderSurfaceMaskProgramAA;
- OwnPtr<CCRenderSurface::ProgramAA> m_renderSurfaceProgramAA;
- OwnPtr<CCVideoLayerImpl::RGBAProgram> m_videoLayerRGBAProgram;
- OwnPtr<CCVideoLayerImpl::YUVProgram> m_videoLayerYUVProgram;
- OwnPtr<CCVideoLayerImpl::NativeTextureProgram> m_videoLayerNativeTextureProgram;
- OwnPtr<CCVideoLayerImpl::StreamTextureProgram> m_streamTextureLayerProgram;
+
+ // This block of bindings defines all of the programs used by the compositor itself.
+
+ // Tiled layer shaders.
+ typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexAlpha> TileProgram;
+ typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexClampAlphaAA> TileProgramAA;
+ typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexClampSwizzleAlphaAA> TileProgramSwizzleAA;
+ typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexOpaque> TileProgramOpaque;
+ typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexSwizzleAlpha> TileProgramSwizzle;
+ typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexSwizzleOpaque> TileProgramSwizzleOpaque;
+ typedef ProgramBinding<VertexShaderPosTex, FragmentShaderCheckerboard> TileCheckerboardProgram;
+
+ // Render surface shaders.
+ // CCRenderSurface::drawLayers() needs to see these programs currently.
+ // FIXME: Draw with a quad type for render surfaces and get rid of this friendlyness.
+ friend class CCRenderSurface;
+ typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexAlpha> RenderSurfaceProgram;
+ typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexAlphaMask> RenderSurfaceMaskProgram;
+ typedef ProgramBinding<VertexShaderQuad, FragmentShaderRGBATexAlphaAA> RenderSurfaceProgramAA;
+ typedef ProgramBinding<VertexShaderQuad, FragmentShaderRGBATexAlphaMaskAA> RenderSurfaceMaskProgramAA;
+
+ // Texture shaders.
+ typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexAlpha> TextureProgram;
+ typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexFlipAlpha> TextureProgramFlip;
+ typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexRectFlipAlpha> TextureIOSurfaceProgram;
+
+ // Video shaders.
+ typedef ProgramBinding<VertexShaderVideoTransform, FragmentShaderOESImageExternal> VideoStreamTextureProgram;
+ typedef ProgramBinding<VertexShaderPosTexYUVStretch, FragmentShaderYUVVideo> VideoYUVProgram;
+
+ // Special purpose / effects shaders.
+ typedef ProgramBinding<VertexShaderPos, FragmentShaderColor> SolidColorProgram;
+
+ // Debugging shaders.
+ typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexSwizzleAlpha> HeadsUpDisplayProgram;
+
+
+ const TileProgram* tileProgram();
+ const TileProgramOpaque* tileProgramOpaque();
+ const TileProgramAA* tileProgramAA();
+ const TileProgramSwizzle* tileProgramSwizzle();
+ const TileProgramSwizzleOpaque* tileProgramSwizzleOpaque();
+ const TileProgramSwizzleAA* tileProgramSwizzleAA();
+ const TileCheckerboardProgram* tileCheckerboardProgram();
+
+ const RenderSurfaceProgram* renderSurfaceProgram();
+ const RenderSurfaceProgramAA* renderSurfaceProgramAA();
+ const RenderSurfaceMaskProgram* renderSurfaceMaskProgram();
+ const RenderSurfaceMaskProgramAA* renderSurfaceMaskProgramAA();
+
+ const TextureProgram* textureProgram();
+ const TextureProgramFlip* textureProgramFlip();
+ const TextureIOSurfaceProgram* textureIOSurfaceProgram();
+
+ const VideoYUVProgram* videoYUVProgram();
+ const VideoStreamTextureProgram* videoStreamTextureProgram();
+
+ const SolidColorProgram* solidColorProgram();
+
+ const HeadsUpDisplayProgram* headsUpDisplayProgram();
+
+ OwnPtr<TileProgram> m_tileProgram;
+ OwnPtr<TileProgramOpaque> m_tileProgramOpaque;
+ OwnPtr<TileProgramAA> m_tileProgramAA;
+ OwnPtr<TileProgramSwizzle> m_tileProgramSwizzle;
+ OwnPtr<TileProgramSwizzleOpaque> m_tileProgramSwizzleOpaque;
+ OwnPtr<TileProgramSwizzleAA> m_tileProgramSwizzleAA;
+ OwnPtr<TileCheckerboardProgram> m_tileCheckerboardProgram;
+
+ OwnPtr<RenderSurfaceProgram> m_renderSurfaceProgram;
+ OwnPtr<RenderSurfaceProgramAA> m_renderSurfaceProgramAA;
+ OwnPtr<RenderSurfaceMaskProgram> m_renderSurfaceMaskProgram;
+ OwnPtr<RenderSurfaceMaskProgramAA> m_renderSurfaceMaskProgramAA;
+
+ OwnPtr<TextureProgram> m_textureProgram;
+ OwnPtr<TextureProgramFlip> m_textureProgramFlip;
+ OwnPtr<TextureIOSurfaceProgram> m_textureIOSurfaceProgram;
+
+ OwnPtr<VideoYUVProgram> m_videoYUVProgram;
+ OwnPtr<VideoStreamTextureProgram> m_videoStreamTextureProgram;
+
+ OwnPtr<SolidColorProgram> m_solidColorProgram;
+ OwnPtr<HeadsUpDisplayProgram> m_headsUpDisplayProgram;
OwnPtr<TextureManager> m_renderSurfaceTextureManager;
+ OwnPtr<AcceleratedTextureCopier> m_textureCopier;
+ OwnPtr<AcceleratedTextureUploader> m_textureUploader;
OwnPtr<TrackingTextureAllocator> m_contentsTextureAllocator;
OwnPtr<TrackingTextureAllocator> m_renderSurfaceTextureAllocator;
- OwnPtr<CCHeadsUpDisplay> m_headsUpDisplay;
-
RefPtr<GraphicsContext3D> m_context;
CCRenderSurface* m_defaultRenderSurface;
@@ -254,15 +297,17 @@ private:
FloatQuad m_sharedGeometryQuad;
bool m_isViewportChanged;
+ bool m_isFramebufferDiscarded;
};
+
// Setting DEBUG_GL_CALLS to 1 will call glGetError() after almost every GL
// call made by the compositor. Useful for debugging rendering issues but
// will significantly degrade performance.
#define DEBUG_GL_CALLS 0
#if DEBUG_GL_CALLS && !defined ( NDEBUG )
-#define GLC(context, x) { (x), LayerRendererChromium::debugGLCall(context, #x, __FILE__, __LINE__); }
+#define GLC(context, x) (x, LayerRendererChromium::debugGLCall(&*context, #x, __FILE__, __LINE__))
#else
#define GLC(context, x) (x)
#endif
diff --git a/Source/WebCore/platform/graphics/chromium/LayerTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/LayerTextureUpdater.h
index 179fea6e1..5db7b4c51 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerTextureUpdater.h
+++ b/Source/WebCore/platform/graphics/chromium/LayerTextureUpdater.h
@@ -74,7 +74,7 @@ public:
// The |resultingOpaqueRect| gives back a region of the layer that was painted opaque. If the layer is marked opaque in the updater,
// then this region should be ignored in preference for the entire layer's area.
virtual void prepareToUpdate(const IntRect& /* contentRect */, const IntSize& /* tileSize */, int /* borderTexels */, float /* contentsScale */,
- IntRect* /* resultingOpaqueRect */) { }
+ IntRect& /* resultingOpaqueRect */) { }
// Set true by the layer when it is known that the entire output is going to be opaque.
virtual void setOpaque(bool) { }
diff --git a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp
deleted file mode 100644
index 97703957f..000000000
--- a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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 "PluginLayerChromium.h"
-
-#include "GraphicsContext3D.h"
-#include "LayerRendererChromium.h"
-#include "cc/CCLayerImpl.h"
-#include "cc/CCPluginLayerImpl.h"
-
-namespace WebCore {
-
-PassRefPtr<PluginLayerChromium> PluginLayerChromium::create()
-{
- return adoptRef(new PluginLayerChromium);
-}
-
-PluginLayerChromium::PluginLayerChromium()
- : LayerChromium()
- , m_textureId(0)
- , m_flipped(true)
- , m_uvRect(0, 0, 1, 1)
- , m_ioSurfaceWidth(0)
- , m_ioSurfaceHeight(0)
- , m_ioSurfaceId(0)
-{
-}
-
-PassOwnPtr<CCLayerImpl> PluginLayerChromium::createCCLayerImpl()
-{
- return CCPluginLayerImpl::create(m_layerId);
-}
-
-void PluginLayerChromium::setTextureId(unsigned id)
-{
- m_textureId = id;
- setNeedsCommit();
-}
-
-void PluginLayerChromium::setFlipped(bool flipped)
-{
- m_flipped = flipped;
- setNeedsCommit();
-}
-
-void PluginLayerChromium::setUVRect(const FloatRect& rect)
-{
- m_uvRect = rect;
- setNeedsCommit();
-}
-
-void PluginLayerChromium::setIOSurfaceProperties(int width, int height, uint32_t ioSurfaceId)
-{
- m_ioSurfaceWidth = width;
- m_ioSurfaceHeight = height;
- m_ioSurfaceId = ioSurfaceId;
- setNeedsCommit();
-}
-
-uint32_t PluginLayerChromium::getIOSurfaceId() const
-{
- return m_ioSurfaceId;
-}
-
-void PluginLayerChromium::pushPropertiesTo(CCLayerImpl* layer)
-{
- LayerChromium::pushPropertiesTo(layer);
-
- CCPluginLayerImpl* pluginLayer = static_cast<CCPluginLayerImpl*>(layer);
- pluginLayer->setTextureId(m_textureId);
- pluginLayer->setFlipped(m_flipped);
- pluginLayer->setUVRect(m_uvRect);
- pluginLayer->setIOSurfaceProperties(m_ioSurfaceWidth, m_ioSurfaceHeight, m_ioSurfaceId);
-}
-
-}
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/ProgramBinding.h b/Source/WebCore/platform/graphics/chromium/ProgramBinding.h
index bb6fc8ddd..c0ef736b3 100644
--- a/Source/WebCore/platform/graphics/chromium/ProgramBinding.h
+++ b/Source/WebCore/platform/graphics/chromium/ProgramBinding.h
@@ -43,7 +43,7 @@ public:
void init(GraphicsContext3D*, const String& vertexShader, const String& fragmentShader);
void cleanup(GraphicsContext3D*);
- unsigned program() const { return m_program; }
+ unsigned program() const { ASSERT(m_initialized); return m_program; }
bool initialized() const { return m_initialized; }
protected:
@@ -67,6 +67,7 @@ public:
{
ASSERT(context);
ASSERT(m_program);
+ ASSERT(!m_initialized);
m_vertexShader.init(context, m_program);
m_fragmentShader.init(context, m_program);
diff --git a/Source/WebCore/platform/graphics/chromium/RateLimiter.cpp b/Source/WebCore/platform/graphics/chromium/RateLimiter.cpp
index c5e4dd5c7..fdadf93b4 100644
--- a/Source/WebCore/platform/graphics/chromium/RateLimiter.cpp
+++ b/Source/WebCore/platform/graphics/chromium/RateLimiter.cpp
@@ -35,20 +35,25 @@
namespace WebCore {
-PassRefPtr<RateLimiter> RateLimiter::create(GraphicsContext3D* context)
+PassRefPtr<RateLimiter> RateLimiter::create(GraphicsContext3D* context, RateLimiterClient *client)
{
- return adoptRef(new RateLimiter(context));
+ return adoptRef(new RateLimiter(context, client));
}
-RateLimiter::RateLimiter(GraphicsContext3D* context)
+RateLimiter::RateLimiter(GraphicsContext3D* context, RateLimiterClient *client)
: m_context(context)
, m_timer(this, &RateLimiter::rateLimitContext)
+ , m_client(client)
{
ASSERT(context);
ASSERT(context->getExtensions());
m_contextSupportsRateLimitingExtension = context->getExtensions()->supports("GL_CHROMIUM_rate_limit_offscreen_context");
}
+RateLimiter::~RateLimiter()
+{
+}
+
void RateLimiter::start()
{
if (m_contextSupportsRateLimitingExtension && !m_timer.isActive())
@@ -66,6 +71,7 @@ void RateLimiter::rateLimitContext(Timer<RateLimiter>*)
Extensions3DChromium* extensions = static_cast<Extensions3DChromium*>(m_context->getExtensions());
+ m_client->rateLimit();
extensions->rateLimitOffscreenContextCHROMIUM();
}
diff --git a/Source/WebCore/platform/graphics/chromium/RateLimiter.h b/Source/WebCore/platform/graphics/chromium/RateLimiter.h
index 2699278d4..68e04455e 100644
--- a/Source/WebCore/platform/graphics/chromium/RateLimiter.h
+++ b/Source/WebCore/platform/graphics/chromium/RateLimiter.h
@@ -28,27 +28,35 @@
#if USE(ACCELERATED_COMPOSITING)
-#include "PassRefPtr.h"
#include "Timer.h"
#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
namespace WebCore {
class GraphicsContext3D;
+class RateLimiterClient {
+public:
+ virtual void rateLimit() = 0;
+};
+
// A class containing a timer, which calls rateLimitCHROMIUM on expiry
class RateLimiter : public RefCounted<RateLimiter> {
public:
- static PassRefPtr<RateLimiter> create(GraphicsContext3D*);
+ static PassRefPtr<RateLimiter> create(GraphicsContext3D*, RateLimiterClient*);
+ ~RateLimiter();
+
void start();
void stop();
private:
- explicit RateLimiter(GraphicsContext3D*);
- GraphicsContext3D* m_context;
+ RateLimiter(GraphicsContext3D*, RateLimiterClient*);
+ RefPtr<GraphicsContext3D> m_context;
bool m_contextSupportsRateLimitingExtension;
Timer<RateLimiter> m_timer;
void rateLimitContext(Timer<RateLimiter>*);
+ RateLimiterClient *m_client;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
index 69ce9526c..4e5528ec8 100644
--- a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
@@ -42,6 +42,9 @@ RenderSurfaceChromium::RenderSurfaceChromium(LayerChromium* owningLayer)
, m_maskLayer(0)
, m_skipsDraw(false)
, m_drawOpacity(1)
+ , m_drawOpacityIsAnimating(false)
+ , m_targetSurfaceTransformsAreAnimating(false)
+ , m_screenSpaceTransformsAreAnimating(false)
, m_nearestAncestorThatMovesPixels(0)
{
}
@@ -61,5 +64,10 @@ FloatRect RenderSurfaceChromium::drawableContentRect() const
return drawableContentRect;
}
+bool RenderSurfaceChromium::hasReplica() const
+{
+ return m_owningLayer->replicaLayer();
+}
+
}
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
index 9045425bc..c89521567 100644
--- a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
@@ -50,10 +50,6 @@ public:
explicit RenderSurfaceChromium(LayerChromium*);
~RenderSurfaceChromium();
- bool prepareContentsTexture();
- void releaseContentsTexture();
- void draw(const IntRect& targetSurfaceRect);
-
// Returns the rect that encloses the RenderSurface including any reflection.
FloatRect drawableContentRect() const;
@@ -63,6 +59,9 @@ public:
float drawOpacity() const { return m_drawOpacity; }
void setDrawOpacity(float drawOpacity) { m_drawOpacity = drawOpacity; }
+ bool drawOpacityIsAnimating() const { return m_drawOpacityIsAnimating; }
+ void setDrawOpacityIsAnimating(bool drawOpacityIsAnimating) { m_drawOpacityIsAnimating = drawOpacityIsAnimating; }
+
// This goes from content space with the origin in the center of the rect being transformed to the target space with the origin in the top left of the
// rect being transformed. Position the rect so that the origin is in the center of it before applying this transform.
const TransformationMatrix& drawTransform() const { return m_drawTransform; }
@@ -71,15 +70,32 @@ public:
const TransformationMatrix& originTransform() const { return m_originTransform; }
void setOriginTransform(const TransformationMatrix& originTransform) { m_originTransform = originTransform; }
+ const TransformationMatrix& screenSpaceTransform() const { return m_screenSpaceTransform; }
+ void setScreenSpaceTransform(const TransformationMatrix& screenSpaceTransform) { m_screenSpaceTransform = screenSpaceTransform; }
+
const TransformationMatrix& replicaDrawTransform() const { return m_replicaDrawTransform; }
void setReplicaDrawTransform(const TransformationMatrix& replicaDrawTransform) { m_replicaDrawTransform = replicaDrawTransform; }
+ const TransformationMatrix& replicaOriginTransform() const { return m_replicaOriginTransform; }
+ void setReplicaOriginTransform(const TransformationMatrix& replicaOriginTransform) { m_replicaOriginTransform = replicaOriginTransform; }
+
+ const TransformationMatrix& replicaScreenSpaceTransform() const { return m_replicaScreenSpaceTransform; }
+ void setReplicaScreenSpaceTransform(const TransformationMatrix& replicaScreenSpaceTransform) { m_replicaScreenSpaceTransform = replicaScreenSpaceTransform; }
+
+ bool targetSurfaceTransformsAreAnimating() const { return m_targetSurfaceTransformsAreAnimating; }
+ void setTargetSurfaceTransformsAreAnimating(bool animating) { m_targetSurfaceTransformsAreAnimating = animating; }
+ bool screenSpaceTransformsAreAnimating() const { return m_screenSpaceTransformsAreAnimating; }
+ void setScreenSpaceTransformsAreAnimating(bool animating) { m_screenSpaceTransformsAreAnimating = animating; }
+
const IntRect& clipRect() const { return m_clipRect; }
void setClipRect(const IntRect& clipRect) { m_clipRect = clipRect; }
void setFilters(const FilterOperations& filters) { m_filters = filters; }
const FilterOperations& filters() const { return m_filters; }
+ void setBackgroundFilters(const FilterOperations& filters) { m_backgroundFilters = filters; }
+ const FilterOperations& backgroundFilters() const { return m_backgroundFilters; }
+
bool skipsDraw() const { return m_skipsDraw; }
void setSkipsDraw(bool skipsDraw) { m_skipsDraw = skipsDraw; }
@@ -91,6 +107,8 @@ public:
void setNearestAncestorThatMovesPixels(RenderSurfaceChromium* surface) { m_nearestAncestorThatMovesPixels = surface; }
const RenderSurfaceChromium* nearestAncestorThatMovesPixels() const { return m_nearestAncestorThatMovesPixels; }
+ bool hasReplica() const;
+
private:
LayerChromium* m_owningLayer;
LayerChromium* m_maskLayer;
@@ -99,10 +117,17 @@ private:
bool m_skipsDraw;
float m_drawOpacity;
+ bool m_drawOpacityIsAnimating;
TransformationMatrix m_drawTransform;
- TransformationMatrix m_replicaDrawTransform;
TransformationMatrix m_originTransform;
+ TransformationMatrix m_screenSpaceTransform;
+ TransformationMatrix m_replicaDrawTransform;
+ TransformationMatrix m_replicaOriginTransform;
+ TransformationMatrix m_replicaScreenSpaceTransform;
+ bool m_targetSurfaceTransformsAreAnimating;
+ bool m_screenSpaceTransformsAreAnimating;
FilterOperations m_filters;
+ FilterOperations m_backgroundFilters;
IntRect m_clipRect;
Vector<RefPtr<LayerChromium> > m_layerList;
diff --git a/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp b/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp
index 71d4d1fd1..e7b8c5aaf 100644
--- a/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp
@@ -63,38 +63,6 @@ String VertexShaderPosTex::getShaderString() const
);
}
-VertexShaderPosTexStretch::VertexShaderPosTexStretch()
- : m_matrixLocation(-1)
- , m_offsetLocation(-1)
- , m_scaleLocation(-1)
-{
-}
-
-void VertexShaderPosTexStretch::init(GraphicsContext3D* context, unsigned program)
-{
- m_matrixLocation = context->getUniformLocation(program, "matrix");
- m_offsetLocation = context->getUniformLocation(program, "offset");
- m_scaleLocation = context->getUniformLocation(program, "scale");
- ASSERT(m_matrixLocation != -1 && m_offsetLocation != -1 && m_scaleLocation != -1);
-}
-
-String VertexShaderPosTexStretch::getShaderString() const
-{
- return SHADER(
- attribute vec4 a_position;
- attribute vec2 a_texCoord;
- uniform mat4 matrix;
- uniform vec2 offset;
- uniform vec2 scale;
- varying vec2 v_texCoord;
- void main()
- {
- gl_Position = matrix * a_position;
- v_texCoord = scale * a_texCoord + offset;
- }
- );
-}
-
VertexShaderPosTexYUVStretch::VertexShaderPosTexYUVStretch()
: m_matrixLocation(-1)
, m_yWidthScaleFactorLocation(-1)
@@ -188,6 +156,19 @@ VertexShaderQuad::VertexShaderQuad()
{
}
+String VertexShaderPosTexIdentity::getShaderString() const
+{
+ return SHADER(
+ attribute vec4 a_position;
+ varying vec2 v_texCoord;
+ void main()
+ {
+ gl_Position = a_position;
+ v_texCoord = (a_position.xy + vec2(1.0)) * 0.5;
+ }
+ );
+}
+
void VertexShaderQuad::init(GraphicsContext3D* context, unsigned program)
{
m_matrixLocation = context->getUniformLocation(program, "matrix");
@@ -410,6 +391,19 @@ String FragmentShaderRGBATexOpaque::getShaderString() const
);
}
+String FragmentShaderRGBATex::getShaderString() const
+{
+ return SHADER(
+ precision mediump float;
+ varying vec2 v_texCoord;
+ uniform sampler2D s_texture;
+ void main()
+ {
+ gl_FragColor = texture2D(s_texture, v_texCoord);
+ }
+ );
+}
+
String FragmentShaderRGBATexSwizzleAlpha::getShaderString() const
{
return SHADER(
@@ -694,7 +688,45 @@ String FragmentShaderColor::getShaderString() const
uniform vec4 color;
void main()
{
- gl_FragColor = vec4(color.xyz * color.w, color.w);
+ gl_FragColor = color;
+ }
+ );
+}
+
+FragmentShaderCheckerboard::FragmentShaderCheckerboard()
+ : m_alphaLocation(-1)
+ , m_texTransformLocation(-1)
+ , m_frequencyLocation(-1)
+{
+}
+
+void FragmentShaderCheckerboard::init(GraphicsContext3D* context, unsigned program)
+{
+ m_alphaLocation = context->getUniformLocation(program, "alpha");
+ m_texTransformLocation = context->getUniformLocation(program, "texTransform");
+ m_frequencyLocation = context->getUniformLocation(program, "frequency");
+ ASSERT(m_alphaLocation != -1 && m_texTransformLocation != -1 && m_frequencyLocation != -1);
+}
+
+String FragmentShaderCheckerboard::getShaderString() const
+{
+ // Shader based on Example 13-17 of "OpenGL ES 2.0 Programming Guide"
+ // by Munshi, Ginsburg, Shreiner.
+ return SHADER(
+ precision mediump float;
+ precision mediump int;
+ varying vec2 v_texCoord;
+ uniform float alpha;
+ uniform float frequency;
+ uniform vec4 texTransform;
+ void main()
+ {
+ vec4 color1 = vec4(1.0, 1.0, 1.0, 1.0);
+ vec4 color2 = vec4(0.945, 0.945, 0.945, 1.0);
+ vec2 texCoord = clamp(v_texCoord, 0.0, 1.0) * texTransform.zw + texTransform.xy;
+ vec2 coord = mod(floor(texCoord * frequency * 2.0), 2.0);
+ float picker = abs(coord.x - coord.y);
+ gl_FragColor = mix(color1, color2, picker) * alpha;
}
);
}
diff --git a/Source/WebCore/platform/graphics/chromium/ShaderChromium.h b/Source/WebCore/platform/graphics/chromium/ShaderChromium.h
index 2bd760a99..81db3e243 100644
--- a/Source/WebCore/platform/graphics/chromium/ShaderChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/ShaderChromium.h
@@ -48,23 +48,6 @@ private:
int m_matrixLocation;
};
-class VertexShaderPosTexStretch {
-public:
- VertexShaderPosTexStretch();
-
- void init(GraphicsContext3D*, unsigned program);
- String getShaderString() const;
-
- int matrixLocation() const { return m_matrixLocation; }
- int offsetLocation() const { return m_offsetLocation; }
- int scaleLocation() const { return m_scaleLocation; }
-
-private:
- int m_matrixLocation;
- int m_offsetLocation;
- int m_scaleLocation;
-};
-
class VertexShaderPosTexYUVStretch {
public:
VertexShaderPosTexYUVStretch();
@@ -95,6 +78,12 @@ private:
int m_matrixLocation;
};
+class VertexShaderPosTexIdentity {
+public:
+ void init(GraphicsContext3D*, unsigned program) { }
+ String getShaderString() const;
+};
+
class VertexShaderPosTexTransform {
public:
VertexShaderPosTexTransform();
@@ -213,6 +202,11 @@ public:
String getShaderString() const;
};
+class FragmentShaderRGBATex : public FragmentTexOpaqueBinding {
+public:
+ String getShaderString() const;
+};
+
// Swizzles the red and blue component of sampled texel with alpha.
class FragmentShaderRGBATexSwizzleAlpha : public FragmentTexAlphaBinding {
public:
@@ -348,6 +342,21 @@ private:
int m_colorLocation;
};
+class FragmentShaderCheckerboard {
+public:
+ FragmentShaderCheckerboard();
+ String getShaderString() const;
+
+ void init(GraphicsContext3D*, unsigned program);
+ int alphaLocation() const { return m_alphaLocation; }
+ int texTransformLocation() const { return m_texTransformLocation; }
+ int frequencyLocation() const { return m_frequencyLocation; }
+private:
+ int m_alphaLocation;
+ int m_texTransformLocation;
+ int m_frequencyLocation;
+};
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp
index 5ae7ee6a9..39327d02a 100644
--- a/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp
+++ b/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp
@@ -48,18 +48,20 @@ SkPictureCanvasLayerTextureUpdater::~SkPictureCanvasLayerTextureUpdater()
{
}
-void SkPictureCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& /* tileSize */, int /* borderTexels */, float contentsScale, IntRect* resultingOpaqueRect)
+void SkPictureCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& /* tileSize */, int borderTexels, float contentsScale, IntRect& resultingOpaqueRect)
{
SkCanvas* canvas = m_picture.beginRecording(contentRect.width(), contentRect.height());
PlatformContextSkia platformContext(canvas);
platformContext.setDeferred(true);
platformContext.setTrackOpaqueRegion(!m_layerIsOpaque);
+ // Assumption: if a tiler is using border texels, then it is because the
+ // layer is likely to be filtered or transformed. Because it might be
+ // transformed, set image buffer flag to draw the text in grayscale
+ // instead of using subpixel antialiasing.
+ platformContext.setDrawingToImageBuffer(borderTexels ? true : false);
GraphicsContext graphicsContext(&platformContext);
- paintContents(graphicsContext, platformContext, contentRect, contentsScale);
+ paintContents(graphicsContext, platformContext, contentRect, contentsScale, resultingOpaqueRect);
m_picture.endRecording();
-
- if (!m_layerIsOpaque)
- *resultingOpaqueRect = platformContext.opaqueRegion().asRect();
}
void SkPictureCanvasLayerTextureUpdater::drawPicture(SkCanvas* canvas)
diff --git a/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.h
index ff839fe32..258a28ba3 100644
--- a/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.h
+++ b/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.h
@@ -52,7 +52,7 @@ public:
protected:
explicit SkPictureCanvasLayerTextureUpdater(PassOwnPtr<LayerPainterChromium>);
- virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, int borderTexels, float contentsScale, IntRect* resultingOpaqueRect);
+ virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, int borderTexels, float contentsScale, IntRect& resultingOpaqueRect);
void drawPicture(SkCanvas*);
bool layerIsOpaque() const { return m_layerIsOpaque; }
diff --git a/Source/WebCore/platform/graphics/chromium/TextureCopier.cpp b/Source/WebCore/platform/graphics/chromium/TextureCopier.cpp
new file mode 100644
index 000000000..a591a32a1
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/TextureCopier.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2012, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "TextureCopier.h"
+
+#include "LayerRendererChromium.h" // For the GLC() macro
+
+namespace WebCore {
+
+#if USE(ACCELERATED_COMPOSITING)
+AcceleratedTextureCopier::AcceleratedTextureCopier(PassRefPtr<GraphicsContext3D> context)
+ : m_context(context)
+{
+ GLC(m_context, m_fbo = m_context->createFramebuffer());
+ GLC(m_context, m_positionBuffer = m_context->createBuffer());
+
+ static const float kPositions[4][4] = {
+ {-1, -1, 0, 1},
+ { 1, -1, 0, 1},
+ { 1, 1, 0, 1},
+ {-1, 1, 0, 1}
+ };
+
+ GLC(m_context.get(), m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_positionBuffer));
+ GLC(m_context.get(), m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, sizeof(kPositions), kPositions, GraphicsContext3D::STATIC_DRAW));
+ GLC(m_context.get(), m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0));
+
+ m_blitProgram = adoptPtr(new BlitProgram(m_context.get()));
+}
+
+AcceleratedTextureCopier::~AcceleratedTextureCopier()
+{
+ if (m_blitProgram)
+ m_blitProgram->cleanup(m_context.get());
+ if (m_positionBuffer)
+ GLC(m_context, m_context->deleteBuffer(m_positionBuffer));
+ if (m_fbo)
+ GLC(m_context, m_context->deleteFramebuffer(m_fbo));
+}
+
+void AcceleratedTextureCopier::copyTexture(GraphicsContext3D* context, unsigned sourceTextureId, unsigned destTextureId, const IntSize& size)
+{
+ TRACE_EVENT("TextureCopier::copyTexture", this, 0);
+
+ // Note: this code does not restore the viewport, bound program, 2D texture, framebuffer, buffer or blend enable.
+ GLC(context, context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo));
+ GLC(context, context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, destTextureId, 0));
+
+#if OS(ANDROID)
+ // Clear destination to improve performance on tiling GPUs.
+ // TODO: Use EXT_discard_framebuffer or skip clearing if it isn't available.
+ GLC(context, context->clear(GraphicsContext3D::COLOR_BUFFER_BIT));
+#endif
+
+ GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, sourceTextureId));
+ GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST));
+ GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST));
+
+ if (!m_blitProgram->initialized())
+ m_blitProgram->initialize(context);
+
+ // TODO: Use EXT_framebuffer_blit if available.
+ GLC(context, context->useProgram(m_blitProgram->program()));
+
+ const int kPositionAttribute = 0;
+ GLC(context, context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_positionBuffer));
+ GLC(context, context->vertexAttribPointer(kPositionAttribute, 4, GraphicsContext3D::FLOAT, false, 0, 0));
+ GLC(context, context->enableVertexAttribArray(kPositionAttribute));
+ GLC(context, context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0));
+
+ GLC(context, context->viewport(0, 0, size.width(), size.height()));
+ GLC(context, context->disable(GraphicsContext3D::BLEND));
+ GLC(context, context->drawArrays(GraphicsContext3D::TRIANGLE_FAN, 0, 4));
+
+ GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
+ GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
+ GLC(context, context->disableVertexAttribArray(kPositionAttribute));
+
+ GLC(context, context->useProgram(0));
+
+ GLC(context, context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, 0, 0));
+ GLC(context, context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
+ GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0));
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/TextureCopier.h b/Source/WebCore/platform/graphics/chromium/TextureCopier.h
new file mode 100644
index 000000000..73be5ecad
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/TextureCopier.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TextureCopier_h
+#define TextureCopier_h
+
+#include "GraphicsContext3D.h"
+#include "ProgramBinding.h"
+#include "ShaderChromium.h"
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class TextureCopier {
+public:
+ // Copy the base level contents of |sourceTextureId| to |destTextureId|. Both texture objects
+ // must be complete and have a base level of |size| dimensions. The color formats do not need
+ // to match, but |destTextureId| must have a renderable format.
+ virtual void copyTexture(GraphicsContext3D*, unsigned sourceTextureId, unsigned destTextureId, const IntSize&) = 0;
+
+protected:
+ virtual ~TextureCopier() { }
+};
+
+#if USE(ACCELERATED_COMPOSITING)
+
+class AcceleratedTextureCopier : public TextureCopier {
+ WTF_MAKE_NONCOPYABLE(AcceleratedTextureCopier);
+public:
+ static PassOwnPtr<AcceleratedTextureCopier> create(PassRefPtr<GraphicsContext3D> context)
+ {
+ return adoptPtr(new AcceleratedTextureCopier(context));
+ }
+ virtual ~AcceleratedTextureCopier();
+
+ virtual void copyTexture(GraphicsContext3D*, unsigned sourceTextureId, unsigned destTextureId, const IntSize&);
+
+protected:
+ explicit AcceleratedTextureCopier(PassRefPtr<GraphicsContext3D>);
+
+private:
+ typedef ProgramBinding<VertexShaderPosTexIdentity, FragmentShaderRGBATex> BlitProgram;
+
+ RefPtr<GraphicsContext3D> m_context;
+ Platform3DObject m_fbo;
+ Platform3DObject m_positionBuffer;
+ OwnPtr<BlitProgram> m_blitProgram;
+};
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/TextureLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/TextureLayerChromium.cpp
new file mode 100644
index 000000000..b0a1ec4c6
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/TextureLayerChromium.cpp
@@ -0,0 +1,133 @@
+/*
+ * 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 "TextureLayerChromium.h"
+
+#include "Extensions3D.h"
+#include "cc/CCLayerTreeHost.h"
+#include "cc/CCTextureLayerImpl.h"
+
+namespace WebCore {
+
+PassRefPtr<TextureLayerChromium> TextureLayerChromium::create(TextureLayerChromiumClient* client)
+{
+ return adoptRef(new TextureLayerChromium(client));
+}
+
+TextureLayerChromium::TextureLayerChromium(TextureLayerChromiumClient* client)
+ : LayerChromium()
+ , m_client(client)
+ , m_flipped(true)
+ , m_uvRect(0, 0, 1, 1)
+ , m_premultipliedAlpha(true)
+ , m_rateLimitContext(false)
+ , m_contextLost(false)
+ , m_textureId(0)
+{
+}
+
+TextureLayerChromium::~TextureLayerChromium()
+{
+ if (m_rateLimitContext && m_client && layerTreeHost())
+ layerTreeHost()->stopRateLimiter(m_client->context());
+}
+
+PassOwnPtr<CCLayerImpl> TextureLayerChromium::createCCLayerImpl()
+{
+ return CCTextureLayerImpl::create(m_layerId);
+}
+
+void TextureLayerChromium::setFlipped(bool flipped)
+{
+ m_flipped = flipped;
+ setNeedsCommit();
+}
+
+void TextureLayerChromium::setUVRect(const FloatRect& rect)
+{
+ m_uvRect = rect;
+ setNeedsCommit();
+}
+
+void TextureLayerChromium::setPremultipliedAlpha(bool premultipliedAlpha)
+{
+ m_premultipliedAlpha = premultipliedAlpha;
+ setNeedsCommit();
+}
+
+void TextureLayerChromium::setRateLimitContext(bool rateLimit)
+{
+ if (!rateLimit && m_rateLimitContext && m_client && layerTreeHost())
+ layerTreeHost()->stopRateLimiter(m_client->context());
+
+ m_rateLimitContext = rateLimit;
+}
+
+void TextureLayerChromium::setTextureId(unsigned id)
+{
+ m_textureId = id;
+ setNeedsCommit();
+}
+
+void TextureLayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect)
+{
+ LayerChromium::setNeedsDisplayRect(dirtyRect);
+
+ if (m_rateLimitContext && m_client && layerTreeHost())
+ layerTreeHost()->startRateLimiter(m_client->context());
+}
+
+bool TextureLayerChromium::drawsContent() const
+{
+ return (m_client || m_textureId) && !m_contextLost && LayerChromium::drawsContent();
+}
+
+void TextureLayerChromium::update(CCTextureUpdater& updater, const CCOcclusionTracker*)
+{
+ if (m_client) {
+ m_textureId = m_client->prepareTexture(updater);
+ m_contextLost = m_client->context()->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR;
+ }
+
+ m_needsDisplay = false;
+}
+
+void TextureLayerChromium::pushPropertiesTo(CCLayerImpl* layer)
+{
+ LayerChromium::pushPropertiesTo(layer);
+
+ CCTextureLayerImpl* textureLayer = static_cast<CCTextureLayerImpl*>(layer);
+ textureLayer->setFlipped(m_flipped);
+ textureLayer->setUVRect(m_uvRect);
+ textureLayer->setPremultipliedAlpha(m_premultipliedAlpha);
+ textureLayer->setTextureId(m_textureId);
+}
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/TextureLayerChromium.h b/Source/WebCore/platform/graphics/chromium/TextureLayerChromium.h
new file mode 100644
index 000000000..a306012f0
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/TextureLayerChromium.h
@@ -0,0 +1,104 @@
+/*
+ * 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 TextureLayerChromium_h
+#define TextureLayerChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerChromium.h"
+
+namespace WebCore {
+
+class TextureLayerChromiumClient {
+public:
+ // Called to prepare this layer's texture for compositing. The client may queue a texture
+ // upload or copy on the CCTextureUpdater.
+ // Returns the texture ID to be used for compositing.
+ virtual unsigned prepareTexture(CCTextureUpdater&) = 0;
+
+ // Returns the context that is providing the texture. Used for rate limiting and detecting lost context.
+ virtual GraphicsContext3D* context() = 0;
+
+protected:
+ virtual ~TextureLayerChromiumClient() { }
+};
+
+// A Layer containing a the rendered output of a plugin instance.
+class TextureLayerChromium : public LayerChromium {
+public:
+ // If this texture layer requires special preparation logic for each frame driven by
+ // the compositor, pass in a non-nil client. Pass in a nil client pointer if texture updates
+ // are driven by an external process.
+ static PassRefPtr<TextureLayerChromium> create(TextureLayerChromiumClient*);
+ virtual ~TextureLayerChromium();
+
+ void clearClient() { m_client = 0; }
+
+ virtual PassOwnPtr<CCLayerImpl> createCCLayerImpl() OVERRIDE;
+
+ // Sets whether this texture should be Y-flipped at draw time. Defaults to true.
+ void setFlipped(bool);
+
+ // Sets a UV transform to be used at draw time. Defaults to (0, 0, 1, 1).
+ void setUVRect(const FloatRect&);
+
+ // Sets whether the alpha channel is premultiplied or unpremultiplied. Defaults to true.
+ void setPremultipliedAlpha(bool);
+
+ // Sets whether this context should rate limit on damage to prevent too many frames from
+ // being queued up before the compositor gets a chance to run. Requires a non-nil client.
+ // Defaults to false.
+ void setRateLimitContext(bool);
+
+ // Code path for plugins which supply their own texture ID.
+ void setTextureId(unsigned);
+
+ virtual void setNeedsDisplayRect(const FloatRect&) OVERRIDE;
+
+ virtual bool drawsContent() const OVERRIDE;
+ virtual void update(CCTextureUpdater&, const CCOcclusionTracker*) OVERRIDE;
+ virtual void pushPropertiesTo(CCLayerImpl*) OVERRIDE;
+
+protected:
+ explicit TextureLayerChromium(TextureLayerChromiumClient*);
+
+private:
+ TextureLayerChromiumClient* m_client;
+
+ bool m_flipped;
+ FloatRect m_uvRect;
+ bool m_premultipliedAlpha;
+ bool m_rateLimitContext;
+ bool m_contextLost;
+
+ unsigned m_textureId;
+};
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/TextureManager.cpp b/Source/WebCore/platform/graphics/chromium/TextureManager.cpp
index 0c6fe14f9..97e62b91c 100644
--- a/Source/WebCore/platform/graphics/chromium/TextureManager.cpp
+++ b/Source/WebCore/platform/graphics/chromium/TextureManager.cpp
@@ -39,6 +39,8 @@ namespace WebCore {
namespace {
size_t memoryLimitBytes(size_t viewportMultiplier, const IntSize& viewportSize, size_t minMegabytes, size_t maxMegabytes)
{
+ if (!viewportMultiplier)
+ return maxMegabytes * 1024 * 1024;
if (viewportSize.isEmpty())
return minMegabytes * 1024 * 1024;
return max(minMegabytes * 1024 * 1024, min(maxMegabytes * 1024 * 1024, viewportMultiplier * TextureManager::memoryUseBytes(viewportSize, GraphicsContext3D::RGBA)));
@@ -48,12 +50,13 @@ size_t memoryLimitBytes(size_t viewportMultiplier, const IntSize& viewportSize,
size_t TextureManager::highLimitBytes(const IntSize& viewportSize)
{
size_t viewportMultiplier, minMegabytes, maxMegabytes;
- viewportMultiplier = 12;
#if OS(ANDROID)
- minMegabytes = 24;
- maxMegabytes = 40;
+ viewportMultiplier = 16;
+ minMegabytes = 32;
+ maxMegabytes = 64;
#else
- minMegabytes = 64;
+ viewportMultiplier = 0;
+ minMegabytes = 0;
maxMegabytes = 128;
#endif
return memoryLimitBytes(viewportMultiplier, viewportSize, minMegabytes, maxMegabytes);
@@ -62,26 +65,18 @@ size_t TextureManager::highLimitBytes(const IntSize& viewportSize)
size_t TextureManager::reclaimLimitBytes(const IntSize& viewportSize)
{
size_t viewportMultiplier, minMegabytes, maxMegabytes;
- viewportMultiplier = 6;
#if OS(ANDROID)
- minMegabytes = 9;
+ viewportMultiplier = 8;
+ minMegabytes = 16;
maxMegabytes = 32;
#else
- minMegabytes = 32;
+ viewportMultiplier = 0;
+ minMegabytes = 0;
maxMegabytes = 64;
#endif
return memoryLimitBytes(viewportMultiplier, viewportSize, minMegabytes, maxMegabytes);
}
-size_t TextureManager::lowLimitBytes(const IntSize& viewportSize)
-{
- size_t viewportMultiplier, minMegabytes, maxMegabytes;
- viewportMultiplier = 1;
- minMegabytes = 2;
- maxMegabytes = 3;
- return memoryLimitBytes(viewportMultiplier, viewportSize, minMegabytes, maxMegabytes);
-}
-
size_t TextureManager::memoryUseBytes(const IntSize& size, GC3Denum textureFormat)
{
// FIXME: This assumes all textures are 1 byte/component.
@@ -110,6 +105,20 @@ TextureManager::~TextureManager()
(*it)->clearManager();
}
+void TextureManager::setMemoryAllocationLimitBytes(size_t memoryLimitBytes)
+{
+ setMaxMemoryLimitBytes(memoryLimitBytes);
+#if defined(OS_ANDROID)
+ // On android, we are setting the preferred memory limit to half of our
+ // maximum allocation, because we would like to stay significantly below
+ // the absolute memory limit whenever we can. Specifically, by limitting
+ // prepainting only to the halfway memory mark.
+ setPreferredMemoryLimitBytes(memoryLimitBytes / 2);
+#else
+ setPreferredMemoryLimitBytes(memoryLimitBytes);
+#endif
+}
+
void TextureManager::setMaxMemoryLimitBytes(size_t memoryLimitBytes)
{
reduceMemoryToLimit(memoryLimitBytes);
diff --git a/Source/WebCore/platform/graphics/chromium/TextureManager.h b/Source/WebCore/platform/graphics/chromium/TextureManager.h
index e4d6d38b8..3147635a8 100644
--- a/Source/WebCore/platform/graphics/chromium/TextureManager.h
+++ b/Source/WebCore/platform/graphics/chromium/TextureManager.h
@@ -62,11 +62,10 @@ public:
static size_t highLimitBytes(const IntSize& viewportSize);
// Preferred texture size limit given the viewport size.
static size_t reclaimLimitBytes(const IntSize& viewportSize);
- // The maximum texture memory usage when asked to release textures.
- static size_t lowLimitBytes(const IntSize& viewport);
static size_t memoryUseBytes(const IntSize&, GC3Denum format);
+ void setMemoryAllocationLimitBytes(size_t);
void setMaxMemoryLimitBytes(size_t);
size_t maxMemoryLimitBytes() { return m_maxMemoryLimitBytes; }
void setPreferredMemoryLimitBytes(size_t);
diff --git a/Source/WebCore/platform/graphics/chromium/TextureUploader.cpp b/Source/WebCore/platform/graphics/chromium/TextureUploader.cpp
new file mode 100644
index 000000000..556fe0e0c
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/TextureUploader.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "TextureUploader.h"
+
+namespace WebCore {
+
+AcceleratedTextureUploader::AcceleratedTextureUploader(PassRefPtr<GraphicsContext3D> context)
+ : m_context(context)
+{
+}
+
+AcceleratedTextureUploader::~AcceleratedTextureUploader()
+{
+}
+
+void AcceleratedTextureUploader::uploadTexture(GraphicsContext3D* context, LayerTextureUpdater::Texture* texture, TextureAllocator* allocator, const IntRect sourceRect, const IntRect destRect)
+{
+ texture->updateRect(context, allocator, sourceRect, destRect);
+}
+
+}
diff --git a/Source/WebCore/platform/graphics/chromium/TextureUploader.h b/Source/WebCore/platform/graphics/chromium/TextureUploader.h
new file mode 100644
index 000000000..afed54a4a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/TextureUploader.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TextureUploader_h
+#define TextureUploader_h
+
+#include "LayerTextureUpdater.h"
+
+namespace WebCore {
+
+class TextureUploader {
+public:
+ virtual void uploadTexture(GraphicsContext3D*, LayerTextureUpdater::Texture*, TextureAllocator*, const IntRect sourceRect, const IntRect destRect) = 0;
+
+protected:
+ virtual ~TextureUploader() { }
+};
+
+class AcceleratedTextureUploader : public TextureUploader {
+ WTF_MAKE_NONCOPYABLE(AcceleratedTextureUploader);
+public:
+ static PassOwnPtr<AcceleratedTextureUploader> create(PassRefPtr<GraphicsContext3D> context)
+ {
+ return adoptPtr(new AcceleratedTextureUploader(context));
+ }
+ virtual ~AcceleratedTextureUploader();
+
+ virtual void uploadTexture(GraphicsContext3D*, LayerTextureUpdater::Texture*, TextureAllocator*, const IntRect sourceRect, const IntRect destRect);
+
+protected:
+ explicit AcceleratedTextureUploader(PassRefPtr<GraphicsContext3D>);
+
+ RefPtr<GraphicsContext3D> m_context;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp
index 0259a23d3..68f4964ba 100644
--- a/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp
@@ -32,14 +32,16 @@
#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h"
#include "ManagedTexture.h"
-#include "MathExtras.h"
#include "Region.h"
#include "TextStream.h"
#include "TraceEvent.h"
+
#include "cc/CCLayerImpl.h"
#include "cc/CCTextureUpdater.h"
#include "cc/CCTiledLayerImpl.h"
+
#include <wtf/CurrentTime.h>
+#include <wtf/MathExtras.h>
// Start tiling when the width and height of a layer are larger than this size.
static int maxUntiledSize = 512;
@@ -62,20 +64,26 @@ public:
LayerTextureUpdater::Texture* texture() { return m_texture.get(); }
ManagedTexture* managedTexture() { return m_texture->texture(); }
- bool isDirty() const { return !m_dirtyRect.isEmpty(); }
+ bool isDirty() const { return !dirtyRect.isEmpty(); }
void copyAndClearDirty()
{
- m_updateRect = m_dirtyRect;
- m_dirtyRect = IntRect();
+ updateRect = dirtyRect;
+ dirtyRect = IntRect();
}
- bool isDirtyForCurrentFrame() { return !m_dirtyRect.isEmpty() && m_updateRect.isEmpty(); }
-
- IntRect m_dirtyRect;
- IntRect m_updateRect;
- bool m_partialUpdate;
+ // Returns whether the layer was dirty and not updated in the current frame. For tiles that were not culled, the
+ // updateRect holds the area of the tile that was updated. Otherwise, the area that would have been updated.
+ bool isDirtyForCurrentFrame() { return !dirtyRect.isEmpty() && (updateRect.isEmpty() || !updated); }
+
+ IntRect dirtyRect;
+ IntRect updateRect;
+ bool partialUpdate;
+ bool updated;
+ bool isInUseOnImpl;
private:
explicit UpdatableTile(PassOwnPtr<LayerTextureUpdater::Texture> texture)
- : m_partialUpdate(false)
+ : partialUpdate(false)
+ , updated(false)
+ , isInUseOnImpl(false)
, m_texture(texture)
{
}
@@ -89,6 +97,7 @@ TiledLayerChromium::TiledLayerChromium()
, m_skipsDraw(false)
, m_skipsIdlePaint(false)
, m_sampledTexelFormat(LayerTextureUpdater::SampledTexelFormatInvalid)
+ , m_didPaint(false)
, m_tilingOption(AutoTile)
{
m_tiler = CCLayerTilingData::create(IntSize(defaultTileSize, defaultTileSize), CCLayerTilingData::HasBorderTexels);
@@ -160,7 +169,8 @@ bool TiledLayerChromium::drawsContent() const
if (!LayerChromium::drawsContent())
return false;
- if (m_tilingOption == NeverTile && m_tiler->numTiles() > 1)
+ bool hasMoreThanOneTile = m_tiler->numTilesX() > 1 || m_tiler->numTilesY() > 1;
+ if (m_tilingOption == NeverTile && hasMoreThanOneTile)
return false;
return true;
@@ -176,65 +186,6 @@ IntSize TiledLayerChromium::contentBounds() const
return IntSize(lroundf(bounds().width() * contentsScale()), lroundf(bounds().height() * contentsScale()));
}
-void TiledLayerChromium::updateCompositorResources(GraphicsContext3D*, CCTextureUpdater& updater)
-{
- // Painting could cause compositing to get turned off, which may cause the tiler to become invalidated mid-update.
- if (m_skipsDraw || m_requestedUpdateTilesRect.isEmpty() || m_tiler->isEmpty())
- return;
-
- int left = m_requestedUpdateTilesRect.x();
- int top = m_requestedUpdateTilesRect.y();
- int right = m_requestedUpdateTilesRect.maxX() - 1;
- int bottom = m_requestedUpdateTilesRect.maxY() - 1;
- for (int j = top; j <= bottom; ++j) {
- for (int i = left; i <= right; ++i) {
- UpdatableTile* tile = tileAt(i, j);
-
- // Required tiles are created in prepareToUpdate(). A tile should
- // never be removed between the call to prepareToUpdate() and the
- // call to updateCompositorResources().
- if (!tile)
- CRASH();
-
- IntRect sourceRect = tile->m_updateRect;
- if (tile->m_updateRect.isEmpty())
- continue;
-
- ASSERT(tile->managedTexture()->isReserved());
- const IntPoint anchor = m_tiler->tileRect(tile).location();
-
- // Calculate tile-space rectangle to upload into.
- IntRect destRect(IntPoint(sourceRect.x() - anchor.x(), sourceRect.y() - anchor.y()), sourceRect.size());
- if (destRect.x() < 0)
- CRASH();
- if (destRect.y() < 0)
- CRASH();
-
- // Offset from paint rectangle to this tile's dirty rectangle.
- IntPoint paintOffset(sourceRect.x() - m_paintRect.x(), sourceRect.y() - m_paintRect.y());
- if (paintOffset.x() < 0)
- CRASH();
- if (paintOffset.y() < 0)
- CRASH();
- if (paintOffset.x() + destRect.width() > m_paintRect.width())
- CRASH();
- if (paintOffset.y() + destRect.height() > m_paintRect.height())
- CRASH();
-
- if (tile->m_partialUpdate)
- updater.appendPartial(tile->texture(), sourceRect, destRect);
- else
- updater.append(tile->texture(), sourceRect, destRect);
- }
- }
-
- // The updateRect should be in layer space. So we have to convert the paintRect from content space to layer space.
- m_updateRect = FloatRect(m_paintRect);
- float widthScale = bounds().width() / static_cast<float>(contentBounds().width());
- float heightScale = bounds().height() / static_cast<float>(contentBounds().height());
- m_updateRect.scale(widthScale, heightScale);
-}
-
void TiledLayerChromium::setTilingOption(TilingOption tilingOption)
{
m_tilingOption = tilingOption;
@@ -260,6 +211,7 @@ void TiledLayerChromium::pushPropertiesTo(CCLayerImpl* layer)
int i = iter->first.first;
int j = iter->first.second;
UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get());
+ tile->isInUseOnImpl = false;
if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) {
invalidTiles.append(tile);
continue;
@@ -268,6 +220,7 @@ void TiledLayerChromium::pushPropertiesTo(CCLayerImpl* layer)
continue;
tiledLayer->pushTileProperties(i, j, tile->managedTexture()->textureId(), tile->opaqueRect());
+ tile->isInUseOnImpl = true;
}
for (Vector<UpdatableTile*>::const_iterator iter = invalidTiles.begin(); iter != invalidTiles.end(); ++iter)
m_tiler->takeTile((*iter)->i(), (*iter)->j());
@@ -302,7 +255,7 @@ UpdatableTile* TiledLayerChromium::createTile(int i, int j)
UpdatableTile* addedTile = tile.get();
m_tiler->addTile(tile.release(), i, j);
- addedTile->m_dirtyRect = m_tiler->tileRect(addedTile);
+ addedTile->dirtyRect = m_tiler->tileRect(addedTile);
return addedTile;
}
@@ -340,7 +293,7 @@ void TiledLayerChromium::invalidateRect(const IntRect& layerRect)
ASSERT(tile);
IntRect bound = m_tiler->tileRect(tile);
bound.intersect(layerRect);
- tile->m_dirtyRect.unite(bound);
+ tile->dirtyRect.unite(bound);
}
}
@@ -371,109 +324,107 @@ void TiledLayerChromium::protectTileTextures(const IntRect& layerRect)
// Returns true if tile is dirty and only part of it needs to be updated.
bool TiledLayerChromium::tileOnlyNeedsPartialUpdate(UpdatableTile* tile)
{
- if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat))
- return false;
-
- if (!tile->isDirty())
- return false;
-
- return !tile->m_dirtyRect.contains(m_tiler->tileRect(tile));
+ return !tile->dirtyRect.contains(m_tiler->tileRect(tile));
}
// Dirty tiles with valid textures needs buffered update to guarantee that
// we don't modify textures currently used for drawing by the impl thread.
bool TiledLayerChromium::tileNeedsBufferedUpdate(UpdatableTile* tile)
{
- // No impl thread?.
- if (!CCProxy::hasImplThread())
- return false;
-
if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat))
return false;
if (!tile->isDirty())
return false;
- return true;
-}
+ if (!tile->isInUseOnImpl)
+ return false;
-// FIXME: This gets rolled into CCOcclusionTracker when we stop passing around Region objects.
-static inline TransformationMatrix contentToLayerTransform(const IntSize& boundsInLayerSpace, const IntSize& boundsInContentSpace)
-{
- TransformationMatrix transform;
- // Scale from content space to layer space
- transform.scaleNonUniform(boundsInLayerSpace.width() / static_cast<double>(boundsInContentSpace.width()),
- boundsInLayerSpace.height() / static_cast<double>(boundsInContentSpace.height()));
- return transform;
+ return true;
}
-void TiledLayerChromium::prepareToUpdateTiles(bool idle, int left, int top, int right, int bottom, const Region& occludedScreenSpace)
+void TiledLayerChromium::updateTiles(bool idle, int left, int top, int right, int bottom, CCTextureUpdater& updater, const CCOcclusionTracker* occlusion)
{
createTextureUpdaterIfNeeded();
- // Tiles are in the layer's content space, the occluded region is in screen space.
- TransformationMatrix contentToScreenSpace = screenSpaceTransform() * contentToLayerTransform(bounds(), contentBounds());
-
// Create tiles as needed, expanding a dirty rect to contain all
// the dirty regions currently being drawn. All dirty tiles that are to be painted
- // get their m_updateRect set to m_dirtyRect and m_dirtyRect cleared. This way if
- // invalidateRect is invoked during prepareToUpdate we don't lose the request.
- IntRect dirtyLayerRect;
+ // get their updateRect set to dirtyRect and dirtyRect cleared. This way if
+ // invalidateRect is invoked during updateLayerRect we don't lose the request.
+ IntRect paintRect;
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
UpdatableTile* tile = tileAt(i, j);
if (!tile)
tile = createTile(i, j);
- // When not idle painting, if the visible region of the tile is occluded, don't reserve a texture or mark it for update.
- // If any part of the tile is visible, then we need to paint it so the tile is pushed to the impl thread.
- // This will also avoid painting the tile in the next loop, below.
- if (!idle) {
+ if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) {
+ // Sets the dirty rect to a full-sized tile with border texels.
+ tile->dirtyRect = m_tiler->tileRect(tile);
+ }
+
+ // When not idle painting, if the visible region of the tile is occluded, don't reserve a texture or update the tile.
+ // If any part of the tile is visible, then we need to update it so the tile is pushed to the impl thread.
+ if (!idle && occlusion) {
IntRect visibleTileRect = intersection(m_tiler->tileBounds(i, j), visibleLayerRect());
- if (occludedScreenSpace.contains(contentToScreenSpace.mapRect(visibleTileRect)))
+ if (occlusion->occluded(this, visibleTileRect)) {
+ ASSERT(!tile->updated);
continue;
+ }
}
- // FIXME: Decide if partial update should be allowed based on cost
- // of update. https://bugs.webkit.org/show_bug.cgi?id=77376
- if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost() && layerTreeHost()->requestPartialTextureUpdate())
- tile->m_partialUpdate = true;
- else if (tileNeedsBufferedUpdate(tile) && layerTreeHost())
- layerTreeHost()->deleteTextureAfterCommit(tile->managedTexture()->steal());
-
- if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) {
- // Sets the dirty rect to a full-sized tile with border texels.
- tile->m_dirtyRect = m_tiler->tileRect(tile);
+ // We come through this function multiple times during a commit, and updated should be true if the tile is not culled
+ // any single time through the function.
+ tile->updated = true;
+
+ if (layerTreeHost() && layerTreeHost()->bufferedUpdates() && tileNeedsBufferedUpdate(tile)) {
+ // FIXME: Decide if partial update should be allowed based on cost
+ // of update. https://bugs.webkit.org/show_bug.cgi?id=77376
+ if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost()->requestPartialTextureUpdate())
+ tile->partialUpdate = true;
+ else {
+ layerTreeHost()->deleteTextureAfterCommit(tile->managedTexture()->steal());
+ // Sets the dirty rect to a full-sized tile with border texels.
+ tile->dirtyRect = m_tiler->tileRect(tile);
+ }
}
if (!tile->managedTexture()->reserve(m_tiler->tileSize(), m_textureFormat)) {
m_skipsIdlePaint = true;
if (!idle) {
- // If the background covers the viewport, always draw this
- // layer so that checkerboarded tiles will still draw.
- if (!backgroundCoversViewport())
- m_skipsDraw = true;
+ m_skipsDraw = true;
m_tiler->reset();
- m_paintRect = IntRect();
- m_requestedUpdateTilesRect = IntRect();
}
return;
}
- dirtyLayerRect.unite(tile->m_dirtyRect);
- tile->copyAndClearDirty();
+ paintRect.unite(tile->dirtyRect);
}
}
- m_paintRect = dirtyLayerRect;
- if (dirtyLayerRect.isEmpty())
+ // For tiles that were not culled, we are going to update the area currently marked as dirty. So
+ // clear that dirty area and mark it for update instead.
+ for (int j = top; j <= bottom; ++j) {
+ for (int i = left; i <= right; ++i) {
+ UpdatableTile* tile = tileAt(i, j);
+ if (tile->updated)
+ tile->copyAndClearDirty();
+ else if (!idle && occlusion && tile->isDirty())
+ occlusion->overdrawMetrics().didCullTileForUpload();
+ }
+ }
+
+ if (paintRect.isEmpty())
return;
- // Due to borders, when the paint rect is extended to tile boundaries, it
- // may end up overlapping more tiles than the original content rect. Record
- // the original tiles so we don't upload more tiles than necessary.
- if (!m_paintRect.isEmpty())
- m_requestedUpdateTilesRect = IntRect(left, top, right - left + 1, bottom - top + 1);
+ if (occlusion)
+ occlusion->overdrawMetrics().didPaint(paintRect);
+
+ // The updateRect should be in layer space. So we have to convert the paintRect from content space to layer space.
+ m_updateRect = FloatRect(paintRect);
+ float widthScale = bounds().width() / static_cast<float>(contentBounds().width());
+ float heightScale = bounds().height() / static_cast<float>(contentBounds().height());
+ m_updateRect.scale(widthScale, heightScale);
// Calling prepareToUpdate() calls into WebKit to paint, which may have the side
// effect of disabling compositing, which causes our reference to the texture updater to be deleted.
@@ -481,25 +432,26 @@ void TiledLayerChromium::prepareToUpdateTiles(bool idle, int left, int top, int
// so we grab a local reference here to hold the updater alive until the paint completes.
RefPtr<LayerTextureUpdater> protector(textureUpdater());
IntRect paintedOpaqueRect;
- textureUpdater()->prepareToUpdate(m_paintRect, m_tiler->tileSize(), m_tiler->hasBorderTexels(), contentsScale(), &paintedOpaqueRect);
+ textureUpdater()->prepareToUpdate(paintRect, m_tiler->tileSize(), m_tiler->hasBorderTexels(), contentsScale(), paintedOpaqueRect);
+ m_didPaint = true;
+
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
UpdatableTile* tile = tileAt(i, j);
- // Tiles are created before prepareToUpdate() is called.
- if (!tile)
- CRASH();
-
IntRect tileRect = m_tiler->tileBounds(i, j);
- // Use m_updateRect as copyAndClearDirty above moved the existing dirty rect to m_updateRect if the tile isn't culled.
- const IntRect& dirtyRect = tile->m_updateRect;
+ if (!tile->updated)
+ continue;
+
+ // Use updateRect as the above loop copied the dirty rect for this frame to updateRect.
+ const IntRect& dirtyRect = tile->updateRect;
if (dirtyRect.isEmpty())
continue;
// Save what was painted opaque in the tile. Keep the old area if the paint didn't touch it, and didn't paint some
// other part of the tile opaque.
- IntRect tilePaintedRect = intersection(tileRect, m_paintRect);
+ IntRect tilePaintedRect = intersection(tileRect, paintRect);
IntRect tilePaintedOpaqueRect = intersection(tileRect, paintedOpaqueRect);
if (!tilePaintedRect.isEmpty()) {
IntRect paintInsideTileOpaqueRect = intersection(tile->opaqueRect(), tilePaintedRect);
@@ -515,13 +467,41 @@ void TiledLayerChromium::prepareToUpdateTiles(bool idle, int left, int top, int
sourceRect.intersect(dirtyRect);
// Paint rect not guaranteed to line up on tile boundaries, so
// make sure that sourceRect doesn't extend outside of it.
- sourceRect.intersect(m_paintRect);
+ sourceRect.intersect(paintRect);
+
+ tile->updateRect = sourceRect;
- tile->m_updateRect = sourceRect;
if (sourceRect.isEmpty())
continue;
tile->texture()->prepareRect(sourceRect);
+ if (occlusion)
+ occlusion->overdrawMetrics().didUpload(TransformationMatrix(), sourceRect, tile->opaqueRect());
+
+ const IntPoint anchor = m_tiler->tileRect(tile).location();
+
+ // Calculate tile-space rectangle to upload into.
+ IntRect destRect(IntPoint(sourceRect.x() - anchor.x(), sourceRect.y() - anchor.y()), sourceRect.size());
+ if (destRect.x() < 0)
+ CRASH();
+ if (destRect.y() < 0)
+ CRASH();
+
+ // Offset from paint rectangle to this tile's dirty rectangle.
+ IntPoint paintOffset(sourceRect.x() - paintRect.x(), sourceRect.y() - paintRect.y());
+ if (paintOffset.x() < 0)
+ CRASH();
+ if (paintOffset.y() < 0)
+ CRASH();
+ if (paintOffset.x() + destRect.width() > paintRect.width())
+ CRASH();
+ if (paintOffset.y() + destRect.height() > paintRect.height())
+ CRASH();
+
+ if (tile->partialUpdate)
+ updater.appendPartialUpdate(tile->texture(), sourceRect, destRect);
+ else
+ updater.appendUpdate(tile->texture(), sourceRect, destRect);
}
}
}
@@ -531,7 +511,7 @@ void TiledLayerChromium::reserveTextures()
updateBounds();
const IntRect& layerRect = visibleLayerRect();
- if (layerRect.isEmpty() || !m_tiler->numTiles())
+ if (layerRect.isEmpty() || m_tiler->hasEmptyBounds())
return;
int left, top, right, bottom;
@@ -545,7 +525,7 @@ void TiledLayerChromium::reserveTextures()
tile = createTile(i, j);
if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat))
- tile->m_dirtyRect = m_tiler->tileRect(tile);
+ tile->dirtyRect = m_tiler->tileRect(tile);
if (!tile->managedTexture()->reserve(m_tiler->tileSize(), m_textureFormat))
return;
@@ -553,97 +533,117 @@ void TiledLayerChromium::reserveTextures()
}
}
-Region TiledLayerChromium::opaqueContentsRegion() const
+Region TiledLayerChromium::visibleContentOpaqueRegion() const
{
if (m_skipsDraw)
return Region();
-
+ if (opaque())
+ return visibleLayerRect();
return m_tiler->opaqueRegionInLayerRect(visibleLayerRect());
}
void TiledLayerChromium::resetUpdateState()
{
- // Reset m_updateRect for all tiles.
CCLayerTilingData::TileMap::const_iterator end = m_tiler->tiles().end();
for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != end; ++iter) {
UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get());
- tile->m_updateRect = IntRect();
- tile->m_partialUpdate = false;
+ tile->updateRect = IntRect();
+ tile->partialUpdate = false;
+ tile->updated = false;
}
}
-void TiledLayerChromium::prepareToUpdate(const IntRect& layerRect, const Region& occludedScreenSpace)
+void TiledLayerChromium::updateLayerRect(CCTextureUpdater& updater, const IntRect& layerRect, const CCOcclusionTracker* occlusion)
{
m_skipsDraw = false;
m_skipsIdlePaint = false;
- m_requestedUpdateTilesRect = IntRect();
- m_paintRect = IntRect();
+ m_didPaint = false;
updateBounds();
resetUpdateState();
- if (layerRect.isEmpty() || !m_tiler->numTiles())
+ if (layerRect.isEmpty() || m_tiler->hasEmptyBounds())
return;
int left, top, right, bottom;
m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom);
- prepareToUpdateTiles(false, left, top, right, bottom, occludedScreenSpace);
+ updateTiles(false, left, top, right, bottom, updater, occlusion);
}
-void TiledLayerChromium::prepareToUpdateIdle(const IntRect& layerRect, const Region& occludedScreenSpace)
+void TiledLayerChromium::idleUpdateLayerRect(CCTextureUpdater& updater, const IntRect& layerRect, const CCOcclusionTracker* occlusion)
{
- // Abort if we have already prepared a paint or run out of memory.
- if (m_skipsIdlePaint || !m_paintRect.isEmpty())
+ // Abort if we have already painted or run out of memory.
+ if (m_skipsIdlePaint || m_didPaint)
return;
ASSERT(m_tiler);
updateBounds();
- if (m_tiler->isEmpty())
+ if (m_tiler->hasEmptyBounds())
return;
- // Protect any textures in the pre-paint area so we don't end up just
- // reclaiming them below.
IntRect idlePaintLayerRect = idlePaintRect(layerRect);
+ if (idlePaintLayerRect.isEmpty())
+ return;
+
+ // Protect any textures in the pre-paint area, as we would steal them from other layers
+ // over time anyhow. This ensures we don't lose tiles in the first rounds of idle painting
+ // that we have already painted.
protectTileTextures(idlePaintLayerRect);
+ int prepaintLeft, prepaintTop, prepaintRight, prepaintBottom;
+ m_tiler->layerRectToTileIndices(idlePaintLayerRect, prepaintLeft, prepaintTop, prepaintRight, prepaintBottom);
+
+ // If the layer is not visible, we have nothing to expand from, so instead we prepaint the outer-most set of tiles.
+ if (layerRect.isEmpty()) {
+ updateTiles(true, prepaintLeft, prepaintTop, prepaintRight, prepaintTop, updater, 0);
+ if (m_didPaint || m_skipsIdlePaint)
+ return;
+ updateTiles(true, prepaintLeft, prepaintBottom, prepaintRight, prepaintBottom, updater, 0);
+ if (m_didPaint || m_skipsIdlePaint)
+ return;
+ updateTiles(true, prepaintLeft, prepaintTop, prepaintLeft, prepaintBottom, updater, 0);
+ if (m_didPaint || m_skipsIdlePaint)
+ return;
+ updateTiles(true, prepaintRight, prepaintTop, prepaintRight, prepaintBottom, updater, 0);
+ return;
+ }
+
int left, top, right, bottom;
m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom);
- // Prepaint anything that was occluded but inside the layer's visible region.
- prepareToUpdateTiles(true, left, top, right, bottom, occludedScreenSpace);
- if (!m_paintRect.isEmpty() || m_skipsIdlePaint)
+ // Otherwise, prepaint anything that was occluded but inside the layer's visible region.
+ updateTiles(true, left, top, right, bottom, updater, 0);
+ if (m_didPaint || m_skipsIdlePaint)
return;
- // Expand outwards until we find a dirty row or column to update.
- int prepaintLeft, prepaintTop, prepaintRight, prepaintBottom;
- m_tiler->layerRectToTileIndices(idlePaintLayerRect, prepaintLeft, prepaintTop, prepaintRight, prepaintBottom);
+ // Then expand outwards from the visible area until we find a dirty row or column to update.
while (!m_skipsIdlePaint && (left > prepaintLeft || top > prepaintTop || right < prepaintRight || bottom < prepaintBottom)) {
if (bottom < prepaintBottom) {
++bottom;
- prepareToUpdateTiles(true, left, bottom, right, bottom, occludedScreenSpace);
- if (!m_paintRect.isEmpty() || m_skipsIdlePaint)
+ updateTiles(true, left, bottom, right, bottom, updater, 0);
+ if (m_didPaint || m_skipsIdlePaint)
break;
}
if (top > prepaintTop) {
--top;
- prepareToUpdateTiles(true, left, top, right, top, occludedScreenSpace);
- if (!m_paintRect.isEmpty() || m_skipsIdlePaint)
+ updateTiles(true, left, top, right, top, updater, 0);
+ if (m_didPaint || m_skipsIdlePaint)
break;
}
if (left > prepaintLeft) {
--left;
- prepareToUpdateTiles(true, left, top, left, bottom, occludedScreenSpace);
- if (!m_paintRect.isEmpty() || m_skipsIdlePaint)
+ updateTiles(true, left, top, left, bottom, updater, 0);
+ if (m_didPaint || m_skipsIdlePaint)
break;
}
if (right < prepaintRight) {
++right;
- prepareToUpdateTiles(true, right, top, right, bottom, occludedScreenSpace);
- if (!m_paintRect.isEmpty() || m_skipsIdlePaint)
+ updateTiles(true, right, top, right, bottom, updater, 0);
+ if (m_didPaint || m_skipsIdlePaint)
break;
}
}
@@ -654,13 +654,19 @@ bool TiledLayerChromium::needsIdlePaint(const IntRect& layerRect)
if (m_skipsIdlePaint)
return false;
+ if (m_tiler->hasEmptyBounds())
+ return false;
+
IntRect idlePaintLayerRect = idlePaintRect(layerRect);
+ if (idlePaintLayerRect.isEmpty())
+ return false;
int left, top, right, bottom;
m_tiler->layerRectToTileIndices(idlePaintLayerRect, left, top, right, bottom);
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
- if (m_requestedUpdateTilesRect.contains(IntPoint(i, j)))
+ // If the layerRect is empty, then we are painting the outer-most set of tiles only.
+ if (layerRect.isEmpty() && i != left && i != right && j != top && j != bottom)
continue;
UpdatableTile* tile = tileAt(i, j);
if (!tile || !tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat) || tile->isDirty())
@@ -672,6 +678,16 @@ bool TiledLayerChromium::needsIdlePaint(const IntRect& layerRect)
IntRect TiledLayerChromium::idlePaintRect(const IntRect& visibleLayerRect)
{
+ // For layers that are animating transforms but not visible at all, we don't know what part
+ // of them is going to become visible. For small layers we return the entire layer, for larger
+ // ones we avoid prepainting the layer at all.
+ if (visibleLayerRect.isEmpty()) {
+ bool isSmallLayer = m_tiler->numTilesX() <= 9 && m_tiler->numTilesY() <= 9 && m_tiler->numTilesX() * m_tiler->numTilesY() <= 9;
+ if ((drawTransformIsAnimating() || screenSpaceTransformIsAnimating()) && isSmallLayer)
+ return IntRect(IntPoint(), contentBounds());
+ return IntRect();
+ }
+
IntRect prepaintRect = visibleLayerRect;
// FIXME: This can be made a lot larger if we can:
// - reserve memory at a lower priority than for visible content
diff --git a/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h b/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h
index 6ff901dfd..102f532f0 100644
--- a/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h
@@ -33,9 +33,7 @@
#include "cc/CCTiledLayerImpl.h"
namespace WebCore {
-
class LayerTextureUpdater;
-class Region;
class UpdatableTile;
class TiledLayerChromium : public LayerChromium {
@@ -44,29 +42,28 @@ public:
virtual ~TiledLayerChromium();
- virtual void updateCompositorResources(GraphicsContext3D*, CCTextureUpdater&);
- virtual void setIsMask(bool);
+ virtual void setIsMask(bool) OVERRIDE;
- virtual void pushPropertiesTo(CCLayerImpl*);
+ virtual void pushPropertiesTo(CCLayerImpl*) OVERRIDE;
- virtual bool drawsContent() const;
- virtual bool needsContentsScale() const;
+ virtual bool drawsContent() const OVERRIDE;
+ virtual bool needsContentsScale() const OVERRIDE;
- virtual IntSize contentBounds() const;
+ virtual IntSize contentBounds() const OVERRIDE;
- virtual void setNeedsDisplayRect(const FloatRect&);
+ virtual void setNeedsDisplayRect(const FloatRect&) OVERRIDE;
- virtual void setIsNonCompositedContent(bool);
+ virtual void setIsNonCompositedContent(bool) OVERRIDE;
- virtual void setLayerTreeHost(CCLayerTreeHost*);
+ virtual void setLayerTreeHost(CCLayerTreeHost*) OVERRIDE;
// Reserves all existing and valid tile textures to protect them from being
// recycled by the texture manager.
void protectTileTextures(const IntRect& layerRect);
- virtual void reserveTextures();
+ virtual void reserveTextures() OVERRIDE;
- virtual Region opaqueContentsRegion() const;
+ virtual Region visibleContentOpaqueRegion() const OVERRIDE;
protected:
TiledLayerChromium();
@@ -79,6 +76,7 @@ protected:
void setTextureFormat(GC3Denum textureFormat) { m_textureFormat = textureFormat; }
void setBorderTexelOption(CCLayerTilingData::BorderTexelOption);
void setSampledTexelFormat(LayerTextureUpdater::SampledTexelFormat sampledTexelFormat) { m_sampledTexelFormat = sampledTexelFormat; }
+ size_t numPaintedTiles() { return m_tiler->tiles().size(); }
virtual LayerTextureUpdater* textureUpdater() const = 0;
virtual void createTextureUpdaterIfNeeded() = 0;
@@ -90,22 +88,25 @@ protected:
void resetUpdateState();
// Prepare data needed to update textures that intersect with layerRect.
- void prepareToUpdate(const IntRect& layerRect, const Region& occludedTargetSpace);
+ void updateLayerRect(CCTextureUpdater&, const IntRect& layerRect, const CCOcclusionTracker*);
// Same as above, but this will try to paint additional surrounding content if idle.
- void prepareToUpdateIdle(const IntRect& layerRect, const Region& occludedTargetSpace);
+ void idleUpdateLayerRect(CCTextureUpdater&, const IntRect& layerRect, const CCOcclusionTracker*);
// After preparing an update, returns true if more pre-painting is needed.
bool needsIdlePaint(const IntRect& layerRect);
+ IntRect idlePaintRect(const IntRect& visibleLayerRect);
+
bool skipsDraw() const { return m_skipsDraw; }
- virtual void protectVisibleTileTextures();
+ virtual void protectVisibleTileTextures() OVERRIDE;
+ // Virtual for testing
virtual TextureManager* textureManager() const;
private:
- virtual PassOwnPtr<CCLayerImpl> createCCLayerImpl();
+ virtual PassOwnPtr<CCLayerImpl> createCCLayerImpl() OVERRIDE;
void createTilerIfNeeded();
void setTilingOption(TilingOption);
@@ -113,24 +114,19 @@ private:
bool tileOnlyNeedsPartialUpdate(UpdatableTile*);
bool tileNeedsBufferedUpdate(UpdatableTile*);
- void prepareToUpdateTiles(bool idle, int left, int top, int right, int bottom, const Region& occludedTargetSpace);
- IntRect idlePaintRect(const IntRect& visibleLayerRect);
+ void updateTiles(bool idle, int left, int top, int right, int bottom, CCTextureUpdater&, const CCOcclusionTracker*);
UpdatableTile* tileAt(int, int) const;
UpdatableTile* createTile(int, int);
- // Temporary state held between prepareToUpdate() and updateCompositorResources().
- IntRect m_requestedUpdateTilesRect;
-
- // State held between prepareToUpdate() and pushPropertiesTo(). This represents the area
- // of the layer that is actually re-painted by WebKit.
- IntRect m_paintRect;
-
GC3Denum m_textureFormat;
bool m_skipsDraw;
bool m_skipsIdlePaint;
LayerTextureUpdater::SampledTexelFormat m_sampledTexelFormat;
+ // Tracks if we've done any painting on this update cycle.
+ bool m_didPaint;
+
TilingOption m_tilingOption;
OwnPtr<CCLayerTilingData> m_tiler;
};
diff --git a/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp b/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp
index 432ca78bd..28b1b8e68 100644
--- a/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp
@@ -210,11 +210,19 @@ void TransparencyWin::computeLayerSize()
// uses the variable: to determine how to translate things to account
// for the offset of the layer.
m_transformedSourceRect = m_sourceRect;
- m_layerSize = IntSize(m_sourceRect.width(), m_sourceRect.height());
- } else {
+ } else if (m_transformMode == KeepTransform && m_layerMode != TextComposite) {
+ // FIXME: support clipping for other modes
+ IntRect clippedSourceRect = m_sourceRect;
+ SkRect clipBounds;
+ if (m_destContext->platformContext()->canvas()->getClipBounds(&clipBounds)) {
+ FloatRect clipRect(clipBounds.left(), clipBounds.top(), clipBounds.width(), clipBounds.height());
+ clippedSourceRect.intersect(enclosingIntRect(clipRect));
+ }
+ m_transformedSourceRect = m_orgTransform.mapRect(clippedSourceRect);
+ } else
m_transformedSourceRect = m_orgTransform.mapRect(m_sourceRect);
- m_layerSize = IntSize(m_transformedSourceRect.width(), m_transformedSourceRect.height());
- }
+
+ m_layerSize = IntSize(m_transformedSourceRect.width(), m_transformedSourceRect.height());
}
void TransparencyWin::setupLayer()
diff --git a/Source/WebCore/platform/graphics/chromium/TransparencyWin.h b/Source/WebCore/platform/graphics/chromium/TransparencyWin.h
index 535cbaa75..14f97b156 100644
--- a/Source/WebCore/platform/graphics/chromium/TransparencyWin.h
+++ b/Source/WebCore/platform/graphics/chromium/TransparencyWin.h
@@ -35,8 +35,9 @@
#include "AffineTransform.h"
#include "ImageBuffer.h"
-#include "Noncopyable.h"
-#include "wtf/OwnPtr.h"
+
+#include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
class SkBitmap;
class SkCanvas;
diff --git a/Source/WebCore/platform/graphics/chromium/TreeSynchronizer.cpp b/Source/WebCore/platform/graphics/chromium/TreeSynchronizer.cpp
index 07f04b372..974513ff1 100644
--- a/Source/WebCore/platform/graphics/chromium/TreeSynchronizer.cpp
+++ b/Source/WebCore/platform/graphics/chromium/TreeSynchronizer.cpp
@@ -99,6 +99,9 @@ PassOwnPtr<CCLayerImpl> TreeSynchronizer::synchronizeTreeRecursive(RawPtrCCLayer
void TreeSynchronizer::updateScrollbarLayerPointersRecursive(const RawPtrCCLayerImplMap& newLayers, LayerChromium* layer)
{
+ if (!layer)
+ return;
+
const Vector<RefPtr<LayerChromium> >& children = layer->children();
for (size_t i = 0; i < children.size(); ++i)
updateScrollbarLayerPointersRecursive(newLayers, children[i].get());
diff --git a/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp b/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
index 51b0c695f..fa8ec9467 100644
--- a/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
+++ b/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
@@ -217,7 +217,18 @@ void UniscribeHelper::justify(int additionalSpace)
// The documentation for Scriptjustify is wrong, the parameter is the space
// to add and not the width of the column you want.
- const int minKashida = 1; // How do we decide what this should be?
+ int minKashida;
+#if USE(SKIA_TEXT)
+ // Disable kashida justification based on
+ // http://blogs.msdn.com/b/michkap/archive/2010/08/31/10056140.aspx.
+ for (int i = 0; i < totalGlyphs; ++i) {
+ if (visualAttributes[i].uJustification == SCRIPT_JUSTIFY_ARABIC_KASHIDA)
+ visualAttributes[i].uJustification = SCRIPT_JUSTIFY_NONE;
+ }
+ minKashida = 0;
+#else
+ minKashida = 1; // How do we decide what this should be?
+#endif
ScriptJustify(&visualAttributes[0], &advances[0], totalGlyphs,
additionalSpace, minKashida, &justify[0]);
@@ -541,7 +552,7 @@ void UniscribeHelper::fillRuns()
0, // fNeutralOverride :1;
0, // fNumericOverride :1;
0, // fLegacyBidiClass :1;
- 1, // fMergeNeutralItems :1;
+ 0, // fMergeNeutralItems :1;
0};// fReserved :7;
// Calling ScriptApplyDigitSubstitution( 0, &inputControl, &inputState)
// here would be appropriate if we wanted to set the language ID, and get
@@ -575,6 +586,24 @@ void UniscribeHelper::fillRuns()
&inputControl, &inputState,
&m_runs[0], &m_scriptTags[0],
&numberOfItems);
+
+ if (SUCCEEDED(hr)) {
+ // Pack consecutive runs, the script tag of which are
+ // SCRIPT_TAG_UNKNOWN, to reduce the number of runs.
+ for (int i = 0; i < numberOfItems; ++i) {
+ if (m_scriptTags[i] == SCRIPT_TAG_UNKNOWN) {
+ int j = 1;
+ while (i + j < numberOfItems && m_scriptTags[i + j] == SCRIPT_TAG_UNKNOWN)
+ ++j;
+ if (--j) {
+ m_runs.remove(i + 1, j);
+ m_scriptTags.remove(i + 1, j);
+ numberOfItems -= j;
+ }
+ }
+ }
+ m_scriptTags.resize(numberOfItems);
+ }
} else {
hr = ScriptItemize(m_input, m_inputLength,
static_cast<int>(m_runs.size()) - 1,
@@ -892,6 +921,8 @@ void UniscribeHelper::adjustSpaceAdvances()
int glyphIndex = shaping.m_logs[i];
int currentAdvance = shaping.m_advance[glyphIndex];
+ shaping.m_glyphs[glyphIndex] = shaping.m_spaceGlyph;
+
if (treatAsSpace) {
// currentAdvance does not include additional letter-spacing,
// but m_spaceWidth does. Here we find out how off we are from
@@ -913,7 +944,6 @@ void UniscribeHelper::adjustSpaceAdvances()
shaping.m_abc.abcB -= currentAdvance;
shaping.m_offsets[glyphIndex].du = 0;
shaping.m_offsets[glyphIndex].dv = 0;
- shaping.m_glyphs[glyphIndex] = shaping.m_spaceGlyph;
}
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
index e6911981e..e70c9ebc6 100644
--- a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
@@ -36,12 +36,12 @@
namespace WebCore {
-PassRefPtr<VideoLayerChromium> VideoLayerChromium::create(VideoFrameProvider* provider)
+PassRefPtr<VideoLayerChromium> VideoLayerChromium::create(WebKit::WebVideoFrameProvider* provider)
{
return adoptRef(new VideoLayerChromium(provider));
}
-VideoLayerChromium::VideoLayerChromium(VideoFrameProvider* provider)
+VideoLayerChromium::VideoLayerChromium(WebKit::WebVideoFrameProvider* provider)
: LayerChromium()
, m_provider(provider)
{
diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h
index 1f2e92012..dc4559cf8 100644
--- a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h
@@ -36,25 +36,28 @@
#include "LayerChromium.h"
+namespace WebKit {
+class WebVideoFrameProvider;
+}
+
namespace WebCore {
class CCVideoLayerImpl;
-class VideoFrameProvider;
// A Layer that contains a Video element.
class VideoLayerChromium : public LayerChromium {
public:
- static PassRefPtr<VideoLayerChromium> create(VideoFrameProvider* = 0);
+ static PassRefPtr<VideoLayerChromium> create(WebKit::WebVideoFrameProvider*);
virtual ~VideoLayerChromium();
- virtual PassOwnPtr<CCLayerImpl> createCCLayerImpl();
+ virtual PassOwnPtr<CCLayerImpl> createCCLayerImpl() OVERRIDE;
private:
- explicit VideoLayerChromium(VideoFrameProvider*);
+ explicit VideoLayerChromium(WebKit::WebVideoFrameProvider*);
// This pointer is only for passing to CCVideoLayerImpl's constructor. It should never be dereferenced by this class.
- VideoFrameProvider* m_provider;
+ WebKit::WebVideoFrameProvider* m_provider;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
deleted file mode 100644
index e3e19e258..000000000
--- a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * 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:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "WebGLLayerChromium.h"
-
-#include "DrawingBuffer.h"
-#include "Extensions3DChromium.h"
-#include "GraphicsContext3D.h"
-#include "LayerRendererChromium.h"
-#include "TraceEvent.h"
-
-namespace WebCore {
-
-PassRefPtr<WebGLLayerChromium> WebGLLayerChromium::create()
-{
- return adoptRef(new WebGLLayerChromium());
-}
-
-WebGLLayerChromium::WebGLLayerChromium()
- : CanvasLayerChromium()
- , m_hasAlpha(true)
- , m_premultipliedAlpha(true)
- , m_textureId(0)
- , m_textureChanged(true)
- , m_textureUpdated(false)
- , m_contextLost(false)
- , m_drawingBuffer(0)
-{
-}
-
-WebGLLayerChromium::~WebGLLayerChromium()
-{
- if (context() && layerTreeHost())
- layerTreeHost()->stopRateLimiter(context());
-}
-
-bool WebGLLayerChromium::drawsContent() const
-{
- return LayerChromium::drawsContent() && !m_contextLost;
-}
-
-void WebGLLayerChromium::paintContentsIfDirty(const Region&)
-{
- if (!drawsContent() || !m_needsDisplay || !m_textureUpdated)
- return;
-
- drawingBuffer()->publishToPlatformLayer();
- context()->markLayerComposited();
- m_needsDisplay = false;
- m_textureUpdated = false;
- m_contextLost = context()->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR;
-}
-
-void WebGLLayerChromium::updateCompositorResources(GraphicsContext3D* rendererContext, CCTextureUpdater&)
-{
- if (m_textureChanged) {
- rendererContext->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId);
- // Set the min-mag filters to linear and wrap modes to GL_CLAMP_TO_EDGE
- // to get around NPOT texture limitations of GLES.
- rendererContext->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
- rendererContext->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
- rendererContext->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
- rendererContext->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
- m_textureChanged = false;
- }
-}
-
-void WebGLLayerChromium::pushPropertiesTo(CCLayerImpl* layer)
-{
- CanvasLayerChromium::pushPropertiesTo(layer);
-
- CCCanvasLayerImpl* canvasLayer = static_cast<CCCanvasLayerImpl*>(layer);
- canvasLayer->setTextureId(m_textureId);
- canvasLayer->setHasAlpha(m_hasAlpha);
- canvasLayer->setPremultipliedAlpha(m_premultipliedAlpha);
-}
-
-bool WebGLLayerChromium::paintRenderedResultsToCanvas(ImageBuffer* imageBuffer)
-{
- if (m_textureUpdated || !m_drawingBuffer || !drawsContent())
- return false;
-
- IntSize framebufferSize = context()->getInternalFramebufferSize();
-
- // Since we're using the same context as WebGL, we have to restore any state we change (in this case, just the framebuffer binding).
- // FIXME: The WebGLRenderingContext tracks the current framebuffer binding, it would be slightly more efficient to use this value
- // rather than querying it off of the context.
- GC3Dint previousFramebuffer = 0;
- context()->getIntegerv(GraphicsContext3D::FRAMEBUFFER_BINDING, &previousFramebuffer);
-
- Platform3DObject framebuffer = context()->createFramebuffer();
- context()->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, framebuffer);
- context()->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_textureId, 0);
-
- Extensions3DChromium* extensions = static_cast<Extensions3DChromium*>(context()->getExtensions());
- extensions->paintFramebufferToCanvas(framebuffer, framebufferSize.width(), framebufferSize.height(), !context()->getContextAttributes().premultipliedAlpha, imageBuffer);
- context()->deleteFramebuffer(framebuffer);
-
- context()->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, previousFramebuffer);
- return true;
-}
-
-void WebGLLayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect)
-{
- LayerChromium::setNeedsDisplayRect(dirtyRect);
-
- m_textureUpdated = true;
-
- // If WebGL commands are issued outside of a the animation callbacks, then use
- // call rateLimitOffscreenContextCHROMIUM() to keep the context from getting too far ahead.
- if (layerTreeHost())
- layerTreeHost()->startRateLimiter(context());
-}
-
-void WebGLLayerChromium::setDrawingBuffer(DrawingBuffer* drawingBuffer)
-{
- bool drawingBufferChanged = (m_drawingBuffer != drawingBuffer);
-
- // The GraphicsContext3D used by the layer is the context associated with
- // the drawing buffer. If the drawing buffer is changing, make sure
- // to stop the rate limiter on the old context, not the new context from the
- // new drawing buffer.
- GraphicsContext3D* context3D = context();
- if (layerTreeHost() && drawingBufferChanged && context3D)
- layerTreeHost()->stopRateLimiter(context3D);
-
- m_drawingBuffer = drawingBuffer;
- if (!m_drawingBuffer)
- return;
-
- unsigned int textureId = m_drawingBuffer->platformColorBuffer();
- if (textureId != m_textureId || drawingBufferChanged) {
- m_textureChanged = true;
- m_textureUpdated = true;
- }
- m_textureId = textureId;
- GraphicsContext3D::Attributes attributes = context()->getContextAttributes();
- m_hasAlpha = attributes.alpha;
- m_premultipliedAlpha = attributes.premultipliedAlpha;
- m_contextLost = context()->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR;
-}
-
-GraphicsContext3D* WebGLLayerChromium::context() const
-{
- if (drawingBuffer())
- return drawingBuffer()->graphicsContext3D().get();
-
- return 0;
-}
-
-}
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
deleted file mode 100644
index af138fa1e..000000000
--- a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef WebGLLayerChromium_h
-#define WebGLLayerChromium_h
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "CanvasLayerChromium.h"
-#include "DrawingBuffer.h"
-
-namespace WebCore {
-
-class GraphicsContext3D;
-class WebGLLayerChromiumRateLimitTask;
-
-// A Layer containing a WebGL canvas
-class WebGLLayerChromium : public CanvasLayerChromium {
-public:
- static PassRefPtr<WebGLLayerChromium> create();
-
- virtual ~WebGLLayerChromium();
-
- unsigned textureId() const { return m_textureId; }
- void setTextureId(unsigned textureId) { m_textureId = textureId; }
-
- virtual bool drawsContent() const;
- virtual void paintContentsIfDirty(const Region&);
- virtual void updateCompositorResources(GraphicsContext3D*, CCTextureUpdater&);
- virtual void pushPropertiesTo(CCLayerImpl*);
- virtual void setNeedsDisplayRect(const FloatRect&);
- bool paintRenderedResultsToCanvas(ImageBuffer*);
-
- GraphicsContext3D* context() const;
-
- void setDrawingBuffer(DrawingBuffer*);
- DrawingBuffer* drawingBuffer() const { return m_drawingBuffer; }
-private:
- WebGLLayerChromium();
- friend class WebGLLayerChromiumRateLimitTask;
-
- bool m_hasAlpha;
- bool m_premultipliedAlpha;
- unsigned m_textureId;
- bool m_textureChanged;
- bool m_textureUpdated;
- bool m_contextLost;
-
- // The DrawingBuffer holding the WebGL contents for this layer.
- // A reference is not held here, because the DrawingBuffer already holds
- // a reference to the WebGLLayerChromium.
- DrawingBuffer* m_drawingBuffer;
-};
-
-}
-#endif // USE(ACCELERATED_COMPOSITING)
-
-#endif
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.cpp
index 8c0303ed6..ccffdbc72 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.cpp
@@ -45,6 +45,9 @@ CCActiveAnimation::CCActiveAnimation(PassOwnPtr<CCAnimationCurve> curve, int ani
, m_runState(WaitingForTargetAvailability)
, m_iterations(1)
, m_startTime(0)
+ , m_timeOffset(0)
+ , m_needsSynchronizedStartTime(false)
+ , m_suspended(false)
, m_pauseTime(0)
, m_totalPausedTime(0)
{
@@ -54,46 +57,49 @@ CCActiveAnimation::~CCActiveAnimation()
{
}
-void CCActiveAnimation::setRunState(RunState runState, double now)
+void CCActiveAnimation::setRunState(RunState runState, double monotonicTime)
{
+ if (m_suspended)
+ return;
+
if (runState == Running && m_runState == Paused)
- m_totalPausedTime += now - m_pauseTime;
+ m_totalPausedTime += monotonicTime - m_pauseTime;
else if (runState == Paused)
- m_pauseTime = now;
+ m_pauseTime = monotonicTime;
m_runState = runState;
}
-bool CCActiveAnimation::isFinishedAt(double time) const
+void CCActiveAnimation::suspend(double monotonicTime)
{
- if (m_runState == Finished || m_runState == Aborted)
- return true;
-
- return m_runState == Running
- && m_iterations >= 0
- && m_iterations * m_curve->duration() <= time - startTime() - m_totalPausedTime;
+ setRunState(Paused, monotonicTime);
+ m_suspended = true;
}
-bool CCActiveAnimation::isWaiting() const
+void CCActiveAnimation::resume(double monotonicTime)
{
- return m_runState == WaitingForNextTick
- || m_runState == WaitingForTargetAvailability
- || m_runState == WaitingForStartTime;
+ m_suspended = false;
+ setRunState(Running, monotonicTime);
}
-bool CCActiveAnimation::isRunningOrHasRun() const
+bool CCActiveAnimation::isFinishedAt(double monotonicTime) const
{
+ if (m_runState == Finished || m_runState == Aborted)
+ return true;
+
+ if (m_needsSynchronizedStartTime)
+ return false;
+
return m_runState == Running
- || m_runState == Finished
- || m_runState == Aborted
- || m_runState == Paused;
+ && m_iterations >= 0
+ && m_iterations * m_curve->duration() <= monotonicTime - startTime() - m_totalPausedTime;
}
-double CCActiveAnimation::trimTimeToCurrentIteration(double now) const
+double CCActiveAnimation::trimTimeToCurrentIteration(double monotonicTime) const
{
- double trimmed = now;
+ double trimmed = monotonicTime + m_timeOffset;
// If we're paused, time is 'stuck' at the pause time.
- if (m_runState == Paused && trimmed > m_pauseTime)
+ if (m_runState == Paused)
trimmed = m_pauseTime;
// Returned time should always be relative to the start time and should subtract
@@ -128,28 +134,18 @@ PassOwnPtr<CCActiveAnimation> CCActiveAnimation::cloneForImplThread() const
toReturn->m_startTime = m_startTime;
toReturn->m_pauseTime = m_pauseTime;
toReturn->m_totalPausedTime = m_totalPausedTime;
+ toReturn->m_timeOffset = m_timeOffset;
return toReturn.release();
}
-void CCActiveAnimation::synchronizeProperties(CCActiveAnimation* other)
+void CCActiveAnimation::pushPropertiesTo(CCActiveAnimation* other) const
{
- // It is possible for the impl thread to initiate a run state change.
- // This happens when the animation was waiting for a future event to take
- // place, and the event has happened. In that case, we want 'this' to
- // assume the impl thread's run state and start time.
- if (isWaiting() && other->isRunningOrHasRun()) {
- m_runState = other->m_runState;
- m_startTime = other->m_startTime;
- } else {
+ // Currently, we only push changes due to pausing and resuming animations on the main thread.
+ if (m_runState == CCActiveAnimation::Paused || other->m_runState == CCActiveAnimation::Paused) {
other->m_runState = m_runState;
- other->m_startTime = m_startTime;
+ other->m_pauseTime = m_pauseTime;
+ other->m_totalPausedTime = m_totalPausedTime;
}
-
- // Change in state related to iterations and pause is always initiated from
- // the main thread, so it is safe to push properties in that direction.
- other->m_iterations = m_iterations;
- other->m_pauseTime = m_pauseTime;
- other->m_totalPausedTime = m_totalPausedTime;
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.h b/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.h
index 2093421a7..531eb464f 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.h
@@ -63,14 +63,6 @@ public:
Opacity
};
- struct AnimationSignature {
- AnimationSignature(int groupId, TargetProperty targetProperty)
- : groupId(groupId)
- , targetProperty(targetProperty) { }
- int groupId;
- TargetProperty targetProperty;
- };
-
static PassOwnPtr<CCActiveAnimation> create(PassOwnPtr<CCAnimationCurve>, int animationId, int groupId, TargetProperty);
virtual ~CCActiveAnimation();
@@ -80,7 +72,7 @@ public:
TargetProperty targetProperty() const { return m_targetProperty; }
RunState runState() const { return m_runState; }
- void setRunState(RunState, double now);
+ void setRunState(RunState, double monotonicTime);
// This is the number of times that the animation will play. If this
// value is zero the animation will not play. If it is negative, then
@@ -89,26 +81,33 @@ public:
void setIterations(int n) { m_iterations = n; }
double startTime() const { return m_startTime; }
- void setStartTime(double startTime) { m_startTime = startTime; }
+ void setStartTime(double monotonicTime) { m_startTime = monotonicTime; }
+ bool hasSetStartTime() const { return m_startTime; }
- bool isFinishedAt(double time) const;
- bool isFinished() const { return m_runState == Finished || m_runState == Aborted; }
+ double timeOffset() const { return m_timeOffset; }
+ void setTimeOffset(double monotonicTime) { m_timeOffset = monotonicTime; }
- bool isWaiting() const;
- bool isRunningOrHasRun() const;
+ void suspend(double monotonicTime);
+ void resume(double monotonicTime);
+
+ bool isFinishedAt(double monotonicTime) const;
+ bool isFinished() const { return m_runState == Finished || m_runState == Aborted; }
CCAnimationCurve* curve() { return m_curve.get(); }
const CCAnimationCurve* curve() const { return m_curve.get(); }
+ // If this is true, even if the animation is running, it will not be tickable until
+ // it is given a start time. This is true for animations running on the main thread.
+ bool needsSynchronizedStartTime() const { return m_needsSynchronizedStartTime; }
+ void setNeedsSynchronizedStartTime(bool needsSynchronizedStartTime) { m_needsSynchronizedStartTime = needsSynchronizedStartTime; }
+
// Takes the given absolute time, and using the start time and the number
// of iterations, returns the relative time in the current iteration.
- double trimTimeToCurrentIteration(double now) const;
-
- AnimationSignature signature() const { return AnimationSignature(m_group, m_targetProperty); }
+ double trimTimeToCurrentIteration(double monotonicTime) const;
PassOwnPtr<CCActiveAnimation> cloneForImplThread() const;
- void synchronizeProperties(CCActiveAnimation*);
+ void pushPropertiesTo(CCActiveAnimation*) const;
private:
CCActiveAnimation(PassOwnPtr<CCAnimationCurve>, int animationId, int groupId, TargetProperty);
@@ -130,6 +129,17 @@ private:
int m_iterations;
double m_startTime;
+ // The time offset effectively pushes the start of the animation back in time. This is
+ // used for resuming paused animations -- an animation is added with a non-zero time
+ // offset, causing the animation to skip ahead to the desired point in time.
+ double m_timeOffset;
+
+ bool m_needsSynchronizedStartTime;
+
+ // When an animation is suspended, it behaves as if it is paused and it also ignores
+ // all run state changes until it is resumed. This is used for testing purposes.
+ bool m_suspended;
+
// These are used in trimTimeToCurrentIteration to account for time
// spent while paused. This is not included in AnimationState since it
// there is absolutely no need for clients of this controller to know
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCActiveGestureAnimation.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCActiveGestureAnimation.cpp
index 556e46b4e..50f4ad8a6 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCActiveGestureAnimation.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCActiveGestureAnimation.cpp
@@ -26,30 +26,39 @@
#include "cc/CCActiveGestureAnimation.h"
+#include "TraceEvent.h"
#include "cc/CCGestureCurve.h"
namespace WebCore {
-PassOwnPtr<CCActiveGestureAnimation> CCActiveGestureAnimation::create(double startTime, PassOwnPtr<CCGestureCurve> curve, CCGestureCurveTarget* target)
+PassOwnPtr<CCActiveGestureAnimation> CCActiveGestureAnimation::create(PassOwnPtr<CCGestureCurve> curve, CCGestureCurveTarget* target)
{
- return adoptPtr(new CCActiveGestureAnimation(startTime, curve, target));
+ return adoptPtr(new CCActiveGestureAnimation(curve, target));
}
-CCActiveGestureAnimation::CCActiveGestureAnimation(double startTime, PassOwnPtr<CCGestureCurve> curve, CCGestureCurveTarget* target)
- : m_startTime(startTime)
+CCActiveGestureAnimation::CCActiveGestureAnimation(PassOwnPtr<CCGestureCurve> curve, CCGestureCurveTarget* target)
+ : m_startTime(0)
+ , m_waitingForFirstTick(true)
, m_gestureCurve(curve)
, m_gestureCurveTarget(target)
{
+ TRACE_EVENT_ASYNC_BEGIN1("input", "GestureAnimation", this, "curve", m_gestureCurve->debugName());
}
CCActiveGestureAnimation::~CCActiveGestureAnimation()
{
+ TRACE_EVENT_ASYNC_END0("input", "GestureAnimation", this);
}
-bool CCActiveGestureAnimation::animate(double time)
+bool CCActiveGestureAnimation::animate(double monotonicTime)
{
+ if (m_waitingForFirstTick) {
+ m_startTime = monotonicTime;
+ m_waitingForFirstTick = false;
+ }
+
// CCGestureCurves used zero-based time, so subtract start-time.
- return m_gestureCurve->apply(time - m_startTime, m_gestureCurveTarget);
+ return m_gestureCurve->apply(monotonicTime - m_startTime, m_gestureCurveTarget);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCActiveGestureAnimation.h b/Source/WebCore/platform/graphics/chromium/cc/CCActiveGestureAnimation.h
index c71b225df..000ed424b 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCActiveGestureAnimation.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCActiveGestureAnimation.h
@@ -37,15 +37,16 @@ class CCGestureCurveTarget;
class CCActiveGestureAnimation {
WTF_MAKE_NONCOPYABLE(CCActiveGestureAnimation);
public:
- static PassOwnPtr<CCActiveGestureAnimation> create(double startTime, PassOwnPtr<CCGestureCurve>, CCGestureCurveTarget*);
+ static PassOwnPtr<CCActiveGestureAnimation> create(PassOwnPtr<CCGestureCurve>, CCGestureCurveTarget*);
~CCActiveGestureAnimation();
- bool animate(double time);
+ bool animate(double monotonicTime);
private:
- CCActiveGestureAnimation(double startTime, PassOwnPtr<CCGestureCurve>, CCGestureCurveTarget*);
+ CCActiveGestureAnimation(PassOwnPtr<CCGestureCurve>, CCGestureCurveTarget*);
double m_startTime;
+ double m_waitingForFirstTick;
OwnPtr<CCGestureCurve> m_gestureCurve;
CCGestureCurveTarget* m_gestureCurveTarget;
};
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.cpp
deleted file mode 100644
index 9f41844ca..000000000
--- a/Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include "cc/CCAnimationEvents.h"
-
-#include <wtf/OwnPtr.h>
-
-namespace WebCore {
-
-CCAnimationEvent::CCAnimationEvent(int layerId)
- : m_layerId(layerId)
-{
-}
-
-CCAnimationEvent::~CCAnimationEvent()
-{
-}
-
-const CCAnimationStartedEvent* CCAnimationEvent::toAnimationStartedEvent() const
-{
- ASSERT(type() == Started);
- return static_cast<const CCAnimationStartedEvent*>(this);
-}
-
-const CCAnimationFinishedEvent* CCAnimationEvent::toAnimationFinishedEvent() const
-{
- ASSERT(type() == Finished);
- return static_cast<const CCAnimationFinishedEvent*>(this);
-}
-
-PassOwnPtr<CCAnimationStartedEvent> CCAnimationStartedEvent::create(int layerId)
-{
- return adoptPtr(new CCAnimationStartedEvent(layerId));
-}
-
-CCAnimationStartedEvent::CCAnimationStartedEvent(int layerId)
- : CCAnimationEvent(layerId)
-{
-}
-
-CCAnimationStartedEvent::~CCAnimationStartedEvent()
-{
-}
-
-CCAnimationEvent::Type CCAnimationStartedEvent::type() const
-{
- return Started;
-}
-
-PassOwnPtr<CCAnimationFinishedEvent> CCAnimationFinishedEvent::create(int layerId, int animationId)
-{
- return adoptPtr(new CCAnimationFinishedEvent(layerId, animationId));
-}
-
-CCAnimationFinishedEvent::CCAnimationFinishedEvent(int layerId, int animationId)
- : CCAnimationEvent(layerId)
- , m_animationId(animationId)
-{
-}
-
-CCAnimationFinishedEvent::~CCAnimationFinishedEvent()
-{
-}
-
-CCAnimationEvent::Type CCAnimationFinishedEvent::type() const
-{
- return Finished;
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.h b/Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.h
index da94e1e27..ef8011736 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.h
@@ -25,65 +25,33 @@
#ifndef CCAnimationEvents_h
#define CCAnimationEvents_h
+#include "cc/CCActiveAnimation.h"
+
#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>
namespace WebCore {
-class CCAnimationStartedEvent;
-class CCAnimationFinishedEvent;
-
-class CCAnimationEvent {
-public:
+struct CCAnimationEvent {
enum Type { Started, Finished };
- virtual ~CCAnimationEvent();
-
- virtual Type type() const = 0;
-
- int layerId() const { return m_layerId; }
-
- const CCAnimationStartedEvent* toAnimationStartedEvent() const;
- const CCAnimationFinishedEvent* toAnimationFinishedEvent() const;
-
-protected:
- CCAnimationEvent(int layerId);
-
-private:
- int m_layerId;
-};
-
-// Indicates that an animation has started on a particular layer.
-class CCAnimationStartedEvent : public CCAnimationEvent {
-public:
- static PassOwnPtr<CCAnimationStartedEvent> create(int layerId);
-
- virtual ~CCAnimationStartedEvent();
-
- virtual Type type() const;
-
-private:
- explicit CCAnimationStartedEvent(int layerId);
-};
-
-// Indicates that an animation has started on a particular layer.
-class CCAnimationFinishedEvent : public CCAnimationEvent {
-public:
- static PassOwnPtr<CCAnimationFinishedEvent> create(int layerId, int animationId);
-
- virtual ~CCAnimationFinishedEvent();
-
- virtual Type type() const;
-
- int animationId() const { return m_animationId; }
-
-private:
- CCAnimationFinishedEvent(int layerId, int animationId);
-
- int m_animationId;
+ CCAnimationEvent(Type type, int layerId, int groupId, CCActiveAnimation::TargetProperty targetProperty, double monotonicTime)
+ : type(type)
+ , layerId(layerId)
+ , groupId(groupId)
+ , targetProperty(targetProperty)
+ , monotonicTime(monotonicTime)
+ {
+ }
+
+ Type type;
+ int layerId;
+ int groupId;
+ CCActiveAnimation::TargetProperty targetProperty;
+ double monotonicTime;
};
-typedef Vector<OwnPtr<CCAnimationEvent> > CCAnimationEventsVector;
+typedef Vector<CCAnimationEvent> CCAnimationEventsVector;
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCheckerboardDrawQuad.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCCheckerboardDrawQuad.cpp
new file mode 100644
index 000000000..aae033514
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCCheckerboardDrawQuad.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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"
+
+#include "cc/CCCheckerboardDrawQuad.h"
+
+namespace WebCore {
+
+PassOwnPtr<CCCheckerboardDrawQuad> CCCheckerboardDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect)
+{
+ return adoptPtr(new CCCheckerboardDrawQuad(sharedQuadState, quadRect));
+}
+
+CCCheckerboardDrawQuad::CCCheckerboardDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect)
+ : CCDrawQuad(sharedQuadState, CCDrawQuad::Checkerboard, quadRect)
+{
+}
+
+}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCheckerboardDrawQuad.h b/Source/WebCore/platform/graphics/chromium/cc/CCCheckerboardDrawQuad.h
new file mode 100644
index 000000000..27f8c56bd
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCCheckerboardDrawQuad.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 CCCheckerboardDrawQuad_h
+#define CCCheckerboardDrawQuad_h
+
+#include "cc/CCDrawQuad.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class CCCheckerboardDrawQuad : public CCDrawQuad {
+ WTF_MAKE_NONCOPYABLE(CCCheckerboardDrawQuad);
+public:
+ static PassOwnPtr<CCCheckerboardDrawQuad> create(const CCSharedQuadState*, const IntRect&);
+
+private:
+ CCCheckerboardDrawQuad(const CCSharedQuadState*, const IntRect&);
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp
index 6a062caca..94bbc1dc5 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp
@@ -34,8 +34,10 @@
#include "cc/CCDamageTracker.h"
+#include "FilterOperations.h"
#include "cc/CCLayerImpl.h"
#include "cc/CCLayerTreeHostCommon.h"
+#include "cc/CCMathUtil.h"
#include "cc/CCRenderSurface.h"
namespace WebCore {
@@ -56,7 +58,24 @@ CCDamageTracker::~CCDamageTracker()
{
}
-void CCDamageTracker::updateDamageTrackingState(const Vector<CCLayerImpl*>& layerList, int targetSurfaceLayerID, CCLayerImpl* targetSurfaceMaskLayer)
+static inline void expandDamageRectWithFilters(FloatRect& damageRect, const FilterOperations& filters)
+{
+ int top, right, bottom, left;
+ filters.getOutsets(top, right, bottom, left);
+ damageRect.move(-left, -top);
+ damageRect.expand(left + right, top + bottom);
+}
+
+static inline void expandDamageRectInsideRectWithFilters(FloatRect& damageRect, const FloatRect& filterRect, const FilterOperations& filters)
+{
+ FloatRect expandedDamageRect = damageRect;
+ expandDamageRectWithFilters(expandedDamageRect, filters);
+ expandedDamageRect.intersect(filterRect);
+
+ damageRect.unite(expandedDamageRect);
+}
+
+void CCDamageTracker::updateDamageTrackingState(const Vector<CCLayerImpl*>& layerList, int targetSurfaceLayerID, bool targetSurfacePropertyChangedOnlyFromDescendant, const IntRect& targetSurfaceContentRect, CCLayerImpl* targetSurfaceMaskLayer, const FilterOperations& filters)
{
//
// This function computes the "damage rect" of a target surface, and updates the state
@@ -71,20 +90,20 @@ void CCDamageTracker::updateDamageTrackingState(const Vector<CCLayerImpl*>& laye
//
// The basic algorithm for computing the damage region is as follows:
//
- // // 1. compute damage caused by changes in active/new layers
+ // 1. compute damage caused by changes in active/new layers
// for each layer in the layerList:
// if the layer is actually a renderSurface:
// add the surface's damage to our target surface.
// else
// add the layer's damage to the target surface.
//
- // // 2. compute damage caused by the target surface's mask, if it exists.
+ // 2. compute damage caused by the target surface's mask, if it exists.
//
- // // 3. compute damage caused by old layers/surfaces that no longer exist
+ // 3. compute damage caused by old layers/surfaces that no longer exist
// for each leftover layer:
// add the old layer/surface bounds to the target surface damage.
//
- // // 4. combine all partial damage rects to get the full damage rect.
+ // 4. combine all partial damage rects to get the full damage rect.
//
// Additional important points:
//
@@ -128,28 +147,27 @@ void CCDamageTracker::updateDamageTrackingState(const Vector<CCLayerImpl*>& laye
FloatRect damageFromSurfaceMask = trackDamageFromSurfaceMask(targetSurfaceMaskLayer);
FloatRect damageFromLeftoverRects = trackDamageFromLeftoverRects();
- // If the target surface already knows its entire region is damaged, we can return early.
- // FIXME: this should go away, or will be cleaner, after refactoring into RenderPass/RenderSchedule.
- CCLayerImpl* layer = layerList[0];
- CCRenderSurface* targetSurface = layer->targetRenderSurface();
-
- if (m_forceFullDamageNextUpdate || targetSurface->surfacePropertyChangedOnlyFromDescendant()) {
- m_currentDamageRect = FloatRect(targetSurface->contentRect());
+ if (m_forceFullDamageNextUpdate || targetSurfacePropertyChangedOnlyFromDescendant) {
+ m_currentDamageRect = targetSurfaceContentRect;
m_forceFullDamageNextUpdate = false;
} else {
- // FIXME: can we need to clamp this damage to the surface's content rect? (affects performance, but not correctness)
+ // FIXME: can we clamp this damage to the surface's content rect? (affects performance, but not correctness)
m_currentDamageRect = damageFromActiveLayers;
m_currentDamageRect.uniteIfNonZero(damageFromSurfaceMask);
m_currentDamageRect.uniteIfNonZero(damageFromLeftoverRects);
+
+ if (filters.hasFilterThatMovesPixels())
+ expandDamageRectWithFilters(m_currentDamageRect, filters);
}
// The next history map becomes the current map for the next frame.
swap(m_currentRectHistory, m_nextRectHistory);
}
-FloatRect CCDamageTracker::removeRectFromCurrentFrame(int layerID)
+FloatRect CCDamageTracker::removeRectFromCurrentFrame(int layerID, bool& layerIsNew)
{
- // This function exists mainly for readability of the code.
+ layerIsNew = !m_currentRectHistory->contains(layerID);
+
// take() will remove the entry from the map, or if not found, return a default (empty) rect.
return m_currentRectHistory->take(layerID);
}
@@ -166,6 +184,7 @@ FloatRect CCDamageTracker::trackDamageFromActiveLayers(const Vector<CCLayerImpl*
FloatRect damageRect = FloatRect();
for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) {
+ // Visit layers in back-to-front order.
CCLayerImpl* layer = layerList[layerIndex];
if (CCLayerTreeHostCommon::renderSurfaceContributesToTarget<CCLayerImpl>(layer, targetSurfaceLayerID))
@@ -226,13 +245,14 @@ void CCDamageTracker::extendDamageForLayer(CCLayerImpl* layer, FloatRect& target
TransformationMatrix originTransform = layer->drawTransform();
originTransform.translate(-0.5 * layer->bounds().width(), -0.5 * layer->bounds().height());
- FloatRect oldLayerRect = removeRectFromCurrentFrame(layer->id());
+ bool layerIsNew = false;
+ FloatRect oldLayerRect = removeRectFromCurrentFrame(layer->id(), layerIsNew);
- FloatRect layerRectInTargetSpace = originTransform.mapRect(FloatRect(FloatPoint::zero(), layer->bounds()));
+ FloatRect layerRectInTargetSpace = CCMathUtil::mapClippedRect(originTransform, FloatRect(FloatPoint::zero(), layer->bounds()));
saveRectForNextFrame(layer->id(), layerRectInTargetSpace);
- if (layer->layerPropertyChanged()) {
- // If a layer has changed, then its entire layer rect affects the target surface.
+ if (layerIsNew || layer->layerPropertyChanged()) {
+ // If a layer is new or has changed, then its entire layer rect affects the target surface.
targetDamageRect.uniteIfNonZero(layerRectInTargetSpace);
// The layer's old region is now exposed on the target surface, too.
@@ -241,7 +261,7 @@ void CCDamageTracker::extendDamageForLayer(CCLayerImpl* layer, FloatRect& target
} else if (!layer->updateRect().isEmpty()) {
// If the layer properties havent changed, then the the target surface is only
// affected by the layer's update area, which could be empty.
- FloatRect updateRectInTargetSpace = originTransform.mapRect(layer->updateRect());
+ FloatRect updateRectInTargetSpace = CCMathUtil::mapClippedRect(originTransform, layer->updateRect());
targetDamageRect.uniteIfNonZero(updateRectInTargetSpace);
}
}
@@ -262,13 +282,19 @@ void CCDamageTracker::extendDamageForRenderSurface(CCLayerImpl* layer, FloatRect
CCRenderSurface* renderSurface = layer->renderSurface();
- FloatRect oldSurfaceRect = removeRectFromCurrentFrame(layer->id());
+ bool surfaceIsNew = false;
+ FloatRect oldSurfaceRect = removeRectFromCurrentFrame(layer->id(), surfaceIsNew);
FloatRect surfaceRectInTargetSpace = renderSurface->drawableContentRect(); // already includes replica if it exists.
saveRectForNextFrame(layer->id(), surfaceRectInTargetSpace);
+ // If the layer has a background filter, this may cause pixels in our surface to be expanded, so we will need to expand any damage
+ // that exists below this layer by that amount.
+ if (layer->backgroundFilters().hasFilterThatMovesPixels())
+ expandDamageRectInsideRectWithFilters(targetDamageRect, surfaceRectInTargetSpace, layer->backgroundFilters());
+
FloatRect damageRectInLocalSpace;
- if (renderSurface->surfacePropertyChanged()) {
+ if (surfaceIsNew || renderSurface->surfacePropertyChanged()) {
// The entire surface contributes damage.
damageRectInLocalSpace = renderSurface->contentRect();
@@ -282,17 +308,12 @@ void CCDamageTracker::extendDamageForRenderSurface(CCLayerImpl* layer, FloatRect
// If there was damage, transform it to target space, and possibly contribute its reflection if needed.
if (!damageRectInLocalSpace.isEmpty()) {
const TransformationMatrix& originTransform = renderSurface->originTransform();
- FloatRect damageRectInTargetSpace = originTransform.mapRect(damageRectInLocalSpace);
+ FloatRect damageRectInTargetSpace = CCMathUtil::mapClippedRect(originTransform, damageRectInLocalSpace);
targetDamageRect.uniteIfNonZero(damageRectInTargetSpace);
if (layer->replicaLayer()) {
- // Compute the replica's "originTransform" that maps from the replica's origin space to the target surface origin space.
- TransformationMatrix replicaOriginTransform = layer->renderSurface()->originTransform();
- replicaOriginTransform.translate(layer->replicaLayer()->position().x(), layer->replicaLayer()->position().y());
- replicaOriginTransform.multiply(layer->replicaLayer()->transform());
- replicaOriginTransform.translate(-layer->replicaLayer()->position().x(), -layer->replicaLayer()->position().y());
-
- targetDamageRect.uniteIfNonZero(replicaOriginTransform.mapRect(damageRectInLocalSpace));
+ const TransformationMatrix& replicaOriginTransform = renderSurface->replicaOriginTransform();
+ targetDamageRect.uniteIfNonZero(CCMathUtil::mapClippedRect(replicaOriginTransform, damageRectInLocalSpace));
}
}
@@ -300,19 +321,16 @@ void CCDamageTracker::extendDamageForRenderSurface(CCLayerImpl* layer, FloatRect
if (layer->replicaLayer() && layer->replicaLayer()->maskLayer()) {
CCLayerImpl* replicaMaskLayer = layer->replicaLayer()->maskLayer();
- removeRectFromCurrentFrame(replicaMaskLayer->id());
+ bool replicaIsNew = false;
+ removeRectFromCurrentFrame(replicaMaskLayer->id(), replicaIsNew);
// Compute the replica's "originTransform" that maps from the replica's origin space to the target surface origin space.
- TransformationMatrix replicaOriginTransform = layer->renderSurface()->originTransform();
- replicaOriginTransform.translate(layer->replicaLayer()->position().x(), layer->replicaLayer()->position().y());
- replicaOriginTransform.multiply(layer->replicaLayer()->transform());
- replicaOriginTransform.translate(-layer->replicaLayer()->position().x(), -layer->replicaLayer()->position().y());
-
- FloatRect replicaMaskLayerRect = replicaOriginTransform.mapRect(FloatRect(FloatPoint::zero(), FloatSize(replicaMaskLayer->bounds().width(), replicaMaskLayer->bounds().height())));
+ const TransformationMatrix& replicaOriginTransform = renderSurface->replicaOriginTransform();
+ FloatRect replicaMaskLayerRect = CCMathUtil::mapClippedRect(replicaOriginTransform, FloatRect(FloatPoint::zero(), FloatSize(replicaMaskLayer->bounds().width(), replicaMaskLayer->bounds().height())));
saveRectForNextFrame(replicaMaskLayer->id(), replicaMaskLayerRect);
// In the current implementation, a change in the replica mask damages the entire replica region.
- if (replicaMaskLayer->layerPropertyChanged() || !replicaMaskLayer->updateRect().isEmpty())
+ if (replicaIsNew || replicaMaskLayer->layerPropertyChanged() || !replicaMaskLayer->updateRect().isEmpty())
targetDamageRect.uniteIfNonZero(replicaMaskLayerRect);
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.h b/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.h
index 7a629c478..fade8cdff 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.h
@@ -35,6 +35,7 @@ namespace WebCore {
class CCLayerImpl;
class CCRenderSurface;
+class FilterOperations;
// Computes the region where pixels have actually changed on a RenderSurface. This region is used
// to scissor what is actually drawn to the screen to save GPU computation and bandwidth.
@@ -44,7 +45,7 @@ public:
~CCDamageTracker();
void forceFullDamageNextUpdate() { m_forceFullDamageNextUpdate = true; }
- void updateDamageTrackingState(const Vector<CCLayerImpl*>& layerList, int targetSurfaceLayerID, CCLayerImpl* targetSurfaceMaskLayer);
+ void updateDamageTrackingState(const Vector<CCLayerImpl*>& layerList, int targetSurfaceLayerID, bool targetSurfacePropertyChangedOnlyFromDescendant, const IntRect& targetSurfaceContentRect, CCLayerImpl* targetSurfaceMaskLayer, const FilterOperations&);
const FloatRect& currentDamageRect() { return m_currentDamageRect; }
private:
@@ -54,7 +55,7 @@ private:
FloatRect trackDamageFromSurfaceMask(CCLayerImpl* targetSurfaceMaskLayer);
FloatRect trackDamageFromLeftoverRects();
- FloatRect removeRectFromCurrentFrame(int layerID);
+ FloatRect removeRectFromCurrentFrame(int layerID, bool& layerIsNew);
void saveRectForNextFrame(int layerID, const FloatRect& targetSpaceRect);
// These helper functions are used only in trackDamageFromActiveLayers().
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDebugRectHistory.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCDebugRectHistory.cpp
new file mode 100644
index 000000000..3c88dcc40
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCDebugRectHistory.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+#include "CCDebugRectHistory.h"
+
+#include "CCDamageTracker.h"
+#include "CCLayerImpl.h"
+#include "CCLayerTreeHost.h"
+#include "CCMathUtil.h"
+
+namespace WebCore {
+
+CCDebugRectHistory::CCDebugRectHistory()
+{
+}
+
+bool CCDebugRectHistory::enabled(const CCSettings& settings)
+{
+ return settings.showPaintRects || settings.showPropertyChangedRects || settings.showSurfaceDamageRects;
+}
+
+void CCDebugRectHistory::saveDebugRectsForCurrentFrame(CCLayerImpl* rootLayer, const Vector<CCLayerImpl*>& renderSurfaceLayerList, const CCSettings& settings)
+{
+ // For now, clear all rects from previous frames. In the future we may want to store
+ // all debug rects for a history of many frames.
+ m_debugRects.clear();
+
+ if (settings.showPaintRects)
+ savePaintRects(rootLayer);
+
+ if (settings.showPropertyChangedRects)
+ savePropertyChangedRects(renderSurfaceLayerList);
+
+ if (settings.showSurfaceDamageRects)
+ saveSurfaceDamageRects(renderSurfaceLayerList);
+}
+
+
+void CCDebugRectHistory::savePaintRects(CCLayerImpl* layer)
+{
+ // We would like to visualize where any layer's paint rect (update rect) has changed,
+ // regardless of whether this layer is skipped for actual drawing or not. Therefore
+ // we traverse recursively over all layers, not just the render surface list.
+
+ if (!layer->updateRect().isEmpty() && layer->drawsContent())
+ m_debugRects.append(CCDebugRect(PaintRectType, CCMathUtil::mapClippedRect(layer->screenSpaceTransform(), layer->updateRect())));
+
+ for (unsigned i = 0; i < layer->children().size(); ++i)
+ savePaintRects(layer->children()[i].get());
+}
+
+void CCDebugRectHistory::savePropertyChangedRects(const Vector<CCLayerImpl*>& renderSurfaceLayerList)
+{
+ for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
+ CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
+ CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface();
+ ASSERT(renderSurface);
+
+ const Vector<CCLayerImpl*>& layerList = renderSurface->layerList();
+ for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) {
+ CCLayerImpl* layer = layerList[layerIndex];
+
+ if (CCLayerTreeHostCommon::renderSurfaceContributesToTarget<CCLayerImpl>(layer, renderSurfaceLayer->id()))
+ continue;
+
+ if (layer->layerPropertyChanged())
+ m_debugRects.append(CCDebugRect(PropertyChangedRectType, CCMathUtil::mapClippedRect(layer->screenSpaceTransform(), FloatRect(FloatPoint::zero(), layer->bounds()))));
+ }
+ }
+}
+
+void CCDebugRectHistory::saveSurfaceDamageRects(const Vector<CCLayerImpl* >& renderSurfaceLayerList)
+{
+ for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
+ CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
+ CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface();
+ ASSERT(renderSurface);
+
+ m_debugRects.append(CCDebugRect(SurfaceDamageRectType, CCMathUtil::mapClippedRect(renderSurface->screenSpaceTransform(), renderSurface->damageTracker()->currentDamageRect())));
+ }
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDebugRectHistory.h b/Source/WebCore/platform/graphics/chromium/cc/CCDebugRectHistory.h
new file mode 100644
index 000000000..93da107ad
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCDebugRectHistory.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CCDebugRectHistory_h
+#define CCDebugRectHistory_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "FloatRect.h"
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class CCLayerImpl;
+struct CCSettings;
+
+// There are currently three types of debug rects:
+//
+// - Paint rects (update rects): regions of a layer that needed to be re-uploaded to the
+// texture resource; in most cases implying that WebCore had to repaint them, too.
+//
+// - Property-changed rects: enclosing bounds of layers that cause changes to the screen
+// even if the layer did not change internally. (For example, if the layer's opacity or
+// position changes.)
+//
+// - Surface damage rects: the aggregate damage on a target surface that is caused by all
+// layers and surfaces that contribute to it. This includes (1) paint rects, (2) property-
+// changed rects, and (3) newly exposed areas.
+//
+enum DebugRectType { PaintRectType, PropertyChangedRectType, SurfaceDamageRectType };
+
+struct CCDebugRect {
+ CCDebugRect(DebugRectType newType, FloatRect newRect)
+ : type(newType)
+ , rect(newRect) { }
+
+ DebugRectType type;
+ FloatRect rect;
+};
+
+// This class maintains a history of rects of various types that can be used
+// for debugging purposes. The overhead of collecting rects is performed only if
+// the appropriate CCSettings are enabled.
+class CCDebugRectHistory {
+ WTF_MAKE_NONCOPYABLE(CCDebugRectHistory);
+public:
+ static PassOwnPtr<CCDebugRectHistory> create()
+ {
+ return adoptPtr(new CCDebugRectHistory());
+ }
+
+ bool enabled(const CCSettings&);
+
+ // Note: Saving debug rects must happen before layers' change tracking is reset.
+ void saveDebugRectsForCurrentFrame(CCLayerImpl* rootLayer, const Vector<CCLayerImpl*>& renderSurfaceLayerList, const CCSettings&);
+
+ const Vector<CCDebugRect>& debugRects() { return m_debugRects; }
+
+private:
+ CCDebugRectHistory();
+
+ void savePaintRects(CCLayerImpl*);
+ void savePropertyChangedRects(const Vector<CCLayerImpl*>& renderSurfaceLayerList);
+ void saveSurfaceDamageRects(const Vector<CCLayerImpl* >& renderSurfaceLayerList);
+
+ Vector<CCDebugRect> m_debugRects;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDelayBasedTimeSource.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCDelayBasedTimeSource.cpp
index e7b19a760..b688a78a2 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCDelayBasedTimeSource.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCDelayBasedTimeSource.cpp
@@ -33,15 +33,15 @@
namespace WebCore {
-PassRefPtr<CCDelayBasedTimeSource> CCDelayBasedTimeSource::create(double intervalMs, CCThread* thread)
+PassRefPtr<CCDelayBasedTimeSource> CCDelayBasedTimeSource::create(double interval, CCThread* thread)
{
- return adoptRef(new CCDelayBasedTimeSource(intervalMs, thread));
+ return adoptRef(new CCDelayBasedTimeSource(interval, thread));
}
-CCDelayBasedTimeSource::CCDelayBasedTimeSource(double intervalMs, CCThread* thread)
+CCDelayBasedTimeSource::CCDelayBasedTimeSource(double intervalSeconds, CCThread* thread)
: m_client(0)
, m_hasTickTarget(false)
- , m_intervalMs(intervalMs)
+ , m_intervalSeconds(intervalSeconds)
, m_tickTarget(0)
, m_state(STATE_INACTIVE)
, m_timer(thread, this)
@@ -70,32 +70,32 @@ void CCDelayBasedTimeSource::setActive(bool active)
m_state = STATE_ACTIVE;
- double nowMs = monotonicallyIncreasingTimeMs();
- postNextTickTask(nowMs);
+ double now = monotonicallyIncreasingTime();
+ postNextTickTask(now);
}
void CCDelayBasedTimeSource::onTimerFired()
{
ASSERT(m_state != STATE_INACTIVE);
- double nowMs = monotonicallyIncreasingTimeMs();
+ double now = monotonicallyIncreasingTime();
if (m_state == STATE_STARTING) {
m_hasTickTarget = true;
- m_tickTarget = nowMs;
+ m_tickTarget = now;
m_state = STATE_ACTIVE;
}
- postNextTickTask(nowMs);
+ postNextTickTask(now);
// Fire the tick
if (m_client)
m_client->onTimerTick();
}
-double CCDelayBasedTimeSource::monotonicallyIncreasingTimeMs() const
+double CCDelayBasedTimeSource::monotonicallyIncreasingTime() const
{
- return WTF::monotonicallyIncreasingTime() * 1000.0;
+ return WTF::monotonicallyIncreasingTime();
}
// This code tries to achieve an average tick rate as close to m_intervalMs as possible.
@@ -141,21 +141,23 @@ double CCDelayBasedTimeSource::monotonicallyIncreasingTimeMs() const
//
// For the really late delay, we we move to the next logical tick. The timebase is not reset.
// now=37 tickTarget=16.667 newTarget=50.000 --> tick(), postDelayedTask(floor(50.000-37)) --> postDelayedTask(13)
-void CCDelayBasedTimeSource::postNextTickTask(double nowMs)
+//
+// Note, that in the above discussion, times are expressed in milliseconds, but in the code, seconds are used.
+void CCDelayBasedTimeSource::postNextTickTask(double now)
{
- int numIntervalsElapsed = static_cast<int>(floor((nowMs - m_tickTarget) / m_intervalMs));
- double lastEffectiveTick = m_tickTarget + m_intervalMs * numIntervalsElapsed;
- double newTickTarget = lastEffectiveTick + m_intervalMs;
-
- long long delay = static_cast<long long>(newTickTarget - nowMs);
- if (!delay) {
- newTickTarget = newTickTarget + m_intervalMs;
- delay = static_cast<long long>(newTickTarget - nowMs);
+ int numIntervalsElapsed = static_cast<int>(floor((now - m_tickTarget) / m_intervalSeconds));
+ double lastEffectiveTick = m_tickTarget + m_intervalSeconds * numIntervalsElapsed;
+ double newTickTarget = lastEffectiveTick + m_intervalSeconds;
+
+ long long delayMs = static_cast<long long>((newTickTarget - now) * 1000.0);
+ if (!delayMs) {
+ newTickTarget = newTickTarget + m_intervalSeconds;
+ delayMs = static_cast<long long>((newTickTarget - now) * 1000.0);
}
// Post another task *before* the tick and update state
- ASSERT(newTickTarget > nowMs);
- m_timer.startOneShot(delay);
+ ASSERT(newTickTarget > now);
+ m_timer.startOneShot(delayMs / 1000.0);
m_tickTarget = newTickTarget;
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDelayBasedTimeSource.h b/Source/WebCore/platform/graphics/chromium/cc/CCDelayBasedTimeSource.h
index a41aad4d8..99795db81 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCDelayBasedTimeSource.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCDelayBasedTimeSource.h
@@ -38,24 +38,24 @@ class CCThread;
// in face of millisecond-precision delayed callbacks and random queueing delays.
class CCDelayBasedTimeSource : public CCTimeSource, CCTimerClient {
public:
- static PassRefPtr<CCDelayBasedTimeSource> create(double intervalMs, CCThread*);
+ static PassRefPtr<CCDelayBasedTimeSource> create(double intervalSeconds, CCThread*);
virtual ~CCDelayBasedTimeSource() { }
- virtual void setClient(CCTimeSourceClient* client) { m_client = client; }
+ virtual void setClient(CCTimeSourceClient* client) OVERRIDE { m_client = client; }
- virtual void setActive(bool);
- virtual bool active() const { return m_state != STATE_INACTIVE; }
+ virtual void setActive(bool) OVERRIDE;
+ virtual bool active() const OVERRIDE { return m_state != STATE_INACTIVE; }
// CCTimerClient implementation.
- virtual void onTimerFired();
+ virtual void onTimerFired() OVERRIDE;
// Virtual for testing.
- virtual double monotonicallyIncreasingTimeMs() const;
+ virtual double monotonicallyIncreasingTime() const;
protected:
- CCDelayBasedTimeSource(double intervalMs, CCThread*);
- void postNextTickTask(double nowMs);
+ CCDelayBasedTimeSource(double interval, CCThread*);
+ void postNextTickTask(double now);
enum State {
STATE_INACTIVE,
@@ -64,7 +64,7 @@ protected:
};
CCTimeSourceClient* m_client;
bool m_hasTickTarget;
- double m_intervalMs;
+ double m_intervalSeconds;
double m_tickTarget;
State m_state;
CCThread* m_thread;
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.cpp
index 708500267..2812d652f 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.cpp
@@ -27,12 +27,13 @@
#include "cc/CCDrawQuad.h"
-#include "cc/CCCanvasDrawQuad.h"
+#include "cc/CCCheckerboardDrawQuad.h"
#include "cc/CCDebugBorderDrawQuad.h"
+#include "cc/CCIOSurfaceDrawQuad.h"
#include "cc/CCLayerImpl.h"
-#include "cc/CCPluginDrawQuad.h"
#include "cc/CCRenderSurfaceDrawQuad.h"
#include "cc/CCSolidColorDrawQuad.h"
+#include "cc/CCTextureDrawQuad.h"
#include "cc/CCTileDrawQuad.h"
#include "cc/CCVideoDrawQuad.h"
@@ -65,12 +66,24 @@ void CCDrawQuad::setQuadVisibleRect(const IntRect& quadVisibleRect)
m_quadVisibleRect.intersect(m_quadRect);
}
+const CCCheckerboardDrawQuad* CCDrawQuad::toCheckerboardDrawQuad() const
+{
+ ASSERT(m_material == Checkerboard);
+ return static_cast<const CCCheckerboardDrawQuad*>(this);
+}
+
const CCDebugBorderDrawQuad* CCDrawQuad::toDebugBorderDrawQuad() const
{
ASSERT(m_material == DebugBorder);
return static_cast<const CCDebugBorderDrawQuad*>(this);
}
+const CCIOSurfaceDrawQuad* CCDrawQuad::toIOSurfaceDrawQuad() const
+{
+ ASSERT(m_material == IOSurfaceContent);
+ return static_cast<const CCIOSurfaceDrawQuad*>(this);
+}
+
const CCRenderSurfaceDrawQuad* CCDrawQuad::toRenderSurfaceDrawQuad() const
{
ASSERT(m_material == RenderSurface);
@@ -83,28 +96,22 @@ const CCSolidColorDrawQuad* CCDrawQuad::toSolidColorDrawQuad() const
return static_cast<const CCSolidColorDrawQuad*>(this);
}
+const CCTextureDrawQuad* CCDrawQuad::toTextureDrawQuad() const
+{
+ ASSERT(m_material == TextureContent);
+ return static_cast<const CCTextureDrawQuad*>(this);
+}
const CCTileDrawQuad* CCDrawQuad::toTileDrawQuad() const
{
ASSERT(m_material == TiledContent);
return static_cast<const CCTileDrawQuad*>(this);
}
-const CCCanvasDrawQuad* CCDrawQuad::toCanvasDrawQuad() const
-{
- ASSERT(m_material == CanvasContent);
- return static_cast<const CCCanvasDrawQuad*>(this);
-}
-
const CCVideoDrawQuad* CCDrawQuad::toVideoDrawQuad() const
{
ASSERT(m_material == VideoContent);
return static_cast<const CCVideoDrawQuad*>(this);
}
-const CCPluginDrawQuad* CCDrawQuad::toPluginDrawQuad() const
-{
- ASSERT(m_material == PluginContent);
- return static_cast<const CCPluginDrawQuad*>(this);
-}
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.h b/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.h
index 1738b4b0e..b78882e6a 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.h
@@ -30,13 +30,14 @@
namespace WebCore {
+class CCCheckerboardDrawQuad;
class CCDebugBorderDrawQuad;
+class CCIOSurfaceDrawQuad;
class CCRenderSurfaceDrawQuad;
class CCSolidColorDrawQuad;
+class CCTextureDrawQuad;
class CCTileDrawQuad;
-class CCCanvasDrawQuad;
class CCVideoDrawQuad;
-class CCPluginDrawQuad;
// CCDrawQuad is a bag of data used for drawing a quad. Because different
// materials need different bits of per-quad data to render, classes that derive
@@ -51,9 +52,9 @@ public:
const IntRect& layerRect() const { return m_sharedQuadState->layerRect(); }
const IntRect& clipRect() const { return m_sharedQuadState->clipRect(); }
float opacity() const { return m_sharedQuadState->opacity(); }
- // For the purposes of culling, what part of the contents of this quad are opaque?
+ // For the purposes of blending, what part of the contents of this quad are opaque?
IntRect opaqueRect() const;
- bool needsBlending() const { return m_needsBlending || opaqueRect() != m_quadRect; }
+ bool needsBlending() const { return m_needsBlending || !opaqueRect().contains(m_quadVisibleRect); }
bool isLayerAxisAlignedIntRect() const { return m_sharedQuadState->isLayerAxisAlignedIntRect(); }
// Allows changing the rect that gets drawn to make it smaller. Parameter passed
@@ -63,24 +64,26 @@ public:
enum Material {
Invalid,
+ Checkerboard,
DebugBorder,
+ IOSurfaceContent,
RenderSurface,
+ TextureContent,
SolidColor,
TiledContent,
- CanvasContent,
VideoContent,
- PluginContent,
};
Material material() const { return m_material; }
+ const CCCheckerboardDrawQuad* toCheckerboardDrawQuad() const;
const CCDebugBorderDrawQuad* toDebugBorderDrawQuad() const;
+ const CCIOSurfaceDrawQuad* toIOSurfaceDrawQuad() const;
const CCRenderSurfaceDrawQuad* toRenderSurfaceDrawQuad() const;
const CCSolidColorDrawQuad* toSolidColorDrawQuad() const;
+ const CCTextureDrawQuad* toTextureDrawQuad() const;
const CCTileDrawQuad* toTileDrawQuad() const;
- const CCCanvasDrawQuad* toCanvasDrawQuad() const;
const CCVideoDrawQuad* toVideoDrawQuad() const;
- const CCPluginDrawQuad* toPluginDrawQuad() const;
protected:
CCDrawQuad(const CCSharedQuadState*, Material, const IntRect&);
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCFontAtlas.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCFontAtlas.cpp
new file mode 100644
index 000000000..5da4296c5
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCFontAtlas.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+#include "CCFontAtlas.h"
+
+#include "CCProxy.h"
+#include "Font.h"
+#include "FontCache.h"
+#include "FontDescription.h"
+#include "GraphicsContext.h"
+#include "ImageBuffer.h"
+#include "TextRun.h"
+
+#define ATLAS_SIZE 128
+#define FONT_HEIGHT 14
+
+namespace WebCore {
+
+using namespace std;
+
+
+CCFontAtlas::CCFontAtlas()
+ : m_fontHeight(FONT_HEIGHT)
+{
+}
+
+static void wrapPositionIfNeeded(IntPoint& position, int textWidth, int textHeight)
+{
+ if (position.x() + textWidth > ATLAS_SIZE)
+ position = IntPoint(0, position.y() + textHeight);
+}
+
+void CCFontAtlas::generateAtlasForFont(GraphicsContext* atlasContext, const FontDescription& fontDescription, const Color& fontColor, const IntPoint& startingPosition, IntRect asciiToAtlasTable[128])
+{
+ ASSERT(CCProxy::isMainThread());
+ ASSERT(m_atlas);
+
+ FontCachePurgePreventer fontCachePurgePreventer;
+
+ IntPoint position = startingPosition;
+ int textHeight = fontDescription.computedPixelSize();
+ // This is a dirty little trick to account for overhang letters like g, p, j.
+ int inflation = textHeight / 3;
+
+ Font font(fontDescription, 0, 0);
+ font.update(0);
+
+ atlasContext->setStrokeColor(fontColor, ColorSpaceDeviceRGB);
+ atlasContext->setFillColor(fontColor, ColorSpaceDeviceRGB);
+
+ // First, draw a generic rect that will be used for special and unknown characters that have nothing else to render.
+ {
+ int textWidth = textHeight / 2;
+ wrapPositionIfNeeded(position, textWidth, textHeight + inflation);
+ atlasContext->strokeRect(FloatRect(FloatPoint(position.x() + 1, position.y() - textHeight + 1 + inflation), FloatSize(textWidth - 2, textHeight - 2 - inflation)), 1);
+
+ // Initialize the rect that would be copied when drawing this glyph from the atlas.
+ asciiToAtlasTable[0] = IntRect(IntPoint(position.x(), position.y() - textHeight), IntSize(textWidth, textHeight + inflation));
+
+ // Increment to the position where the next glyph will be placed.
+ position.setX(position.x() + textWidth);
+ }
+
+ // Then, draw the ASCII characters.
+ for (LChar i = 1; i < 128; ++i) {
+ if (i < 32) {
+ // Special characters will simply use the the default glyph.
+ asciiToAtlasTable[i] = asciiToAtlasTable[0];
+ continue;
+ }
+
+ String str;
+ str.append(i);
+ TextRun text(str);
+
+ int textWidth = round(font.width(text));
+ wrapPositionIfNeeded(position, textWidth, textHeight + inflation);
+ atlasContext->drawText(font, text, position);
+
+ // Initialize the rect that would be copied when drawing this glyph from the atlas.
+ asciiToAtlasTable[i] = IntRect(IntPoint(position.x(), position.y() - textHeight), IntSize(textWidth, textHeight + inflation));
+
+ // Increment to the position where the next glyph will be placed.
+ position.setX(position.x() + textWidth);
+ }
+}
+
+void CCFontAtlas::initialize()
+{
+ ASSERT(CCProxy::isMainThread());
+
+ // We expect this function to be called only once when the atlas did not exist yet. We should be aware if that's not true.
+ ASSERT(!m_atlas);
+
+ m_atlas = ImageBuffer::create(IntSize(ATLAS_SIZE, ATLAS_SIZE));
+ GraphicsContext* atlasContext = m_atlas->context();
+
+ // Clear the entire texture atlas to transparent before drawing fonts.
+ atlasContext->setFillColor(Color(0, 0, 0, 0), ColorSpaceDeviceRGB);
+ atlasContext->fillRect(FloatRect(0, 0, ATLAS_SIZE, ATLAS_SIZE));
+
+ // FIXME: monospace font does not work as expected.
+ FontDescription fontDescription;
+ fontDescription.setGenericFamily(FontDescription::MonospaceFamily);
+ fontDescription.setComputedSize(m_fontHeight);
+ generateAtlasForFont(atlasContext, fontDescription, Color(255, 0, 0), IntPoint(0, fontDescription.computedPixelSize()), m_asciiToRectTable);
+}
+
+void CCFontAtlas::drawText(GraphicsContext* targetContext, const String& text, const IntPoint& destPosition, const IntSize& clip) const
+{
+ ASSERT(CCProxy::isImplThread());
+ ASSERT(m_atlas);
+
+ Vector<String> lines;
+ text.split('\n', lines);
+
+ IntPoint position = destPosition;
+ for (size_t i = 0; i < lines.size(); ++i) {
+ drawOneLineOfTextInternal(targetContext, lines[i], position);
+ position.setY(position.y() + m_fontHeight);
+ if (position.y() > clip.height())
+ return;
+ }
+}
+
+void CCFontAtlas::drawOneLineOfTextInternal(GraphicsContext* targetContext, const String& textLine, const IntPoint& destPosition) const
+{
+ ASSERT(CCProxy::isImplThread());
+ ASSERT(m_atlas);
+
+ IntPoint position = destPosition;
+ for (unsigned i = 0; i < textLine.length(); ++i) {
+ // If the ASCII code is out of bounds, then index 0 is used, which is just a plain rectangle glyph.
+ int asciiIndex = (textLine[i] < 128) ? textLine[i] : 0;
+ IntRect glyphBounds = m_asciiToRectTable[asciiIndex];
+ targetContext->drawImageBuffer(m_atlas.get(), ColorSpaceDeviceRGB, position, glyphBounds);
+ position.setX(position.x() + glyphBounds.width());
+ }
+}
+
+void CCFontAtlas::drawDebugAtlas(GraphicsContext* targetContext, const IntPoint& destPosition) const
+{
+ ASSERT(CCProxy::isImplThread());
+ ASSERT(m_atlas);
+
+ targetContext->drawImageBuffer(m_atlas.get(), ColorSpaceDeviceRGB, destPosition, IntRect(IntPoint::zero(), IntSize(ATLAS_SIZE, ATLAS_SIZE)));
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCFontAtlas.h b/Source/WebCore/platform/graphics/chromium/cc/CCFontAtlas.h
new file mode 100644
index 000000000..cca3a1ce5
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCFontAtlas.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CCFontAtlas_h
+#define CCFontAtlas_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "ImageBuffer.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class Color;
+class FontDescription;
+class IntPoint;
+class IntRect;
+class GraphicsContext;
+
+// This class provides basic ability to draw text onto the heads-up display.
+// It must be initialized on the main thread, and it can only draw text on the impl thread.
+class CCFontAtlas {
+ WTF_MAKE_NONCOPYABLE(CCFontAtlas);
+public:
+ static PassOwnPtr<CCFontAtlas> create()
+ {
+ return adoptPtr(new CCFontAtlas());
+ }
+
+ // Creates the font atlas.
+ // - Should only be called on the main thread.
+ void initialize();
+
+ // Draws multiple lines of text where each line of text is separated by '\n'.
+ // - Correct glyphs will be drawn for ASCII codes in the range 32-127; any characters
+ // outside that range will be displayed as a default rectangle glyph.
+ // - IntSize clip is used to avoid wasting time drawing things that are outside the
+ // target canvas bounds.
+ // - Should only be called only on the impl thread.
+ void drawText(GraphicsContext*, const String& text, const IntPoint& destPosition, const IntSize& clip) const;
+
+ // Draws the entire atlas at the specified position, just for debugging purposes.
+ void drawDebugAtlas(GraphicsContext*, const IntPoint& destPosition) const;
+
+private:
+ CCFontAtlas();
+
+ // Paints the font into the atlas, from left-to-right, top-to-bottom, starting at
+ // startingPosition. At the same time, it updates the ascii-to-IntRect mapping for
+ // each character. By doing things this way, it is possible to support variable-width
+ // fonts and multiple fonts on the same atlas.
+ void generateAtlasForFont(GraphicsContext*, const FontDescription&, const Color& fontColor, const IntPoint& startingPosition, IntRect asciiToAtlasTable[128]);
+
+ void drawOneLineOfTextInternal(GraphicsContext*, const String&, const IntPoint& destPosition) const;
+
+ // The actual texture atlas containing all the pre-rendered glyphs.
+ OwnPtr<ImageBuffer> m_atlas;
+
+ // The look-up tables mapping ascii characters to their IntRect locations on the atlas.
+ IntRect m_asciiToRectTable[128];
+
+ int m_fontHeight;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.cpp
index 55447ca59..84a7cb310 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.cpp
@@ -40,7 +40,7 @@ public:
}
virtual ~CCFrameRateControllerTimeSourceAdapter() { }
- virtual void onTimerTick() { m_frameRateController->onTimerTick(); }
+ virtual void onTimerTick() OVERRIDE { m_frameRateController->onTimerTick(); }
private:
explicit CCFrameRateControllerTimeSourceAdapter(CCFrameRateController* frameRateController)
: m_frameRateController(frameRateController) { }
@@ -87,7 +87,7 @@ void CCFrameRateController::onTimerTick()
}
if (m_client)
- m_client->beginFrame();
+ m_client->vsyncTick();
}
void CCFrameRateController::didBeginFrame()
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.h b/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.h
index a3eefe846..5734d4aa6 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.h
@@ -35,7 +35,7 @@ namespace WebCore {
class CCFrameRateControllerClient {
public:
- virtual void beginFrame() = 0;
+ virtual void vsyncTick() = 0;
protected:
virtual ~CCFrameRateControllerClient() { }
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateCounter.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateCounter.cpp
new file mode 100644
index 000000000..d6dff06ab
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateCounter.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+#include "CCFrameRateCounter.h"
+
+#include "CCProxy.h"
+#include <wtf/CurrentTime.h>
+
+namespace WebCore {
+
+const double CCFrameRateCounter::kFrameTooFast = 1.0 / 70.0; // measured in seconds
+const double CCFrameRateCounter::kFrameTooSlow = 1.0 / 12.0;
+
+// safeMod works on -1, returning m-1 in that case.
+static inline int safeMod(int number, int modulus)
+{
+ return (number + modulus) % modulus;
+}
+
+inline int CCFrameRateCounter::frameIndex(int frame) const
+{
+ return safeMod(frame, kTimeStampHistorySize);
+}
+
+CCFrameRateCounter::CCFrameRateCounter()
+ : m_currentFrameNumber(1)
+{
+ m_timeStampHistory[0] = currentTime();
+ m_timeStampHistory[1] = m_timeStampHistory[0];
+ for (int i = 2; i < kTimeStampHistorySize; i++)
+ m_timeStampHistory[i] = 0;
+}
+
+void CCFrameRateCounter::markBeginningOfFrame(double timestamp)
+{
+ m_timeStampHistory[frameIndex(m_currentFrameNumber)] = timestamp;
+}
+
+void CCFrameRateCounter::markEndOfFrame()
+{
+ m_currentFrameNumber += 1;
+}
+
+bool CCFrameRateCounter::isBadFrameInterval(double intervalBetweenConsecutiveFrames) const
+{
+ bool schedulerAllowsDoubleFrames = !CCProxy::hasImplThread();
+ bool intervalTooFast = schedulerAllowsDoubleFrames && intervalBetweenConsecutiveFrames < kFrameTooFast;
+ bool intervalTooSlow = intervalBetweenConsecutiveFrames > kFrameTooSlow;
+ return intervalTooFast || intervalTooSlow;
+}
+
+bool CCFrameRateCounter::isBadFrame(int frameNumber) const
+{
+ double delta = m_timeStampHistory[frameIndex(frameNumber)] -
+ m_timeStampHistory[frameIndex(frameNumber - 1)];
+ return isBadFrameInterval(delta);
+}
+
+void CCFrameRateCounter::getAverageFPSAndStandardDeviation(double& averageFPS, double& standardDeviation) const
+{
+ int frame = m_currentFrameNumber - 1;
+ averageFPS = 0;
+ int averageFPSCount = 0;
+ double fpsVarianceNumerator = 0;
+
+ // Walk backwards through the samples looking for a run of good frame
+ // timings from which to compute the mean and standard deviation.
+ //
+ // Slow frames occur just because the user is inactive, and should be
+ // ignored. Fast frames are ignored if the scheduler is in single-thread
+ // mode in order to represent the true frame rate in spite of the fact that
+ // the first few swapbuffers happen instantly which skews the statistics
+ // too much for short lived animations.
+ //
+ // isBadFrame encapsulates the frame too slow/frame too fast logic.
+ while (1) {
+ if (!isBadFrame(frame)) {
+ averageFPSCount++;
+ double secForLastFrame = m_timeStampHistory[frameIndex(frame)] -
+ m_timeStampHistory[frameIndex(frame - 1)];
+ double x = 1.0 / secForLastFrame;
+ double deltaFromAverage = x - averageFPS;
+ // Change with caution - numerics. http://en.wikipedia.org/wiki/Standard_deviation
+ averageFPS = averageFPS + deltaFromAverage / averageFPSCount;
+ fpsVarianceNumerator = fpsVarianceNumerator + deltaFromAverage * (x - averageFPS);
+ }
+ if (averageFPSCount && isBadFrame(frame)) {
+ // We've gathered a run of good samples, so stop.
+ break;
+ }
+ --frame;
+ if (frameIndex(frame) == frameIndex(m_currentFrameNumber) || frame < 0) {
+ // We've gone through all available historical data, so stop.
+ break;
+ }
+ }
+
+ standardDeviation = sqrt(fpsVarianceNumerator / averageFPSCount);
+}
+
+double CCFrameRateCounter::timeStampOfRecentFrame(int n)
+{
+ ASSERT(n >= 0 && n < kTimeStampHistorySize);
+ int desiredIndex = (frameIndex(m_currentFrameNumber) + n) % kTimeStampHistorySize;
+ return m_timeStampHistory[desiredIndex];
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateCounter.h b/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateCounter.h
new file mode 100644
index 000000000..c49f17c23
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateCounter.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CCFrameRateCounter_h
+#define CCFrameRateCounter_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+// This class maintains a history of timestamps, and provides functionality to
+// intelligently compute average frames per second (and standard deviation).
+class CCFrameRateCounter {
+ WTF_MAKE_NONCOPYABLE(CCFrameRateCounter);
+public:
+ static PassOwnPtr<CCFrameRateCounter> create()
+ {
+ return adoptPtr(new CCFrameRateCounter());
+ }
+
+ void markBeginningOfFrame(double timestamp);
+ void markEndOfFrame();
+ int currentFrameNumber() const { return m_currentFrameNumber; }
+ void getAverageFPSAndStandardDeviation(double& averageFPS, double& standardDeviation) const;
+ int timeStampHistorySize() const { return kTimeStampHistorySize; }
+
+ // n = 0 returns the oldest frame retained in the history,
+ // while n = timeStampHistorySize() - 1 returns the timestamp most recent frame.
+ double timeStampOfRecentFrame(int /* n */);
+
+ // This is a heuristic that can be used to ignore frames in a reasonable way. Returns
+ // true if the given frame interval is too fast or too slow, based on constant thresholds.
+ bool isBadFrameInterval(double intervalBetweenConsecutiveFrames) const;
+
+private:
+ CCFrameRateCounter();
+
+ int frameIndex(int frameNumber) const;
+ bool isBadFrame(int frameNumber) const;
+
+ // Two thresholds (measured in seconds) that describe what is considered to be a "no-op frame" that should not be counted.
+ // - if the frame is too fast, then given our compositor implementation, the frame probably was a no-op and did not draw.
+ // - if the frame is too slow, then there is probably not animating content, so we should not pollute the average.
+ static const double kFrameTooFast;
+ static const double kFrameTooSlow;
+
+ static const int kTimeStampHistorySize = 120;
+
+ int m_currentFrameNumber;
+ double m_timeStampHistory[kTimeStampHistorySize];
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCGestureCurve.h b/Source/WebCore/platform/graphics/chromium/cc/CCGestureCurve.h
index 3ef935b6a..9089a48f3 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCGestureCurve.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCGestureCurve.h
@@ -31,18 +31,19 @@ class IntPoint;
class CCGestureCurveTarget {
public:
- virtual void setScrollIncrement(const IntPoint&) = 0;
- // FIXME: add interfaces for setScroll(), setPageScaleAndScroll(), etc.
-
-protected:
virtual ~CCGestureCurveTarget() { }
+
+ virtual void scrollBy(const IntPoint&) = 0;
+ // FIXME: add interfaces for scroll(), etc.
};
class CCGestureCurve {
public:
virtual ~CCGestureCurve() { }
- virtual bool apply(double time, CCGestureCurveTarget*) = 0;
+ virtual const char* debugName() const = 0;
+
+ virtual bool apply(double monotonicTime, CCGestureCurveTarget*) = 0;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp
index 3ddc123c0..7d49f798d 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp
@@ -28,85 +28,58 @@
#include "CCHeadsUpDisplay.h"
#include "Extensions3DChromium.h"
-#include "Font.h"
-#include "FontCache.h"
-#include "FontDescription.h"
#include "GraphicsContext3D.h"
-#include "InspectorController.h"
-#include "LayerChromium.h"
#include "LayerRendererChromium.h"
#include "ManagedTexture.h"
#include "PlatformCanvas.h"
-#include "TextRun.h"
-#include "TextStream.h"
#include "TextureManager.h"
-#include <wtf/CurrentTime.h>
-#include <wtf/text/CString.h>
+#include "cc/CCDebugRectHistory.h"
+#include "cc/CCFontAtlas.h"
+#include "cc/CCFrameRateCounter.h"
+#include "cc/CCLayerTreeHostImpl.h"
#include <wtf/text/WTFString.h>
namespace WebCore {
using namespace std;
-CCHeadsUpDisplay::CCHeadsUpDisplay(LayerRendererChromium* owner)
- : m_currentFrameNumber(1)
- , m_filteredFrameTime(0)
- , m_layerRenderer(owner)
- , m_useMapSubForUploads(owner->contextSupportsMapSub())
+CCHeadsUpDisplay::~CCHeadsUpDisplay()
{
- m_beginTimeHistoryInSec[0] = currentTime();
- m_beginTimeHistoryInSec[1] = m_beginTimeHistoryInSec[0];
- for (int i = 2; i < kBeginFrameHistorySize; i++)
- m_beginTimeHistoryInSec[i] = 0;
-
- FontDescription mediumFontDesc;
- mediumFontDesc.setGenericFamily(FontDescription::MonospaceFamily);
- mediumFontDesc.setComputedSize(20);
-
- m_mediumFont = adoptPtr(new Font(mediumFontDesc, 0, 0));
- m_mediumFont->update(0);
-
- FontDescription smallFontDesc;
- smallFontDesc.setGenericFamily(FontDescription::MonospaceFamily);
- smallFontDesc.setComputedSize(10);
-
- m_smallFont = adoptPtr(new Font(smallFontDesc, 0, 0));
- m_smallFont->update(0);
}
-CCHeadsUpDisplay::~CCHeadsUpDisplay()
+void CCHeadsUpDisplay::setFontAtlas(PassOwnPtr<CCFontAtlas> fontAtlas)
{
+ m_fontAtlas = fontAtlas;
}
-void CCHeadsUpDisplay::onFrameBegin(double timestamp)
+bool CCHeadsUpDisplay::enabled(const CCSettings& settings) const
{
- m_beginTimeHistoryInSec[m_currentFrameNumber % kBeginFrameHistorySize] = timestamp;
+ return showPlatformLayerTree(settings) || settings.showFPSCounter || showDebugRects(settings);
}
-void CCHeadsUpDisplay::onSwapBuffers()
+bool CCHeadsUpDisplay::showPlatformLayerTree(const CCSettings& settings) const
{
- m_currentFrameNumber += 1;
+ return settings.showPlatformLayerTree;
}
-bool CCHeadsUpDisplay::enabled() const
+bool CCHeadsUpDisplay::showDebugRects(const CCSettings& settings) const
{
- // FIXME: HUD does not work in compositor thread mode.
- if (CCProxy::hasImplThread())
- return false;
- return settings().showPlatformLayerTree || settings().showFPSCounter;
+ return settings.showPaintRects || settings.showPropertyChangedRects || settings.showSurfaceDamageRects;
}
-void CCHeadsUpDisplay::draw()
+void CCHeadsUpDisplay::draw(CCLayerTreeHostImpl* layerTreeHostImpl)
{
- GraphicsContext3D* context = m_layerRenderer->context();
+ LayerRendererChromium* layerRenderer = layerTreeHostImpl->layerRenderer();
+ GraphicsContext3D* context = layerRenderer->context();
if (!m_hudTexture)
- m_hudTexture = ManagedTexture::create(m_layerRenderer->renderSurfaceTextureManager());
+ m_hudTexture = ManagedTexture::create(layerRenderer->renderSurfaceTextureManager());
+ const CCSettings& settings = layerTreeHostImpl->settings();
// Use a fullscreen texture only if we need to...
IntSize hudSize;
- if (settings().showPlatformLayerTree) {
- hudSize.setWidth(min(2048, m_layerRenderer->viewportWidth()));
- hudSize.setHeight(min(2048, m_layerRenderer->viewportHeight()));
+ if (showPlatformLayerTree(settings) || showDebugRects(settings)) {
+ hudSize.setWidth(min(2048, layerTreeHostImpl->viewportSize().width()));
+ hudSize.setHeight(min(2048, layerTreeHostImpl->viewportSize().height()));
} else {
hudSize.setWidth(512);
hudSize.setHeight(128);
@@ -120,16 +93,17 @@ void CCHeadsUpDisplay::draw()
canvas.resize(hudSize);
{
PlatformCanvas::Painter painter(&canvas, PlatformCanvas::Painter::GrayscaleText);
- drawHudContents(painter.context(), hudSize);
+ painter.context()->clearRect(FloatRect(0, 0, hudSize.width(), hudSize.height()));
+ drawHudContents(painter.context(), layerTreeHostImpl, settings, hudSize);
}
// Upload to GL.
{
PlatformCanvas::AutoLocker locker(&canvas);
- m_hudTexture->bindTexture(context, m_layerRenderer->renderSurfaceTextureAllocator());
+ m_hudTexture->bindTexture(context, layerRenderer->renderSurfaceTextureAllocator());
bool uploadedViaMap = false;
- if (m_useMapSubForUploads) {
+ if (layerRenderer->contextSupportsMapSub()) {
Extensions3DChromium* extensions = static_cast<Extensions3DChromium*>(context->getExtensions());
uint8_t* pixelDest = static_cast<uint8_t*>(extensions->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, hudSize.width(), hudSize.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, Extensions3DChromium::WRITE_ONLY));
@@ -145,119 +119,130 @@ void CCHeadsUpDisplay::draw()
}
}
- // Draw the HUD onto the default render surface.
- const Program* program = m_layerRenderer->headsUpDisplayProgram();
- ASSERT(program && program->initialized());
- GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
- m_hudTexture->bindTexture(context, m_layerRenderer->renderSurfaceTextureAllocator());
- GLC(context, context->useProgram(program->program()));
- GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
-
- TransformationMatrix matrix;
- matrix.translate3d(hudSize.width() * 0.5, hudSize.height() * 0.5, 0);
- m_layerRenderer->drawTexturedQuad(matrix, hudSize.width(), hudSize.height(),
- 1.0f, m_layerRenderer->sharedGeometryQuad(), program->vertexShader().matrixLocation(),
- program->fragmentShader().alphaLocation(),
- -1);
+ layerRenderer->drawHeadsUpDisplay(m_hudTexture.get(), hudSize);
+
m_hudTexture->unreserve();
}
-void CCHeadsUpDisplay::drawHudContents(GraphicsContext* ctx, const IntSize& hudSize)
+void CCHeadsUpDisplay::drawHudContents(GraphicsContext* context, CCLayerTreeHostImpl* layerTreeHostImpl, const CCSettings& settings, const IntSize& hudSize)
{
- FontCachePurgePreventer fontCachePurgePreventer;
-
- if (settings().showPlatformLayerTree) {
- ctx->setFillColor(Color(0, 0, 0, 192), ColorSpaceDeviceRGB);
- ctx->fillRect(FloatRect(0, 0, hudSize.width(), hudSize.height()));
+ if (showPlatformLayerTree(settings)) {
+ context->setFillColor(Color(0, 0, 0, 192), ColorSpaceDeviceRGB);
+ context->fillRect(FloatRect(0, 0, hudSize.width(), hudSize.height()));
}
- int fpsCounterHeight = m_mediumFont->fontMetrics().floatHeight() + 2;
+ int fpsCounterHeight = 40;
int fpsCounterTop = 2;
int platformLayerTreeTop;
- if (settings().showFPSCounter)
- platformLayerTreeTop = fpsCounterTop + fpsCounterHeight + 2;
+
+ if (settings.showFPSCounter)
+ platformLayerTreeTop = fpsCounterTop + fpsCounterHeight;
else
platformLayerTreeTop = 0;
- if (settings().showFPSCounter)
- drawFPSCounter(ctx, fpsCounterTop, fpsCounterHeight);
+ if (settings.showFPSCounter)
+ drawFPSCounter(context, layerTreeHostImpl->fpsCounter(), fpsCounterTop, fpsCounterHeight);
+
+ if (showPlatformLayerTree(settings) && m_fontAtlas) {
+ String layerTree = layerTreeHostImpl->layerTreeAsText();
+ m_fontAtlas->drawText(context, layerTree, IntPoint(2, platformLayerTreeTop), hudSize);
+ }
- if (settings().showPlatformLayerTree)
- drawPlatformLayerTree(ctx, platformLayerTreeTop);
+ if (showDebugRects(settings))
+ drawDebugRects(context, layerTreeHostImpl->debugRectHistory(), settings);
}
-void CCHeadsUpDisplay::drawFPSCounter(GraphicsContext* ctx, int top, int height)
+void CCHeadsUpDisplay::drawFPSCounter(GraphicsContext* context, CCFrameRateCounter* fpsCounter, int top, int height)
{
- // Note that since we haven't finished the current frame, the FPS counter
- // actually reports the last frame's time.
- double secForLastFrame = m_beginTimeHistoryInSec[(m_currentFrameNumber + kBeginFrameHistorySize - 1) % kBeginFrameHistorySize] -
- m_beginTimeHistoryInSec[(m_currentFrameNumber + kBeginFrameHistorySize - 2) % kBeginFrameHistorySize];
-
- // Filter the frame times to avoid spikes.
- const float alpha = 0.1;
- if (!m_filteredFrameTime) {
- if (m_currentFrameNumber == 2)
- m_filteredFrameTime = secForLastFrame;
- } else
- m_filteredFrameTime = ((1.0 - alpha) * m_filteredFrameTime) + (alpha * secForLastFrame);
-
- // Create & measure FPS text.
- String text(String::format("FPS: %5.1f", 1.0 / m_filteredFrameTime));
- TextRun run(text);
- float textWidth = m_mediumFont->width(run) + 2.0f;
- float graphWidth = kBeginFrameHistorySize;
-
- // Draw background.
- ctx->setFillColor(Color(0, 0, 0, 255), ColorSpaceDeviceRGB);
- ctx->fillRect(FloatRect(2, top, textWidth + graphWidth, height));
+ float textWidth = 170; // so text fits on linux.
+ float graphWidth = fpsCounter->timeStampHistorySize();
- // Draw FPS text.
- if (m_filteredFrameTime) {
- ctx->setFillColor(Color(255, 0, 0), ColorSpaceDeviceRGB);
- ctx->drawText(*m_mediumFont, run, IntPoint(3, top + height - 6));
- }
+ // Draw the FPS text.
+ drawFPSCounterText(context, fpsCounter, top, textWidth, height);
// Draw FPS graph.
- const double loFPS = 0.0;
- const double hiFPS = 120.0;
- ctx->setStrokeStyle(SolidStroke);
- ctx->setStrokeColor(Color(255, 0, 0), ColorSpaceDeviceRGB);
+ const double loFPS = 0;
+ const double hiFPS = 80;
+ context->setStrokeStyle(SolidStroke);
+ context->setFillColor(Color(154, 205, 50), ColorSpaceDeviceRGB);
+ context->fillRect(FloatRect(2 + textWidth, top, graphWidth, height / 2));
+ context->setFillColor(Color(255, 250, 205), ColorSpaceDeviceRGB);
+ context->fillRect(FloatRect(2 + textWidth, top + height / 2, graphWidth, height / 2));
+ context->setStrokeColor(Color(255, 0, 0), ColorSpaceDeviceRGB);
+ context->setFillColor(Color(255, 0, 0), ColorSpaceDeviceRGB);
+
int graphLeft = static_cast<int>(textWidth + 3);
IntPoint prev(-1, 0);
int x = 0;
double h = static_cast<double>(height - 2);
- for (int i = m_currentFrameNumber % kBeginFrameHistorySize; i != (m_currentFrameNumber - 1) % kBeginFrameHistorySize; i = (i + 1) % kBeginFrameHistorySize) {
- int j = (i + 1) % kBeginFrameHistorySize;
- double fps = 1.0 / (m_beginTimeHistoryInSec[j] - m_beginTimeHistoryInSec[i]);
+ for (int i = 0; i < fpsCounter->timeStampHistorySize() - 1; ++i) {
+ int j = i + 1;
+ double delta = fpsCounter->timeStampOfRecentFrame(j) - fpsCounter->timeStampOfRecentFrame(i);
+
+ // Skip plotting this particular instantaneous frame rate if it is not likely to have been valid.
+ if (fpsCounter->isBadFrameInterval(delta)) {
+ x += 1;
+ continue;
+ }
+
+ double fps = 1.0 / delta;
+
+ // Clamp the FPS to the range we want to plot visually.
double p = 1 - ((fps - loFPS) / (hiFPS - loFPS));
if (p < 0)
p = 0;
if (p > 1)
p = 1;
+
+ // Plot this data point.
IntPoint cur(graphLeft + x, 1 + top + p*h);
if (prev.x() != -1)
- ctx->drawLine(prev, cur);
+ context->drawLine(prev, cur);
prev = cur;
x += 1;
}
}
-void CCHeadsUpDisplay::drawPlatformLayerTree(GraphicsContext* ctx, int top)
+void CCHeadsUpDisplay::drawFPSCounterText(GraphicsContext* context, CCFrameRateCounter* fpsCounter, int top, int width, int height)
{
- float smallFontHeight = m_smallFont->fontMetrics().floatHeight();
- int y = top + smallFontHeight - 4;
- ctx->setFillColor(Color(255, 0, 0), ColorSpaceDeviceRGB);
- Vector<String> lines;
- m_layerRenderer->layerTreeAsText().split('\n', lines);
- for (size_t i = 0; i < lines.size(); ++i) {
- ctx->drawText(*m_smallFont, TextRun(lines[i]), IntPoint(2, y));
- y += smallFontHeight;
- }
+ double averageFPS, stdDeviation;
+ fpsCounter->getAverageFPSAndStandardDeviation(averageFPS, stdDeviation);
+
+ // Draw background.
+ context->setFillColor(Color(0, 0, 0, 255), ColorSpaceDeviceRGB);
+ context->fillRect(FloatRect(2, top, width, height));
+
+ // Draw FPS text.
+ if (m_fontAtlas)
+ m_fontAtlas->drawText(context, String::format("FPS: %4.1f +/- %3.1f", averageFPS, stdDeviation), IntPoint(10, height / 3), IntSize(width, height));
}
-const CCSettings& CCHeadsUpDisplay::settings() const
+void CCHeadsUpDisplay::drawDebugRects(GraphicsContext* context, CCDebugRectHistory* debugRectHistory, const CCSettings& settings)
{
- return m_layerRenderer->settings();
+ const Vector<CCDebugRect>& debugRects = debugRectHistory->debugRects();
+ for (size_t i = 0; i < debugRects.size(); ++i) {
+
+ if (debugRects[i].type == PaintRectType) {
+ // Paint rects in red
+ context->setStrokeColor(Color(255, 0, 0, 255), ColorSpaceDeviceRGB);
+ context->fillRect(debugRects[i].rect, Color(255, 0, 0, 30), ColorSpaceDeviceRGB);
+ context->strokeRect(debugRects[i].rect, 2.0);
+ }
+
+ if (debugRects[i].type == PropertyChangedRectType) {
+ // Property-changed rects in blue
+ context->setStrokeColor(Color(0, 0, 255, 255), ColorSpaceDeviceRGB);
+ context->fillRect(debugRects[i].rect, Color(0, 0, 255, 30), ColorSpaceDeviceRGB);
+ context->strokeRect(debugRects[i].rect, 2.0);
+ }
+
+ if (debugRects[i].type == SurfaceDamageRectType) {
+ // Surface damage rects in yellow-orange
+ context->setStrokeColor(Color(200, 100, 0, 255), ColorSpaceDeviceRGB);
+ context->fillRect(debugRects[i].rect, Color(200, 100, 0, 30), ColorSpaceDeviceRGB);
+ context->strokeRect(debugRects[i].rect, 2.0);
+ }
+ }
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h
index 05cb20d52..4831e5dd1 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h
@@ -27,61 +27,46 @@
#if USE(ACCELERATED_COMPOSITING)
-#include "Font.h"
-#include "ProgramBinding.h"
-#include "ShaderChromium.h"
+#include "cc/CCFontAtlas.h"
namespace WebCore {
-struct CCSettings;
-class GeometryBinding;
-class GraphicsContext3D;
-class LayerRendererChromium;
+class CCDebugRectHistory;
+class CCFrameRateCounter;
+class CCLayerTreeHostImpl;
+class GraphicsContext;
class ManagedTexture;
+struct CCSettings;
// Class that handles drawing of composited render layers using GL.
class CCHeadsUpDisplay {
WTF_MAKE_NONCOPYABLE(CCHeadsUpDisplay);
public:
- static PassOwnPtr<CCHeadsUpDisplay> create(LayerRendererChromium* owner)
+ static PassOwnPtr<CCHeadsUpDisplay> create()
{
- return adoptPtr(new CCHeadsUpDisplay(owner));
+ return adoptPtr(new CCHeadsUpDisplay());
}
~CCHeadsUpDisplay();
- int currentFrameNumber() const { return m_currentFrameNumber; }
-
- void onFrameBegin(double timestamp);
- void onSwapBuffers();
-
- bool enabled() const;
- void draw();
+ void setFontAtlas(PassOwnPtr<CCFontAtlas>);
- typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexSwizzleAlpha> Program;
+ bool enabled(const CCSettings&) const;
+ void draw(CCLayerTreeHostImpl*);
private:
- explicit CCHeadsUpDisplay(LayerRendererChromium* owner);
- void drawHudContents(GraphicsContext*, const IntSize& hudSize);
- void drawFPSCounter(GraphicsContext*, int top, int height);
- void drawPlatformLayerTree(GraphicsContext*, int top);
- const CCSettings& settings() const;
+ CCHeadsUpDisplay() { };
- int m_currentFrameNumber;
+ void drawHudContents(GraphicsContext*, CCLayerTreeHostImpl*, const CCSettings&, const IntSize& hudSize);
+ void drawFPSCounter(GraphicsContext*, CCFrameRateCounter*, int top, int height);
+ void drawFPSCounterText(GraphicsContext*, CCFrameRateCounter*, int top, int width, int height);
+ void drawDebugRects(GraphicsContext*, CCDebugRectHistory*, const CCSettings&);
- double m_filteredFrameTime;
+ bool showPlatformLayerTree(const CCSettings&) const;
+ bool showDebugRects(const CCSettings&) const;
OwnPtr<ManagedTexture> m_hudTexture;
-
- LayerRendererChromium* m_layerRenderer;
-
- static const int kBeginFrameHistorySize = 64;
- double m_beginTimeHistoryInSec[kBeginFrameHistorySize];
-
- OwnPtr<Font> m_smallFont;
- OwnPtr<Font> m_mediumFont;
-
- bool m_useMapSubForUploads;
+ OwnPtr<CCFontAtlas> m_fontAtlas;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCIOSurfaceDrawQuad.cpp
index 85289141d..2fdb4efcb 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCIOSurfaceDrawQuad.cpp
@@ -25,22 +25,18 @@
#include "config.h"
-#include "cc/CCPluginDrawQuad.h"
+#include "cc/CCIOSurfaceDrawQuad.h"
namespace WebCore {
-PassOwnPtr<CCPluginDrawQuad> CCPluginDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const FloatRect& uvRect, unsigned textureId, bool flipped, int ioSurfaceWidth, int ioSurfaceHeight, unsigned ioSurfaceTextureId)
+PassOwnPtr<CCIOSurfaceDrawQuad> CCIOSurfaceDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const IntSize& ioSurfaceSize, unsigned ioSurfaceTextureId)
{
- return adoptPtr(new CCPluginDrawQuad(sharedQuadState, quadRect, uvRect, textureId, flipped, ioSurfaceWidth, ioSurfaceHeight, ioSurfaceTextureId));
+ return adoptPtr(new CCIOSurfaceDrawQuad(sharedQuadState, quadRect, ioSurfaceSize, ioSurfaceTextureId));
}
-CCPluginDrawQuad::CCPluginDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const FloatRect& uvRect, unsigned textureId, bool flipped, int ioSurfaceWidth, int ioSurfaceHeight, unsigned ioSurfaceTextureId)
- : CCDrawQuad(sharedQuadState, CCDrawQuad::PluginContent, quadRect)
- , m_uvRect(uvRect)
- , m_textureId(textureId)
- , m_flipped(flipped)
- , m_ioSurfaceWidth(ioSurfaceWidth)
- , m_ioSurfaceHeight(ioSurfaceHeight)
+CCIOSurfaceDrawQuad::CCIOSurfaceDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const IntSize& ioSurfaceSize, unsigned ioSurfaceTextureId)
+ : CCDrawQuad(sharedQuadState, CCDrawQuad::IOSurfaceContent, quadRect)
+ , m_ioSurfaceSize(ioSurfaceSize)
, m_ioSurfaceTextureId(ioSurfaceTextureId)
{
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.h b/Source/WebCore/platform/graphics/chromium/cc/CCIOSurfaceDrawQuad.h
index 31a260d43..27f863ee6 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCIOSurfaceDrawQuad.h
@@ -23,37 +23,26 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef CCPluginDrawQuad_h
-#define CCPluginDrawQuad_h
+#ifndef CCIOSurfaceDrawQuad_h
+#define CCIOSurfaceDrawQuad_h
#include "cc/CCDrawQuad.h"
#include <wtf/PassOwnPtr.h>
namespace WebCore {
-class CCLayerImpl;
-
-class CCPluginDrawQuad : public CCDrawQuad {
- WTF_MAKE_NONCOPYABLE(CCPluginDrawQuad);
+class CCIOSurfaceDrawQuad : public CCDrawQuad {
+ WTF_MAKE_NONCOPYABLE(CCIOSurfaceDrawQuad);
public:
- static PassOwnPtr<CCPluginDrawQuad> create(const CCSharedQuadState*, const IntRect& quadRect, const FloatRect& uvRect, unsigned textureId, bool flipped, int ioSurfaceWidth, int ioSurfaceHeight, unsigned m_ioSurfaceTextureId);
-
- FloatRect uvRect() const { return m_uvRect; }
- unsigned textureId() const { return m_textureId; }
- bool flipped() const { return m_flipped; }
- int ioSurfaceWidth() const { return m_ioSurfaceWidth; }
- int ioSurfaceHeight() const { return m_ioSurfaceHeight; }
+ static PassOwnPtr<CCIOSurfaceDrawQuad> create(const CCSharedQuadState*, const IntRect&, const IntSize& ioSurfaceSize, unsigned ioSurfaceTextureId);
+ const IntSize& ioSurfaceSize() const { return m_ioSurfaceSize; }
unsigned ioSurfaceTextureId() const { return m_ioSurfaceTextureId; }
-
+
private:
- CCPluginDrawQuad(const CCSharedQuadState*, const IntRect& quadRect, const FloatRect& uvRect, unsigned textureId, bool flipped, int ioSurfaceWidth, int ioSurfaceHeight, unsigned ioSurfaceTextureId);
+ CCIOSurfaceDrawQuad(const CCSharedQuadState*, const IntRect&, const IntSize& ioSurfaceSize, unsigned ioSurfaceTextureId);
- FloatRect m_uvRect;
- unsigned m_textureId;
- bool m_flipped;
- int m_ioSurfaceWidth;
- int m_ioSurfaceHeight;
+ IntSize m_ioSurfaceSize;
unsigned m_ioSurfaceTextureId;
};
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCIOSurfaceLayerImpl.cpp
index 74538168e..95c32bdec 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCIOSurfaceLayerImpl.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,39 +27,36 @@
#if USE(ACCELERATED_COMPOSITING)
-#include "cc/CCPluginLayerImpl.h"
+#include "cc/CCIOSurfaceLayerImpl.h"
#include "Extensions3DChromium.h"
#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h"
-#include "cc/CCPluginDrawQuad.h"
+#include "cc/CCIOSurfaceDrawQuad.h"
#include "cc/CCProxy.h"
-#include <wtf/text/WTFString.h>
+#include "cc/CCQuadCuller.h"
namespace WebCore {
-CCPluginLayerImpl::CCPluginLayerImpl(int id)
+CCIOSurfaceLayerImpl::CCIOSurfaceLayerImpl(int id)
: CCLayerImpl(id)
- , m_textureId(0)
- , m_flipped(true)
- , m_uvRect(0, 0, 1, 1)
, m_ioSurfaceId(0)
- , m_ioSurfaceWidth(0)
- , m_ioSurfaceHeight(0)
, m_ioSurfaceChanged(false)
, m_ioSurfaceTextureId(0)
{
}
-CCPluginLayerImpl::~CCPluginLayerImpl()
+CCIOSurfaceLayerImpl::~CCIOSurfaceLayerImpl()
{
// FIXME: it seems there is no layer renderer / GraphicsContext3D available here. Ideally we
// would like to delete m_ioSurfaceTextureId.
m_ioSurfaceTextureId = 0;
}
-void CCPluginLayerImpl::willDraw(LayerRendererChromium* layerRenderer)
+void CCIOSurfaceLayerImpl::willDraw(LayerRendererChromium* layerRenderer)
{
+ CCLayerImpl::willDraw(layerRenderer);
+
if (m_ioSurfaceChanged) {
GraphicsContext3D* context = layerRenderer->context();
Extensions3DChromium* extensions = static_cast<Extensions3DChromium*>(context->getExtensions());
@@ -76,8 +73,8 @@ void CCPluginLayerImpl::willDraw(LayerRendererChromium* layerRenderer)
GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
extensions->texImageIOSurface2DCHROMIUM(Extensions3D::TEXTURE_RECTANGLE_ARB,
- m_ioSurfaceWidth,
- m_ioSurfaceHeight,
+ m_ioSurfaceSize.width(),
+ m_ioSurfaceSize.height(),
m_ioSurfaceId,
0);
// Do not check for error conditions. texImageIOSurface2DCHROMIUM is supposed to hold on to
@@ -90,39 +87,35 @@ void CCPluginLayerImpl::willDraw(LayerRendererChromium* layerRenderer)
}
}
-void CCPluginLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState)
+void CCIOSurfaceLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool&)
{
IntRect quadRect(IntPoint(), bounds());
- quadList.append(CCPluginDrawQuad::create(sharedQuadState, quadRect, m_uvRect, m_textureId, m_flipped, m_ioSurfaceWidth, m_ioSurfaceHeight, m_ioSurfaceTextureId));
+ quadList.append(CCIOSurfaceDrawQuad::create(sharedQuadState, quadRect, m_ioSurfaceSize, m_ioSurfaceTextureId));
}
-void CCPluginLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
+void CCIOSurfaceLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
{
writeIndent(ts, indent);
- ts << "plugin layer texture id: " << m_textureId << "\n";
+ ts << "iosurface id: " << m_ioSurfaceId << " texture id: " << m_ioSurfaceTextureId;
CCLayerImpl::dumpLayerProperties(ts, indent);
}
-void CCPluginLayerImpl::didLoseContext()
+void CCIOSurfaceLayerImpl::didLoseContext()
{
- if (m_ioSurfaceId) {
- // We don't have a valid texture ID in the new context; however,
- // the IOSurface is still valid.
- m_ioSurfaceTextureId = 0;
- m_ioSurfaceChanged = true;
- }
+ // We don't have a valid texture ID in the new context; however,
+ // the IOSurface is still valid.
+ m_ioSurfaceTextureId = 0;
+ m_ioSurfaceChanged = true;
}
-void CCPluginLayerImpl::setIOSurfaceProperties(int width, int height, uint32_t ioSurfaceId)
+void CCIOSurfaceLayerImpl::setIOSurfaceProperties(unsigned ioSurfaceId, const IntSize& size)
{
if (m_ioSurfaceId != ioSurfaceId)
m_ioSurfaceChanged = true;
- m_ioSurfaceWidth = width;
- m_ioSurfaceHeight = height;
m_ioSurfaceId = ioSurfaceId;
+ m_ioSurfaceSize = size;
+}
}
-
-} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCIOSurfaceLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCIOSurfaceLayerImpl.h
new file mode 100644
index 000000000..5d66496e1
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCIOSurfaceLayerImpl.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 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 CCIOSurfaceLayerImpl_h
+#define CCIOSurfaceLayerImpl_h
+
+#include "IntSize.h"
+#include "cc/CCLayerImpl.h"
+
+namespace WebCore {
+
+class CCIOSurfaceLayerImpl : public CCLayerImpl {
+public:
+ static PassOwnPtr<CCIOSurfaceLayerImpl> create(int id)
+ {
+ return adoptPtr(new CCIOSurfaceLayerImpl(id));
+ }
+ virtual ~CCIOSurfaceLayerImpl();
+
+ void setIOSurfaceProperties(unsigned ioSurfaceId, const IntSize&);
+
+ virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*, bool& hadMissingTiles) OVERRIDE;
+
+ virtual void willDraw(LayerRendererChromium*) OVERRIDE;
+ virtual void didLoseContext() OVERRIDE;
+
+ virtual void dumpLayerProperties(TextStream&, int indent) const OVERRIDE;
+
+private:
+ explicit CCIOSurfaceLayerImpl(int);
+
+ virtual const char* layerTypeAsString() const OVERRIDE { return "IOSurfaceLayer"; }
+
+ unsigned m_ioSurfaceId;
+ IntSize m_ioSurfaceSize;
+ bool m_ioSurfaceChanged;
+ unsigned m_ioSurfaceTextureId;
+};
+
+}
+
+#endif // CCIOSurfaceLayerImpl_h
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCInputHandler.h b/Source/WebCore/platform/graphics/chromium/cc/CCInputHandler.h
index 33721f1df..76608d9fc 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCInputHandler.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCInputHandler.h
@@ -29,6 +29,8 @@
namespace WebCore {
+class CCActiveGestureAnimation;
+class CCGestureCurveTarget;
class IntPoint;
class IntSize;
@@ -43,8 +45,6 @@ class IntSize;
class CCInputHandlerClient {
WTF_MAKE_NONCOPYABLE(CCInputHandlerClient);
public:
- virtual void setNeedsRedraw() = 0;
-
enum ScrollStatus { ScrollFailed, ScrollStarted, ScrollIgnored };
enum ScrollInputType { Gesture, Wheel };
@@ -75,6 +75,12 @@ public:
double startTime,
double duration) = 0;
+ virtual CCActiveGestureAnimation* activeGestureAnimation() = 0;
+ virtual void setActiveGestureAnimation(PassOwnPtr<CCActiveGestureAnimation>) = 0;
+
+ // Request another callback to CCInputHandler::animate().
+ virtual void scheduleAnimation() = 0;
+
protected:
CCInputHandlerClient() { }
virtual ~CCInputHandlerClient() { }
@@ -87,7 +93,7 @@ public:
virtual ~CCInputHandler() { }
virtual int identifier() const = 0;
- virtual void willDraw(double monotonicTime) = 0;
+ virtual void animate(double monotonicTime) = 0;
protected:
CCInputHandler() { }
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCKeyframedAnimationCurve.h b/Source/WebCore/platform/graphics/chromium/cc/CCKeyframedAnimationCurve.h
index c3073bf08..8d1f0e055 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCKeyframedAnimationCurve.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCKeyframedAnimationCurve.h
@@ -88,11 +88,11 @@ public:
void addKeyframe(PassOwnPtr<CCFloatKeyframe>);
// CCAnimationCurve implementation
- virtual double duration() const;
- virtual PassOwnPtr<CCAnimationCurve> clone() const;
+ virtual double duration() const OVERRIDE;
+ virtual PassOwnPtr<CCAnimationCurve> clone() const OVERRIDE;
// CCFloatAnimationCurve implementation
- virtual float getValue(double t) const;
+ virtual float getValue(double t) const OVERRIDE;
private:
CCKeyframedFloatAnimationCurve();
@@ -112,11 +112,11 @@ public:
void addKeyframe(PassOwnPtr<CCTransformKeyframe>);
// CCAnimationCurve implementation
- virtual double duration() const;
- virtual PassOwnPtr<CCAnimationCurve> clone() const;
+ virtual double duration() const OVERRIDE;
+ virtual PassOwnPtr<CCAnimationCurve> clone() const OVERRIDE;
// CCTransformAnimationCurve implementation
- virtual TransformationMatrix getValue(double t, const IntSize&) const;
+ virtual TransformationMatrix getValue(double t, const IntSize&) const OVERRIDE;
private:
CCKeyframedTransformAnimationCurve();
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp
index 335d3a58e..199192d52 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp
@@ -27,9 +27,9 @@
#include "cc/CCLayerAnimationController.h"
#include "GraphicsLayer.h" // for KeyframeValueList
+#include "TransformationMatrix.h"
#include "cc/CCActiveAnimation.h"
#include "cc/CCKeyframedAnimationCurve.h"
-#include "cc/CCLayerAnimationControllerImpl.h"
#include <wtf/CurrentTime.h>
#include <wtf/HashMap.h>
@@ -53,11 +53,7 @@ template <class Value, class Keyframe, class Curve>
PassOwnPtr<CCActiveAnimation> createActiveAnimation(const KeyframeValueList& valueList, const Animation* animation, size_t animationId, size_t groupId, double timeOffset, CCActiveAnimation::TargetProperty targetProperty)
{
// FIXME: add support for different directions.
- if (animation && animation->isDirectionSet() && animation->direction() == Animation::AnimationDirectionAlternate)
- return nullptr;
-
- // FIXME: add support for delay
- if (animation && animation->isDelaySet() && animation->delay() > 0)
+ if (animation && animation->isDirectionSet() && animation->direction() != Animation::AnimationDirectionNormal)
return nullptr;
// FIXME: add support for fills forwards and fills backwards
@@ -71,8 +67,15 @@ PassOwnPtr<CCActiveAnimation> createActiveAnimation(const KeyframeValueList& val
const Value* originalValue = static_cast<const Value*>(valueList.at(i));
OwnPtr<CCTimingFunction> timingFunction;
- if (originalValue->timingFunction()) {
- switch (originalValue->timingFunction()->type()) {
+ const TimingFunction* originalTimingFunction = originalValue->timingFunction();
+
+ // If there hasn't been a timing function associated with this keyframe, use the
+ // animation's timing function, if we have one.
+ if (!originalTimingFunction && animation->isTimingFunctionSet())
+ originalTimingFunction = animation->timingFunction().get();
+
+ if (originalTimingFunction) {
+ switch (originalTimingFunction->type()) {
case TimingFunction::StepsFunction:
// FIXME: add support for steps timing function.
return nullptr;
@@ -80,8 +83,8 @@ PassOwnPtr<CCActiveAnimation> createActiveAnimation(const KeyframeValueList& val
// Don't set the timing function. Keyframes are interpolated linearly if there is no timing function.
break;
case TimingFunction::CubicBezierFunction:
- const CubicBezierTimingFunction* originalTimingFunction = static_cast<const CubicBezierTimingFunction*>(originalValue->timingFunction());
- timingFunction = CCCubicBezierTimingFunction::create(originalTimingFunction->x1(), originalTimingFunction->y1(), originalTimingFunction->x2(), originalTimingFunction->y2());
+ const CubicBezierTimingFunction* originalBezierTimingFunction = static_cast<const CubicBezierTimingFunction*>(originalTimingFunction);
+ timingFunction = CCCubicBezierTimingFunction::create(originalBezierTimingFunction->x1(), originalBezierTimingFunction->y1(), originalBezierTimingFunction->x2(), originalBezierTimingFunction->y2());
break;
} // switch
} else
@@ -100,12 +103,20 @@ PassOwnPtr<CCActiveAnimation> createActiveAnimation(const KeyframeValueList& val
anim->setIterations(iterations);
}
+ // In order to avoid skew, the main thread animation cannot tick until it has received the start time of
+ // the corresponding impl thread animation.
+ anim->setNeedsSynchronizedStartTime(true);
+
+ // If timeOffset > 0, then the animation has started in the past.
+ anim->setTimeOffset(timeOffset);
+
return anim.release();
}
} // namepace
-CCLayerAnimationController::CCLayerAnimationController()
+CCLayerAnimationController::CCLayerAnimationController(CCLayerAnimationControllerClient* client)
+ : m_client(client)
{
}
@@ -113,9 +124,9 @@ CCLayerAnimationController::~CCLayerAnimationController()
{
}
-PassOwnPtr<CCLayerAnimationController> CCLayerAnimationController::create()
+PassOwnPtr<CCLayerAnimationController> CCLayerAnimationController::create(CCLayerAnimationControllerClient* client)
{
- return adoptPtr(new CCLayerAnimationController);
+ return adoptPtr(new CCLayerAnimationController(client));
}
bool CCLayerAnimationController::addAnimation(const KeyframeValueList& valueList, const IntSize&, const Animation* animation, int animationId, int groupId, double timeOffset)
@@ -130,6 +141,13 @@ bool CCLayerAnimationController::addAnimation(const KeyframeValueList& valueList
toAdd = createActiveAnimation<FloatAnimationValue, CCFloatKeyframe, CCKeyframedFloatAnimationCurve>(valueList, animation, animationId, groupId, timeOffset, CCActiveAnimation::Opacity);
if (toAdd.get()) {
+ // Remove any existing animations with the same animation id and target property.
+ for (size_t i = 0; i < m_activeAnimations.size();) {
+ if (m_activeAnimations[i]->id() == animationId && m_activeAnimations[i]->targetProperty() == toAdd->targetProperty())
+ m_activeAnimations.remove(i);
+ else
+ i++;
+ }
m_activeAnimations.append(toAdd.release());
return true;
}
@@ -141,7 +159,7 @@ void CCLayerAnimationController::pauseAnimation(int animationId, double timeOffs
{
for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
if (m_activeAnimations[i]->id() == animationId)
- m_activeAnimations[i]->setRunState(CCActiveAnimation::Paused, timeOffset);
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Paused, timeOffset + m_activeAnimations[i]->startTime());
}
}
@@ -156,43 +174,110 @@ void CCLayerAnimationController::removeAnimation(int animationId)
}
// According to render layer backing, these are for testing only.
-void CCLayerAnimationController::suspendAnimations(double time)
+void CCLayerAnimationController::suspendAnimations(double monotonicTime)
{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() != CCActiveAnimation::Finished && m_activeAnimations[i]->runState() != CCActiveAnimation::Aborted)
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Paused, monotonicTime);
+ }
}
// Looking at GraphicsLayerCA, this appears to be the analog to suspendAnimations, which is for testing.
-void CCLayerAnimationController::resumeAnimations()
+void CCLayerAnimationController::resumeAnimations(double monotonicTime)
{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() == CCActiveAnimation::Paused)
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime);
+ }
}
// Ensures that the list of active animations on the main thread and the impl thread
// are kept in sync.
-void CCLayerAnimationController::synchronizeAnimations(CCLayerAnimationControllerImpl* controllerImpl)
+void CCLayerAnimationController::pushAnimationUpdatesTo(CCLayerAnimationController* controllerImpl)
{
- removeCompletedAnimations(controllerImpl);
pushNewAnimationsToImplThread(controllerImpl);
removeAnimationsCompletedOnMainThread(controllerImpl);
- pushAnimationProperties(controllerImpl);
+ pushPropertiesToImplThread(controllerImpl);
+}
+
+void CCLayerAnimationController::animate(double monotonicTime, CCAnimationEventsVector* events)
+{
+ startAnimationsWaitingForNextTick(monotonicTime, events);
+ startAnimationsWaitingForStartTime(monotonicTime, events);
+ startAnimationsWaitingForTargetAvailability(monotonicTime, events);
+ resolveConflicts(monotonicTime);
+ tickAnimations(monotonicTime);
+ purgeFinishedAnimations(monotonicTime, events);
+ startAnimationsWaitingForTargetAvailability(monotonicTime, events);
+}
+
+void CCLayerAnimationController::add(PassOwnPtr<CCActiveAnimation> animation)
+{
+ m_activeAnimations.append(animation);
+}
+
+CCActiveAnimation* CCLayerAnimationController::getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty targetProperty) const
+{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i)
+ if (m_activeAnimations[i]->group() == groupId && m_activeAnimations[i]->targetProperty() == targetProperty)
+ return m_activeAnimations[i].get();
+ return 0;
+}
+
+bool CCLayerAnimationController::hasActiveAnimation() const
+{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() != CCActiveAnimation::Finished && m_activeAnimations[i]->runState() != CCActiveAnimation::Aborted)
+ return true;
+ }
+ return false;
}
-void CCLayerAnimationController::removeCompletedAnimations(CCLayerAnimationControllerImpl* controllerImpl)
+bool CCLayerAnimationController::isAnimatingProperty(CCActiveAnimation::TargetProperty targetProperty) const
{
- // Any animations finished on the impl thread are removed from the main thread's collection.
- for (size_t i = 0; i < controllerImpl->m_finishedAnimations.size(); ++i)
- remove(controllerImpl->m_finishedAnimations[i].groupId, controllerImpl->m_finishedAnimations[i].targetProperty);
- controllerImpl->m_finishedAnimations.clear();
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() != CCActiveAnimation::Finished && m_activeAnimations[i]->runState() != CCActiveAnimation::Aborted && m_activeAnimations[i]->targetProperty() == targetProperty)
+ return true;
+ }
+ return false;
}
-void CCLayerAnimationController::pushNewAnimationsToImplThread(CCLayerAnimationControllerImpl* controllerImpl)
+void CCLayerAnimationController::notifyAnimationStarted(const CCAnimationEvent& event)
+{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->group() == event.groupId && m_activeAnimations[i]->targetProperty() == event.targetProperty) {
+ ASSERT(m_activeAnimations[i]->needsSynchronizedStartTime());
+ m_activeAnimations[i]->setNeedsSynchronizedStartTime(false);
+ m_activeAnimations[i]->setStartTime(event.monotonicTime);
+ return;
+ }
+ }
+}
+
+void CCLayerAnimationController::pushNewAnimationsToImplThread(CCLayerAnimationController* controllerImpl) const
{
// Any new animations owned by the main thread's controller are cloned and adde to the impl thread's controller.
for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (!controllerImpl->getActiveAnimation(m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty()))
- controllerImpl->add(m_activeAnimations[i]->cloneForImplThread());
+ // If the animation is already running on the impl thread, there is no need to copy it over.
+ if (controllerImpl->getActiveAnimation(m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty()))
+ continue;
+
+ // If the animation is not running on the impl thread, it does not necessarily mean that it needs
+ // to be copied over and started; it may have already finished. In this case, the impl thread animation
+ // will have already notified that it has started and the main thread animation will no longer need
+ // a synchronized start time.
+ if (!m_activeAnimations[i]->needsSynchronizedStartTime())
+ continue;
+
+ OwnPtr<CCActiveAnimation> toAdd(m_activeAnimations[i]->cloneForImplThread());
+ ASSERT(!toAdd->needsSynchronizedStartTime());
+ // The new animation should be set to run as soon as possible.
+ toAdd->setRunState(CCActiveAnimation::WaitingForTargetAvailability, 0);
+ controllerImpl->add(toAdd.release());
}
}
-void CCLayerAnimationController::removeAnimationsCompletedOnMainThread(CCLayerAnimationControllerImpl* controllerImpl)
+void CCLayerAnimationController::removeAnimationsCompletedOnMainThread(CCLayerAnimationController* controllerImpl) const
{
// Delete all impl thread animations for which there is no corresponding main thread animation.
// Each iteration, controller->m_activeAnimations.size() is decremented or i is incremented
@@ -206,34 +291,178 @@ void CCLayerAnimationController::removeAnimationsCompletedOnMainThread(CCLayerAn
}
}
-void CCLayerAnimationController::pushAnimationProperties(CCLayerAnimationControllerImpl* controllerImpl)
+void CCLayerAnimationController::pushPropertiesToImplThread(CCLayerAnimationController* controllerImpl) const
{
- // Delete all impl thread animations for which there is no corresponding main thread animation.
- // Each iteration, controller->m_activeAnimations.size() is decremented or i is incremented
- // guaranteeing progress towards loop termination.
- for (size_t i = 0; i < controllerImpl->m_activeAnimations.size(); ++i) {
- CCActiveAnimation* currentImpl = controllerImpl->m_activeAnimations[i].get();
- CCActiveAnimation* current = getActiveAnimation(currentImpl->group(), currentImpl->targetProperty());
- ASSERT(current);
- if (current)
- current->synchronizeProperties(currentImpl);
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ CCActiveAnimation* currentImpl = controllerImpl->getActiveAnimation(m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty());
+ if (currentImpl)
+ m_activeAnimations[i]->pushPropertiesTo(currentImpl);
}
}
-CCActiveAnimation* CCLayerAnimationController::getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty targetProperty)
+void CCLayerAnimationController::startAnimationsWaitingForNextTick(double monotonicTime, CCAnimationEventsVector* events)
{
- for (size_t i = 0; i < m_activeAnimations.size(); ++i)
- if (m_activeAnimations[i]->group() == groupId && m_activeAnimations[i]->targetProperty() == targetProperty)
- return m_activeAnimations[i].get();
- return 0;
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForNextTick) {
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime);
+ if (!m_activeAnimations[i]->hasSetStartTime())
+ m_activeAnimations[i]->setStartTime(monotonicTime);
+ if (events)
+ events->append(CCAnimationEvent(CCAnimationEvent::Started, m_client->id(), m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime));
+ }
+ }
}
-void CCLayerAnimationController::remove(int groupId, CCActiveAnimation::TargetProperty targetProperty)
+void CCLayerAnimationController::startAnimationsWaitingForStartTime(double monotonicTime, CCAnimationEventsVector* events)
{
for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->group() == groupId && m_activeAnimations[i]->targetProperty() == targetProperty) {
- m_activeAnimations.remove(i);
- return;
+ if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForStartTime && m_activeAnimations[i]->startTime() <= monotonicTime) {
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime);
+ if (events)
+ events->append(CCAnimationEvent(CCAnimationEvent::Started, m_client->id(), m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime));
+ }
+ }
+}
+
+void CCLayerAnimationController::startAnimationsWaitingForTargetAvailability(double monotonicTime, CCAnimationEventsVector* events)
+{
+ // First collect running properties.
+ TargetProperties blockedProperties;
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running || m_activeAnimations[i]->runState() == CCActiveAnimation::Finished)
+ blockedProperties.add(m_activeAnimations[i]->targetProperty());
+ }
+
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForTargetAvailability) {
+ // Collect all properties for animations with the same group id (they should all also be in the list of animations).
+ TargetProperties enqueuedProperties;
+ enqueuedProperties.add(m_activeAnimations[i]->targetProperty());
+ for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
+ if (m_activeAnimations[i]->group() == m_activeAnimations[j]->group())
+ enqueuedProperties.add(m_activeAnimations[j]->targetProperty());
+ }
+
+ // Check to see if intersection of the list of properties affected by the group and the list of currently
+ // blocked properties is null. In any case, the group's target properties need to be added to the list
+ // of blocked properties.
+ bool nullIntersection = true;
+ for (TargetProperties::iterator pIter = enqueuedProperties.begin(); pIter != enqueuedProperties.end(); ++pIter) {
+ if (!blockedProperties.add(*pIter).isNewEntry)
+ nullIntersection = false;
+ }
+
+ // If the intersection is null, then we are free to start the animations in the group.
+ if (nullIntersection) {
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime);
+ if (!m_activeAnimations[i]->hasSetStartTime())
+ m_activeAnimations[i]->setStartTime(monotonicTime);
+ if (events)
+ events->append(CCAnimationEvent(CCAnimationEvent::Started, m_client->id(), m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime));
+ for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
+ if (m_activeAnimations[i]->group() == m_activeAnimations[j]->group()) {
+ m_activeAnimations[j]->setRunState(CCActiveAnimation::Running, monotonicTime);
+ if (!m_activeAnimations[j]->hasSetStartTime())
+ m_activeAnimations[j]->setStartTime(monotonicTime);
+ }
+ }
+ }
+ }
+ }
+}
+
+void CCLayerAnimationController::resolveConflicts(double monotonicTime)
+{
+ // Find any animations that are animating the same property and resolve the
+ // confict. We could eventually blend, but for now we'll just abort the
+ // previous animation (where 'previous' means: (1) has a prior start time or
+ // (2) has an equal start time, but was added to the queue earlier, i.e.,
+ // has a lower index in m_activeAnimations).
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running) {
+ for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
+ if (m_activeAnimations[j]->runState() == CCActiveAnimation::Running && m_activeAnimations[i]->targetProperty() == m_activeAnimations[j]->targetProperty()) {
+ if (m_activeAnimations[i]->startTime() > m_activeAnimations[j]->startTime())
+ m_activeAnimations[j]->setRunState(CCActiveAnimation::Aborted, monotonicTime);
+ else
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Aborted, monotonicTime);
+ }
+ }
+ }
+ }
+}
+
+void CCLayerAnimationController::purgeFinishedAnimations(double monotonicTime, CCAnimationEventsVector* events)
+{
+ // Each iteration, m_activeAnimations.size() decreases or i increments,
+ // guaranteeing progress towards loop termination.
+ size_t i = 0;
+ while (i < m_activeAnimations.size()) {
+ int groupId = m_activeAnimations[i]->group();
+ bool allAnimsWithSameIdAreFinished = false;
+ if (m_activeAnimations[i]->isFinished()) {
+ allAnimsWithSameIdAreFinished = true;
+ for (size_t j = 0; j < m_activeAnimations.size(); ++j) {
+ if (groupId == m_activeAnimations[j]->group() && !m_activeAnimations[j]->isFinished()) {
+ allAnimsWithSameIdAreFinished = false;
+ break;
+ }
+ }
+ }
+ if (allAnimsWithSameIdAreFinished) {
+ // We now need to remove all animations with the same group id as groupId
+ // (and send along animation finished notifications, if necessary).
+ // Each iteration, m_activeAnimations.size() decreases or j increments,
+ // guaranteeing progress towards loop termination. Also, we are guaranteed
+ // to remove at least one active animation.
+ for (size_t j = i; j < m_activeAnimations.size();) {
+ if (groupId != m_activeAnimations[j]->group())
+ j++;
+ else {
+ if (events)
+ events->append(CCAnimationEvent(CCAnimationEvent::Finished, m_client->id(), m_activeAnimations[j]->group(), m_activeAnimations[j]->targetProperty(), monotonicTime));
+ m_activeAnimations.remove(j);
+ }
+ }
+ } else
+ i++;
+ }
+}
+
+void CCLayerAnimationController::tickAnimations(double monotonicTime)
+{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running || m_activeAnimations[i]->runState() == CCActiveAnimation::Paused) {
+ double trimmed = m_activeAnimations[i]->trimTimeToCurrentIteration(monotonicTime);
+
+ // Animation assumes its initial value until it gets the synchronized start time
+ // from the impl thread and can start ticking.
+ if (m_activeAnimations[i]->needsSynchronizedStartTime())
+ trimmed = 0;
+
+ switch (m_activeAnimations[i]->targetProperty()) {
+
+ case CCActiveAnimation::Transform: {
+ const CCTransformAnimationCurve* transformAnimationCurve = m_activeAnimations[i]->curve()->toTransformAnimationCurve();
+ const TransformationMatrix matrix = transformAnimationCurve->getValue(trimmed, m_client->bounds());
+ if (m_activeAnimations[i]->isFinishedAt(monotonicTime))
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, monotonicTime);
+
+ m_client->setTransformFromAnimation(matrix);
+ break;
+ }
+
+ case CCActiveAnimation::Opacity: {
+ const CCFloatAnimationCurve* floatAnimationCurve = m_activeAnimations[i]->curve()->toFloatAnimationCurve();
+ const float opacity = floatAnimationCurve->getValue(trimmed);
+ if (m_activeAnimations[i]->isFinishedAt(monotonicTime))
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, monotonicTime);
+
+ m_client->setOpacityFromAnimation(opacity);
+ break;
+ }
+
+ }
}
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.h
index 068213047..e22f8054d 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.h
@@ -26,50 +26,89 @@
#define CCLayerAnimationController_h
#include "cc/CCActiveAnimation.h"
+#include "cc/CCAnimationCurve.h"
+#include "cc/CCAnimationEvents.h"
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>
-
namespace WebCore {
class Animation;
-class CCLayerAnimationControllerImpl;
class IntSize;
class KeyframeValueList;
+class TransformationMatrix;
+
+class CCLayerAnimationControllerClient {
+public:
+ virtual ~CCLayerAnimationControllerClient() { }
+
+ virtual int id() const = 0;
+ virtual void setOpacityFromAnimation(float) = 0;
+ virtual float opacity() const = 0;
+ virtual void setTransformFromAnimation(const TransformationMatrix&) = 0;
+ virtual const TransformationMatrix& transform() const = 0;
+ virtual const IntSize& bounds() const = 0;
+};
class CCLayerAnimationController {
WTF_MAKE_NONCOPYABLE(CCLayerAnimationController);
public:
- static PassOwnPtr<CCLayerAnimationController> create();
+ static PassOwnPtr<CCLayerAnimationController> create(CCLayerAnimationControllerClient*);
virtual ~CCLayerAnimationController();
- // These are virtual for testing.
+ // These methods are virtual for testing.
virtual bool addAnimation(const KeyframeValueList&, const IntSize& boxSize, const Animation*, int animationId, int groupId, double timeOffset);
virtual void pauseAnimation(int animationId, double timeOffset);
virtual void removeAnimation(int animationId);
- virtual void suspendAnimations(double time);
- virtual void resumeAnimations();
+ virtual void suspendAnimations(double monotonicTime);
+ virtual void resumeAnimations(double monotonicTime);
// Ensures that the list of active animations on the main thread and the impl thread
// are kept in sync. This function does not take ownership of the impl thread controller.
- virtual void synchronizeAnimations(CCLayerAnimationControllerImpl*);
+ virtual void pushAnimationUpdatesTo(CCLayerAnimationController*);
+
+ void animate(double monotonicTime, CCAnimationEventsVector*);
+
+ void add(PassOwnPtr<CCActiveAnimation>);
- bool hasActiveAnimation() const { return m_activeAnimations.size(); }
- CCActiveAnimation* getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty);
+ // Returns the active animation in the given group, animating the given property if such an
+ // animation exists.
+ CCActiveAnimation* getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty) const;
+
+ // Returns true if there are any animations that have neither finished nor aborted.
+ bool hasActiveAnimation() const;
+
+ // Returns true if there is an animation currently animating the given property, or
+ // if there is an animation scheduled to animate this property in the future.
+ bool isAnimatingProperty(CCActiveAnimation::TargetProperty) const;
+
+ // This is called in response to an animation being started on the impl thread. This
+ // function updates the corresponding main thread animation's start time.
+ void notifyAnimationStarted(const CCAnimationEvent&);
protected:
- CCLayerAnimationController();
+ explicit CCLayerAnimationController(CCLayerAnimationControllerClient*);
private:
- void removeCompletedAnimations(CCLayerAnimationControllerImpl*);
- void pushNewAnimationsToImplThread(CCLayerAnimationControllerImpl*);
- void removeAnimationsCompletedOnMainThread(CCLayerAnimationControllerImpl*);
- void pushAnimationProperties(CCLayerAnimationControllerImpl*);
+ typedef HashSet<int> TargetProperties;
+
+ void pushNewAnimationsToImplThread(CCLayerAnimationController*) const;
+ void removeAnimationsCompletedOnMainThread(CCLayerAnimationController*) const;
+ void pushPropertiesToImplThread(CCLayerAnimationController*) const;
+
+ void startAnimationsWaitingForNextTick(double monotonicTime, CCAnimationEventsVector*);
+ void startAnimationsWaitingForStartTime(double monotonicTime, CCAnimationEventsVector*);
+ void startAnimationsWaitingForTargetAvailability(double monotonicTime, CCAnimationEventsVector*);
+ void resolveConflicts(double monotonicTime);
+ void purgeFinishedAnimations(double monotonicTime, CCAnimationEventsVector*);
- void remove(int groupId, CCActiveAnimation::TargetProperty);
+ void tickAnimations(double monotonicTime);
+ CCLayerAnimationControllerClient* m_client;
Vector<OwnPtr<CCActiveAnimation> > m_activeAnimations;
};
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp
deleted file mode 100644
index f09dcfae0..000000000
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include "cc/CCLayerAnimationControllerImpl.h"
-
-#include "TransformationMatrix.h"
-#include "TransformOperations.h"
-
-namespace WebCore {
-
-// A collection of properties. Used when deterimining if animations waiting for target
-// availibility are able to run.
-typedef HashSet<int> TargetProperties;
-
-PassOwnPtr<CCLayerAnimationControllerImpl> CCLayerAnimationControllerImpl::create(CCLayerAnimationControllerImplClient* client)
-{
- return adoptPtr(new CCLayerAnimationControllerImpl(client));
-}
-
-CCLayerAnimationControllerImpl::CCLayerAnimationControllerImpl(CCLayerAnimationControllerImplClient* client)
- : m_client(client)
-{
-}
-
-CCLayerAnimationControllerImpl::~CCLayerAnimationControllerImpl()
-{
-}
-
-void CCLayerAnimationControllerImpl::animate(double monotonicTime, CCAnimationEventsVector& events)
-{
- startAnimationsWaitingForNextTick(monotonicTime, events);
- startAnimationsWaitingForStartTime(monotonicTime, events);
- startAnimationsWaitingForTargetAvailability(monotonicTime, events);
- resolveConflicts(monotonicTime);
- tickAnimations(monotonicTime);
- purgeFinishedAnimations(events);
- startAnimationsWaitingForTargetAvailability(monotonicTime, events);
-}
-
-void CCLayerAnimationControllerImpl::add(PassOwnPtr<CCActiveAnimation> anim)
-{
- m_activeAnimations.append(anim);
-}
-
-CCActiveAnimation* CCLayerAnimationControllerImpl::getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty property)
-{
- for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->group() == groupId && m_activeAnimations[i]->targetProperty() == property)
- return m_activeAnimations[i].get();
- }
- return 0;
-}
-
-bool CCLayerAnimationControllerImpl::hasActiveAnimation() const
-{
- for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->runState() != CCActiveAnimation::Finished && m_activeAnimations[i]->runState() != CCActiveAnimation::Aborted)
- return true;
- }
- return false;
-}
-
-void CCLayerAnimationControllerImpl::startAnimationsWaitingForNextTick(double monotonicTime, CCAnimationEventsVector& events)
-{
- for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForNextTick) {
- m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime);
- m_activeAnimations[i]->setStartTime(monotonicTime);
- events.append(CCAnimationStartedEvent::create(m_client->id()));
- }
- }
-}
-
-void CCLayerAnimationControllerImpl::startAnimationsWaitingForStartTime(double monotonicTime, CCAnimationEventsVector& events)
-{
- for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForStartTime && m_activeAnimations[i]->startTime() <= monotonicTime) {
- m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime);
- events.append(CCAnimationStartedEvent::create(m_client->id()));
- }
- }
-}
-
-void CCLayerAnimationControllerImpl::startAnimationsWaitingForTargetAvailability(double monotonicTime, CCAnimationEventsVector& events)
-{
- // First collect running properties.
- TargetProperties blockedProperties;
- for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running || m_activeAnimations[i]->runState() == CCActiveAnimation::Finished)
- blockedProperties.add(m_activeAnimations[i]->targetProperty());
- }
-
- for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForTargetAvailability) {
- // Collect all properties for animations with the same group id (they should all also be in the list of animations).
- TargetProperties enqueuedProperties;
- enqueuedProperties.add(m_activeAnimations[i]->targetProperty());
- for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
- if (m_activeAnimations[i]->group() == m_activeAnimations[j]->group())
- enqueuedProperties.add(m_activeAnimations[j]->targetProperty());
- }
-
- // Check to see if intersection of the list of properties affected by the group and the list of currently
- // blocked properties is null. In any case, the group's target properties need to be added to the list
- // of blocked properties.
- bool nullIntersection = true;
- for (TargetProperties::iterator pIter = enqueuedProperties.begin(); pIter != enqueuedProperties.end(); ++pIter) {
- if (!blockedProperties.add(*pIter).second)
- nullIntersection = false;
- }
-
- // If the intersection is null, then we are free to start the animations in the group.
- if (nullIntersection) {
- m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime);
- m_activeAnimations[i]->setStartTime(monotonicTime);
- events.append(CCAnimationStartedEvent::create(m_client->id()));
- for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
- if (m_activeAnimations[i]->group() == m_activeAnimations[j]->group()) {
- m_activeAnimations[j]->setRunState(CCActiveAnimation::Running, monotonicTime);
- m_activeAnimations[j]->setStartTime(monotonicTime);
- }
- }
- }
- }
- }
-}
-
-void CCLayerAnimationControllerImpl::resolveConflicts(double monotonicTime)
-{
- // Find any animations that are animating the same property and resolve the
- // confict. We could eventually blend, but for now we'll just abort the
- // previous animation (where 'previous' means: (1) has a prior start time or
- // (2) has an equal start time, but was added to the queue earlier, i.e.,
- // has a lower index in m_activeAnimations).
- for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running) {
- for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
- if (m_activeAnimations[j]->runState() == CCActiveAnimation::Running && m_activeAnimations[i]->targetProperty() == m_activeAnimations[j]->targetProperty()) {
- if (m_activeAnimations[i]->startTime() > m_activeAnimations[j]->startTime())
- m_activeAnimations[j]->setRunState(CCActiveAnimation::Aborted, monotonicTime);
- else
- m_activeAnimations[i]->setRunState(CCActiveAnimation::Aborted, monotonicTime);
- }
- }
- }
- }
-}
-
-void CCLayerAnimationControllerImpl::purgeFinishedAnimations(CCAnimationEventsVector& events)
-{
- // Each iteration, m_activeAnimations.size() decreases or i increments,
- // guaranteeing progress towards loop termination.
- size_t i = 0;
- while (i < m_activeAnimations.size()) {
- bool allAnimsWithSameIdAreFinished = false;
- if (m_activeAnimations[i]->isFinished()) {
- allAnimsWithSameIdAreFinished = true;
- for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
- if (m_activeAnimations[i]->group() == m_activeAnimations[j]->group() && !m_activeAnimations[j]->isFinished()) {
- allAnimsWithSameIdAreFinished = false;
- break;
- }
- }
- }
- if (allAnimsWithSameIdAreFinished) {
- events.append(CCAnimationFinishedEvent::create(m_client->id(), m_activeAnimations[i]->id()));
- m_finishedAnimations.append(m_activeAnimations[i]->signature());
- m_activeAnimations.remove(i);
- } else
- i++;
- }
-}
-
-void CCLayerAnimationControllerImpl::tickAnimations(double monotonicTime)
-{
- for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running) {
- double trimmed = m_activeAnimations[i]->trimTimeToCurrentIteration(monotonicTime);
-
- switch (m_activeAnimations[i]->targetProperty()) {
-
- case CCActiveAnimation::Transform: {
- const CCTransformAnimationCurve* transformAnimationCurve = m_activeAnimations[i]->curve()->toTransformAnimationCurve();
- const TransformationMatrix matrix = transformAnimationCurve->getValue(trimmed, m_client->bounds());
- if (m_activeAnimations[i]->isFinishedAt(monotonicTime))
- m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, monotonicTime);
-
- m_client->setTransform(matrix);
- break;
- }
-
- case CCActiveAnimation::Opacity: {
- const CCFloatAnimationCurve* floatAnimationCurve = m_activeAnimations[i]->curve()->toFloatAnimationCurve();
- const float opacity = floatAnimationCurve->getValue(trimmed);
- if (m_activeAnimations[i]->isFinishedAt(monotonicTime))
- m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, monotonicTime);
-
- m_client->setOpacity(opacity);
- break;
- }
-
- } // switch
- } // if running
- } // for each animation
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.h
deleted file mode 100644
index 6ac00e7ae..000000000
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CCLayerAnimationControllerImpl_h
-#define CCLayerAnimationControllerImpl_h
-
-#include "cc/CCActiveAnimation.h"
-#include "cc/CCAnimationCurve.h"
-#include "cc/CCAnimationEvents.h"
-
-#include <wtf/HashSet.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
-#include <wtf/Vector.h>
-
-namespace WebCore {
-
-class CCLayerAnimationControllerImpl;
-class IntSize;
-class TransformationMatrix;
-class TransformOperations;
-
-class CCLayerAnimationControllerImplClient {
-public:
- virtual ~CCLayerAnimationControllerImplClient() { }
-
- virtual int id() const = 0;
- virtual float opacity() const = 0;
- virtual void setOpacity(float) = 0;
- virtual const TransformationMatrix& transform() const = 0;
- virtual void setTransform(const TransformationMatrix&) = 0;
- virtual const IntSize& bounds() const = 0;
-};
-
-class CCLayerAnimationControllerImpl {
- WTF_MAKE_NONCOPYABLE(CCLayerAnimationControllerImpl);
-public:
- static PassOwnPtr<CCLayerAnimationControllerImpl> create(CCLayerAnimationControllerImplClient*);
-
- virtual ~CCLayerAnimationControllerImpl();
-
- void animate(double monotonicTime, CCAnimationEventsVector&);
-
- void add(PassOwnPtr<CCActiveAnimation>);
-
- // Returns the active animation in the given group, animating the given property if such an
- // animation exists.
- CCActiveAnimation* getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty);
-
- // Returns true if there are any animations that are neither finished nor aborted.
- bool hasActiveAnimation() const;
-
-private:
- friend class CCLayerAnimationController;
-
- // The animator is owned by the layer.
- explicit CCLayerAnimationControllerImpl(CCLayerAnimationControllerImplClient*);
-
- void startAnimationsWaitingForNextTick(double monotonicTime, CCAnimationEventsVector&);
- void startAnimationsWaitingForStartTime(double monotonicTime, CCAnimationEventsVector&);
- void startAnimationsWaitingForTargetAvailability(double monotonicTime, CCAnimationEventsVector&);
- void resolveConflicts(double monotonicTime);
- void purgeFinishedAnimations(CCAnimationEventsVector&);
-
- void tickAnimations(double monotonicTime);
-
- CCLayerAnimationControllerImplClient* m_client;
- Vector<OwnPtr<CCActiveAnimation> > m_activeAnimations;
- Vector<CCActiveAnimation::AnimationSignature> m_finishedAnimations;
-};
-
-} // namespace WebCore
-
-#endif // CCLayerAnimationControllerImpl_h
-
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationDelegate.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationDelegate.h
index a764cc37b..06b21d3d1 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationDelegate.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationDelegate.h
@@ -31,7 +31,7 @@ namespace WebCore {
class CCLayerAnimationDelegate {
public:
virtual void notifyAnimationStarted(double time) = 0;
- virtual void notifyAnimationFinished(int animationId) = 0;
+ virtual void notifyAnimationFinished(double time) = 0;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp
index 8f6078097..6ee9aa71d 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp
@@ -33,8 +33,8 @@
#include "LayerChromium.h"
#include "LayerRendererChromium.h"
#include "cc/CCDebugBorderDrawQuad.h"
-#include "cc/CCLayerAnimationControllerImpl.h"
#include "cc/CCLayerSorter.h"
+#include "cc/CCQuadCuller.h"
#include "cc/CCSolidColorDrawQuad.h"
#include <wtf/text/WTFString.h>
@@ -50,13 +50,13 @@ CCLayerImpl::CCLayerImpl(int id)
, m_scrollable(false)
, m_shouldScrollOnMainThread(false)
, m_haveWheelEventHandlers(false)
- , m_backgroundCoversViewport(false)
, m_doubleSided(true)
, m_layerPropertyChanged(false)
, m_masksToBounds(false)
, m_opaque(false)
, m_opacity(1.0)
, m_preserves3D(false)
+ , m_drawCheckerboardForMissingTiles(false)
, m_usesLayerClipping(false)
, m_isNonCompositedContent(false)
, m_drawsContent(false)
@@ -64,9 +64,15 @@ CCLayerImpl::CCLayerImpl(int id)
, m_targetRenderSurface(0)
, m_drawDepth(0)
, m_drawOpacity(0)
+ , m_drawOpacityIsAnimating(false)
, m_debugBorderColor(0, 0, 0, 0)
, m_debugBorderWidth(0)
- , m_layerAnimationController(CCLayerAnimationControllerImpl::create(this))
+ , m_drawTransformIsAnimating(false)
+ , m_screenSpaceTransformIsAnimating(false)
+#ifndef NDEBUG
+ , m_betweenWillDrawAndDidDraw(false)
+#endif
+ , m_layerAnimationController(CCLayerAnimationController::create(this))
{
ASSERT(CCProxy::isImplThread());
}
@@ -74,6 +80,9 @@ CCLayerImpl::CCLayerImpl(int id)
CCLayerImpl::~CCLayerImpl()
{
ASSERT(CCProxy::isImplThread());
+#ifndef NDEBUG
+ ASSERT(!m_betweenWillDrawAndDidDraw);
+#endif
}
void CCLayerImpl::addChild(PassOwnPtr<CCLayerImpl> child)
@@ -133,44 +142,24 @@ PassOwnPtr<CCSharedQuadState> CCLayerImpl::createSharedQuadState() const
return CCSharedQuadState::create(quadTransform(), drawTransform(), visibleLayerRect(), layerClipRect, drawOpacity(), opaque());
}
-void CCLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState)
+void CCLayerImpl::willDraw(LayerRendererChromium*)
{
- appendGutterQuads(quadList, sharedQuadState);
+#ifndef NDEBUG
+ // willDraw/didDraw must be matched.
+ ASSERT(!m_betweenWillDrawAndDidDraw);
+ m_betweenWillDrawAndDidDraw = true;
+#endif
}
-void CCLayerImpl::appendGutterQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState)
+void CCLayerImpl::didDraw()
{
- if (!backgroundCoversViewport() || !backgroundColor().isValid())
- return;
-
- const IntRect& layerRect = visibleLayerRect();
- IntRect clip = screenSpaceTransform().inverse().mapRect(clipRect());
-
- if (layerRect.isEmpty()) {
- quadList.append(CCSolidColorDrawQuad::create(sharedQuadState, clip, backgroundColor()));
- return;
- }
-
- IntRect gutterRects[4];
- for (int i = 0; i < 4; i++)
- gutterRects[i] = clip;
- gutterRects[0].shiftMaxYEdgeTo(layerRect.y());
- gutterRects[1].shiftYEdgeTo(layerRect.maxY());
- gutterRects[2].shiftMaxXEdgeTo(layerRect.x());
- gutterRects[3].shiftXEdgeTo(layerRect.maxX());
-
- gutterRects[2].shiftYEdgeTo(layerRect.y());
- gutterRects[3].shiftYEdgeTo(layerRect.y());
- gutterRects[2].shiftMaxYEdgeTo(layerRect.maxY());
- gutterRects[3].shiftMaxYEdgeTo(layerRect.maxY());
-
- for (int i = 0; i < 4; i++) {
- if (!gutterRects[i].isEmpty())
- quadList.append(CCSolidColorDrawQuad::create(sharedQuadState, gutterRects[i], backgroundColor()));
- }
+#ifndef NDEBUG
+ ASSERT(m_betweenWillDrawAndDidDraw);
+ m_betweenWillDrawAndDidDraw = false;
+#endif
}
-void CCLayerImpl::appendDebugBorderQuad(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState) const
+void CCLayerImpl::appendDebugBorderQuad(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState) const
{
if (!hasDebugBorders())
return;
@@ -184,9 +173,9 @@ void CCLayerImpl::bindContentsTexture(LayerRendererChromium*)
ASSERT_NOT_REACHED();
}
-void CCLayerImpl::scrollBy(const IntSize& scroll)
+void CCLayerImpl::scrollBy(const FloatSize& scroll)
{
- IntSize newDelta = m_scrollDelta + scroll;
+ FloatSize newDelta = m_scrollDelta + scroll;
IntSize minDelta = -toSize(m_scrollPosition);
IntSize maxDelta = m_maxScrollPosition - toSize(m_scrollPosition);
// Clamp newDelta so that position + delta stays within scroll bounds.
@@ -276,6 +265,13 @@ void CCLayerImpl::dumpLayer(TextStream& ts, int indent) const
m_children[i]->dumpLayer(ts, indent+1);
}
+void CCLayerImpl::setStackingOrderChanged(bool stackingOrderChanged)
+{
+ // We don't need to store this flag; we only need to track that the change occurred.
+ if (stackingOrderChanged)
+ noteLayerPropertyChangedForSubtree();
+}
+
void CCLayerImpl::noteLayerPropertyChangedForSubtree()
{
m_layerPropertyChanged = true;
@@ -306,6 +302,16 @@ void CCLayerImpl::resetAllChangeTrackingForSubtree()
m_children[i]->resetAllChangeTrackingForSubtree();
}
+void CCLayerImpl::setOpacityFromAnimation(float opacity)
+{
+ setOpacity(opacity);
+}
+
+void CCLayerImpl::setTransformFromAnimation(const TransformationMatrix& transform)
+{
+ setTransform(transform);
+}
+
void CCLayerImpl::setBounds(const IntSize& bounds)
{
if (m_bounds == bounds)
@@ -379,22 +385,22 @@ void CCLayerImpl::setBackgroundColor(const Color& backgroundColor)
m_layerPropertyChanged = true;
}
-void CCLayerImpl::setBackgroundCoversViewport(bool backgroundCoversViewport)
+void CCLayerImpl::setFilters(const FilterOperations& filters)
{
- if (m_backgroundCoversViewport == backgroundCoversViewport)
+ if (m_filters == filters)
return;
- m_backgroundCoversViewport = backgroundCoversViewport;
- m_layerPropertyChanged = true;
+ m_filters = filters;
+ noteLayerPropertyChangedForSubtree();
}
-void CCLayerImpl::setFilters(const FilterOperations& filters)
+void CCLayerImpl::setBackgroundFilters(const FilterOperations& backgroundFilters)
{
- if (m_filters == filters)
+ if (m_backgroundFilters == backgroundFilters)
return;
- m_filters = filters;
- noteLayerPropertyChangedForSubtree();
+ m_backgroundFilters = backgroundFilters;
+ m_layerPropertyChanged = true;
}
void CCLayerImpl::setMasksToBounds(bool masksToBounds)
@@ -424,6 +430,11 @@ void CCLayerImpl::setOpacity(float opacity)
noteLayerPropertyChangedForSubtree();
}
+bool CCLayerImpl::opacityIsAnimating() const
+{
+ return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Opacity);
+}
+
void CCLayerImpl::setPosition(const FloatPoint& position)
{
if (m_position == position)
@@ -461,6 +472,11 @@ void CCLayerImpl::setTransform(const TransformationMatrix& transform)
noteLayerPropertyChangedForSubtree();
}
+bool CCLayerImpl::transformIsAnimating() const
+{
+ return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Transform);
+}
+
void CCLayerImpl::setDebugBorderColor(Color debugBorderColor)
{
if (m_debugBorderColor == debugBorderColor)
@@ -502,7 +518,7 @@ void CCLayerImpl::setScrollPosition(const IntPoint& scrollPosition)
noteLayerPropertyChangedForSubtree();
}
-void CCLayerImpl::setScrollDelta(const IntSize& scrollDelta)
+void CCLayerImpl::setScrollDelta(const FloatSize& scrollDelta)
{
if (m_scrollDelta == scrollDelta)
return;
@@ -529,6 +545,13 @@ void CCLayerImpl::setDoubleSided(bool doubleSided)
noteLayerPropertyChangedForSubtree();
}
+Region CCLayerImpl::visibleContentOpaqueRegion() const
+{
+ if (opaque())
+ return visibleLayerRect();
+ return Region();
+}
+
void CCLayerImpl::didLoseContext()
{
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h
index f1c7b4ee5..bdbfe692e 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h
@@ -33,9 +33,9 @@
#include "Region.h"
#include "TextStream.h"
#include "TransformationMatrix.h"
-#include "cc/CCLayerAnimationControllerImpl.h"
-#include "cc/CCRenderPass.h"
+#include "cc/CCLayerAnimationController.h"
#include "cc/CCRenderSurface.h"
+#include "cc/CCSharedQuadState.h"
#include <wtf/OwnPtr.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
@@ -44,26 +44,27 @@
namespace WebCore {
class CCLayerSorter;
+class CCQuadCuller;
class LayerChromium;
class LayerRendererChromium;
-class CCLayerImpl : public CCLayerAnimationControllerImplClient {
+class CCLayerImpl : public CCLayerAnimationControllerClient {
public:
static PassOwnPtr<CCLayerImpl> create(int id)
{
return adoptPtr(new CCLayerImpl(id));
}
- // CCLayerAnimationControllerImplClient implementation.
- virtual int id() const { return m_layerId; }
- virtual void setOpacity(float);
- virtual float opacity() const { return m_opacity; }
- virtual void setTransform(const TransformationMatrix&);
- virtual const TransformationMatrix& transform() const { return m_transform; }
- virtual const IntSize& bounds() const { return m_bounds; }
-
virtual ~CCLayerImpl();
+ // CCLayerAnimationControllerClient implementation.
+ virtual int id() const OVERRIDE { return m_layerId; }
+ virtual void setOpacityFromAnimation(float) OVERRIDE;
+ virtual float opacity() const OVERRIDE { return m_opacity; }
+ virtual void setTransformFromAnimation(const TransformationMatrix&) OVERRIDE;
+ virtual const TransformationMatrix& transform() const OVERRIDE { return m_transform; }
+ virtual const IntSize& bounds() const OVERRIDE { return m_bounds; }
+
// Tree structure.
CCLayerImpl* parent() const { return m_parent; }
const Vector<OwnPtr<CCLayerImpl> >& children() const { return m_children; }
@@ -77,17 +78,16 @@ public:
void setReplicaLayer(PassOwnPtr<CCLayerImpl>);
CCLayerImpl* replicaLayer() const { return m_replicaLayer.get(); }
-#ifndef NDEBUG
- int debugID() const { return m_debugID; }
-#endif
-
PassOwnPtr<CCSharedQuadState> createSharedQuadState() const;
- virtual void willDraw(LayerRendererChromium*) { }
- virtual void appendQuads(CCQuadList&, const CCSharedQuadState*);
- virtual void didDraw() { }
- void appendDebugBorderQuad(CCQuadList&, const CCSharedQuadState*) const;
+ // willDraw must be called before appendQuads. If willDraw is called,
+ // didDraw is guaranteed to be called before another willDraw or before
+ // the layer is destroyed. To enforce this, any class that overrides
+ // willDraw/didDraw must call the base class version.
+ virtual void willDraw(LayerRendererChromium*);
+ virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*, bool& hadMissingTiles) { }
+ virtual void didDraw();
+ void appendDebugBorderQuad(CCQuadCuller&, const CCSharedQuadState*) const;
- void unreserveContentsTexture();
virtual void bindContentsTexture(LayerRendererChromium*);
// Returns true if this layer has content to draw.
@@ -106,18 +106,21 @@ public:
void setBackgroundColor(const Color&);
Color backgroundColor() const { return m_backgroundColor; }
- void setBackgroundCoversViewport(bool);
- bool backgroundCoversViewport() const { return m_backgroundCoversViewport; }
-
void setFilters(const FilterOperations&);
const FilterOperations& filters() const { return m_filters; }
+ void setBackgroundFilters(const FilterOperations&);
+ const FilterOperations& backgroundFilters() const { return m_backgroundFilters; }
+
void setMasksToBounds(bool);
bool masksToBounds() const { return m_masksToBounds; }
void setOpaque(bool);
bool opaque() const { return m_opaque; }
+ void setOpacity(float);
+ bool opacityIsAnimating() const;
+
void setPosition(const FloatPoint&);
const FloatPoint& position() const { return m_position; }
@@ -151,6 +154,10 @@ public:
float drawOpacity() const { return m_drawOpacity; }
void setDrawOpacity(float opacity) { m_drawOpacity = opacity; }
+ bool drawOpacityIsAnimating() const { return m_drawOpacityIsAnimating; }
+ void setDrawOpacityIsAnimating(bool drawOpacityIsAnimating) { m_drawOpacityIsAnimating = drawOpacityIsAnimating; }
+
+ // Usage: if this->usesLayerClipping() is false, then this clipRect should not be used.
const IntRect& clipRect() const { return m_clipRect; }
void setClipRect(const IntRect& rect) { m_clipRect = rect; }
CCRenderSurface* targetRenderSurface() const { return m_targetRenderSurface; }
@@ -167,8 +174,8 @@ public:
const IntSize& maxScrollPosition() const {return m_maxScrollPosition; }
void setMaxScrollPosition(const IntSize& maxScrollPosition) { m_maxScrollPosition = maxScrollPosition; }
- const IntSize& scrollDelta() const { return m_scrollDelta; }
- void setScrollDelta(const IntSize&);
+ const FloatSize& scrollDelta() const { return m_scrollDelta; }
+ void setScrollDelta(const FloatSize&);
float pageScaleDelta() const { return m_pageScaleDelta; }
void setPageScaleDelta(float);
@@ -176,7 +183,7 @@ public:
const IntSize& sentScrollDelta() const { return m_sentScrollDelta; }
void setSentScrollDelta(const IntSize& sentScrollDelta) { m_sentScrollDelta = sentScrollDelta; }
- void scrollBy(const IntSize& scroll);
+ void scrollBy(const FloatSize& scroll);
bool scrollable() const { return m_scrollable; }
void setScrollable(bool scrollable) { m_scrollable = scrollable; }
@@ -190,6 +197,9 @@ public:
const Region& nonFastScrollableRegion() const { return m_nonFastScrollableRegion; }
void setNonFastScrollableRegion(const Region& region) { m_nonFastScrollableRegion = region; }
+ void setDrawCheckerboardForMissingTiles(bool checkerboard) { m_drawCheckerboardForMissingTiles = checkerboard; }
+ bool drawCheckerboardForMissingTiles() const { return m_drawCheckerboardForMissingTiles; }
+
const IntRect& visibleLayerRect() const { return m_visibleLayerRect; }
void setVisibleLayerRect(const IntRect& visibleLayerRect) { m_visibleLayerRect = visibleLayerRect; }
@@ -199,10 +209,19 @@ public:
// Returns the rect containtaining this layer in the current view's coordinate system.
const IntRect getDrawRect() const;
+ void setTransform(const TransformationMatrix&);
+ bool transformIsAnimating() const;
+
const TransformationMatrix& drawTransform() const { return m_drawTransform; }
void setDrawTransform(const TransformationMatrix& matrix) { m_drawTransform = matrix; }
const TransformationMatrix& screenSpaceTransform() const { return m_screenSpaceTransform; }
void setScreenSpaceTransform(const TransformationMatrix& matrix) { m_screenSpaceTransform = matrix; }
+
+ bool drawTransformIsAnimating() const { return m_drawTransformIsAnimating; }
+ void setDrawTransformIsAnimating(bool animating) { m_drawTransformIsAnimating = animating; }
+ bool screenSpaceTransformIsAnimating() const { return m_screenSpaceTransformIsAnimating; }
+ void setScreenSpaceTransformIsAnimating(bool animating) { m_screenSpaceTransformIsAnimating = animating; }
+
const IntRect& drawableContentRect() const { return m_drawableContentRect; }
void setDrawableContentRect(const IntRect& rect) { m_drawableContentRect = rect; }
const FloatRect& updateRect() const { return m_updateRect; }
@@ -210,12 +229,14 @@ public:
String layerTreeAsText() const;
+ void setStackingOrderChanged(bool);
+
bool layerPropertyChanged() const { return m_layerPropertyChanged; }
void resetAllChangeTrackingForSubtree();
- CCLayerAnimationControllerImpl* layerAnimationController() { return m_layerAnimationController.get(); }
+ CCLayerAnimationController* layerAnimationController() { return m_layerAnimationController.get(); }
- virtual Region opaqueContentsRegion() const { return Region(); };
+ virtual Region visibleContentOpaqueRegion() const;
// Indicates that the context previously used to render this layer
// was lost and that a new one has been created. Won't be called
@@ -231,8 +252,6 @@ protected:
// Transformation used to transform quads provided in appendQuads.
virtual TransformationMatrix quadTransform() const;
- void appendGutterQuads(CCQuadList&, const CCSharedQuadState*);
-
private:
void setParent(CCLayerImpl* parent) { m_parent = parent; }
friend class TreeSynchronizer;
@@ -268,7 +287,6 @@ private:
bool m_haveWheelEventHandlers;
Region m_nonFastScrollableRegion;
Color m_backgroundColor;
- bool m_backgroundCoversViewport;
// Whether the "back" of this layer should draw.
bool m_doubleSided;
@@ -282,6 +300,7 @@ private:
float m_opacity;
FloatPoint m_position;
bool m_preserves3D;
+ bool m_drawCheckerboardForMissingTiles;
TransformationMatrix m_sublayerTransform;
TransformationMatrix m_transform;
bool m_usesLayerClipping;
@@ -289,17 +308,11 @@ private:
bool m_drawsContent;
- IntSize m_scrollDelta;
+ FloatSize m_scrollDelta;
IntSize m_sentScrollDelta;
IntSize m_maxScrollPosition;
float m_pageScaleDelta;
- // Properties owned exclusively by this CCLayerImpl.
- // Debugging.
-#ifndef NDEBUG
- int m_debugID;
-#endif
-
// 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
@@ -310,6 +323,7 @@ private:
// to sort layers from back to front.
float m_drawDepth;
float m_drawOpacity;
+ bool m_drawOpacityIsAnimating;
// Debug borders.
Color m_debugBorderColor;
@@ -319,9 +333,16 @@ private:
String m_debugName;
FilterOperations m_filters;
+ FilterOperations m_backgroundFilters;
TransformationMatrix m_drawTransform;
TransformationMatrix m_screenSpaceTransform;
+ bool m_drawTransformIsAnimating;
+ bool m_screenSpaceTransformIsAnimating;
+
+#ifndef NDEBUG
+ bool m_betweenWillDrawAndDidDraw;
+#endif
// The rect that contributes to the scissor when this layer is drawn.
// Inherited by the parent layer and further restricted if this layer masks
@@ -340,7 +361,7 @@ private:
FloatRect m_updateRect;
// Manages animations for this layer.
- OwnPtr<CCLayerAnimationControllerImpl> m_layerAnimationController;
+ OwnPtr<CCLayerAnimationController> m_layerAnimationController;
};
void sortLayers(Vector<CCLayerImpl*>::iterator first, Vector<CCLayerImpl*>::iterator end, CCLayerSorter*);
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerIterator.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerIterator.h
index d89bd6912..12c627f6a 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerIterator.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerIterator.h
@@ -91,6 +91,16 @@ struct CCLayerIteratorValue {
static const int LayerIndexRepresentingTargetRenderSurface = -1;
};
+// The position of a layer iterator that is independent of its many template types.
+template <typename LayerType>
+struct CCLayerIteratorPosition {
+ bool representsTargetRenderSurface;
+ bool representsContributingRenderSurface;
+ bool representsItself;
+ LayerType* targetRenderSurfaceLayer;
+ LayerType* currentLayer;
+};
+
// An iterator class for walking over layers in the RenderSurface-Layer tree.
template <typename LayerType, typename LayerList, typename RenderSurfaceType, typename IteratorActionType>
class CCLayerIterator {
@@ -119,6 +129,17 @@ public:
LayerType* targetRenderSurfaceLayer() const { return getRawPtr((*m_renderSurfaceLayerList)[m_targetRenderSurfaceLayerIndex]); }
+ operator const CCLayerIteratorPosition<LayerType>() const
+ {
+ CCLayerIteratorPosition<LayerType> position;
+ position.representsTargetRenderSurface = representsTargetRenderSurface();
+ position.representsContributingRenderSurface = representsContributingRenderSurface();
+ position.representsItself = representsItself();
+ position.targetRenderSurfaceLayer = targetRenderSurfaceLayer();
+ position.currentLayer = currentLayer();
+ return position;
+ }
+
private:
CCLayerIterator(const LayerList* renderSurfaceLayerList, bool start)
: m_renderSurfaceLayerList(renderSurfaceLayerList)
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.cpp
index c434a1d95..1af639c8b 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.cpp
@@ -27,6 +27,7 @@
#include "cc/CCLayerSorter.h"
#include "TransformationMatrix.h"
+#include "cc/CCMathUtil.h"
#include "cc/CCRenderSurface.h"
#include <limits.h>
#include <wtf/Deque.h>
@@ -46,56 +47,11 @@ static WTFLogChannel LogCCLayerSorter = { 0x00000000, "", WTFLogChannelOff };
namespace WebCore {
-bool CCLayerSorter::pointInTriangle(const FloatPoint& point,
- const FloatPoint& a,
- const FloatPoint& b,
- const FloatPoint& c)
-{
- // Algorithm from http://www.blackpawn.com/texts/pointinpoly/default.html
- float x0 = c.x() - a.x();
- float y0 = c.y() - a.y();
- float x1 = b.x() - a.x();
- float y1 = b.y() - a.y();
- float x2 = point.x() - a.x();
- float y2 = point.y() - a.y();
-
- float dot00 = x0 * x0 + y0 * y0;
- float dot01 = x0 * x1 + y0 * y1;
- float dot02 = x0 * x2 + y0 * y2;
- float dot11 = x1 * x1 + y1 * y1;
- float dot12 = x1 * x2 + y1 * y2;
- float denominator = dot00 * dot11 - dot01 * dot01;
- if (!denominator)
- // Triangle is zero-area. Treat query point as not being inside.
- return false;
- // Compute
- float inverseDenominator = 1.0f / denominator;
- float u = (dot11 * dot02 - dot01 * dot12) * inverseDenominator;
- float v = (dot00 * dot12 - dot01 * dot02) * inverseDenominator;
-
- return (u > 0.0f) && (v > 0.0f) && (u + v < 1.0f);
-}
-
inline static float perpProduct(const FloatSize& u, const FloatSize& v)
{
return u.width() * v.height() - u.height() * v.width();
}
-inline static float innerProduct(const FloatSize& u, const FloatSize& v)
-{
- return u.width() * v.width() + u.height() * v.height();
-}
-
-
-inline static bool pointInColinearEdge(const FloatPoint& p, const FloatPoint& a, const FloatPoint& b)
-{
- // if ab is not vertical.
- if (a.x() != b.x())
- return (p.x() >= min(a.x(), b.x()) && p.x() <= max(a.x(), b.x()));
-
- return (p.y() >= min(a.y(), b.y()) && p.y() <= max(a.y(), b.y()));
-}
-
// Tests if two edges defined by their endpoints (a,b) and (c,d) intersect. Returns true and the
// point of intersection if they do and false otherwise.
static bool edgeEdgeTest(const FloatPoint& a, const FloatPoint& b, const FloatPoint& c, const FloatPoint& d, FloatPoint& r)
@@ -106,31 +62,12 @@ static bool edgeEdgeTest(const FloatPoint& a, const FloatPoint& b, const FloatPo
float denom = perpProduct(u, v);
- // If denom == 0 then the edges are parallel.
- if (!denom) {
- // If the edges are not colinear then there's no intersection.
- if (perpProduct(u, w) || perpProduct(v, w))
- return false;
-
- if (pointInColinearEdge(a, c, d)) {
- r = a;
- return true;
- }
- if (pointInColinearEdge(b, c, d)) {
- r = b;
- return true;
- }
- if (pointInColinearEdge(c, a, b)) {
- r = c;
- return true;
- }
- if (pointInColinearEdge(d, a, b)) {
- r = d;
- return true;
- }
-
+ // If denom == 0 then the edges are parallel. While they could be overlapping
+ // we don't bother to check here as the we'll find their intersections from the
+ // corner to quad tests.
+ if (!denom)
return false;
- }
+
float s = perpProduct(v, w) / denom;
if (s < 0 || s > 1)
return false;
@@ -144,105 +81,136 @@ static bool edgeEdgeTest(const FloatPoint& a, const FloatPoint& b, const FloatPo
return true;
}
-float CCLayerSorter::calculateZDiff(const LayerShape& layerA, const LayerShape& layerB, float earlyExitThreshold)
+// Checks whether layer "a" draws on top of layer "b". The weight value returned is an indication of
+// the maximum z-depth difference between the layers or zero if the layers are found to be intesecting
+// (some features are in front and some are behind).
+CCLayerSorter::ABCompareResult CCLayerSorter::checkOverlap(LayerShape* a, LayerShape* b, float zThreshold, float& weight)
{
- LayerIntersector intersector(layerA, layerB, earlyExitThreshold);
- intersector.go();
- return intersector.zDiff;
-}
+ weight = 0;
-CCLayerSorter::LayerIntersector::LayerIntersector(const LayerShape& layerA, const LayerShape& layerB, float earlyExitThreshold)
- : layerA(layerA)
- , layerB(layerB)
- , zDiff(0)
- , earlyExitThreshold(earlyExitThreshold)
-{
-}
+ // Early out if the projected bounds don't overlap.
+ if (!a->projectedBounds.intersects(b->projectedBounds))
+ return None;
-void CCLayerSorter::LayerIntersector::go()
-{
- (triangleTriangleTest(layerA.c1, layerA.c2, layerA.c3, layerB.c1, layerB.c2, layerB.c3)
- || triangleTriangleTest(layerA.c3, layerA.c4, layerA.c1, layerB.c1, layerB.c2, layerB.c3)
- || triangleTriangleTest(layerA.c1, layerA.c2, layerA.c3, layerB.c3, layerB.c4, layerB.c1)
- || triangleTriangleTest(layerA.c3, layerA.c4, layerA.c1, layerB.c3, layerB.c4, layerB.c1));
-}
+ FloatPoint aPoints[4] = {a->projectedQuad.p1(), a->projectedQuad.p2(), a->projectedQuad.p3(), a->projectedQuad.p4() };
+ FloatPoint bPoints[4] = {b->projectedQuad.p1(), b->projectedQuad.p2(), b->projectedQuad.p3(), b->projectedQuad.p4() };
-// Checks if segment pq intersects any of the sides of triangle abc.
-bool CCLayerSorter::LayerIntersector::edgeTriangleTest(const FloatPoint& p, const FloatPoint& q, const FloatPoint& a, const FloatPoint& b, const FloatPoint& c)
-{
+ // Make a list of points that inside both layer quad projections.
+ Vector<FloatPoint> overlapPoints;
+
+ // Check all four corners of one layer against the other layer's quad.
+ for (int i = 0; i < 4; ++i) {
+ if (a->projectedQuad.containsPoint(bPoints[i]))
+ overlapPoints.append(bPoints[i]);
+ if (b->projectedQuad.containsPoint(aPoints[i]))
+ overlapPoints.append(aPoints[i]);
+ }
+
+ // Check all the edges of one layer for intersection with the other layer's edges.
FloatPoint r;
- if ((edgeEdgeTest(p, q, a, b, r) && checkZDiff(r))
- || (edgeEdgeTest(p, q, a, c, r) && checkZDiff(r))
- || (edgeEdgeTest(p, q, b, c, r) && checkZDiff(r)))
- return true;
+ for (int ea = 0; ea < 4; ++ea)
+ for (int eb = 0; eb < 4; ++eb)
+ if (edgeEdgeTest(aPoints[ea], aPoints[(ea + 1) % 4],
+ bPoints[eb], bPoints[(eb + 1) % 4],
+ r))
+ overlapPoints.append(r);
+
+ if (!overlapPoints.size())
+ return None;
- return false;
-}
+ // Check the corresponding layer depth value for all overlap points to determine
+ // which layer is in front.
+ float maxPositive = 0;
+ float maxNegative = 0;
+ for (unsigned o = 0; o < overlapPoints.size(); o++) {
+ float za = a->layerZFromProjectedPoint(overlapPoints[o]);
+ float zb = b->layerZFromProjectedPoint(overlapPoints[o]);
+
+ float diff = za - zb;
+ if (diff > maxPositive)
+ maxPositive = diff;
+ if (diff < maxNegative)
+ maxNegative = diff;
+ }
-// Checks if two co-planar triangles intersect.
-bool CCLayerSorter::LayerIntersector::triangleTriangleTest(const FloatPoint& a1, const FloatPoint& b1, const FloatPoint& c1, const FloatPoint& a2, const FloatPoint& b2, const FloatPoint& c2)
-{
- // Check all edges of first triangle with edges of the second one.
- if (edgeTriangleTest(a1, b1, a2, b2, c2)
- || edgeTriangleTest(a1, c1, a2, b2, c2)
- || edgeTriangleTest(b1, c1, a2, b2, c2))
- return true;
-
- // Check all points of the first triangle for inclusion in the second triangle.
- if ((pointInTriangle(a1, a2, b2, c2) && checkZDiff(a1))
- || (pointInTriangle(b1, a2, b2, c2) && checkZDiff(b1))
- || (pointInTriangle(c1, a2, b2, c2) && checkZDiff(c1)))
- return true;
-
- // Check all points of the second triangle for inclusion in the first triangle.
- if ((pointInTriangle(a2, a1, b1, c1) && checkZDiff(a2))
- || (pointInTriangle(b2, a1, b1, c1) && checkZDiff(b2))
- || (pointInTriangle(c2, a1, b1, c1) && checkZDiff(c2)))
- return true;
-
- return false;
+ float maxDiff = (fabsf(maxPositive) > fabsf(maxNegative) ? maxPositive : maxNegative);
+
+ // If the results are inconsistent (and the z difference substantial to rule out
+ // numerical errors) then the layers are intersecting. We will still return an
+ // order based on the maximum depth difference but with an edge weight of zero
+ // these layers will get priority if a graph cycle is present and needs to be broken.
+ if (maxPositive > zThreshold && maxNegative < -zThreshold)
+ weight = 0;
+ else
+ weight = fabsf(maxDiff);
+
+ // Maintain relative order if the layers have the same depth at all intersection points.
+ if (maxDiff <= 0)
+ return ABeforeB;
+
+ return BBeforeA;
}
-// Computes the z difference between point p projected onto the two layers to determine
-// which layer is in front. If the new z difference is higher than the currently
-// recorded one the this becomes the point of choice for doing the comparison between the
-// layers. If the value of difference is higher than our early exit threshold then
-// it means that the z difference is conclusive enough that we don't have to check
-// other intersection points.
-bool CCLayerSorter::LayerIntersector::checkZDiff(const FloatPoint& p)
+CCLayerSorter::LayerShape::LayerShape(float width, float height, const TransformationMatrix& drawTransform)
{
- float za = layerZFromProjectedPoint(layerA, p);
- float zb = layerZFromProjectedPoint(layerB, p);
-
- float diff = za - zb;
- float absDiff = fabsf(diff);
- if ((absDiff) > fabsf(zDiff)) {
- intersectionPoint = p;
- zDiff = diff;
- }
+ FloatQuad layerQuad(FloatPoint(-width * 0.5, height * 0.5),
+ FloatPoint(width * 0.5, height * 0.5),
+ FloatPoint(width * 0.5, -height * 0.5),
+ FloatPoint(-width * 0.5, -height * 0.5));
- if (absDiff > earlyExitThreshold)
- return true;
+ // Compute the projection of the layer quad onto the z = 0 plane.
- return false;
-}
+ FloatPoint clippedQuad[8];
+ int numVerticesInClippedQuad;
+ CCMathUtil::mapClippedQuad(drawTransform, layerQuad, clippedQuad, numVerticesInClippedQuad);
+
+ if (numVerticesInClippedQuad < 3) {
+ projectedBounds = FloatRect();
+ return;
+ }
+ projectedBounds = CCMathUtil::computeEnclosingRectOfVertices(clippedQuad, numVerticesInClippedQuad);
+
+ // NOTE: it will require very significant refactoring and overhead to deal with
+ // generalized polygons or multiple quads per layer here. For the sake of layer
+ // sorting it is equally correct to take a subsection of the polygon that can be made
+ // into a quad. This will only be incorrect in the case of intersecting layers, which
+ // are not supported yet anyway.
+ projectedQuad.setP1(clippedQuad[0]);
+ projectedQuad.setP2(clippedQuad[1]);
+ projectedQuad.setP3(clippedQuad[2]);
+ if (numVerticesInClippedQuad >= 4)
+ projectedQuad.setP4(clippedQuad[3]);
+ else
+ projectedQuad.setP4(clippedQuad[2]); // this will be a degenerate quad that is actually a triangle.
+
+ // Compute the normal of the layer's plane.
+ FloatPoint3D c1 = drawTransform.mapPoint(FloatPoint3D(0, 0, 0));
+ FloatPoint3D c2 = drawTransform.mapPoint(FloatPoint3D(0, 1, 0));
+ FloatPoint3D c3 = drawTransform.mapPoint(FloatPoint3D(1, 0, 0));
+ FloatPoint3D c12 = c2 - c1;
+ FloatPoint3D c13 = c3 - c1;
+ layerNormal = c13.cross(c12);
+
+ transformOrigin = c1;
+}
-// Returns the Z coordinate of a point on the given layer that projects
+// Returns the Z coordinate of a point on the layer that projects
// to point p which lies on the z = 0 plane. It does it by computing the
// intersection of a line starting from p along the Z axis and the plane
// of the layer.
-float CCLayerSorter::LayerIntersector::layerZFromProjectedPoint(const LayerShape& layer, const FloatPoint& p)
+float CCLayerSorter::LayerShape::layerZFromProjectedPoint(const FloatPoint& p) const
{
const FloatPoint3D zAxis(0, 0, 1);
- FloatPoint3D w = FloatPoint3D(p.x(), p.y(), 0) - layer.origin;
+ FloatPoint3D w = FloatPoint3D(p) - transformOrigin;
- float d = layer.normal.dot(zAxis);
- float n = -layer.normal.dot(w);
+ float d = layerNormal.dot(zAxis);
+ float n = -layerNormal.dot(w);
- // Check if layer is parallel to the z = 0 axis
+ // Check if layer is parallel to the z = 0 axis which will make it
+ // invisible and hence returning zero is fine.
if (!d)
- return layer.origin.z();
+ return 0;
// The intersection point would be given by:
// p + (n / d) * u but since we are only interested in the
@@ -250,43 +218,6 @@ float CCLayerSorter::LayerIntersector::layerZFromProjectedPoint(const LayerShape
return n / d;
}
-CCLayerSorter::CCLayerSorter()
- : m_zRange(0)
-{
-}
-
-CCLayerSorter::ABCompareResult CCLayerSorter::checkOverlap(GraphNode* a, GraphNode* b)
-{
- if (!a->shape.boundingBox.intersects(b->shape.boundingBox))
- return None;
-
- // These thresholds are defined relative to the total Z range. If further Z-fighting
- // bugs come up due to precision errors, it may be worth considering doing an ulp
- // error measurement instead.
- float exitThreshold = m_zRange * 0.01;
- float nonZeroThreshold = max(exitThreshold, 0.001f);
-
- float zDiff = calculateZDiff(a->shape, b->shape, exitThreshold);
-
- if (zDiff > nonZeroThreshold)
- return BBeforeA;
- if (zDiff < -nonZeroThreshold)
- return ABeforeB;
-
- return None;
-}
-
-CCLayerSorter::LayerShape::LayerShape(const FloatPoint3D& p1, const FloatPoint3D& p2, const FloatPoint3D& p3, const FloatPoint3D& p4)
- : normal((p2 - p1).cross(p3 - p1))
- , c1(FloatPoint(p1.x(), p1.y()))
- , c2(FloatPoint(p2.x(), p2.y()))
- , c3(FloatPoint(p3.x(), p3.y()))
- , c4(FloatPoint(p4.x(), p4.y()))
- , origin(p1)
-{
- boundingBox.fitToPoints(c1, c2, c3, c4);
-}
-
void CCLayerSorter::createGraphNodes(LayerList::iterator first, LayerList::iterator last)
{
#if !defined( NDEBUG )
@@ -302,32 +233,28 @@ void CCLayerSorter::createGraphNodes(LayerList::iterator first, LayerList::itera
continue;
#if !defined( NDEBUG )
- LOG(CCLayerSorter, "Layer %d (%d x %d)\n", node.layer->debugID(), node.layer->bounds().width(), node.layer->bounds().height());
+ LOG(CCLayerSorter, "Layer %d (%d x %d)\n", node.layer->id(), node.layer->bounds().width(), node.layer->bounds().height());
#endif
TransformationMatrix drawTransform;
float layerWidth, layerHeight;
if (renderSurface) {
drawTransform = renderSurface->drawTransform();
- layerWidth = 0.5 * renderSurface->contentRect().width();
- layerHeight = 0.5 * renderSurface->contentRect().height();
+ layerWidth = renderSurface->contentRect().width();
+ layerHeight = renderSurface->contentRect().height();
} else {
drawTransform = node.layer->drawTransform();
- layerWidth = 0.5 * node.layer->bounds().width();
- layerHeight = 0.5 * node.layer->bounds().height();
+ layerWidth = node.layer->bounds().width();
+ layerHeight = node.layer->bounds().height();
}
- FloatPoint3D c1 = drawTransform.mapPoint(FloatPoint3D(-layerWidth, layerHeight, 0));
- FloatPoint3D c2 = drawTransform.mapPoint(FloatPoint3D(layerWidth, layerHeight, 0));
- FloatPoint3D c3 = drawTransform.mapPoint(FloatPoint3D(layerWidth, -layerHeight, 0));
- FloatPoint3D c4 = drawTransform.mapPoint(FloatPoint3D(-layerWidth, -layerHeight, 0));
- node.shape = LayerShape(c1, c2, c3, c4);
-
- maxZ = max(c4.z(), max(c3.z(), max(c2.z(), max(maxZ, c1.z()))));
- minZ = min(c4.z(), min(c3.z(), min(c2.z(), min(minZ, c1.z()))));
+ node.shape = LayerShape(layerWidth, layerHeight, drawTransform);
+
+ maxZ = max(maxZ, node.shape.transformOrigin.z());
+ minZ = min(minZ, node.shape.transformOrigin.z());
}
- if (last - first)
- m_zRange = fabsf(maxZ - minZ);
+
+ m_zRange = fabsf(maxZ - minZ);
}
void CCLayerSorter::createGraphEdges()
@@ -335,6 +262,11 @@ void CCLayerSorter::createGraphEdges()
#if !defined( NDEBUG )
LOG(CCLayerSorter, "Edges:\n");
#endif
+ // Fraction of the total zRange below which z differences
+ // are not considered reliable.
+ const float zThresholdFactor = 0.01;
+ float zThreshold = m_zRange * zThresholdFactor;
+
for (unsigned na = 0; na < m_nodes.size(); na++) {
GraphNode& nodeA = m_nodes[na];
if (!nodeA.layer->drawsContent() && !nodeA.layer->renderSurface())
@@ -343,7 +275,8 @@ void CCLayerSorter::createGraphEdges()
GraphNode& nodeB = m_nodes[nb];
if (!nodeB.layer->drawsContent() && !nodeB.layer->renderSurface())
continue;
- ABCompareResult overlapResult = checkOverlap(&nodeA, &nodeB);
+ float weight = 0;
+ ABCompareResult overlapResult = checkOverlap(&nodeA.shape, &nodeB.shape, zThreshold, weight);
GraphNode* startNode = 0;
GraphNode* endNode = 0;
if (overlapResult == ABeforeB) {
@@ -356,9 +289,9 @@ void CCLayerSorter::createGraphEdges()
if (startNode) {
#if !defined( NDEBUG )
- LOG(CCLayerSorter, "%d -> %d\n", startNode->layer->debugID(), endNode->layer->debugID());
+ LOG(CCLayerSorter, "%d -> %d\n", startNode->layer->id(), endNode->layer->id());
#endif
- m_edges.append(GraphEdge(startNode, endNode));
+ m_edges.append(GraphEdge(startNode, endNode, weight));
}
}
}
@@ -368,6 +301,7 @@ void CCLayerSorter::createGraphEdges()
m_activeEdges.add(&edge, &edge);
edge.from->outgoing.append(&edge);
edge.to->incoming.append(&edge);
+ edge.to->incomingEdgeWeight += edge.weight;
}
}
@@ -390,7 +324,7 @@ void CCLayerSorter::removeEdgeFromList(GraphEdge* edge, Vector<GraphEdge*>& list
// Sorts the given list of layers such that they can be painted in a back-to-front
// order. Sorting produces correct results for non-intersecting layers that don't have
-// cyclical order dependencies. Cycles and intersections are broken aribtrarily.
+// cyclical order dependencies. Cycles and intersections are broken (somewhat) aribtrarily.
// Sorting of layers is done via a topological sort of a directed graph whose nodes are
// the layers themselves. An edge from node A to node B signifies that layer A needs to
// be drawn before layer B. If A and B have no dependency between each other, then we
@@ -441,7 +375,7 @@ void CCLayerSorter::sort(LayerList::iterator first, LayerList::iterator last)
sortedList.append(fromNode);
#if !defined( NDEBUG )
- LOG(CCLayerSorter, "%d, ", fromNode->layer->debugID());
+ LOG(CCLayerSorter, "%d, ", fromNode->layer->id());
#endif
// Remove all its outgoing edges from the graph.
@@ -450,6 +384,7 @@ void CCLayerSorter::sort(LayerList::iterator first, LayerList::iterator last)
m_activeEdges.remove(outgoingEdge);
removeEdgeFromList(outgoingEdge, outgoingEdge->to->incoming);
+ outgoingEdge->to->incomingEdgeWeight -= outgoingEdge->weight;
if (!outgoingEdge->to->incoming.size())
noIncomingEdgeNodeList.append(outgoingEdge->to);
@@ -462,12 +397,14 @@ void CCLayerSorter::sort(LayerList::iterator first, LayerList::iterator last)
// If there are still active edges but the list of nodes without incoming edges
// is empty then we have run into a cycle. Break the cycle by finding the node
- // with the least number incoming edges and remove them all.
- unsigned minIncomingEdgeCount = UINT_MAX;
+ // with the smallest overall incoming edge weight and use it. This will favor
+ // nodes that have zero-weight incoming edges i.e. layers that are being
+ // occluded by a layer that intersects them.
+ float minIncomingEdgeWeight = FLT_MAX;
GraphNode* nextNode = 0;
for (unsigned i = 0; i < m_nodes.size(); i++) {
- if (m_nodes[i].incoming.size() && (m_nodes[i].incoming.size() < minIncomingEdgeCount)) {
- minIncomingEdgeCount = m_nodes[i].incoming.size();
+ if (m_nodes[i].incoming.size() && m_nodes[i].incomingEdgeWeight < minIncomingEdgeWeight) {
+ minIncomingEdgeWeight = m_nodes[i].incomingEdgeWeight;
nextNode = &m_nodes[i];
}
}
@@ -480,9 +417,10 @@ void CCLayerSorter::sort(LayerList::iterator first, LayerList::iterator last)
removeEdgeFromList(incomingEdge, incomingEdge->from->outgoing);
}
nextNode->incoming.clear();
+ nextNode->incomingEdgeWeight = 0;
noIncomingEdgeNodeList.append(nextNode);
#if !defined( NDEBUG )
- LOG(CCLayerSorter, "Breaking cycle by cleaning up %d edges from %d\n", minIncomingEdgeCount, nextNode->layer->debugID());
+ LOG(CCLayerSorter, "Breaking cycle by cleaning up incoming edges from %d (weight = %f)\n", nextNode->layer->id(), minIncomingEdgeWeight);
#endif
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.h
index 8ab9b7581..3e2a88c92 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.h
@@ -26,6 +26,7 @@
#define CCLayerSorter_h
#include "FloatPoint3D.h"
+#include "FloatQuad.h"
#include "FloatRect.h"
#include "cc/CCLayerImpl.h"
#include <wtf/HashMap.h>
@@ -37,62 +38,52 @@ namespace WebCore {
class CCLayerSorter {
WTF_MAKE_NONCOPYABLE(CCLayerSorter);
public:
- CCLayerSorter();
+ CCLayerSorter() : m_zRange(0) { }
typedef Vector<CCLayerImpl*> LayerList;
void sort(LayerList::iterator first, LayerList::iterator last);
- // Helper methods, public for unit testing.
- static bool pointInTriangle(const FloatPoint&, const FloatPoint&, const FloatPoint&, const FloatPoint&);
-
// Holds various useful properties derived from a layer's 3D outline.
struct LayerShape {
LayerShape() { }
- LayerShape(const FloatPoint3D&, const FloatPoint3D&, const FloatPoint3D&, const FloatPoint3D&);
+ LayerShape(float width, float height, const TransformationMatrix& drawTransform);
+
+ float layerZFromProjectedPoint(const FloatPoint&) const;
- FloatPoint3D normal;
- FloatPoint c1, c2, c3, c4;
- FloatPoint3D origin;
- FloatRect boundingBox;
+ FloatPoint3D layerNormal;
+ FloatPoint3D transformOrigin;
+ FloatQuad projectedQuad;
+ FloatRect projectedBounds;
+ };
+
+ enum ABCompareResult {
+ ABeforeB,
+ BBeforeA,
+ None
};
- static float calculateZDiff(const LayerShape&, const LayerShape&, float earlyExitThreshold);
+ static ABCompareResult checkOverlap(LayerShape*, LayerShape*, float zThreshold, float& weight);
private:
struct GraphEdge;
struct GraphNode {
- explicit GraphNode(CCLayerImpl* cclayer) : layer(cclayer) { }
+ explicit GraphNode(CCLayerImpl* cclayer) : layer(cclayer), incomingEdgeWeight(0) { }
CCLayerImpl* layer;
LayerShape shape;
Vector<GraphEdge*> incoming;
Vector<GraphEdge*> outgoing;
+ float incomingEdgeWeight;
};
struct GraphEdge {
- GraphEdge(GraphNode* fromNode, GraphNode* toNode) : from(fromNode), to(toNode) { };
+ GraphEdge(GraphNode* fromNode, GraphNode* toNode, float weight) : from(fromNode), to(toNode), weight(weight) { };
GraphNode* from;
GraphNode* to;
- };
-
- struct LayerIntersector {
- LayerIntersector(const LayerShape&, const LayerShape&, float);
-
- void go();
-
- float layerZFromProjectedPoint(const LayerShape&, const FloatPoint&);
- bool triangleTriangleTest(const FloatPoint&, const FloatPoint&, const FloatPoint&, const FloatPoint&, const FloatPoint&, const FloatPoint&);
- bool edgeTriangleTest(const FloatPoint&, const FloatPoint&, const FloatPoint&, const FloatPoint&, const FloatPoint&);
- bool checkZDiff(const FloatPoint&);
-
- FloatPoint intersectionPoint;
- const LayerShape& layerA;
- const LayerShape& layerB;
- float zDiff;
- float earlyExitThreshold;
+ float weight;
};
typedef Vector<GraphNode> NodeList;
@@ -104,18 +95,9 @@ private:
typedef HashMap<GraphEdge*, GraphEdge*> EdgeMap;
EdgeMap m_activeEdges;
- float m_zDiffEpsilon;
-
void createGraphNodes(LayerList::iterator first, LayerList::iterator last);
void createGraphEdges();
void removeEdgeFromList(GraphEdge*, Vector<GraphEdge*>&);
-
- enum ABCompareResult {
- ABeforeB,
- BBeforeA,
- None
- };
- ABCompareResult checkOverlap(GraphNode*, GraphNode*);
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp
index 19d0251dc..ab132ae14 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp
@@ -106,14 +106,16 @@ void CCLayerTilingData::layerRectToTileIndices(const IntRect& layerRect, int& le
IntRect CCLayerTilingData::tileRect(const Tile* tile) const
{
- const int index = m_tilingData.tileIndex(tile->i(), tile->j());
- IntRect tileRect = m_tilingData.tileBoundsWithBorder(index);
+ IntRect tileRect = m_tilingData.tileBoundsWithBorder(tile->i(), tile->j());
tileRect.setSize(m_tileSize);
return tileRect;
}
Region CCLayerTilingData::opaqueRegionInLayerRect(const IntRect& layerRect) const
{
+ if (layerRect.isEmpty())
+ return Region();
+
Region opaqueRegion;
int left, top, right, bottom;
layerRectToTileIndices(layerRect, left, top, right, bottom);
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.h
index 9e18695e8..d87dcd260 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.h
@@ -44,10 +44,10 @@ public:
static PassOwnPtr<CCLayerTilingData> create(const IntSize& tileSize, BorderTexelOption);
- int numTiles() const { return m_tilingData.numTiles(); }
+ bool hasEmptyBounds() const { return m_tilingData.hasEmptyBounds(); }
int numTilesX() const { return m_tilingData.numTilesX(); }
int numTilesY() const { return m_tilingData.numTilesY(); }
- IntRect tileBounds(int i, int j) const { return m_tilingData.tileBounds(m_tilingData.tileIndex(i, j)); }
+ IntRect tileBounds(int i, int j) const { return m_tilingData.tileBounds(i, j); }
IntPoint textureOffset(int xIndex, int yIndex) const { return m_tilingData.textureOffset(xIndex, yIndex); }
// Change the tile size. This may invalidate all the existing tiles.
@@ -57,7 +57,7 @@ public:
void setBorderTexelOption(BorderTexelOption);
bool hasBorderTexels() const { return m_tilingData.borderTexels(); }
- bool isEmpty() const { return !m_tilingData.numTiles() || !tiles().size(); }
+ bool isEmpty() const { return hasEmptyBounds() || !tiles().size(); }
const CCLayerTilingData& operator=(const CCLayerTilingData&);
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp
index 34bce1181..39d2a1658 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp
@@ -32,6 +32,8 @@
#include "Region.h"
#include "TraceEvent.h"
#include "TreeSynchronizer.h"
+#include "cc/CCFontAtlas.h"
+#include "cc/CCLayerAnimationController.h"
#include "cc/CCLayerIterator.h"
#include "cc/CCLayerTreeHostCommon.h"
#include "cc/CCLayerTreeHostImpl.h"
@@ -48,22 +50,25 @@ static int numLayerTreeInstances;
namespace WebCore {
+bool CCLayerTreeHost::s_needsFilterContext = false;
+
bool CCLayerTreeHost::anyLayerTreeHostInstanceExists()
{
return numLayerTreeInstances > 0;
}
-PassRefPtr<CCLayerTreeHost> CCLayerTreeHost::create(CCLayerTreeHostClient* client, const CCSettings& settings)
+PassOwnPtr<CCLayerTreeHost> CCLayerTreeHost::create(CCLayerTreeHostClient* client, const CCSettings& settings)
{
- RefPtr<CCLayerTreeHost> layerTreeHost = adoptRef(new CCLayerTreeHost(client, settings));
+ OwnPtr<CCLayerTreeHost> layerTreeHost = adoptPtr(new CCLayerTreeHost(client, settings));
if (!layerTreeHost->initialize())
- return 0;
- return layerTreeHost;
+ return nullptr;
+ return layerTreeHost.release();
}
CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCSettings& settings)
: m_compositorIdentifier(-1)
, m_animating(false)
+ , m_needsAnimateLayers(false)
, m_client(client)
, m_frameNumber(0)
, m_layerRendererInitialized(false)
@@ -76,6 +81,7 @@ CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCSettings
, m_minPageScaleFactor(1)
, m_maxPageScaleFactor(1)
, m_triggerIdlePaints(true)
+ , m_backgroundColor(Color::white)
, m_partialTextureUpdateRequests(0)
{
ASSERT(CCProxy::isMainThread());
@@ -85,19 +91,24 @@ CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCSettings
bool CCLayerTreeHost::initialize()
{
TRACE_EVENT("CCLayerTreeHost::initialize", this, 0);
- if (CCProxy::hasImplThread()) {
- // The HUD does not work in threaded mode. Turn it off.
- m_settings.showFPSCounter = false;
- m_settings.showPlatformLayerTree = false;
+ if (CCProxy::hasImplThread())
m_proxy = CCThreadProxy::create(this);
- } else
+ else
m_proxy = CCSingleThreadProxy::create(this);
m_proxy->start();
if (!m_proxy->initializeContext())
return false;
+ // Only allocate the font atlas if we have reason to use the heads-up display.
+ if (m_settings.showFPSCounter || m_settings.showPlatformLayerTree) {
+ TRACE_EVENT0("cc", "CCLayerTreeHost::initialize::initializeFontAtlas");
+ OwnPtr<CCFontAtlas> fontAtlas(CCFontAtlas::create());
+ fontAtlas->initialize();
+ m_proxy->setFontAtlas(fontAtlas.release());
+ }
+
m_compositorIdentifier = m_proxy->compositorIdentifier();
return true;
}
@@ -109,10 +120,14 @@ CCLayerTreeHost::~CCLayerTreeHost()
ASSERT(m_proxy);
m_proxy->stop();
m_proxy.clear();
- clearPendingUpdate();
numLayerTreeInstances--;
}
+void CCLayerTreeHost::setSurfaceReady()
+{
+ m_proxy->setSurfaceReady();
+}
+
void CCLayerTreeHost::initializeLayerRenderer()
{
TRACE_EVENT("CCLayerTreeHost::initializeLayerRenderer", this, 0);
@@ -173,14 +188,21 @@ CCLayerTreeHost::RecreateResult CCLayerTreeHost::recreateContext()
void CCLayerTreeHost::deleteContentsTexturesOnImplThread(TextureAllocator* allocator)
{
ASSERT(CCProxy::isImplThread());
- if (m_contentsTextureManager)
+ if (m_layerRendererInitialized)
m_contentsTextureManager->evictAndDeleteAllTextures(allocator);
}
-void CCLayerTreeHost::updateAnimations(double frameBeginTime)
+void CCLayerTreeHost::acquireLayerTextures()
+{
+ ASSERT(CCProxy::isMainThread());
+ m_proxy->acquireLayerTextures();
+}
+
+void CCLayerTreeHost::updateAnimations(double monotonicFrameBeginTime)
{
m_animating = true;
- m_client->updateAnimations(frameBeginTime);
+ m_client->updateAnimations(monotonicFrameBeginTime);
+ animateLayers(monotonicFrameBeginTime);
m_animating = false;
}
@@ -194,7 +216,7 @@ void CCLayerTreeHost::beginCommitOnImplThread(CCLayerTreeHostImpl* hostImpl)
ASSERT(CCProxy::isImplThread());
TRACE_EVENT("CCLayerTreeHost::commitTo", this, 0);
- m_contentsTextureManager->reduceMemoryToLimit(TextureManager::reclaimLimitBytes(viewportSize()));
+ m_contentsTextureManager->reduceMemoryToLimit(m_contentsTextureManager->preferredMemoryLimitBytes());
m_contentsTextureManager->deleteEvictedTextures(hostImpl->contentsTextureAllocator());
}
@@ -209,13 +231,17 @@ void CCLayerTreeHost::finishCommitOnImplThread(CCLayerTreeHostImpl* hostImpl)
hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->releaseRootLayer()));
- // We may have added an animation during the tree sync. This will cause hostImpl to visit its controllers.
- if (rootLayer())
+ // We may have added an animation during the tree sync. This will cause both layer tree hosts
+ // to visit their controllers.
+ if (rootLayer()) {
hostImpl->setNeedsAnimateLayers();
+ m_needsAnimateLayers = true;
+ }
hostImpl->setSourceFrameNumber(frameNumber());
hostImpl->setViewportSize(viewportSize());
hostImpl->setPageScaleFactorAndLimits(m_pageScaleFactor, m_minPageScaleFactor, m_maxPageScaleFactor);
+ hostImpl->setBackgroundColor(m_backgroundColor);
m_frameNumber++;
}
@@ -223,8 +249,8 @@ void CCLayerTreeHost::finishCommitOnImplThread(CCLayerTreeHostImpl* hostImpl)
void CCLayerTreeHost::commitComplete()
{
m_deleteTextureAfterCommitList.clear();
- clearPendingUpdate();
m_contentsTextureManager->unprotectAllTextures();
+ m_client->didCommit();
}
PassRefPtr<GraphicsContext3D> CCLayerTreeHost::createContext()
@@ -302,6 +328,11 @@ void CCLayerTreeHost::setNeedsRedraw()
m_client->scheduleComposite();
}
+bool CCLayerTreeHost::commitRequested() const
+{
+ return m_proxy->commitRequested();
+}
+
void CCLayerTreeHost::setAnimationEvents(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime)
{
ASSERT(CCThreadProxy::isMainThread());
@@ -326,10 +357,6 @@ void CCLayerTreeHost::setViewportSize(const IntSize& viewportSize)
if (viewportSize == m_viewportSize)
return;
- if (m_contentsTextureManager) {
- m_contentsTextureManager->setMaxMemoryLimitBytes(TextureManager::highLimitBytes(viewportSize));
- m_contentsTextureManager->setPreferredMemoryLimitBytes(TextureManager::reclaimLimitBytes(viewportSize));
- }
m_viewportSize = viewportSize;
setNeedsCommit();
}
@@ -352,11 +379,6 @@ void CCLayerTreeHost::setVisible(bool visible)
m_visible = visible;
- if (!visible && m_layerRendererInitialized) {
- m_contentsTextureManager->reduceMemoryToLimit(TextureManager::lowLimitBytes(viewportSize()));
- m_contentsTextureManager->unprotectAllTextures();
- }
-
// Tells the proxy that visibility state has changed. This will in turn call
// CCLayerTreeHost::didBecomeInvisibleOnImplThread on the appropriate thread, for
// the case where !visible.
@@ -369,28 +391,38 @@ void CCLayerTreeHost::didBecomeInvisibleOnImplThread(CCLayerTreeHostImpl* hostIm
if (!m_layerRendererInitialized)
return;
- if (m_proxy->layerRendererCapabilities().contextHasCachedFrontBuffer)
- contentsTextureManager()->evictAndDeleteAllTextures(hostImpl->contentsTextureAllocator());
- else {
- contentsTextureManager()->reduceMemoryToLimit(TextureManager::reclaimLimitBytes(viewportSize()));
- contentsTextureManager()->deleteEvictedTextures(hostImpl->contentsTextureAllocator());
- }
-
- // Ensure that the dropped tiles are propagated to the impl tree.
- // If the frontbuffer is cached, then clobber the impl tree. Otherwise,
- // push over the tree changes.
if (m_proxy->layerRendererCapabilities().contextHasCachedFrontBuffer) {
- hostImpl->setRootLayer(nullptr);
- return;
+ // Unprotect and delete all textures.
+ m_contentsTextureManager->unprotectAllTextures();
+ m_contentsTextureManager->reduceMemoryToLimit(0);
+ } else {
+ // Delete all unprotected textures, and only save textures that fit in the preferred memory limit.
+ m_contentsTextureManager->reduceMemoryToLimit(0);
+ m_contentsTextureManager->unprotectAllTextures();
+ m_contentsTextureManager->reduceMemoryToLimit(m_contentsTextureManager->preferredMemoryLimitBytes());
}
+ m_contentsTextureManager->deleteEvictedTextures(hostImpl->contentsTextureAllocator());
hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->releaseRootLayer()));
- // We may have added an animation during the tree sync. This will cause hostImpl to visit its controllers.
- if (rootLayer())
+ // We may have added an animation during the tree sync. This will cause both layer tree hosts
+ // to visit their controllers.
+ if (rootLayer()) {
hostImpl->setNeedsAnimateLayers();
+ m_needsAnimateLayers = true;
+ }
}
+void CCLayerTreeHost::setContentsMemoryAllocationLimitBytes(size_t bytes)
+{
+ ASSERT(CCProxy::isMainThread());
+ if (!m_layerRendererInitialized)
+ return;
+
+ m_contentsTextureManager->setMemoryAllocationLimitBytes(bytes);
+}
+
+
void CCLayerTreeHost::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec)
{
m_proxy->startPageScaleAnimation(targetPosition, useAnchor, scale, durationSec);
@@ -414,7 +446,7 @@ void CCLayerTreeHost::composite()
static_cast<CCSingleThreadProxy*>(m_proxy.get())->compositeImmediately();
}
-bool CCLayerTreeHost::updateLayers()
+bool CCLayerTreeHost::updateLayers(CCTextureUpdater& updater)
{
if (!m_layerRendererInitialized) {
initializeLayerRenderer();
@@ -433,11 +465,11 @@ bool CCLayerTreeHost::updateLayers()
if (viewportSize().isEmpty())
return true;
- updateLayers(rootLayer());
+ updateLayers(rootLayer(), updater);
return true;
}
-void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer)
+void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer, CCTextureUpdater& updater)
{
TRACE_EVENT("CCLayerTreeHost::updateLayers", this, 0);
@@ -448,10 +480,8 @@ void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer)
IntRect rootClipRect(IntPoint(), viewportSize());
rootLayer->setClipRect(rootClipRect);
- // This assert fires if updateCompositorResources wasn't called after
- // updateLayers. Only one update can be pending at any given time.
- ASSERT(!m_updateList.size());
- m_updateList.append(rootLayer);
+ LayerList updateList;
+ updateList.append(rootLayer);
RenderSurfaceChromium* rootRenderSurface = rootLayer->renderSurface();
rootRenderSurface->clearLayerList();
@@ -459,20 +489,20 @@ void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer)
TransformationMatrix identityMatrix;
{
TRACE_EVENT("CCLayerTreeHost::updateLayers::calcDrawEtc", this, 0);
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootLayer, rootLayer, identityMatrix, identityMatrix, m_updateList, rootRenderSurface->layerList(), layerRendererCapabilities().maxTextureSize);
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootLayer, rootLayer, identityMatrix, identityMatrix, updateList, rootRenderSurface->layerList(), layerRendererCapabilities().maxTextureSize);
}
// Reset partial texture update requests.
m_partialTextureUpdateRequests = 0;
- reserveTextures();
+ reserveTextures(updateList);
- paintLayerContents(m_updateList, PaintVisible);
+ paintLayerContents(updateList, PaintVisible, updater);
if (!m_triggerIdlePaints)
return;
- size_t preferredLimitBytes = TextureManager::reclaimLimitBytes(m_viewportSize);
- size_t maxLimitBytes = TextureManager::highLimitBytes(m_viewportSize);
+ size_t preferredLimitBytes = m_contentsTextureManager->preferredMemoryLimitBytes();
+ size_t maxLimitBytes = m_contentsTextureManager->maxMemoryLimitBytes();
m_contentsTextureManager->reduceMemoryToLimit(preferredLimitBytes);
if (m_contentsTextureManager->currentMemoryUseBytes() >= preferredLimitBytes)
return;
@@ -481,17 +511,20 @@ void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer)
// otherwise it will always push us towards the maximum limit.
m_contentsTextureManager->setMaxMemoryLimitBytes(preferredLimitBytes);
// The second (idle) paint will be a no-op in layers where painting already occured above.
- paintLayerContents(m_updateList, PaintIdle);
+ paintLayerContents(updateList, PaintIdle, updater);
m_contentsTextureManager->setMaxMemoryLimitBytes(maxLimitBytes);
+
+ for (size_t i = 0; i < updateList.size(); ++i)
+ updateList[i]->clearRenderSurface();
}
-void CCLayerTreeHost::reserveTextures()
+void CCLayerTreeHost::reserveTextures(const LayerList& updateList)
{
// Use BackToFront since it's cheap and this isn't order-dependent.
typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::BackToFront> CCLayerIteratorType;
- CCLayerIteratorType end = CCLayerIteratorType::end(&m_updateList);
- for (CCLayerIteratorType it = CCLayerIteratorType::begin(&m_updateList); it != end; ++it) {
+ CCLayerIteratorType end = CCLayerIteratorType::end(&updateList);
+ for (CCLayerIteratorType it = CCLayerIteratorType::begin(&updateList); it != end; ++it) {
if (!it.representsItself() || !it->alwaysReserveTextures())
continue;
it->reserveTextures();
@@ -499,97 +532,60 @@ void CCLayerTreeHost::reserveTextures()
}
// static
-void CCLayerTreeHost::paintContentsIfDirty(LayerChromium* layer, PaintType paintType, const Region& occludedScreenSpace)
+void CCLayerTreeHost::update(LayerChromium* layer, PaintType paintType, CCTextureUpdater& updater, const CCOcclusionTracker* occlusion)
{
ASSERT(layer);
ASSERT(PaintVisible == paintType || PaintIdle == paintType);
if (PaintVisible == paintType)
- layer->paintContentsIfDirty(occludedScreenSpace);
+ layer->update(updater, occlusion);
else
- layer->idlePaintContentsIfDirty(occludedScreenSpace);
+ layer->idleUpdate(updater, occlusion);
}
-void CCLayerTreeHost::paintMaskAndReplicaForRenderSurface(LayerChromium* renderSurfaceLayer, PaintType paintType)
+void CCLayerTreeHost::paintMasksForRenderSurface(LayerChromium* renderSurfaceLayer, PaintType paintType, CCTextureUpdater& updater)
{
// Note: Masks and replicas only exist for layers that own render surfaces. If we reach this point
// in code, we already know that at least something will be drawn into this render surface, so the
// mask and replica should be painted.
- // FIXME: If the surface has a replica, it should be painted with occlusion that excludes the current target surface subtree.
- Region noOcclusion;
-
- if (renderSurfaceLayer->maskLayer()) {
- renderSurfaceLayer->maskLayer()->setVisibleLayerRect(IntRect(IntPoint(), renderSurfaceLayer->contentBounds()));
- paintContentsIfDirty(renderSurfaceLayer->maskLayer(), paintType, noOcclusion);
+ LayerChromium* maskLayer = renderSurfaceLayer->maskLayer();
+ if (maskLayer) {
+ maskLayer->setVisibleLayerRect(IntRect(IntPoint(), renderSurfaceLayer->contentBounds()));
+ update(maskLayer, paintType, updater, 0);
}
- LayerChromium* replicaLayer = renderSurfaceLayer->replicaLayer();
- if (replicaLayer) {
- paintContentsIfDirty(replicaLayer, paintType, noOcclusion);
-
- if (replicaLayer->maskLayer()) {
- replicaLayer->maskLayer()->setVisibleLayerRect(IntRect(IntPoint(), replicaLayer->maskLayer()->contentBounds()));
- paintContentsIfDirty(replicaLayer->maskLayer(), paintType, noOcclusion);
- }
+ LayerChromium* replicaMaskLayer = renderSurfaceLayer->replicaLayer() ? renderSurfaceLayer->replicaLayer()->maskLayer() : 0;
+ if (replicaMaskLayer) {
+ replicaMaskLayer->setVisibleLayerRect(IntRect(IntPoint(), renderSurfaceLayer->contentBounds()));
+ update(replicaMaskLayer, paintType, updater, 0);
}
}
-void CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList, PaintType paintType)
+void CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList, PaintType paintType, CCTextureUpdater& updater)
{
// Use FrontToBack to allow for testing occlusion and performing culling during the tree walk.
typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
- CCOcclusionTracker occlusionTracker(IntRect(IntPoint(), viewportSize()));
- occlusionTracker.setUsePaintTracking(false); // FIXME: Remove this to turn on paint tracking for paint culling
+ bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off.
+ CCOcclusionTracker occlusionTracker(IntRect(IntPoint(), viewportSize()), recordMetricsForFrame);
+ occlusionTracker.setMinimumTrackingSize(CCOcclusionTracker::preferredMinimumTrackingSize());
CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
- if (it.representsTargetRenderSurface()) {
- ASSERT(it->renderSurface()->drawOpacity());
+ occlusionTracker.enterLayer(it);
- occlusionTracker.finishedTargetRenderSurface(*it, it->renderSurface());
- paintMaskAndReplicaForRenderSurface(*it, paintType);
+ if (it.representsTargetRenderSurface()) {
+ ASSERT(it->renderSurface()->drawOpacity() || it->renderSurface()->drawOpacityIsAnimating());
+ paintMasksForRenderSurface(*it, paintType, updater);
} else if (it.representsItself()) {
ASSERT(!it->bounds().isEmpty());
+ update(*it, paintType, updater, &occlusionTracker);
+ }
- occlusionTracker.enterTargetRenderSurface(it->targetRenderSurface());
- paintContentsIfDirty(*it, paintType, occlusionTracker.currentOcclusionInScreenSpace());
- occlusionTracker.markOccludedBehindLayer(*it);
- } else
- occlusionTracker.leaveToTargetRenderSurface(it.targetRenderSurfaceLayer()->renderSurface());
- }
-}
-
-void CCLayerTreeHost::updateCompositorResources(GraphicsContext3D* context, CCTextureUpdater& updater)
-{
- // Use BackToFront since it's cheap and this isn't order-dependent.
- typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::BackToFront> CCLayerIteratorType;
-
- CCLayerIteratorType end = CCLayerIteratorType::end(&m_updateList);
- for (CCLayerIteratorType it = CCLayerIteratorType::begin(&m_updateList); it != end; ++it) {
- if (it.representsTargetRenderSurface()) {
- ASSERT(it->renderSurface()->drawOpacity());
- if (it->maskLayer())
- it->maskLayer()->updateCompositorResources(context, updater);
-
- if (it->replicaLayer()) {
- it->replicaLayer()->updateCompositorResources(context, updater);
- if (it->replicaLayer()->maskLayer())
- it->replicaLayer()->maskLayer()->updateCompositorResources(context, updater);
- }
- } else if (it.representsItself())
- it->updateCompositorResources(context, updater);
+ occlusionTracker.leaveLayer(it);
}
-}
-void CCLayerTreeHost::clearPendingUpdate()
-{
- for (size_t surfaceIndex = 0; surfaceIndex < m_updateList.size(); ++surfaceIndex) {
- LayerChromium* layer = m_updateList[surfaceIndex].get();
- ASSERT(layer->renderSurface());
- layer->clearRenderSurface();
- }
- m_updateList.clear();
+ occlusionTracker.overdrawMetrics().recordMetrics(this);
}
void CCLayerTreeHost::applyScrollAndScale(const CCScrollAndScaleSet& info)
@@ -612,12 +608,19 @@ void CCLayerTreeHost::startRateLimiter(GraphicsContext3D* context)
if (it != m_rateLimiters.end())
it->second->start();
else {
- RefPtr<RateLimiter> rateLimiter = RateLimiter::create(context);
+ RefPtr<RateLimiter> rateLimiter = RateLimiter::create(context, this);
m_rateLimiters.set(context, rateLimiter);
rateLimiter->start();
}
}
+void CCLayerTreeHost::rateLimit()
+{
+ // Force a no-op command on the compositor context, so that any ratelimiting commands will wait for the compositing
+ // context, and therefore for the SwapBuffers.
+ m_proxy->forceSerializeOnSwapBuffers();
+}
+
void CCLayerTreeHost::stopRateLimiter(GraphicsContext3D* context)
{
RateLimiterMap::iterator it = m_rateLimiters.find(context);
@@ -627,6 +630,11 @@ void CCLayerTreeHost::stopRateLimiter(GraphicsContext3D* context)
}
}
+bool CCLayerTreeHost::bufferedUpdates()
+{
+ return m_settings.maxPartialTextureUpdates != numeric_limits<size_t>::max();
+}
+
bool CCLayerTreeHost::requestPartialTextureUpdate()
{
if (m_partialTextureUpdateRequests >= m_settings.maxPartialTextureUpdates)
@@ -641,11 +649,48 @@ void CCLayerTreeHost::deleteTextureAfterCommit(PassOwnPtr<ManagedTexture> textur
m_deleteTextureAfterCommitList.append(texture);
}
+void CCLayerTreeHost::animateLayers(double monotonicTime)
+{
+ if (!m_settings.threadedAnimationEnabled || !m_needsAnimateLayers)
+ return;
+
+ TRACE_EVENT("CCLayerTreeHostImpl::animateLayers", this, 0);
+ m_needsAnimateLayers = animateLayersRecursive(m_rootLayer.get(), monotonicTime);
+}
+
+bool CCLayerTreeHost::animateLayersRecursive(LayerChromium* current, double monotonicTime)
+{
+ if (!current)
+ return false;
+
+ bool subtreeNeedsAnimateLayers = false;
+ CCLayerAnimationController* currentController = current->layerAnimationController();
+ currentController->animate(monotonicTime, 0);
+
+ // If the current controller still has an active animation, we must continue animating layers.
+ if (currentController->hasActiveAnimation())
+ subtreeNeedsAnimateLayers = true;
+
+ for (size_t i = 0; i < current->children().size(); ++i) {
+ if (animateLayersRecursive(current->children()[i].get(), monotonicTime))
+ subtreeNeedsAnimateLayers = true;
+ }
+
+ return subtreeNeedsAnimateLayers;
+}
+
void CCLayerTreeHost::setAnimationEventsRecursive(const CCAnimationEventsVector& events, LayerChromium* layer, double wallClockTime)
{
+ if (!layer)
+ return;
+
for (size_t eventIndex = 0; eventIndex < events.size(); ++eventIndex) {
- if (layer->id() == events[eventIndex]->layerId())
- layer->setAnimationEvent(*events[eventIndex], wallClockTime);
+ if (layer->id() == events[eventIndex].layerId) {
+ if (events[eventIndex].type == CCAnimationEvent::Started)
+ layer->notifyAnimationStarted(events[eventIndex], wallClockTime);
+ else
+ layer->notifyAnimationFinished(wallClockTime);
+ }
}
for (size_t childIndex = 0; childIndex < layer->children().size(); ++childIndex)
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h
index d5262262d..40612eaf0 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h
@@ -25,6 +25,7 @@
#ifndef CCLayerTreeHost_h
#define CCLayerTreeHost_h
+#include "Color.h"
#include "GraphicsTypes3D.h"
#include "IntRect.h"
#include "LayerChromium.h"
@@ -36,13 +37,14 @@
#include <limits>
#include <wtf/HashMap.h>
+#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/PassRefPtr.h>
-#include <wtf/RefCounted.h>
namespace WebCore {
class CCLayerTreeHostImpl;
+class CCLayerTreeHostImplClient;
class CCTextureUpdater;
class GraphicsContext3D;
class LayerPainterChromium;
@@ -52,11 +54,13 @@ class TextureManager;
class CCLayerTreeHostClient {
public:
+ virtual void willBeginFrame() = 0;
virtual void updateAnimations(double frameBeginTime) = 0;
virtual void layout() = 0;
virtual void applyScrollAndScale(const IntSize& scrollDelta, float pageScale) = 0;
virtual PassRefPtr<GraphicsContext3D> createContext() = 0;
virtual void didRecreateContext(bool success) = 0;
+ virtual void didCommit() = 0;
virtual void didCommitAndDrawFrame() = 0;
virtual void didCompleteSwapBuffers() = 0;
@@ -70,9 +74,11 @@ protected:
struct CCSettings {
CCSettings()
: acceleratePainting(false)
- , compositeOffscreen(false)
, showFPSCounter(false)
, showPlatformLayerTree(false)
+ , showPaintRects(false)
+ , showPropertyChangedRects(false)
+ , showSurfaceDamageRects(false)
, refreshRate(0)
, perTilePainting(false)
, partialSwapEnabled(false)
@@ -80,9 +86,11 @@ struct CCSettings {
, maxPartialTextureUpdates(std::numeric_limits<size_t>::max()) { }
bool acceleratePainting;
- bool compositeOffscreen;
bool showFPSCounter;
bool showPlatformLayerTree;
+ bool showPaintRects;
+ bool showPropertyChangedRects;
+ bool showSurfaceDamageRects;
double refreshRate;
bool perTilePainting;
bool partialSwapEnabled;
@@ -102,6 +110,8 @@ struct LayerRendererCapabilities {
, usingSwapCompleteCallback(false)
, usingTextureUsageHint(false)
, usingTextureStorageExtension(false)
+ , usingGpuMemoryManager(false)
+ , usingDiscardFramebuffer(false)
, maxTextureSize(0) { }
GC3Denum bestTextureFormat;
@@ -113,19 +123,28 @@ struct LayerRendererCapabilities {
bool usingSwapCompleteCallback;
bool usingTextureUsageHint;
bool usingTextureStorageExtension;
+ bool usingGpuMemoryManager;
+ bool usingDiscardFramebuffer;
int maxTextureSize;
};
-class CCLayerTreeHost : public RefCounted<CCLayerTreeHost> {
+class CCLayerTreeHost : public RateLimiterClient {
+ WTF_MAKE_NONCOPYABLE(CCLayerTreeHost);
public:
- static PassRefPtr<CCLayerTreeHost> create(CCLayerTreeHostClient*, const CCSettings&);
+ static PassOwnPtr<CCLayerTreeHost> create(CCLayerTreeHostClient*, const CCSettings&);
virtual ~CCLayerTreeHost();
+ void setSurfaceReady();
+
// Returns true if any CCLayerTreeHost is alive.
static bool anyLayerTreeHostInstanceExists();
+ static bool needsFilterContext() { return s_needsFilterContext; }
+ static void setNeedsFilterContext(bool needsFilterContext) { s_needsFilterContext = needsFilterContext; }
+
// CCLayerTreeHost interface to CCProxy.
- void updateAnimations(double frameBeginTime);
+ void willBeginFrame() { m_client->willBeginFrame(); }
+ void updateAnimations(double monotonicFrameBeginTime);
void layout();
void beginCommitOnImplThread(CCLayerTreeHostImpl*);
void finishCommitOnImplThread(CCLayerTreeHostImpl*);
@@ -143,8 +162,9 @@ public:
void didCommitAndDrawFrame() { m_client->didCommitAndDrawFrame(); }
void didCompleteSwapBuffers() { m_client->didCompleteSwapBuffers(); }
void deleteContentsTexturesOnImplThread(TextureAllocator*);
+ void acquireLayerTextures();
// Returns false if we should abort this frame due to initialization failure.
- bool updateLayers();
+ bool updateLayers(CCTextureUpdater&);
CCLayerTreeHostClient* client() { return m_client; }
@@ -175,6 +195,7 @@ public:
// virtual for testing
virtual void setNeedsCommit();
void setNeedsRedraw();
+ bool commitRequested() const;
void setAnimationEvents(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime);
@@ -190,18 +211,24 @@ public:
void setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor);
+ void setBackgroundColor(const Color& color) { m_backgroundColor = color; }
+
TextureManager* contentsTextureManager() const;
+ void setContentsMemoryAllocationLimitBytes(size_t);
bool visible() const { return m_visible; }
void setVisible(bool);
void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec);
- void updateCompositorResources(GraphicsContext3D*, CCTextureUpdater&);
void applyScrollAndScale(const CCScrollAndScaleSet&);
void startRateLimiter(GraphicsContext3D*);
void stopRateLimiter(GraphicsContext3D*);
+ // RateLimitClient implementation
+ virtual void rateLimit() OVERRIDE;
+
+ bool bufferedUpdates();
bool requestPartialTextureUpdate();
void deleteTextureAfterCommit(PassOwnPtr<ManagedTexture>);
@@ -216,20 +243,22 @@ private:
void initializeLayerRenderer();
enum PaintType { PaintVisible, PaintIdle };
- static void paintContentsIfDirty(LayerChromium*, PaintType, const Region& occludedScreenSpace);
- void paintLayerContents(const LayerList&, PaintType);
- void paintMaskAndReplicaForRenderSurface(LayerChromium*, PaintType);
+ static void update(LayerChromium*, PaintType, CCTextureUpdater&, const CCOcclusionTracker*);
+ void paintLayerContents(const LayerList&, PaintType, CCTextureUpdater&);
+ void paintMasksForRenderSurface(LayerChromium*, PaintType, CCTextureUpdater&);
- void updateLayers(LayerChromium*);
+ void updateLayers(LayerChromium*, CCTextureUpdater&);
// Pre-reserve textures for any layer marked "always reserve textures"
- void reserveTextures();
- void clearPendingUpdate();
+ void reserveTextures(const LayerList&);
+ void animateLayers(double monotonicTime);
+ bool animateLayersRecursive(LayerChromium* current, double monotonicTime);
void setAnimationEventsRecursive(const CCAnimationEventsVector&, LayerChromium*, double wallClockTime);
int m_compositorIdentifier;
bool m_animating;
+ bool m_needsAnimateLayers;
CCLayerTreeHostClient* m_client;
@@ -244,8 +273,6 @@ private:
RefPtr<LayerChromium> m_rootLayer;
OwnPtr<TextureManager> m_contentsTextureManager;
- LayerList m_updateList;
-
CCSettings m_settings;
IntSize m_viewportSize;
@@ -256,9 +283,11 @@ private:
float m_pageScaleFactor;
float m_minPageScaleFactor, m_maxPageScaleFactor;
bool m_triggerIdlePaints;
+ Color m_backgroundColor;
TextureList m_deleteTextureAfterCommitList;
size_t m_partialTextureUpdateRequests;
+ static bool s_needsFilterContext;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp
index c86d74d86..511e837dc 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp
@@ -32,9 +32,12 @@
#include "LayerChromium.h"
#include "RenderSurfaceChromium.h"
#include "TransformationMatrix.h"
+#include "cc/CCActiveAnimation.h"
+#include "cc/CCLayerAnimationController.h"
#include "cc/CCLayerImpl.h"
#include "cc/CCLayerIterator.h"
#include "cc/CCLayerSorter.h"
+#include "cc/CCMathUtil.h"
#include "cc/CCRenderSurface.h"
namespace WebCore {
@@ -42,7 +45,7 @@ namespace WebCore {
IntRect CCLayerTreeHostCommon::calculateVisibleRect(const IntRect& targetSurfaceRect, const IntRect& layerBoundRect, const TransformationMatrix& transform)
{
// Is this layer fully contained within the target surface?
- IntRect layerInSurfaceSpace = transform.mapRect(layerBoundRect);
+ IntRect layerInSurfaceSpace = CCMathUtil::mapClippedRect(transform, layerBoundRect);
if (targetSurfaceRect.contains(layerInSurfaceSpace))
return layerBoundRect;
@@ -57,18 +60,83 @@ IntRect CCLayerTreeHostCommon::calculateVisibleRect(const IntRect& targetSurface
// axis-aligned), but is a reasonable filter on the space to consider.
// Non-invertible transforms will create an empty rect here.
const TransformationMatrix surfaceToLayer = transform.inverse();
- IntRect layerRect = surfaceToLayer.projectQuad(FloatQuad(FloatRect(minimalSurfaceRect))).enclosingBoundingBox();
+ IntRect layerRect = enclosingIntRect(CCMathUtil::projectClippedRect(surfaceToLayer, FloatRect(minimalSurfaceRect)));
layerRect.intersect(layerBoundRect);
return layerRect;
}
+template<typename LayerType>
+static IntRect calculateVisibleLayerRect(LayerType* layer)
+{
+ ASSERT(layer->targetRenderSurface());
+
+ // Animated layers can exist in the render surface tree that are not visible currently
+ // and have their back face showing. In this case, their visible rect should be empty.
+ if (!layer->doubleSided() && layer->screenSpaceTransform().isBackFaceVisible())
+ return IntRect();
+
+ IntRect targetSurfaceRect = layer->targetRenderSurface()->contentRect();
+
+ if (layer->usesLayerClipping())
+ targetSurfaceRect.intersect(layer->clipRect());
+
+ if (targetSurfaceRect.isEmpty() || layer->contentBounds().isEmpty())
+ return targetSurfaceRect;
+
+ // Note carefully these are aliases
+ const IntSize& bounds = layer->bounds();
+ const IntSize& contentBounds = layer->contentBounds();
+
+ const IntRect layerBoundRect = IntRect(IntPoint(), contentBounds);
+ TransformationMatrix transform = layer->drawTransform();
+
+ transform.scaleNonUniform(bounds.width() / static_cast<double>(contentBounds.width()),
+ bounds.height() / static_cast<double>(contentBounds.height()));
+ transform.translate(-contentBounds.width() / 2.0, -contentBounds.height() / 2.0);
+
+ IntRect visibleLayerRect = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerBoundRect, transform);
+ return visibleLayerRect;
+}
+
static bool isScaleOrTranslation(const TransformationMatrix& m)
{
return !m.m12() && !m.m13() && !m.m14()
&& !m.m21() && !m.m23() && !m.m24()
&& !m.m31() && !m.m32() && !m.m43()
&& m.m44();
+}
+
+static inline bool layerOpacityIsOpaque(CCLayerImpl* layer)
+{
+ return layer->opacity() == 1;
+}
+
+static inline bool layerOpacityIsOpaque(LayerChromium* layer)
+{
+ // If the opacity is being animated then the opacity on the main thread is unreliable
+ // (since the impl thread may be using a different opacity), so it should not be trusted.
+ // In particular, it should not be treated as opaque.
+ return layer->opacity() == 1 && !layer->opacityIsAnimating();
+}
+
+static inline bool transformToParentIsKnown(CCLayerImpl*)
+{
+ return true;
+}
+
+static inline bool transformToParentIsKnown(LayerChromium* layer)
+{
+ return !layer->transformIsAnimating();
+}
+
+static inline bool transformToScreenIsKnown(CCLayerImpl*)
+{
+ return true;
+}
+static inline bool transformToScreenIsKnown(LayerChromium* layer)
+{
+ return !layer->screenSpaceTransformIsAnimating();
}
template<typename LayerType>
@@ -83,27 +151,37 @@ static bool layerShouldBeSkipped(LayerType* layer)
// Some additional conditions need to be computed at a later point after the recursion is finished.
// - the intersection of render surface content and layer clipRect is empty
// - the visibleLayerRect is empty
+ //
+ // Note, if the layer should not have been drawn due to being fully transparent,
+ // we would have skipped the entire subtree and never made it into this function,
+ // so it is safe to omit this check here.
- if (!layer->drawsContent() || !layer->opacity() || layer->bounds().isEmpty())
+ if (!layer->drawsContent() || layer->bounds().isEmpty())
return true;
- // The layer should not be drawn if (1) it is not double-sided and (2) the back of the layer is facing the screen.
- // This second condition is checked by computing the transformed normal of the layer.
- if (!layer->doubleSided()) {
- FloatRect layerRect(FloatPoint(0, 0), FloatSize(layer->bounds()));
- FloatQuad mappedLayer = layer->screenSpaceTransform().mapQuad(FloatQuad(layerRect));
- FloatSize horizontalDir = mappedLayer.p2() - mappedLayer.p1();
- FloatSize verticalDir = mappedLayer.p4() - mappedLayer.p1();
- FloatPoint3D xAxis(horizontalDir.width(), horizontalDir.height(), 0);
- FloatPoint3D yAxis(verticalDir.width(), verticalDir.height(), 0);
- FloatPoint3D zAxis = xAxis.cross(yAxis);
- if (zAxis.z() < 0)
- return true;
- }
+ // The layer should not be drawn if (1) it is not double-sided and (2) the back of the layer is known to be facing the screen.
+ if (!layer->doubleSided() && transformToScreenIsKnown(layer) && layer->screenSpaceTransform().isBackFaceVisible())
+ return true;
return false;
}
+static inline bool subtreeShouldBeSkipped(CCLayerImpl* layer)
+{
+ // The opacity of a layer always applies to its children (either implicitly
+ // via a render surface or explicitly if the parent preserves 3D), so the
+ // entire subtree can be skipped if this layer is fully transparent.
+ return !layer->opacity();
+}
+
+static inline bool subtreeShouldBeSkipped(LayerChromium* layer)
+{
+ // If the opacity is being animated then the opacity on the main thread is unreliable
+ // (since the impl thread may be using a different opacity), so it should not be trusted.
+ // In particular, it should not cause the subtree to be skipped.
+ return !layer->opacity() && !layer->opacityIsAnimating();
+}
+
template<typename LayerType>
static bool subtreeShouldRenderToSeparateSurface(LayerType* layer, bool axisAlignedWithRespectToParent)
{
@@ -128,7 +206,7 @@ static bool subtreeShouldRenderToSeparateSurface(LayerType* layer, bool axisAlig
return true;
// If the layer uses a CSS filter.
- if (!layer->filters().isEmpty())
+ if (!layer->filters().isEmpty() || !layer->backgroundFilters().isEmpty())
return true;
// If the layer flattens its subtree (i.e. the layer doesn't preserve-3d), but it is
@@ -136,12 +214,18 @@ static bool subtreeShouldRenderToSeparateSurface(LayerType* layer, bool axisAlig
if (layer->parent() && layer->parent()->preserves3D() && !layer->preserves3D() && descendantDrawsContent)
return true;
+ // On the main thread side, animating transforms are unknown, and may cause a RenderSurface on the impl side.
+ // Since they are cheap, we create a rendersurface for all animating transforms to cover these cases, and so
+ // that we can consider descendants as not animating relative to their target to aid culling.
+ if (!transformToParentIsKnown(layer) && descendantDrawsContent)
+ return true;
+
// If the layer clips its descendants but it is not axis-aligned with respect to its parent.
if (layer->masksToBounds() && !axisAlignedWithRespectToParent && descendantDrawsContent)
return true;
// If the layer has opacity != 1 and does not have a preserves-3d transform style.
- if (layer->opacity() != 1 && !layer->preserves3D() && descendantDrawsContent)
+ if (!layerOpacityIsOpaque(layer) && !layer->preserves3D() && descendantDrawsContent)
return true;
return false;
@@ -229,15 +313,35 @@ static bool calculateDrawTransformsAndVisibilityInternal(LayerType* layer, Layer
// P is the projection matrix
// S is the scale adjustment (to scale up to the layer size)
//
+ // When a render surface has a replica layer, that layer's transform is used to draw a second copy of the surface.
+ // Transforms named here are relative to the surface, unless they specify they are relative to the replica layer.
+ //
+ // The render surface origin transform to its target surface origin is:
+ // M[surfaceOrigin] = M[owningLayer->Draw] * Tr[origin2center].inverse()
+ //
+ // The render surface origin transform to its the root (screen space) origin is:
+ // M[surface2root] = M[owningLayer->screenspace]
+ //
+ // The replica draw transform is:
+ // M[replicaDraw] = M[surfaceOrigin] * Tr[replica->position()] * Tr[replica] * Tr[anchor2center]
+ // = M[owningLayer->draw] * Tr[origin2center].inverse() * Tr[replica->position()] * Tr[replica] * Tr[anchor2clippedCenter]
+ //
+ // The replica origin transform to its target surface origin is:
+ // M[replicaOrigin] = M[surfaceOrigin] * Tr[replica->position()] * Tr[replica] * Tr[origin2anchor].inverse()
+ //
+ // The replica origin transform to the root (screen space) origin is:
+ // M[replica2root] = M[surface2root] * Tr[replica->position()] * Tr[replica] * Tr[origin2anchor].inverse()
+ //
+
+ if (subtreeShouldBeSkipped(layer))
+ return false;
float drawOpacity = layer->opacity();
- if (layer->parent() && layer->parent()->preserves3D())
+ bool drawOpacityIsAnimating = layer->opacityIsAnimating();
+ if (layer->parent() && layer->parent()->preserves3D()) {
drawOpacity *= layer->parent()->drawOpacity();
- // The opacity of a layer always applies to its children (either implicitly
- // via a render surface or explicitly if the parent preserves 3D), so the
- // entire subtree can be skipped if this layer is fully transparent.
- if (!drawOpacity)
- return false;
+ drawOpacityIsAnimating |= layer->parent()->drawOpacityIsAnimating();
+ }
IntSize bounds = layer->bounds();
FloatPoint anchorPoint = layer->anchorPoint();
@@ -260,6 +364,13 @@ static bool calculateDrawTransformsAndVisibilityInternal(LayerType* layer, Layer
TransformationMatrix combinedTransform = parentMatrix;
combinedTransform = combinedTransform.multiply(layerLocalTransform);
+ bool animatingTransformToTarget = layer->transformIsAnimating();
+ bool animatingTransformToScreen = animatingTransformToTarget;
+ if (layer->parent()) {
+ animatingTransformToTarget |= layer->parent()->drawTransformIsAnimating();
+ animatingTransformToScreen |= layer->parent()->screenSpaceTransformIsAnimating();
+ }
+
FloatRect layerRect(-0.5 * layer->bounds().width(), -0.5 * layer->bounds().height(), layer->bounds().width(), layer->bounds().height());
IntRect transformedLayerRect;
@@ -286,20 +397,32 @@ static bool calculateDrawTransformsAndVisibilityInternal(LayerType* layer, Layer
// The opacity value is moved from the layer to its surface, so that the entire subtree properly inherits opacity.
renderSurface->setDrawOpacity(drawOpacity);
+ renderSurface->setDrawOpacityIsAnimating(drawOpacityIsAnimating);
layer->setDrawOpacity(1);
+ layer->setDrawOpacityIsAnimating(false);
+
+ TransformationMatrix surfaceOriginTransform = combinedTransform;
+ surfaceOriginTransform.translate3d(-0.5 * bounds.width(), -0.5 * bounds.height(), 0);
+ renderSurface->setOriginTransform(surfaceOriginTransform);
- TransformationMatrix layerOriginTransform = combinedTransform;
- layerOriginTransform.translate3d(-0.5 * bounds.width(), -0.5 * bounds.height(), 0);
- renderSurface->setOriginTransform(layerOriginTransform);
+ renderSurface->setTargetSurfaceTransformsAreAnimating(animatingTransformToTarget);
+ renderSurface->setScreenSpaceTransformsAreAnimating(animatingTransformToScreen);
+ animatingTransformToTarget = false;
+ layer->setDrawTransformIsAnimating(animatingTransformToTarget);
+ layer->setScreenSpaceTransformIsAnimating(animatingTransformToScreen);
// Update the aggregate hierarchy matrix to include the transform of the newly created RenderSurface.
- nextHierarchyMatrix.multiply(layerOriginTransform);
+ nextHierarchyMatrix.multiply(surfaceOriginTransform);
// The render surface clipRect contributes to the scissor rect that needs to
// be applied before drawing the render surface onto its containing
// surface and is therefore expressed in the parent's coordinate system.
renderSurface->setClipRect(layer->parent() ? layer->parent()->clipRect() : layer->clipRect());
+ // The layer's clipRect can be reset here. The renderSurface will correctly clip the subtree.
+ layer->setUsesLayerClipping(false);
+ layer->setClipRect(IntRect());
+
if (layer->maskLayer()) {
renderSurface->setMaskLayer(layer->maskLayer());
layer->maskLayer()->setTargetRenderSurface(renderSurface);
@@ -314,12 +437,17 @@ static bool calculateDrawTransformsAndVisibilityInternal(LayerType* layer, Layer
nearestAncestorThatMovesPixels = renderSurface;
renderSurface->setNearestAncestorThatMovesPixels(nearestAncestorThatMovesPixels);
+ renderSurface->setBackgroundFilters(layer->backgroundFilters());
+
renderSurfaceLayerList.append(layer);
} else {
layer->setDrawTransform(combinedTransform);
- transformedLayerRect = enclosingIntRect(layer->drawTransform().mapRect(layerRect));
+ layer->setDrawTransformIsAnimating(animatingTransformToTarget);
+ layer->setScreenSpaceTransformIsAnimating(animatingTransformToScreen);
+ transformedLayerRect = enclosingIntRect(CCMathUtil::mapClippedRect(layer->drawTransform(), layerRect));
layer->setDrawOpacity(drawOpacity);
+ layer->setDrawOpacityIsAnimating(drawOpacityIsAnimating);
if (layer != rootLayer) {
ASSERT(layer->parent());
@@ -333,13 +461,18 @@ static bool calculateDrawTransformsAndVisibilityInternal(LayerType* layer, Layer
// Layers without their own renderSurface will render into the nearest ancestor surface.
layer->setTargetRenderSurface(layer->parent()->targetRenderSurface());
}
+ }
+
+ if (layer->masksToBounds()) {
+ IntRect clipRect = transformedLayerRect;
- if (layer->masksToBounds()) {
- IntRect clipRect = transformedLayerRect;
+ // If the layer already inherited a clipRect, we need to intersect with it before
+ // overriding the layer's clipRect and usesLayerClipping.
+ if (layer->usesLayerClipping())
clipRect.intersect(layer->clipRect());
- layer->setClipRect(clipRect);
- layer->setUsesLayerClipping(true);
- }
+
+ layer->setClipRect(clipRect);
+ layer->setUsesLayerClipping(true);
}
// Note that at this point, layer->drawTransform() is not necessarily the same as local variable drawTransform.
@@ -449,14 +582,29 @@ static bool calculateDrawTransformsAndVisibilityInternal(LayerType* layer, Layer
drawTransform.translate3d(surfaceCenter.x() + centerOffsetDueToClipping.width(), surfaceCenter.y() + centerOffsetDueToClipping.height(), 0);
renderSurface->setDrawTransform(drawTransform);
- // Compute the transformation matrix used to draw the replica of the render
- // surface.
+ // The layer's origin is equal to the surface's origin so the screenSpaceTransform is the same.
+ renderSurface->setScreenSpaceTransform(layer->screenSpaceTransform());
+
if (layer->replicaLayer()) {
+ // Compute the transformation matrix used to draw the surface's replica to the target surface.
TransformationMatrix replicaDrawTransform = renderSurface->originTransform();
- replicaDrawTransform.translate3d(layer->replicaLayer()->position().x(), layer->replicaLayer()->position().y(), 0);
+ replicaDrawTransform.translate(layer->replicaLayer()->position().x(), layer->replicaLayer()->position().y());
replicaDrawTransform.multiply(layer->replicaLayer()->transform());
- replicaDrawTransform.translate3d(surfaceCenter.x() - anchorPoint.x() * bounds.width(), surfaceCenter.y() - anchorPoint.y() * bounds.height(), 0);
+ replicaDrawTransform.translate(surfaceCenter.x() - anchorPoint.x() * bounds.width(), surfaceCenter.y() - anchorPoint.y() * bounds.height());
renderSurface->setReplicaDrawTransform(replicaDrawTransform);
+
+ TransformationMatrix surfaceOriginToReplicaOriginTransform;
+ surfaceOriginToReplicaOriginTransform.translate(layer->replicaLayer()->position().x(), layer->replicaLayer()->position().y());
+ surfaceOriginToReplicaOriginTransform.multiply(layer->replicaLayer()->transform());
+ surfaceOriginToReplicaOriginTransform.translate(-anchorPoint.x() * bounds.width(), -anchorPoint.y() * bounds.height());
+
+ // Compute the replica's "originTransform" that maps from the replica's origin space to the target surface origin space.
+ TransformationMatrix replicaOriginTransform = layer->renderSurface()->originTransform() * surfaceOriginToReplicaOriginTransform;
+ renderSurface->setReplicaOriginTransform(replicaOriginTransform);
+
+ // Compute the replica's "screenSpaceTransform" that maps from the replica's origin space to the screen's origin space.
+ TransformationMatrix replicaScreenSpaceTransform = layer->renderSurface()->screenSpaceTransform() * surfaceOriginToReplicaOriginTransform;
+ renderSurface->setReplicaScreenSpaceTransform(replicaScreenSpaceTransform);
}
// If a render surface has no layer list, then it and none of its children needed to get drawn.
@@ -502,7 +650,7 @@ static void walkLayersAndCalculateVisibleLayerRects(const LayerList& renderSurfa
CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
if (!it.representsTargetRenderSurface()) {
- IntRect visibleLayerRect = CCLayerTreeHostCommon::calculateVisibleLayerRect<LayerType>(*it);
+ IntRect visibleLayerRect = calculateVisibleLayerRect(*it);
it->setVisibleLayerRect(visibleLayerRect);
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.h
index df23cd01f..3762f64b1 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.h
@@ -40,7 +40,6 @@ class LayerChromium;
class CCLayerTreeHostCommon {
public:
static IntRect calculateVisibleRect(const IntRect& targetSurfaceRect, const IntRect& layerBoundRect, const TransformationMatrix&);
- template<typename LayerType> static IntRect calculateVisibleLayerRect(LayerType*);
static void calculateDrawTransformsAndVisibility(LayerChromium*, LayerChromium* rootLayer, const TransformationMatrix& parentMatrix, const TransformationMatrix& fullHierarchyMatrix, Vector<RefPtr<LayerChromium> >& renderSurfaceLayerList, Vector<RefPtr<LayerChromium> >& layerList, int maxTextureSize);
static void calculateDrawTransformsAndVisibility(CCLayerImpl*, CCLayerImpl* rootLayer, const TransformationMatrix& parentMatrix, const TransformationMatrix& fullHierarchyMatrix, Vector<CCLayerImpl*>& renderSurfaceLayerList, Vector<CCLayerImpl*>& layerList, CCLayerSorter*, int maxTextureSize);
@@ -59,33 +58,6 @@ struct CCScrollAndScaleSet {
};
template<typename LayerType>
-IntRect CCLayerTreeHostCommon::calculateVisibleLayerRect(LayerType* layer)
-{
- ASSERT(layer->targetRenderSurface());
- IntRect targetSurfaceRect = layer->targetRenderSurface()->contentRect();
-
- if (layer->usesLayerClipping())
- targetSurfaceRect.intersect(layer->clipRect());
-
- if (targetSurfaceRect.isEmpty() || layer->contentBounds().isEmpty())
- return targetSurfaceRect;
-
- // Note carefully these are aliases
- const IntSize& bounds = layer->bounds();
- const IntSize& contentBounds = layer->contentBounds();
-
- const IntRect layerBoundRect = IntRect(IntPoint(), contentBounds);
- TransformationMatrix transform = layer->drawTransform();
-
- transform.scaleNonUniform(bounds.width() / static_cast<double>(contentBounds.width()),
- bounds.height() / static_cast<double>(contentBounds.height()));
- transform.translate(-contentBounds.width() / 2.0, -contentBounds.height() / 2.0);
-
- IntRect visibleLayerRect = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerBoundRect, transform);
- return visibleLayerRect;
-}
-
-template<typename LayerType>
bool CCLayerTreeHostCommon::renderSurfaceContributesToTarget(LayerType* layer, int targetSurfaceLayerID)
{
// A layer will either contribute its own content, or its render surface's content, to
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp
index 002e7826d..3ea5fb19a 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp
@@ -30,8 +30,14 @@
#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h"
#include "TraceEvent.h"
+#include "cc/CCActiveGestureAnimation.h"
#include "cc/CCDamageTracker.h"
+#include "cc/CCDebugRectHistory.h"
#include "cc/CCDelayBasedTimeSource.h"
+#include "cc/CCFontAtlas.h"
+#include "cc/CCFrameRateCounter.h"
+#include "cc/CCGestureCurve.h"
+#include "cc/CCHeadsUpDisplay.h"
#include "cc/CCLayerIterator.h"
#include "cc/CCLayerTreeHost.h"
#include "cc/CCLayerTreeHostCommon.h"
@@ -42,6 +48,17 @@
namespace {
const double lowFrequencyAnimationInterval = 1;
+
+void didVisibilityChange(WebCore::CCLayerTreeHostImpl* id, bool visible)
+{
+ if (visible) {
+ TRACE_EVENT_ASYNC_BEGIN1("webkit", "CCLayerTreeHostImpl::setVisible", id, "CCLayerTreeHostImpl", id);
+ return;
+ }
+
+ TRACE_EVENT_ASYNC_END0("webkit", "CCLayerTreeHostImpl::setVisible", id);
+}
+
} // namespace
namespace WebCore {
@@ -59,7 +76,7 @@ public:
m_timeSource->setActive(false);
}
- virtual void onTimerTick()
+ virtual void onTimerTick() OVERRIDE
{
m_layerTreeHostImpl->animate(monotonicallyIncreasingTime(), currentTime());
}
@@ -94,6 +111,7 @@ CCLayerTreeHostImpl::CCLayerTreeHostImpl(const CCSettings& settings, CCLayerTree
, m_scrollLayerImpl(0)
, m_settings(settings)
, m_visible(true)
+ , m_headsUpDisplay(CCHeadsUpDisplay::create())
, m_pageScale(1)
, m_pageScaleDelta(1)
, m_sentPageScaleDelta(1)
@@ -102,16 +120,20 @@ CCLayerTreeHostImpl::CCLayerTreeHostImpl(const CCSettings& settings, CCLayerTree
, m_needsAnimateLayers(false)
, m_pinchGestureActive(false)
, m_timeSourceClientAdapter(CCLayerTreeHostImplTimeSourceAdapter::create(this, CCDelayBasedTimeSource::create(lowFrequencyAnimationInterval * 1000.0, CCProxy::currentThread())))
+ , m_fpsCounter(CCFrameRateCounter::create())
+ , m_debugRectHistory(CCDebugRectHistory::create())
{
ASSERT(CCProxy::isImplThread());
+ didVisibilityChange(this, m_visible);
}
CCLayerTreeHostImpl::~CCLayerTreeHostImpl()
{
ASSERT(CCProxy::isImplThread());
TRACE_EVENT("CCLayerTreeHostImpl::~CCLayerTreeHostImpl()", this, 0);
- if (m_layerRenderer)
- m_layerRenderer->close();
+
+ if (m_rootLayerImpl)
+ clearRenderSurfacesOnCCLayerImplRecursive(m_rootLayerImpl.get());
}
void CCLayerTreeHostImpl::beginCommit()
@@ -127,10 +149,12 @@ void CCLayerTreeHostImpl::commitComplete()
bool CCLayerTreeHostImpl::canDraw()
{
- if (!rootLayer())
+ if (!m_rootLayerImpl)
return false;
if (viewportSize().isEmpty())
return false;
+ if (!m_layerRenderer)
+ return false;
return true;
}
@@ -143,6 +167,7 @@ void CCLayerTreeHostImpl::animate(double monotonicTime, double wallClockTime)
{
animatePageScale(monotonicTime);
animateLayers(monotonicTime, wallClockTime);
+ animateGestures(monotonicTime);
}
void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTime, double duration)
@@ -150,7 +175,7 @@ void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition,
if (!m_scrollLayerImpl)
return;
- IntSize scrollTotal = toSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
+ IntSize scrollTotal = flooredIntSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
scrollTotal.scale(m_pageScaleDelta);
float scaleTotal = m_pageScale * m_pageScaleDelta;
IntSize scaledContentSize = contentSize();
@@ -170,6 +195,19 @@ void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition,
m_client->setNeedsCommitOnImplThread();
}
+void CCLayerTreeHostImpl::setActiveGestureAnimation(PassOwnPtr<CCActiveGestureAnimation> gestureAnimation)
+{
+ m_activeGestureAnimation = gestureAnimation;
+
+ if (m_activeGestureAnimation)
+ m_client->setNeedsRedrawOnImplThread();
+}
+
+void CCLayerTreeHostImpl::scheduleAnimation()
+{
+ m_client->setNeedsRedrawOnImplThread();
+}
+
void CCLayerTreeHostImpl::trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList)
{
// For now, we use damage tracking to compute a global scissor. To do this, we must
@@ -180,31 +218,16 @@ void CCLayerTreeHostImpl::trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer,
CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface();
ASSERT(renderSurface);
- renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurfaceLayer->maskLayer());
+ renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurface->surfacePropertyChangedOnlyFromDescendant(), renderSurface->contentRect(), renderSurfaceLayer->maskLayer(), renderSurfaceLayer->filters());
}
}
-static TransformationMatrix computeScreenSpaceTransformForSurface(CCLayerImpl* renderSurfaceLayer)
-{
- // The layer's screen space transform can be written as:
- // layerScreenSpaceTransform = surfaceScreenSpaceTransform * layerOriginTransform
- // So, to compute the surface screen space, we can do:
- // surfaceScreenSpaceTransform = layerScreenSpaceTransform * inverse(layerOriginTransform)
-
- TransformationMatrix layerOriginTransform = renderSurfaceLayer->drawTransform();
- layerOriginTransform.translate(-0.5 * renderSurfaceLayer->bounds().width(), -0.5 * renderSurfaceLayer->bounds().height());
- TransformationMatrix surfaceScreenSpaceTransform = renderSurfaceLayer->screenSpaceTransform();
- surfaceScreenSpaceTransform.multiply(layerOriginTransform.inverse());
-
- return surfaceScreenSpaceTransform;
-}
-
static FloatRect damageInSurfaceSpace(CCLayerImpl* renderSurfaceLayer, const FloatRect& rootDamageRect)
{
FloatRect surfaceDamageRect;
// For now, we conservatively use the root damage as the damage for
// all surfaces, except perspective transforms.
- TransformationMatrix screenSpaceTransform = computeScreenSpaceTransformForSurface(renderSurfaceLayer);
+ const TransformationMatrix& screenSpaceTransform = renderSurfaceLayer->renderSurface()->screenSpaceTransform();
if (screenSpaceTransform.hasPerspective()) {
// Perspective projections do not play nice with mapRect of
// inverse transforms. In this uncommon case, its simpler to
@@ -219,27 +242,40 @@ static FloatRect damageInSurfaceSpace(CCLayerImpl* renderSurfaceLayer, const Flo
return surfaceDamageRect;
}
-void CCLayerTreeHostImpl::calculateRenderPasses(CCRenderPassList& passes, CCLayerList& renderSurfaceLayerList)
+void CCLayerTreeHostImpl::calculateRenderSurfaceLayerList(CCLayerList& renderSurfaceLayerList)
{
- renderSurfaceLayerList.append(rootLayer());
+ ASSERT(renderSurfaceLayerList.isEmpty());
+
+ renderSurfaceLayerList.append(m_rootLayerImpl.get());
- if (!rootLayer()->renderSurface())
- rootLayer()->createRenderSurface();
- rootLayer()->renderSurface()->clearLayerList();
- rootLayer()->renderSurface()->setContentRect(IntRect(IntPoint(), viewportSize()));
+ if (!m_rootLayerImpl->renderSurface())
+ m_rootLayerImpl->createRenderSurface();
+ m_rootLayerImpl->renderSurface()->clearLayerList();
+ m_rootLayerImpl->renderSurface()->setContentRect(IntRect(IntPoint(), viewportSize()));
- rootLayer()->setClipRect(IntRect(IntPoint(), viewportSize()));
+ m_rootLayerImpl->setClipRect(IntRect(IntPoint(), viewportSize()));
{
TransformationMatrix identityMatrix;
TRACE_EVENT("CCLayerTreeHostImpl::calcDrawEtc", this, 0);
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootLayer(), rootLayer(), identityMatrix, identityMatrix, renderSurfaceLayerList, rootLayer()->renderSurface()->layerList(), &m_layerSorter, layerRendererCapabilities().maxTextureSize);
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(m_rootLayerImpl.get(), m_rootLayerImpl.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, m_rootLayerImpl->renderSurface()->layerList(), &m_layerSorter, layerRendererCapabilities().maxTextureSize);
}
+}
- if (layerRendererCapabilities().usingPartialSwap)
- trackDamageForAllSurfaces(rootLayer(), renderSurfaceLayerList);
- m_rootDamageRect = rootLayer()->renderSurface()->damageTracker()->currentDamageRect();
+bool CCLayerTreeHostImpl::calculateRenderPasses(CCRenderPassList& passes, CCLayerList& renderSurfaceLayerList)
+{
+ ASSERT(passes.isEmpty());
+
+ calculateRenderSurfaceLayerList(renderSurfaceLayerList);
+ TRACE_EVENT1("webkit", "CCLayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast<long long unsigned>(renderSurfaceLayerList.size()));
+
+ if (layerRendererCapabilities().usingPartialSwap || settings().showSurfaceDamageRects)
+ trackDamageForAllSurfaces(m_rootLayerImpl.get(), renderSurfaceLayerList);
+ m_rootDamageRect = m_rootLayerImpl->renderSurface()->damageTracker()->currentDamageRect();
+
+ // Create the render passes in dependency order.
+ HashMap<CCRenderSurface*, CCRenderPass*> surfacePassMap;
for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface();
@@ -251,53 +287,68 @@ void CCLayerTreeHostImpl::calculateRenderPasses(CCRenderPassList& passes, CCLaye
surfaceDamageRect = damageInSurfaceSpace(renderSurfaceLayer, m_rootDamageRect);
pass->setSurfaceDamageRect(surfaceDamageRect);
- const CCLayerList& layerList = renderSurface->layerList();
- for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) {
- CCLayerImpl* layer = layerList[layerIndex];
- if (layer->visibleLayerRect().isEmpty())
- continue;
+ surfacePassMap.add(renderSurface, pass.get());
+ passes.append(pass.release());
+ }
- if (CCLayerTreeHostCommon::renderSurfaceContributesToTarget(layer, renderSurfaceLayer->id())) {
- pass->appendQuadsForRenderSurfaceLayer(layer);
- continue;
- }
+ IntRect scissorRect;
+ if (layerRendererCapabilities().usingPartialSwap)
+ scissorRect = enclosingIntRect(m_rootDamageRect);
+ else
+ scissorRect = IntRect(IntPoint(), viewportSize());
- layer->willDraw(m_layerRenderer.get());
- pass->appendQuadsForLayer(layer);
- }
+ bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off.
+ CCOcclusionTrackerImpl occlusionTracker(scissorRect, recordMetricsForFrame);
+ occlusionTracker.setMinimumTrackingSize(CCOcclusionTrackerImpl::preferredMinimumTrackingSize());
- passes.append(pass.release());
- }
-}
+ // Add quads to the Render passes in FrontToBack order to allow for testing occlusion and performing culling during the tree walk.
+ typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
-void CCLayerTreeHostImpl::optimizeRenderPasses(CCRenderPassList& passes)
-{
- TRACE_EVENT1("webkit", "CCLayerTreeHostImpl::optimizeRenderPasses", "passes.size()", static_cast<long long unsigned>(passes.size()));
+ // Typically when we are missing a texture and use a checkerboard quad, we still draw the frame. However when the layer being
+ // checkerboarded is moving due to an impl-animation, we drop the frame to avoid flashing due to the texture suddenly appearing
+ // in the future.
+ bool drawFrame = true;
+
+ CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
+ for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
+ CCRenderSurface* renderSurface = it.targetRenderSurfaceLayer()->renderSurface();
+ CCRenderPass* pass = surfacePassMap.get(renderSurface);
+ bool hadMissingTiles = false;
- bool haveDamageRect = layerRendererCapabilities().usingPartialSwap;
+ occlusionTracker.enterLayer(it);
- // FIXME: compute overdraw metrics only occasionally, not every frame.
- CCOverdrawCounts overdrawCounts;
- for (unsigned i = 0; i < passes.size(); ++i) {
- FloatRect damageRect = passes[i]->surfaceDamageRect();
- passes[i]->optimizeQuads(haveDamageRect, damageRect, &overdrawCounts);
+ if (it.representsContributingRenderSurface())
+ pass->appendQuadsForRenderSurfaceLayer(*it, &occlusionTracker);
+ else if (it.representsItself() && !it->visibleLayerRect().isEmpty()) {
+ it->willDraw(m_layerRenderer.get());
+ pass->appendQuadsForLayer(*it, &occlusionTracker, hadMissingTiles);
+ }
+
+ if (hadMissingTiles) {
+ bool layerHasAnimatingTransform = it->screenSpaceTransformIsAnimating() || it->drawTransformIsAnimating();
+ if (layerHasAnimatingTransform)
+ drawFrame = false;
+ }
+
+ occlusionTracker.leaveLayer(it);
}
- float normalization = 1000.f / (m_layerRenderer->viewportWidth() * m_layerRenderer->viewportHeight());
- PlatformSupport::histogramCustomCounts("Renderer4.pixelOverdrawOpaque", static_cast<int>(normalization * overdrawCounts.m_pixelsDrawnOpaque), 100, 1000000, 50);
- PlatformSupport::histogramCustomCounts("Renderer4.pixelOverdrawTransparent", static_cast<int>(normalization * overdrawCounts.m_pixelsDrawnTransparent), 100, 1000000, 50);
- PlatformSupport::histogramCustomCounts("Renderer4.pixelOverdrawCulled", static_cast<int>(normalization * overdrawCounts.m_pixelsCulled), 100, 1000000, 50);
+ passes.last()->appendQuadsToFillScreen(m_rootLayerImpl.get(), m_backgroundColor, occlusionTracker);
+
+ if (drawFrame)
+ occlusionTracker.overdrawMetrics().recordMetrics(this);
+ return drawFrame;
}
-void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double monotonicTime, double wallClockTime, CCAnimationEventsVector& events, bool& didAnimate, bool& needsAnimateLayers)
+void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double monotonicTime, double wallClockTime, CCAnimationEventsVector* events, bool& didAnimate, bool& needsAnimateLayers)
{
bool subtreeNeedsAnimateLayers = false;
- CCLayerAnimationControllerImpl* currentController = current->layerAnimationController();
+ CCLayerAnimationController* currentController = current->layerAnimationController();
bool hadActiveAnimation = currentController->hasActiveAnimation();
currentController->animate(monotonicTime, events);
- bool startedAnimation = events.size() > 0;
+ bool startedAnimation = events->size() > 0;
// We animated if we either ticked a running animation, or started a new animation.
if (hadActiveAnimation || startedAnimation)
@@ -326,37 +377,72 @@ IntSize CCLayerTreeHostImpl::contentSize() const
return m_scrollLayerImpl->children()[0]->contentBounds();
}
-void CCLayerTreeHostImpl::drawLayers()
+bool CCLayerTreeHostImpl::prepareToDraw(FrameData& frame)
+{
+ TRACE_EVENT("CCLayerTreeHostImpl::prepareToDraw", this, 0);
+
+ frame.renderPasses.clear();
+ frame.renderSurfaceLayerList.clear();
+
+ if (!m_rootLayerImpl)
+ return false;
+
+ if (!calculateRenderPasses(frame.renderPasses, frame.renderSurfaceLayerList)) {
+ // We're missing textures on an animating layer. Request a commit.
+ m_client->setNeedsCommitOnImplThread();
+ return false;
+ }
+
+ // If we return true, then we expect drawLayers() to be called before this function is called again.
+ return true;
+}
+
+void CCLayerTreeHostImpl::setContentsMemoryAllocationLimitBytes(size_t bytes)
+{
+ m_client->postSetContentsMemoryAllocationLimitBytesToMainThreadOnImplThread(bytes);
+}
+
+void CCLayerTreeHostImpl::drawLayers(const FrameData& frame)
{
TRACE_EVENT("CCLayerTreeHostImpl::drawLayers", this, 0);
ASSERT(m_layerRenderer);
- if (!rootLayer())
+ if (!m_rootLayerImpl)
return;
- CCRenderPassList passes;
- CCLayerList renderSurfaceLayerList;
- calculateRenderPasses(passes, renderSurfaceLayerList);
+ // FIXME: use the frame begin time from the overall compositor scheduler.
+ // This value is currently inaccessible because it is up in Chromium's
+ // RenderWidget.
- optimizeRenderPasses(passes);
+ m_fpsCounter->markBeginningOfFrame(currentTime());
+ m_layerRenderer->beginDrawingFrame(m_rootLayerImpl->renderSurface());
- m_layerRenderer->beginDrawingFrame();
- for (size_t i = 0; i < passes.size(); ++i)
- m_layerRenderer->drawRenderPass(passes[i].get());
+ for (size_t i = 0; i < frame.renderPasses.size(); ++i)
+ m_layerRenderer->drawRenderPass(frame.renderPasses[i].get());
- typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::BackToFront> CCLayerIteratorType;
+ if (m_debugRectHistory->enabled(settings()))
+ m_debugRectHistory->saveDebugRectsForCurrentFrame(m_rootLayerImpl.get(), frame.renderSurfaceLayerList, settings());
+
+ if (m_headsUpDisplay->enabled(settings()))
+ m_headsUpDisplay->draw(this);
- CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
- for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
- if (it.representsItself() && !it->visibleLayerRect().isEmpty())
- it->didDraw();
- }
m_layerRenderer->finishDrawingFrame();
++m_frameNumber;
// The next frame should start by assuming nothing has changed, and changes are noted as they occur.
- rootLayer()->resetAllChangeTrackingForSubtree();
+ m_rootLayerImpl->resetAllChangeTrackingForSubtree();
+}
+
+void CCLayerTreeHostImpl::didDrawAllLayers(const FrameData& frame)
+{
+ typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::BackToFront> CCLayerIteratorType;
+
+ CCLayerIteratorType end = CCLayerIteratorType::end(&frame.renderSurfaceLayerList);
+ for (CCLayerIteratorType it = CCLayerIteratorType::begin(&frame.renderSurfaceLayerList); it != end; ++it) {
+ if (it.representsItself() && !it->visibleLayerRect().isEmpty())
+ it->didDraw();
+ }
}
void CCLayerTreeHostImpl::finishAllRendering()
@@ -380,10 +466,12 @@ TextureAllocator* CCLayerTreeHostImpl::contentsTextureAllocator() const
return m_layerRenderer ? m_layerRenderer->contentsTextureAllocator() : 0;
}
-void CCLayerTreeHostImpl::swapBuffers()
+bool CCLayerTreeHostImpl::swapBuffers()
{
ASSERT(m_layerRenderer);
- m_layerRenderer->swapBuffers(enclosingIntRect(m_rootDamageRect));
+
+ m_fpsCounter->markEndOfFrame();
+ return m_layerRenderer->swapBuffers(enclosingIntRect(m_rootDamageRect));
}
void CCLayerTreeHostImpl::didLoseContext()
@@ -432,17 +520,13 @@ void CCLayerTreeHostImpl::setVisible(bool visible)
if (m_visible == visible)
return;
m_visible = visible;
+ didVisibilityChange(this, m_visible);
if (!m_layerRenderer)
return;
m_layerRenderer->setVisible(visible);
- // Reset the damage tracker because the front/back buffers may have been damaged by the GPU
- // process on visibility change.
- if (visible && m_layerRenderer->capabilities().usingPartialSwap)
- setFullRootLayerDamage();
-
const bool shouldTickInBackground = !visible && m_needsAnimateLayers;
m_timeSourceClientAdapter->setActive(shouldTickInBackground);
}
@@ -452,8 +536,10 @@ bool CCLayerTreeHostImpl::initializeLayerRenderer(PassRefPtr<GraphicsContext3D>
OwnPtr<LayerRendererChromium> layerRenderer;
layerRenderer = LayerRendererChromium::create(this, context);
- if (m_layerRenderer) {
- m_layerRenderer->close();
+ // Since we now have a new context/layerRenderer, we cannot continue to use the old
+ // resources (i.e. renderSurfaces and texture IDs).
+ if (m_rootLayerImpl) {
+ clearRenderSurfacesOnCCLayerImplRecursive(m_rootLayerImpl.get());
sendDidLoseContextRecursive(m_rootLayerImpl.get());
}
@@ -506,7 +592,7 @@ void CCLayerTreeHostImpl::adjustScrollsForPageScaleChange(float pageScaleChange)
// We also need to convert impl-side scroll deltas to pageScale space.
if (m_scrollLayerImpl) {
- IntSize scrollDelta = m_scrollLayerImpl->scrollDelta();
+ FloatSize scrollDelta = m_scrollLayerImpl->scrollDelta();
scrollDelta.scale(pageScaleChange);
m_scrollLayerImpl->setScrollDelta(scrollDelta);
}
@@ -665,7 +751,7 @@ void CCLayerTreeHostImpl::computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo
// Compute where the scroll offset/page scale would be if fully pinch-zoomed
// out from the anchor point.
- FloatSize scrollBegin = toSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
+ IntSize scrollBegin = flooredIntSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
scrollBegin.scale(m_pageScaleDelta);
float scaleBegin = m_pageScale * m_pageScaleDelta;
float pageScaleDeltaToSend = m_minPageScale / m_pageScale;
@@ -713,7 +799,7 @@ PassOwnPtr<CCScrollAndScaleSet> CCLayerTreeHostImpl::processScrollDeltas()
// FIXME: track scrolls from layers other than the root
CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
scroll.layerId = m_scrollLayerImpl->id();
- scroll.scrollDelta = m_scrollLayerImpl->scrollDelta();
+ scroll.scrollDelta = flooredIntSize(m_scrollLayerImpl->scrollDelta());
scrollInfo->scrolls.append(scroll);
m_scrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
@@ -723,8 +809,8 @@ PassOwnPtr<CCScrollAndScaleSet> CCLayerTreeHostImpl::processScrollDeltas()
void CCLayerTreeHostImpl::setFullRootLayerDamage()
{
- if (rootLayer()) {
- CCRenderSurface* renderSurface = rootLayer()->renderSurface();
+ if (m_rootLayerImpl) {
+ CCRenderSurface* renderSurface = m_rootLayerImpl->renderSurface();
if (renderSurface)
renderSurface->damageTracker()->forceFullDamageNextUpdate();
}
@@ -732,10 +818,10 @@ void CCLayerTreeHostImpl::setFullRootLayerDamage()
void CCLayerTreeHostImpl::animatePageScale(double monotonicTime)
{
- if (!m_pageScaleAnimation)
+ if (!m_pageScaleAnimation || !m_scrollLayerImpl)
return;
- IntSize scrollTotal = toSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
+ IntSize scrollTotal = flooredIntSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pageScale);
IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime);
@@ -759,7 +845,7 @@ void CCLayerTreeHostImpl::animateLayers(double monotonicTime, double wallClockTi
OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
bool didAnimate = false;
- animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, *events, didAnimate, m_needsAnimateLayers);
+ animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers);
if (!events->isEmpty())
m_client->postAnimationEventsToMainThreadOnImplThread(events.release(), wallClockTime);
@@ -773,14 +859,60 @@ void CCLayerTreeHostImpl::animateLayers(double monotonicTime, double wallClockTi
void CCLayerTreeHostImpl::sendDidLoseContextRecursive(CCLayerImpl* current)
{
- if (!current)
- return;
-
+ ASSERT(current);
current->didLoseContext();
- sendDidLoseContextRecursive(current->maskLayer());
- sendDidLoseContextRecursive(current->replicaLayer());
+ if (current->maskLayer())
+ sendDidLoseContextRecursive(current->maskLayer());
+ if (current->replicaLayer())
+ sendDidLoseContextRecursive(current->replicaLayer());
for (size_t i = 0; i < current->children().size(); ++i)
sendDidLoseContextRecursive(current->children()[i].get());
}
+void CCLayerTreeHostImpl::clearRenderSurfacesOnCCLayerImplRecursive(CCLayerImpl* current)
+{
+ ASSERT(current);
+ for (size_t i = 0; i < current->children().size(); ++i)
+ clearRenderSurfacesOnCCLayerImplRecursive(current->children()[i].get());
+ current->clearRenderSurface();
+}
+
+String CCLayerTreeHostImpl::layerTreeAsText() const
+{
+ TextStream ts;
+ if (m_rootLayerImpl) {
+ ts << m_rootLayerImpl->layerTreeAsText();
+ ts << "RenderSurfaces:\n";
+ dumpRenderSurfaces(ts, 1, m_rootLayerImpl.get());
+ }
+ return ts.release();
+}
+
+void CCLayerTreeHostImpl::setFontAtlas(PassOwnPtr<CCFontAtlas> fontAtlas)
+{
+ m_headsUpDisplay->setFontAtlas(fontAtlas);
+}
+
+void CCLayerTreeHostImpl::dumpRenderSurfaces(TextStream& ts, int indent, const CCLayerImpl* layer) const
+{
+ if (layer->renderSurface())
+ layer->renderSurface()->dumpSurface(ts, indent);
+
+ for (size_t i = 0; i < layer->children().size(); ++i)
+ dumpRenderSurfaces(ts, indent, layer->children()[i].get());
+}
+
+
+void CCLayerTreeHostImpl::animateGestures(double monotonicTime)
+{
+ if (!m_activeGestureAnimation)
+ return;
+
+ bool isContinuing = m_activeGestureAnimation->animate(monotonicTime);
+ if (isContinuing)
+ m_client->setNeedsRedrawOnImplThread();
+ else
+ m_activeGestureAnimation.clear();
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h
index 1cfd0fb67..dde27f68b 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h
@@ -25,6 +25,7 @@
#ifndef CCLayerTreeHostImpl_h
#define CCLayerTreeHostImpl_h
+#include "Color.h"
#include "LayerRendererChromium.h"
#include "cc/CCAnimationEvents.h"
#include "cc/CCInputHandler.h"
@@ -37,7 +38,12 @@
namespace WebCore {
+class CCActiveGestureAnimation;
class CCCompletionEvent;
+class CCDebugRectHistory;
+class CCFontAtlas;
+class CCFrameRateCounter;
+class CCHeadsUpDisplay;
class CCPageScaleAnimation;
class CCLayerImpl;
class CCLayerTreeHostImplTimeSourceAdapter;
@@ -54,17 +60,19 @@ public:
virtual void setNeedsRedrawOnImplThread() = 0;
virtual void setNeedsCommitOnImplThread() = 0;
virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime) = 0;
+ virtual void postSetContentsMemoryAllocationLimitBytesToMainThreadOnImplThread(size_t) = 0;
};
// CCLayerTreeHostImpl owns the CCLayerImpl tree as well as associated rendering state
class CCLayerTreeHostImpl : public CCInputHandlerClient, LayerRendererChromiumClient {
WTF_MAKE_NONCOPYABLE(CCLayerTreeHostImpl);
+ typedef Vector<CCLayerImpl*> CCLayerList;
+
public:
static PassOwnPtr<CCLayerTreeHostImpl> create(const CCSettings&, CCLayerTreeHostImplClient*);
virtual ~CCLayerTreeHostImpl();
// CCInputHandlerClient implementation
- virtual void setNeedsRedraw();
virtual CCInputHandlerClient::ScrollStatus scrollBegin(const IntPoint&, CCInputHandlerClient::ScrollInputType);
virtual void scrollBy(const IntSize&);
virtual void scrollEnd();
@@ -72,25 +80,45 @@ public:
virtual void pinchGestureUpdate(float, const IntPoint&);
virtual void pinchGestureEnd();
virtual void startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTime, double duration);
+ virtual CCActiveGestureAnimation* activeGestureAnimation() { return m_activeGestureAnimation.get(); }
+ // To clear an active animation, pass nullptr.
+ virtual void setActiveGestureAnimation(PassOwnPtr<CCActiveGestureAnimation>);
+ virtual void scheduleAnimation();
+
+ struct FrameData {
+ CCRenderPassList renderPasses;
+ CCLayerList renderSurfaceLayerList;
+ };
// Virtual for testing.
virtual void beginCommit();
virtual void commitComplete();
virtual void animate(double monotonicTime, double wallClockTime);
- virtual void drawLayers();
+
+ // Returns false if problems occured preparing the frame, and we should try
+ // to avoid displaying the frame. If prepareToDraw is called,
+ // didDrawAllLayers must also be called, regardless of whether drawLayers is
+ // called between the two.
+ virtual bool prepareToDraw(FrameData&);
+ virtual void drawLayers(const FrameData&);
+ // Must be called if and only if prepareToDraw was called.
+ void didDrawAllLayers(const FrameData&);
// LayerRendererChromiumClient implementation
- virtual const IntSize& viewportSize() const { return m_viewportSize; }
- virtual const CCSettings& settings() const { return m_settings; }
- virtual CCLayerImpl* rootLayer() { return m_rootLayerImpl.get(); }
- virtual const CCLayerImpl* rootLayer() const { return m_rootLayerImpl.get(); }
- virtual void didLoseContext();
- virtual void onSwapBuffersComplete();
+ virtual const IntSize& viewportSize() const OVERRIDE { return m_viewportSize; }
+ virtual const CCSettings& settings() const OVERRIDE { return m_settings; }
+ virtual void didLoseContext() OVERRIDE;
+ virtual void onSwapBuffersComplete() OVERRIDE;
+ virtual void setFullRootLayerDamage() OVERRIDE;
+ virtual void setContentsMemoryAllocationLimitBytes(size_t) OVERRIDE;
// Implementation
bool canDraw();
GraphicsContext3D* context();
+ String layerTreeAsText() const;
+ void setFontAtlas(PassOwnPtr<CCFontAtlas>);
+
void finishAllRendering();
int frameNumber() const { return m_frameNumber; }
@@ -100,12 +128,13 @@ public:
const LayerRendererCapabilities& layerRendererCapabilities() const;
TextureAllocator* contentsTextureAllocator() const;
- void swapBuffers();
+ bool swapBuffers();
void readback(void* pixels, const IntRect&);
void setRootLayer(PassOwnPtr<CCLayerImpl>);
PassOwnPtr<CCLayerImpl> releaseRootLayer() { return m_rootLayerImpl.release(); }
+ CCLayerImpl* rootLayer() { return m_rootLayerImpl.get(); }
CCLayerImpl* scrollLayer() const { return m_scrollLayerImpl; }
@@ -122,19 +151,24 @@ public:
PassOwnPtr<CCScrollAndScaleSet> processScrollDeltas();
- // Where possible, redraws are scissored to a damage region calculated from changes to
- // layer properties. This function overrides the damage region for the next draw cycle.
- void setFullRootLayerDamage();
-
void startPageScaleAnimation(const IntSize& tragetPosition, bool useAnchor, float scale, double durationSec);
+ const Color& backgroundColor() const { return m_backgroundColor; }
+ void setBackgroundColor(const Color& color) { m_backgroundColor = color; }
+
bool needsAnimateLayers() const { return m_needsAnimateLayers; }
void setNeedsAnimateLayers() { m_needsAnimateLayers = true; }
+ void setNeedsRedraw();
+
+ CCFrameRateCounter* fpsCounter() const { return m_fpsCounter.get(); }
+ CCDebugRectHistory* debugRectHistory() const { return m_debugRectHistory.get(); }
+
protected:
CCLayerTreeHostImpl(const CCSettings&, CCLayerTreeHostImplClient*);
void animatePageScale(double monotonicTime);
+ void animateGestures(double monotonicTime);
// Virtual for testing.
virtual void animateLayers(double monotonicTime, double wallClockTime);
@@ -144,8 +178,6 @@ protected:
int m_frameNumber;
private:
- typedef Vector<CCLayerImpl*> CCLayerList;
-
void computeDoubleTapZoomDeltas(CCScrollAndScaleSet* scrollInfo);
void computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo);
void makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale);
@@ -155,11 +187,18 @@ private:
void adjustScrollsForPageScaleChange(float);
void updateMaxScrollPosition();
void trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList);
- void calculateRenderPasses(CCRenderPassList&, CCLayerList& renderSurfaceLayerList);
- void optimizeRenderPasses(CCRenderPassList&);
- void animateLayersRecursive(CCLayerImpl*, double monotonicTime, double wallClockTime, CCAnimationEventsVector&, bool& didAnimate, bool& needsAnimateLayers);
+ void calculateRenderSurfaceLayerList(CCLayerList&);
+
+ // Returns false if the frame should not be displayed. This function should
+ // only be called from prepareToDraw, as didDrawAllLayers must be called
+ // if this helper function is called.
+ bool calculateRenderPasses(CCRenderPassList&, CCLayerList& renderSurfaceLayerList);
+ void animateLayersRecursive(CCLayerImpl*, double monotonicTime, double wallClockTime, CCAnimationEventsVector*, bool& didAnimate, bool& needsAnimateLayers);
IntSize contentSize() const;
void sendDidLoseContextRecursive(CCLayerImpl*);
+ void clearRenderSurfacesOnCCLayerImplRecursive(CCLayerImpl*);
+
+ void dumpRenderSurfaces(TextStream&, int indent, const CCLayerImpl*) const;
OwnPtr<LayerRendererChromium> m_layerRenderer;
OwnPtr<CCLayerImpl> m_rootLayerImpl;
@@ -168,17 +207,22 @@ private:
IntSize m_viewportSize;
bool m_visible;
+ OwnPtr<CCHeadsUpDisplay> m_headsUpDisplay;
+
float m_pageScale;
float m_pageScaleDelta;
float m_sentPageScaleDelta;
float m_minPageScale, m_maxPageScale;
+ Color m_backgroundColor;
+
// If this is true, it is necessary to traverse the layer tree ticking the animators.
bool m_needsAnimateLayers;
bool m_pinchGestureActive;
IntPoint m_previousPinchAnchor;
OwnPtr<CCPageScaleAnimation> m_pageScaleAnimation;
+ OwnPtr<CCActiveGestureAnimation> m_activeGestureAnimation;
// This is used for ticking animations slowly when hidden.
OwnPtr<CCLayerTreeHostImplTimeSourceAdapter> m_timeSourceClientAdapter;
@@ -186,6 +230,9 @@ private:
CCLayerSorter m_layerSorter;
FloatRect m_rootDamageRect;
+
+ OwnPtr<CCFrameRateCounter> m_fpsCounter;
+ OwnPtr<CCDebugRectHistory> m_debugRectHistory;
};
};
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.cpp
new file mode 100644
index 000000000..ee803da69
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.cpp
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "cc/CCMathUtil.h"
+
+#include "FloatPoint.h"
+#include "FloatQuad.h"
+#include "IntRect.h"
+#include "TransformationMatrix.h"
+
+namespace WebCore {
+
+struct HomogeneousCoordinate {
+ HomogeneousCoordinate(double newX, double newY, double newZ, double newW)
+ : x(newX)
+ , y(newY)
+ , z(newZ)
+ , w(newW)
+ {
+ }
+
+ bool shouldBeClipped() const
+ {
+ return w <= 0;
+ }
+
+ FloatPoint cartesianPoint2d() const
+ {
+ if (w == 1)
+ return FloatPoint(x, y);
+
+ // For now, because this code is used privately only by CCMathUtil, it should never be called when w == 0, and we do not yet need to handle that case.
+ ASSERT(w);
+ double invW = 1.0 / w;
+ return FloatPoint(x * invW, y * invW);
+ }
+
+ double x;
+ double y;
+ double z;
+ double w;
+};
+
+static HomogeneousCoordinate projectPoint(const TransformationMatrix& transform, const FloatPoint& p)
+{
+ double x = p.x();
+ double y = p.y();
+ double z = -(transform.m13() * x + transform.m23() * y + transform.m43()) / transform.m33();
+ // implicit definition of w = 1;
+
+ double outX = x * transform.m11() + y * transform.m21() + z * transform.m31() + transform.m41();
+ double outY = x * transform.m12() + y * transform.m22() + z * transform.m32() + transform.m42();
+ double outZ = x * transform.m13() + y * transform.m23() + z * transform.m33() + transform.m43();
+ double outW = x * transform.m14() + y * transform.m24() + z * transform.m34() + transform.m44();
+
+ return HomogeneousCoordinate(outX, outY, outZ, outW);
+}
+
+static HomogeneousCoordinate mapPoint(const TransformationMatrix& transform, const FloatPoint& p)
+{
+ double x = p.x();
+ double y = p.y();
+ // implicit definition of z = 0;
+ // implicit definition of w = 1;
+
+ double outX = x * transform.m11() + y * transform.m21() + transform.m41();
+ double outY = x * transform.m12() + y * transform.m22() + transform.m42();
+ double outZ = x * transform.m13() + y * transform.m23() + transform.m43();
+ double outW = x * transform.m14() + y * transform.m24() + transform.m44();
+
+ return HomogeneousCoordinate(outX, outY, outZ, outW);
+}
+
+static HomogeneousCoordinate computeClippedPointForEdge(const HomogeneousCoordinate& h1, const HomogeneousCoordinate& h2)
+{
+ // Points h1 and h2 form a line in 4d, and any point on that line can be represented
+ // as an interpolation between h1 and h2:
+ // p = (1-t) h1 + (t) h2
+ //
+ // We want to compute point p such that p.w == epsilon, where epsilon is a small
+ // non-zero number. (but the smaller the number is, the higher the risk of overflow)
+ // To do this, we solve for t in the following equation:
+ // p.w = epsilon = (1-t) * h1.w + (t) * h2.w
+ //
+ // Once paramter t is known, the rest of p can be computed via p = (1-t) h1 + (t) h2.
+
+ // Technically this is a special case of the following assertion, but its a good idea to keep it an explicit sanity check here.
+ ASSERT(h2.w != h1.w);
+ // Exactly one of h1 or h2 (but not both) must be on the negative side of the w plane when this is called.
+ ASSERT(h1.shouldBeClipped() ^ h2.shouldBeClipped());
+
+ double w = 0.00001; // or any positive non-zero small epsilon
+
+ double t = (w - h1.w) / (h2.w - h1.w);
+
+ double x = (1-t) * h1.x + t * h2.x;
+ double y = (1-t) * h1.y + t * h2.y;
+ double z = (1-t) * h1.z + t * h2.z;
+
+ return HomogeneousCoordinate(x, y, z, w);
+}
+
+static inline void expandBoundsToIncludePoint(float& xmin, float& xmax, float& ymin, float& ymax, const FloatPoint& p)
+{
+ xmin = std::min(p.x(), xmin);
+ xmax = std::max(p.x(), xmax);
+ ymin = std::min(p.y(), ymin);
+ ymax = std::max(p.y(), ymax);
+}
+
+static FloatRect computeEnclosingRect(const HomogeneousCoordinate& h1, const HomogeneousCoordinate& h2, const HomogeneousCoordinate& h3, const HomogeneousCoordinate& h4)
+{
+ // This function performs clipping as necessary and computes the enclosing 2d
+ // FloatRect of the vertices. Doing these two steps simultaneously allows us to avoid
+ // the overhead of storing an unknown number of clipped vertices.
+
+ // If no vertices on the quad are clipped, then we can simply return the enclosing rect directly.
+ bool somethingClipped = h1.shouldBeClipped() || h2.shouldBeClipped() || h3.shouldBeClipped() || h4.shouldBeClipped();
+ if (!somethingClipped) {
+ FloatQuad mappedQuad = FloatQuad(h1.cartesianPoint2d(), h2.cartesianPoint2d(), h3.cartesianPoint2d(), h4.cartesianPoint2d());
+ return mappedQuad.boundingBox();
+ }
+
+ bool everythingClipped = h1.shouldBeClipped() && h2.shouldBeClipped() && h3.shouldBeClipped() && h4.shouldBeClipped();
+ if (everythingClipped)
+ return FloatRect();
+
+ float xmin = std::numeric_limits<float>::max();
+ float xmax = std::numeric_limits<float>::min();
+ float ymin = std::numeric_limits<float>::max();
+ float ymax = std::numeric_limits<float>::min();
+
+ if (!h1.shouldBeClipped())
+ expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h1.cartesianPoint2d());
+
+ if (h1.shouldBeClipped() ^ h2.shouldBeClipped())
+ expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h1, h2).cartesianPoint2d());
+
+ if (!h2.shouldBeClipped())
+ expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h2.cartesianPoint2d());
+
+ if (h2.shouldBeClipped() ^ h3.shouldBeClipped())
+ expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h2, h3).cartesianPoint2d());
+
+ if (!h3.shouldBeClipped())
+ expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h3.cartesianPoint2d());
+
+ if (h3.shouldBeClipped() ^ h4.shouldBeClipped())
+ expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h3, h4).cartesianPoint2d());
+
+ if (!h4.shouldBeClipped())
+ expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h4.cartesianPoint2d());
+
+ if (h4.shouldBeClipped() ^ h1.shouldBeClipped())
+ expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h4, h1).cartesianPoint2d());
+
+ return FloatRect(FloatPoint(xmin, ymin), FloatSize(xmax - xmin, ymax - ymin));
+}
+
+static inline void addVertexToClippedQuad(const FloatPoint& newVertex, FloatPoint clippedQuad[8], int& numVerticesInClippedQuad)
+{
+ clippedQuad[numVerticesInClippedQuad] = newVertex;
+ numVerticesInClippedQuad++;
+}
+
+IntRect CCMathUtil::mapClippedRect(const TransformationMatrix& transform, const IntRect& srcRect)
+{
+ return enclosingIntRect(mapClippedRect(transform, FloatRect(srcRect)));
+}
+
+FloatRect CCMathUtil::mapClippedRect(const TransformationMatrix& transform, const FloatRect& srcRect)
+{
+ if (transform.isIdentityOrTranslation()) {
+ FloatRect mappedRect(srcRect);
+ mappedRect.move(static_cast<float>(transform.m41()), static_cast<float>(transform.m42()));
+ return mappedRect;
+ }
+
+ // Apply the transform, but retain the result in homogeneous coordinates.
+ FloatQuad q = FloatQuad(FloatRect(srcRect));
+ HomogeneousCoordinate h1 = mapPoint(transform, q.p1());
+ HomogeneousCoordinate h2 = mapPoint(transform, q.p2());
+ HomogeneousCoordinate h3 = mapPoint(transform, q.p3());
+ HomogeneousCoordinate h4 = mapPoint(transform, q.p4());
+
+ return computeEnclosingRect(h1, h2, h3, h4);
+}
+
+FloatRect CCMathUtil::projectClippedRect(const TransformationMatrix& transform, const FloatRect& srcRect)
+{
+ // Perform the projection, but retain the result in homogeneous coordinates.
+ FloatQuad q = FloatQuad(FloatRect(srcRect));
+ HomogeneousCoordinate h1 = projectPoint(transform, q.p1());
+ HomogeneousCoordinate h2 = projectPoint(transform, q.p2());
+ HomogeneousCoordinate h3 = projectPoint(transform, q.p3());
+ HomogeneousCoordinate h4 = projectPoint(transform, q.p4());
+
+ return computeEnclosingRect(h1, h2, h3, h4);
+}
+
+void CCMathUtil::mapClippedQuad(const TransformationMatrix& transform, const FloatQuad& srcQuad, FloatPoint clippedQuad[8], int& numVerticesInClippedQuad)
+{
+ HomogeneousCoordinate h1 = mapPoint(transform, srcQuad.p1());
+ HomogeneousCoordinate h2 = mapPoint(transform, srcQuad.p2());
+ HomogeneousCoordinate h3 = mapPoint(transform, srcQuad.p3());
+ HomogeneousCoordinate h4 = mapPoint(transform, srcQuad.p4());
+
+ // The order of adding the vertices to the array is chosen so that clockwise / counter-clockwise orientation is retained.
+
+ numVerticesInClippedQuad = 0;
+
+ if (!h1.shouldBeClipped())
+ addVertexToClippedQuad(h1.cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad);
+
+ if (h1.shouldBeClipped() ^ h2.shouldBeClipped())
+ addVertexToClippedQuad(computeClippedPointForEdge(h1, h2).cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad);
+
+ if (!h2.shouldBeClipped())
+ addVertexToClippedQuad(h2.cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad);
+
+ if (h2.shouldBeClipped() ^ h3.shouldBeClipped())
+ addVertexToClippedQuad(computeClippedPointForEdge(h2, h3).cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad);
+
+ if (!h3.shouldBeClipped())
+ addVertexToClippedQuad(h3.cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad);
+
+ if (h3.shouldBeClipped() ^ h4.shouldBeClipped())
+ addVertexToClippedQuad(computeClippedPointForEdge(h3, h4).cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad);
+
+ if (!h4.shouldBeClipped())
+ addVertexToClippedQuad(h4.cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad);
+
+ if (h4.shouldBeClipped() ^ h1.shouldBeClipped())
+ addVertexToClippedQuad(computeClippedPointForEdge(h4, h1).cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad);
+
+ ASSERT(numVerticesInClippedQuad <= 8);
+}
+
+FloatRect CCMathUtil::computeEnclosingRectOfVertices(FloatPoint vertices[], int numVertices)
+{
+ if (numVertices < 2)
+ return FloatRect();
+
+ float xmin = std::numeric_limits<float>::max();
+ float xmax = std::numeric_limits<float>::min();
+ float ymin = std::numeric_limits<float>::max();
+ float ymax = std::numeric_limits<float>::min();
+
+ for (int i = 0; i < numVertices; ++i)
+ expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, vertices[i]);
+
+ return FloatRect(FloatPoint(xmin, ymin), FloatSize(xmax - xmin, ymax - ymin));
+}
+
+FloatQuad CCMathUtil::mapQuad(const TransformationMatrix& transform, const FloatQuad& q, bool& clipped)
+{
+ if (transform.isIdentityOrTranslation()) {
+ FloatQuad mappedQuad(q);
+ mappedQuad.move(static_cast<float>(transform.m41()), static_cast<float>(transform.m42()));
+ clipped = false;
+ return mappedQuad;
+ }
+
+ HomogeneousCoordinate h1 = mapPoint(transform, q.p1());
+ HomogeneousCoordinate h2 = mapPoint(transform, q.p2());
+ HomogeneousCoordinate h3 = mapPoint(transform, q.p3());
+ HomogeneousCoordinate h4 = mapPoint(transform, q.p4());
+
+ clipped = h1.shouldBeClipped() || h2.shouldBeClipped() || h3.shouldBeClipped() || h4.shouldBeClipped();
+
+ // Result will be invalid if clipped == true. But, compute it anyway just in case, to emulate existing behavior.
+ return FloatQuad(h1.cartesianPoint2d(), h2.cartesianPoint2d(), h3.cartesianPoint2d(), h4.cartesianPoint2d());
+}
+
+FloatQuad CCMathUtil::projectQuad(const TransformationMatrix& transform, const FloatQuad& q, bool& clipped)
+{
+ FloatQuad projectedQuad;
+ bool clippedPoint;
+ projectedQuad.setP1(transform.projectPoint(q.p1(), &clippedPoint));
+ clipped = clippedPoint;
+ projectedQuad.setP2(transform.projectPoint(q.p2(), &clippedPoint));
+ clipped |= clippedPoint;
+ projectedQuad.setP3(transform.projectPoint(q.p3(), &clippedPoint));
+ clipped |= clippedPoint;
+ projectedQuad.setP4(transform.projectPoint(q.p4(), &clippedPoint));
+ clipped |= clippedPoint;
+
+ return projectedQuad;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.h b/Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.h
new file mode 100644
index 000000000..398604d9a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CCMathUtil_h
+#define CCMathUtil_h
+
+namespace WebCore {
+
+class IntRect;
+class FloatPoint;
+class FloatRect;
+class FloatQuad;
+class TransformationMatrix;
+
+// This class contains math helper functionality that does not belong in WebCore.
+// It is possible that this functionality should be migrated to WebCore eventually.
+class CCMathUtil {
+public:
+
+ // Background: TransformationMatrix code in WebCore does not do the right thing in
+ // mapRect / mapQuad / projectQuad when there is a perspective projection that causes
+ // one of the transformed vertices to go to w < 0. In those cases, it is necessary to
+ // perform clipping in homogeneous coordinates, after applying the transform, before
+ // dividing-by-w to convert to cartesian coordinates.
+ //
+ // These functions return the axis-aligned rect that encloses the correctly clipped,
+ // transformed polygon.
+ static IntRect mapClippedRect(const TransformationMatrix&, const IntRect&);
+ static FloatRect mapClippedRect(const TransformationMatrix&, const FloatRect&);
+ static FloatRect projectClippedRect(const TransformationMatrix&, const FloatRect&);
+
+ // Returns an array of vertices that represent the clipped polygon. After returning, indexes from
+ // 0 to numVerticesInClippedQuad are valid in the clippedQuad array. Note that
+ // numVerticesInClippedQuad may be zero, which means the entire quad was clipped, and
+ // none of the vertices in the array are valid.
+ static void mapClippedQuad(const TransformationMatrix&, const FloatQuad& srcQuad, FloatPoint clippedQuad[8], int& numVerticesInClippedQuad);
+ static FloatRect computeEnclosingRectOfVertices(FloatPoint vertices[], int numVertices);
+
+ // NOTE: These functions do not do correct clipping against w = 0 plane, but they
+ // correctly detect the clipped condition via the boolean clipped.
+ static FloatQuad mapQuad(const TransformationMatrix&, const FloatQuad&, bool& clipped);
+ static FloatQuad projectQuad(const TransformationMatrix&, const FloatQuad&, bool& clipped);
+};
+
+} // namespace WebCore
+
+#endif // #define CCMathUtil_h
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp
index f1c933882..3d04cfa54 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp
@@ -31,6 +31,7 @@
#include "LayerChromium.h"
#include "cc/CCLayerImpl.h"
+#include "cc/CCMathUtil.h"
#include <algorithm>
@@ -39,19 +40,32 @@ using namespace std;
namespace WebCore {
template<typename LayerType, typename RenderSurfaceType>
-CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace)
+CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace, bool recordMetricsForFrame)
: m_scissorRectInScreenSpace(scissorRectInScreenSpace)
- , m_surfaceDamageClient(0)
- , m_usePaintTracking(true) // FIXME: Remove this when paint tracking is on for paint culling.
+ , m_overdrawMetrics(CCOverdrawMetrics::create(recordMetricsForFrame))
{
}
template<typename LayerType, typename RenderSurfaceType>
-CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace, const DamageClientType* surfaceDamageClient)
- : m_scissorRectInScreenSpace(scissorRectInScreenSpace)
- , m_surfaceDamageClient(surfaceDamageClient)
- , m_usePaintTracking(true) // FIXME: Remove this when paint tracking is on for paint culling.
+void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::enterLayer(const CCLayerIteratorPosition<LayerType>& layerIterator)
+{
+ RenderSurfaceType* renderSurface = layerIterator.targetRenderSurfaceLayer->renderSurface();
+
+ if (layerIterator.representsItself)
+ enterTargetRenderSurface(renderSurface);
+ else if (layerIterator.representsTargetRenderSurface)
+ finishedTargetRenderSurface(layerIterator.currentLayer, renderSurface);
+}
+
+template<typename LayerType, typename RenderSurfaceType>
+void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::leaveLayer(const CCLayerIteratorPosition<LayerType>& layerIterator)
{
+ RenderSurfaceType* renderSurface = layerIterator.targetRenderSurfaceLayer->renderSurface();
+
+ if (layerIterator.representsItself)
+ markOccludedBehindLayer(layerIterator.currentLayer);
+ else if (layerIterator.representsContributingRenderSurface)
+ leaveToTargetRenderSurface(renderSurface);
}
template<typename LayerType, typename RenderSurfaceType>
@@ -64,8 +78,7 @@ void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::enterTargetRenderSurf
const RenderSurfaceType* oldAncestorThatMovesPixels = !oldTarget ? 0 : oldTarget->nearestAncestorThatMovesPixels();
const RenderSurfaceType* newAncestorThatMovesPixels = newTarget->nearestAncestorThatMovesPixels();
- m_stack.append(StackObject());
- m_stack.last().surface = newTarget;
+ m_stack.append(StackObject(newTarget));
// We copy the screen occlusion into the new RenderSurface subtree, but we never copy in the
// target occlusion, since we are looking at a new RenderSurface target.
@@ -82,6 +95,20 @@ void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::enterTargetRenderSurf
}
}
+static inline bool layerOpacityKnown(const LayerChromium* layer) { return !layer->drawOpacityIsAnimating(); }
+static inline bool layerOpacityKnown(const CCLayerImpl*) { return true; }
+static inline bool layerTransformsToTargetKnown(const LayerChromium* layer) { return !layer->drawTransformIsAnimating(); }
+static inline bool layerTransformsToTargetKnown(const CCLayerImpl*) { return true; }
+static inline bool layerTransformsToScreenKnown(const LayerChromium* layer) { return !layer->screenSpaceTransformIsAnimating(); }
+static inline bool layerTransformsToScreenKnown(const CCLayerImpl*) { return true; }
+
+static inline bool surfaceOpacityKnown(const RenderSurfaceChromium* surface) { return !surface->drawOpacityIsAnimating(); }
+static inline bool surfaceOpacityKnown(const CCRenderSurface*) { return true; }
+static inline bool surfaceTransformsToTargetKnown(const RenderSurfaceChromium* surface) { return !surface->targetSurfaceTransformsAreAnimating(); }
+static inline bool surfaceTransformsToTargetKnown(const CCRenderSurface*) { return true; }
+static inline bool surfaceTransformsToScreenKnown(const RenderSurfaceChromium* surface) { return !surface->screenSpaceTransformsAreAnimating(); }
+static inline bool surfaceTransformsToScreenKnown(const CCRenderSurface*) { return true; }
+
template<typename LayerType, typename RenderSurfaceType>
void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::finishedTargetRenderSurface(const LayerType* owningLayer, const RenderSurfaceType* finishedTarget)
{
@@ -91,9 +118,15 @@ void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::finishedTargetRenderS
// Make sure we know about the target surface.
enterTargetRenderSurface(finishedTarget);
- if (owningLayer->maskLayer() || finishedTarget->drawOpacity() < 1 || finishedTarget->filters().hasFilterThatAffectsOpacity()) {
+ // If the occlusion within the surface can not be applied to things outside of the surface's subtree, then clear the occlusion here so it won't be used.
+ if (owningLayer->maskLayer() || !surfaceOpacityKnown(finishedTarget) || finishedTarget->drawOpacity() < 1 || finishedTarget->filters().hasFilterThatAffectsOpacity()) {
m_stack.last().occlusionInScreen = Region();
m_stack.last().occlusionInTarget = Region();
+ } else {
+ if (!surfaceTransformsToTargetKnown(finishedTarget))
+ m_stack.last().occlusionInTarget = Region();
+ if (!surfaceTransformsToScreenKnown(finishedTarget))
+ m_stack.last().occlusionInScreen = Region();
}
}
@@ -103,25 +136,89 @@ static inline Region transformSurfaceOpaqueRegion(const RenderSurfaceType* surfa
// Verify that rects within the |surface| will remain rects in its target surface after applying |transform|. If this is true, then
// apply |transform| to each rect within |region| in order to transform the entire Region.
- IntRect bounds = region.bounds();
- FloatRect centeredBounds(-bounds.width() / 2.0, -bounds.height() / 2.0, bounds.width(), bounds.height());
- FloatQuad transformedBoundsQuad = transform.mapQuad(FloatQuad(centeredBounds));
- if (!transformedBoundsQuad.isRectilinear())
+ bool clipped;
+ FloatQuad transformedBoundsQuad = CCMathUtil::mapQuad(transform, FloatQuad(region.bounds()), clipped);
+ // FIXME: Find a rect interior to each transformed quad.
+ if (clipped || !transformedBoundsQuad.isRectilinear())
return Region();
Region transformedRegion;
- IntRect surfaceBounds = surface->contentRect();
Vector<IntRect> rects = region.rects();
- Vector<IntRect>::const_iterator end = rects.end();
- for (Vector<IntRect>::const_iterator i = rects.begin(); i != end; ++i) {
- FloatRect centeredOriginRect(-i->width() / 2.0 + i->x() - surfaceBounds.x(), -i->height() / 2.0 + i->y() - surfaceBounds.y(), i->width(), i->height());
- FloatRect transformedRect = transform.mapRect(FloatRect(centeredOriginRect));
- transformedRegion.unite(enclosedIntRect(transformedRect));
+ // Clipping has been verified above, so mapRect will give correct results.
+ for (size_t i = 0; i < rects.size(); ++i) {
+ IntRect transformedRect = enclosedIntRect(transform.mapRect(FloatRect(rects[i])));
+ if (!surface->clipRect().isEmpty())
+ transformedRect.intersect(surface->clipRect());
+ transformedRegion.unite(transformedRect);
}
return transformedRegion;
}
+static inline void reduceOcclusion(const IntRect& affectedArea, const IntRect& expandedPixel, Region& occlusion)
+{
+ if (affectedArea.isEmpty())
+ return;
+
+ Region affectedOcclusion = intersect(occlusion, affectedArea);
+ Vector<IntRect> affectedOcclusionRects = affectedOcclusion.rects();
+
+ occlusion.subtract(affectedArea);
+ for (size_t j = 0; j < affectedOcclusionRects.size(); ++j) {
+ IntRect& occlusionRect = affectedOcclusionRects[j];
+
+ // Shrink the rect by expanding the non-opaque pixels outside the rect.
+
+ // The expandedPixel is the IntRect for a single pixel after being
+ // expanded by filters on the layer. The original pixel would be
+ // IntRect(0, 0, 1, 1), and the expanded pixel is the rect, relative
+ // to this original rect, that the original pixel can influence after
+ // being filtered.
+ // To convert the expandedPixel IntRect back to filter outsets:
+ // x = -leftOutset
+ // width = leftOutset + rightOutset
+ // maxX = x + width = -leftOutset + leftOutset + rightOutset = rightOutset
+
+ // The leftOutset of the filters moves pixels on the right side of
+ // the occlusionRect into it, shrinking its right edge.
+ int shrinkLeft = occlusionRect.x() == affectedArea.x() ? 0 : expandedPixel.maxX();
+ int shrinkTop = occlusionRect.y() == affectedArea.y() ? 0 : expandedPixel.maxY();
+ int shrinkRight = occlusionRect.maxX() == affectedArea.maxX() ? 0 : -expandedPixel.x();
+ int shrinkBottom = occlusionRect.maxY() == affectedArea.maxY() ? 0 : -expandedPixel.y();
+
+ occlusionRect.move(shrinkLeft, shrinkTop);
+ occlusionRect.contract(shrinkLeft + shrinkRight, shrinkTop + shrinkBottom);
+
+ occlusion.unite(occlusionRect);
+ }
+}
+
+template<typename RenderSurfaceType>
+static void reduceOcclusionBelowSurface(RenderSurfaceType* surface, const IntRect& surfaceRect, const TransformationMatrix& surfaceTransform, RenderSurfaceType* surfaceTarget, Region& occlusionInTarget, Region& occlusionInScreen)
+{
+ if (surfaceRect.isEmpty())
+ return;
+
+ IntRect boundsInTarget = enclosingIntRect(CCMathUtil::mapClippedRect(surfaceTransform, FloatRect(surfaceRect)));
+ if (!surface->clipRect().isEmpty())
+ boundsInTarget.intersect(surface->clipRect());
+
+ int outsetTop, outsetRight, outsetBottom, outsetLeft;
+ surface->backgroundFilters().getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft);
+
+ // The filter can move pixels from outside of the clip, so allow affectedArea to expand outside the clip.
+ boundsInTarget.move(-outsetLeft, -outsetTop);
+ boundsInTarget.expand(outsetLeft + outsetRight, outsetTop + outsetBottom);
+
+ IntRect boundsInScreen = enclosingIntRect(CCMathUtil::mapClippedRect(surfaceTarget->screenSpaceTransform(), FloatRect(boundsInTarget)));
+
+ IntRect filterOutsetsInTarget(-outsetLeft, -outsetTop, outsetLeft + outsetRight, outsetTop + outsetBottom);
+ IntRect filterOutsetsInScreen = enclosingIntRect(CCMathUtil::mapClippedRect(surfaceTarget->screenSpaceTransform(), FloatRect(filterOutsetsInTarget)));
+
+ reduceOcclusion(boundsInTarget, filterOutsetsInTarget, occlusionInTarget);
+ reduceOcclusion(boundsInScreen, filterOutsetsInScreen, occlusionInScreen);
+}
+
template<typename LayerType, typename RenderSurfaceType>
void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::leaveToTargetRenderSurface(const RenderSurfaceType* newTarget)
{
@@ -132,11 +229,20 @@ void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::leaveToTargetRenderSu
// The target occlusion can be merged out as well but needs to be transformed to the new target.
const RenderSurfaceType* oldTarget = m_stack[lastIndex].surface;
- Region oldTargetOcclusionInNewTarget = transformSurfaceOpaqueRegion<RenderSurfaceType>(oldTarget, m_stack[lastIndex].occlusionInTarget, oldTarget->drawTransform());
+ Region oldTargetOcclusionInNewTarget = transformSurfaceOpaqueRegion<RenderSurfaceType>(oldTarget, m_stack[lastIndex].occlusionInTarget, oldTarget->originTransform());
+ if (oldTarget->hasReplica())
+ oldTargetOcclusionInNewTarget.unite(transformSurfaceOpaqueRegion<RenderSurfaceType>(oldTarget, m_stack[lastIndex].occlusionInTarget, oldTarget->replicaOriginTransform()));
+
+ IntRect unoccludedSurfaceRect;
+ IntRect unoccludedReplicaRect;
+ if (oldTarget->backgroundFilters().hasFilterThatMovesPixels()) {
+ unoccludedSurfaceRect = unoccludedContributingSurfaceContentRect(oldTarget, false, oldTarget->contentRect());
+ if (oldTarget->hasReplica())
+ unoccludedReplicaRect = unoccludedContributingSurfaceContentRect(oldTarget, true, oldTarget->contentRect());
+ }
if (surfaceWillBeAtTopAfterPop) {
// Merge the top of the stack down.
-
m_stack[lastIndex - 1].occlusionInScreen.unite(m_stack[lastIndex].occlusionInScreen);
m_stack[lastIndex - 1].occlusionInTarget.unite(oldTargetOcclusionInNewTarget);
m_stack.removeLast();
@@ -145,11 +251,18 @@ void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::leaveToTargetRenderSu
m_stack.last().surface = newTarget;
m_stack.last().occlusionInTarget = oldTargetOcclusionInNewTarget;
}
+
+ if (oldTarget->backgroundFilters().hasFilterThatMovesPixels()) {
+ reduceOcclusionBelowSurface(oldTarget, unoccludedSurfaceRect, oldTarget->originTransform(), newTarget, m_stack.last().occlusionInTarget, m_stack.last().occlusionInScreen);
+ if (oldTarget->hasReplica())
+ reduceOcclusionBelowSurface(oldTarget, unoccludedReplicaRect, oldTarget->replicaOriginTransform(), newTarget, m_stack.last().occlusionInTarget, m_stack.last().occlusionInScreen);
+ }
}
template<typename LayerType>
static inline TransformationMatrix contentToScreenSpaceTransform(const LayerType* layer)
{
+ ASSERT(layerTransformsToScreenKnown(layer));
IntSize boundsInLayerSpace = layer->bounds();
IntSize boundsInContentSpace = layer->contentBounds();
@@ -168,6 +281,7 @@ static inline TransformationMatrix contentToScreenSpaceTransform(const LayerType
template<typename LayerType>
static inline TransformationMatrix contentToTargetSurfaceTransform(const LayerType* layer)
{
+ ASSERT(layerTransformsToTargetKnown(layer));
IntSize boundsInLayerSpace = layer->bounds();
IntSize boundsInContentSpace = layer->contentBounds();
@@ -188,26 +302,24 @@ static inline TransformationMatrix contentToTargetSurfaceTransform(const LayerTy
// FIXME: Remove usePaintTracking when paint tracking is on for paint culling.
template<typename LayerType>
-static inline Region computeOcclusionBehindLayer(const LayerType* layer, const TransformationMatrix& transform, bool usePaintTracking)
+static inline void addOcclusionBehindLayer(Region& region, const LayerType* layer, const TransformationMatrix& transform, const Region& opaqueContents, const IntRect& scissorRect, const IntSize& minimumTrackingSize)
{
- Region opaqueRegion;
-
- FloatQuad unoccludedQuad = transform.mapQuad(FloatQuad(layer->visibleLayerRect()));
- bool isPaintedAxisAligned = unoccludedQuad.isRectilinear();
- if (!isPaintedAxisAligned)
- return opaqueRegion;
-
- if (layer->opaque())
- opaqueRegion = enclosedIntRect(unoccludedQuad.boundingBox());
- else if (usePaintTracking && transform.isIdentity())
- opaqueRegion = layer->opaqueContentsRegion();
- else if (usePaintTracking) {
- Region contentRegion = layer->opaqueContentsRegion();
- Vector<IntRect> contentRects = contentRegion.rects();
- for (size_t i = 0; i < contentRects.size(); ++i)
- opaqueRegion.unite(enclosedIntRect(transform.mapRect(FloatRect(contentRects[i]))));
+ ASSERT(layer->visibleLayerRect().contains(opaqueContents.bounds()));
+
+ bool clipped;
+ FloatQuad visibleTransformedQuad = CCMathUtil::mapQuad(transform, FloatQuad(layer->visibleLayerRect()), clipped);
+ // FIXME: Find a rect interior to each transformed quad.
+ if (clipped || !visibleTransformedQuad.isRectilinear())
+ return;
+
+ Vector<IntRect> contentRects = opaqueContents.rects();
+ // We verify that the possible bounds of this region are not clipped above, so we can use mapRect() safely here.
+ for (size_t i = 0; i < contentRects.size(); ++i) {
+ IntRect transformedRect = enclosedIntRect(transform.mapRect(FloatRect(contentRects[i])));
+ transformedRect.intersect(scissorRect);
+ if (transformedRect.width() >= minimumTrackingSize.width() || transformedRect.height() >= minimumTrackingSize.height())
+ region.unite(transformedRect);
}
- return opaqueRegion;
}
template<typename LayerType, typename RenderSurfaceType>
@@ -218,20 +330,35 @@ void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::markOccludedBehindLay
if (m_stack.isEmpty())
return;
- if (layer->drawOpacity() != 1)
+ if (!layerOpacityKnown(layer) || layer->drawOpacity() < 1)
return;
- TransformationMatrix contentToScreenSpace = contentToScreenSpaceTransform<LayerType>(layer);
- TransformationMatrix contentToTargetSurface = contentToTargetSurfaceTransform<LayerType>(layer);
+ Region opaqueContents = layer->visibleContentOpaqueRegion();
+ if (opaqueContents.isEmpty())
+ return;
- // FIXME: Remove m_usePaintTracking when paint tracking is on for paint culling.
- m_stack.last().occlusionInScreen.unite(computeOcclusionBehindLayer<LayerType>(layer, contentToScreenSpace, m_usePaintTracking));
- m_stack.last().occlusionInTarget.unite(computeOcclusionBehindLayer<LayerType>(layer, contentToTargetSurface, m_usePaintTracking));
+ IntRect scissorInTarget = layerScissorRectInTargetSurface(layer);
+ if (layerTransformsToTargetKnown(layer))
+ addOcclusionBehindLayer<LayerType>(m_stack.last().occlusionInTarget, layer, contentToTargetSurfaceTransform<LayerType>(layer), opaqueContents, scissorInTarget, m_minimumTrackingSize);
+
+ // We must clip the occlusion within the layer's scissorInTarget within screen space as well. If the scissor rect can't be moved to screen space and
+ // remain rectilinear, then we don't add any occlusion in screen space.
+
+ if (layerTransformsToScreenKnown(layer)) {
+ TransformationMatrix targetToScreenTransform = m_stack.last().surface->screenSpaceTransform();
+ bool clipped;
+ FloatQuad scissorInScreenQuad = CCMathUtil::mapQuad(targetToScreenTransform, FloatQuad(FloatRect(scissorInTarget)), clipped);
+ // FIXME: Find a rect interior to the transformed scissor quad.
+ if (clipped || !scissorInScreenQuad.isRectilinear())
+ return;
+ IntRect scissorInScreenRect = intersection(m_scissorRectInScreenSpace, enclosedIntRect(scissorInScreenQuad.boundingBox()));
+ addOcclusionBehindLayer<LayerType>(m_stack.last().occlusionInScreen, layer, contentToScreenSpaceTransform<LayerType>(layer), opaqueContents, scissorInScreenRect, m_minimumTrackingSize);
+ }
}
static inline bool testContentRectOccluded(const IntRect& contentRect, const TransformationMatrix& contentSpaceTransform, const IntRect& scissorRect, const Region& occlusion)
{
- FloatRect transformedRect = contentSpaceTransform.mapRect(FloatRect(contentRect));
+ FloatRect transformedRect = CCMathUtil::mapClippedRect(contentSpaceTransform, FloatRect(contentRect));
// Take the enclosingIntRect, as we want to include partial pixels in the test.
IntRect targetRect = intersection(enclosingIntRect(transformedRect), scissorRect);
return targetRect.isEmpty() || occlusion.contains(targetRect);
@@ -243,12 +370,14 @@ bool CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::occluded(const LayerT
ASSERT(!m_stack.isEmpty());
if (m_stack.isEmpty())
return false;
+ if (contentRect.isEmpty())
+ return true;
ASSERT(layer->targetRenderSurface() == m_stack.last().surface);
- if (testContentRectOccluded(contentRect, contentToScreenSpaceTransform<LayerType>(layer), m_scissorRectInScreenSpace, m_stack.last().occlusionInScreen))
+ if (layerTransformsToScreenKnown(layer) && testContentRectOccluded(contentRect, contentToScreenSpaceTransform<LayerType>(layer), m_scissorRectInScreenSpace, m_stack.last().occlusionInScreen))
return true;
- if (testContentRectOccluded(contentRect, contentToTargetSurfaceTransform<LayerType>(layer), layerScissorRectInTargetSurface(layer), m_stack.last().occlusionInTarget))
+ if (layerTransformsToTargetKnown(layer) && testContentRectOccluded(contentRect, contentToTargetSurfaceTransform<LayerType>(layer), layerScissorRectInTargetSurface(layer), m_stack.last().occlusionInTarget))
return true;
return false;
}
@@ -258,22 +387,19 @@ bool CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::occluded(const LayerT
static inline IntRect rectSubtractRegion(const IntRect& rect, const Region& region)
{
Region rectRegion(rect);
- Region intersectRegion(intersect(region, rectRegion));
-
- if (intersectRegion.isEmpty())
- return rect;
-
- rectRegion.subtract(intersectRegion);
- IntRect boundsRect = rectRegion.bounds();
- return boundsRect;
+ rectRegion.subtract(region);
+ return rectRegion.bounds();
}
static inline IntRect computeUnoccludedContentRect(const IntRect& contentRect, const TransformationMatrix& contentSpaceTransform, const IntRect& scissorRect, const Region& occlusion)
{
- FloatRect transformedRect = contentSpaceTransform.mapRect(FloatRect(contentRect));
+ if (!contentSpaceTransform.isInvertible())
+ return contentRect;
+
// Take the enclosingIntRect at each step, as we want to contain any unoccluded partial pixels in the resulting IntRect.
+ FloatRect transformedRect = CCMathUtil::mapClippedRect(contentSpaceTransform, FloatRect(contentRect));
IntRect shrunkRect = rectSubtractRegion(intersection(enclosingIntRect(transformedRect), scissorRect), occlusion);
- IntRect unoccludedRect = enclosingIntRect(contentSpaceTransform.inverse().mapRect(FloatRect(shrunkRect)));
+ IntRect unoccludedRect = enclosingIntRect(CCMathUtil::projectClippedRect(contentSpaceTransform.inverse(), FloatRect(shrunkRect)));
// The rect back in content space is a bounding box and may extend outside of the original contentRect, so clamp it to the contentRectBounds.
return intersection(unoccludedRect, contentRect);
}
@@ -284,71 +410,100 @@ IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::unoccludedContentR
ASSERT(!m_stack.isEmpty());
if (m_stack.isEmpty())
return contentRect;
+ if (contentRect.isEmpty())
+ return contentRect;
+
+ ASSERT(layer->targetRenderSurface() == m_stack.last().surface);
// We want to return a rect that contains all the visible parts of |contentRect| in both screen space and in the target surface.
// So we find the visible parts of |contentRect| in each space, and take the intersection.
- TransformationMatrix contentToScreenSpace = contentToScreenSpaceTransform<LayerType>(layer);
- TransformationMatrix contentToTargetSurface = contentToTargetSurfaceTransform<LayerType>(layer);
+ IntRect unoccludedInScreen = contentRect;
+ if (layerTransformsToScreenKnown(layer))
+ unoccludedInScreen = computeUnoccludedContentRect(contentRect, contentToScreenSpaceTransform<LayerType>(layer), m_scissorRectInScreenSpace, m_stack.last().occlusionInScreen);
- IntRect unoccludedInScreen = computeUnoccludedContentRect(contentRect, contentToScreenSpace, m_scissorRectInScreenSpace, m_stack.last().occlusionInScreen);
if (unoccludedInScreen.isEmpty())
- return IntRect();
- IntRect unoccludedInTarget = computeUnoccludedContentRect(contentRect, contentToTargetSurface, layerScissorRectInTargetSurface(layer), m_stack.last().occlusionInTarget);
+ return unoccludedInScreen;
- return intersection(unoccludedInScreen, unoccludedInTarget);
-}
+ IntRect unoccludedInTarget = contentRect;
+ if (layerTransformsToTargetKnown(layer))
+ unoccludedInTarget = computeUnoccludedContentRect(contentRect, contentToTargetSurfaceTransform<LayerType>(layer), layerScissorRectInTargetSurface(layer), m_stack.last().occlusionInTarget);
-template<typename LayerType, typename RenderSurfaceType>
-IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::layerScissorRectInTargetSurface(const LayerType* layer) const
-{
- const RenderSurfaceType* targetSurface = m_stack.last().surface;
- FloatRect totalScissor = targetSurface->contentRect();
- if (m_surfaceDamageClient)
- totalScissor.intersect(m_surfaceDamageClient->damageRect(targetSurface));
- if (!layer->clipRect().isEmpty())
- totalScissor.intersect(layer->clipRect());
- return enclosingIntRect(totalScissor);
+ return intersection(unoccludedInScreen, unoccludedInTarget);
}
template<typename LayerType, typename RenderSurfaceType>
-const Region& CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::currentOcclusionInScreenSpace() const
+IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::unoccludedContributingSurfaceContentRect(const RenderSurfaceType* surface, bool forReplica, const IntRect& contentRect) const
{
ASSERT(!m_stack.isEmpty());
- return m_stack.last().occlusionInScreen;
+ // This should be called while the contributing render surface is still considered the current target in the occlusion tracker.
+ ASSERT(surface == m_stack.last().surface);
+
+ // A contributing surface doesn't get occluded by things inside its own surface, so only things outside the surface can occlude it. That occlusion is
+ // found just below the top of the stack (if it exists).
+ if (m_stack.size() < 2)
+ return contentRect;
+ if (contentRect.isEmpty())
+ return contentRect;
+
+ const StackObject& secondLast = m_stack[m_stack.size() - 2];
+
+ IntRect surfaceClipRect = surface->clipRect();
+ if (surfaceClipRect.isEmpty()) {
+ const RenderSurfaceType* targetSurface = secondLast.surface;
+ surfaceClipRect = intersection(targetSurface->contentRect(), enclosingIntRect(surface->drawableContentRect()));
+ }
+
+ const TransformationMatrix& transformToScreen = forReplica ? surface->replicaScreenSpaceTransform() : surface->screenSpaceTransform();
+ const TransformationMatrix& transformToTarget = forReplica ? surface->replicaOriginTransform() : surface->originTransform();
+
+ IntRect unoccludedInScreen = contentRect;
+ if (surfaceTransformsToScreenKnown(surface))
+ unoccludedInScreen = computeUnoccludedContentRect(contentRect, transformToScreen, m_scissorRectInScreenSpace, secondLast.occlusionInScreen);
+
+ if (unoccludedInScreen.isEmpty())
+ return unoccludedInScreen;
+
+ IntRect unoccludedInTarget = contentRect;
+ if (surfaceTransformsToTargetKnown(surface))
+ unoccludedInTarget = computeUnoccludedContentRect(contentRect, transformToTarget, surfaceClipRect, secondLast.occlusionInTarget);
+
+ return intersection(unoccludedInScreen, unoccludedInTarget);
}
template<typename LayerType, typename RenderSurfaceType>
-const Region& CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::currentOcclusionInTargetSurface() const
+IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::layerScissorRectInTargetSurface(const LayerType* layer) const
{
- ASSERT(!m_stack.isEmpty());
- return m_stack.last().occlusionInTarget;
+ const RenderSurfaceType* targetSurface = m_stack.last().surface;
+ FloatRect totalScissor = targetSurface->contentRect();
+ if (layer->usesLayerClipping())
+ totalScissor.intersect(layer->clipRect());
+ return enclosingIntRect(totalScissor);
}
-
// Declare the possible functions here for the linker.
-template CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace);
-template CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace, const CCOcclusionTrackerDamageClient* surfaceDamageClient);
+template CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace, bool recordMetricsForFrame);
+template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::enterLayer(const CCLayerIteratorPosition<LayerChromium>&);
+template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::leaveLayer(const CCLayerIteratorPosition<LayerChromium>&);
template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::enterTargetRenderSurface(const RenderSurfaceChromium* newTarget);
template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::finishedTargetRenderSurface(const LayerChromium* owningLayer, const RenderSurfaceChromium* finishedTarget);
template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::leaveToTargetRenderSurface(const RenderSurfaceChromium* newTarget);
template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::markOccludedBehindLayer(const LayerChromium*);
template bool CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::occluded(const LayerChromium*, const IntRect& contentRect) const;
template IntRect CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::unoccludedContentRect(const LayerChromium*, const IntRect& contentRect) const;
-template const Region& CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::currentOcclusionInScreenSpace() const;
-template const Region& CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::currentOcclusionInTargetSurface() const;
+template IntRect CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::unoccludedContributingSurfaceContentRect(const RenderSurfaceChromium*, bool forReplica, const IntRect& contentRect) const;
template IntRect CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::layerScissorRectInTargetSurface(const LayerChromium*) const;
-template CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace);
-template CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace, const CCOcclusionTrackerDamageClientImpl* surfaceDamageClient);
+template CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace, bool recordMetricsForFrame);
+template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::enterLayer(const CCLayerIteratorPosition<CCLayerImpl>&);
+template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::leaveLayer(const CCLayerIteratorPosition<CCLayerImpl>&);
template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::enterTargetRenderSurface(const CCRenderSurface* newTarget);
template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::finishedTargetRenderSurface(const CCLayerImpl* owningLayer, const CCRenderSurface* finishedTarget);
template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::leaveToTargetRenderSurface(const CCRenderSurface* newTarget);
template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::markOccludedBehindLayer(const CCLayerImpl*);
template bool CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::occluded(const CCLayerImpl*, const IntRect& contentRect) const;
template IntRect CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::unoccludedContentRect(const CCLayerImpl*, const IntRect& contentRect) const;
-template const Region& CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::currentOcclusionInScreenSpace() const;
-template const Region& CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::currentOcclusionInTargetSurface() const;
+template IntRect CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::unoccludedContributingSurfaceContentRect(const CCRenderSurface*, bool forReplica, const IntRect& contentRect) const;
template IntRect CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::layerScissorRectInTargetSurface(const CCLayerImpl*) const;
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h b/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h
index 19fc2c1dd..232874523 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h
@@ -29,6 +29,8 @@
#include "FloatQuad.h"
#include "Region.h"
#include "TransformationMatrix.h"
+#include "cc/CCLayerIterator.h"
+#include "cc/CCOverdrawMetrics.h"
namespace WebCore {
class CCLayerImpl;
@@ -36,15 +38,6 @@ class CCRenderSurface;
class LayerChromium;
class RenderSurfaceChromium;
-template<typename RenderSurfaceType>
-class CCOcclusionTrackerDamageClientBase {
-public:
- virtual FloatRect damageRect(const RenderSurfaceType*) const = 0;
-};
-
-typedef CCOcclusionTrackerDamageClientBase<RenderSurfaceChromium> CCOcclusionTrackerDamageClient;
-typedef CCOcclusionTrackerDamageClientBase<CCRenderSurface> CCOcclusionTrackerDamageClientImpl;
-
// This class is used to track occlusion of layers while traversing them in a front-to-back order. As each layer is visited, one of the
// methods in this class is called to notify it about the current target surface.
// Then, occlusion in the content space of the current layer may be queried, via methods such as occluded() and unoccludedContentRect().
@@ -53,39 +46,37 @@ typedef CCOcclusionTrackerDamageClientBase<CCRenderSurface> CCOcclusionTrackerDa
template<typename LayerType, typename RenderSurfaceType>
class CCOcclusionTrackerBase {
WTF_MAKE_NONCOPYABLE(CCOcclusionTrackerBase);
- typedef CCOcclusionTrackerDamageClientBase<RenderSurfaceType> DamageClientType;
public:
- CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace);
- CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace, const DamageClientType*);
-
- // Called when visiting a layer representing itself. If the target was not already current, then this indicates we have entered a new surface subtree.
- void enterTargetRenderSurface(const RenderSurfaceType* newTarget);
-
- // Called when visiting a layer representing a target surface. This indicates we have visited all the layers within the surface, and we may
- // perform any surface-wide operations.
- void finishedTargetRenderSurface(const LayerType*, const RenderSurfaceType* finishedTarget);
-
- // Called when visiting a layer representing a contributing surface. This indicates that we are leaving our current surface, and
- // entering the new one. We then perform any operations required for merging results from the child subtree into its parent.
- void leaveToTargetRenderSurface(const RenderSurfaceType* newTarget);
+ CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace, bool recordMetricsForFrame);
- // Add the layer's occlusion to the tracked state.
- void markOccludedBehindLayer(const LayerType*);
+ // Called at the beginning of each step in the CCLayerIterator's front-to-back traversal.
+ void enterLayer(const CCLayerIteratorPosition<LayerType>&);
+ // Called at the end of each step in the CCLayerIterator's front-to-back traversal.
+ void leaveLayer(const CCLayerIteratorPosition<LayerType>&);
// Returns true if the given rect in content space for the layer is fully occluded in either screen space or the layer's target surface.
bool occluded(const LayerType*, const IntRect& contentRect) const;
// Gives an unoccluded sub-rect of |contentRect| in the content space of the layer. Used when considering occlusion for a layer that paints/draws something.
IntRect unoccludedContentRect(const LayerType*, const IntRect& contentRect) const;
- // FIXME: Remove this when paint tracking is on for paint culling.
- void setUsePaintTracking(bool use) { m_usePaintTracking = use; }
+ // Gives an unoccluded sub-rect of |contentRect| in the content space of the surface. Used when considering occlusion for a contributing surface
+ // that is rendering into another target surface.
+ IntRect unoccludedContributingSurfaceContentRect(const RenderSurfaceType*, bool forReplica, const IntRect& contentRect) const;
- // FIXME: Remove these in future, they are to make CLs for transitioning to this easier.
- const Region& currentOcclusionInScreenSpace() const;
- const Region& currentOcclusionInTargetSurface() const;
+ // Report operations for recording overdraw metrics.
+ CCOverdrawMetrics& overdrawMetrics() const { return *m_overdrawMetrics.get(); }
+
+ // Gives the region of the screen that is not occluded by something opaque.
+ Region computeVisibleRegionInScreen() const { return subtract(Region(m_scissorRectInScreenSpace), m_stack.last().occlusionInScreen); }
+
+ void setMinimumTrackingSize(const IntSize& size) { m_minimumTrackingSize = size; }
+
+ static IntSize preferredMinimumTrackingSize() { return IntSize(160, 160); }
protected:
struct StackObject {
+ StackObject() : surface(0) { }
+ StackObject(const RenderSurfaceType* surface) : surface(surface) { }
const RenderSurfaceType* surface;
Region occlusionInScreen;
Region occlusionInTarget;
@@ -104,9 +95,23 @@ protected:
virtual IntRect layerScissorRectInTargetSurface(const LayerType*) const;
private:
+ // Called when visiting a layer representing itself. If the target was not already current, then this indicates we have entered a new surface subtree.
+ void enterTargetRenderSurface(const RenderSurfaceType* newTarget);
+
+ // Called when visiting a layer representing a target surface. This indicates we have visited all the layers within the surface, and we may
+ // perform any surface-wide operations.
+ void finishedTargetRenderSurface(const LayerType*, const RenderSurfaceType* finishedTarget);
+
+ // Called when visiting a layer representing a contributing surface. This indicates that we are leaving our current surface, and
+ // entering the new one. We then perform any operations required for merging results from the child subtree into its parent.
+ void leaveToTargetRenderSurface(const RenderSurfaceType* newTarget);
+
+ // Add the layer's occlusion to the tracked state.
+ void markOccludedBehindLayer(const LayerType*);
+
IntRect m_scissorRectInScreenSpace;
- const DamageClientType* m_surfaceDamageClient;
- bool m_usePaintTracking; // FIXME: Remove this when paint tracking is on for paint culling.
+ OwnPtr<CCOverdrawMetrics> m_overdrawMetrics;
+ IntSize m_minimumTrackingSize;
};
typedef CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium> CCOcclusionTracker;
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCOverdrawMetrics.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCOverdrawMetrics.cpp
new file mode 100644
index 000000000..3b0193ec4
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCOverdrawMetrics.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "cc/CCOverdrawMetrics.h"
+
+#include "FloatQuad.h"
+#include "IntRect.h"
+#include "TraceEvent.h"
+#include "TransformationMatrix.h"
+#include "cc/CCLayerTreeHost.h"
+#include "cc/CCLayerTreeHostImpl.h"
+#include <public/Platform.h>
+
+namespace WebCore {
+
+CCOverdrawMetrics::CCOverdrawMetrics(bool recordMetricsForFrame)
+ : m_recordMetricsForFrame(recordMetricsForFrame)
+ , m_pixelsPainted(0)
+ , m_pixelsUploadedOpaque(0)
+ , m_pixelsUploadedTranslucent(0)
+ , m_tilesCulledForUpload(0)
+ , m_pixelsDrawnOpaque(0)
+ , m_pixelsDrawnTranslucent(0)
+ , m_pixelsCulledForDrawing(0)
+{
+}
+
+static inline float wedgeProduct(const FloatPoint& p1, const FloatPoint& p2)
+{
+ return p1.x() * p2.y() - p1.y() * p2.x();
+}
+
+// Computes area of quads that are possibly non-rectangular. Can be easily extended to polygons.
+static inline float quadArea(const FloatQuad& quad)
+{
+ return fabs(0.5 * (wedgeProduct(quad.p1(), quad.p2()) +
+ wedgeProduct(quad.p2(), quad.p3()) +
+ wedgeProduct(quad.p3(), quad.p4()) +
+ wedgeProduct(quad.p4(), quad.p1())));
+}
+
+void CCOverdrawMetrics::didPaint(const IntRect& paintedRect)
+{
+ if (!m_recordMetricsForFrame)
+ return;
+
+ m_pixelsPainted += static_cast<float>(paintedRect.width()) * paintedRect.height();
+}
+
+void CCOverdrawMetrics::didCullTileForUpload()
+{
+ if (m_recordMetricsForFrame)
+ ++m_tilesCulledForUpload;
+}
+
+void CCOverdrawMetrics::didUpload(const TransformationMatrix& transformToTarget, const IntRect& uploadRect, const IntRect& opaqueRect)
+{
+ if (!m_recordMetricsForFrame)
+ return;
+
+ float uploadArea = quadArea(transformToTarget.mapQuad(FloatQuad(uploadRect)));
+ float uploadOpaqueArea = quadArea(transformToTarget.mapQuad(FloatQuad(intersection(opaqueRect, uploadRect))));
+
+ m_pixelsUploadedOpaque += uploadOpaqueArea;
+ m_pixelsUploadedTranslucent += uploadArea - uploadOpaqueArea;
+}
+
+void CCOverdrawMetrics::didCullForDrawing(const TransformationMatrix& transformToTarget, const IntRect& beforeCullRect, const IntRect& afterCullRect)
+{
+ if (!m_recordMetricsForFrame)
+ return;
+
+ float beforeCullArea = quadArea(transformToTarget.mapQuad(FloatQuad(beforeCullRect)));
+ float afterCullArea = quadArea(transformToTarget.mapQuad(FloatQuad(afterCullRect)));
+
+ m_pixelsCulledForDrawing += beforeCullArea - afterCullArea;
+}
+
+void CCOverdrawMetrics::didDraw(const TransformationMatrix& transformToTarget, const IntRect& afterCullRect, const IntRect& opaqueRect)
+{
+ if (!m_recordMetricsForFrame)
+ return;
+
+ float afterCullArea = quadArea(transformToTarget.mapQuad(FloatQuad(afterCullRect)));
+ float afterCullOpaqueArea = quadArea(transformToTarget.mapQuad(FloatQuad(intersection(opaqueRect, afterCullRect))));
+
+ m_pixelsDrawnOpaque += afterCullOpaqueArea;
+ m_pixelsDrawnTranslucent += afterCullArea - afterCullOpaqueArea;
+}
+
+void CCOverdrawMetrics::recordMetrics(const CCLayerTreeHost* layerTreeHost) const
+{
+ if (m_recordMetricsForFrame)
+ recordMetricsInternal<CCLayerTreeHost>(UpdateAndCommit, layerTreeHost);
+}
+
+void CCOverdrawMetrics::recordMetrics(const CCLayerTreeHostImpl* layerTreeHost) const
+{
+ if (m_recordMetricsForFrame)
+ recordMetricsInternal<CCLayerTreeHostImpl>(DrawingToScreen, layerTreeHost);
+}
+
+template<typename LayerTreeHostType>
+void CCOverdrawMetrics::recordMetricsInternal(MetricsType metricsType, const LayerTreeHostType* layerTreeHost) const
+{
+ // This gives approximately 10x the percentage of pixels to fill the viewport once.
+ float normalization = 1000.f / (layerTreeHost->viewportSize().width() * layerTreeHost->viewportSize().height());
+ // This gives approximately 100x the percentage of tiles to fill the viewport once, if all tiles were 256x256.
+ float tileNormalization = 10000.f / (layerTreeHost->viewportSize().width() / 256.f * layerTreeHost->viewportSize().height() / 256.f);
+
+ switch (metricsType) {
+ case DrawingToScreen:
+ WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountOpaque_Draw", static_cast<int>(normalization * m_pixelsDrawnOpaque), 100, 1000000, 50);
+ WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountTranslucent_Draw", static_cast<int>(normalization * m_pixelsDrawnTranslucent), 100, 1000000, 50);
+ WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountCulled_Draw", static_cast<int>(normalization * m_pixelsCulledForDrawing), 100, 1000000, 50);
+
+ {
+ TRACE_COUNTER_ID1("webkit", "DrawPixelsCulled", layerTreeHost, m_pixelsCulledForDrawing);
+ TRACE_EVENT2("webkit", "CCOverdrawMetrics", "PixelsDrawnOpaque", m_pixelsDrawnOpaque, "PixelsDrawnTranslucent", m_pixelsDrawnTranslucent);
+ }
+ break;
+ case UpdateAndCommit:
+ WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountPainted", static_cast<int>(normalization * m_pixelsPainted), 100, 1000000, 50);
+ WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountOpaque_Upload", static_cast<int>(normalization * m_pixelsUploadedOpaque), 100, 1000000, 50);
+ WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountTranslucent_Upload", static_cast<int>(normalization * m_pixelsUploadedTranslucent), 100, 1000000, 50);
+ WebKit::Platform::current()->histogramCustomCounts("Renderer4.tileCountCulled_Upload", static_cast<int>(tileNormalization * m_tilesCulledForUpload), 100, 10000000, 50);
+
+ {
+ TRACE_COUNTER_ID1("webkit", "UploadTilesCulled", layerTreeHost, m_tilesCulledForUpload);
+ TRACE_EVENT2("webkit", "CCOverdrawMetrics", "PixelsUploadedOpaque", m_pixelsUploadedOpaque, "PixelsUploadedTranslucent", m_pixelsUploadedTranslucent);
+ }
+ {
+ // This must be in a different scope than the TRACE_EVENT2 above.
+ TRACE_EVENT1("webkit", "CCOverdrawPaintMetrics", "PixelsPainted", m_pixelsPainted);
+ }
+ break;
+ }
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCOverdrawMetrics.h b/Source/WebCore/platform/graphics/chromium/cc/CCOverdrawMetrics.h
new file mode 100644
index 000000000..5156c3c39
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCOverdrawMetrics.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CCOverdrawMetrics_h
+#define CCOverdrawMetrics_h
+
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+class IntRect;
+class TransformationMatrix;
+class CCLayerTreeHost;
+class CCLayerTreeHostImpl;
+
+// FIXME: compute overdraw metrics only occasionally, not every frame.
+class CCOverdrawMetrics {
+public:
+ static PassOwnPtr<CCOverdrawMetrics> create(bool recordMetricsForFrame) { return adoptPtr(new CCOverdrawMetrics(recordMetricsForFrame)); }
+
+ // These methods are used for saving metrics during update/commit.
+
+ // Record pixels painted by WebKit into the texture updater, but does not mean the pixels were rasterized in main memory.
+ void didPaint(const IntRect& paintedRect);
+ // Records that an invalid tile was culled and did not need to be painted/uploaded, and did not contribute to other tiles needing to be painted.
+ void didCullTileForUpload();
+ // Records pixels that were uploaded to texture memory.
+ void didUpload(const TransformationMatrix& transformToTarget, const IntRect& uploadRect, const IntRect& opaqueRect);
+
+ // These methods are used for saving metrics during draw.
+
+ // Record pixels that were not drawn to screen.
+ void didCullForDrawing(const TransformationMatrix& transformToTarget, const IntRect& beforeCullRect, const IntRect& afterCullRect);
+ // Record pixels that were drawn to screen.
+ void didDraw(const TransformationMatrix& transformToTarget, const IntRect& afterCullRect, const IntRect& opaqueRect);
+
+ void recordMetrics(const CCLayerTreeHost*) const;
+ void recordMetrics(const CCLayerTreeHostImpl*) const;
+
+ // Accessors for tests.
+ float pixelsDrawnOpaque() const { return m_pixelsDrawnOpaque; }
+ float pixelsDrawnTranslucent() const { return m_pixelsDrawnTranslucent; }
+ float pixelsCulledForDrawing() const { return m_pixelsCulledForDrawing; }
+ float pixelsPainted() const { return m_pixelsPainted; }
+ float pixelsUploadedOpaque() const { return m_pixelsUploadedOpaque; }
+ float pixelsUploadedTranslucent() const { return m_pixelsUploadedTranslucent; }
+ int tilesCulledForUpload() const { return m_tilesCulledForUpload; }
+
+private:
+ enum MetricsType {
+ UpdateAndCommit,
+ DrawingToScreen
+ };
+
+ explicit CCOverdrawMetrics(bool recordMetricsForFrame);
+
+ template<typename LayerTreeHostType>
+ void recordMetricsInternal(MetricsType, const LayerTreeHostType*) const;
+
+ // When false this class is a giant no-op.
+ bool m_recordMetricsForFrame;
+
+ // These values are used for saving metrics during update/commit.
+
+ // Count of pixels that were painted due to invalidation.
+ float m_pixelsPainted;
+ // Count of pixels uploaded to textures and known to be opaque.
+ float m_pixelsUploadedOpaque;
+ // Count of pixels uploaded to textures and not known to be opaque.
+ float m_pixelsUploadedTranslucent;
+ // Count of tiles that were invalidated but not uploaded.
+ int m_tilesCulledForUpload;
+
+ // These values are used for saving metrics during draw.
+
+ // Count of pixels that are opaque (and thus occlude). Ideally this is no more than wiewport width x height.
+ float m_pixelsDrawnOpaque;
+ // Count of pixels that are possibly translucent, and cannot occlude.
+ float m_pixelsDrawnTranslucent;
+ // Count of pixels not drawn as they are occluded by somthing opaque.
+ float m_pixelsCulledForDrawing;
+};
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPageScaleAnimation.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCPageScaleAnimation.cpp
index 49a125d23..e45c00f6b 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCPageScaleAnimation.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCPageScaleAnimation.cpp
@@ -51,6 +51,7 @@ CCPageScaleAnimation::CCPageScaleAnimation(const IntSize& scrollStart, float pag
, m_scrollEnd(scrollStart)
, m_pageScaleEnd(pageScaleStart)
, m_startTime(startTime)
+ , m_duration(0)
{
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h
deleted file mode 100644
index 370e09d94..000000000
--- a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CCPluginLayerImpl_h
-#define CCPluginLayerImpl_h
-
-#include "FloatRect.h"
-#include "ProgramBinding.h"
-#include "ShaderChromium.h"
-#include "cc/CCLayerImpl.h"
-
-namespace WebCore {
-
-class CCPluginLayerImpl : public CCLayerImpl {
-public:
- static PassOwnPtr<CCPluginLayerImpl> create(int id)
- {
- return adoptPtr(new CCPluginLayerImpl(id));
- }
- virtual ~CCPluginLayerImpl();
-
- virtual void willDraw(LayerRendererChromium*);
- virtual void appendQuads(CCQuadList&, const CCSharedQuadState*);
-
- typedef ProgramBinding<VertexShaderPosTexStretch, FragmentShaderRGBATexAlpha> Program;
- typedef ProgramBinding<VertexShaderPosTexStretch, FragmentShaderRGBATexFlipAlpha> ProgramFlip;
- typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexRectAlpha> TexRectProgram;
- typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexRectFlipAlpha> TexRectProgramFlip;
-
- virtual void dumpLayerProperties(TextStream&, int indent) const;
- virtual void didLoseContext();
-
- void setTextureId(unsigned id) { m_textureId = id; }
- void setFlipped(bool flipped) { m_flipped = flipped; }
- void setUVRect(const FloatRect& rect) { m_uvRect = rect; }
- void setIOSurfaceProperties(int width, int height, uint32_t ioSurfaceId);
-
-private:
- explicit CCPluginLayerImpl(int);
-
- virtual const char* layerTypeAsString() const { return "PluginLayer"; }
-
- unsigned m_textureId;
- bool m_flipped;
- FloatRect m_uvRect;
- uint32_t m_ioSurfaceId;
- int m_ioSurfaceWidth;
- int m_ioSurfaceHeight;
-
- // Internals for the IOSurface rendering path.
- bool m_ioSurfaceChanged;
- unsigned m_ioSurfaceTextureId;
-};
-
-}
-
-#endif // CCPluginLayerImpl_h
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCProxy.h b/Source/WebCore/platform/graphics/chromium/cc/CCProxy.h
index 016226ca5..4a36c388e 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCProxy.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCProxy.h
@@ -33,13 +33,10 @@
namespace WebCore {
+class CCFontAtlas;
class CCThread;
-class CCLayerTreeHost;
-class CCLayerTreeHostImpl;
-class CCLayerTreeHostImplClient;
class GraphicsContext3D;
struct LayerRendererCapabilities;
-class TextureManager;
// Abstract class responsible for proxying commands from the main-thread side of
// the compositor over to the compositor implementation.
@@ -70,6 +67,9 @@ public:
// The context will not be used and no frames may be produced until initializeLayerRenderer() is called.
virtual bool initializeContext() = 0;
+ // Indicates that the compositing surface associated with our context is ready to use.
+ virtual void setSurfaceReady() = 0;
+
// Attempts to initialize the layer renderer. Returns false if the context isn't usable for compositing.
virtual bool initializeLayerRenderer() = 0;
@@ -86,12 +86,22 @@ public:
virtual void setNeedsRedraw() = 0;
virtual void setVisible(bool) = 0;
+ virtual bool commitRequested() const = 0;
+
virtual void start() = 0; // Must be called before using the proxy.
virtual void stop() = 0; // Must be called before deleting the proxy.
+ // Forces 3D commands on all contexts to wait for all previous SwapBuffers to finish before executing in the GPU
+ // process.
+ virtual void forceSerializeOnSwapBuffers() = 0;
+
// Maximum number of sub-region texture updates supported for each commit.
virtual size_t maxPartialTextureUpdates() const = 0;
+ virtual void acquireLayerTextures() = 0;
+
+ virtual void setFontAtlas(PassOwnPtr<CCFontAtlas>) = 0;
+
// Debug hooks
#ifndef NDEBUG
static bool isMainThread();
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp
index 1c4a499cc..e5fd690cc 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp
@@ -32,127 +32,53 @@
#include "Region.h"
#include "TransformationMatrix.h"
#include "cc/CCLayerImpl.h"
+#include "cc/CCOverdrawMetrics.h"
#include "cc/CCRenderPass.h"
#include "cc/CCRenderSurfaceDrawQuad.h"
using namespace std;
-namespace std {
+namespace WebCore {
-// Specialize for OwnPtr<CCDrawQuad> since Vector doesn't know how to reverse a Vector of OwnPtr<T> in general.
-template<>
-void swap(OwnPtr<WebCore::CCDrawQuad>& a, OwnPtr<WebCore::CCDrawQuad>& b)
+CCQuadCuller::CCQuadCuller(CCQuadList& quadList, CCLayerImpl* layer, const CCOcclusionTrackerImpl* occlusionTracker)
+ : m_quadList(quadList)
+ , m_layer(layer)
+ , m_occlusionTracker(occlusionTracker)
{
- a.swap(b);
-}
-
}
-namespace WebCore {
-
-// Determines what portion of rect, if any, is visible (not occluded by region). If
-// the resulting visible region is not rectangular, we just return the original rect.
-static IntRect rectSubtractRegion(const Region& region, const IntRect& rect)
+static inline bool appendQuadInternal(PassOwnPtr<CCDrawQuad> passDrawQuad, const IntRect& culledRect, CCQuadList& quadList, const CCOcclusionTrackerImpl& occlusionTracker)
{
- Region rectRegion(rect);
- Region intersectRegion(intersect(region, rectRegion));
-
- if (intersectRegion.isEmpty())
- return rect;
-
- // Test if intersectRegion = rectRegion, if so return empty rect.
- rectRegion.subtract(intersectRegion);
- IntRect boundsRect = rectRegion.bounds();
- if (boundsRect.isEmpty())
- return boundsRect;
-
- // Test if rectRegion is still a rectangle. If it is, it will be identical to its bounds.
- Region boundsRegion(boundsRect);
- boundsRegion.subtract(rectRegion);
- if (boundsRegion.isEmpty())
- return boundsRect;
-
- return rect;
+ OwnPtr<CCDrawQuad> drawQuad(passDrawQuad);
+ bool keepQuad = !culledRect.isEmpty();
+ if (keepQuad)
+ drawQuad->setQuadVisibleRect(culledRect);
+
+ occlusionTracker.overdrawMetrics().didCullForDrawing(drawQuad->quadTransform(), drawQuad->quadRect(), culledRect);
+ occlusionTracker.overdrawMetrics().didDraw(drawQuad->quadTransform(), culledRect, drawQuad->opaqueRect());
+
+ // Release the quad after we're done using it.
+ if (keepQuad)
+ quadList.append(drawQuad.release());
+ return keepQuad;
}
-static float wedgeProduct(const FloatPoint& p1, const FloatPoint& p2)
+bool CCQuadCuller::append(PassOwnPtr<CCDrawQuad> passDrawQuad)
{
- return p1.x() * p2.y() - p1.y() * p2.x();
+ IntRect culledRect = m_occlusionTracker->unoccludedContentRect(m_layer, passDrawQuad->quadRect());
+ return appendQuadInternal(passDrawQuad, culledRect, m_quadList, *m_occlusionTracker);
}
-// Computes area of quads that are possibly non-rectangular. Can
-// be easily extended to polygons.
-static float quadArea(const FloatQuad& quad)
+bool CCQuadCuller::appendSurface(PassOwnPtr<CCDrawQuad> passDrawQuad)
{
- return fabs(0.5 * (wedgeProduct(quad.p1(), quad.p2()) +
- wedgeProduct(quad.p2(), quad.p3()) +
- wedgeProduct(quad.p3(), quad.p4()) +
- wedgeProduct(quad.p4(), quad.p1())));
+ IntRect culledRect = m_occlusionTracker->unoccludedContributingSurfaceContentRect(m_layer->renderSurface(), false, passDrawQuad->quadRect());
+ return appendQuadInternal(passDrawQuad, culledRect, m_quadList, *m_occlusionTracker);
}
-void CCQuadCuller::cullOccludedQuads(CCQuadList& quadList, bool haveDamageRect, const FloatRect& damageRect, CCOverdrawCounts* overdrawMetrics)
+bool CCQuadCuller::appendReplica(PassOwnPtr<CCDrawQuad> passDrawQuad)
{
- if (!quadList.size())
- return;
-
- CCQuadList culledList;
- culledList.reserveCapacity(quadList.size());
-
- Region opaqueCoverageThusFar;
-
- for (int i = quadList.size() - 1; i >= 0; --i) {
- CCDrawQuad* drawQuad = quadList[i].get();
-
- FloatRect floatTransformedRect = drawQuad->quadTransform().mapRect(FloatRect(drawQuad->quadRect()));
- if (haveDamageRect)
- floatTransformedRect.intersect(damageRect);
- // Inflate rect to be tested to stay conservative.
- IntRect transformedQuadRect(enclosingIntRect(floatTransformedRect));
-
- IntRect transformedVisibleQuadRect = rectSubtractRegion(opaqueCoverageThusFar, transformedQuadRect);
- bool keepQuad = !transformedVisibleQuadRect.isEmpty();
-
- // See if we can reduce the number of pixels to draw by reducing the size of the draw
- // quad - we do this by changing its visible rect.
- bool didReduceQuadSize = false;
- if (keepQuad) {
- if (transformedVisibleQuadRect != transformedQuadRect && drawQuad->isLayerAxisAlignedIntRect()) {
- drawQuad->setQuadVisibleRect(drawQuad->quadTransform().inverse().mapRect(transformedVisibleQuadRect));
- didReduceQuadSize = true;
- }
-
- // When adding rect to opaque region, deflate it to stay conservative.
- if (drawQuad->isLayerAxisAlignedIntRect() && !drawQuad->opaqueRect().isEmpty()) {
- FloatRect floatOpaqueRect = drawQuad->quadTransform().mapRect(FloatRect(drawQuad->opaqueRect()));
- opaqueCoverageThusFar.unite(Region(enclosedIntRect(floatOpaqueRect)));
- }
-
- culledList.append(quadList[i].release());
- }
-
- if (overdrawMetrics) {
- // We compute the area of the transformed quad, as this should be in pixels.
- float area = quadArea(drawQuad->quadTransform().mapQuad(FloatQuad(drawQuad->quadRect())));
- if (keepQuad) {
- if (didReduceQuadSize) {
- float visibleQuadRectArea = quadArea(drawQuad->quadTransform().mapQuad(FloatQuad(drawQuad->quadVisibleRect())));
- overdrawMetrics->m_pixelsCulled += area - visibleQuadRectArea;
- area = visibleQuadRectArea;
- }
- IntRect visibleOpaqueRect(drawQuad->quadVisibleRect());
- visibleOpaqueRect.intersect(drawQuad->opaqueRect());
- FloatQuad visibleOpaqueQuad = drawQuad->quadTransform().mapQuad(FloatQuad(visibleOpaqueRect));
- float opaqueArea = quadArea(visibleOpaqueQuad);
- overdrawMetrics->m_pixelsDrawnOpaque += opaqueArea;
- overdrawMetrics->m_pixelsDrawnTransparent += area - opaqueArea;
- } else
- overdrawMetrics->m_pixelsCulled += area;
- }
- }
- quadList.clear(); // Release anything that remains.
-
- culledList.reverse();
- quadList.swap(culledList);
+ IntRect culledRect = m_occlusionTracker->unoccludedContributingSurfaceContentRect(m_layer->renderSurface(), true, passDrawQuad->quadRect());
+ return appendQuadInternal(passDrawQuad, culledRect, m_quadList, *m_occlusionTracker);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.h b/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.h
index 89582573b..5db0a98c5 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.h
@@ -29,16 +29,24 @@
#include "cc/CCRenderPass.h"
namespace WebCore {
+class CCLayerImpl;
+class CCOverdrawMetrics;
class CCQuadCuller {
public:
// Passing 0 for CCOverdrawCounts* is valid, and disable the extra computation
// done to estimate over draw statistics.
- static void cullOccludedQuads(CCQuadList&, bool haveDamageRect, const FloatRect& damageRect, CCOverdrawCounts*);
+ CCQuadCuller(CCQuadList&, CCLayerImpl*, const CCOcclusionTrackerImpl*);
+
+ // Returns true if the quad is added to the list, and false if the quad is entirely culled.
+ virtual bool append(PassOwnPtr<CCDrawQuad> passDrawQuad);
+ virtual bool appendSurface(PassOwnPtr<CCDrawQuad> passDrawQuad);
+ virtual bool appendReplica(PassOwnPtr<CCDrawQuad> passDrawQuad);
private:
- // Make non-instantiable.
- CCQuadCuller() { }
+ CCQuadList& m_quadList;
+ CCLayerImpl* m_layer;
+ const CCOcclusionTrackerImpl* m_occlusionTracker;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.cpp
index bd877ec30..33b5e7310 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.cpp
@@ -27,14 +27,26 @@
#include "cc/CCRenderPass.h"
+#include "Color.h"
#include "cc/CCDamageTracker.h"
+#include "cc/CCDebugBorderDrawQuad.h"
#include "cc/CCLayerImpl.h"
#include "cc/CCQuadCuller.h"
#include "cc/CCRenderSurfaceDrawQuad.h"
#include "cc/CCSharedQuadState.h"
+#include "cc/CCSolidColorDrawQuad.h"
namespace WebCore {
+static const int debugSurfaceBorderWidth = 2;
+static const int debugSurfaceBorderAlpha = 100;
+static const int debugSurfaceBorderColorRed = 0;
+static const int debugSurfaceBorderColorGreen = 0;
+static const int debugSurfaceBorderColorBlue = 255;
+static const int debugReplicaBorderColorRed = 160;
+static const int debugReplicaBorderColorGreen = 0;
+static const int debugReplicaBorderColorBlue = 255;
+
PassOwnPtr<CCRenderPass> CCRenderPass::create(CCRenderSurface* targetSurface)
{
return adoptPtr(new CCRenderPass(targetSurface));
@@ -46,28 +58,62 @@ CCRenderPass::CCRenderPass(CCRenderSurface* targetSurface)
ASSERT(m_targetSurface);
}
-void CCRenderPass::appendQuadsForLayer(CCLayerImpl* layer)
+void CCRenderPass::appendQuadsForLayer(CCLayerImpl* layer, CCOcclusionTrackerImpl* occlusionTracker, bool& hadMissingTiles)
{
+ CCQuadCuller quadCuller(m_quadList, layer, occlusionTracker);
+
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
- layer->appendQuads(m_quadList, sharedQuadState.get());
- layer->appendDebugBorderQuad(m_quadList, sharedQuadState.get());
+ layer->appendDebugBorderQuad(quadCuller, sharedQuadState.get());
+ layer->appendQuads(quadCuller, sharedQuadState.get(), hadMissingTiles);
m_sharedQuadStateList.append(sharedQuadState.release());
}
-void CCRenderPass::appendQuadsForRenderSurfaceLayer(CCLayerImpl* layer)
+void CCRenderPass::appendQuadsForRenderSurfaceLayer(CCLayerImpl* layer, CCOcclusionTrackerImpl* occlusionTracker)
{
// FIXME: render surface layers should be a CCLayerImpl-derived class and
// not be handled specially here.
+ CCQuadCuller quadCuller(m_quadList, layer, occlusionTracker);
+
CCRenderSurface* surface = layer->renderSurface();
- bool isOpaque = false;
- OwnPtr<CCSharedQuadState> sharedQuadState = CCSharedQuadState::create(surface->drawTransform(), surface->drawTransform(), surface->contentRect(), surface->clipRect(), surface->drawOpacity(), isOpaque);
- m_quadList.append(CCRenderSurfaceDrawQuad::create(sharedQuadState.get(), surface->contentRect(), layer, surfaceDamageRect()));
+ OwnPtr<CCSharedQuadState> sharedQuadState = surface->createSharedQuadState();
+ if (layer->hasDebugBorders()) {
+ Color color(debugSurfaceBorderColorRed, debugSurfaceBorderColorGreen, debugSurfaceBorderColorBlue, debugSurfaceBorderAlpha);
+ quadCuller.appendSurface(CCDebugBorderDrawQuad::create(sharedQuadState.get(), surface->contentRect(), color, debugSurfaceBorderWidth));
+ }
+ bool isReplica = false;
+ quadCuller.appendSurface(CCRenderSurfaceDrawQuad::create(sharedQuadState.get(), surface->contentRect(), layer, surfaceDamageRect(), isReplica));
m_sharedQuadStateList.append(sharedQuadState.release());
+
+ // Add replica after the surface so that it appears below the surface.
+ if (surface->hasReplica()) {
+ OwnPtr<CCSharedQuadState> sharedQuadState = surface->createReplicaSharedQuadState();
+ if (layer->hasDebugBorders()) {
+ Color color(debugReplicaBorderColorRed, debugReplicaBorderColorGreen, debugReplicaBorderColorBlue, debugSurfaceBorderAlpha);
+ quadCuller.appendReplica(CCDebugBorderDrawQuad::create(sharedQuadState.get(), surface->contentRect(), color, debugSurfaceBorderWidth));
+ }
+ bool isReplica = true;
+ quadCuller.appendReplica(CCRenderSurfaceDrawQuad::create(sharedQuadState.get(), surface->contentRect(), layer, surfaceDamageRect(), isReplica));
+ m_sharedQuadStateList.append(sharedQuadState.release());
+ }
}
-void CCRenderPass::optimizeQuads(bool haveDamageRect, const FloatRect& damageRect, CCOverdrawCounts* overdraw)
+void CCRenderPass::appendQuadsToFillScreen(CCLayerImpl* rootLayer, const Color& screenBackgroundColor, const CCOcclusionTrackerImpl& occlusionTracker)
{
- CCQuadCuller::cullOccludedQuads(m_quadList, haveDamageRect, damageRect, overdraw);
+ if (!rootLayer || !screenBackgroundColor.isValid())
+ return;
+
+ Region fillRegion = occlusionTracker.computeVisibleRegionInScreen();
+ if (fillRegion.isEmpty())
+ return;
+
+ OwnPtr<CCSharedQuadState> sharedQuadState = rootLayer->createSharedQuadState();
+ TransformationMatrix transformToLayerSpace = rootLayer->screenSpaceTransform().inverse();
+ Vector<IntRect> fillRects = fillRegion.rects();
+ for (size_t i = 0; i < fillRects.size(); ++i) {
+ IntRect layerRect = transformToLayerSpace.mapRect(fillRects[i]);
+ m_quadList.append(CCSolidColorDrawQuad::create(sharedQuadState.get(), layerRect, screenBackgroundColor));
+ }
+ m_sharedQuadStateList.append(sharedQuadState.release());
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.h b/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.h
index 2affce541..452a8610f 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.h
@@ -27,6 +27,7 @@
#define CCRenderPass_h
#include "cc/CCDrawQuad.h"
+#include "cc/CCOcclusionTracker.h"
#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>
@@ -35,23 +36,18 @@ namespace WebCore {
class CCLayerImpl;
class CCRenderSurface;
class CCSharedQuadState;
+class Color;
-typedef Vector<OwnPtr<CCDrawQuad> > CCQuadList;
+// A list of CCDrawQuad objects, sorted internally in front-to-back order.
+class CCQuadList : public Vector<OwnPtr<CCDrawQuad> > {
+public:
+ typedef reverse_iterator backToFrontIterator;
+ typedef const_reverse_iterator constBackToFrontIterator;
-struct CCOverdrawCounts {
- CCOverdrawCounts()
- : m_pixelsDrawnOpaque(0)
- , m_pixelsDrawnTransparent(0)
- , m_pixelsCulled(0)
- {
- }
- // Count of pixels that are opaque (and thus occlude). Ideally this is no more
- // than wiewport width x height.
- float m_pixelsDrawnOpaque;
- // Count of pixels that are possibly transparent, and cannot occlude.
- float m_pixelsDrawnTransparent;
- // Count of pixels not drawn as they are occluded by somthing opaque.
- float m_pixelsCulled;
+ inline backToFrontIterator backToFrontBegin() { return rbegin(); }
+ inline backToFrontIterator backToFrontEnd() { return rend(); }
+ inline constBackToFrontIterator backToFrontBegin() const { return rbegin(); }
+ inline constBackToFrontIterator backToFrontEnd() const { return rend(); }
};
class CCRenderPass {
@@ -59,11 +55,9 @@ class CCRenderPass {
public:
static PassOwnPtr<CCRenderPass> create(CCRenderSurface*);
- void appendQuadsForLayer(CCLayerImpl*);
- void appendQuadsForRenderSurfaceLayer(CCLayerImpl*);
-
- // Passing in 0 for CCOverdrawCounts is valid, and disables performing overdraw calculations.
- void optimizeQuads(bool haveDamageRect, const FloatRect& damageRect, CCOverdrawCounts*);
+ void appendQuadsForLayer(CCLayerImpl*, CCOcclusionTrackerImpl*, bool& hadMissingTiles);
+ void appendQuadsForRenderSurfaceLayer(CCLayerImpl*, CCOcclusionTrackerImpl*);
+ void appendQuadsToFillScreen(CCLayerImpl* rootLayer, const Color& screenBackgroundColor, const CCOcclusionTrackerImpl&);
const CCQuadList& quadList() const { return m_quadList; }
CCRenderSurface* targetSurface() const { return m_targetSurface; }
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp
index 25ac8fa9b..ec1ac167a 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp
@@ -41,6 +41,7 @@
#include "cc/CCLayerImpl.h"
#include "cc/CCProxy.h"
#include "cc/CCRenderSurfaceFilters.h"
+#include "cc/CCSharedQuadState.h"
#include <wtf/text/CString.h>
namespace WebCore {
@@ -51,7 +52,12 @@ CCRenderSurface::CCRenderSurface(CCLayerImpl* owningLayer)
, m_skipsDraw(false)
, m_surfacePropertyChanged(false)
, m_drawOpacity(1)
+ , m_drawOpacityIsAnimating(false)
+ , m_targetSurfaceTransformsAreAnimating(false)
+ , m_screenSpaceTransformsAreAnimating(false)
, m_nearestAncestorThatMovesPixels(0)
+ , m_targetRenderSurfaceLayerIndexHistory(0)
+ , m_currentLayerIndexHistory(0)
{
m_damageTracker = CCDamageTracker::create();
}
@@ -65,7 +71,7 @@ FloatRect CCRenderSurface::drawableContentRect() const
FloatRect localContentRect(-0.5 * m_contentRect.width(), -0.5 * m_contentRect.height(),
m_contentRect.width(), m_contentRect.height());
FloatRect drawableContentRect = m_drawTransform.mapRect(localContentRect);
- if (m_owningLayer->replicaLayer())
+ if (hasReplica())
drawableContentRect.unite(m_replicaDrawTransform.mapRect(localContentRect));
return drawableContentRect;
@@ -98,22 +104,112 @@ void CCRenderSurface::releaseContentsTexture()
m_contentsTexture->unreserve();
}
-void CCRenderSurface::draw(LayerRendererChromium* layerRenderer, const FloatRect& surfaceDamageRect)
+bool CCRenderSurface::prepareBackgroundTexture(LayerRendererChromium* layerRenderer)
{
- if (m_skipsDraw || !m_contentsTexture)
+ IntSize requiredSize(m_contentRect.size());
+ TextureManager* textureManager = layerRenderer->renderSurfaceTextureManager();
+
+ if (!m_backgroundTexture)
+ m_backgroundTexture = ManagedTexture::create(textureManager);
+
+ if (m_backgroundTexture->isReserved())
+ return true;
+
+ if (!m_backgroundTexture->reserve(requiredSize, GraphicsContext3D::RGBA))
+ return false;
+
+ return true;
+}
+
+void CCRenderSurface::releaseBackgroundTexture()
+{
+ if (!m_backgroundTexture)
return;
+ m_backgroundTexture->unreserve();
+}
- SkBitmap filterBitmap = applyFilters(layerRenderer);
- // FIXME: By using the same RenderSurface for both the content and its reflection,
- // it's currently not possible to apply a separate mask to the reflection layer
- // or correctly handle opacity in reflections (opacity must be applied after drawing
- // both the layer and its reflection). The solution is to introduce yet another RenderSurface
- // to draw the layer and its reflection in. For now we only apply a separate reflection
- // mask if the contents don't have a mask of their own.
- CCLayerImpl* replicaMaskLayer = m_maskLayer;
- if (!m_maskLayer && m_owningLayer->replicaLayer())
- replicaMaskLayer = m_owningLayer->replicaLayer()->maskLayer();
+TransformationMatrix CCRenderSurface::computeDeviceTransform(LayerRendererChromium* layerRenderer, const TransformationMatrix& drawTransform) const
+{
+ TransformationMatrix renderTransform = drawTransform;
+ // Apply a scaling factor to size the quad from 1x1 to its intended size.
+ renderTransform.scale3d(m_contentRect.width(), m_contentRect.height(), 1);
+ TransformationMatrix deviceTransform = TransformationMatrix(layerRenderer->windowMatrix() * layerRenderer->projectionMatrix() * renderTransform).to2dTransform();
+ return deviceTransform;
+}
+
+IntRect CCRenderSurface::computeDeviceBoundingBox(LayerRendererChromium* layerRenderer, const TransformationMatrix& drawTransform) const
+{
+ TransformationMatrix contentsDeviceTransform = computeDeviceTransform(layerRenderer, drawTransform);
+
+ // Can only draw surface if device matrix is invertible.
+ if (!contentsDeviceTransform.isInvertible())
+ return IntRect();
+
+ FloatQuad deviceQuad = contentsDeviceTransform.mapQuad(layerRenderer->sharedGeometryQuad());
+ return enclosingIntRect(deviceQuad.boundingBox());
+}
+
+IntRect CCRenderSurface::computeReadbackDeviceBoundingBox(LayerRendererChromium* layerRenderer, const TransformationMatrix& drawTransform) const
+{
+ IntRect deviceRect = computeDeviceBoundingBox(layerRenderer, drawTransform);
+
+ if (m_backgroundFilters.isEmpty())
+ return deviceRect;
+
+ int top, right, bottom, left;
+ m_backgroundFilters.getOutsets(top, right, bottom, left);
+ deviceRect.move(-left, -top);
+ deviceRect.expand(left + right, top + bottom);
+
+ return deviceRect;
+}
+
+IntRect CCRenderSurface::readbackDeviceContentRect(LayerRendererChromium* layerRenderer, const TransformationMatrix& drawTransform) const
+{
+ return computeReadbackDeviceBoundingBox(layerRenderer, drawTransform);
+}
+
+void CCRenderSurface::copyTextureToFramebuffer(LayerRendererChromium* layerRenderer, int textureId, const IntSize& bounds, const TransformationMatrix& drawMatrix)
+{
+ const LayerRendererChromium::RenderSurfaceProgram* program = layerRenderer->renderSurfaceProgram();
+
+ GLC(layerRenderer->context(), layerRenderer->context()->activeTexture(GraphicsContext3D::TEXTURE0));
+ GLC(layerRenderer->context(), layerRenderer->context()->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
+ GLC(layerRenderer->context(), layerRenderer->context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
+ GLC(layerRenderer->context(), layerRenderer->context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
+
+ GLC(layerRenderer->context(), layerRenderer->context()->useProgram(program->program()));
+ GLC(layerRenderer->context(), layerRenderer->context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
+ layerRenderer->drawTexturedQuad(drawMatrix, bounds.width(), bounds.height(), 1, layerRenderer->sharedGeometryQuad(),
+ program->vertexShader().matrixLocation(),
+ program->fragmentShader().alphaLocation(),
+ -1);
+}
+void CCRenderSurface::copyDeviceToBackgroundTexture(LayerRendererChromium* layerRenderer, int deviceBackgroundTextureId, const IntRect& deviceTextureRect, const TransformationMatrix& deviceTransform) const
+{
+ ASSERT(!m_backgroundFilters.isEmpty());
+
+ TransformationMatrix deviceToSurfaceTransform;
+ deviceToSurfaceTransform.translate(m_contentRect.width() / 2.0, m_contentRect.height() / 2.0);
+ deviceToSurfaceTransform.scale3d(m_contentRect.width(), m_contentRect.height(), 1);
+ deviceToSurfaceTransform *= deviceTransform.inverse();
+ deviceToSurfaceTransform.translate(deviceTextureRect.width() / 2.0, deviceTextureRect.height() / 2.0);
+ deviceToSurfaceTransform.translate(deviceTextureRect.x(), deviceTextureRect.y());
+
+ copyTextureToFramebuffer(layerRenderer, deviceBackgroundTextureId, deviceTextureRect.size(), deviceToSurfaceTransform);
+}
+
+inline static int getSkBitmapTextureId(const SkBitmap& bitmap, int fallback)
+{
+ if (!bitmap.getTexture())
+ return fallback;
+ GrTexture* texture = reinterpret_cast<GrTexture*>(bitmap.getTexture());
+ return texture->getTextureHandle();
+}
+
+void CCRenderSurface::setScissorRect(LayerRendererChromium* layerRenderer, const FloatRect& surfaceDamageRect) const
+{
if (m_owningLayer->parent() && m_owningLayer->parent()->usesLayerClipping() && layerRenderer->capabilities().usingPartialSwap) {
FloatRect clipAndDamageRect = m_clipRect;
clipAndDamageRect.intersect(surfaceDamageRect);
@@ -124,26 +220,56 @@ void CCRenderSurface::draw(LayerRendererChromium* layerRenderer, const FloatRect
layerRenderer->setScissorToRect(m_clipRect);
else
GLC(layerRenderer->context(), layerRenderer->context()->disable(GraphicsContext3D::SCISSOR_TEST));
+}
+
+void CCRenderSurface::drawContents(LayerRendererChromium* layerRenderer)
+{
+ if (m_skipsDraw || !m_contentsTexture)
+ return;
- // Reflection draws before the layer.
- if (m_owningLayer->replicaLayer())
- drawLayer(layerRenderer, replicaMaskLayer, m_replicaDrawTransform, filterBitmap);
+ // FIXME: Cache this value so that we don't have to do it for both the surface and its replica.
+ // Apply filters to the contents texture.
+ SkBitmap filterBitmap = applyFilters(layerRenderer, m_filters, m_contentsTexture.get());
- drawLayer(layerRenderer, m_maskLayer, m_drawTransform, filterBitmap);
+ int contentsTextureId = getSkBitmapTextureId(filterBitmap, m_contentsTexture->textureId());
+ drawLayer(layerRenderer, m_maskLayer, m_drawTransform, contentsTextureId);
}
-void CCRenderSurface::drawLayer(LayerRendererChromium* layerRenderer, CCLayerImpl* maskLayer, const TransformationMatrix& drawTransform, const SkBitmap& filterBitmap)
+void CCRenderSurface::drawReplica(LayerRendererChromium* layerRenderer)
{
- TransformationMatrix renderMatrix = drawTransform;
- // Apply a scaling factor to size the quad from 1x1 to its intended size.
- renderMatrix.scale3d(m_contentRect.width(), m_contentRect.height(), 1);
+ ASSERT(hasReplica());
+ if (!hasReplica() || m_skipsDraw || !m_contentsTexture)
+ return;
+
+ // Apply filters to the contents texture.
+ SkBitmap filterBitmap = applyFilters(layerRenderer, m_filters, m_contentsTexture.get());
+
+ // FIXME: By using the same RenderSurface for both the content and its reflection,
+ // it's currently not possible to apply a separate mask to the reflection layer
+ // or correctly handle opacity in reflections (opacity must be applied after drawing
+ // both the layer and its reflection). The solution is to introduce yet another RenderSurface
+ // to draw the layer and its reflection in. For now we only apply a separate reflection
+ // mask if the contents don't have a mask of their own.
+ CCLayerImpl* replicaMaskLayer = m_maskLayer;
+ if (!m_maskLayer && m_owningLayer->replicaLayer())
+ replicaMaskLayer = m_owningLayer->replicaLayer()->maskLayer();
- TransformationMatrix deviceMatrix = TransformationMatrix(layerRenderer->windowMatrix() * layerRenderer->projectionMatrix() * renderMatrix).to2dTransform();
+ int contentsTextureId = getSkBitmapTextureId(filterBitmap, m_contentsTexture->textureId());
+ drawLayer(layerRenderer, replicaMaskLayer, m_replicaDrawTransform, contentsTextureId);
+}
+
+void CCRenderSurface::drawLayer(LayerRendererChromium* layerRenderer, CCLayerImpl* maskLayer, const TransformationMatrix& drawTransform, int contentsTextureId)
+{
+ TransformationMatrix deviceMatrix = computeDeviceTransform(layerRenderer, drawTransform);
// Can only draw surface if device matrix is invertible.
if (!deviceMatrix.isInvertible())
return;
+ // Draw the background texture if there is one.
+ if (m_backgroundTexture && m_backgroundTexture->isReserved())
+ copyTextureToFramebuffer(layerRenderer, m_backgroundTexture->textureId(), m_contentRect.size(), drawTransform);
+
FloatQuad quad = deviceMatrix.mapQuad(layerRenderer->sharedGeometryQuad());
CCLayerQuad deviceRect = CCLayerQuad(FloatQuad(quad.boundingBox()));
CCLayerQuad layerQuad = CCLayerQuad(quad);
@@ -161,27 +287,29 @@ void CCRenderSurface::drawLayer(LayerRendererChromium* layerRenderer, CCLayerImp
if (!maskLayer->bounds().isEmpty())
useMask = true;
+ // FIXME: pass in backgroundTextureId and blend the background in with this draw instead of having a separate drawBackground() pass.
+
if (useMask) {
if (useAA) {
- const MaskProgramAA* program = layerRenderer->renderSurfaceMaskProgramAA();
- drawSurface(layerRenderer, maskLayer, drawTransform, deviceMatrix, deviceRect, layerQuad, program, program->fragmentShader().maskSamplerLocation(), program->vertexShader().pointLocation(), program->fragmentShader().edgeLocation(), filterBitmap);
+ const LayerRendererChromium::RenderSurfaceMaskProgramAA* program = layerRenderer->renderSurfaceMaskProgramAA();
+ drawSurface(layerRenderer, maskLayer, drawTransform, deviceMatrix, deviceRect, layerQuad, contentsTextureId, program, program->fragmentShader().maskSamplerLocation(), program->vertexShader().pointLocation(), program->fragmentShader().edgeLocation());
} else {
- const MaskProgram* program = layerRenderer->renderSurfaceMaskProgram();
- drawSurface(layerRenderer, maskLayer, drawTransform, deviceMatrix, deviceRect, layerQuad, program, program->fragmentShader().maskSamplerLocation(), -1, -1, filterBitmap);
+ const LayerRendererChromium::RenderSurfaceMaskProgram* program = layerRenderer->renderSurfaceMaskProgram();
+ drawSurface(layerRenderer, maskLayer, drawTransform, deviceMatrix, deviceRect, layerQuad, contentsTextureId, program, program->fragmentShader().maskSamplerLocation(), -1, -1);
}
} else {
if (useAA) {
- const ProgramAA* program = layerRenderer->renderSurfaceProgramAA();
- drawSurface(layerRenderer, maskLayer, drawTransform, deviceMatrix, deviceRect, layerQuad, program, -1, program->vertexShader().pointLocation(), program->fragmentShader().edgeLocation(), filterBitmap);
+ const LayerRendererChromium::RenderSurfaceProgramAA* program = layerRenderer->renderSurfaceProgramAA();
+ drawSurface(layerRenderer, maskLayer, drawTransform, deviceMatrix, deviceRect, layerQuad, contentsTextureId, program, -1, program->vertexShader().pointLocation(), program->fragmentShader().edgeLocation());
} else {
- const Program* program = layerRenderer->renderSurfaceProgram();
- drawSurface(layerRenderer, maskLayer, drawTransform, deviceMatrix, deviceRect, layerQuad, program, -1, -1, -1, filterBitmap);
+ const LayerRendererChromium::RenderSurfaceProgram* program = layerRenderer->renderSurfaceProgram();
+ drawSurface(layerRenderer, maskLayer, drawTransform, deviceMatrix, deviceRect, layerQuad, contentsTextureId, program, -1, -1, -1);
}
}
}
template <class T>
-void CCRenderSurface::drawSurface(LayerRendererChromium* layerRenderer, CCLayerImpl* maskLayer, const TransformationMatrix& drawTransform, const TransformationMatrix& deviceTransform, const CCLayerQuad& deviceRect, const CCLayerQuad& layerQuad, const T* program, int shaderMaskSamplerLocation, int shaderQuadLocation, int shaderEdgeLocation, const SkBitmap& filterBitmap)
+void CCRenderSurface::drawSurface(LayerRendererChromium* layerRenderer, CCLayerImpl* maskLayer, const TransformationMatrix& drawTransform, const TransformationMatrix& deviceTransform, const CCLayerQuad& deviceRect, const CCLayerQuad& layerQuad, int contentsTextureId, const T* program, int shaderMaskSamplerLocation, int shaderQuadLocation, int shaderEdgeLocation)
{
GraphicsContext3D* context3D = layerRenderer->context();
@@ -190,11 +318,7 @@ void CCRenderSurface::drawSurface(LayerRendererChromium* layerRenderer, CCLayerI
GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE0));
GLC(context3D, context3D->uniform1i(program->fragmentShader().samplerLocation(), 0));
- if (filterBitmap.getTexture()) {
- GrTexture* texture = reinterpret_cast<GrTexture*>(filterBitmap.getTexture());
- context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, texture->getTextureHandle());
- } else
- m_contentsTexture->bindTexture(context3D, layerRenderer->renderSurfaceTextureAllocator());
+ context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, contentsTextureId);
if (shaderMaskSamplerLocation != -1) {
GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE1));
@@ -217,15 +341,18 @@ void CCRenderSurface::drawSurface(LayerRendererChromium* layerRenderer, CCLayerI
program->vertexShader().matrixLocation(), program->fragmentShader().alphaLocation(), shaderQuadLocation);
}
-SkBitmap CCRenderSurface::applyFilters(LayerRendererChromium* layerRenderer)
+SkBitmap CCRenderSurface::applyFilters(LayerRendererChromium* layerRenderer, const FilterOperations& filters, ManagedTexture* sourceTexture)
{
- // Don't use the utility context if we have a compositor thread, since
- // it can race with canvas's use.
- if (!m_contentsTexture || !m_filters.size() || CCProxy::hasImplThread())
+ if (filters.isEmpty())
+ return SkBitmap();
+
+ RefPtr<GraphicsContext3D> filterContext = CCProxy::hasImplThread() ? SharedGraphicsContext3D::getForImplThread() : SharedGraphicsContext3D::get();
+ if (!filterContext)
return SkBitmap();
layerRenderer->context()->flush();
- return CCRenderSurfaceFilters::apply(m_filters, m_contentsTexture->textureId(), m_contentRect.size(), SharedGraphicsContext3D::get());
+
+ return CCRenderSurfaceFilters::apply(filters, sourceTexture->textureId(), sourceTexture->size(), filterContext.get());
}
String CCRenderSurface::name() const
@@ -264,6 +391,11 @@ int CCRenderSurface::owningLayerId() const
return m_owningLayer ? m_owningLayer->id() : 0;
}
+bool CCRenderSurface::hasReplica() const
+{
+ return m_owningLayer->replicaLayer();
+}
+
void CCRenderSurface::setClipRect(const IntRect& clipRect)
{
if (m_clipRect == clipRect)
@@ -301,5 +433,17 @@ bool CCRenderSurface::surfacePropertyChangedOnlyFromDescendant() const
return m_surfacePropertyChanged && !m_owningLayer->layerPropertyChanged();
}
+PassOwnPtr<CCSharedQuadState> CCRenderSurface::createSharedQuadState() const
+{
+ bool isOpaque = false;
+ return CCSharedQuadState::create(originTransform(), drawTransform(), contentRect(), clipRect(), drawOpacity(), isOpaque);
+}
+
+PassOwnPtr<CCSharedQuadState> CCRenderSurface::createReplicaSharedQuadState() const
+{
+ bool isOpaque = false;
+ return CCSharedQuadState::create(replicaOriginTransform(), replicaDrawTransform(), contentRect(), clipRect(), drawOpacity(), isOpaque);
+}
+
}
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.h b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.h
index 141ed2d24..10a5f365e 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.h
@@ -32,8 +32,6 @@
#include "FilterOperations.h"
#include "FloatRect.h"
#include "IntRect.h"
-#include "ProgramBinding.h"
-#include "ShaderChromium.h"
#include "SkBitmap.h"
#include "TextureManager.h"
#include "TransformationMatrix.h"
@@ -43,6 +41,7 @@
namespace WebCore {
class CCDamageTracker;
+class CCSharedQuadState;
class CCLayerImpl;
class LayerRendererChromium;
class ManagedTexture;
@@ -56,7 +55,17 @@ public:
bool prepareContentsTexture(LayerRendererChromium*);
void releaseContentsTexture();
- void draw(LayerRendererChromium*, const FloatRect& surfaceDamageRect);
+ bool prepareBackgroundTexture(LayerRendererChromium*);
+ void releaseBackgroundTexture();
+
+ void setScissorRect(LayerRendererChromium*, const FloatRect& surfaceDamageRect) const;
+
+ void drawContents(LayerRendererChromium*);
+ void drawReplica(LayerRendererChromium*);
+
+ // Takes a texture with pixels in device space, and a transform from content space to the device. Copies the device-space texture back into
+ // content space for the surface, storing the result in the backgroundTexture(). The surface's backgroundTexture() must be the active drawing target.
+ void copyDeviceToBackgroundTexture(LayerRendererChromium*, int deviceBackgroundTextureId, const IntRect& deviceTextureRect, const TransformationMatrix& deviceTransform) const;
String name() const;
void dumpSurface(TextStream&, int indent) const;
@@ -65,26 +74,52 @@ public:
// Returns the rect that encloses the RenderSurface including any reflection.
FloatRect drawableContentRect() const;
+ // Returns the rect that encloses the pixels that may affect the pixel values in this surface through background filters.
+ IntRect readbackDeviceContentRect(LayerRendererChromium*, const TransformationMatrix& drawTransform) const;
+
+ // Gives the transform from the surface content space, with origin in the top left, to the current target device space, with origin in the top left.
+ TransformationMatrix computeDeviceTransform(LayerRendererChromium*, const TransformationMatrix& drawTransform) const;
float drawOpacity() const { return m_drawOpacity; }
void setDrawOpacity(float opacity) { m_drawOpacity = opacity; }
- void setDrawTransform(const TransformationMatrix& drawTransform) { m_drawTransform = drawTransform; }
- const TransformationMatrix& drawTransform() const { return m_drawTransform; }
-
void setFilters(const FilterOperations& filters) { m_filters = filters; }
const FilterOperations& filters() const { return m_filters; }
- SkBitmap applyFilters(LayerRendererChromium*);
+ SkBitmap applyFilters(LayerRendererChromium*, const FilterOperations&, ManagedTexture* sourceTexture);
+
+ void setBackgroundFilters(const FilterOperations& filters) { m_backgroundFilters = filters; }
+ const FilterOperations& backgroundFilters() const { return m_backgroundFilters; }
void setNearestAncestorThatMovesPixels(CCRenderSurface* surface) { m_nearestAncestorThatMovesPixels = surface; }
const CCRenderSurface* nearestAncestorThatMovesPixels() const { return m_nearestAncestorThatMovesPixels; }
- void setReplicaDrawTransform(const TransformationMatrix& replicaDrawTransform) { m_replicaDrawTransform = replicaDrawTransform; }
- const TransformationMatrix& replicaDrawTransform() const { return m_replicaDrawTransform; }
+ bool drawOpacityIsAnimating() const { return m_drawOpacityIsAnimating; }
+ void setDrawOpacityIsAnimating(bool drawOpacityIsAnimating) { m_drawOpacityIsAnimating = drawOpacityIsAnimating; }
+
+ void setDrawTransform(const TransformationMatrix& drawTransform) { m_drawTransform = drawTransform; }
+ const TransformationMatrix& drawTransform() const { return m_drawTransform; }
void setOriginTransform(const TransformationMatrix& originTransform) { m_originTransform = originTransform; }
const TransformationMatrix& originTransform() const { return m_originTransform; }
+ void setScreenSpaceTransform(const TransformationMatrix& screenSpaceTransform) { m_screenSpaceTransform = screenSpaceTransform; }
+ const TransformationMatrix& screenSpaceTransform() const { return m_screenSpaceTransform; }
+
+ void setReplicaDrawTransform(const TransformationMatrix& replicaDrawTransform) { m_replicaDrawTransform = replicaDrawTransform; }
+ const TransformationMatrix& replicaDrawTransform() const { return m_replicaDrawTransform; }
+
+ void setReplicaOriginTransform(const TransformationMatrix& replicaOriginTransform) { m_replicaOriginTransform = replicaOriginTransform; }
+ const TransformationMatrix& replicaOriginTransform() const { return m_replicaOriginTransform; }
+
+ void setReplicaScreenSpaceTransform(const TransformationMatrix& replicaScreenSpaceTransform) { m_replicaScreenSpaceTransform = replicaScreenSpaceTransform; }
+ const TransformationMatrix& replicaScreenSpaceTransform() const { return m_replicaScreenSpaceTransform; }
+
+ bool targetSurfaceTransformsAreAnimating() const { return m_targetSurfaceTransformsAreAnimating; }
+ void setTargetSurfaceTransformsAreAnimating(bool animating) { m_targetSurfaceTransformsAreAnimating = animating; }
+ bool screenSpaceTransformsAreAnimating() const { return m_screenSpaceTransformsAreAnimating; }
+ void setScreenSpaceTransformsAreAnimating(bool animating) { m_screenSpaceTransformsAreAnimating = animating; }
+
+ // Usage: this clipRect should not be used if one of the two conditions is true: (a) clipRect() is empty, or (b) owningLayer->parent()->usesLayerClipping() is false.
void setClipRect(const IntRect&);
const IntRect& clipRect() const { return m_clipRect; }
@@ -99,25 +134,31 @@ public:
void setMaskLayer(CCLayerImpl* maskLayer) { m_maskLayer = maskLayer; }
- typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexAlpha> Program;
- typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexAlphaMask> MaskProgram;
- typedef ProgramBinding<VertexShaderQuad, FragmentShaderRGBATexAlphaAA> ProgramAA;
- typedef ProgramBinding<VertexShaderQuad, FragmentShaderRGBATexAlphaMaskAA> MaskProgramAA;
-
ManagedTexture* contentsTexture() const { return m_contentsTexture.get(); }
+ ManagedTexture* backgroundTexture() const { return m_backgroundTexture.get(); }
int owningLayerId() const;
+ bool hasReplica() const;
+
void resetPropertyChangedFlag() { m_surfacePropertyChanged = false; }
bool surfacePropertyChanged() const;
bool surfacePropertyChangedOnlyFromDescendant() const;
CCDamageTracker* damageTracker() const { return m_damageTracker.get(); }
+ PassOwnPtr<CCSharedQuadState> createSharedQuadState() const;
+ PassOwnPtr<CCSharedQuadState> createReplicaSharedQuadState() const;
+
private:
- void drawLayer(LayerRendererChromium*, CCLayerImpl*, const TransformationMatrix&, const SkBitmap& filterBitmap);
+ IntRect computeDeviceBoundingBox(LayerRendererChromium*, const TransformationMatrix& drawTransform) const;
+ IntRect computeReadbackDeviceBoundingBox(LayerRendererChromium*, const TransformationMatrix& drawTransform) const;
+
+ void drawLayer(LayerRendererChromium*, CCLayerImpl*, const TransformationMatrix&, int contentsTextureId);
template <class T>
- void drawSurface(LayerRendererChromium*, CCLayerImpl*, const TransformationMatrix& drawTransform, const TransformationMatrix& deviceTransform, const CCLayerQuad& deviceRect, const CCLayerQuad&, const T* program, int shaderMaskSamplerLocation, int shaderQuadLocation, int shaderEdgeLocation, const SkBitmap& filterBitmap);
+ void drawSurface(LayerRendererChromium*, CCLayerImpl*, const TransformationMatrix& drawTransform, const TransformationMatrix& deviceTransform, const CCLayerQuad& deviceRect, const CCLayerQuad&, int contentsTextureId, const T* program, int shaderMaskSamplerLocation, int shaderQuadLocation, int shaderEdgeLocation);
+
+ static void copyTextureToFramebuffer(LayerRendererChromium*, int textureId, const IntSize& bounds, const TransformationMatrix& drawMatrix);
CCLayerImpl* m_owningLayer;
CCLayerImpl* m_maskLayer;
@@ -127,11 +168,20 @@ private:
bool m_surfacePropertyChanged;
OwnPtr<ManagedTexture> m_contentsTexture;
+ OwnPtr<ManagedTexture> m_backgroundTexture;
+
float m_drawOpacity;
+ bool m_drawOpacityIsAnimating;
TransformationMatrix m_drawTransform;
- TransformationMatrix m_replicaDrawTransform;
TransformationMatrix m_originTransform;
+ TransformationMatrix m_screenSpaceTransform;
+ TransformationMatrix m_replicaDrawTransform;
+ TransformationMatrix m_replicaOriginTransform;
+ TransformationMatrix m_replicaScreenSpaceTransform;
+ bool m_targetSurfaceTransformsAreAnimating;
+ bool m_screenSpaceTransformsAreAnimating;
FilterOperations m_filters;
+ FilterOperations m_backgroundFilters;
IntRect m_clipRect;
Vector<CCLayerImpl*> m_layerList;
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceDrawQuad.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceDrawQuad.cpp
index c89a172d1..c6e021ece 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceDrawQuad.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceDrawQuad.cpp
@@ -29,15 +29,16 @@
namespace WebCore {
-PassOwnPtr<CCRenderSurfaceDrawQuad> CCRenderSurfaceDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCLayerImpl* layer, const FloatRect& surfaceDamageRect)
+PassOwnPtr<CCRenderSurfaceDrawQuad> CCRenderSurfaceDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCLayerImpl* layer, const FloatRect& surfaceDamageRect, bool isReplica)
{
- return adoptPtr(new CCRenderSurfaceDrawQuad(sharedQuadState, quadRect, layer, surfaceDamageRect));
+ return adoptPtr(new CCRenderSurfaceDrawQuad(sharedQuadState, quadRect, layer, surfaceDamageRect, isReplica));
}
-CCRenderSurfaceDrawQuad::CCRenderSurfaceDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCLayerImpl* layer, const FloatRect& surfaceDamageRect)
+CCRenderSurfaceDrawQuad::CCRenderSurfaceDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCLayerImpl* layer, const FloatRect& surfaceDamageRect, bool isReplica)
: CCDrawQuad(sharedQuadState, CCDrawQuad::RenderSurface, quadRect)
, m_layer(layer)
, m_surfaceDamageRect(surfaceDamageRect)
+ , m_isReplica(isReplica)
{
ASSERT(m_layer);
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceDrawQuad.h b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceDrawQuad.h
index 7535d32da..8f6da5eee 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceDrawQuad.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceDrawQuad.h
@@ -36,19 +36,21 @@ class CCLayerImpl;
class CCRenderSurfaceDrawQuad : public CCDrawQuad {
WTF_MAKE_NONCOPYABLE(CCRenderSurfaceDrawQuad);
public:
- static PassOwnPtr<CCRenderSurfaceDrawQuad> create(const CCSharedQuadState*, const IntRect&, CCLayerImpl*, const FloatRect& surfaceDamageRect);
+ static PassOwnPtr<CCRenderSurfaceDrawQuad> create(const CCSharedQuadState*, const IntRect&, CCLayerImpl*, const FloatRect& surfaceDamageRect, bool isReplica);
CCLayerImpl* layer() const { return m_layer; }
+ bool isReplica() const { return m_isReplica; }
// The surface damage rect for the target surface this quad draws into.
// FIXME: This can be removed once render surfaces get their own layer type.
const FloatRect& surfaceDamageRect() const { return m_surfaceDamageRect; }
private:
- CCRenderSurfaceDrawQuad(const CCSharedQuadState*, const IntRect&, CCLayerImpl*, const FloatRect& surfaceDamageRect);
+ CCRenderSurfaceDrawQuad(const CCSharedQuadState*, const IntRect&, CCLayerImpl*, const FloatRect& surfaceDamageRect, bool isReplica);
CCLayerImpl* m_layer;
FloatRect m_surfaceDamageRect;
+ bool m_isReplica;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceFilters.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceFilters.cpp
index b175d112d..35cf6abc5 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceFilters.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceFilters.cpp
@@ -30,6 +30,7 @@
#include "cc/CCRenderSurfaceFilters.h"
#include "GraphicsContext3D.h"
+#include "LengthFunctions.h"
#include "SkBlurImageFilter.h"
#include "SkCanvas.h"
#include "SkColorMatrixFilter.h"
@@ -202,7 +203,7 @@ SkBitmap CCRenderSurfaceFilters::apply(const FilterOperations& filters, unsigned
desc.fSampleCnt = 0;
desc.fWidth = size.width();
desc.fHeight = size.height();
- desc.fConfig = kRGBA_8888_GrPixelConfig;
+ desc.fConfig = kSkia8888_PM_GrPixelConfig;
// FIXME: could we use approximate match, and fix texcoords on draw
dest = gr->lockScratchTexture(desc, GrContext::kExact_ScratchTexMatch);
if (!dest.texture())
@@ -269,15 +270,12 @@ SkBitmap CCRenderSurfaceFilters::apply(const FilterOperations& filters, unsigned
}
case FilterOperation::BLUR: {
const BlurFilterOperation* op = static_cast<const BlurFilterOperation*>(filterOperation);
- float stdX = op->stdDeviation().calcFloatValue(0);
- float stdY = op->stdDeviation().calcFloatValue(1);
+ float stdX = floatValueForLength(op->stdDeviation(), 0);
+ float stdY = floatValueForLength(op->stdDeviation(), 1);
SkAutoTUnref<SkImageFilter> filter(new SkBlurImageFilter(stdX, stdY));
SkPaint paint;
paint.setImageFilter(filter.get());
- paint.setColor(0xFFFFFFFF);
- canvas.saveLayer(0, &paint);
- canvas.drawBitmap(source, 0, 0);
- canvas.restore();
+ canvas.drawSprite(source, 0, 0, &paint);
break;
}
case FilterOperation::DROP_SHADOW: {
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp
index 633f21d47..84b842358 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp
@@ -44,6 +44,12 @@ CCScheduler::~CCScheduler()
m_frameRateController->setActive(false);
}
+void CCScheduler::setCanBeginFrame(bool can)
+{
+ m_stateMachine.setCanBeginFrame(can);
+ processScheduledActions();
+}
+
void CCScheduler::setVisible(bool visible)
{
m_stateMachine.setVisible(visible);
@@ -56,6 +62,12 @@ void CCScheduler::setNeedsCommit()
processScheduledActions();
}
+void CCScheduler::setNeedsForcedCommit()
+{
+ m_stateMachine.setNeedsForcedCommit();
+ processScheduledActions();
+}
+
void CCScheduler::setNeedsRedraw()
{
m_stateMachine.setNeedsRedraw();
@@ -68,6 +80,12 @@ void CCScheduler::setNeedsForcedRedraw()
processScheduledActions();
}
+void CCScheduler::setMainThreadNeedsLayerTextures()
+{
+ m_stateMachine.setMainThreadNeedsLayerTextures();
+ processScheduledActions();
+}
+
void CCScheduler::beginFrameComplete()
{
TRACE_EVENT("CCScheduler::beginFrameComplete", this, 0);
@@ -101,13 +119,13 @@ void CCScheduler::didRecreateContext()
processScheduledActions();
}
-void CCScheduler::beginFrame()
+void CCScheduler::vsyncTick()
{
if (m_updateMoreResourcesPending) {
m_updateMoreResourcesPending = false;
m_stateMachine.beginUpdateMoreResourcesComplete(m_client->hasMoreResourceUpdates());
}
- TRACE_EVENT("CCScheduler::beginFrame", this, 0);
+ TRACE_EVENT("CCScheduler::vsyncTick", this, 0);
m_stateMachine.didEnterVSync();
processScheduledActions();
@@ -156,13 +174,24 @@ void CCScheduler::processScheduledActions()
case CCSchedulerStateMachine::ACTION_COMMIT:
m_client->scheduledActionCommit();
break;
- case CCSchedulerStateMachine::ACTION_DRAW:
- m_client->scheduledActionDrawAndSwap();
- m_frameRateController->didBeginFrame();
+ case CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE: {
+ CCScheduledActionDrawAndSwapResult result = m_client->scheduledActionDrawAndSwapIfPossible();
+ m_stateMachine.didDrawIfPossibleCompleted(result.didDraw);
+ if (result.didSwap)
+ m_frameRateController->didBeginFrame();
break;
- case CCSchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION:
+ }
+ case CCSchedulerStateMachine::ACTION_DRAW_FORCED: {
+ CCScheduledActionDrawAndSwapResult result = m_client->scheduledActionDrawAndSwapForced();
+ if (result.didSwap)
+ m_frameRateController->didBeginFrame();
+ break;
+ } case CCSchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION:
m_client->scheduledActionBeginContextRecreation();
break;
+ case CCSchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
+ m_client->scheduledActionAcquireLayerTexturesForMainThread();
+ break;
}
} while (action != CCSchedulerStateMachine::ACTION_NONE);
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.h b/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.h
index f8ba21f99..0e6971642 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.h
@@ -35,16 +35,33 @@ namespace WebCore {
class CCThread;
+struct CCScheduledActionDrawAndSwapResult {
+ CCScheduledActionDrawAndSwapResult()
+ : didDraw(false)
+ , didSwap(false)
+ {
+ }
+ CCScheduledActionDrawAndSwapResult(bool didDraw, bool didSwap)
+ : didDraw(didDraw)
+ , didSwap(didSwap)
+ {
+ }
+ bool didDraw;
+ bool didSwap;
+};
+
class CCSchedulerClient {
public:
virtual bool canDraw() = 0;
virtual bool hasMoreResourceUpdates() const = 0;
virtual void scheduledActionBeginFrame() = 0;
- virtual void scheduledActionDrawAndSwap() = 0;
+ virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapIfPossible() = 0;
+ virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapForced() = 0;
virtual void scheduledActionUpdateMoreResources() = 0;
virtual void scheduledActionCommit() = 0;
virtual void scheduledActionBeginContextRecreation() = 0;
+ virtual void scheduledActionAcquireLayerTexturesForMainThread() = 0;
protected:
virtual ~CCSchedulerClient() { }
@@ -60,12 +77,20 @@ public:
virtual ~CCScheduler();
+ void setCanBeginFrame(bool);
+
void setVisible(bool);
void setNeedsCommit();
+
+ // Like setNeedsCommit(), but ensures a commit will definitely happen even if we are not visible.
+ void setNeedsForcedCommit();
+
void setNeedsRedraw();
- // As setNeedsRedraw(), but ensures the draw will definitely happen even if we are not visible.
+ void setMainThreadNeedsLayerTextures();
+
+ // Like setNeedsRedraw(), but ensures the draw will definitely happen even if we are not visible.
void setNeedsForcedRedraw();
void beginFrameComplete();
@@ -80,7 +105,7 @@ public:
bool redrawPending() const { return m_stateMachine.redrawPending(); }
// CCFrameRateControllerClient implementation
- virtual void beginFrame();
+ virtual void vsyncTick() OVERRIDE;
private:
CCScheduler(CCSchedulerClient*, PassOwnPtr<CCFrameRateController>);
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp
index 054a4edd7..da3779bfe 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp
@@ -35,10 +35,15 @@ CCSchedulerStateMachine::CCSchedulerStateMachine()
, m_needsRedraw(false)
, m_needsForcedRedraw(false)
, m_needsCommit(false)
+ , m_needsForcedCommit(false)
+ , m_mainThreadNeedsLayerTextures(false)
, m_updateMoreResourcesPending(false)
, m_insideVSync(false)
, m_visible(false)
+ , m_canBeginFrame(false)
, m_canDraw(true)
+ , m_drawIfPossibleFailed(false)
+ , m_textureState(LAYER_TEXTURE_STATE_UNLOCKED)
, m_contextState(CONTEXT_ACTIVE)
{
}
@@ -48,51 +53,86 @@ bool CCSchedulerStateMachine::hasDrawnThisFrame() const
return m_currentFrameNumber == m_lastFrameNumberWhereDrawWasCalled;
}
+bool CCSchedulerStateMachine::drawSuspendedUntilCommit() const
+{
+ if (!m_canDraw)
+ return true;
+ if (m_textureState == LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD)
+ return true;
+ return false;
+}
+
+bool CCSchedulerStateMachine::scheduledToDraw() const
+{
+ if (!m_needsRedraw)
+ return false;
+ if (!m_visible)
+ return false;
+ if (drawSuspendedUntilCommit())
+ return false;
+ return true;
+}
+
bool CCSchedulerStateMachine::shouldDraw() const
{
if (m_needsForcedRedraw)
return true;
- if (!m_needsRedraw)
+ if (!scheduledToDraw())
return false;
if (!m_insideVSync)
return false;
- if (!m_visible)
- return false;
if (hasDrawnThisFrame())
return false;
- if (!m_canDraw)
- return false;
if (m_contextState != CONTEXT_ACTIVE)
return false;
return true;
}
-CCSchedulerStateMachine::Action CCSchedulerStateMachine::nextAction() const
+bool CCSchedulerStateMachine::shouldAcquireLayerTexturesForMainThread() const
{
+ if (!m_mainThreadNeedsLayerTextures)
+ return false;
+ if (m_textureState == LAYER_TEXTURE_STATE_UNLOCKED)
+ return true;
+ ASSERT(m_textureState == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD);
+ // Transfer the lock from impl thread to main thread immediately if the
+ // impl thread is not even scheduled to draw. Guards against deadlocking.
+ if (!scheduledToDraw())
+ return true;
+ if (!vsyncCallbackNeeded())
+ return true;
+ return false;
+}
+CCSchedulerStateMachine::Action CCSchedulerStateMachine::nextAction() const
+{
+ if (shouldAcquireLayerTexturesForMainThread())
+ return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD;
switch (m_commitState) {
case COMMIT_STATE_IDLE:
if (m_contextState != CONTEXT_ACTIVE && m_needsForcedRedraw)
- return ACTION_DRAW;
+ return ACTION_DRAW_FORCED;
+ if (m_contextState != CONTEXT_ACTIVE && m_needsForcedCommit)
+ return ACTION_BEGIN_FRAME;
if (m_contextState == CONTEXT_LOST)
return ACTION_BEGIN_CONTEXT_RECREATION;
if (m_contextState == CONTEXT_RECREATING)
return ACTION_NONE;
if (shouldDraw())
- return ACTION_DRAW;
- if (m_needsCommit && m_visible)
+ return m_needsForcedRedraw ? ACTION_DRAW_FORCED : ACTION_DRAW_IF_POSSIBLE;
+ if (m_needsCommit && ((m_visible && m_canBeginFrame) || m_needsForcedCommit))
return ACTION_BEGIN_FRAME;
return ACTION_NONE;
case COMMIT_STATE_FRAME_IN_PROGRESS:
if (shouldDraw())
- return ACTION_DRAW;
+ return m_needsForcedRedraw ? ACTION_DRAW_FORCED : ACTION_DRAW_IF_POSSIBLE;
return ACTION_NONE;
case COMMIT_STATE_UPDATING_RESOURCES:
if (shouldDraw())
- return ACTION_DRAW;
+ return m_needsForcedRedraw ? ACTION_DRAW_FORCED : ACTION_DRAW_IF_POSSIBLE;
if (!m_updateMoreResourcesPending)
return ACTION_BEGIN_UPDATE_MORE_RESOURCES;
return ACTION_NONE;
@@ -102,10 +142,11 @@ CCSchedulerStateMachine::Action CCSchedulerStateMachine::nextAction() const
case COMMIT_STATE_WAITING_FOR_FIRST_DRAW:
if (shouldDraw() || m_contextState == CONTEXT_LOST)
- return ACTION_DRAW;
- // COMMIT_STATE_WAITING_FOR_FIRST_DRAW wants to enforce a draw. If m_canDraw is false,
- // proceed to the next step (similar as in COMMIT_STATE_IDLE).
- if (!m_canDraw && m_needsCommit && m_visible)
+ return m_needsForcedRedraw ? ACTION_DRAW_FORCED : ACTION_DRAW_IF_POSSIBLE;
+ // COMMIT_STATE_WAITING_FOR_FIRST_DRAW wants to enforce a draw. If m_canDraw is false
+ // or textures are not available, proceed to the next step (similar as in COMMIT_STATE_IDLE).
+ bool canCommit = m_visible || m_needsForcedCommit;
+ if (m_needsCommit && canCommit && drawSuspendedUntilCommit())
return ACTION_BEGIN_FRAME;
return ACTION_NONE;
}
@@ -120,9 +161,10 @@ void CCSchedulerStateMachine::updateState(Action action)
return;
case ACTION_BEGIN_FRAME:
- ASSERT(m_visible);
+ ASSERT(m_visible || m_needsForcedCommit);
m_commitState = COMMIT_STATE_FRAME_IN_PROGRESS;
m_needsCommit = false;
+ m_needsForcedCommit = false;
return;
case ACTION_BEGIN_UPDATE_MORE_RESOURCES:
@@ -131,22 +173,29 @@ void CCSchedulerStateMachine::updateState(Action action)
return;
case ACTION_COMMIT:
- if (m_needsCommit || !m_visible)
+ if ((m_needsCommit || !m_visible) && !m_needsForcedCommit)
m_commitState = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
else
m_commitState = COMMIT_STATE_IDLE;
m_needsRedraw = true;
+ if (m_drawIfPossibleFailed)
+ m_lastFrameNumberWhereDrawWasCalled = -1;
+ m_textureState = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD;
return;
- case ACTION_DRAW:
+ case ACTION_DRAW_FORCED:
+ case ACTION_DRAW_IF_POSSIBLE:
m_needsRedraw = false;
m_needsForcedRedraw = false;
+ m_drawIfPossibleFailed = false;
if (m_insideVSync)
m_lastFrameNumberWhereDrawWasCalled = m_currentFrameNumber;
if (m_commitState == COMMIT_STATE_WAITING_FOR_FIRST_DRAW) {
ASSERT(m_needsCommit || !m_visible);
m_commitState = COMMIT_STATE_IDLE;
}
+ if (m_textureState == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD)
+ m_textureState = LAYER_TEXTURE_STATE_UNLOCKED;
return;
case ACTION_BEGIN_CONTEXT_RECREATION:
@@ -154,19 +203,33 @@ void CCSchedulerStateMachine::updateState(Action action)
ASSERT(m_contextState == CONTEXT_LOST);
m_contextState = CONTEXT_RECREATING;
return;
+
+ case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
+ m_textureState = LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD;
+ m_mainThreadNeedsLayerTextures = false;
+ if (m_commitState != COMMIT_STATE_FRAME_IN_PROGRESS)
+ m_needsCommit = true;
+ return;
}
}
+void CCSchedulerStateMachine::setMainThreadNeedsLayerTextures()
+{
+ ASSERT(!m_mainThreadNeedsLayerTextures);
+ ASSERT(m_textureState != LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD);
+ m_mainThreadNeedsLayerTextures = true;
+}
+
bool CCSchedulerStateMachine::vsyncCallbackNeeded() const
{
if (!m_visible || m_contextState != CONTEXT_ACTIVE) {
- if (m_needsForcedRedraw)
+ if (m_needsForcedRedraw || m_commitState == COMMIT_STATE_UPDATING_RESOURCES)
return true;
return false;
}
- return m_needsRedraw || m_needsForcedRedraw || m_updateMoreResourcesPending;
+ return m_needsRedraw || m_needsForcedRedraw || m_commitState == COMMIT_STATE_UPDATING_RESOURCES;
}
void CCSchedulerStateMachine::didEnterVSync()
@@ -195,11 +258,25 @@ void CCSchedulerStateMachine::setNeedsForcedRedraw()
m_needsForcedRedraw = true;
}
+void CCSchedulerStateMachine::didDrawIfPossibleCompleted(bool success)
+{
+ m_drawIfPossibleFailed = !success;
+ if (m_drawIfPossibleFailed) {
+ m_needsRedraw = true;
+ m_needsCommit = true;
+ }
+}
+
void CCSchedulerStateMachine::setNeedsCommit()
{
m_needsCommit = true;
}
+void CCSchedulerStateMachine::setNeedsForcedCommit()
+{
+ m_needsForcedCommit = true;
+}
+
void CCSchedulerStateMachine::beginFrameComplete()
{
ASSERT(m_commitState == COMMIT_STATE_FRAME_IN_PROGRESS);
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h b/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h
index 22fcdf422..f3c2f630d 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h
@@ -51,11 +51,18 @@ public:
COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
};
+ enum TextureState {
+ LAYER_TEXTURE_STATE_UNLOCKED,
+ LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD,
+ LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD,
+ };
+
enum ContextState {
CONTEXT_ACTIVE,
CONTEXT_LOST,
CONTEXT_RECREATING,
};
+
bool commitPending() const
{
return m_commitState != COMMIT_STATE_IDLE;
@@ -68,8 +75,10 @@ public:
ACTION_BEGIN_FRAME,
ACTION_BEGIN_UPDATE_MORE_RESOURCES,
ACTION_COMMIT,
- ACTION_DRAW,
- ACTION_BEGIN_CONTEXT_RECREATION
+ ACTION_DRAW_IF_POSSIBLE,
+ ACTION_DRAW_FORCED,
+ ACTION_BEGIN_CONTEXT_RECREATION,
+ ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD,
};
Action nextAction() const;
void updateState(Action);
@@ -94,11 +103,18 @@ public:
// we are not visible.
void setNeedsForcedRedraw();
+ // Indicates whether ACTION_DRAW_IF_POSSIBLE drew to the screen or not.
+ void didDrawIfPossibleCompleted(bool success);
+
// Indicates that a new commit flow needs to be performed, either to pull
// updates from the main thread to the impl, or to push deltas from the impl
// thread to main.
void setNeedsCommit();
+ // As setNeedsCommit(), but ensures the beginFrame will definitely happen even if
+ // we are not visible.
+ void setNeedsForcedCommit();
+
// Call this only in response to receiving an ACTION_BEGIN_FRAME
// from nextState. Indicates that all painting is complete and that
// updating of compositor resources can begin.
@@ -108,6 +124,15 @@ public:
// from nextState. Indicates that the specific update request completed.
void beginUpdateMoreResourcesComplete(bool morePending);
+ // Request exclusive access to the textures that back single buffered
+ // layers on behalf of the main thread. Upon acqusition,
+ // ACTION_DRAW_IF_POSSIBLE will not draw until the main thread releases the
+ // textures to the impl thread by committing the layers.
+ void setMainThreadNeedsLayerTextures();
+
+ // Indicates whether we can successfully begin a frame at this time.
+ void setCanBeginFrame(bool can) { m_canBeginFrame = can; }
+
// Indicates whether drawing would, at this time, make sense.
// canDraw can be used to supress flashes or checkerboarding
// when such behavior would be undesirable.
@@ -117,7 +142,11 @@ public:
void didRecreateContext();
protected:
+ bool shouldDrawForced() const;
+ bool drawSuspendedUntilCommit() const;
+ bool scheduledToDraw() const;
bool shouldDraw() const;
+ bool shouldAcquireLayerTexturesForMainThread() const;
bool hasDrawnThisFrame() const;
CommitState m_commitState;
@@ -127,10 +156,15 @@ protected:
bool m_needsRedraw;
bool m_needsForcedRedraw;
bool m_needsCommit;
+ bool m_needsForcedCommit;
+ bool m_mainThreadNeedsLayerTextures;
bool m_updateMoreResourcesPending;
bool m_insideVSync;
bool m_visible;
+ bool m_canBeginFrame;
bool m_canDraw;
+ bool m_drawIfPossibleFailed;
+ TextureState m_textureState;
ContextState m_contextState;
};
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.cpp
index 872a35832..243ad231e 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.cpp
@@ -34,6 +34,7 @@
#include "ManagedTexture.h"
#include "PlatformCanvas.h"
#include "ScrollbarTheme.h"
+#include "cc/CCQuadCuller.h"
namespace WebCore {
@@ -51,12 +52,18 @@ CCScrollbarLayerImpl::CCScrollbarLayerImpl(int id)
void CCScrollbarLayerImpl::willDraw(LayerRendererChromium* layerRenderer)
{
+ CCLayerImpl::willDraw(layerRenderer);
+
if (bounds().isEmpty() || contentBounds().isEmpty())
return;
if (!m_texture)
m_texture = ManagedTexture::create(layerRenderer->renderSurfaceTextureManager());
+ // The context could have been lost since the last frame and the old texture
+ // manager may no longer be valid.
+ m_texture->setTextureManager(layerRenderer->renderSurfaceTextureManager());
+
IntSize textureSize = contentBounds();
if (!m_texture->reserve(textureSize, GraphicsContext3D::RGBA))
return;
@@ -78,7 +85,7 @@ void CCScrollbarLayerImpl::willDraw(LayerRendererChromium* layerRenderer)
}
}
-void CCScrollbarLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState)
+void CCScrollbarLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool&)
{
if (!m_texture->isReserved())
return;
@@ -89,6 +96,8 @@ void CCScrollbarLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadS
void CCScrollbarLayerImpl::didDraw()
{
+ CCLayerImpl::didDraw();
+
m_texture->unreserve();
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.h
index f6f005360..32ad1d8dd 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.h
@@ -59,16 +59,16 @@ public:
CCLayerImpl* scrollLayer() const { return m_scrollLayer; }
void setScrollLayer(CCLayerImpl* scrollLayer) { m_scrollLayer = scrollLayer; }
- virtual void willDraw(LayerRendererChromium*);
- virtual void appendQuads(CCQuadList&, const CCSharedQuadState*);
- virtual void didDraw();
+ virtual void willDraw(LayerRendererChromium*) OVERRIDE;
+ virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*, bool& hadMissingTiles) OVERRIDE;
+ virtual void didDraw() OVERRIDE;
protected:
explicit CCScrollbarLayerImpl(int id);
-private:
- void paint(GraphicsContext*);
+ virtual void paint(GraphicsContext*);
+private:
CCLayerImpl* m_scrollLayer;
OwnPtr<ManagedTexture> m_texture;
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSharedQuadState.h b/Source/WebCore/platform/graphics/chromium/cc/CCSharedQuadState.h
index e785757f9..4206aa5c2 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCSharedQuadState.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCSharedQuadState.h
@@ -43,6 +43,7 @@ public:
// The transform that layerRect() should be transformed with.
const TransformationMatrix& layerTransform() const { return m_layerTransform; }
const IntRect& layerRect() const { return m_layerRect; }
+ // Usage: if clipRect is empty, this clipRect should not be used.
const IntRect& clipRect() const { return m_clipRect; }
float opacity() const { return m_opacity; }
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp
index b6fc76b52..b39736dd0 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp
@@ -29,6 +29,7 @@
#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h"
#include "TraceEvent.h"
+#include "cc/CCFontAtlas.h"
#include "cc/CCLayerTreeHost.h"
#include "cc/CCTextureUpdater.h"
#include <wtf/CurrentTime.h>
@@ -72,10 +73,7 @@ bool CCSingleThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect
TRACE_EVENT("CCSingleThreadProxy::compositeAndReadback", this, 0);
ASSERT(CCProxy::isMainThread());
- if (!commitIfNeeded())
- return false;
-
- if (!doComposite())
+ if (!commitAndComposite())
return false;
m_layerTreeHostImpl->readback(pixels, rect);
@@ -129,6 +127,11 @@ bool CCSingleThreadProxy::initializeContext()
return true;
}
+void CCSingleThreadProxy::setSurfaceReady()
+{
+ // Scheduling is controlled by the embedder in the single thread case, so nothing to do.
+}
+
bool CCSingleThreadProxy::initializeLayerRenderer()
{
ASSERT(CCProxy::isMainThread());
@@ -191,7 +194,7 @@ void CCSingleThreadProxy::setNeedsAnimate()
ASSERT_NOT_REACHED();
}
-void CCSingleThreadProxy::doCommit()
+void CCSingleThreadProxy::doCommit(CCTextureUpdater& updater)
{
ASSERT(CCProxy::isMainThread());
// Commit immediately
@@ -200,9 +203,7 @@ void CCSingleThreadProxy::doCommit()
m_layerTreeHostImpl->beginCommit();
m_layerTreeHost->beginCommitOnImplThread(m_layerTreeHostImpl.get());
- CCTextureUpdater updater(m_layerTreeHostImpl->contentsTextureAllocator());
- m_layerTreeHost->updateCompositorResources(m_layerTreeHostImpl->context(), updater);
- updater.update(m_layerTreeHostImpl->context(), numeric_limits<size_t>::max());
+ updater.update(m_layerTreeHostImpl->context(), m_layerTreeHostImpl->contentsTextureAllocator(), m_layerTreeHostImpl->layerRenderer()->textureCopier(), m_layerTreeHostImpl->layerRenderer()->textureUploader(), numeric_limits<size_t>::max());
ASSERT(!updater.hasMoreUpdates());
m_layerTreeHostImpl->setVisible(m_layerTreeHost->visible());
m_layerTreeHost->finishCommitOnImplThread(m_layerTreeHostImpl.get());
@@ -234,6 +235,11 @@ void CCSingleThreadProxy::setNeedsRedraw()
setNeedsCommit();
}
+bool CCSingleThreadProxy::commitRequested() const
+{
+ return false;
+}
+
void CCSingleThreadProxy::setVisible(bool visible)
{
m_layerTreeHostImpl->setVisible(visible);
@@ -259,6 +265,13 @@ void CCSingleThreadProxy::stop()
m_layerTreeHost = 0;
}
+void CCSingleThreadProxy::setFontAtlas(PassOwnPtr<CCFontAtlas> fontAtlas)
+{
+ ASSERT(isMainThread());
+ DebugScopedSetImplThread impl;
+ m_layerTreeHostImpl->setFontAtlas(fontAtlas);
+}
+
void CCSingleThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime)
{
ASSERT(CCProxy::isImplThread());
@@ -266,27 +279,43 @@ void CCSingleThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr
m_layerTreeHost->setAnimationEvents(events, wallClockTime);
}
+void CCSingleThreadProxy::postSetContentsMemoryAllocationLimitBytesToMainThreadOnImplThread(size_t bytes)
+{
+ // FIXME: This is called via a graphics context callback, on main thread in single threaded mode, because its hard to fake the impl thread. This should need to DebugScopedSetMainThread, but is actually already on the main thread.
+ ASSERT(CCProxy::isMainThread());
+ ASSERT(m_layerTreeHost);
+ m_layerTreeHost->setContentsMemoryAllocationLimitBytes(bytes);
+}
+
// Called by the legacy scheduling path (e.g. where render_widget does the scheduling)
void CCSingleThreadProxy::compositeImmediately()
{
- if (!commitIfNeeded())
- return;
-
- if (doComposite()) {
+ if (commitAndComposite()) {
m_layerTreeHostImpl->swapBuffers();
didSwapFrame();
}
}
-bool CCSingleThreadProxy::commitIfNeeded()
+void CCSingleThreadProxy::forceSerializeOnSwapBuffers()
+{
+ {
+ DebugScopedSetImplThread impl;
+ if (m_layerRendererInitialized)
+ m_layerTreeHostImpl->layerRenderer()->doNoOp();
+ }
+}
+
+bool CCSingleThreadProxy::commitAndComposite()
{
ASSERT(CCProxy::isMainThread());
- if (!m_layerTreeHost->updateLayers())
+ CCTextureUpdater updater;
+
+ if (!m_layerTreeHost->updateLayers(updater))
return false;
- doCommit();
- return true;
+ doCommit(updater);
+ return doComposite();
}
bool CCSingleThreadProxy::doComposite()
@@ -298,7 +327,10 @@ bool CCSingleThreadProxy::doComposite()
double wallClockTime = currentTime();
m_layerTreeHostImpl->animate(monotonicTime, wallClockTime);
- m_layerTreeHostImpl->drawLayers();
+ CCLayerTreeHostImpl::FrameData frame;
+ m_layerTreeHostImpl->prepareToDraw(frame);
+ m_layerTreeHostImpl->drawLayers(frame);
+ m_layerTreeHostImpl->didDrawAllLayers(frame);
}
if (m_layerTreeHostImpl->isContextLost()) {
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h
index ebbd96e2c..156bddca1 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h
@@ -42,31 +42,37 @@ public:
virtual ~CCSingleThreadProxy();
// CCProxy implementation
- virtual bool compositeAndReadback(void *pixels, const IntRect&);
- virtual void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration);
- virtual GraphicsContext3D* context();
- virtual void finishAllRendering();
- virtual bool isStarted() const;
- virtual bool initializeContext();
- virtual bool initializeLayerRenderer();
- virtual bool recreateContext();
- virtual int compositorIdentifier() const { return m_compositorIdentifier; }
- virtual const LayerRendererCapabilities& layerRendererCapabilities() const;
- virtual void loseContext();
- virtual void setNeedsAnimate();
- virtual void setNeedsCommit();
- virtual void setNeedsRedraw();
- virtual void setVisible(bool);
- virtual void start();
- virtual void stop();
- virtual size_t maxPartialTextureUpdates() const { return std::numeric_limits<size_t>::max(); }
+ virtual bool compositeAndReadback(void *pixels, const IntRect&) OVERRIDE;
+ virtual void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration) OVERRIDE;
+ virtual GraphicsContext3D* context() OVERRIDE;
+ virtual void finishAllRendering() OVERRIDE;
+ virtual bool isStarted() const OVERRIDE;
+ virtual bool initializeContext() OVERRIDE;
+ virtual void setSurfaceReady() OVERRIDE;
+ virtual bool initializeLayerRenderer() OVERRIDE;
+ virtual bool recreateContext() OVERRIDE;
+ virtual int compositorIdentifier() const OVERRIDE { return m_compositorIdentifier; }
+ virtual const LayerRendererCapabilities& layerRendererCapabilities() const OVERRIDE;
+ virtual void loseContext() OVERRIDE;
+ virtual void setNeedsAnimate() OVERRIDE;
+ virtual void setNeedsCommit() OVERRIDE;
+ virtual void setNeedsRedraw() OVERRIDE;
+ virtual bool commitRequested() const OVERRIDE;
+ virtual void setVisible(bool) OVERRIDE;
+ virtual void start() OVERRIDE;
+ virtual void stop() OVERRIDE;
+ virtual size_t maxPartialTextureUpdates() const OVERRIDE { return std::numeric_limits<size_t>::max(); }
+ virtual void acquireLayerTextures() OVERRIDE { }
+ virtual void setFontAtlas(PassOwnPtr<CCFontAtlas>) OVERRIDE;
+ virtual void forceSerializeOnSwapBuffers() OVERRIDE;
// CCLayerTreeHostImplClient implementation
- virtual void didLoseContextOnImplThread() { }
- virtual void onSwapBuffersCompleteOnImplThread() { ASSERT_NOT_REACHED(); }
- virtual void setNeedsRedrawOnImplThread() { m_layerTreeHost->setNeedsCommit(); }
- virtual void setNeedsCommitOnImplThread() { m_layerTreeHost->setNeedsCommit(); }
- virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime);
+ virtual void didLoseContextOnImplThread() OVERRIDE { }
+ virtual void onSwapBuffersCompleteOnImplThread() OVERRIDE { ASSERT_NOT_REACHED(); }
+ virtual void setNeedsRedrawOnImplThread() OVERRIDE { m_layerTreeHost->setNeedsCommit(); }
+ virtual void setNeedsCommitOnImplThread() OVERRIDE { m_layerTreeHost->setNeedsCommit(); }
+ virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime) OVERRIDE;
+ virtual void postSetContentsMemoryAllocationLimitBytesToMainThreadOnImplThread(size_t) OVERRIDE;
// Called by the legacy path where RenderWidget does the scheduling.
void compositeImmediately();
@@ -74,8 +80,8 @@ public:
private:
explicit CCSingleThreadProxy(CCLayerTreeHost*);
- bool commitIfNeeded();
- void doCommit();
+ bool commitAndComposite();
+ void doCommit(CCTextureUpdater&);
bool doComposite();
void didSwapFrame();
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.cpp
index 864aff30a..6ae3a1729 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.cpp
@@ -30,6 +30,7 @@
#include "cc/CCSolidColorLayerImpl.h"
#include "LayerRendererChromium.h"
+#include "cc/CCQuadCuller.h"
#include "cc/CCSolidColorDrawQuad.h"
#include <wtf/MathExtras.h>
#include <wtf/text/WTFString.h>
@@ -56,7 +57,7 @@ TransformationMatrix CCSolidColorLayerImpl::quadTransform() const
return solidColorTransform;
}
-void CCSolidColorLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState)
+void CCSolidColorLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool&)
{
// We create a series of smaller quads instead of just one large one so that the
// culler can reduce the total pixels drawn.
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.h
index 2e7441666..d8fce3761 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.h
@@ -41,14 +41,14 @@ public:
}
virtual ~CCSolidColorLayerImpl();
- virtual TransformationMatrix quadTransform() const;
- virtual void appendQuads(CCQuadList&, const CCSharedQuadState*);
+ virtual TransformationMatrix quadTransform() const OVERRIDE;
+ virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*, bool& hadMissingTiles) OVERRIDE;
protected:
explicit CCSolidColorLayerImpl(int id);
private:
- virtual const char* layerTypeAsString() const { return "SolidColorLayer"; }
+ virtual const char* layerTypeAsString() const OVERRIDE { return "SolidColorLayer"; }
const int m_tileSize;
};
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasDrawQuad.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCTextureDrawQuad.cpp
index 56f5083a5..859e9d9d3 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasDrawQuad.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCTextureDrawQuad.cpp
@@ -25,20 +25,21 @@
#include "config.h"
-#include "cc/CCCanvasDrawQuad.h"
+#include "cc/CCTextureDrawQuad.h"
namespace WebCore {
-PassOwnPtr<CCCanvasDrawQuad> CCCanvasDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, unsigned textureId, bool hasAlpha, bool premultipliedAlpha)
+PassOwnPtr<CCTextureDrawQuad> CCTextureDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, unsigned textureId, bool premultipliedAlpha, const FloatRect& uvRect, bool flipped)
{
- return adoptPtr(new CCCanvasDrawQuad(sharedQuadState, quadRect, textureId, hasAlpha, premultipliedAlpha));
+ return adoptPtr(new CCTextureDrawQuad(sharedQuadState, quadRect, textureId, premultipliedAlpha, uvRect, flipped));
}
-CCCanvasDrawQuad::CCCanvasDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, unsigned textureId, bool hasAlpha, bool premultipliedAlpha)
- : CCDrawQuad(sharedQuadState, CCDrawQuad::CanvasContent, quadRect)
+CCTextureDrawQuad::CCTextureDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, unsigned textureId, bool premultipliedAlpha, const FloatRect& uvRect, bool flipped)
+ : CCDrawQuad(sharedQuadState, CCDrawQuad::TextureContent, quadRect)
, m_textureId(textureId)
- , m_hasAlpha(hasAlpha)
, m_premultipliedAlpha(premultipliedAlpha)
+ , m_uvRect(uvRect)
+ , m_flipped(flipped)
{
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasDrawQuad.h b/Source/WebCore/platform/graphics/chromium/cc/CCTextureDrawQuad.h
index aa85dbd13..591001bc8 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasDrawQuad.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCTextureDrawQuad.h
@@ -23,30 +23,31 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef CCCanvasDrawQuad_h
-#define CCCanvasDrawQuad_h
+#ifndef CCTextureDrawQuad_h
+#define CCTextureDrawQuad_h
#include "cc/CCDrawQuad.h"
#include <wtf/PassOwnPtr.h>
namespace WebCore {
-class CCLayerImpl;
-class CCCanvasDrawQuad : public CCDrawQuad {
- WTF_MAKE_NONCOPYABLE(CCCanvasDrawQuad);
+class CCTextureDrawQuad : public CCDrawQuad {
+ WTF_MAKE_NONCOPYABLE(CCTextureDrawQuad);
public:
- static PassOwnPtr<CCCanvasDrawQuad> create(const CCSharedQuadState*, const IntRect&, unsigned texture_id, bool hasAlpha, bool premultipliedAlpha);
+ static PassOwnPtr<CCTextureDrawQuad> create(const CCSharedQuadState*, const IntRect&, unsigned textureId, bool premultipliedAlpha, const FloatRect& uvRect, bool flipped);
unsigned textureId() const { return m_textureId; }
- bool hasAlpha() const { return m_hasAlpha; }
bool premultipliedAlpha() const { return m_premultipliedAlpha; }
+ FloatRect uvRect() const { return m_uvRect; }
+ bool flipped() const { return m_flipped; }
private:
- CCCanvasDrawQuad(const CCSharedQuadState*, const IntRect&, unsigned texture_id, bool hasAlpha, bool premultipliedAlpha);
+ CCTextureDrawQuad(const CCSharedQuadState*, const IntRect&, unsigned texture_id, bool premultipliedAlpha, const FloatRect& uvRect, bool flipped);
unsigned m_textureId;
- bool m_hasAlpha;
bool m_premultipliedAlpha;
+ FloatRect m_uvRect;
+ bool m_flipped;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCTextureLayerImpl.cpp
index 2bb3eff22..44d9ff395 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCTextureLayerImpl.cpp
@@ -27,41 +27,49 @@
#if USE(ACCELERATED_COMPOSITING)
-#include "cc/CCCanvasLayerImpl.h"
+#include "cc/CCTextureLayerImpl.h"
+#include "Extensions3DChromium.h"
#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h"
-#include "cc/CCCanvasDrawQuad.h"
+#include "cc/CCIOSurfaceDrawQuad.h"
#include "cc/CCProxy.h"
-#include <wtf/text/WTFString.h>
+#include "cc/CCQuadCuller.h"
+#include "cc/CCTextureDrawQuad.h"
namespace WebCore {
-CCCanvasLayerImpl::CCCanvasLayerImpl(int id)
+CCTextureLayerImpl::CCTextureLayerImpl(int id)
: CCLayerImpl(id)
, m_textureId(0)
- , m_hasAlpha(true)
, m_premultipliedAlpha(true)
+ , m_flipped(true)
+ , m_uvRect(0, 0, 1, 1)
{
}
-CCCanvasLayerImpl::~CCCanvasLayerImpl()
+CCTextureLayerImpl::~CCTextureLayerImpl()
{
}
-void CCCanvasLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState)
+void CCTextureLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool&)
{
IntRect quadRect(IntPoint(), bounds());
- quadList.append(CCCanvasDrawQuad::create(sharedQuadState, quadRect, m_textureId, m_hasAlpha, m_premultipliedAlpha));
+ quadList.append(CCTextureDrawQuad::create(sharedQuadState, quadRect, m_textureId, m_premultipliedAlpha, m_uvRect, m_flipped));
}
-void CCCanvasLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
+void CCTextureLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
{
writeIndent(ts, indent);
- ts << "canvas layer texture id: " << m_textureId << " premultiplied: " << m_premultipliedAlpha << "\n";
+ ts << "texture layer texture id: " << m_textureId << " premultiplied: " << m_premultipliedAlpha << "\n";
CCLayerImpl::dumpLayerProperties(ts, indent);
}
+void CCTextureLayerImpl::didLoseContext()
+{
+ m_textureId = 0;
+}
+
}
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCTextureLayerImpl.h
index c96af246e..4abdb51ff 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCTextureLayerImpl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,43 +23,44 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef CCCanvasLayerImpl_h
-#define CCCanvasLayerImpl_h
+#ifndef CCTextureLayerImpl_h
+#define CCTextureLayerImpl_h
-#include "ProgramBinding.h"
-#include "ShaderChromium.h"
#include "cc/CCLayerImpl.h"
namespace WebCore {
-class CCCanvasLayerImpl : public CCLayerImpl {
+class CCTextureLayerImpl : public CCLayerImpl {
public:
- static PassOwnPtr<CCCanvasLayerImpl> create(int id)
+ static PassOwnPtr<CCTextureLayerImpl> create(int id)
{
- return adoptPtr(new CCCanvasLayerImpl(id));
+ return adoptPtr(new CCTextureLayerImpl(id));
}
- virtual ~CCCanvasLayerImpl();
+ virtual ~CCTextureLayerImpl();
- virtual void appendQuads(CCQuadList&, const CCSharedQuadState*);
+ virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*, bool& hadMissingTiles) OVERRIDE;
- typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program;
+ virtual void didLoseContext() OVERRIDE;
- virtual void dumpLayerProperties(TextStream&, int indent) const;
+ virtual void dumpLayerProperties(TextStream&, int indent) const OVERRIDE;
unsigned textureId() const { return m_textureId; }
void setTextureId(unsigned id) { m_textureId = id; }
- void setHasAlpha(bool hasAlpha) { m_hasAlpha = hasAlpha; }
void setPremultipliedAlpha(bool premultipliedAlpha) { m_premultipliedAlpha = premultipliedAlpha; }
+ void setFlipped(bool flipped) { m_flipped = flipped; }
+ void setUVRect(const FloatRect& rect) { m_uvRect = rect; }
+
private:
- explicit CCCanvasLayerImpl(int);
+ explicit CCTextureLayerImpl(int);
- virtual const char* layerTypeAsString() const { return "CanvasLayer"; }
+ virtual const char* layerTypeAsString() const OVERRIDE { return "TextureLayer"; }
unsigned m_textureId;
- bool m_hasAlpha;
bool m_premultipliedAlpha;
+ bool m_flipped;
+ FloatRect m_uvRect;
};
}
-#endif // CCCanvasLayerImpl_h
+#endif // CCTextureLayerImpl_h
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.cpp
index 66e08c8bd..e1743a8c9 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.cpp
@@ -32,55 +32,73 @@
#include "GraphicsContext3D.h"
#include "LayerTextureUpdater.h"
#include "ManagedTexture.h"
+#include "TextureCopier.h"
+#include "TextureUploader.h"
using namespace std;
namespace WebCore {
-CCTextureUpdater::CCTextureUpdater(TextureAllocator* allocator)
- : m_allocator(allocator)
- , m_entryIndex(0)
+CCTextureUpdater::CCTextureUpdater()
+ : m_entryIndex(0)
{
- ASSERT(m_allocator);
}
CCTextureUpdater::~CCTextureUpdater()
{
}
-void CCTextureUpdater::append(LayerTextureUpdater::Texture* texture, const IntRect& sourceRect, const IntRect& destRect, Vector<UpdateEntry>& entries)
+void CCTextureUpdater::appendUpdate(LayerTextureUpdater::Texture* texture, const IntRect& sourceRect, const IntRect& destRect, Vector<UpdateEntry>& entries)
{
ASSERT(texture);
UpdateEntry entry;
- entry.m_texture = texture;
- entry.m_sourceRect = sourceRect;
- entry.m_destRect = destRect;
+ entry.texture = texture;
+ entry.sourceRect = sourceRect;
+ entry.destRect = destRect;
entries.append(entry);
}
-void CCTextureUpdater::append(LayerTextureUpdater::Texture* texture, const IntRect& sourceRect, const IntRect& destRect)
+void CCTextureUpdater::appendUpdate(LayerTextureUpdater::Texture* texture, const IntRect& sourceRect, const IntRect& destRect)
{
- append(texture, sourceRect, destRect, m_entries);
+ appendUpdate(texture, sourceRect, destRect, m_entries);
}
-void CCTextureUpdater::appendPartial(LayerTextureUpdater::Texture* texture, const IntRect& sourceRect, const IntRect& destRect)
+void CCTextureUpdater::appendPartialUpdate(LayerTextureUpdater::Texture* texture, const IntRect& sourceRect, const IntRect& destRect)
{
- append(texture, sourceRect, destRect, m_partialEntries);
+ appendUpdate(texture, sourceRect, destRect, m_partialEntries);
+}
+
+void CCTextureUpdater::appendCopy(unsigned sourceTexture, unsigned destTexture, const IntSize& size)
+{
+ CopyEntry copy;
+ copy.sourceTexture = sourceTexture;
+ copy.destTexture = destTexture;
+ copy.size = size;
+ m_copyEntries.append(copy);
+}
+
+void CCTextureUpdater::appendManagedCopy(unsigned sourceTexture, ManagedTexture* destTexture, const IntSize& size)
+{
+ ManagedCopyEntry copy;
+ copy.sourceTexture = sourceTexture;
+ copy.destTexture = destTexture;
+ copy.size = size;
+ m_managedCopyEntries.append(copy);
}
bool CCTextureUpdater::hasMoreUpdates() const
{
- return m_entries.size() || m_partialEntries.size();
+ return m_entries.size() || m_partialEntries.size() || m_copyEntries.size() || m_managedCopyEntries.size();
}
-bool CCTextureUpdater::update(GraphicsContext3D* context, size_t count)
+bool CCTextureUpdater::update(GraphicsContext3D* context, TextureAllocator* allocator, TextureCopier* copier, TextureUploader* uploader, size_t count)
{
size_t index;
size_t maxIndex = min(m_entryIndex + count, m_entries.size());
for (index = m_entryIndex; index < maxIndex; ++index) {
UpdateEntry& entry = m_entries[index];
- entry.m_texture->updateRect(context, m_allocator, entry.m_sourceRect, entry.m_destRect);
+ uploader->uploadTexture(context, entry.texture, allocator, entry.sourceRect, entry.destRect);
}
bool moreUpdates = maxIndex < m_entries.size();
@@ -98,8 +116,23 @@ bool CCTextureUpdater::update(GraphicsContext3D* context, size_t count)
for (index = 0; index < m_partialEntries.size(); ++index) {
UpdateEntry& entry = m_partialEntries[index];
- entry.m_texture->updateRect(context, m_allocator, entry.m_sourceRect, entry.m_destRect);
+ uploader->uploadTexture(context, entry.texture, allocator, entry.sourceRect, entry.destRect);
+ }
+
+ for (index = 0; index < m_copyEntries.size(); ++index) {
+ CopyEntry& copyEntry = m_copyEntries[index];
+ copier->copyTexture(context, copyEntry.sourceTexture, copyEntry.destTexture, copyEntry.size);
+ }
+ for (index = 0; index < m_managedCopyEntries.size(); ++index) {
+ ManagedCopyEntry& managedCopyEntry = m_managedCopyEntries[index];
+ managedCopyEntry.destTexture->allocate(allocator);
+ copier->copyTexture(context, managedCopyEntry.sourceTexture, managedCopyEntry.destTexture->textureId(), managedCopyEntry.size);
}
+ // If we've performed any texture copies, we need to insert a flush here into the compositor context
+ // before letting the main thread proceed as it may make draw calls to the source texture of one of
+ // our copy operations.
+ if (m_copyEntries.size() || m_managedCopyEntries.size())
+ context->flush();
// If no entries left to process, auto-clear.
clear();
@@ -111,6 +144,8 @@ void CCTextureUpdater::clear()
m_entryIndex = 0;
m_entries.clear();
m_partialEntries.clear();
+ m_copyEntries.clear();
+ m_managedCopyEntries.clear();
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.h
index dbb52c9ba..01508bfa2 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.h
@@ -34,37 +34,52 @@ namespace WebCore {
class GraphicsContext3D;
class TextureAllocator;
+class TextureCopier;
+class TextureUploader;
class CCTextureUpdater {
public:
- CCTextureUpdater(TextureAllocator*);
+ CCTextureUpdater();
~CCTextureUpdater();
- void append(LayerTextureUpdater::Texture*, const IntRect& sourceRect, const IntRect& destRect);
- void appendPartial(LayerTextureUpdater::Texture*, const IntRect& sourceRect, const IntRect& destRect);
+ void appendUpdate(LayerTextureUpdater::Texture*, const IntRect& sourceRect, const IntRect& destRect);
+ void appendPartialUpdate(LayerTextureUpdater::Texture*, const IntRect& sourceRect, const IntRect& destRect);
+ void appendCopy(unsigned sourceTexture, unsigned destTexture, const IntSize&);
+ void appendManagedCopy(unsigned sourceTexture, ManagedTexture* destTexture, const IntSize&);
bool hasMoreUpdates() const;
// Update some textures. Returns true if more textures left to process.
- bool update(GraphicsContext3D*, size_t count);
+ bool update(GraphicsContext3D*, TextureAllocator*, TextureCopier*, TextureUploader*, size_t count);
void clear();
- TextureAllocator* allocator() { return m_allocator; }
-
private:
struct UpdateEntry {
- LayerTextureUpdater::Texture* m_texture;
- IntRect m_sourceRect;
- IntRect m_destRect;
+ LayerTextureUpdater::Texture* texture;
+ IntRect sourceRect;
+ IntRect destRect;
+ };
+
+ struct CopyEntry {
+ IntSize size;
+ unsigned sourceTexture;
+ unsigned destTexture;
+ };
+
+ struct ManagedCopyEntry {
+ IntSize size;
+ unsigned sourceTexture;
+ ManagedTexture* destTexture;
};
- static void append(LayerTextureUpdater::Texture*, const IntRect& sourceRect, const IntRect& destRect, Vector<UpdateEntry>&);
+ static void appendUpdate(LayerTextureUpdater::Texture*, const IntRect& sourceRect, const IntRect& destRect, Vector<UpdateEntry>&);
- TextureAllocator* m_allocator;
size_t m_entryIndex;
Vector<UpdateEntry> m_entries;
Vector<UpdateEntry> m_partialEntries;
+ Vector<CopyEntry> m_copyEntries;
+ Vector<ManagedCopyEntry> m_managedCopyEntries;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp
index 8454e21ff..eaf2f89a9 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp
@@ -27,8 +27,11 @@
#include "cc/CCThreadProxy.h"
#include "GraphicsContext3D.h"
+#include "LayerRendererChromium.h"
+#include "SharedGraphicsContext3D.h"
#include "TraceEvent.h"
#include "cc/CCDelayBasedTimeSource.h"
+#include "cc/CCFontAtlas.h"
#include "cc/CCFrameRateController.h"
#include "cc/CCInputHandler.h"
#include "cc/CCLayerTreeHost.h"
@@ -45,7 +48,10 @@ namespace {
// Number of textures to update with each call to
// scheduledActionUpdateMoreResources().
-static const size_t textureUpdatesPerFrame = 5;
+static const size_t textureUpdatesPerFrame = 48;
+
+// Measured in seconds.
+static const double contextRecreationTickRate = 0.03;
} // anonymous namespace
@@ -64,12 +70,13 @@ CCThreadProxy::CCThreadProxy(CCLayerTreeHost* layerTreeHost)
, m_compositorIdentifier(-1)
, m_layerRendererInitialized(false)
, m_started(false)
- , m_lastExecutedBeginFrameAndCommitSequenceNumber(-1)
- , m_numBeginFrameAndCommitsIssuedOnImplThread(0)
+ , m_texturesAcquired(true)
, m_mainThreadProxy(CCScopedThreadProxy::create(CCProxy::mainThread()))
+ , m_beginFrameCompletionEventOnImplThread(0)
, m_readbackRequestOnImplThread(0)
, m_finishAllRenderingCompletionEventOnImplThread(0)
, m_commitCompletionEventOnImplThread(0)
+ , m_textureAcquisitionCompletionEventOnImplThread(0)
, m_nextFrameIsNewlyCommittedFrameOnImplThread(false)
{
TRACE_EVENT("CCThreadProxy::CCThreadProxy", this, 0);
@@ -94,25 +101,14 @@ bool CCThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect)
return false;
}
- // If a commit is pending, perform the commit first.
- if (m_commitRequested) {
- // This bit of code is uglier than it should be because returning
- // pointers via the CCThread task model is really messy. Effectively, we
- // are making a blocking call to createBeginFrameAndCommitTaskOnImplThread,
- // and trying to get the CCMainThread::Task it returns so we can run it.
- OwnPtr<CCThread::Task> beginFrameAndCommitTask;
- {
- CCThread::Task* taskPtr = 0;
- CCCompletionEvent completion;
- CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::obtainBeginFrameAndCommitTaskFromCCThread, AllowCrossThreadAccess(&completion), AllowCrossThreadAccess(&taskPtr)));
- completion.wait();
- beginFrameAndCommitTask = adoptPtr(taskPtr);
- }
-
- beginFrameAndCommitTask->performTask();
- }
- // Draw using the new tree and read back the results.
+ // Perform a synchronous commit.
+ CCCompletionEvent beginFrameCompletion;
+ CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::forceBeginFrameOnImplThread, AllowCrossThreadAccess(&beginFrameCompletion)));
+ beginFrameCompletion.wait();
+ beginFrame();
+
+ // Perform a synchronous readback.
ReadbackRequest request;
request.rect = rect;
request.pixels = pixels;
@@ -130,7 +126,9 @@ void CCThreadProxy::requestReadbackOnImplThread(ReadbackRequest* request)
request->completion.signal();
return;
}
+
m_readbackRequestOnImplThread = request;
+ m_schedulerOnImplThread->setNeedsRedraw();
m_schedulerOnImplThread->setNeedsForcedRedraw();
}
@@ -185,6 +183,18 @@ bool CCThreadProxy::initializeContext()
return true;
}
+void CCThreadProxy::setSurfaceReady()
+{
+ TRACE_EVENT0("cc", "CCThreadProxy::setSurfaceReady");
+ CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setSurfaceReadyOnImplThread));
+}
+
+void CCThreadProxy::setSurfaceReadyOnImplThread()
+{
+ TRACE_EVENT0("cc", "CCThreadProxy::setSurfaceReadyOnImplThread");
+ m_schedulerOnImplThread->setCanBeginFrame(true);
+}
+
bool CCThreadProxy::initializeLayerRenderer()
{
TRACE_EVENT("CCThreadProxy::initializeLayerRenderer", this, 0);
@@ -215,6 +225,10 @@ bool CCThreadProxy::recreateContext()
RefPtr<GraphicsContext3D> context = m_layerTreeHost->createContext();
if (!context)
return false;
+ if (CCLayerTreeHost::needsFilterContext())
+ if (!SharedGraphicsContext3D::createForImplThread())
+ return false;
+
ASSERT(context->hasOneRef());
// Leak the context pointer so we can transfer ownership of it to the other side...
@@ -307,6 +321,12 @@ void CCThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAni
m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::setAnimationEvents, events, wallClockTime));
}
+void CCThreadProxy::postSetContentsMemoryAllocationLimitBytesToMainThreadOnImplThread(size_t bytes)
+{
+ ASSERT(isImplThread());
+ m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::setContentsMemoryAllocationLimitBytes, bytes));
+}
+
void CCThreadProxy::setNeedsRedraw()
{
ASSERT(isMainThread());
@@ -315,6 +335,12 @@ void CCThreadProxy::setNeedsRedraw()
CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsRedrawOnImplThread));
}
+bool CCThreadProxy::commitRequested() const
+{
+ ASSERT(isMainThread());
+ return m_commitRequested;
+}
+
void CCThreadProxy::setVisible(bool visible)
{
ASSERT(isMainThread());
@@ -375,6 +401,21 @@ void CCThreadProxy::stop()
m_started = false;
}
+void CCThreadProxy::forceSerializeOnSwapBuffers()
+{
+ CCCompletionEvent completion;
+ CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::forceSerializeOnSwapBuffersOnImplThread, AllowCrossThreadAccess(&completion)));
+ completion.wait();
+}
+
+void CCThreadProxy::forceSerializeOnSwapBuffersOnImplThread(CCCompletionEvent* completion)
+{
+ if (m_layerRendererInitialized)
+ m_layerTreeHostImpl->layerRenderer()->doNoOp();
+ completion->signal();
+}
+
+
void CCThreadProxy::finishAllRenderingOnImplThread(CCCompletionEvent* completion)
{
TRACE_EVENT("CCThreadProxy::finishAllRenderingOnImplThread", this, 0);
@@ -385,54 +426,55 @@ void CCThreadProxy::finishAllRenderingOnImplThread(CCCompletionEvent* completion
m_schedulerOnImplThread->setNeedsForcedRedraw();
}
-void CCThreadProxy::scheduledActionBeginFrame()
+void CCThreadProxy::forceBeginFrameOnImplThread(CCCompletionEvent* completion)
{
- TRACE_EVENT("CCThreadProxy::scheduledActionBeginFrame", this, 0);
- m_mainThreadProxy->postTask(createBeginFrameAndCommitTaskOnImplThread());
+ TRACE_EVENT0("cc", "CCThreadProxy::forceBeginFrameOnImplThread");
+ ASSERT(!m_beginFrameCompletionEventOnImplThread);
+
+ if (m_schedulerOnImplThread->commitPending()) {
+ completion->signal();
+ return;
+ }
+
+ m_beginFrameCompletionEventOnImplThread = completion;
+ m_schedulerOnImplThread->setNeedsCommit();
+ m_schedulerOnImplThread->setNeedsForcedCommit();
}
-void CCThreadProxy::obtainBeginFrameAndCommitTaskFromCCThread(CCCompletionEvent* completion, CCThread::Task** taskPtr)
+void CCThreadProxy::scheduledActionBeginFrame()
{
- OwnPtr<CCThread::Task> task = createBeginFrameAndCommitTaskOnImplThread();
- *taskPtr = task.leakPtr();
- completion->signal();
+ TRACE_EVENT0("cc", "CCThreadProxy::scheduledActionBeginFrame");
+ ASSERT(!m_pendingBeginFrameRequest);
+ m_pendingBeginFrameRequest = adoptPtr(new BeginFrameAndCommitState());
+ m_pendingBeginFrameRequest->monotonicFrameBeginTime = monotonicallyIncreasingTime();
+ m_pendingBeginFrameRequest->scrollInfo = m_layerTreeHostImpl->processScrollDeltas();
+ m_currentTextureUpdaterOnImplThread = adoptPtr(new CCTextureUpdater);
+ m_pendingBeginFrameRequest->updater = m_currentTextureUpdaterOnImplThread.get();
+
+ m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::beginFrame));
+
+ if (m_beginFrameCompletionEventOnImplThread) {
+ m_beginFrameCompletionEventOnImplThread->signal();
+ m_beginFrameCompletionEventOnImplThread = 0;
+ }
}
-PassOwnPtr<CCThread::Task> CCThreadProxy::createBeginFrameAndCommitTaskOnImplThread()
+void CCThreadProxy::beginFrame()
{
- TRACE_EVENT("CCThreadProxy::createBeginFrameAndCommitTaskOnImplThread", this, 0);
- ASSERT(isImplThread());
- double frameBeginTime = currentTime();
-
- // NOTE, it is possible to receieve a request for a
- // beginFrameAndCommitOnImplThread from finishAllRendering while a
- // beginFrameAndCommitOnImplThread is enqueued. Since CCThread doesn't
- // provide a threadsafe way to cancel tasks, it is important that
- // beginFrameAndCommit be structured to understand that it may get called at
- // a point that it shouldn't. We do this by assigning a sequence number to
- // every new beginFrameAndCommit task. Then, beginFrameAndCommit tracks the
- // last executed sequence number, dropping beginFrameAndCommit with sequence
- // numbers below the last executed one.
- int thisTaskSequenceNumber = m_numBeginFrameAndCommitsIssuedOnImplThread;
- m_numBeginFrameAndCommitsIssuedOnImplThread++;
- OwnPtr<CCScrollAndScaleSet> scrollInfo = m_layerTreeHostImpl->processScrollDeltas();
- return createCCThreadTask(this, &CCThreadProxy::beginFrameAndCommit, thisTaskSequenceNumber, frameBeginTime, scrollInfo.release());
-}
-
-void CCThreadProxy::beginFrameAndCommit(int sequenceNumber, double frameBeginTime, PassOwnPtr<CCScrollAndScaleSet> scrollInfo)
-{
- TRACE_EVENT("CCThreadProxy::beginFrameAndCommit", this, 0);
+ TRACE_EVENT0("cc", "CCThreadProxy::beginFrame");
ASSERT(isMainThread());
if (!m_layerTreeHost)
return;
- // Drop beginFrameAndCommit calls that occur out of sequence. See createBeginFrameAndCommitTaskOnImplThread for
- // an explanation of how out-of-sequence beginFrameAndCommit tasks can occur.
- if (sequenceNumber < m_lastExecutedBeginFrameAndCommitSequenceNumber) {
- TRACE_EVENT("EarlyOut_StaleBeginFrameAndCommit", this, 0);
+ if (!m_pendingBeginFrameRequest) {
+ TRACE_EVENT0("cc", "EarlyOut_StaleBeginFrameMessage");
return;
}
- m_lastExecutedBeginFrameAndCommitSequenceNumber = sequenceNumber;
+
+ if (CCLayerTreeHost::needsFilterContext() && !SharedGraphicsContext3D::haveForImplThread())
+ SharedGraphicsContext3D::createForImplThread();
+
+ OwnPtr<BeginFrameAndCommitState> request(m_pendingBeginFrameRequest.release());
// Do not notify the impl thread of commit requests that occur during
// the apply/animate/layout part of the beginFrameAndCommit process since
@@ -448,22 +490,26 @@ void CCThreadProxy::beginFrameAndCommit(int sequenceNumber, double frameBeginTim
// FIXME: technically, scroll deltas need to be applied for dropped commits as well.
// Re-do the commit flow so that we don't send the scrollInfo on the BFAC message.
- m_layerTreeHost->applyScrollAndScale(*scrollInfo);
+ m_layerTreeHost->applyScrollAndScale(*request->scrollInfo);
+
+ m_layerTreeHost->willBeginFrame();
// FIXME: recreate the context if it was requested by the impl thread.
- m_layerTreeHost->updateAnimations(frameBeginTime);
+ m_layerTreeHost->updateAnimations(request->monotonicFrameBeginTime);
m_layerTreeHost->layout();
- ASSERT(m_lastExecutedBeginFrameAndCommitSequenceNumber == sequenceNumber);
-
// Clear the commit flag after updating animations and layout here --- objects that only
// layout when painted will trigger another setNeedsCommit inside
// updateLayers.
m_commitRequested = false;
- if (!m_layerTreeHost->updateLayers())
+ if (!m_layerTreeHost->updateLayers(*request->updater))
return;
+ // Once single buffered layers are committed, they cannot be modified until
+ // they are drawn by the impl thread.
+ m_texturesAcquired = false;
+
// Before applying scrolls and calling animate, we set m_animateRequested to false.
// If it is true now, it means setNeedAnimate was called again. Call setNeedsCommit
// now so that we get begin frame when this one is done.
@@ -482,8 +528,6 @@ void CCThreadProxy::beginFrameAndCommit(int sequenceNumber, double frameBeginTim
}
m_layerTreeHost->commitComplete();
-
- ASSERT(m_lastExecutedBeginFrameAndCommitSequenceNumber == sequenceNumber);
}
void CCThreadProxy::beginFrameCompleteOnImplThread(CCCompletionEvent* completion)
@@ -493,6 +537,7 @@ void CCThreadProxy::beginFrameCompleteOnImplThread(CCCompletionEvent* completion
ASSERT(isImplThread());
ASSERT(m_schedulerOnImplThread);
ASSERT(m_schedulerOnImplThread->commitPending());
+
if (!m_layerTreeHostImpl) {
completion->signal();
return;
@@ -500,10 +545,6 @@ void CCThreadProxy::beginFrameCompleteOnImplThread(CCCompletionEvent* completion
m_commitCompletionEventOnImplThread = completion;
- ASSERT(!m_currentTextureUpdaterOnImplThread);
- m_currentTextureUpdaterOnImplThread = adoptPtr(new CCTextureUpdater(m_layerTreeHostImpl->contentsTextureAllocator()));
- m_layerTreeHost->updateCompositorResources(m_layerTreeHostImpl->context(), *m_currentTextureUpdaterOnImplThread);
-
m_schedulerOnImplThread->beginFrameComplete();
}
@@ -526,19 +567,19 @@ void CCThreadProxy::scheduledActionUpdateMoreResources()
{
TRACE_EVENT("CCThreadProxy::scheduledActionUpdateMoreResources", this, 0);
ASSERT(m_currentTextureUpdaterOnImplThread);
- m_currentTextureUpdaterOnImplThread->update(m_layerTreeHostImpl->context(), textureUpdatesPerFrame);
+ m_currentTextureUpdaterOnImplThread->update(m_layerTreeHostImpl->context(), m_layerTreeHostImpl->contentsTextureAllocator(), m_layerTreeHostImpl->layerRenderer()->textureCopier(), m_layerTreeHostImpl->layerRenderer()->textureUploader(), textureUpdatesPerFrame);
}
void CCThreadProxy::scheduledActionCommit()
{
TRACE_EVENT("CCThreadProxy::scheduledActionCommit", this, 0);
+ ASSERT(isImplThread());
ASSERT(m_currentTextureUpdaterOnImplThread);
ASSERT(!m_currentTextureUpdaterOnImplThread->hasMoreUpdates());
ASSERT(m_commitCompletionEventOnImplThread);
m_currentTextureUpdaterOnImplThread.clear();
-
m_layerTreeHostImpl->beginCommit();
m_layerTreeHost->beginCommitOnImplThread(m_layerTreeHostImpl.get());
@@ -558,33 +599,50 @@ void CCThreadProxy::scheduledActionBeginContextRecreation()
m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::beginContextRecreation));
}
-void CCThreadProxy::scheduledActionDrawAndSwap()
+CCScheduledActionDrawAndSwapResult CCThreadProxy::scheduledActionDrawAndSwapInternal(bool forcedDraw)
{
TRACE_EVENT("CCThreadProxy::scheduledActionDrawAndSwap", this, 0);
+ CCScheduledActionDrawAndSwapResult result;
+ result.didDraw = false;
+ result.didSwap = false;
ASSERT(isImplThread());
+ ASSERT(m_layerTreeHostImpl);
if (!m_layerTreeHostImpl)
- return;
+ return result;
+
+ ASSERT(m_layerTreeHostImpl->layerRenderer());
+ if (!m_layerTreeHostImpl->layerRenderer())
+ return result;
// FIXME: compute the frame display time more intelligently
double monotonicTime = monotonicallyIncreasingTime();
double wallClockTime = currentTime();
- m_inputHandlerOnImplThread->willDraw(monotonicTime);
+ m_inputHandlerOnImplThread->animate(monotonicTime);
m_layerTreeHostImpl->animate(monotonicTime, wallClockTime);
- m_layerTreeHostImpl->drawLayers();
+ CCLayerTreeHostImpl::FrameData frame;
+ bool drawFrame = m_layerTreeHostImpl->prepareToDraw(frame) || forcedDraw;
+ if (drawFrame) {
+ m_layerTreeHostImpl->drawLayers(frame);
+ result.didDraw = true;
+ }
+ m_layerTreeHostImpl->didDrawAllLayers(frame);
// Check for a pending compositeAndReadback.
if (m_readbackRequestOnImplThread) {
+ ASSERT(drawFrame); // This should be a forcedDraw
m_layerTreeHostImpl->readback(m_readbackRequestOnImplThread->pixels, m_readbackRequestOnImplThread->rect);
m_readbackRequestOnImplThread->success = !m_layerTreeHostImpl->isContextLost();
m_readbackRequestOnImplThread->completion.signal();
m_readbackRequestOnImplThread = 0;
}
- m_layerTreeHostImpl->swapBuffers();
+ if (drawFrame)
+ result.didSwap = m_layerTreeHostImpl->swapBuffers();
// Process any finish request
if (m_finishAllRenderingCompletionEventOnImplThread) {
+ ASSERT(drawFrame); // This should be a forcedDraw
m_layerTreeHostImpl->finishAllRendering();
m_finishAllRenderingCompletionEventOnImplThread->signal();
m_finishAllRenderingCompletionEventOnImplThread = 0;
@@ -595,6 +653,55 @@ void CCThreadProxy::scheduledActionDrawAndSwap()
m_nextFrameIsNewlyCommittedFrameOnImplThread = false;
m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::didCommitAndDrawFrame));
}
+
+ ASSERT(drawFrame || (!drawFrame && !forcedDraw));
+ return result;
+}
+
+void CCThreadProxy::acquireLayerTextures()
+{
+ // Called when the main thread needs to modify a layer texture that is used
+ // directly by the compositor.
+ // This method will block until the next compositor draw if there is a
+ // previously committed frame that is still undrawn. This is necessary to
+ // ensure that the main thread does not monopolize access to the textures.
+ ASSERT(isMainThread());
+
+ if (m_texturesAcquired)
+ return;
+
+ TRACE_EVENT("CCThreadProxy::acquireLayerTextures", this, 0);
+ CCCompletionEvent completion;
+ CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::acquireLayerTexturesForMainThreadOnImplThread, AllowCrossThreadAccess(&completion)));
+ completion.wait(); // Block until it is safe to write to layer textures from the main thread.
+
+ m_texturesAcquired = true;
+}
+
+void CCThreadProxy::acquireLayerTexturesForMainThreadOnImplThread(CCCompletionEvent* completion)
+{
+ ASSERT(isImplThread());
+ ASSERT(!m_textureAcquisitionCompletionEventOnImplThread);
+
+ m_textureAcquisitionCompletionEventOnImplThread = completion;
+ m_schedulerOnImplThread->setMainThreadNeedsLayerTextures();
+}
+
+void CCThreadProxy::scheduledActionAcquireLayerTexturesForMainThread()
+{
+ ASSERT(m_textureAcquisitionCompletionEventOnImplThread);
+ m_textureAcquisitionCompletionEventOnImplThread->signal();
+ m_textureAcquisitionCompletionEventOnImplThread = 0;
+}
+
+CCScheduledActionDrawAndSwapResult CCThreadProxy::scheduledActionDrawAndSwapIfPossible()
+{
+ return scheduledActionDrawAndSwapInternal(false);
+}
+
+CCScheduledActionDrawAndSwapResult CCThreadProxy::scheduledActionDrawAndSwapForced()
+{
+ return scheduledActionDrawAndSwapInternal(true);
}
void CCThreadProxy::didCommitAndDrawFrame()
@@ -622,17 +729,23 @@ void CCThreadProxy::setAnimationEvents(PassOwnPtr<CCAnimationEventsVector> event
m_layerTreeHost->setAnimationEvents(events, wallClockTime);
}
+void CCThreadProxy::setContentsMemoryAllocationLimitBytes(size_t bytes)
+{
+ ASSERT(isMainThread());
+ if (!m_layerTreeHost)
+ return;
+ m_layerTreeHost->setContentsMemoryAllocationLimitBytes(bytes);
+}
+
class CCThreadProxyContextRecreationTimer : public CCTimer, CCTimerClient {
public:
static PassOwnPtr<CCThreadProxyContextRecreationTimer> create(CCThreadProxy* proxy) { return adoptPtr(new CCThreadProxyContextRecreationTimer(proxy)); }
- virtual void onTimerFired()
+ virtual void onTimerFired() OVERRIDE
{
m_proxy->tryToRecreateContext();
}
- enum Recreation { RecreationTickRateMs = 30 };
-
private:
explicit CCThreadProxyContextRecreationTimer(CCThreadProxy* proxy)
: CCTimer(CCProxy::mainThread(), this)
@@ -650,7 +763,7 @@ void CCThreadProxy::beginContextRecreation()
ASSERT(!m_contextRecreationTimer);
m_contextRecreationTimer = CCThreadProxyContextRecreationTimer::create(this);
m_layerTreeHost->didLoseContext();
- m_contextRecreationTimer->startOneShot(CCThreadProxyContextRecreationTimer::RecreationTickRateMs);
+ m_contextRecreationTimer->startOneShot(contextRecreationTickRate);
}
void CCThreadProxy::tryToRecreateContext()
@@ -659,7 +772,7 @@ void CCThreadProxy::tryToRecreateContext()
ASSERT(m_layerTreeHost);
CCLayerTreeHost::RecreateResult result = m_layerTreeHost->recreateContext();
if (result == CCLayerTreeHost::RecreateFailedButTryAgain)
- m_contextRecreationTimer->startOneShot(CCThreadProxyContextRecreationTimer::RecreationTickRateMs);
+ m_contextRecreationTimer->startOneShot(contextRecreationTickRate);
else if (result == CCLayerTreeHost::RecreateSucceeded)
m_contextRecreationTimer.clear();
}
@@ -669,8 +782,8 @@ void CCThreadProxy::initializeImplOnImplThread(CCCompletionEvent* completion)
TRACE_EVENT("CCThreadProxy::initializeImplOnImplThread", this, 0);
ASSERT(isImplThread());
m_layerTreeHostImpl = m_layerTreeHost->createLayerTreeHostImpl(this);
- const double displayRefreshIntervalMs = 1000.0 / 60.0;
- OwnPtr<CCFrameRateController> frameRateController = adoptPtr(new CCFrameRateController(CCDelayBasedTimeSource::create(displayRefreshIntervalMs, CCProxy::implThread())));
+ const double displayRefreshInterval = 1.0 / 60.0;
+ OwnPtr<CCFrameRateController> frameRateController = adoptPtr(new CCFrameRateController(CCDelayBasedTimeSource::create(displayRefreshInterval, CCProxy::implThread())));
m_schedulerOnImplThread = CCScheduler::create(this, frameRateController.release());
m_schedulerOnImplThread->setVisible(m_layerTreeHostImpl->visible());
@@ -707,8 +820,8 @@ void CCThreadProxy::layerTreeHostClosedOnImplThread(CCCompletionEvent* completio
TRACE_EVENT("CCThreadProxy::layerTreeHostClosedOnImplThread", this, 0);
ASSERT(isImplThread());
m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->contentsTextureAllocator());
- m_layerTreeHostImpl.clear();
m_inputHandlerOnImplThread.clear();
+ m_layerTreeHostImpl.clear();
m_schedulerOnImplThread.clear();
completion->signal();
}
@@ -724,6 +837,19 @@ size_t CCThreadProxy::maxPartialTextureUpdates() const
return textureUpdatesPerFrame;
}
+void CCThreadProxy::setFontAtlas(PassOwnPtr<CCFontAtlas> fontAtlas)
+{
+ ASSERT(isMainThread());
+ CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setFontAtlasOnImplThread, fontAtlas));
+
+}
+
+void CCThreadProxy::setFontAtlasOnImplThread(PassOwnPtr<CCFontAtlas> fontAtlas)
+{
+ ASSERT(isImplThread());
+ m_layerTreeHostImpl->setFontAtlas(fontAtlas);
+}
+
void CCThreadProxy::recreateContextOnImplThread(CCCompletionEvent* completion, GraphicsContext3D* contextPtr, bool* recreateSucceeded, LayerRendererCapabilities* capabilities)
{
TRACE_EVENT0("cc", "CCThreadProxy::recreateContextOnImplThread");
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h
index 057691213..2915a8119 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h
@@ -51,50 +51,73 @@ public:
virtual ~CCThreadProxy();
// CCProxy implementation
- virtual bool compositeAndReadback(void *pixels, const IntRect&);
- virtual void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration);
- virtual GraphicsContext3D* context();
- virtual void finishAllRendering();
- virtual bool isStarted() const;
- virtual bool initializeContext();
- virtual bool initializeLayerRenderer();
- virtual bool recreateContext();
- virtual int compositorIdentifier() const;
- virtual const LayerRendererCapabilities& layerRendererCapabilities() const;
- virtual void loseContext();
- virtual void setNeedsAnimate();
- virtual void setNeedsCommit();
- virtual void setNeedsRedraw();
- virtual void setVisible(bool);
- virtual void start();
- virtual void stop();
- virtual size_t maxPartialTextureUpdates() const;
+ virtual bool compositeAndReadback(void *pixels, const IntRect&) OVERRIDE;
+ virtual void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration) OVERRIDE;
+ virtual GraphicsContext3D* context() OVERRIDE;
+ virtual void finishAllRendering() OVERRIDE;
+ virtual bool isStarted() const OVERRIDE;
+ virtual bool initializeContext() OVERRIDE;
+ virtual void setSurfaceReady() OVERRIDE;
+ virtual bool initializeLayerRenderer() OVERRIDE;
+ virtual bool recreateContext() OVERRIDE;
+ virtual int compositorIdentifier() const OVERRIDE;
+ virtual const LayerRendererCapabilities& layerRendererCapabilities() const OVERRIDE;
+ virtual void loseContext() OVERRIDE;
+ virtual void setNeedsAnimate() OVERRIDE;
+ virtual void setNeedsCommit() OVERRIDE;
+ virtual void setNeedsRedraw() OVERRIDE;
+ virtual bool commitRequested() const OVERRIDE;
+ virtual void setVisible(bool) OVERRIDE;
+ virtual void start() OVERRIDE;
+ virtual void stop() OVERRIDE;
+ virtual size_t maxPartialTextureUpdates() const OVERRIDE;
+ virtual void acquireLayerTextures() OVERRIDE;
+ virtual void setFontAtlas(PassOwnPtr<CCFontAtlas>) OVERRIDE;
+ virtual void forceSerializeOnSwapBuffers() OVERRIDE;
// CCLayerTreeHostImplClient implementation
- virtual void didLoseContextOnImplThread();
- virtual void onSwapBuffersCompleteOnImplThread();
- virtual void setNeedsRedrawOnImplThread();
- virtual void setNeedsCommitOnImplThread();
- virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime);
+ virtual void didLoseContextOnImplThread() OVERRIDE;
+ virtual void onSwapBuffersCompleteOnImplThread() OVERRIDE;
+ virtual void setNeedsRedrawOnImplThread() OVERRIDE;
+ virtual void setNeedsCommitOnImplThread() OVERRIDE;
+ virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime) OVERRIDE;
+ virtual void postSetContentsMemoryAllocationLimitBytesToMainThreadOnImplThread(size_t) OVERRIDE;
// CCSchedulerClient implementation
- virtual bool canDraw();
- virtual bool hasMoreResourceUpdates() const;
- virtual void scheduledActionBeginFrame();
- virtual void scheduledActionDrawAndSwap();
- virtual void scheduledActionUpdateMoreResources();
- virtual void scheduledActionCommit();
- virtual void scheduledActionBeginContextRecreation();
+ virtual bool canDraw() OVERRIDE;
+ virtual bool hasMoreResourceUpdates() const OVERRIDE;
+ virtual void scheduledActionBeginFrame() OVERRIDE;
+ virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapIfPossible() OVERRIDE;
+ virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapForced() OVERRIDE;
+ virtual void scheduledActionUpdateMoreResources() OVERRIDE;
+ virtual void scheduledActionCommit() OVERRIDE;
+ virtual void scheduledActionBeginContextRecreation() OVERRIDE;
+ virtual void scheduledActionAcquireLayerTexturesForMainThread() OVERRIDE;
private:
explicit CCThreadProxy(CCLayerTreeHost*);
friend class CCThreadProxyContextRecreationTimer;
+ // Set on impl thread, read on main thread.
+ struct BeginFrameAndCommitState {
+ BeginFrameAndCommitState()
+ : monotonicFrameBeginTime(0)
+ , updater(0)
+ {
+ }
+
+ double monotonicFrameBeginTime;
+ OwnPtr<CCScrollAndScaleSet> scrollInfo;
+ CCTextureUpdater* updater;
+ };
+ OwnPtr<BeginFrameAndCommitState> m_pendingBeginFrameRequest;
+
// Called on main thread
- void beginFrameAndCommit(int sequenceNumber, double frameBeginTime, PassOwnPtr<CCScrollAndScaleSet>);
+ void beginFrame();
void didCommitAndDrawFrame();
void didCompleteSwapBuffers();
void setAnimationEvents(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime);
+ void setContentsMemoryAllocationLimitBytes(size_t);
void beginContextRecreation();
void tryToRecreateContext();
@@ -105,19 +128,23 @@ private:
void* pixels;
IntRect rect;
};
- PassOwnPtr<CCThread::Task> createBeginFrameAndCommitTaskOnImplThread();
- void obtainBeginFrameAndCommitTaskFromCCThread(CCCompletionEvent*, CCThread::Task**);
+ void forceBeginFrameOnImplThread(CCCompletionEvent*);
void beginFrameCompleteOnImplThread(CCCompletionEvent*);
void requestReadbackOnImplThread(ReadbackRequest*);
void requestStartPageScaleAnimationOnImplThread(IntSize targetPosition, bool useAnchor, float scale, double durationSec);
void finishAllRenderingOnImplThread(CCCompletionEvent*);
void initializeImplOnImplThread(CCCompletionEvent*);
+ void setSurfaceReadyOnImplThread();
void initializeContextOnImplThread(GraphicsContext3D*);
void initializeLayerRendererOnImplThread(CCCompletionEvent*, bool* initializeSucceeded, LayerRendererCapabilities*);
void setVisibleOnImplThread(CCCompletionEvent*, bool visible);
void layerTreeHostClosedOnImplThread(CCCompletionEvent*);
void setFullRootLayerDamageOnImplThread();
+ void acquireLayerTexturesForMainThreadOnImplThread(CCCompletionEvent*);
void recreateContextOnImplThread(CCCompletionEvent*, GraphicsContext3D*, bool* recreateSucceeded, LayerRendererCapabilities*);
+ CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapInternal(bool forcedDraw);
+ void setFontAtlasOnImplThread(PassOwnPtr<CCFontAtlas>);
+ void forceSerializeOnSwapBuffersOnImplThread(CCCompletionEvent*);
// Accessed on main thread only.
bool m_animateRequested;
@@ -129,11 +156,9 @@ private:
bool m_layerRendererInitialized;
LayerRendererCapabilities m_layerRendererCapabilitiesMainThreadCopy;
bool m_started;
- int m_lastExecutedBeginFrameAndCommitSequenceNumber;
+ bool m_texturesAcquired;
- // Used on the CCThread only.
OwnPtr<CCLayerTreeHostImpl> m_layerTreeHostImpl;
- int m_numBeginFrameAndCommitsIssuedOnImplThread;
OwnPtr<CCInputHandler> m_inputHandlerOnImplThread;
@@ -145,7 +170,10 @@ private:
// and initializeLayerRenderer() calls.
RefPtr<GraphicsContext3D> m_contextBeforeInitializationOnImplThread;
- // Set when the main thread is waiing on a readback.
+ // Set when the main thread is waiting on a scheduledActionBeginFrame to be issued.
+ CCCompletionEvent* m_beginFrameCompletionEventOnImplThread;
+
+ // Set when the main thread is waiting on a readback.
ReadbackRequest* m_readbackRequestOnImplThread;
// Set when the main thread is waiting on a finishAllRendering call.
@@ -153,6 +181,10 @@ private:
// Set when the main thread is waiting on a commit to complete.
CCCompletionEvent* m_commitCompletionEventOnImplThread;
+
+ // Set when the main thread is waiting on layers to be drawn.
+ CCCompletionEvent* m_textureAcquisitionCompletionEventOnImplThread;
+
OwnPtr<CCTextureUpdater> m_currentTextureUpdaterOnImplThread;
// Set when the next draw should post didCommitAndDrawFrame to the main thread.
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp
index e8d2a6c45..ec22a9fd6 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp
@@ -30,7 +30,9 @@
#include "cc/CCTiledLayerImpl.h"
#include "LayerRendererChromium.h"
+#include "cc/CCCheckerboardDrawQuad.h"
#include "cc/CCDebugBorderDrawQuad.h"
+#include "cc/CCQuadCuller.h"
#include "cc/CCSolidColorDrawQuad.h"
#include "cc/CCTileDrawQuad.h"
#include <wtf/text/WTFString.h>
@@ -41,6 +43,12 @@ namespace WebCore {
static const int debugTileBorderWidth = 1;
static const int debugTileBorderAlpha = 100;
+static const int debugTileBorderColorRed = 80;
+static const int debugTileBorderColorGreen = 200;
+static const int debugTileBorderColorBlue = 200;
+static const int debugTileBorderMissingTileColorRed = 255;
+static const int debugTileBorderMissingTileColorGreen = 0;
+static const int debugTileBorderMissingTileColorBlue = 0;
class ManagedTexture;
@@ -73,7 +81,8 @@ void CCTiledLayerImpl::bindContentsTexture(LayerRendererChromium* layerRenderer)
{
// This function is only valid for single texture layers, e.g. masks.
ASSERT(m_tiler);
- ASSERT(m_tiler->numTiles() == 1);
+ ASSERT(m_tiler->numTilesX() == 1);
+ ASSERT(m_tiler->numTilesY() == 1);
DrawableTile* tile = tileAt(0, 0);
Platform3DObject textureId = tile ? tile->textureId() : 0;
@@ -94,6 +103,11 @@ bool CCTiledLayerImpl::hasTileAt(int i, int j) const
return m_tiler->tileAt(i, j);
}
+bool CCTiledLayerImpl::hasTextureIdForTileAt(int i, int j) const
+{
+ return hasTileAt(i, j) && tileAt(i, j)->textureId();
+}
+
DrawableTile* CCTiledLayerImpl::tileAt(int i, int j) const
{
return static_cast<DrawableTile*>(m_tiler->tileAt(i, j));
@@ -122,20 +136,35 @@ TransformationMatrix CCTiledLayerImpl::quadTransform() const
return transform;
}
-void CCTiledLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState)
+void CCTiledLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool& hadMissingTiles)
{
const IntRect& layerRect = visibleLayerRect();
- if (m_skipsDraw)
+ if (!m_tiler || m_tiler->hasEmptyBounds() || layerRect.isEmpty())
return;
- appendGutterQuads(quadList, sharedQuadState);
+ int left, top, right, bottom;
+ m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom);
+
+ if (hasDebugBorders()) {
+ for (int j = top; j <= bottom; ++j) {
+ for (int i = left; i <= right; ++i) {
+ DrawableTile* tile = tileAt(i, j);
+ IntRect tileRect = m_tiler->tileBounds(i, j);
+ Color borderColor;
+
+ if (m_skipsDraw || !tile || !tile->textureId())
+ borderColor = Color(debugTileBorderMissingTileColorRed, debugTileBorderMissingTileColorGreen, debugTileBorderMissingTileColorBlue, debugTileBorderAlpha);
+ else
+ borderColor = Color(debugTileBorderColorRed, debugTileBorderColorGreen, debugTileBorderColorBlue, debugTileBorderAlpha);
+ quadList.append(CCDebugBorderDrawQuad::create(sharedQuadState, tileRect, borderColor, debugTileBorderWidth));
+ }
+ }
+ }
- if (!m_tiler || !m_tiler->numTiles() || layerRect.isEmpty())
+ if (m_skipsDraw)
return;
- int left, top, right, bottom;
- m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom);
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
DrawableTile* tile = tileAt(i, j);
@@ -148,7 +177,10 @@ void CCTiledLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState
continue;
if (!tile || !tile->textureId()) {
- quadList.append(CCSolidColorDrawQuad::create(sharedQuadState, tileRect, backgroundColor()));
+ if (drawCheckerboardForMissingTiles())
+ hadMissingTiles |= quadList.append(CCCheckerboardDrawQuad::create(sharedQuadState, tileRect));
+ else
+ hadMissingTiles |= quadList.append(CCSolidColorDrawQuad::create(sharedQuadState, tileRect, backgroundColor()));
continue;
}
@@ -172,11 +204,6 @@ void CCTiledLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState
const GC3Dint textureFilter = m_tiler->hasBorderTexels() ? GraphicsContext3D::LINEAR : GraphicsContext3D::NEAREST;
quadList.append(CCTileDrawQuad::create(sharedQuadState, tileRect, tileOpaqueRect, tile->textureId(), textureOffset, textureSize, textureFilter, contentsSwizzled(), leftEdgeAA, topEdgeAA, rightEdgeAA, bottomEdgeAA));
-
- if (hasDebugBorders()) {
- Color color(debugBorderColor().red(), debugBorderColor().green(), debugBorderColor().blue(), debugTileBorderAlpha);
- quadList.append(CCDebugBorderDrawQuad::create(sharedQuadState, tileRect, color, debugTileBorderWidth));
- }
}
}
}
@@ -199,14 +226,20 @@ void CCTiledLayerImpl::pushTileProperties(int i, int j, Platform3DObject texture
tile->setOpaqueRect(opaqueRect);
}
-Region CCTiledLayerImpl::opaqueContentsRegion() const
+Region CCTiledLayerImpl::visibleContentOpaqueRegion() const
{
if (m_skipsDraw)
return Region();
-
+ if (opaque())
+ return visibleLayerRect();
return m_tiler->opaqueRegionInLayerRect(visibleLayerRect());
}
+void CCTiledLayerImpl::didLoseContext()
+{
+ m_tiler->reset();
+}
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.h
index 84fe47621..bd146650b 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.h
@@ -43,11 +43,11 @@ public:
}
virtual ~CCTiledLayerImpl();
- virtual void appendQuads(CCQuadList&, const CCSharedQuadState*);
+ virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*, bool& hadMissingTiles) OVERRIDE;
- virtual void bindContentsTexture(LayerRendererChromium*);
+ virtual void bindContentsTexture(LayerRendererChromium*) OVERRIDE;
- virtual void dumpLayerProperties(TextStream&, int indent) const;
+ virtual void dumpLayerProperties(TextStream&, int indent) const OVERRIDE;
void setSkipsDraw(bool skipsDraw) { m_skipsDraw = skipsDraw; }
void setTilingData(const CCLayerTilingData& tiler);
@@ -56,31 +56,20 @@ public:
void setContentsSwizzled(bool contentsSwizzled) { m_contentsSwizzled = contentsSwizzled; }
bool contentsSwizzled() const { return m_contentsSwizzled; }
- virtual Region opaqueContentsRegion() const;
-
- typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexAlpha> Program;
- // Shader program that swaps red and blue components of texture.
- // Used when texture format does not match native color format.
- typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexSwizzleAlpha> ProgramSwizzle;
-
- // Same as above but ignoring alpha and writing out 1.0 for the alpha channel.
- typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexOpaque> ProgramOpaque;
- typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexSwizzleOpaque> ProgramSwizzleOpaque;
-
- // Shader program that produces anti-aliased layer edges.
- typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexClampAlphaAA> ProgramAA;
- typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexClampSwizzleAlphaAA> ProgramSwizzleAA;
+ virtual Region visibleContentOpaqueRegion() const OVERRIDE;
+ virtual void didLoseContext() OVERRIDE;
protected:
explicit CCTiledLayerImpl(int id);
// Exposed for testing.
bool hasTileAt(int, int) const;
+ bool hasTextureIdForTileAt(int, int) const;
- virtual TransformationMatrix quadTransform() const;
+ virtual TransformationMatrix quadTransform() const OVERRIDE;
private:
- virtual const char* layerTypeAsString() const { return "ContentLayer"; }
+ virtual const char* layerTypeAsString() const OVERRIDE { return "ContentLayer"; }
DrawableTile* tileAt(int, int) const;
DrawableTile* createTile(int, int);
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTimer.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCTimer.cpp
index 9fcc61305..6d6189e23 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCTimer.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCTimer.cpp
@@ -76,12 +76,14 @@ CCTimer::~CCTimer()
stop();
}
-void CCTimer::startOneShot(double intervalMs)
+void CCTimer::startOneShot(double intervalSeconds)
{
stop();
m_task = new CCTimerTask(this);
- m_thread->postDelayedTask(adoptPtr(m_task), intervalMs);
+
+ // The thread expects delays in milliseconds.
+ m_thread->postDelayedTask(adoptPtr(m_task), intervalSeconds * 1000.0);
}
void CCTimer::stop()
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTimer.h b/Source/WebCore/platform/graphics/chromium/cc/CCTimer.h
index b8db5e189..a845190d9 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCTimer.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCTimer.h
@@ -50,7 +50,7 @@ public:
~CCTimer();
// If a previous task is pending, it will be replaced with the new one.
- void startOneShot(double intervalMs);
+ void startOneShot(double intervalSeconds);
void stop();
bool isActive() const { return m_task; }
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTimingFunction.h b/Source/WebCore/platform/graphics/chromium/cc/CCTimingFunction.h
index 77e5c43c5..272997e7c 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCTimingFunction.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCTimingFunction.h
@@ -38,7 +38,7 @@ public:
virtual ~CCTimingFunction();
// Partial implementation of CCFloatAnimationCurve.
- virtual double duration() const;
+ virtual double duration() const OVERRIDE;
protected:
CCTimingFunction();
@@ -50,8 +50,8 @@ public:
virtual ~CCCubicBezierTimingFunction();
// Partial implementation of CCFloatAnimationCurve.
- virtual float getValue(double time) const;
- virtual PassOwnPtr<CCAnimationCurve> clone() const;
+ virtual float getValue(double time) const OVERRIDE;
+ virtual PassOwnPtr<CCAnimationCurve> clone() const OVERRIDE;
protected:
CCCubicBezierTimingFunction(double x1, double y1, double x2, double y2);
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.cpp
index ba5734909..9cca71412 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.cpp
@@ -29,12 +29,12 @@
namespace WebCore {
-PassOwnPtr<CCVideoDrawQuad> CCVideoDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCVideoLayerImpl::Texture* textures, VideoFrameChromium* frame, GC3Denum format)
+PassOwnPtr<CCVideoDrawQuad> CCVideoDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCVideoLayerImpl::Texture* textures, WebKit::WebVideoFrame* frame, GC3Denum format)
{
return adoptPtr(new CCVideoDrawQuad(sharedQuadState, quadRect, textures, frame, format));
}
-CCVideoDrawQuad::CCVideoDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCVideoLayerImpl::Texture* textures, VideoFrameChromium* frame, GC3Denum format)
+CCVideoDrawQuad::CCVideoDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCVideoLayerImpl::Texture* textures, WebKit::WebVideoFrame* frame, GC3Denum format)
: CCDrawQuad(sharedQuadState, CCDrawQuad::VideoContent, quadRect)
, m_textures(textures)
, m_frame(frame)
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.h b/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.h
index aef78472a..9eb357fc8 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.h
@@ -31,25 +31,29 @@
#include "cc/CCVideoLayerImpl.h"
#include <wtf/PassOwnPtr.h>
+namespace WebKit {
+class WebVideoFrame;
+}
+
namespace WebCore {
class CCVideoDrawQuad : public CCDrawQuad {
WTF_MAKE_NONCOPYABLE(CCVideoDrawQuad);
public:
- static PassOwnPtr<CCVideoDrawQuad> create(const CCSharedQuadState*, const IntRect&, CCVideoLayerImpl::Texture* textures, VideoFrameChromium*, GC3Denum format);
+ static PassOwnPtr<CCVideoDrawQuad> create(const CCSharedQuadState*, const IntRect&, CCVideoLayerImpl::Texture* textures, WebKit::WebVideoFrame*, GC3Denum format);
CCVideoLayerImpl::Texture* textures() const { return m_textures; }
- VideoFrameChromium* frame() const { return m_frame; }
+ WebKit::WebVideoFrame* frame() const { return m_frame; }
GC3Denum format() const { return m_format; }
const float* matrix() const { return m_matrix; }
void setMatrix(const float* matrix) { m_matrix = matrix; }
private:
- CCVideoDrawQuad(const CCSharedQuadState*, const IntRect&, CCVideoLayerImpl::Texture* textures, VideoFrameChromium*, GC3Denum format);
+ CCVideoDrawQuad(const CCSharedQuadState*, const IntRect&, CCVideoLayerImpl::Texture* textures, WebKit::WebVideoFrame*, GC3Denum format);
CCVideoLayerImpl::Texture* m_textures;
- VideoFrameChromium* m_frame;
+ WebKit::WebVideoFrame* m_frame;
GC3Denum m_format;
const float* m_matrix;
};
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp
index fd53e41d3..9c076a2ed 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp
@@ -36,7 +36,9 @@
#include "ProgramBinding.h"
#include "cc/CCLayerTreeHostImpl.h"
#include "cc/CCProxy.h"
+#include "cc/CCQuadCuller.h"
#include "cc/CCVideoDrawQuad.h"
+#include <public/WebVideoFrame.h>
#include <wtf/text/WTFString.h>
namespace WebCore {
@@ -71,7 +73,7 @@ const float CCVideoLayerImpl::flipTransform[16] = {
0, 1, 0, 1,
};
-CCVideoLayerImpl::CCVideoLayerImpl(int id, VideoFrameProvider* provider)
+CCVideoLayerImpl::CCVideoLayerImpl(int id, WebKit::WebVideoFrameProvider* provider)
: CCLayerImpl(id)
, m_provider(provider)
, m_layerTreeHostImpl(0)
@@ -98,26 +100,19 @@ void CCVideoLayerImpl::stopUsingProvider()
m_provider = 0;
}
-// Convert VideoFrameChromium::Format to GraphicsContext3D's format enum values.
-static GC3Denum convertVFCFormatToGC3DFormat(const VideoFrameChromium* frame)
+// Convert WebKit::WebVideoFrame::Format to GraphicsContext3D's format enum values.
+static GC3Denum convertVFCFormatToGC3DFormat(const WebKit::WebVideoFrame& frame)
{
- switch (frame->format()) {
- case VideoFrameChromium::YV12:
- case VideoFrameChromium::YV16:
+ switch (frame.format()) {
+ case WebKit::WebVideoFrame::FormatYV12:
+ case WebKit::WebVideoFrame::FormatYV16:
return GraphicsContext3D::LUMINANCE;
- case VideoFrameChromium::RGBA:
- return GraphicsContext3D::RGBA;
- case VideoFrameChromium::NativeTexture:
- return frame->textureTarget();
- case VideoFrameChromium::Invalid:
- case VideoFrameChromium::RGB555:
- case VideoFrameChromium::RGB565:
- case VideoFrameChromium::RGB24:
- case VideoFrameChromium::RGB32:
- case VideoFrameChromium::NV12:
- case VideoFrameChromium::Empty:
- case VideoFrameChromium::ASCII:
- case VideoFrameChromium::I420:
+ case WebKit::WebVideoFrame::FormatNativeTexture:
+ return frame.textureTarget();
+ case WebKit::WebVideoFrame::FormatInvalid:
+ case WebKit::WebVideoFrame::FormatRGB32:
+ case WebKit::WebVideoFrame::FormatEmpty:
+ case WebKit::WebVideoFrame::FormatI420:
notImplemented();
}
return GraphicsContext3D::INVALID_VALUE;
@@ -126,8 +121,26 @@ static GC3Denum convertVFCFormatToGC3DFormat(const VideoFrameChromium* frame)
void CCVideoLayerImpl::willDraw(LayerRendererChromium* layerRenderer)
{
ASSERT(CCProxy::isImplThread());
+ CCLayerImpl::willDraw(layerRenderer);
- MutexLocker locker(m_providerMutex);
+ // Explicitly lock and unlock the provider mutex so it can be held from
+ // willDraw to didDraw. Since the compositor thread is in the middle of
+ // drawing, the layer will not be destroyed before didDraw is called.
+ // Therefore, the only thing that will prevent this lock from being released
+ // is the GPU process locking it. As the GPU process can't cause the
+ // destruction of the provider (calling stopUsingProvider), holding this
+ // lock should not cause a deadlock.
+ m_providerMutex.lock();
+
+ willDrawInternal(layerRenderer);
+
+ if (!m_frame)
+ m_providerMutex.unlock();
+}
+
+void CCVideoLayerImpl::willDrawInternal(LayerRendererChromium* layerRenderer)
+{
+ ASSERT(CCProxy::isImplThread());
if (!m_provider) {
m_frame = 0;
@@ -139,7 +152,7 @@ void CCVideoLayerImpl::willDraw(LayerRendererChromium* layerRenderer)
if (!m_frame)
return;
- m_format = convertVFCFormatToGC3DFormat(m_frame);
+ m_format = convertVFCFormatToGC3DFormat(*m_frame);
if (m_format == GraphicsContext3D::INVALID_VALUE) {
m_provider->putCurrentFrame(m_frame);
@@ -147,14 +160,19 @@ void CCVideoLayerImpl::willDraw(LayerRendererChromium* layerRenderer)
return;
}
- if (!reserveTextures(m_frame, m_format, layerRenderer)) {
+ if (!reserveTextures(*m_frame, m_format, layerRenderer)) {
m_provider->putCurrentFrame(m_frame);
m_frame = 0;
}
}
-void CCVideoLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState)
+void CCVideoLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool&)
{
+ ASSERT(CCProxy::isImplThread());
+
+ if (!m_frame)
+ return;
+
IntRect quadRect(IntPoint(), bounds());
OwnPtr<CCVideoDrawQuad> videoQuad = CCVideoDrawQuad::create(sharedQuadState, quadRect, m_textures, m_frame, m_format);
@@ -167,49 +185,62 @@ void CCVideoLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState
void CCVideoLayerImpl::didDraw()
{
ASSERT(CCProxy::isImplThread());
+ CCLayerImpl::didDraw();
- MutexLocker locker(m_providerMutex);
-
- if (!m_provider || !m_frame)
+ if (!m_frame)
return;
for (unsigned plane = 0; plane < m_frame->planes(); ++plane)
m_textures[plane].m_texture->unreserve();
m_provider->putCurrentFrame(m_frame);
m_frame = 0;
+
+ m_providerMutex.unlock();
+}
+
+static int videoFrameDimension(int originalDimension, unsigned plane, int format)
+{
+ if (format == WebKit::WebVideoFrame::FormatYV12 && plane != WebKit::WebVideoFrame::yPlane)
+ return originalDimension / 2;
+ return originalDimension;
+}
+
+static bool hasPaddingBytes(const WebKit::WebVideoFrame& frame, unsigned plane)
+{
+ return frame.stride(plane) > videoFrameDimension(frame.width(), plane, frame.format());
}
-IntSize CCVideoLayerImpl::computeVisibleSize(const VideoFrameChromium* frame, unsigned plane)
+IntSize CCVideoLayerImpl::computeVisibleSize(const WebKit::WebVideoFrame& frame, unsigned plane)
{
- int visibleWidth = frame->width(plane);
- int visibleHeight = frame->height(plane);
+ int visibleWidth = videoFrameDimension(frame.width(), plane, frame.format());
+ int originalWidth = visibleWidth;
+ int visibleHeight = videoFrameDimension(frame.height(), plane, frame.format());
+
// When there are dead pixels at the edge of the texture, decrease
// the frame width by 1 to prevent the rightmost pixels from
// interpolating with the dead pixels.
- if (frame->hasPaddingBytes(plane))
+ if (hasPaddingBytes(frame, plane))
--visibleWidth;
// In YV12, every 2x2 square of Y values corresponds to one U and
// one V value. If we decrease the width of the UV plane, we must decrease the
// width of the Y texture by 2 for proper alignment. This must happen
// always, even if Y's texture does not have padding bytes.
- if (plane == VideoFrameChromium::yPlane && frame->format() == VideoFrameChromium::YV12) {
- if (frame->hasPaddingBytes(VideoFrameChromium::uPlane)) {
- int originalWidth = frame->width(plane);
+ if (plane == WebKit::WebVideoFrame::yPlane && frame.format() == WebKit::WebVideoFrame::FormatYV12) {
+ if (hasPaddingBytes(frame, WebKit::WebVideoFrame::uPlane))
visibleWidth = originalWidth - 2;
- }
}
return IntSize(visibleWidth, visibleHeight);
}
-bool CCVideoLayerImpl::reserveTextures(const VideoFrameChromium* frame, GC3Denum format, LayerRendererChromium* layerRenderer)
+bool CCVideoLayerImpl::reserveTextures(const WebKit::WebVideoFrame& frame, GC3Denum format, LayerRendererChromium* layerRenderer)
{
- if (frame->planes() > MaxPlanes)
+ if (frame.planes() > MaxPlanes)
return false;
int maxTextureSize = layerRenderer->capabilities().maxTextureSize;
- for (unsigned plane = 0; plane < frame->planes(); ++plane) {
- IntSize requiredTextureSize = frame->requiredTextureSize(plane);
+ for (unsigned plane = 0; plane < frame.planes(); ++plane) {
+ IntSize requiredTextureSize(frame.stride(plane), videoFrameDimension(frame.height(), plane, frame.format()));
// If the renderer cannot handle this large of a texture, return false.
// FIXME: Remove this test when tiled layers are implemented.
if (requiredTextureSize.isZero() || requiredTextureSize.width() > maxTextureSize || requiredTextureSize.height() > maxTextureSize)
@@ -243,6 +274,12 @@ void CCVideoLayerImpl::didUpdateMatrix(const float matrix[16])
setNeedsRedraw();
}
+void CCVideoLayerImpl::didLoseContext()
+{
+ for (unsigned i = 0; i < MaxPlanes; ++i)
+ m_textures[i].m_texture.clear();
+}
+
void CCVideoLayerImpl::setNeedsRedraw()
{
if (m_layerTreeHostImpl)
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h
index 4c4e23102..44606c13b 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h
@@ -27,47 +27,42 @@
#define CCVideoLayerImpl_h
#include "ManagedTexture.h"
-#include "ShaderChromium.h"
-#include "VideoFrameChromium.h"
-#include "VideoFrameProvider.h"
-#include "VideoLayerChromium.h"
#include "cc/CCLayerImpl.h"
+#include <public/WebVideoFrameProvider.h>
+
+namespace WebKit {
+class WebVideoFrame;
+}
namespace WebCore {
class CCLayerTreeHostImpl;
class CCVideoLayerImpl;
-template<class VertexShader, class FragmentShader> class ProgramBinding;
-
class CCVideoLayerImpl : public CCLayerImpl
- , public VideoFrameProvider::Client {
+ , public WebKit::WebVideoFrameProvider::Client {
public:
- static PassOwnPtr<CCVideoLayerImpl> create(int id, VideoFrameProvider* provider)
+ static PassOwnPtr<CCVideoLayerImpl> create(int id, WebKit::WebVideoFrameProvider* provider)
{
return adoptPtr(new CCVideoLayerImpl(id, provider));
}
virtual ~CCVideoLayerImpl();
- virtual void willDraw(LayerRendererChromium*);
- virtual void appendQuads(CCQuadList&, const CCSharedQuadState*);
- virtual void didDraw();
+ virtual void willDraw(LayerRendererChromium*) OVERRIDE;
+ virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*, bool& hadMissingTiles) OVERRIDE;
+ virtual void didDraw() OVERRIDE;
- typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexFlipAlpha> RGBAProgram;
- typedef ProgramBinding<VertexShaderPosTexYUVStretch, FragmentShaderYUVVideo> YUVProgram;
- typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexFlipAlpha> NativeTextureProgram;
- typedef ProgramBinding<VertexShaderVideoTransform, FragmentShaderOESImageExternal> StreamTextureProgram;
-
- virtual void dumpLayerProperties(TextStream&, int indent) const;
+ virtual void dumpLayerProperties(TextStream&, int indent) const OVERRIDE;
Mutex& providerMutex() { return m_providerMutex; }
- VideoFrameProvider* provider() const { return m_provider; }
- // VideoFrameProvider::Client implementation.
+ // WebKit::WebVideoFrameProvider::Client implementation.
virtual void stopUsingProvider(); // Callable on any thread.
virtual void didReceiveFrame(); // Callable on impl thread.
virtual void didUpdateMatrix(const float*); // Callable on impl thread.
+ virtual void didLoseContext() OVERRIDE;
+
void setNeedsRedraw();
static const float yuv2RGB[9];
@@ -81,22 +76,24 @@ public:
enum { MaxPlanes = 3 };
private:
- explicit CCVideoLayerImpl(int, VideoFrameProvider*);
+ CCVideoLayerImpl(int, WebKit::WebVideoFrameProvider*);
- static IntSize computeVisibleSize(const VideoFrameChromium*, unsigned plane);
- virtual const char* layerTypeAsString() const { return "VideoLayer"; }
+ static IntSize computeVisibleSize(const WebKit::WebVideoFrame&, unsigned plane);
+ virtual const char* layerTypeAsString() const OVERRIDE { return "VideoLayer"; }
- bool reserveTextures(const VideoFrameChromium*, GC3Denum format, LayerRendererChromium*);
+ void willDrawInternal(LayerRendererChromium*);
+ bool reserveTextures(const WebKit::WebVideoFrame&, GC3Denum format, LayerRendererChromium*);
- Mutex m_providerMutex; // Guards m_provider below.
- VideoFrameProvider* m_provider;
+ // Guards the destruction of m_provider and the frame that it provides
+ Mutex m_providerMutex;
+ WebKit::WebVideoFrameProvider* m_provider;
Texture m_textures[MaxPlanes];
float m_streamTextureMatrix[16];
CCLayerTreeHostImpl* m_layerTreeHostImpl;
- VideoFrameChromium* m_frame;
+ WebKit::WebVideoFrame* m_frame;
GC3Denum m_format;
};
diff --git a/Source/WebCore/platform/ScrollAnimatorWin.h b/Source/WebCore/platform/graphics/clutter/DrawingBufferClutter.cpp
index 6f87e58fd..41bc7e612 100644
--- a/Source/WebCore/platform/ScrollAnimatorWin.h
+++ b/Source/WebCore/platform/graphics/clutter/DrawingBufferClutter.cpp
@@ -1,10 +1,11 @@
/*
* Copyright (c) 2010, Google Inc. All rights reserved.
- *
+ * Copyright (c) 2012, Collabora Ltd.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
@@ -14,7 +15,7 @@
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -28,49 +29,53 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ScrollAnimatorWin_h
-#define ScrollAnimatorWin_h
+#include "config.h"
-#if ENABLE(SMOOTH_SCROLLING)
+#if ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(WEBGL)
-#include "ScrollAnimator.h"
-#include "Timer.h"
+#include "DrawingBuffer.h"
-namespace WebCore {
-
-class ScrollAnimatorWin : public ScrollAnimator {
-public:
- ScrollAnimatorWin(ScrollableArea*);
- virtual ~ScrollAnimatorWin();
+#include "Extensions3D.h"
- virtual bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier);
- virtual void scrollToOffsetWithoutAnimation(const FloatPoint&);
+namespace WebCore {
-private:
- struct PerAxisData {
- PerAxisData(ScrollAnimatorWin* parent, float* currentPos);
+DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
+ const IntSize& size,
+ bool multisampleExtensionSupported,
+ bool packedDepthStencilExtensionSupported,
+ PreserveDrawingBuffer preserveDrawingBuffer,
+ AlphaRequirement alpha)
+ : m_preserveDrawingBuffer(preserveDrawingBuffer)
+ , m_alpha(alpha)
+ , m_frontColorBuffer(0)
+ , m_separateFrontTexture(false)
+{
+}
- float* m_currentPos;
- float m_desiredPos;
- float m_currentVelocity;
- float m_desiredVelocity;
- double m_lastAnimationTime;
- Timer<ScrollAnimatorWin> m_animationTimer;
- };
+DrawingBuffer::~DrawingBuffer()
+{
+}
- static double accelerationTime();
- static const double animationTimerDelay;
+#if USE(ACCELERATED_COMPOSITING)
+void DrawingBuffer::prepareBackBuffer()
+{
+}
- void animationTimerFired(Timer<ScrollAnimatorWin>*);
- void stopAnimationTimerIfNeeded(PerAxisData*);
- void animateScroll(PerAxisData*);
+bool DrawingBuffer::requiresCopyFromBackToFrontBuffer() const
+{
+ return false;
+}
- PerAxisData m_horizontalData;
- PerAxisData m_verticalData;
-};
+unsigned DrawingBuffer::frontColorBuffer() const
+{
+ return colorBuffer();
+}
-} // namespace WebCore
+void DrawingBuffer::paintCompositedResultsToCanvas(CanvasRenderingContext* context)
+{
+}
+#endif
-#endif // ENABLE(SMOOTH_SCROLLING)
+}
-#endif // ScrollAnimatorWin_h
+#endif
diff --git a/Source/WebCore/platform/graphics/clutter/GraphicsContext3DClutter.cpp b/Source/WebCore/platform/graphics/clutter/GraphicsContext3DClutter.cpp
new file mode 100644
index 000000000..ca0ffdc2b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/clutter/GraphicsContext3DClutter.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2011 Igalia S.L.
+ * Copyright (C) 2012 Collabora Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "GraphicsContext3D.h"
+
+#if ENABLE(WEBGL)
+
+#include "Extensions3DOpenGL.h"
+#include "GraphicsContext3DPrivate.h"
+#include "NotImplemented.h"
+#include <wtf/NotFound.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attributes, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle)
+{
+ RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(attributes, hostWindow, false));
+ return context.release();
+}
+
+GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attributes, HostWindow* hostWindow, bool)
+{
+ notImplemented();
+}
+
+GraphicsContext3D::~GraphicsContext3D()
+{
+ notImplemented();
+}
+
+bool GraphicsContext3D::getImageData(Image* image, unsigned int format, unsigned int type, bool premultiplyAlpha, bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector)
+{
+ notImplemented();
+ return false;
+}
+
+void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, PlatformContextCairo* context)
+{
+ notImplemented();
+}
+
+void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>)
+{
+}
+
+void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<ErrorMessageCallback>)
+{
+}
+
+bool GraphicsContext3D::makeContextCurrent()
+{
+ if (!m_private)
+ return false;
+ return m_private->makeContextCurrent();
+}
+PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D()
+{
+ return m_private->platformContext();
+}
+
+bool GraphicsContext3D::isGLES2Compliant() const
+{
+ return false;
+}
+
+#if USE(ACCELERATED_COMPOSITING)
+PlatformLayer* GraphicsContext3D::platformLayer() const
+{
+ return m_private->platformLayer();
+}
+#endif
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/clutter/GraphicsContext3DPrivate.cpp b/Source/WebCore/platform/graphics/clutter/GraphicsContext3DPrivate.cpp
new file mode 100644
index 000000000..cad170fb0
--- /dev/null
+++ b/Source/WebCore/platform/graphics/clutter/GraphicsContext3DPrivate.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011, 2012 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "GraphicsContext3DPrivate.h"
+
+#if ENABLE(WEBGL)
+
+#include "HostWindow.h"
+#include "NotImplemented.h"
+
+
+namespace WebCore {
+
+PassOwnPtr<GraphicsContext3DPrivate> GraphicsContext3DPrivate::create(GraphicsContext3D* context, HostWindow* window)
+{
+ return adoptPtr(new GraphicsContext3DPrivate(context, window));
+}
+
+GraphicsContext3DPrivate::GraphicsContext3DPrivate(GraphicsContext3D* context, HostWindow* window)
+ : m_context(context)
+ , m_window(window)
+{
+}
+
+GraphicsContext3DPrivate::~GraphicsContext3DPrivate()
+{
+}
+
+bool GraphicsContext3DPrivate::makeContextCurrent()
+{
+ return false;
+}
+
+PlatformGraphicsContext3D GraphicsContext3DPrivate::platformContext()
+{
+ return 0;
+}
+
+#if USE(ACCELERATED_COMPOSITING) && USE(CLUTTER)
+void GraphicsContext3DPrivate::paintToGraphicsLayerActor(ClutterActor*, const FloatRect& target, const TransformationMatrix& matrix, float opacity)
+{
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
+} // namespace WebCore
+
+#endif // ENABLE_WEBGL
diff --git a/Source/WebCore/platform/graphics/clutter/GraphicsContext3DPrivate.h b/Source/WebCore/platform/graphics/clutter/GraphicsContext3DPrivate.h
new file mode 100644
index 000000000..570f82f5c
--- /dev/null
+++ b/Source/WebCore/platform/graphics/clutter/GraphicsContext3DPrivate.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 Igalia S.L.
+ * Copyright (C) 2012 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef GraphicsContext3DPrivate_h
+#define GraphicsContext3DPrivate_h
+
+#include "GraphicsContext3D.h"
+#include <wtf/PassOwnPtr.h>
+
+#if USE(ACCELERATED_COMPOSITING) && USE(CLUTTER)
+#include <clutter/clutter.h>
+#endif
+
+namespace WebCore {
+
+class GraphicsContext3DPrivate {
+public:
+ static PassOwnPtr<GraphicsContext3DPrivate> create(GraphicsContext3D*, HostWindow*);
+ ~GraphicsContext3DPrivate();
+ bool makeContextCurrent();
+ PlatformGraphicsContext3D platformContext();
+ ClutterActor* platformLayer() { return m_layer; }
+
+#if USE(ACCELERATED_COMPOSITING) && USE(CLUTTER)
+ virtual void paintToGraphicsLayerActor(ClutterActor*, const FloatRect& target, const TransformationMatrix&, float opacity);
+#endif
+
+private:
+ GraphicsContext3DPrivate(GraphicsContext3D*, HostWindow*);
+
+ GraphicsContext3D* m_context;
+ HostWindow* m_window;
+ ClutterActor* m_layer;
+};
+
+}
+
+#endif // GraphicsContext3DPrivate_h
diff --git a/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp b/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp
index 56ae61024..eda14d037 100644
--- a/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp
+++ b/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp
@@ -47,6 +47,7 @@ GraphicsLayerClutter::GraphicsLayerClutter(GraphicsLayerClient* client)
GraphicsLayerClutter::~GraphicsLayerClutter()
{
+ willBeDestroyed();
}
ClutterActor* GraphicsLayerClutter::platformLayer() const
diff --git a/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm b/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm
index 7b1360883..d1099669a 100644
--- a/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm
+++ b/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm
@@ -41,7 +41,7 @@ void FontPlatformData::loadFont(NSFont* nsFont, float, NSFont*& outNSFont, CGFon
}
#endif // PLATFORM(MAC)
-FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation,
+FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool isPrinterFont, bool syntheticBold, bool syntheticOblique, FontOrientation orientation,
TextOrientation textOrientation, FontWidthVariant widthVariant)
: m_syntheticBold(syntheticBold)
, m_syntheticOblique(syntheticOblique)
@@ -50,18 +50,26 @@ FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool syntheticBol
, m_size(size)
, m_widthVariant(widthVariant)
, m_font(nsFont)
-#if !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
- // have blocked font loading, in which case we'll only have the real loaded font file after the call to loadFont().
- , m_isColorBitmapFont(CTFontGetSymbolicTraits(toCTFontRef(nsFont)) & kCTFontColorGlyphsTrait)
-#else
, m_isColorBitmapFont(false)
-#endif
+ , m_isCompositeFontReference(false)
+ , m_isPrinterFont(isPrinterFont)
{
ASSERT_ARG(nsFont, nsFont);
CGFontRef cgFont = 0;
loadFont(nsFont, size, m_font, cgFont);
+
+#if !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
+ // have blocked font loading, in which case we'll only have the real loaded font file after the call to loadFont().
+ {
+ CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(toCTFontRef(m_font));
+ m_isColorBitmapFont = traits & kCTFontColorGlyphsTrait;
+#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) && !PLATFORM(IOS)
+ m_isCompositeFontReference = traits & kCTFontCompositeTrait;
+#endif
+ }
+#endif
if (m_font)
CFRetain(m_font);
@@ -141,7 +149,13 @@ void FontPlatformData::setFont(NSFont *font)
m_cgFont.adoptCF(cgFont);
#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
- m_isColorBitmapFont = CTFontGetSymbolicTraits(toCTFontRef(m_font)) & kCTFontColorGlyphsTrait;
+ {
+ CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(toCTFontRef(m_font));
+ m_isColorBitmapFont = traits & kCTFontColorGlyphsTrait;
+#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION)
+ m_isCompositeFontReference = traits & kCTFontCompositeTrait;
+#endif
+ }
#endif
m_CTFont = 0;
}
@@ -247,6 +261,13 @@ CTFontRef FontPlatformData::ctFont() const
if (m_CTFont)
return m_CTFont.get();
+#if PLATFORM(CHROMIUM)
+ if (m_inMemoryFont) {
+ m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_inMemoryFont->cgFont(), m_size, 0, canSetCascadeListForCustomFont() ? cascadeToLastResortFontDescriptor() : 0));
+ return m_CTFont.get();
+ }
+#endif
+
m_CTFont = toCTFontRef(m_font);
if (m_CTFont) {
CTFontDescriptorRef fontDescriptor;
diff --git a/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp b/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp
index 08153f004..e51ddc1b4 100644
--- a/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp
+++ b/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp
@@ -139,7 +139,7 @@ bool GraphicsContext3DPrivate::createSurface(PageClientEfl* pageClient, bool ren
evas_gl_native_surface_get(m_evasGL, m_surface, &nativeSurface);
// Create and specially set up a evas_object which act as the render targer surface.
- if (!pageClient->createEvasObjectForAcceleratedCompositing(&nativeSurface, x, y, width, height))
+ if (!pageClient->createEvasObjectForAcceleratedCompositing(&nativeSurface, IntRect(x, y, width, height)))
return false;
}
#endif
diff --git a/Source/WebCore/platform/graphics/efl/GraphicsLayerEfl.cpp b/Source/WebCore/platform/graphics/efl/GraphicsLayerEfl.cpp
index adb9d6416..a566bd064 100644
--- a/Source/WebCore/platform/graphics/efl/GraphicsLayerEfl.cpp
+++ b/Source/WebCore/platform/graphics/efl/GraphicsLayerEfl.cpp
@@ -39,6 +39,7 @@ GraphicsLayerEfl::GraphicsLayerEfl(GraphicsLayerClient* client)
GraphicsLayerEfl::~GraphicsLayerEfl()
{
+ willBeDestroyed();
}
void GraphicsLayerEfl::setNeedsDisplay()
diff --git a/Source/WebCore/platform/graphics/efl/IconEfl.cpp b/Source/WebCore/platform/graphics/efl/IconEfl.cpp
index 6b3de04cd..304a17eaa 100644
--- a/Source/WebCore/platform/graphics/efl/IconEfl.cpp
+++ b/Source/WebCore/platform/graphics/efl/IconEfl.cpp
@@ -37,8 +37,8 @@
#include "GraphicsContext.h"
#include "MIMETypeRegistry.h"
#include "NotImplemented.h"
-#include "PassRefPtr.h"
#include "PlatformString.h"
+#include <wtf/PassRefPtr.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterNumberParameter.h b/Source/WebCore/platform/graphics/filters/CustomFilterNumberParameter.h
index 0ade173f2..2770b4ced 100644
--- a/Source/WebCore/platform/graphics/filters/CustomFilterNumberParameter.h
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterNumberParameter.h
@@ -48,6 +48,27 @@ public:
void addValue(double value) { m_data.append(value); }
+ virtual PassRefPtr<CustomFilterParameter> blend(const CustomFilterParameter* from, double progress)
+ {
+ if (!from || !isSameType(*from))
+ return this;
+ const CustomFilterNumberParameter* fromNumber = static_cast<const CustomFilterNumberParameter*>(from);
+ if (size() != fromNumber->size())
+ return this;
+ RefPtr<CustomFilterNumberParameter> result = CustomFilterNumberParameter::create(name());
+ for (size_t i = 0; i < size(); ++i)
+ result->addValue(WebCore::blend(fromNumber->valueAt(i), valueAt(i), progress));
+ return result.release();
+ }
+
+ virtual bool operator==(const CustomFilterParameter& o) const
+ {
+ if (!isSameType(o))
+ return false;
+ const CustomFilterNumberParameter* other = static_cast<const CustomFilterNumberParameter*>(&o);
+ return m_data == other->m_data;
+ }
+
private:
CustomFilterNumberParameter(const String& name)
: CustomFilterParameter(NUMBER, name)
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterOperation.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterOperation.cpp
index c05a40f62..f5c81724f 100644
--- a/Source/WebCore/platform/graphics/filters/CustomFilterOperation.cpp
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterOperation.cpp
@@ -40,6 +40,60 @@
namespace WebCore {
+bool customFilterParametersEqual(const CustomFilterParameterList& listA, const CustomFilterParameterList& listB)
+{
+ if (listA.size() != listB.size())
+ return false;
+ for (size_t i = 0; i < listA.size(); ++i) {
+ if (listA.at(i).get() != listB.at(i).get()
+ && *listA.at(i).get() != *listB.at(i).get())
+ return false;
+ }
+ return true;
+}
+
+#if !ASSERT_DISABLED
+static bool checkCustomFilterParametersOrder(const CustomFilterParameterList& parameters)
+{
+ for (unsigned i = 1; i < parameters.size(); ++i) {
+ // Break for equal or not-sorted parameters.
+ if (!codePointCompareLessThan(parameters.at(i - 1)->name(), parameters.at(i)->name()))
+ return false;
+ }
+ return true;
+}
+#endif
+
+void blendCustomFilterParameters(const CustomFilterParameterList& fromList, const CustomFilterParameterList& toList, double progress, CustomFilterParameterList& resultList)
+{
+ // This method expects both lists to be sorted by parameter name and the result list is also sorted.
+ ASSERT(checkCustomFilterParametersOrder(fromList));
+ ASSERT(checkCustomFilterParametersOrder(toList));
+ size_t fromListIndex = 0, toListIndex = 0;
+ while (fromListIndex < fromList.size() && toListIndex < toList.size()) {
+ CustomFilterParameter* paramFrom = fromList.at(fromListIndex).get();
+ CustomFilterParameter* paramTo = toList.at(toListIndex).get();
+ if (paramFrom->name() == paramTo->name()) {
+ resultList.append(paramTo->blend(paramFrom, progress));
+ ++fromListIndex;
+ ++toListIndex;
+ continue;
+ }
+ if (codePointCompareLessThan(paramFrom->name(), paramTo->name())) {
+ resultList.append(paramFrom);
+ ++fromListIndex;
+ continue;
+ }
+ resultList.append(paramTo);
+ ++toListIndex;
+ }
+ for (; fromListIndex < fromList.size(); ++fromListIndex)
+ resultList.append(fromList.at(fromListIndex));
+ for (; toListIndex < toList.size(); ++toListIndex)
+ resultList.append(toList.at(toListIndex));
+ ASSERT(checkCustomFilterParametersOrder(resultList));
+}
+
CustomFilterOperation::CustomFilterOperation(PassRefPtr<CustomFilterProgram> program, const CustomFilterParameterList& sortedParameters, unsigned meshRows, unsigned meshColumns, MeshBoxType meshBoxType, MeshType meshType)
: FilterOperation(CUSTOM)
, m_program(program)
@@ -50,24 +104,33 @@ CustomFilterOperation::CustomFilterOperation(PassRefPtr<CustomFilterProgram> pro
, m_meshType(meshType)
{
// Make sure that the parameters are alwyas sorted by name. We use that to merge two CustomFilterOperations in animations.
- ASSERT(hasSortedParameterList());
+ ASSERT(checkCustomFilterParametersOrder(m_parameters));
}
CustomFilterOperation::~CustomFilterOperation()
{
}
-#ifndef NDEBUG
-bool CustomFilterOperation::hasSortedParameterList()
+PassRefPtr<FilterOperation> CustomFilterOperation::blend(const FilterOperation* from, double progress, bool blendToPassthrough)
{
- for (unsigned i = 1; i < m_parameters.size(); ++i) {
- // Break for equal or not-sorted parameters.
- if (!codePointCompareLessThan(m_parameters.at(i - i)->name(), m_parameters.at(i)->name()))
- return false;
- }
- return true;
+ // FIXME: There's no way to decide what is the "passthrough filter" for shaders using the current CSS Syntax.
+ // https://bugs.webkit.org/show_bug.cgi?id=84903
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=16861
+ if (blendToPassthrough || !from || !from->isSameType(*this))
+ return this;
+
+ const CustomFilterOperation* fromOp = static_cast<const CustomFilterOperation*>(from);
+ if (*m_program.get() != *fromOp->m_program.get()
+ || m_meshRows != fromOp->m_meshRows
+ || m_meshColumns != fromOp->m_meshColumns
+ || m_meshBoxType != fromOp->m_meshBoxType
+ || m_meshType != fromOp->m_meshType)
+ return this;
+
+ CustomFilterParameterList animatedParameters;
+ blendCustomFilterParameters(fromOp->m_parameters, m_parameters, progress, animatedParameters);
+ return CustomFilterOperation::create(m_program, animatedParameters, m_meshRows, m_meshColumns, m_meshBoxType, m_meshType);
}
-#endif
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterOperation.h b/Source/WebCore/platform/graphics/filters/CustomFilterOperation.h
index 4d8392682..63507f561 100644
--- a/Source/WebCore/platform/graphics/filters/CustomFilterOperation.h
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterOperation.h
@@ -43,6 +43,9 @@ namespace WebCore {
class CustomFilterParameter;
typedef Vector<RefPtr<CustomFilterParameter> > CustomFilterParameterList;
+bool customFilterParametersEqual(const CustomFilterParameterList&, const CustomFilterParameterList&);
+void blendCustomFilterParameters(const CustomFilterParameterList& listFrom, const CustomFilterParameterList& listTo, double progress, CustomFilterParameterList& resultList);
+
class CustomFilterOperation : public FilterOperation {
public:
enum MeshBoxType {
@@ -62,6 +65,13 @@ public:
return adoptRef(new CustomFilterOperation(program, sortedParameters, meshRows, meshColumns, meshBoxType, meshType));
}
+ virtual PassRefPtr<FilterOperation> clone() const
+ {
+ // Some member vars (e.g., m_program) are not thread-safe, so
+ // we can't be cloned.
+ return 0;
+ }
+
CustomFilterProgram* program() const { return m_program.get(); }
const CustomFilterParameterList& parameters() { return m_parameters; }
@@ -74,6 +84,10 @@ public:
virtual ~CustomFilterOperation();
+ virtual bool affectsOpacity() const { return true; }
+ virtual bool movesPixels() const { return true; }
+
+ virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false);
private:
virtual bool operator==(const FilterOperation& o) const
{
@@ -81,18 +95,15 @@ private:
return false;
const CustomFilterOperation* other = static_cast<const CustomFilterOperation*>(&o);
- return m_program.get() == other->m_program.get()
+ return *m_program.get() == *other->m_program.get()
&& m_meshRows == other->m_meshRows
&& m_meshColumns == other->m_meshColumns
&& m_meshBoxType == other->m_meshBoxType
- && m_meshType == other->m_meshType;
+ && m_meshType == other->m_meshType
+ && customFilterParametersEqual(m_parameters, other->m_parameters);
}
CustomFilterOperation(PassRefPtr<CustomFilterProgram>, const CustomFilterParameterList&, unsigned meshRows, unsigned meshColumns, MeshBoxType, MeshType);
-
-#ifndef NDEBUG
- bool hasSortedParameterList();
-#endif
RefPtr<CustomFilterProgram> m_program;
CustomFilterParameterList m_parameters;
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterParameter.h b/Source/WebCore/platform/graphics/filters/CustomFilterParameter.h
index e9c062952..e66e2298a 100644
--- a/Source/WebCore/platform/graphics/filters/CustomFilterParameter.h
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterParameter.h
@@ -52,7 +52,12 @@ public:
ParameterType parameterType() const { return m_type; }
const String& name() const { return m_name; }
-
+
+ bool isSameType(const CustomFilterParameter& other) const { return parameterType() == other.parameterType(); }
+
+ virtual PassRefPtr<CustomFilterParameter> blend(const CustomFilterParameter*, double progress) = 0;
+ virtual bool operator==(const CustomFilterParameter&) const = 0;
+ bool operator!=(const CustomFilterParameter& o) const { return !(*this == o); }
protected:
CustomFilterParameter(ParameterType type, const String& name)
: m_name(name)
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h
index 84e6c205a..e08cbb76e 100644
--- a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h
@@ -56,6 +56,11 @@ public:
#if ENABLE(WEBGL)
PassRefPtr<CustomFilterShader> createShaderWithContext(GraphicsContext3D*);
#endif
+
+ // StyleCustomFilterProgram has the only implementation for the following method. That means, it casts to StyleCustomFilterProgram
+ // withouth checking the type. If you add another implementation, also add a mechanism to check for the correct type.
+ virtual bool operator==(const CustomFilterProgram&) const = 0;
+ bool operator!=(const CustomFilterProgram& o) const { return !(*this == o); }
protected:
// StyleCustomFilterProgram can notify the clients that the cached resources are
// loaded and it is ready to create CustomFilterShader objects.
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterShader.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterShader.cpp
index 8ef66cfa3..511c22413 100644
--- a/Source/WebCore/platform/graphics/filters/CustomFilterShader.cpp
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterShader.cpp
@@ -59,10 +59,10 @@ String CustomFilterShader::defaultFragmentShaderString()
DEFINE_STATIC_LOCAL(String, fragmentShaderString, SHADER(
precision mediump float;
varying vec2 v_texCoord;
- uniform sampler2D s_texture;
+ uniform sampler2D u_texture;
void main()
{
- gl_FragColor = texture2D(s_texture, v_texCoord);
+ gl_FragColor = texture2D(u_texture, v_texCoord);
}
));
return fragmentShaderString;
@@ -156,9 +156,9 @@ void CustomFilterShader::initializeParameterLocations()
m_tileSizeLocation = m_context->getUniformLocation(m_program, "u_tileSize");
m_meshSizeLocation = m_context->getUniformLocation(m_program, "u_meshSize");
m_projectionMatrixLocation = m_context->getUniformLocation(m_program, "u_projectionMatrix");
- m_samplerLocation = m_context->getUniformLocation(m_program, "s_texture");
- m_samplerSizeLocation = m_context->getUniformLocation(m_program, "s_textureSize");
- m_contentSamplerLocation = m_context->getUniformLocation(m_program, "s_contentTexture");
+ m_samplerLocation = m_context->getUniformLocation(m_program, "u_texture");
+ m_samplerSizeLocation = m_context->getUniformLocation(m_program, "u_textureSize");
+ m_contentSamplerLocation = m_context->getUniformLocation(m_program, "u_contentTexture");
}
int CustomFilterShader::uniformLocationByName(const String& name)
diff --git a/Source/WebCore/platform/graphics/filters/FEBlend.cpp b/Source/WebCore/platform/graphics/filters/FEBlend.cpp
index 530636da9..aa733d90f 100644
--- a/Source/WebCore/platform/graphics/filters/FEBlend.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEBlend.cpp
@@ -31,7 +31,7 @@
#include "RenderTreeAsText.h"
#include "TextStream.h"
-#include <wtf/ByteArray.h>
+#include <wtf/Uint8ClampedArray.h>
typedef unsigned char (*BlendType)(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB);
@@ -94,24 +94,24 @@ void FEBlend::platformApplySoftware()
ASSERT(m_mode > FEBLEND_MODE_UNKNOWN);
ASSERT(m_mode <= FEBLEND_MODE_LIGHTEN);
- ByteArray* dstPixelArray = createPremultipliedImageResult();
+ Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
if (!dstPixelArray)
return;
IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- RefPtr<ByteArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect);
+ RefPtr<Uint8ClampedArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect);
IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
- RefPtr<ByteArray> srcPixelArrayB = in2->asPremultipliedImage(effectBDrawingRect);
+ RefPtr<Uint8ClampedArray> srcPixelArrayB = in2->asPremultipliedImage(effectBDrawingRect);
unsigned pixelArrayLength = srcPixelArrayA->length();
ASSERT(pixelArrayLength == srcPixelArrayB->length());
for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) {
- unsigned char alphaA = srcPixelArrayA->get(pixelOffset + 3);
- unsigned char alphaB = srcPixelArrayB->get(pixelOffset + 3);
+ unsigned char alphaA = srcPixelArrayA->item(pixelOffset + 3);
+ unsigned char alphaB = srcPixelArrayB->item(pixelOffset + 3);
for (unsigned channel = 0; channel < 3; ++channel) {
- unsigned char colorA = srcPixelArrayA->get(pixelOffset + channel);
- unsigned char colorB = srcPixelArrayB->get(pixelOffset + channel);
+ unsigned char colorA = srcPixelArrayA->item(pixelOffset + channel);
+ unsigned char colorB = srcPixelArrayB->item(pixelOffset + channel);
unsigned char result;
switch (m_mode) {
diff --git a/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp
index 00b600abd..bd4212d0b 100644
--- a/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp
@@ -30,8 +30,8 @@
#include "RenderTreeAsText.h"
#include "TextStream.h"
-#include <wtf/ByteArray.h>
#include <wtf/MathExtras.h>
+#include <wtf/Uint8ClampedArray.h>
namespace WebCore {
@@ -125,14 +125,14 @@ inline void luminance(double& red, double& green, double& blue, double& alpha)
}
template<ColorMatrixType filterType>
-void effectType(ByteArray* pixelArray, const Vector<float>& values)
+void effectType(Uint8ClampedArray* pixelArray, const Vector<float>& values)
{
unsigned pixelArrayLength = pixelArray->length();
for (unsigned pixelByteOffset = 0; pixelByteOffset < pixelArrayLength; pixelByteOffset += 4) {
- double red = pixelArray->get(pixelByteOffset);
- double green = pixelArray->get(pixelByteOffset + 1);
- double blue = pixelArray->get(pixelByteOffset + 2);
- double alpha = pixelArray->get(pixelByteOffset + 3);
+ double red = pixelArray->item(pixelByteOffset);
+ double green = pixelArray->item(pixelByteOffset + 1);
+ double blue = pixelArray->item(pixelByteOffset + 2);
+ double alpha = pixelArray->item(pixelByteOffset + 3);
switch (filterType) {
case FECOLORMATRIX_TYPE_MATRIX:
@@ -167,7 +167,7 @@ void FEColorMatrix::platformApplySoftware()
resultImage->context()->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
IntRect imageRect(IntPoint(), absolutePaintRect().size());
- RefPtr<ByteArray> pixelArray = resultImage->getUnmultipliedImageData(imageRect);
+ RefPtr<Uint8ClampedArray> pixelArray = resultImage->getUnmultipliedImageData(imageRect);
switch (m_type) {
case FECOLORMATRIX_TYPE_UNKNOWN:
diff --git a/Source/WebCore/platform/graphics/filters/FEComponentTransfer.cpp b/Source/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
index 8db62dc4d..651bac2e1 100644
--- a/Source/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
@@ -31,9 +31,9 @@
#include "RenderTreeAsText.h"
#include "TextStream.h"
-#include <wtf/ByteArray.h>
#include <wtf/MathExtras.h>
#include <wtf/StdLibExtras.h>
+#include <wtf/Uint8ClampedArray.h>
namespace WebCore {
@@ -154,7 +154,7 @@ void FEComponentTransfer::platformApplySoftware()
{
FilterEffect* in = inputEffect(0);
- ByteArray* pixelArray = createUnmultipliedImageResult();
+ Uint8ClampedArray* pixelArray = createUnmultipliedImageResult();
if (!pixelArray)
return;
@@ -176,7 +176,7 @@ void FEComponentTransfer::platformApplySoftware()
unsigned pixelArrayLength = pixelArray->length();
for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) {
for (unsigned channel = 0; channel < 4; ++channel) {
- unsigned char c = pixelArray->get(pixelOffset + channel);
+ unsigned char c = pixelArray->item(pixelOffset + channel);
pixelArray->set(pixelOffset + channel, tables[channel][c]);
}
}
diff --git a/Source/WebCore/platform/graphics/filters/FEComposite.cpp b/Source/WebCore/platform/graphics/filters/FEComposite.cpp
index 5be22f8e2..57101af7f 100644
--- a/Source/WebCore/platform/graphics/filters/FEComposite.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEComposite.cpp
@@ -32,7 +32,7 @@
#include "RenderTreeAsText.h"
#include "TextStream.h"
-#include <wtf/ByteArray.h>
+#include <wtf/Uint8ClampedArray.h>
namespace WebCore {
@@ -179,7 +179,7 @@ static inline void arithmeticSoftware(unsigned char* source, unsigned char* dest
computeArithmeticPixels<1, 1, 1, 1>(source, destination, pixelArrayLength, k1, k2, k3, k4);
}
-inline void FEComposite::platformArithmeticSoftware(ByteArray* source, ByteArray* destination,
+inline void FEComposite::platformArithmeticSoftware(Uint8ClampedArray* source, Uint8ClampedArray* destination,
float k1, float k2, float k3, float k4)
{
int length = source->length();
@@ -221,12 +221,12 @@ void FEComposite::platformApplySoftware()
FilterEffect* in2 = inputEffect(1);
if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC) {
- ByteArray* dstPixelArray = createPremultipliedImageResult();
+ Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
if (!dstPixelArray)
return;
IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- RefPtr<ByteArray> srcPixelArray = in->asPremultipliedImage(effectADrawingRect);
+ RefPtr<Uint8ClampedArray> srcPixelArray = in->asPremultipliedImage(effectADrawingRect);
IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
in2->copyPremultipliedImage(dstPixelArray, effectBDrawingRect);
diff --git a/Source/WebCore/platform/graphics/filters/FEComposite.h b/Source/WebCore/platform/graphics/filters/FEComposite.h
index 24ba3078f..42695f6c2 100644
--- a/Source/WebCore/platform/graphics/filters/FEComposite.h
+++ b/Source/WebCore/platform/graphics/filters/FEComposite.h
@@ -74,7 +74,7 @@ protected:
private:
FEComposite(Filter*, const CompositeOperationType&, float, float, float, float);
- inline void platformArithmeticSoftware(ByteArray* source, ByteArray* destination, float k1, float k2, float k3, float k4);
+ inline void platformArithmeticSoftware(Uint8ClampedArray* source, Uint8ClampedArray* destination, float k1, float k2, float k3, float k4);
inline void platformArithmeticNeon(unsigned char* source, unsigned char* destination, unsigned pixelArrayLength, float* kArray);
CompositeOperationType m_type;
diff --git a/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp b/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp
index cda5f193e..a4a6f9ed3 100644
--- a/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp
@@ -30,8 +30,8 @@
#include "RenderTreeAsText.h"
#include "TextStream.h"
-#include <wtf/ByteArray.h>
#include <wtf/ParallelJobs.h>
+#include <wtf/Uint8ClampedArray.h>
namespace WebCore {
@@ -48,6 +48,8 @@ FEConvolveMatrix::FEConvolveMatrix(Filter* filter, const IntSize& kernelSize,
, m_preserveAlpha(preserveAlpha)
, m_kernelMatrix(kernelMatrix)
{
+ ASSERT(m_kernelSize.width() > 0);
+ ASSERT(m_kernelSize.height() > 0);
}
PassRefPtr<FEConvolveMatrix> FEConvolveMatrix::create(Filter* filter, const IntSize& kernelSize,
@@ -66,7 +68,9 @@ IntSize FEConvolveMatrix::kernelSize() const
void FEConvolveMatrix::setKernelSize(const IntSize& kernelSize)
{
- m_kernelSize = kernelSize;
+ ASSERT(kernelSize.width() > 0);
+ ASSERT(kernelSize.height() > 0);
+ m_kernelSize = kernelSize;
}
const Vector<float>& FEConvolveMatrix::kernel() const
@@ -86,6 +90,7 @@ float FEConvolveMatrix::divisor() const
bool FEConvolveMatrix::setDivisor(float divisor)
{
+ ASSERT(divisor);
if (m_divisor == divisor)
return false;
m_divisor = divisor;
@@ -138,6 +143,8 @@ FloatPoint FEConvolveMatrix::kernelUnitLength() const
bool FEConvolveMatrix::setKernelUnitLength(const FloatPoint& kernelUnitLength)
{
+ ASSERT(kernelUnitLength.x() > 0);
+ ASSERT(kernelUnitLength.y() > 0);
if (m_kernelUnitLength == kernelUnitLength)
return false;
m_kernelUnitLength = kernelUnitLength;
@@ -223,14 +230,14 @@ static ALWAYS_INLINE unsigned char clampRGBAValue(float channel, unsigned char m
}
template<bool preserveAlphaValues>
-ALWAYS_INLINE void setDestinationPixels(ByteArray* image, int& pixel, float* totals, float divisor, float bias, ByteArray* src)
+ALWAYS_INLINE void setDestinationPixels(Uint8ClampedArray* image, int& pixel, float* totals, float divisor, float bias, Uint8ClampedArray* src)
{
unsigned char maxAlpha = preserveAlphaValues ? 255 : clampRGBAValue(totals[3] / divisor + bias);
for (int i = 0; i < 3; ++i)
image->set(pixel++, clampRGBAValue(totals[i] / divisor + bias, maxAlpha));
if (preserveAlphaValues) {
- image->set(pixel, src->get(pixel));
+ image->set(pixel, src->item(pixel));
++pixel;
} else
image->set(pixel++, maxAlpha);
@@ -267,11 +274,11 @@ ALWAYS_INLINE void FEConvolveMatrix::fastSetInteriorPixels(PaintingData& paintin
totals[3] = 0;
while (kernelValue >= 0) {
- totals[0] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(kernelPixel++));
- totals[1] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(kernelPixel++));
- totals[2] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(kernelPixel++));
+ totals[0] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(kernelPixel++));
+ totals[1] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(kernelPixel++));
+ totals[2] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(kernelPixel++));
if (!preserveAlphaValues)
- totals[3] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(kernelPixel));
+ totals[3] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(kernelPixel));
++kernelPixel;
--kernelValue;
if (!--width) {
@@ -350,12 +357,12 @@ void FEConvolveMatrix::fastSetOuterPixels(PaintingData& paintingData, int x1, in
while (kernelValue >= 0) {
int pixelIndex = getPixelValue(paintingData, kernelPixelX, kernelPixelY);
if (pixelIndex >= 0) {
- totals[0] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(pixelIndex));
- totals[1] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(pixelIndex + 1));
- totals[2] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(pixelIndex + 2));
+ totals[0] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(pixelIndex));
+ totals[1] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(pixelIndex + 1));
+ totals[2] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(pixelIndex + 2));
}
if (!preserveAlphaValues && pixelIndex >= 0)
- totals[3] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(pixelIndex + 3));
+ totals[3] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(pixelIndex + 3));
++kernelPixelX;
--kernelValue;
if (!--width) {
@@ -403,7 +410,7 @@ void FEConvolveMatrix::platformApplySoftware()
{
FilterEffect* in = inputEffect(0);
- ByteArray* resultImage;
+ Uint8ClampedArray* resultImage;
if (m_preserveAlpha)
resultImage = createUnmultipliedImageResult();
else
@@ -413,7 +420,7 @@ void FEConvolveMatrix::platformApplySoftware()
IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- RefPtr<ByteArray> srcPixelArray;
+ RefPtr<Uint8ClampedArray> srcPixelArray;
if (m_preserveAlpha)
srcPixelArray = in->asUnmultipliedImage(effectDrawingRect);
else
diff --git a/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.h b/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.h
index 34baf6f17..81eba1d83 100644
--- a/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.h
+++ b/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.h
@@ -40,8 +40,6 @@ enum EdgeModeType {
EDGEMODE_NONE = 3
};
-class CanvasPixelArray;
-
class FEConvolveMatrix : public FilterEffect {
public:
static PassRefPtr<FEConvolveMatrix> create(Filter*, const IntSize&,
@@ -82,8 +80,8 @@ public:
private:
struct PaintingData {
- ByteArray* srcPixelArray;
- ByteArray* dstPixelArray;
+ Uint8ClampedArray* srcPixelArray;
+ Uint8ClampedArray* dstPixelArray;
int width;
int height;
float bias;
diff --git a/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp b/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp
index 9bf2495c0..89223bb19 100644
--- a/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp
+++ b/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp
@@ -32,25 +32,21 @@
#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL)
#include "FECustomFilter.h"
-#include "CachedShader.h"
#include "CustomFilterMesh.h"
#include "CustomFilterNumberParameter.h"
#include "CustomFilterParameter.h"
#include "CustomFilterProgram.h"
#include "CustomFilterShader.h"
-#include "Document.h"
#include "DrawingBuffer.h"
-#include "FrameView.h"
#include "GraphicsContext3D.h"
#include "ImageData.h"
#include "RenderTreeAsText.h"
-#include "StyleCachedShader.h"
#include "TextStream.h"
#include "Texture.h"
#include "TilingData.h"
#include "TransformationMatrix.h"
-#include <wtf/ByteArray.h>
+#include <wtf/Uint8ClampedArray.h>
namespace WebCore {
@@ -76,11 +72,11 @@ static void orthogonalProjectionMatrix(TransformationMatrix& matrix, float left,
matrix.setM44(1.0f);
}
-FECustomFilter::FECustomFilter(Filter* filter, Document* document, PassRefPtr<CustomFilterProgram> program, const CustomFilterParameterList& parameters,
+FECustomFilter::FECustomFilter(Filter* filter, HostWindow* hostWindow, PassRefPtr<CustomFilterProgram> program, const CustomFilterParameterList& parameters,
unsigned meshRows, unsigned meshColumns, CustomFilterOperation::MeshBoxType meshBoxType,
CustomFilterOperation::MeshType meshType)
: FilterEffect(filter)
- , m_document(document)
+ , m_hostWindow(hostWindow)
, m_program(program)
, m_parameters(parameters)
, m_meshRows(meshRows)
@@ -90,22 +86,22 @@ FECustomFilter::FECustomFilter(Filter* filter, Document* document, PassRefPtr<Cu
{
}
-PassRefPtr<FECustomFilter> FECustomFilter::create(Filter* filter, Document* document, PassRefPtr<CustomFilterProgram> program, const CustomFilterParameterList& parameters,
+PassRefPtr<FECustomFilter> FECustomFilter::create(Filter* filter, HostWindow* hostWindow, PassRefPtr<CustomFilterProgram> program, const CustomFilterParameterList& parameters,
unsigned meshRows, unsigned meshColumns, CustomFilterOperation::MeshBoxType meshBoxType,
CustomFilterOperation::MeshType meshType)
{
- return adoptRef(new FECustomFilter(filter, document, program, parameters, meshRows, meshColumns, meshBoxType, meshType));
+ return adoptRef(new FECustomFilter(filter, hostWindow, program, parameters, meshRows, meshColumns, meshBoxType, meshType));
}
void FECustomFilter::platformApplySoftware()
{
- ByteArray* dstPixelArray = createPremultipliedImageResult();
+ Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
if (!dstPixelArray)
return;
FilterEffect* in = inputEffect(0);
IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- RefPtr<ByteArray> srcPixelArray = in->asPremultipliedImage(effectDrawingRect);
+ RefPtr<Uint8ClampedArray> srcPixelArray = in->asPremultipliedImage(effectDrawingRect);
IntSize newContextSize(effectDrawingRect.size());
bool hadContext = m_context;
@@ -116,7 +112,7 @@ void FECustomFilter::platformApplySoftware()
resizeContext(newContextSize);
// Do not draw the filter if the input image cannot fit inside a single GPU texture.
- if (m_inputTexture->tiles().numTiles() != 1)
+ if (m_inputTexture->tiles().numTilesX() != 1 || m_inputTexture->tiles().numTilesY() != 1)
return;
// The shader had compiler errors. We cannot draw anything.
@@ -133,7 +129,7 @@ void FECustomFilter::platformApplySoftware()
m_drawingBuffer->commit();
RefPtr<ImageData> imageData = m_context->paintRenderingResultsToImageData(m_drawingBuffer.get());
- ByteArray* gpuResult = imageData->data()->data();
+ Uint8ClampedArray* gpuResult = imageData->data();
ASSERT(gpuResult->length() == dstPixelArray->length());
memcpy(dstPixelArray->data(), gpuResult->data(), gpuResult->length());
}
@@ -145,8 +141,8 @@ void FECustomFilter::initializeContext(const IntSize& contextSize)
attributes.premultipliedAlpha = false;
ASSERT(!m_context.get());
- m_context = GraphicsContext3D::create(attributes, m_document->view()->root()->hostWindow(), GraphicsContext3D::RenderOffscreen);
- m_drawingBuffer = DrawingBuffer::create(m_context.get(), contextSize, !attributes.preserveDrawingBuffer);
+ m_context = GraphicsContext3D::create(attributes, m_hostWindow, GraphicsContext3D::RenderOffscreen);
+ m_drawingBuffer = DrawingBuffer::create(m_context.get(), contextSize, DrawingBuffer::Discard, DrawingBuffer::Alpha);
m_shader = m_program->createShaderWithContext(m_context.get());
m_mesh = CustomFilterMesh::create(m_context.get(), m_meshColumns, m_meshRows,
@@ -167,7 +163,7 @@ void FECustomFilter::resizeContext(const IntSize& newContextSize)
void FECustomFilter::bindVertexAttribute(int attributeLocation, unsigned size, unsigned& offset)
{
if (attributeLocation != -1) {
- m_context->vertexAttribPointer(attributeLocation, 4, GraphicsContext3D::FLOAT, false, m_mesh->bytesPerVertex(), offset);
+ m_context->vertexAttribPointer(attributeLocation, size, GraphicsContext3D::FLOAT, false, m_mesh->bytesPerVertex(), offset);
m_context->enableVertexAttribArray(attributeLocation);
}
offset += size * sizeof(float);
@@ -213,7 +209,7 @@ void FECustomFilter::bindProgramParameters()
}
}
-void FECustomFilter::bindProgramAndBuffers(ByteArray* srcPixelArray)
+void FECustomFilter::bindProgramAndBuffers(Uint8ClampedArray* srcPixelArray)
{
m_context->useProgram(m_shader->program());
@@ -226,7 +222,12 @@ void FECustomFilter::bindProgramAndBuffers(ByteArray* srcPixelArray)
if (m_shader->projectionMatrixLocation() != -1) {
TransformationMatrix projectionMatrix;
+#if PLATFORM(CHROMIUM)
+ // We flip-y the projection matrix here because Chromium will flip-y the resulting image for us.
+ orthogonalProjectionMatrix(projectionMatrix, -0.5, 0.5, 0.5, -0.5);
+#else
orthogonalProjectionMatrix(projectionMatrix, -0.5, 0.5, -0.5, 0.5);
+#endif
float glProjectionMatrix[16];
projectionMatrix.toColumnMajorFloatArray(glProjectionMatrix);
m_context->uniformMatrix4fv(m_shader->projectionMatrixLocation(), 1, false, &glProjectionMatrix[0]);
diff --git a/Source/WebCore/platform/graphics/filters/FECustomFilter.h b/Source/WebCore/platform/graphics/filters/FECustomFilter.h
index c977c8591..5f5f02768 100644
--- a/Source/WebCore/platform/graphics/filters/FECustomFilter.h
+++ b/Source/WebCore/platform/graphics/filters/FECustomFilter.h
@@ -38,7 +38,7 @@
#include <wtf/RefPtr.h>
namespace JSC {
-class ByteArray;
+class Uint8ClampedArray;
}
namespace WebCore {
@@ -48,15 +48,15 @@ class CustomFilterMesh;
class CustomFilterNumberParameter;
class CustomFilterProgram;
class CustomFilterShader;
-class Document;
class DrawingBuffer;
class GraphicsContext3D;
+class HostWindow;
class IntSize;
class Texture;
class FECustomFilter : public FilterEffect {
public:
- static PassRefPtr<FECustomFilter> create(Filter*, Document*, PassRefPtr<CustomFilterProgram>, const CustomFilterParameterList&,
+ static PassRefPtr<FECustomFilter> create(Filter*, HostWindow*, PassRefPtr<CustomFilterProgram>, const CustomFilterParameterList&,
unsigned meshRows, unsigned meshColumns, CustomFilterOperation::MeshBoxType,
CustomFilterOperation::MeshType);
@@ -66,7 +66,7 @@ public:
virtual TextStream& externalRepresentation(TextStream&, int indention) const;
private:
- FECustomFilter(Filter*, Document*, PassRefPtr<CustomFilterProgram>, const CustomFilterParameterList&,
+ FECustomFilter(Filter*, HostWindow*, PassRefPtr<CustomFilterProgram>, const CustomFilterParameterList&,
unsigned meshRows, unsigned meshColumns, CustomFilterOperation::MeshBoxType,
CustomFilterOperation::MeshType);
@@ -75,9 +75,9 @@ private:
void bindVertexAttribute(int attributeLocation, unsigned size, unsigned& offset);
void bindProgramNumberParameters(int uniformLocation, CustomFilterNumberParameter*);
void bindProgramParameters();
- void bindProgramAndBuffers(ByteArray* srcPixelArray);
+ void bindProgramAndBuffers(Uint8ClampedArray* srcPixelArray);
- Document* m_document;
+ HostWindow* m_hostWindow;
RefPtr<GraphicsContext3D> m_context;
RefPtr<DrawingBuffer> m_drawingBuffer;
diff --git a/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp b/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp
index b0eac449a..7f554aa84 100644
--- a/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp
@@ -31,7 +31,7 @@
#include "RenderTreeAsText.h"
#include "TextStream.h"
-#include <wtf/ByteArray.h>
+#include <wtf/Uint8ClampedArray.h>
namespace WebCore {
@@ -96,15 +96,15 @@ void FEDisplacementMap::platformApplySoftware()
ASSERT(m_xChannelSelector != CHANNEL_UNKNOWN);
ASSERT(m_yChannelSelector != CHANNEL_UNKNOWN);
- ByteArray* dstPixelArray = createPremultipliedImageResult();
+ Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
if (!dstPixelArray)
return;
IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- RefPtr<ByteArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect);
+ RefPtr<Uint8ClampedArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect);
IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
- RefPtr<ByteArray> srcPixelArrayB = in2->asUnmultipliedImage(effectBDrawingRect);
+ RefPtr<Uint8ClampedArray> srcPixelArrayB = in2->asUnmultipliedImage(effectBDrawingRect);
ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length());
@@ -119,13 +119,13 @@ void FEDisplacementMap::platformApplySoftware()
int line = y * stride;
for (int x = 0; x < paintSize.width(); ++x) {
int dstIndex = line + x * 4;
- int srcX = x + static_cast<int>(scaleX * srcPixelArrayB->get(dstIndex + m_xChannelSelector - 1) + scaleAdjustmentX);
- int srcY = y + static_cast<int>(scaleY * srcPixelArrayB->get(dstIndex + m_yChannelSelector - 1) + scaleAdjustmentY);
+ int srcX = x + static_cast<int>(scaleX * srcPixelArrayB->item(dstIndex + m_xChannelSelector - 1) + scaleAdjustmentX);
+ int srcY = y + static_cast<int>(scaleY * srcPixelArrayB->item(dstIndex + m_yChannelSelector - 1) + scaleAdjustmentY);
for (unsigned channel = 0; channel < 4; ++channel) {
if (srcX < 0 || srcX >= paintSize.width() || srcY < 0 || srcY >= paintSize.height())
dstPixelArray->set(dstIndex + channel, static_cast<unsigned char>(0));
else {
- unsigned char pixelValue = srcPixelArrayA->get(srcY * stride + srcX * 4 + channel);
+ unsigned char pixelValue = srcPixelArrayA->item(srcY * stride + srcX * 4 + channel);
dstPixelArray->set(dstIndex + channel, pixelValue);
}
}
diff --git a/Source/WebCore/platform/graphics/filters/FEDropShadow.cpp b/Source/WebCore/platform/graphics/filters/FEDropShadow.cpp
index 3dd5a2763..34997f613 100644
--- a/Source/WebCore/platform/graphics/filters/FEDropShadow.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEDropShadow.cpp
@@ -29,8 +29,8 @@
#include "RenderTreeAsText.h"
#include "ShadowBlur.h"
#include "TextStream.h"
-#include <wtf/ByteArray.h>
#include <wtf/MathExtras.h>
+#include <wtf/Uint8ClampedArray.h>
using namespace std;
@@ -104,7 +104,7 @@ void FEDropShadow::platformApplySoftware()
// TODO: Direct pixel access to ImageBuffer would avoid copying the ImageData.
IntRect shadowArea(IntPoint(), resultImage->internalSize());
- RefPtr<ByteArray> srcPixelArray = resultImage->getPremultipliedImageData(shadowArea);
+ RefPtr<Uint8ClampedArray> srcPixelArray = resultImage->getPremultipliedImageData(shadowArea);
contextShadow.blurLayerImage(srcPixelArray->data(), shadowArea.size(), 4 * shadowArea.size().width());
diff --git a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
index 027642be7..fc3baf832 100644
--- a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
@@ -33,9 +33,9 @@
#include "RenderTreeAsText.h"
#include "TextStream.h"
-#include <wtf/ByteArray.h>
#include <wtf/MathExtras.h>
#include <wtf/ParallelJobs.h>
+#include <wtf/Uint8ClampedArray.h>
using namespace std;
@@ -80,7 +80,7 @@ void FEGaussianBlur::setStdDeviationY(float y)
m_stdY = y;
}
-inline void boxBlur(ByteArray* srcPixelArray, ByteArray* dstPixelArray,
+inline void boxBlur(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* dstPixelArray,
unsigned dx, int dxLeft, int dxRight, int stride, int strideLine, int effectWidth, int effectHeight, bool alphaImage)
{
for (int y = 0; y < effectHeight; ++y) {
@@ -90,16 +90,16 @@ inline void boxBlur(ByteArray* srcPixelArray, ByteArray* dstPixelArray,
// Fill the kernel
int maxKernelSize = min(dxRight, effectWidth);
for (int i = 0; i < maxKernelSize; ++i)
- sum += srcPixelArray->get(line + i * stride + channel);
+ sum += srcPixelArray->item(line + i * stride + channel);
// Blurring
for (int x = 0; x < effectWidth; ++x) {
int pixelByteOffset = line + x * stride + channel;
dstPixelArray->set(pixelByteOffset, static_cast<unsigned char>(sum / dx));
if (x >= dxLeft)
- sum -= srcPixelArray->get(pixelByteOffset - dxLeft * stride);
+ sum -= srcPixelArray->item(pixelByteOffset - dxLeft * stride);
if (x + dxRight < effectWidth)
- sum += srcPixelArray->get(pixelByteOffset + dxRight * stride);
+ sum += srcPixelArray->item(pixelByteOffset + dxRight * stride);
}
if (alphaImage) // Source image is black, it just has different alpha values
break;
@@ -107,15 +107,15 @@ inline void boxBlur(ByteArray* srcPixelArray, ByteArray* dstPixelArray,
}
}
-inline void FEGaussianBlur::platformApplyGeneric(ByteArray* srcPixelArray, ByteArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize)
+inline void FEGaussianBlur::platformApplyGeneric(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize)
{
int stride = 4 * paintSize.width();
int dxLeft = 0;
int dxRight = 0;
int dyLeft = 0;
int dyRight = 0;
- ByteArray* src = srcPixelArray;
- ByteArray* dst = tmpPixelArray;
+ Uint8ClampedArray* src = srcPixelArray;
+ Uint8ClampedArray* dst = tmpPixelArray;
for (int i = 0; i < 3; ++i) {
if (kernelSizeX) {
@@ -151,7 +151,7 @@ void FEGaussianBlur::platformApplyWorker(PlatformApplyParameters* parameters)
#endif
}
-inline void FEGaussianBlur::platformApply(ByteArray* srcPixelArray, ByteArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize)
+inline void FEGaussianBlur::platformApply(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize)
{
int scanline = 4 * paintSize.width();
int extraHeight = 3 * kernelSizeY * 0.5f;
@@ -185,8 +185,8 @@ inline void FEGaussianBlur::platformApply(ByteArray* srcPixelArray, ByteArray* t
}
int blockSize = (endY - startY) * scanline;
- params.srcPixelArray = ByteArray::create(blockSize);
- params.dstPixelArray = ByteArray::create(blockSize);
+ params.srcPixelArray = Uint8ClampedArray::createUninitialized(blockSize);
+ params.dstPixelArray = Uint8ClampedArray::createUninitialized(blockSize);
memcpy(params.srcPixelArray->data(), srcPixelArray->data() + startY * scanline, blockSize);
}
@@ -275,7 +275,7 @@ void FEGaussianBlur::platformApplySoftware()
{
FilterEffect* in = inputEffect(0);
- ByteArray* srcPixelArray = createPremultipliedImageResult();
+ Uint8ClampedArray* srcPixelArray = createPremultipliedImageResult();
if (!srcPixelArray)
return;
@@ -292,8 +292,8 @@ void FEGaussianBlur::platformApplySoftware()
calculateKernelSize(filter(), kernelSizeX, kernelSizeY, m_stdX, m_stdY);
IntSize paintSize = absolutePaintRect().size();
- RefPtr<ByteArray> tmpImageData = ByteArray::create(paintSize.width() * paintSize.height() * 4);
- ByteArray* tmpPixelArray = tmpImageData.get();
+ RefPtr<Uint8ClampedArray> tmpImageData = Uint8ClampedArray::createUninitialized(paintSize.width() * paintSize.height() * 4);
+ Uint8ClampedArray* tmpPixelArray = tmpImageData.get();
platformApply(srcPixelArray, tmpPixelArray, kernelSizeX, kernelSizeY, paintSize);
}
diff --git a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h
index b295d3608..c3db1f150 100644
--- a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h
+++ b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h
@@ -57,8 +57,8 @@ private:
struct PlatformApplyParameters {
FEGaussianBlur* filter;
- RefPtr<ByteArray> srcPixelArray;
- RefPtr<ByteArray> dstPixelArray;
+ RefPtr<Uint8ClampedArray> srcPixelArray;
+ RefPtr<Uint8ClampedArray> dstPixelArray;
int width;
int height;
unsigned kernelSizeX;
@@ -70,10 +70,10 @@ private:
FEGaussianBlur(Filter*, float, float);
static inline void kernelPosition(int boxBlur, unsigned& std, int& dLeft, int& dRight);
- inline void platformApply(ByteArray* srcPixelArray, ByteArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize);
+ inline void platformApply(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize);
- inline void platformApplyGeneric(ByteArray* srcPixelArray, ByteArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize);
- inline void platformApplyNeon(ByteArray* srcPixelArray, ByteArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize);
+ inline void platformApplyGeneric(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize);
+ inline void platformApplyNeon(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize);
#if USE(SKIA)
virtual bool platformApplySkia();
#endif
diff --git a/Source/WebCore/platform/graphics/filters/FELighting.cpp b/Source/WebCore/platform/graphics/filters/FELighting.cpp
index e795d3549..9d386fc6a 100644
--- a/Source/WebCore/platform/graphics/filters/FELighting.cpp
+++ b/Source/WebCore/platform/graphics/filters/FELighting.cpp
@@ -61,114 +61,114 @@ const static float cFactor2div3 = -2 / 3.f;
// << 1 is signed multiply by 2
inline void FELighting::LightingData::topLeft(int offset, IntPoint& normalVector)
{
- int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
- int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+ int center = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
+ int right = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
offset += widthMultipliedByPixelSize;
- int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
- int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+ int bottom = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
+ int bottomRight = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
normalVector.setX(-(center << 1) + (right << 1) - bottom + bottomRight);
normalVector.setY(-(center << 1) - right + (bottom << 1) + bottomRight);
}
inline void FELighting::LightingData::topRow(int offset, IntPoint& normalVector)
{
- int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
- int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
- int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+ int left = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
+ int center = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
+ int right = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
offset += widthMultipliedByPixelSize;
- int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
- int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
- int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+ int bottomLeft = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
+ int bottom = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
+ int bottomRight = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
normalVector.setX(-(left << 1) + (right << 1) - bottomLeft + bottomRight);
normalVector.setY(-left - (center << 1) - right + bottomLeft + (bottom << 1) + bottomRight);
}
inline void FELighting::LightingData::topRight(int offset, IntPoint& normalVector)
{
- int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
- int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+ int left = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
+ int center = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
offset += widthMultipliedByPixelSize;
- int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
- int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+ int bottomLeft = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
+ int bottom = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
normalVector.setX(-(left << 1) + (center << 1) - bottomLeft + bottom);
normalVector.setY(-left - (center << 1) + bottomLeft + (bottom << 1));
}
inline void FELighting::LightingData::leftColumn(int offset, IntPoint& normalVector)
{
- int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
- int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+ int center = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
+ int right = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
offset -= widthMultipliedByPixelSize;
- int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
- int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+ int top = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
+ int topRight = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
offset += widthMultipliedByPixelSize << 1;
- int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
- int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+ int bottom = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
+ int bottomRight = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
normalVector.setX(-top + topRight - (center << 1) + (right << 1) - bottom + bottomRight);
normalVector.setY(-(top << 1) - topRight + (bottom << 1) + bottomRight);
}
inline void FELighting::LightingData::interior(int offset, IntPoint& normalVector)
{
- int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
- int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+ int left = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
+ int right = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
offset -= widthMultipliedByPixelSize;
- int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
- int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
- int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+ int topLeft = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
+ int top = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
+ int topRight = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
offset += widthMultipliedByPixelSize << 1;
- int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
- int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
- int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+ int bottomLeft = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
+ int bottom = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
+ int bottomRight = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
normalVector.setX(-topLeft + topRight - (left << 1) + (right << 1) - bottomLeft + bottomRight);
normalVector.setY(-topLeft - (top << 1) - topRight + bottomLeft + (bottom << 1) + bottomRight);
}
inline void FELighting::LightingData::rightColumn(int offset, IntPoint& normalVector)
{
- int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
- int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+ int left = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
+ int center = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
offset -= widthMultipliedByPixelSize;
- int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
- int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+ int topLeft = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
+ int top = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
offset += widthMultipliedByPixelSize << 1;
- int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
- int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+ int bottomLeft = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
+ int bottom = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
normalVector.setX(-topLeft + top - (left << 1) + (center << 1) - bottomLeft + bottom);
normalVector.setY(-topLeft - (top << 1) + bottomLeft + (bottom << 1));
}
inline void FELighting::LightingData::bottomLeft(int offset, IntPoint& normalVector)
{
- int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
- int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+ int center = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
+ int right = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
offset -= widthMultipliedByPixelSize;
- int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
- int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+ int top = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
+ int topRight = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
normalVector.setX(-top + topRight - (center << 1) + (right << 1));
normalVector.setY(-(top << 1) - topRight + (center << 1) + right);
}
inline void FELighting::LightingData::bottomRow(int offset, IntPoint& normalVector)
{
- int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
- int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
- int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+ int left = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
+ int center = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
+ int right = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
offset -= widthMultipliedByPixelSize;
- int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
- int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
- int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+ int topLeft = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
+ int top = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
+ int topRight = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
normalVector.setX(-topLeft + topRight - (left << 1) + (right << 1));
normalVector.setY(-topLeft - (top << 1) - topRight + left + (center << 1) + right);
}
inline void FELighting::LightingData::bottomRight(int offset, IntPoint& normalVector)
{
- int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
- int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+ int left = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
+ int center = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
offset -= widthMultipliedByPixelSize;
- int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
- int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+ int topLeft = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
+ int top = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
normalVector.setX(-topLeft + top - (left << 1) + (center << 1));
normalVector.setY(-topLeft - (top << 1) + left + (center << 1));
}
@@ -176,7 +176,7 @@ inline void FELighting::LightingData::bottomRight(int offset, IntPoint& normalVe
inline void FELighting::inlineSetPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData,
int lightX, int lightY, float factorX, float factorY, IntPoint& normal2DVector)
{
- m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->get(offset + cAlphaChannelOffset)) * data.surfaceScale);
+ m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->item(offset + cAlphaChannelOffset)) * data.surfaceScale);
float lightStrength;
if (!normal2DVector.x() && !normal2DVector.y()) {
@@ -290,7 +290,7 @@ inline void FELighting::platformApply(LightingData& data, LightSource::PaintingD
#endif
}
-bool FELighting::drawLighting(ByteArray* pixels, int width, int height)
+bool FELighting::drawLighting(Uint8ClampedArray* pixels, int width, int height)
{
LightSource::PaintingData paintingData;
LightingData data;
@@ -373,9 +373,9 @@ bool FELighting::drawLighting(ByteArray* pixels, int width, int height)
data.pixels->set(i, cOpaqueAlpha);
} else {
for (int i = 0; i < lastPixel; i += cPixelSize) {
- unsigned char a1 = data.pixels->get(i);
- unsigned char a2 = data.pixels->get(i + 1);
- unsigned char a3 = data.pixels->get(i + 2);
+ unsigned char a1 = data.pixels->item(i);
+ unsigned char a2 = data.pixels->item(i + 1);
+ unsigned char a3 = data.pixels->item(i + 2);
// alpha set to set to max(a1, a2, a3)
data.pixels->set(i + 3, a1 >= a2 ? (a1 >= a3 ? a1 : a3) : (a2 >= a3 ? a2 : a3));
}
@@ -388,7 +388,7 @@ void FELighting::platformApplySoftware()
{
FilterEffect* in = inputEffect(0);
- ByteArray* srcPixelArray = createUnmultipliedImageResult();
+ Uint8ClampedArray* srcPixelArray = createUnmultipliedImageResult();
if (!srcPixelArray)
return;
diff --git a/Source/WebCore/platform/graphics/filters/FELighting.h b/Source/WebCore/platform/graphics/filters/FELighting.h
index 5426f912c..d0d2b3685 100644
--- a/Source/WebCore/platform/graphics/filters/FELighting.h
+++ b/Source/WebCore/platform/graphics/filters/FELighting.h
@@ -34,8 +34,8 @@
#include "LightSource.h"
#include "PointLightSource.h"
#include "SpotLightSource.h"
-#include <wtf/ByteArray.h>
#include <wtf/Platform.h>
+#include <wtf/Uint8ClampedArray.h>
// Common base class for FEDiffuseLighting and FESpecularLighting
@@ -59,7 +59,7 @@ protected:
struct LightingData {
// This structure contains only read-only (SMP safe) data
- ByteArray* pixels;
+ Uint8ClampedArray* pixels;
float surfaceScale;
int widthMultipliedByPixelSize;
int widthDecreasedByOne;
@@ -92,7 +92,7 @@ protected:
FELighting(Filter*, LightingType, const Color&, float, float, float, float, float, float, PassRefPtr<LightSource>);
- bool drawLighting(ByteArray*, int, int);
+ bool drawLighting(Uint8ClampedArray*, int, int);
inline void inlineSetPixel(int offset, LightingData&, LightSource::PaintingData&,
int lightX, int lightY, float factorX, float factorY, IntPoint& normalVector);
diff --git a/Source/WebCore/platform/graphics/filters/FEMorphology.cpp b/Source/WebCore/platform/graphics/filters/FEMorphology.cpp
index 5ba4dfc14..98d2a6a01 100644
--- a/Source/WebCore/platform/graphics/filters/FEMorphology.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEMorphology.cpp
@@ -30,8 +30,8 @@
#include "RenderTreeAsText.h"
#include "TextStream.h"
-#include <wtf/ByteArray.h>
#include <wtf/ParallelJobs.h>
+#include <wtf/Uint8ClampedArray.h>
#include <wtf/Vector.h>
using std::min;
@@ -106,8 +106,8 @@ bool FEMorphology::setRadiusY(float radiusY)
void FEMorphology::platformApplyGeneric(PaintingData* paintingData, int yStart, int yEnd)
{
- ByteArray* srcPixelArray = paintingData->srcPixelArray;
- ByteArray* dstPixelArray = paintingData->dstPixelArray;
+ Uint8ClampedArray* srcPixelArray = paintingData->srcPixelArray;
+ Uint8ClampedArray* dstPixelArray = paintingData->dstPixelArray;
const int width = paintingData->width;
const int height = paintingData->height;
const int effectWidth = width * 4;
@@ -122,9 +122,9 @@ void FEMorphology::platformApplyGeneric(PaintingData* paintingData, int yStart,
extrema.clear();
// Compute extremas for each columns
for (int x = 0; x <= radiusX; ++x) {
- unsigned char columnExtrema = srcPixelArray->get(extremaStartY * effectWidth + 4 * x + clrChannel);
+ unsigned char columnExtrema = srcPixelArray->item(extremaStartY * effectWidth + 4 * x + clrChannel);
for (int eY = extremaStartY + 1; eY < extremaEndY; ++eY) {
- unsigned char pixel = srcPixelArray->get(eY * effectWidth + 4 * x + clrChannel);
+ unsigned char pixel = srcPixelArray->item(eY * effectWidth + 4 * x + clrChannel);
if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && pixel <= columnExtrema)
|| (m_type == FEMORPHOLOGY_OPERATOR_DILATE && pixel >= columnExtrema)) {
columnExtrema = pixel;
@@ -137,9 +137,9 @@ void FEMorphology::platformApplyGeneric(PaintingData* paintingData, int yStart,
// Kernel is filled, get extrema of next column
for (int x = 0; x < width; ++x) {
const int endX = min(x + radiusX, width - 1);
- unsigned char columnExtrema = srcPixelArray->get(extremaStartY * effectWidth + endX * 4 + clrChannel);
+ unsigned char columnExtrema = srcPixelArray->item(extremaStartY * effectWidth + endX * 4 + clrChannel);
for (int i = extremaStartY + 1; i <= extremaEndY; ++i) {
- unsigned char pixel = srcPixelArray->get(i * effectWidth + endX * 4 + clrChannel);
+ unsigned char pixel = srcPixelArray->item(i * effectWidth + endX * 4 + clrChannel);
if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && pixel <= columnExtrema)
|| (m_type == FEMORPHOLOGY_OPERATOR_DILATE && pixel >= columnExtrema))
columnExtrema = pixel;
@@ -197,13 +197,13 @@ void FEMorphology::platformApplySoftware()
{
FilterEffect* in = inputEffect(0);
- ByteArray* dstPixelArray = createPremultipliedImageResult();
+ Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
if (!dstPixelArray)
return;
setIsAlphaImage(in->isAlphaImage());
if (m_radiusX <= 0 || m_radiusY <= 0) {
- dstPixelArray->clear();
+ dstPixelArray->zeroFill();
return;
}
@@ -212,7 +212,7 @@ void FEMorphology::platformApplySoftware()
int radiusY = static_cast<int>(floorf(filter->applyVerticalScale(m_radiusY)));
IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- RefPtr<ByteArray> srcPixelArray = in->asPremultipliedImage(effectDrawingRect);
+ RefPtr<Uint8ClampedArray> srcPixelArray = in->asPremultipliedImage(effectDrawingRect);
PaintingData paintingData;
paintingData.srcPixelArray = srcPixelArray.get();
diff --git a/Source/WebCore/platform/graphics/filters/FEMorphology.h b/Source/WebCore/platform/graphics/filters/FEMorphology.h
index f92540342..19da635a2 100644
--- a/Source/WebCore/platform/graphics/filters/FEMorphology.h
+++ b/Source/WebCore/platform/graphics/filters/FEMorphology.h
@@ -47,6 +47,9 @@ public:
bool setRadiusY(float);
virtual void platformApplySoftware();
+#if USE(SKIA)
+ virtual bool platformApplySkia();
+#endif
virtual void dump();
virtual void determineAbsolutePaintRect();
@@ -54,8 +57,8 @@ public:
virtual TextStream& externalRepresentation(TextStream&, int indention) const;
struct PaintingData {
- ByteArray* srcPixelArray;
- ByteArray* dstPixelArray;
+ Uint8ClampedArray* srcPixelArray;
+ Uint8ClampedArray* dstPixelArray;
int width;
int height;
int radiusX;
diff --git a/Source/WebCore/platform/graphics/filters/FETile.cpp b/Source/WebCore/platform/graphics/filters/FETile.cpp
index e4a9508ee..3db7a7c38 100644
--- a/Source/WebCore/platform/graphics/filters/FETile.cpp
+++ b/Source/WebCore/platform/graphics/filters/FETile.cpp
@@ -28,7 +28,7 @@
#include "GraphicsContext.h"
#include "Pattern.h"
#include "RenderTreeAsText.h"
-#include "SVGImageBufferTools.h"
+#include "SVGRenderingContext.h"
#include "TextStream.h"
namespace WebCore {
@@ -67,7 +67,7 @@ void FETile::platformApplySoftware()
}
OwnPtr<ImageBuffer> tileImage;
- if (!SVGImageBufferTools::createImageBufferForPattern(tileRect, tileRect, tileImage, ColorSpaceDeviceRGB, filter()->renderingMode()))
+ if (!SVGRenderingContext::createImageBufferForPattern(tileRect, tileRect, tileImage, ColorSpaceDeviceRGB, filter()->renderingMode()))
return;
GraphicsContext* tileImageContext = tileImage->context();
diff --git a/Source/WebCore/platform/graphics/filters/FETurbulence.cpp b/Source/WebCore/platform/graphics/filters/FETurbulence.cpp
index d5d64c130..03df56b30 100644
--- a/Source/WebCore/platform/graphics/filters/FETurbulence.cpp
+++ b/Source/WebCore/platform/graphics/filters/FETurbulence.cpp
@@ -31,9 +31,9 @@
#include "RenderTreeAsText.h"
#include "TextStream.h"
-#include <wtf/ByteArray.h>
#include <wtf/MathExtras.h>
#include <wtf/ParallelJobs.h>
+#include <wtf/Uint8ClampedArray.h>
namespace WebCore {
@@ -330,7 +330,7 @@ unsigned char FETurbulence::calculateTurbulenceValueForPoint(int channel, Painti
return static_cast<unsigned char>(turbulenceFunctionResult * 255);
}
-inline void FETurbulence::fillRegion(ByteArray* pixelArray, PaintingData& paintingData, int startY, int endY)
+inline void FETurbulence::fillRegion(Uint8ClampedArray* pixelArray, PaintingData& paintingData, int startY, int endY)
{
IntRect filterRegion = absolutePaintRect();
IntPoint point(0, filterRegion.y() + startY);
@@ -356,12 +356,12 @@ void FETurbulence::fillRegionWorker(FillRegionParameters* parameters)
void FETurbulence::platformApplySoftware()
{
- ByteArray* pixelArray = createUnmultipliedImageResult();
+ Uint8ClampedArray* pixelArray = createUnmultipliedImageResult();
if (!pixelArray)
return;
if (absolutePaintRect().isEmpty()) {
- pixelArray->clear();
+ pixelArray->zeroFill();
return;
}
diff --git a/Source/WebCore/platform/graphics/filters/FETurbulence.h b/Source/WebCore/platform/graphics/filters/FETurbulence.h
index 59257d026..47c8bee79 100644
--- a/Source/WebCore/platform/graphics/filters/FETurbulence.h
+++ b/Source/WebCore/platform/graphics/filters/FETurbulence.h
@@ -108,7 +108,7 @@ private:
struct FillRegionParameters {
FETurbulence* filter;
- ByteArray* pixelArray;
+ Uint8ClampedArray* pixelArray;
PaintingData* paintingData;
int startY;
int endY;
@@ -121,7 +121,7 @@ private:
inline void initPaint(PaintingData&);
float noise2D(int channel, PaintingData&, StitchData&, const FloatPoint&);
unsigned char calculateTurbulenceValueForPoint(int channel, PaintingData&, StitchData&, const FloatPoint&);
- inline void fillRegion(ByteArray*, PaintingData&, int, int);
+ inline void fillRegion(Uint8ClampedArray*, PaintingData&, int, int);
TurbulenceType m_type;
float m_baseFrequencyX;
diff --git a/Source/WebCore/platform/graphics/filters/FilterEffect.cpp b/Source/WebCore/platform/graphics/filters/FilterEffect.cpp
index 9bf1689f7..8dc918553 100644
--- a/Source/WebCore/platform/graphics/filters/FilterEffect.cpp
+++ b/Source/WebCore/platform/graphics/filters/FilterEffect.cpp
@@ -27,7 +27,7 @@
#include "Filter.h"
#include "ImageBuffer.h"
#include "TextStream.h"
-#include <wtf/ByteArray.h>
+#include <wtf/Uint8ClampedArray.h>
namespace WebCore {
@@ -103,6 +103,9 @@ void FilterEffect::apply()
}
determineAbsolutePaintRect();
+ if (!isFilterSizeValid(m_absolutePaintRect))
+ return;
+
if (requiresValidPreMultipliedPixels()) {
for (unsigned i = 0; i < size; ++i)
inputEffect(i)->correctFilterResultIfNeeded();
@@ -122,7 +125,7 @@ void FilterEffect::forceValidPreMultipliedPixels()
if (!m_premultipliedImageResult)
return;
- ByteArray* imageArray = m_premultipliedImageResult.get();
+ Uint8ClampedArray* imageArray = m_premultipliedImageResult.get();
unsigned char* pixelData = imageArray->data();
int pixelArrayLength = imageArray->length();
@@ -170,23 +173,23 @@ ImageBuffer* FilterEffect::asImageBuffer()
return m_imageBufferResult.get();
}
-PassRefPtr<ByteArray> FilterEffect::asUnmultipliedImage(const IntRect& rect)
+PassRefPtr<Uint8ClampedArray> FilterEffect::asUnmultipliedImage(const IntRect& rect)
{
ASSERT(isFilterSizeValid(rect));
- RefPtr<ByteArray> imageData = ByteArray::create(rect.width() * rect.height() * 4);
+ RefPtr<Uint8ClampedArray> imageData = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4);
copyUnmultipliedImage(imageData.get(), rect);
return imageData.release();
}
-PassRefPtr<ByteArray> FilterEffect::asPremultipliedImage(const IntRect& rect)
+PassRefPtr<Uint8ClampedArray> FilterEffect::asPremultipliedImage(const IntRect& rect)
{
ASSERT(isFilterSizeValid(rect));
- RefPtr<ByteArray> imageData = ByteArray::create(rect.width() * rect.height() * 4);
+ RefPtr<Uint8ClampedArray> imageData = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4);
copyPremultipliedImage(imageData.get(), rect);
return imageData.release();
}
-inline void FilterEffect::copyImageBytes(ByteArray* source, ByteArray* destination, const IntRect& rect)
+inline void FilterEffect::copyImageBytes(Uint8ClampedArray* source, Uint8ClampedArray* destination, const IntRect& rect)
{
// Initialize the destination to transparent black, if not entirely covered by the source.
if (rect.x() < 0 || rect.y() < 0 || rect.maxX() > m_absolutePaintRect.width() || rect.maxY() > m_absolutePaintRect.height())
@@ -230,7 +233,7 @@ inline void FilterEffect::copyImageBytes(ByteArray* source, ByteArray* destinati
}
}
-void FilterEffect::copyUnmultipliedImage(ByteArray* destination, const IntRect& rect)
+void FilterEffect::copyUnmultipliedImage(Uint8ClampedArray* destination, const IntRect& rect)
{
ASSERT(hasResult());
@@ -240,7 +243,7 @@ void FilterEffect::copyUnmultipliedImage(ByteArray* destination, const IntRect&
m_unmultipliedImageResult = m_imageBufferResult->getUnmultipliedImageData(IntRect(IntPoint(), m_absolutePaintRect.size()));
else {
ASSERT(isFilterSizeValid(m_absolutePaintRect));
- m_unmultipliedImageResult = ByteArray::create(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4);
+ m_unmultipliedImageResult = Uint8ClampedArray::createUninitialized(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4);
unsigned char* sourceComponent = m_premultipliedImageResult->data();
unsigned char* destinationComponent = m_unmultipliedImageResult->data();
unsigned char* end = sourceComponent + (m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4);
@@ -264,7 +267,7 @@ void FilterEffect::copyUnmultipliedImage(ByteArray* destination, const IntRect&
copyImageBytes(m_unmultipliedImageResult.get(), destination, rect);
}
-void FilterEffect::copyPremultipliedImage(ByteArray* destination, const IntRect& rect)
+void FilterEffect::copyPremultipliedImage(Uint8ClampedArray* destination, const IntRect& rect)
{
ASSERT(hasResult());
@@ -274,7 +277,7 @@ void FilterEffect::copyPremultipliedImage(ByteArray* destination, const IntRect&
m_premultipliedImageResult = m_imageBufferResult->getPremultipliedImageData(IntRect(IntPoint(), m_absolutePaintRect.size()));
else {
ASSERT(isFilterSizeValid(m_absolutePaintRect));
- m_premultipliedImageResult = ByteArray::create(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4);
+ m_premultipliedImageResult = Uint8ClampedArray::createUninitialized(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4);
unsigned char* sourceComponent = m_unmultipliedImageResult->data();
unsigned char* destinationComponent = m_premultipliedImageResult->data();
unsigned char* end = sourceComponent + (m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4);
@@ -305,7 +308,7 @@ ImageBuffer* FilterEffect::createImageBufferResult()
return m_imageBufferResult.get();
}
-ByteArray* FilterEffect::createUnmultipliedImageResult()
+Uint8ClampedArray* FilterEffect::createUnmultipliedImageResult()
{
// Only one result type is allowed.
ASSERT(!hasResult());
@@ -313,11 +316,11 @@ ByteArray* FilterEffect::createUnmultipliedImageResult()
if (m_absolutePaintRect.isEmpty())
return 0;
- m_unmultipliedImageResult = ByteArray::create(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4);
+ m_unmultipliedImageResult = Uint8ClampedArray::createUninitialized(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4);
return m_unmultipliedImageResult.get();
}
-ByteArray* FilterEffect::createPremultipliedImageResult()
+Uint8ClampedArray* FilterEffect::createPremultipliedImageResult()
{
// Only one result type is allowed.
ASSERT(!hasResult());
@@ -325,7 +328,7 @@ ByteArray* FilterEffect::createPremultipliedImageResult()
if (m_absolutePaintRect.isEmpty())
return 0;
- m_premultipliedImageResult = ByteArray::create(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4);
+ m_premultipliedImageResult = Uint8ClampedArray::createUninitialized(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4);
return m_premultipliedImageResult.get();
}
diff --git a/Source/WebCore/platform/graphics/filters/FilterEffect.h b/Source/WebCore/platform/graphics/filters/FilterEffect.h
index 8b4ad6f92..c99cd501d 100644
--- a/Source/WebCore/platform/graphics/filters/FilterEffect.h
+++ b/Source/WebCore/platform/graphics/filters/FilterEffect.h
@@ -26,10 +26,10 @@
#include "FloatRect.h"
#include "IntRect.h"
-#include <wtf/ByteArray.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
+#include <wtf/Uint8ClampedArray.h>
#include <wtf/Vector.h>
static const float kMaxFilterSize = 5000.0f;
@@ -56,10 +56,10 @@ public:
void clearResult();
ImageBuffer* asImageBuffer();
- PassRefPtr<ByteArray> asUnmultipliedImage(const IntRect&);
- PassRefPtr<ByteArray> asPremultipliedImage(const IntRect&);
- void copyUnmultipliedImage(ByteArray* destination, const IntRect&);
- void copyPremultipliedImage(ByteArray* destination, const IntRect&);
+ PassRefPtr<Uint8ClampedArray> asUnmultipliedImage(const IntRect&);
+ PassRefPtr<Uint8ClampedArray> asPremultipliedImage(const IntRect&);
+ void copyUnmultipliedImage(Uint8ClampedArray* destination, const IntRect&);
+ void copyPremultipliedImage(Uint8ClampedArray* destination, const IntRect&);
FilterEffectVector& inputEffects() { return m_inputEffects; }
FilterEffect* inputEffect(unsigned) const;
@@ -133,8 +133,8 @@ protected:
FilterEffect(Filter*);
ImageBuffer* createImageBufferResult();
- ByteArray* createUnmultipliedImageResult();
- ByteArray* createPremultipliedImageResult();
+ Uint8ClampedArray* createUnmultipliedImageResult();
+ Uint8ClampedArray* createPremultipliedImageResult();
// Return true if the filter will only operate correctly on valid RGBA values, with
// alpha in [0,255] and each color component in [0, alpha].
@@ -145,8 +145,8 @@ protected:
private:
OwnPtr<ImageBuffer> m_imageBufferResult;
- RefPtr<ByteArray> m_unmultipliedImageResult;
- RefPtr<ByteArray> m_premultipliedImageResult;
+ RefPtr<Uint8ClampedArray> m_unmultipliedImageResult;
+ RefPtr<Uint8ClampedArray> m_premultipliedImageResult;
FilterEffectVector m_inputEffects;
bool m_alphaImage;
@@ -159,7 +159,7 @@ private:
Filter* m_filter;
private:
- inline void copyImageBytes(ByteArray* source, ByteArray* destination, const IntRect&);
+ inline void copyImageBytes(Uint8ClampedArray* source, Uint8ClampedArray* destination, const IntRect&);
// The following member variables are SVG specific and will move to RenderSVGResourceFilterPrimitive.
// See bug https://bugs.webkit.org/show_bug.cgi?id=45614.
diff --git a/Source/WebCore/platform/graphics/filters/FilterOperation.cpp b/Source/WebCore/platform/graphics/filters/FilterOperation.cpp
index 5de6ec0aa..656926e28 100644
--- a/Source/WebCore/platform/graphics/filters/FilterOperation.cpp
+++ b/Source/WebCore/platform/graphics/filters/FilterOperation.cpp
@@ -133,21 +133,18 @@ PassRefPtr<FilterOperation> DropShadowFilterOperation::blend(const FilterOperati
if (blendToPassthrough)
return DropShadowFilterOperation::create(
- WebCore::blend(m_x, 0, progress),
- WebCore::blend(m_y, 0, progress),
+ WebCore::blend(m_location, IntPoint(), progress),
WebCore::blend(m_stdDeviation, 0, progress),
WebCore::blend(m_color, Color(Color::transparent), progress),
m_type);
const DropShadowFilterOperation* fromOp = static_cast<const DropShadowFilterOperation*>(from);
- int fromX = fromOp ? fromOp->x() : 0;
- int fromY = fromOp ? fromOp->y() : 0;
+ IntPoint fromLocation = fromOp ? fromOp->location() : IntPoint();
int fromStdDeviation = fromOp ? fromOp->stdDeviation() : 0;
Color fromColor = fromOp ? fromOp->color() : Color(Color::transparent);
return DropShadowFilterOperation::create(
- WebCore::blend(fromX, m_x, progress),
- WebCore::blend(fromY, m_y, progress),
+ WebCore::blend(fromLocation, m_location, progress),
WebCore::blend(fromStdDeviation, m_stdDeviation, progress),
WebCore::blend(fromColor, m_color, progress), m_type);
}
diff --git a/Source/WebCore/platform/graphics/filters/FilterOperation.h b/Source/WebCore/platform/graphics/filters/FilterOperation.h
index 9ee955768..255f64048 100644
--- a/Source/WebCore/platform/graphics/filters/FilterOperation.h
+++ b/Source/WebCore/platform/graphics/filters/FilterOperation.h
@@ -82,6 +82,8 @@ public:
// True if the the value of one pixel can affect the value of another pixel under this operation, such as blur.
virtual bool movesPixels() const { return false; }
+ virtual PassRefPtr<FilterOperation> clone() const = 0;
+
protected:
FilterOperation(OperationType type)
: m_type(type)
@@ -98,6 +100,11 @@ public:
return adoptRef(new DefaultFilterOperation(type));
}
+ virtual PassRefPtr<FilterOperation> clone() const
+ {
+ return adoptRef(new DefaultFilterOperation(m_type));
+ }
+
private:
virtual bool operator==(const FilterOperation& o) const
@@ -120,6 +127,11 @@ public:
return adoptRef(new PassthroughFilterOperation());
}
+ virtual PassRefPtr<FilterOperation> clone() const
+ {
+ return adoptRef(new PassthroughFilterOperation());
+ }
+
private:
virtual bool operator==(const FilterOperation& o) const
@@ -140,6 +152,12 @@ public:
return adoptRef(new ReferenceFilterOperation(reference, type));
}
+ virtual PassRefPtr<FilterOperation> clone() const
+ {
+ // AtomicString is thread-hostile, so we can't be cloned.
+ return 0;
+ }
+
virtual bool affectsOpacity() const { return true; }
virtual bool movesPixels() const { return true; }
@@ -173,6 +191,11 @@ public:
return adoptRef(new BasicColorMatrixFilterOperation(amount, type));
}
+ virtual PassRefPtr<FilterOperation> clone() const
+ {
+ return adoptRef(new BasicColorMatrixFilterOperation(m_amount, m_type));
+ }
+
double amount() const { return m_amount; }
virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false);
@@ -205,6 +228,11 @@ public:
return adoptRef(new BasicComponentTransferFilterOperation(amount, type));
}
+ virtual PassRefPtr<FilterOperation> clone() const
+ {
+ return adoptRef(new BasicComponentTransferFilterOperation(m_amount, m_type));
+ }
+
double amount() const { return m_amount; }
virtual bool affectsOpacity() const { return m_type == OPACITY; }
@@ -238,6 +266,11 @@ public:
return adoptRef(new GammaFilterOperation(amplitude, exponent, offset, type));
}
+ virtual PassRefPtr<FilterOperation> clone() const
+ {
+ return adoptRef(new GammaFilterOperation(m_amplitude, m_exponent, m_offset, m_type));
+ }
+
double amplitude() const { return m_amplitude; }
double exponent() const { return m_exponent; }
double offset() const { return m_offset; }
@@ -273,6 +306,11 @@ public:
return adoptRef(new BlurFilterOperation(stdDeviation, type));
}
+ virtual PassRefPtr<FilterOperation> clone() const
+ {
+ return adoptRef(new BlurFilterOperation(m_stdDeviation, m_type));
+ }
+
Length stdDeviation() const { return m_stdDeviation; }
virtual bool affectsOpacity() const { return true; }
@@ -300,13 +338,19 @@ private:
class DropShadowFilterOperation : public FilterOperation {
public:
- static PassRefPtr<DropShadowFilterOperation> create(int x, int y, int stdDeviation, Color color, OperationType type)
+ static PassRefPtr<DropShadowFilterOperation> create(const IntPoint& location, int stdDeviation, Color color, OperationType type)
+ {
+ return adoptRef(new DropShadowFilterOperation(location, stdDeviation, color, type));
+ }
+
+ virtual PassRefPtr<FilterOperation> clone() const
{
- return adoptRef(new DropShadowFilterOperation(x, y, stdDeviation, color, type));
+ return adoptRef(new DropShadowFilterOperation(m_location, m_stdDeviation, m_color, m_type));
}
- int x() const { return m_x; }
- int y() const { return m_y; }
+ int x() const { return m_location.x(); }
+ int y() const { return m_location.y(); }
+ IntPoint location() const { return m_location; }
int stdDeviation() const { return m_stdDeviation; }
Color color() const { return m_color; }
@@ -322,20 +366,18 @@ private:
if (!isSameType(o))
return false;
const DropShadowFilterOperation* other = static_cast<const DropShadowFilterOperation*>(&o);
- return m_x == other->m_x && m_y == other->m_y && m_stdDeviation == other->m_stdDeviation && m_color == other->m_color;
+ return m_location == other->m_location && m_stdDeviation == other->m_stdDeviation && m_color == other->m_color;
}
- DropShadowFilterOperation(int x, int y, int stdDeviation, Color color, OperationType type)
+ DropShadowFilterOperation(const IntPoint& location, int stdDeviation, Color color, OperationType type)
: FilterOperation(type)
- , m_x(x)
- , m_y(y)
+ , m_location(location)
, m_stdDeviation(stdDeviation)
, m_color(color)
{
}
- int m_x; // FIXME: x and y should be Lengths?
- int m_y;
+ IntPoint m_location; // FIXME: should location be in Lengths?
int m_stdDeviation;
Color m_color;
};
diff --git a/Source/WebCore/platform/graphics/filters/FilterOperations.cpp b/Source/WebCore/platform/graphics/filters/FilterOperations.cpp
index 35282cb53..821bc6e67 100644
--- a/Source/WebCore/platform/graphics/filters/FilterOperations.cpp
+++ b/Source/WebCore/platform/graphics/filters/FilterOperations.cpp
@@ -28,6 +28,7 @@
#include "FEGaussianBlur.h"
#include "IntSize.h"
+#include "LengthFunctions.h"
#if ENABLE(CSS_FILTERS)
@@ -86,6 +87,17 @@ bool FilterOperations::operationsMatch(const FilterOperations& other) const
return true;
}
+#if ENABLE(CSS_SHADERS)
+bool FilterOperations::hasCustomFilter() const
+{
+ for (size_t i = 0; i < m_operations.size(); ++i) {
+ if (m_operations.at(i)->getOperationType() == FilterOperation::CUSTOM)
+ return true;
+ }
+ return false;
+}
+#endif
+
bool FilterOperations::hasOutsets() const
{
for (size_t i = 0; i < m_operations.size(); ++i) {
@@ -96,7 +108,7 @@ bool FilterOperations::hasOutsets() const
return false;
}
-void FilterOperations::getOutsets(LayoutUnit& top, LayoutUnit& right, LayoutUnit& bottom, LayoutUnit& left) const
+void FilterOperations::getOutsets(int& top, int& right, int& bottom, int& left) const
{
top = 0;
right = 0;
@@ -107,7 +119,7 @@ void FilterOperations::getOutsets(LayoutUnit& top, LayoutUnit& right, LayoutUnit
switch (filterOperation->getOperationType()) {
case FilterOperation::BLUR: {
BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation);
- float stdDeviation = blurOperation->stdDeviation().calcFloatValue(0);
+ float stdDeviation = floatValueForLength(blurOperation->stdDeviation(), 0);
IntSize outset = outsetSizeForBlur(stdDeviation);
top += outset.height();
right += outset.width();
@@ -118,10 +130,10 @@ void FilterOperations::getOutsets(LayoutUnit& top, LayoutUnit& right, LayoutUnit
case FilterOperation::DROP_SHADOW: {
DropShadowFilterOperation* dropShadowOperation = static_cast<DropShadowFilterOperation*>(filterOperation);
IntSize outset = outsetSizeForBlur(dropShadowOperation->stdDeviation());
- top += outset.height() - dropShadowOperation->y();
- right += outset.width() + dropShadowOperation->x();
- bottom += outset.height() + dropShadowOperation->y();
- left += outset.width() - dropShadowOperation->x();
+ top += std::max(0, outset.height() - dropShadowOperation->y());
+ right += std::max(0, outset.width() + dropShadowOperation->x());
+ bottom += std::max(0, outset.height() + dropShadowOperation->y());
+ left += std::max(0, outset.width() - dropShadowOperation->x());
break;
}
#if ENABLE(CSS_SHADERS)
diff --git a/Source/WebCore/platform/graphics/filters/FilterOperations.h b/Source/WebCore/platform/graphics/filters/FilterOperations.h
index 0b492eb9a..be1b0a623 100644
--- a/Source/WebCore/platform/graphics/filters/FilterOperations.h
+++ b/Source/WebCore/platform/graphics/filters/FilterOperations.h
@@ -64,11 +64,14 @@ public:
bool operationsMatch(const FilterOperations&) const;
bool hasOutsets() const;
- void getOutsets(LayoutUnit& top, LayoutUnit& right, LayoutUnit& bottom, LayoutUnit& left) const;
+ void getOutsets(int& top, int& right, int& bottom, int& left) const;
bool hasFilterThatAffectsOpacity() const;
bool hasFilterThatMovesPixels() const;
+#if ENABLE(CSS_SHADERS)
+ bool hasCustomFilter() const;
+#endif
private:
Vector<RefPtr<FilterOperation> > m_operations;
};
diff --git a/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h b/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h
index 96037aab9..1fb3752c5 100644
--- a/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h
+++ b/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h
@@ -54,7 +54,7 @@ void neonDrawAllChannelGaussianBlur(unsigned char* source, unsigned char* destin
void neonDrawAlphaChannelGaussianBlur(unsigned char* source, unsigned char* destination, FEGaussianBlurPaintingDataForNeon*);
}
-inline void FEGaussianBlur::platformApplyNeon(ByteArray* srcPixelArray, ByteArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize)
+inline void FEGaussianBlur::platformApplyNeon(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize)
{
const int widthMultipliedByFour = 4 * paintSize.width();
FEGaussianBlurPaintingDataForNeon argumentsX = {
@@ -89,7 +89,7 @@ inline void FEGaussianBlur::platformApplyNeon(ByteArray* srcPixelArray, ByteArra
else
neonDrawAllChannelGaussianBlur(srcPixelArray->data(), tmpPixelArray->data(), &argumentsX);
} else {
- ByteArray* auxPixelArray = tmpPixelArray;
+ Uint8ClampedArray* auxPixelArray = tmpPixelArray;
tmpPixelArray = srcPixelArray;
srcPixelArray = auxPixelArray;
}
@@ -102,7 +102,7 @@ inline void FEGaussianBlur::platformApplyNeon(ByteArray* srcPixelArray, ByteArra
else
neonDrawAllChannelGaussianBlur(tmpPixelArray->data(), srcPixelArray->data(), &argumentsY);
} else {
- ByteArray* auxPixelArray = tmpPixelArray;
+ Uint8ClampedArray* auxPixelArray = tmpPixelArray;
tmpPixelArray = srcPixelArray;
srcPixelArray = auxPixelArray;
}
diff --git a/Source/WebCore/platform/graphics/filters/skia/FEGaussianBlurSkia.cpp b/Source/WebCore/platform/graphics/filters/skia/FEGaussianBlurSkia.cpp
index 4b36751fa..b694c9b1c 100644
--- a/Source/WebCore/platform/graphics/filters/skia/FEGaussianBlurSkia.cpp
+++ b/Source/WebCore/platform/graphics/filters/skia/FEGaussianBlurSkia.cpp
@@ -51,12 +51,13 @@ bool FEGaussianBlur::platformApplySkia()
SkPaint paint;
GraphicsContext* dstContext = resultImage->context();
- SkCanvas* canvas = dstContext->platformContext()->canvas();
+ PlatformContextSkia* platformContext = dstContext->platformContext();
paint.setImageFilter(new SkBlurImageFilter(stdX, stdY))->unref();
- canvas->saveLayer(0, &paint);
+
+ platformContext->saveLayer(0, &paint);
paint.setColor(0xFFFFFFFF);
dstContext->drawImage(image.get(), ColorSpaceDeviceRGB, drawingRegion.location(), CompositeCopy);
- canvas->restore();
+ platformContext->restoreLayer();
return true;
}
diff --git a/Source/WebCore/platform/graphics/filters/skia/FEMorphologySkia.cpp b/Source/WebCore/platform/graphics/filters/skia/FEMorphologySkia.cpp
new file mode 100644
index 000000000..e7290bec7
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/skia/FEMorphologySkia.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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(SKIA)
+#include "FEMorphology.h"
+
+#include "SkMorphologyImageFilter.h"
+
+namespace WebCore {
+
+bool FEMorphology::platformApplySkia()
+{
+ ImageBuffer* resultImage = createImageBufferResult();
+ if (!resultImage)
+ return false;
+
+ FilterEffect* in = inputEffect(0);
+
+ IntRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());
+
+ setIsAlphaImage(in->isAlphaImage());
+
+ float radiusX = filter()->applyHorizontalScale(m_radiusX);
+ float radiusY = filter()->applyVerticalScale(m_radiusY);
+
+ RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore);
+
+ SkPaint paint;
+ GraphicsContext* dstContext = resultImage->context();
+ PlatformContextSkia* platformContext = dstContext->platformContext();
+ if (m_type == FEMORPHOLOGY_OPERATOR_DILATE)
+ paint.setImageFilter(new SkDilateImageFilter(radiusX, radiusY))->unref();
+ else if (m_type == FEMORPHOLOGY_OPERATOR_ERODE)
+ paint.setImageFilter(new SkErodeImageFilter(radiusX, radiusY))->unref();
+
+ platformContext->saveLayer(0, &paint);
+ dstContext->drawImage(image.get(), ColorSpaceDeviceRGB, drawingRegion.location(), CompositeCopy);
+ platformContext->restoreLayer();
+ return true;
+}
+
+};
+#endif
diff --git a/Source/WebCore/platform/graphics/freetype/FontPlatformData.h b/Source/WebCore/platform/graphics/freetype/FontPlatformData.h
index d63363b13..206653ddf 100644
--- a/Source/WebCore/platform/graphics/freetype/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/freetype/FontPlatformData.h
@@ -29,9 +29,9 @@
#include "FontDescription.h"
#include "FontOrientation.h"
#include "GlyphBuffer.h"
-#include "HashFunctions.h"
#include "RefPtrCairo.h"
#include <wtf/Forward.h>
+#include <wtf/HashFunctions.h>
typedef struct _FcFontSet FcFontSet;
diff --git a/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp b/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp
index cdced6832..6062e4381 100644
--- a/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp
+++ b/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp
@@ -17,9 +17,9 @@
*/
#include "config.h"
-#include "GLContext.h"
+#include "GLContextGLX.h"
-#if ENABLE(WEBGL) || USE(TEXTURE_MAPPER_GL)
+#if USE(GLX)
#include "GraphicsContext3D.h"
#include "OpenGLShims.h"
#include <GL/glx.h>
@@ -50,17 +50,17 @@ static ActiveContextList& activeContextList()
return activeContexts;
}
-void GLContext::addActiveContext(GLContext* context)
+void GLContextGLX::addActiveContext(GLContextGLX* context)
{
static bool addedAtExitHandler = false;
if (!addedAtExitHandler) {
- atexit(&GLContext::cleanupActiveContextsAtExit);
+ atexit(&GLContextGLX::cleanupActiveContextsAtExit);
addedAtExitHandler = true;
}
activeContextList().append(context);
}
-void GLContext::removeActiveContext(GLContext* context)
+void GLContextGLX::removeActiveContext(GLContext* context)
{
ActiveContextList& contextList = activeContextList();
size_t i = contextList.find(context);
@@ -68,7 +68,7 @@ void GLContext::removeActiveContext(GLContext* context)
contextList.remove(i);
}
-void GLContext::cleanupActiveContextsAtExit()
+void GLContextGLX::cleanupActiveContextsAtExit()
{
ActiveContextList& contextList = activeContextList();
for (size_t i = 0; i < contextList.size(); ++i)
@@ -80,23 +80,12 @@ void GLContext::cleanupActiveContextsAtExit()
gSharedDisplay = 0;
}
-GLContext* GLContext::getCurrent()
+GLContext* GLContextGLX::createOffscreenSharingContext()
{
- ActiveContextList& contextList = activeContextList();
- GLXContext current = glXGetCurrentContext();
- for (size_t i = 0; i < contextList.size(); ++i) {
- if (current == contextList[i]->m_context)
- return contextList[i];
- }
- return 0;
-}
-
-GLContext* GLContext::createSharingContext(GLContext* sharingContext)
-{
- return createContext(0, sharingContext ? sharingContext->m_context : 0);
+ return createContext(0, m_context);
}
-GLContext* GLContext::createWindowContext(XID window, GLXContext sharingContext)
+GLContextGLX* GLContextGLX::createWindowContext(XID window, GLXContext sharingContext)
{
Display* display = sharedDisplay();
XWindowAttributes attributes;
@@ -116,12 +105,12 @@ GLContext* GLContext::createWindowContext(XID window, GLXContext sharingContext)
// GLXPbuffer and XID are both the same types underneath, so we have to share
// a constructor here with the window path.
- GLContext* contextWrapper = new GLContext(context);
+ GLContextGLX* contextWrapper = new GLContextGLX(context);
contextWrapper->m_window = window;
return contextWrapper;
}
-GLContext* GLContext::createPbufferContext(GLXContext sharingContext)
+GLContextGLX* GLContextGLX::createPbufferContext(GLXContext sharingContext)
{
int fbConfigAttributes[] = {
GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
@@ -157,12 +146,12 @@ GLContext* GLContext::createPbufferContext(GLXContext sharingContext)
// GLXPbuffer and XID are both the same types underneath, so we have to share
// a constructor here with the window path.
- GLContext* contextWrapper = new GLContext(context);
+ GLContextGLX* contextWrapper = new GLContextGLX(context);
contextWrapper->m_pbuffer = pbuffer;
return contextWrapper;
}
-GLContext* GLContext::createPixmapContext(GLXContext sharingContext)
+GLContextGLX* GLContextGLX::createPixmapContext(GLXContext sharingContext)
{
static int visualAttributes[] = {
GLX_RGBA,
@@ -197,10 +186,10 @@ GLContext* GLContext::createPixmapContext(GLXContext sharingContext)
return 0;
}
- return new GLContext(context, pixmap, glxPixmap);
+ return new GLContextGLX(context, pixmap, glxPixmap);
}
-GLContext* GLContext::createContext(XID window, GLXContext sharingContext)
+GLContextGLX* GLContextGLX::createContext(XID window, GLXContext sharingContext)
{
if (!sharedDisplay())
return 0;
@@ -214,7 +203,7 @@ GLContext* GLContext::createContext(XID window, GLXContext sharingContext)
if (!success)
return 0;
- GLContext* context = window ? createWindowContext(window, sharingContext) : 0;
+ GLContextGLX* context = window ? createWindowContext(window, sharingContext) : 0;
if (!context)
context = createPbufferContext(sharingContext);
if (!context)
@@ -225,7 +214,7 @@ GLContext* GLContext::createContext(XID window, GLXContext sharingContext)
return context;
}
-GLContext::GLContext(GLXContext context)
+GLContextGLX::GLContextGLX(GLXContext context)
: m_context(context)
, m_window(0)
, m_pbuffer(0)
@@ -235,7 +224,7 @@ GLContext::GLContext(GLXContext context)
addActiveContext(this);
}
-GLContext::GLContext(GLXContext context, Pixmap pixmap, GLXPixmap glxPixmap)
+GLContextGLX::GLContextGLX(GLXContext context, Pixmap pixmap, GLXPixmap glxPixmap)
: m_context(context)
, m_window(0)
, m_pbuffer(0)
@@ -245,7 +234,7 @@ GLContext::GLContext(GLXContext context, Pixmap pixmap, GLXPixmap glxPixmap)
addActiveContext(this);
}
-GLContext::~GLContext()
+GLContextGLX::~GLContextGLX()
{
if (m_context) {
// This may be necessary to prevent crashes with NVidia's closed source drivers. Originally
@@ -270,14 +259,16 @@ GLContext::~GLContext()
removeActiveContext(this);
}
-bool GLContext::canRenderToDefaultFramebuffer()
+bool GLContextGLX::canRenderToDefaultFramebuffer()
{
return m_window;
}
-bool GLContext::makeContextCurrent()
+bool GLContextGLX::makeContextCurrent()
{
ASSERT(m_context && (m_window || m_pbuffer || m_glxPixmap));
+
+ GLContext::makeContextCurrent();
if (glXGetCurrentContext() == m_context)
return true;
@@ -290,14 +281,14 @@ bool GLContext::makeContextCurrent()
return ::glXMakeCurrent(sharedDisplay(), m_glxPixmap, m_context);
}
-void GLContext::swapBuffers()
+void GLContextGLX::swapBuffers()
{
if (m_window)
glXSwapBuffers(sharedDisplay(), m_window);
}
#if ENABLE(WEBGL)
-PlatformGraphicsContext3D GLContext::platformContext()
+PlatformGraphicsContext3D GLContextGLX::platformContext()
{
return m_context;
}
diff --git a/Source/WebCore/platform/graphics/glx/GLContextGLX.h b/Source/WebCore/platform/graphics/glx/GLContextGLX.h
new file mode 100644
index 000000000..0a7a924f9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/glx/GLContextGLX.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef GLContextGLX_h
+#define GLContextGLX_h
+
+#if USE(GLX)
+
+#include "GLContext.h"
+
+typedef struct __GLXcontextRec* GLXContext;
+typedef struct _XDisplay Display;
+typedef struct __GLXcontextRec *GLXContext;
+typedef unsigned long GLXPbuffer;
+typedef unsigned long GLXPixmap;
+typedef unsigned char GLubyte;
+typedef unsigned long Pixmap;
+typedef unsigned long XID;
+typedef void* ContextKeyType;
+
+namespace WebCore {
+
+class GLContextGLX : public GLContext {
+ WTF_MAKE_NONCOPYABLE(GLContextGLX);
+public:
+ static GLContextGLX* createContext(XID, GLXContext sharingContext = 0);
+ static GLContextGLX* createWindowContext(XID window, GLXContext sharingContext);
+ static GLContextGLX* createPbufferContext(GLXContext sharingContext);
+ static GLContextGLX* createPixmapContext(GLXContext sharingContext);
+ static void removeActiveContext(GLContext*);
+
+ virtual ~GLContextGLX();
+ virtual GLContext* createOffscreenSharingContext();
+ virtual bool makeContextCurrent();
+ virtual void swapBuffers();
+ virtual bool canRenderToDefaultFramebuffer();
+
+#if ENABLE(WEBGL)
+ virtual PlatformGraphicsContext3D platformContext();
+#endif
+
+private:
+ static void addActiveContext(GLContextGLX*);
+ static void cleanupActiveContextsAtExit();
+
+ GLContextGLX(GLXContext);
+ GLContextGLX(GLXContext, Pixmap, GLXPixmap);
+
+ GLXContext m_context;
+ Display* m_display;
+ XID m_window;
+ GLXPbuffer m_pbuffer;
+ Pixmap m_pixmap;
+ GLXPixmap m_glxPixmap;
+};
+
+} // namespace WebCore
+
+#endif // USE(GLX)
+
+#endif // GLContextGLX_h
diff --git a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
index d37d604cf..c58c3c6a7 100644
--- a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
@@ -45,13 +45,13 @@ namespace WebCore {
// exceed the global cap will instead clear the buffer.
#if PLATFORM(CHROMIUM) // Currently, this cap only exists for chromium.
static int s_maximumResourceUsePixels = 16 * 1024 * 1024;
-#else
+#elif !PLATFORM(BLACKBERRY)
static int s_maximumResourceUsePixels = 0;
#endif
static int s_currentResourceUsePixels = 0;
static const float s_resourceAdjustedRatio = 0.5;
-PassRefPtr<DrawingBuffer> DrawingBuffer::create(GraphicsContext3D* context, const IntSize& size, bool separateBackingTexture)
+PassRefPtr<DrawingBuffer> DrawingBuffer::create(GraphicsContext3D* context, const IntSize& size, PreserveDrawingBuffer preserve, AlphaRequirement alpha)
{
Extensions3D* extensions = context->getExtensions();
bool multisampleSupported = extensions->supports("GL_ANGLE_framebuffer_blit") && extensions->supports("GL_ANGLE_framebuffer_multisample") && extensions->supports("GL_OES_rgb8_rgba8");
@@ -63,7 +63,7 @@ PassRefPtr<DrawingBuffer> DrawingBuffer::create(GraphicsContext3D* context, cons
bool packedDepthStencilSupported = extensions->supports("GL_OES_packed_depth_stencil");
if (packedDepthStencilSupported)
extensions->ensureEnabled("GL_OES_packed_depth_stencil");
- RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(context, size, multisampleSupported, packedDepthStencilSupported, separateBackingTexture));
+ RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(context, size, multisampleSupported, packedDepthStencilSupported, preserve, alpha));
return (drawingBuffer->m_context) ? drawingBuffer.release() : 0;
}
@@ -83,9 +83,9 @@ void DrawingBuffer::clear()
m_colorBuffer = 0;
}
- if (m_backingColorBuffer) {
- m_context->deleteTexture(m_backingColorBuffer);
- m_backingColorBuffer = 0;
+ if (m_frontColorBuffer) {
+ m_context->deleteTexture(m_frontColorBuffer);
+ m_frontColorBuffer = 0;
}
if (m_multisampleColorBuffer) {
@@ -167,36 +167,10 @@ void DrawingBuffer::resizeDepthStencil(int sampleCount)
m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
}
-void DrawingBuffer::clearFramebuffer()
+void DrawingBuffer::clearFramebuffers(GC3Dbitfield clearMask)
{
m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO ? m_multisampleFBO : m_fbo);
- const GraphicsContext3D::Attributes& attributes = m_context->getContextAttributes();
- float clearDepth = 0;
- int clearStencil = 0;
- unsigned char depthMask = false;
- unsigned int stencilMask = 0xffffffff;
- unsigned char isScissorEnabled = false;
- unsigned clearMask = GraphicsContext3D::COLOR_BUFFER_BIT;
- if (attributes.depth) {
- m_context->getFloatv(GraphicsContext3D::DEPTH_CLEAR_VALUE, &clearDepth);
- m_context->clearDepth(1);
- m_context->getBooleanv(GraphicsContext3D::DEPTH_WRITEMASK, &depthMask);
- m_context->depthMask(true);
- clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
- }
- if (attributes.stencil) {
- m_context->getIntegerv(GraphicsContext3D::STENCIL_CLEAR_VALUE, &clearStencil);
- m_context->clearStencil(0);
- m_context->getIntegerv(GraphicsContext3D::STENCIL_WRITEMASK, reinterpret_cast<int*>(&stencilMask));
- m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xffffffff);
- clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
- }
- isScissorEnabled = m_context->isEnabled(GraphicsContext3D::SCISSOR_TEST);
- m_context->disable(GraphicsContext3D::SCISSOR_TEST);
- float clearColor[4];
- m_context->getFloatv(GraphicsContext3D::COLOR_CLEAR_VALUE, clearColor);
- m_context->clearColor(0, 0, 0, 0);
m_context->clear(clearMask);
// The multisample fbo was just cleared, but we also need to clear the non-multisampled buffer too.
@@ -205,21 +179,6 @@ void DrawingBuffer::clearFramebuffer()
m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
}
-
- m_context->clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
-
- if (attributes.depth) {
- m_context->clearDepth(clearDepth);
- m_context->depthMask(depthMask);
- }
- if (attributes.stencil) {
- m_context->clearStencil(clearStencil);
- m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, stencilMask);
- }
- if (isScissorEnabled)
- m_context->enable(GraphicsContext3D::SCISSOR_TEST);
- else
- m_context->disable(GraphicsContext3D::SCISSOR_TEST);
}
bool DrawingBuffer::reset(const IntSize& newSize)
@@ -301,9 +260,9 @@ bool DrawingBuffer::reset(const IntSize& newSize)
m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0);
- // resize the backing color buffer
- if (m_separateBackingTexture) {
- m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_backingColorBuffer);
+ // resize the front color buffer
+ if (m_separateFrontTexture) {
+ m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_frontColorBuffer);
m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE, 0);
}
@@ -327,7 +286,23 @@ bool DrawingBuffer::reset(const IntSize& newSize)
}
}
- clearFramebuffer();
+ m_context->disable(GraphicsContext3D::SCISSOR_TEST);
+ m_context->clearColor(0, 0, 0, 0);
+ m_context->colorMask(true, true, true, true);
+
+ GC3Dbitfield clearMask = GraphicsContext3D::COLOR_BUFFER_BIT;
+ if (attributes.depth) {
+ m_context->clearDepth(1.0f);
+ clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
+ m_context->depthMask(true);
+ }
+ if (attributes.stencil) {
+ m_context->clearStencil(0);
+ clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
+ m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xFFFFFFFF);
+ }
+
+ clearFramebuffers(clearMask);
return true;
}
@@ -361,6 +336,14 @@ void DrawingBuffer::commit(long x, long y, long width, long height)
m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
}
+void DrawingBuffer::restoreFramebufferBinding()
+{
+ if (!m_context || !m_framebufferBinding)
+ return;
+
+ m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_framebufferBinding);
+}
+
bool DrawingBuffer::multisample() const
{
return m_context && m_context->getContextAttributes().antialias && m_multisampleExtensionSupported;
@@ -374,7 +357,7 @@ PassRefPtr<ImageData> DrawingBuffer::paintRenderingResultsToImageData()
void DrawingBuffer::discardResources()
{
m_colorBuffer = 0;
- m_backingColorBuffer = 0;
+ m_frontColorBuffer = 0;
m_multisampleColorBuffer = 0;
m_depthStencilBuffer = 0;
diff --git a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h
index 039af5c68..a84dcdc13 100644
--- a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h
+++ b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h
@@ -48,19 +48,31 @@ class CanvasRenderingContext;
class GraphicsContext3D;
class ImageData;
#if PLATFORM(CHROMIUM)
-class WebGLLayerChromium;
+class DrawingBufferPrivate;
#endif
// Manages a rendering target (framebuffer + attachment) for a canvas. Can publish its rendering
// results to a PlatformLayer for compositing.
class DrawingBuffer : public RefCounted<DrawingBuffer> {
public:
- static PassRefPtr<DrawingBuffer> create(GraphicsContext3D*, const IntSize&, bool);
+ enum PreserveDrawingBuffer {
+ Preserve,
+ Discard
+ };
+
+ enum AlphaRequirement {
+ Alpha,
+ Opaque
+ };
+
+ static PassRefPtr<DrawingBuffer> create(GraphicsContext3D*, const IntSize&, PreserveDrawingBuffer, AlphaRequirement);
friend class GraphicsContext3D;
~DrawingBuffer();
- void clearFramebuffer();
+ // Issues a glClear() on all framebuffers associated with this DrawingBuffer. The caller is responsible for
+ // making the context current and setting the clear values and masks. Modifies the framebuffer binding.
+ void clearFramebuffers(GC3Dbitfield clearMask);
// Returns true if the buffer was successfully resized.
bool reset(const IntSize&);
@@ -87,7 +99,14 @@ public:
// The DrawingBuffer needs to track the texture bound to texture unit 0.
// The bound texture is tracked to avoid costly queries during rendering.
- void setTexture2DBinding(GC3Dint texture) { m_texture2DBinding = texture; }
+ void setTexture2DBinding(Platform3DObject texture) { m_texture2DBinding = texture; }
+
+ // The DrawingBuffer needs to track the currently bound framebuffer so it
+ // restore the binding when needed.
+ void setFramebufferBinding(Platform3DObject fbo) { m_framebufferBinding = fbo; }
+
+ // Bind to the m_framebufferBinding if it's not 0.
+ void restoreFramebufferBinding();
// Track the currently active texture unit. Texture unit 0 is used as host for a scratch
// texture.
@@ -95,7 +114,6 @@ public:
bool multisample() const;
- Platform3DObject platformColorBuffer() const;
Platform3DObject framebuffer() const;
PassRefPtr<ImageData> paintRenderingResultsToImageData();
@@ -106,21 +124,25 @@ public:
#if USE(ACCELERATED_COMPOSITING)
PlatformLayer* platformLayer();
- void publishToPlatformLayer();
+ void prepareBackBuffer();
+ bool requiresCopyFromBackToFrontBuffer() const;
+ unsigned frontColorBuffer() const;
void paintCompositedResultsToCanvas(CanvasRenderingContext*);
#endif
- PassRefPtr<GraphicsContext3D> graphicsContext3D() const { return m_context; }
+ GraphicsContext3D* graphicsContext3D() const { return m_context.get(); }
private:
DrawingBuffer(GraphicsContext3D*, const IntSize&, bool multisampleExtensionSupported,
- bool packedDepthStencilExtensionSupported, bool separateBackingTexture);
+ bool packedDepthStencilExtensionSupported, PreserveDrawingBuffer, AlphaRequirement);
void initialize(const IntSize&);
- bool m_separateBackingTexture;
+ PreserveDrawingBuffer m_preserveDrawingBuffer;
+ AlphaRequirement m_alpha;
bool m_scissorEnabled;
Platform3DObject m_texture2DBinding;
+ Platform3DObject m_framebufferBinding;
GC3Denum m_activeTextureUnit;
RefPtr<GraphicsContext3D> m_context;
@@ -129,7 +151,8 @@ private:
bool m_packedDepthStencilExtensionSupported;
Platform3DObject m_fbo;
Platform3DObject m_colorBuffer;
- Platform3DObject m_backingColorBuffer;
+ Platform3DObject m_frontColorBuffer;
+ bool m_separateFrontTexture;
// This is used when we have OES_packed_depth_stencil.
Platform3DObject m_depthStencilBuffer;
@@ -143,7 +166,7 @@ private:
Platform3DObject m_multisampleColorBuffer;
#if PLATFORM(CHROMIUM)
- RefPtr<WebGLLayerChromium> m_platformLayer;
+ OwnPtr<DrawingBufferPrivate> m_private;
#endif
#if PLATFORM(MAC)
diff --git a/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp b/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
index 24af3d8c9..6cd9ee57f 100644
--- a/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
+++ b/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
@@ -27,22 +27,81 @@
#include "config.h"
#include "SharedGraphicsContext3D.h"
+#include "Extensions3D.h"
+#include "cc/CCProxy.h"
namespace WebCore {
-GraphicsContext3D* SharedGraphicsContext3D::get()
+class SharedGraphicsContext3DImpl {
+public:
+ SharedGraphicsContext3DImpl() : m_context(0) { }
+ PassRefPtr<GraphicsContext3D> getOrCreateContext()
+ {
+ // If we lost the context, or can't make it current, create a new one.
+ if (m_context && (!m_context->makeContextCurrent() || (m_context->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR)))
+ m_context.clear();
+
+ if (!m_context)
+ createContext();
+
+ if (m_context && !m_context->makeContextCurrent())
+ m_context.clear();
+
+ return m_context;
+ }
+
+ PassRefPtr<GraphicsContext3D> getContext()
+ {
+ return m_context;
+ }
+
+ PassRefPtr<GraphicsContext3D> createContext()
+ {
+ GraphicsContext3D::Attributes attributes;
+ attributes.depth = false;
+ attributes.stencil = true;
+ attributes.antialias = false;
+ attributes.shareResources = true;
+ attributes.preferDiscreteGPU = true;
+ m_context = GraphicsContext3D::create(attributes, 0);
+ return m_context;
+ }
+private:
+ RefPtr<GraphicsContext3D> m_context;
+};
+
+PassRefPtr<GraphicsContext3D> SharedGraphicsContext3D::get()
+{
+ DEFINE_STATIC_LOCAL(SharedGraphicsContext3DImpl, impl, ());
+ return impl.getOrCreateContext();
+}
+
+enum ContextOperation {
+ Get, Create
+};
+
+static PassRefPtr<GraphicsContext3D> getOrCreateContextForImplThread(ContextOperation op)
+{
+ DEFINE_STATIC_LOCAL(SharedGraphicsContext3DImpl, impl, ());
+ return op == Create ? impl.createContext() : impl.getContext();
+}
+
+PassRefPtr<GraphicsContext3D> SharedGraphicsContext3D::getForImplThread()
+{
+ ASSERT(CCProxy::isImplThread());
+ return getOrCreateContextForImplThread(Get);
+}
+
+bool SharedGraphicsContext3D::haveForImplThread()
+{
+ ASSERT(CCProxy::isMainThread());
+ return getOrCreateContextForImplThread(Get);
+}
+
+bool SharedGraphicsContext3D::createForImplThread()
{
- GraphicsContext3D::Attributes attributes;
- attributes.depth = false;
- attributes.stencil = true;
- attributes.antialias = false;
- attributes.canRecoverFromContextLoss = false; // Canvas contexts can not handle lost contexts.
- attributes.shareResources = true;
- attributes.preferDiscreteGPU = true;
- static GraphicsContext3D* context = GraphicsContext3D::create(attributes, 0).leakRef();
- if (context && !context->makeContextCurrent())
- context = 0;
- return context;
+ ASSERT(CCProxy::isMainThread());
+ return getOrCreateContextForImplThread(Create);
}
}
diff --git a/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h b/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h
index eb2edcb07..850e63e91 100644
--- a/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h
+++ b/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h
@@ -34,7 +34,21 @@ namespace WebCore {
class SharedGraphicsContext3D {
public:
- static GraphicsContext3D* get();
+ // The caller may ref this pointer, and hang onto it as long as they like.
+ // However, the context should be checked periodically to determine if it
+ // has been lost. The easiest way to do that is to simply call this
+ // function again. Note that the return value may be 0 if the
+ // GPU is unavailable.
+ static PassRefPtr<GraphicsContext3D> get();
+ // This one returns the context, and does not touch it or re-create it.
+ // Should only be called on the impl thread.
+ static PassRefPtr<GraphicsContext3D> getForImplThread();
+ // This one returns if the threaded utility context exists.
+ // Should only be called on the main thread.
+ static bool haveForImplThread();
+ // This call creates the context unconditionally, but does not touch it.
+ // Should only be called on the main thread.
+ static bool createForImplThread();
};
}
diff --git a/Source/WebCore/platform/graphics/gpu/Texture.cpp b/Source/WebCore/platform/graphics/gpu/Texture.cpp
index 5ff7d811f..7c2b86e21 100644
--- a/Source/WebCore/platform/graphics/gpu/Texture.cpp
+++ b/Source/WebCore/platform/graphics/gpu/Texture.cpp
@@ -90,7 +90,13 @@ PassRefPtr<Texture> Texture::create(GraphicsContext3D* context, Format format, i
int maxTextureSize = 0;
context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize);
TilingData tiling(maxTextureSize, width, height, true);
- int numTiles = tiling.numTiles();
+
+ // Check for overflow.
+ int numTiles = tiling.numTilesX() * tiling.numTilesY();
+ if (numTiles / tiling.numTilesX() != tiling.numTilesY()) {
+ tiling.setTotalSize(0, 0);
+ numTiles = 0;
+ }
OwnPtr<Vector<unsigned int> > textureIds = adoptPtr(new Vector<unsigned int>(numTiles));
textureIds->fill(0, numTiles);
@@ -104,7 +110,9 @@ PassRefPtr<Texture> Texture::create(GraphicsContext3D* context, Format format, i
}
textureIds->at(i) = textureId;
- IntRect tileBoundsWithBorder = tiling.tileBoundsWithBorder(i);
+ int xIndex = i % tiling.numTilesX();
+ int yIndex = i / tiling.numTilesX();
+ IntRect tileBoundsWithBorder = tiling.tileBoundsWithBorder(xIndex, yIndex);
unsigned int glFormat = 0;
unsigned int glType = 0;
@@ -168,9 +176,12 @@ void Texture::updateSubRect(void* pixels, const IntRect& updateRect)
min(m_tiles.maxTextureSize(), m_tiles.borderTexels() + updateRectSanitized.height());
OwnArrayPtr<uint32_t> tempBuff = adoptArrayPtr(new uint32_t[tempBuffSize]);
- for (int tile = 0; tile < m_tiles.numTiles(); tile++) {
+ for (int tile = 0; tile < m_tiles.numTilesX() * m_tiles.numTilesY(); tile++) {
+ int xIndex = tile % m_tiles.numTilesX();
+ int yIndex = tile / m_tiles.numTilesX();
+
// Intersect with tile
- IntRect tileBoundsWithBorder = m_tiles.tileBoundsWithBorder(tile);
+ IntRect tileBoundsWithBorder = m_tiles.tileBoundsWithBorder(xIndex, yIndex);
IntRect updateRectIntersected = updateRectSanitized;
updateRectIntersected.intersect(tileBoundsWithBorder);
diff --git a/Source/WebCore/platform/graphics/gpu/TilingData.cpp b/Source/WebCore/platform/graphics/gpu/TilingData.cpp
index 20db441ce..6bad62844 100644
--- a/Source/WebCore/platform/graphics/gpu/TilingData.cpp
+++ b/Source/WebCore/platform/graphics/gpu/TilingData.cpp
@@ -99,23 +99,21 @@ int TilingData::tileYIndexFromSrcCoord(int srcPos) const
return min(max(y, 0), numTilesY() - 1);
}
-IntRect TilingData::tileBounds(int tile) const
+IntRect TilingData::tileBounds(int i, int j) const
{
- assertTile(tile);
- int ix = tileXIndex(tile);
- int iy = tileYIndex(tile);
- int x = tilePositionX(ix);
- int y = tilePositionY(iy);
- int width = tileSizeX(ix);
- int height = tileSizeY(iy);
+ assertTile(i, j);
+ int x = tilePositionX(i);
+ int y = tilePositionY(j);
+ int width = tileSizeX(i);
+ int height = tileSizeY(j);
ASSERT(x >= 0 && y >= 0 && width >= 0 && height >= 0);
ASSERT(x <= totalSizeX() && y <= totalSizeY());
return IntRect(x, y, width, height);
}
-IntRect TilingData::tileBoundsWithBorder(int tile) const
+IntRect TilingData::tileBoundsWithBorder(int i, int j) const
{
- IntRect bounds = tileBounds(tile);
+ IntRect bounds = tileBounds(i, j);
if (m_borderTexels) {
int x1 = bounds.x();
@@ -123,13 +121,13 @@ IntRect TilingData::tileBoundsWithBorder(int tile) const
int y1 = bounds.y();
int y2 = bounds.maxY();
- if (tileXIndex(tile) > 0)
+ if (i > 0)
x1--;
- if (tileXIndex(tile) < (numTilesX() - 1))
+ if (i < (numTilesX() - 1))
x2++;
- if (tileYIndex(tile) > 0)
+ if (j > 0)
y1--;
- if (tileYIndex(tile) < (numTilesY() - 1))
+ if (j < (numTilesY() - 1))
y2++;
bounds = IntRect(x1, y1, x2 - x1, y2 - y1);
@@ -138,10 +136,10 @@ IntRect TilingData::tileBoundsWithBorder(int tile) const
return bounds;
}
-FloatRect TilingData::tileBoundsNormalized(int tile) const
+FloatRect TilingData::tileBoundsNormalized(int i, int j) const
{
- assertTile(tile);
- FloatRect bounds(tileBounds(tile));
+ assertTile(i, j);
+ FloatRect bounds(tileBounds(i, j));
bounds.scale(1.0f / m_totalSizeX, 1.0f / m_totalSizeY);
return bounds;
}
@@ -216,36 +214,6 @@ IntRect TilingData::overlappedTileIndices(const WebCore::FloatRect &srcRect) con
return overlappedTileIndices(enclosingIntRect(srcRect));
}
-void TilingData::intersectDrawQuad(const FloatRect& srcRect, const FloatRect& dstRect, int tile,
- FloatRect* newSrc, FloatRect* newDst) const
-{
- // Intersect with tile
- FloatRect tileBounds = this->tileBounds(tile);
- FloatRect srcRectIntersected = srcRect;
- srcRectIntersected.intersect(tileBounds);
-
- if (srcRectIntersected.isEmpty()) {
- *newSrc = *newDst = FloatRect(0, 0, 0, 0);
- return;
- }
-
- float srcRectIntersectedNormX = (srcRectIntersected.x() - srcRect.x()) / srcRect.width();
- float srcRectIntersectedNormY = (srcRectIntersected.y() - srcRect.y()) / srcRect.height();
- float srcRectIntersectedNormW = srcRectIntersected.width() / srcRect.width();
- float srcRectIntersectedNormH = srcRectIntersected.height() / srcRect.height();
-
- *newSrc = srcRectIntersected;
- newSrc->move(
- -tileBounds.x() + ((tileXIndex(tile) > 0) ? m_borderTexels : 0),
- -tileBounds.y() + ((tileYIndex(tile) > 0) ? m_borderTexels : 0));
-
- *newDst = FloatRect(
- srcRectIntersectedNormX * dstRect.width() + dstRect.x(),
- srcRectIntersectedNormY * dstRect.height() + dstRect.y(),
- srcRectIntersectedNormW * dstRect.width(),
- srcRectIntersectedNormH * dstRect.height());
-}
-
IntPoint TilingData::textureOffset(int xIndex, int yIndex) const
{
int left = (!xIndex || m_numTilesX == 1) ? 0 : m_borderTexels;
diff --git a/Source/WebCore/platform/graphics/gpu/TilingData.h b/Source/WebCore/platform/graphics/gpu/TilingData.h
index bc861ef68..146dfe19b 100644
--- a/Source/WebCore/platform/graphics/gpu/TilingData.h
+++ b/Source/WebCore/platform/graphics/gpu/TilingData.h
@@ -50,18 +50,15 @@ public:
void setHasBorderTexels(bool);
int borderTexels() const { return m_borderTexels; }
- int numTiles() const { return numTilesX() * numTilesY(); }
+ bool hasEmptyBounds() const { return !numTilesX() || !numTilesY(); }
int numTilesX() const { return m_numTilesX; }
int numTilesY() const { return m_numTilesY; }
- int tileIndex(int x, int y) const { return x + y * numTilesX(); }
- int tileXIndex(int tile) const { assertTile(tile); return tile % numTilesX(); }
- int tileYIndex(int tile) const { assertTile(tile); return tile / numTilesX(); }
int tileXIndexFromSrcCoord(int) const;
int tileYIndexFromSrcCoord(int) const;
- IntRect tileBounds(int tile) const;
- IntRect tileBoundsWithBorder(int tile) const;
- FloatRect tileBoundsNormalized(int tile) const;
+ IntRect tileBounds(int, int) const;
+ IntRect tileBoundsWithBorder(int, int) const;
+ FloatRect tileBoundsNormalized(int, int) const;
int tilePositionX(int xIndex) const;
int tilePositionY(int yIndex) const;
int tileSizeX(int xIndex) const;
@@ -69,16 +66,12 @@ public:
IntRect overlappedTileIndices(const IntRect& srcRect) const;
IntRect overlappedTileIndices(const FloatRect& srcRect) const;
- // Given a set of source and destination coordinates for a drawing quad
- // in texel units, returns adjusted data to render just the one tile.
- void intersectDrawQuad(const FloatRect& srcRect, const FloatRect& dstRect, int tile, FloatRect* newSrc, FloatRect* newDst) const;
-
// Difference between tileBound's and tileBoundWithBorder's location().
IntPoint textureOffset(int xIndex, int yIndex) const;
private:
TilingData() : m_maxTextureSize(0), m_totalSizeX(0), m_totalSizeY(0) {}
- void assertTile(int tile) const { ASSERT_UNUSED(tile, tile >= 0 && tile < numTiles()); }
+ void assertTile(int i, int j) const { ASSERT_UNUSED(i, i >= 0 && i < numTilesX()); ASSERT_UNUSED(j, j >= 0 && j < numTilesY()); }
void recomputeNumTiles();
int m_maxTextureSize;
diff --git a/Source/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm b/Source/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm
index 3fda6a326..5154fd715 100644
--- a/Source/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm
+++ b/Source/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm
@@ -40,10 +40,13 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
const IntSize& size,
bool multisampleExtensionSupported,
bool packedDepthStencilExtensionSupported,
- bool separateBackingTexture)
- : m_separateBackingTexture(separateBackingTexture)
+ PreserveDrawingBuffer preserveDrawingBuffer,
+ AlphaRequirement alpha)
+ : m_preserveDrawingBuffer(preserveDrawingBuffer)
+ , m_alpha(alpha)
, m_scissorEnabled(false)
, m_texture2DBinding(0)
+ , m_framebufferBinding(0)
, m_activeTextureUnit(GraphicsContext3D::TEXTURE0)
, m_context(context)
, m_size(-1, -1)
@@ -51,15 +54,14 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
, m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupported)
, m_fbo(context->createFramebuffer())
, m_colorBuffer(0)
+ , m_frontColorBuffer(0)
+ , m_separateFrontTexture(false)
, m_depthStencilBuffer(0)
, m_depthBuffer(0)
, m_stencilBuffer(0)
, m_multisampleFBO(0)
, m_multisampleColorBuffer(0)
{
- // Support for a separate backing texture has only been enabled for
- // the chromium port.
- ASSERT(!m_separateBackingTexture);
ASSERT(m_fbo);
if (!m_fbo) {
clear();
@@ -92,16 +94,27 @@ DrawingBuffer::~DrawingBuffer()
clear();
}
+#if USE(ACCELERATED_COMPOSITING)
PlatformLayer* DrawingBuffer::platformLayer()
{
return m_platformLayer.get();
}
-Platform3DObject DrawingBuffer::platformColorBuffer() const
+void DrawingBuffer::prepareBackBuffer()
{
- return m_colorBuffer;
}
+bool DrawingBuffer::requiresCopyFromBackToFrontBuffer() const
+{
+ return false;
+}
+
+unsigned DrawingBuffer::frontColorBuffer() const
+{
+ return colorBuffer();
+}
+#endif
+
}
#endif
diff --git a/Source/WebCore/platform/graphics/gpu/qt/DrawingBufferQt.cpp b/Source/WebCore/platform/graphics/gpu/qt/DrawingBufferQt.cpp
index a592edcf7..5eeac100a 100644
--- a/Source/WebCore/platform/graphics/gpu/qt/DrawingBufferQt.cpp
+++ b/Source/WebCore/platform/graphics/gpu/qt/DrawingBufferQt.cpp
@@ -35,10 +35,13 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
const IntSize& size,
bool multisampleExtensionSupported,
bool packedDepthStencilExtensionSupported,
- bool separateBackingTexture)
- : m_separateBackingTexture(separateBackingTexture)
+ PreserveDrawingBuffer preserveDrawingBuffer,
+ AlphaRequirement alpha)
+ : m_preserveDrawingBuffer(preserveDrawingBuffer)
+ , m_alpha(alpha)
, m_scissorEnabled(false)
, m_texture2DBinding(0)
+ , m_framebufferBinding(0)
, m_activeTextureUnit(GraphicsContext3D::TEXTURE0)
, m_context(context)
, m_size(-1, -1)
@@ -46,15 +49,14 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
, m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupported)
, m_fbo(context->createFramebuffer())
, m_colorBuffer(0)
+ , m_frontColorBuffer(0)
+ , m_separateFrontTexture(false)
, m_depthStencilBuffer(0)
, m_depthBuffer(0)
, m_stencilBuffer(0)
, m_multisampleFBO(0)
, m_multisampleColorBuffer(0)
{
- // Support for a separate backing texture has only been enabled for
- // the chromium port.
- ASSERT(!m_separateBackingTexture);
ASSERT(m_fbo);
if (!m_fbo) {
clear();
@@ -84,14 +86,21 @@ PlatformLayer* DrawingBuffer::platformLayer()
{
return 0;
}
-#endif
-Platform3DObject DrawingBuffer::platformColorBuffer() const
+void DrawingBuffer::prepareBackBuffer()
{
- return m_colorBuffer;
}
-#if USE(ACCELERATED_COMPOSITING)
+bool DrawingBuffer::requiresCopyFromBackToFrontBuffer() const
+{
+ return false;
+}
+
+unsigned DrawingBuffer::frontColorBuffer() const
+{
+ return colorBuffer();
+}
+
void DrawingBuffer::paintCompositedResultsToCanvas(CanvasRenderingContext* context)
{
}
diff --git a/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.cpp
index b8538707c..062e3fc97 100644
--- a/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.cpp
@@ -120,5 +120,45 @@ template <> void derefGPtr<GstTask>(GstTask* ptr)
gst_object_unref(ptr);
}
+template <> GRefPtr<GstBus> adoptGRef(GstBus* ptr)
+{
+ ASSERT(!GST_OBJECT_IS_FLOATING(GST_OBJECT(ptr)));
+ return GRefPtr<GstBus>(ptr, GRefPtrAdopt);
+}
+
+template <> GstBus* refGPtr<GstBus>(GstBus* ptr)
+{
+ if (ptr)
+ webkitGstObjectRefSink(GST_OBJECT(ptr));
+
+ return ptr;
+}
+
+template <> void derefGPtr<GstBus>(GstBus* ptr)
+{
+ if (ptr)
+ gst_object_unref(ptr);
+}
+
+template <> GRefPtr<GstElementFactory> adoptGRef(GstElementFactory* ptr)
+{
+ ASSERT(!GST_OBJECT_IS_FLOATING(GST_OBJECT(ptr)));
+ return GRefPtr<GstElementFactory>(ptr, GRefPtrAdopt);
+}
+
+template <> GstElementFactory* refGPtr<GstElementFactory>(GstElementFactory* ptr)
+{
+ if (ptr)
+ webkitGstObjectRefSink(GST_OBJECT(ptr));
+
+ return ptr;
+}
+
+template <> void derefGPtr<GstElementFactory>(GstElementFactory* ptr)
+{
+ if (ptr)
+ gst_object_unref(ptr);
+}
+
}
#endif // USE(GSTREAMER)
diff --git a/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.h
index a782d74e8..a3dcda8ae 100644
--- a/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.h
+++ b/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.h
@@ -21,13 +21,15 @@
#define GRefPtrGStreamer_h
#if USE(GSTREAMER)
-#include "GRefPtr.h"
+#include <wtf/gobject/GRefPtr.h>
typedef struct _GstElement GstElement;
typedef struct _GstPad GstPad;
typedef struct _GstPadTemplate GstPadTemplate;
typedef struct _GstCaps GstCaps;
typedef struct _GstTask GstTask;
+typedef struct _GstBus GstBus;
+typedef struct _GstElementFactory GstElementFactory;
namespace WTF {
@@ -50,6 +52,14 @@ template<> GRefPtr<GstTask> adoptGRef(GstTask* ptr);
template<> GstTask* refGPtr<GstTask>(GstTask* ptr);
template<> void derefGPtr<GstTask>(GstTask* ptr);
+template<> GRefPtr<GstBus> adoptGRef(GstBus* ptr);
+template<> GstBus* refGPtr<GstBus>(GstBus* ptr);
+template<> void derefGPtr<GstBus>(GstBus* ptr);
+
+template<> GRefPtr<GstElementFactory> adoptGRef(GstElementFactory* ptr);
+template<> GstElementFactory* refGPtr<GstElementFactory>(GstElementFactory* ptr);
+template<> void derefGPtr<GstElementFactory>(GstElementFactory* ptr);
+
}
#endif // USE(GSTREAMER)
diff --git a/Source/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h b/Source/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h
index e7862dea5..dff47b008 100644
--- a/Source/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h
+++ b/Source/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h
@@ -22,10 +22,12 @@
#define GStreamerGWorld_h
#if ENABLE(VIDEO) && USE(GSTREAMER) && !defined(GST_API_VERSION_1)
-#include "GOwnPtr.h"
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/gobject/GOwnPtr.h>
+
#include "PlatformVideoWindow.h"
-#include "RefCounted.h"
-#include "RefPtr.h"
+
#include <glib.h>
typedef struct _GstElement GstElement;
diff --git a/Source/WebCore/platform/graphics/gstreamer/GStreamerUtilities.cpp b/Source/WebCore/platform/graphics/gstreamer/GStreamerUtilities.cpp
new file mode 100644
index 000000000..ac363a75d
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gstreamer/GStreamerUtilities.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#include "config.h"
+#include "GStreamerUtilities.h"
+
+#include <gst/gst.h>
+#include <wtf/gobject/GOwnPtr.h>
+
+#if USE(GSTREAMER)
+
+namespace WebCore {
+
+bool initializeGStreamer()
+{
+ GOwnPtr<GError> error;
+ // FIXME: We should probably pass the arguments from the command line.
+ bool gstInitialized = gst_init_check(0, 0, &error.outPtr());
+ ASSERT_WITH_MESSAGE(gstInitialized, "GStreamer initialization failed: %s", error ? error->message : "unknown error occurred");
+ return gstInitialized;
+}
+
+}
+
+#endif // ENABLE(WEB_AUDIO) && USE(GSTREAMER)
diff --git a/Source/WebCore/platform/graphics/gstreamer/GStreamerUtilities.h b/Source/WebCore/platform/graphics/gstreamer/GStreamerUtilities.h
new file mode 100644
index 000000000..b9eb165e4
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gstreamer/GStreamerUtilities.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+namespace WebCore {
+bool initializeGStreamer();
+}
diff --git a/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp b/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp
index 8b3a07619..a0bf5f431 100644
--- a/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp
@@ -22,7 +22,7 @@
#if ENABLE(VIDEO) && USE(GSTREAMER)
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
using namespace std;
using namespace WebCore;
diff --git a/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerQt.cpp b/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerQt.cpp
index 188c0bb0e..36b08061e 100644
--- a/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerQt.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerQt.cpp
@@ -21,7 +21,7 @@
#include "ImageGStreamer.h"
#if ENABLE(VIDEO) && USE(GSTREAMER)
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
using namespace std;
using namespace WebCore;
diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
index 03066dc97..d0993c25c 100644
--- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
@@ -31,10 +31,12 @@
#include "Frame.h"
#include "FrameView.h"
#include "GStreamerGWorld.h"
+#include "GStreamerUtilities.h"
#include "GStreamerVersioning.h"
#include "GraphicsContext.h"
#include "GraphicsTypes.h"
#include "ImageGStreamer.h"
+#include "ImageOrientation.h"
#include "IntRect.h"
#include "KURL.h"
#include "MIMETypeRegistry.h"
@@ -44,11 +46,11 @@
#include "TimeRanges.h"
#include "VideoSinkGStreamer.h"
#include "WebKitWebSourceGStreamer.h"
-#include <GOwnPtr.h>
#include <gst/gst.h>
#include <gst/video/video.h>
#include <limits>
#include <math.h>
+#include <wtf/gobject/GOwnPtr.h>
#include <wtf/text/CString.h>
#ifdef GST_API_VERSION_1
@@ -174,35 +176,25 @@ void MediaPlayerPrivateGStreamer::registerMediaEngine(MediaEngineRegistrar regis
registrar(create, getSupportedTypes, supportsType, 0, 0, 0);
}
-static bool gstInitialized = false;
-
-static bool doGstInit()
+bool initializeGStreamerAndRegisterWebKitElements()
{
- // FIXME: We should pass the arguments from the command line
- if (!gstInitialized) {
- GOwnPtr<GError> error;
- gstInitialized = gst_init_check(0, 0, &error.outPtr());
- if (!gstInitialized)
- LOG_VERBOSE(Media, "Could not initialize GStreamer: %s",
- error ? error->message : "unknown error occurred");
- else
- gst_element_register(0, "webkitwebsrc", GST_RANK_PRIMARY + 100,
- WEBKIT_TYPE_WEB_SRC);
- }
- return gstInitialized;
+ if (!initializeGStreamer())
+ return false;
+
+ GRefPtr<GstElementFactory> srcFactory = gst_element_factory_find("webkitwebsrc");
+ if (!srcFactory)
+ return gst_element_register(0, "webkitwebsrc", GST_RANK_PRIMARY + 100, WEBKIT_TYPE_WEB_SRC);
+
+ return true;
}
bool MediaPlayerPrivateGStreamer::isAvailable()
{
- if (!doGstInit())
+ if (!initializeGStreamerAndRegisterWebKitElements())
return false;
- GstElementFactory* factory = gst_element_factory_find(gPlaybinName);
- if (factory) {
- gst_object_unref(GST_OBJECT(factory));
- return true;
- }
- return false;
+ GRefPtr<GstElementFactory> factory = gst_element_factory_find(gPlaybinName);
+ return factory;
}
MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer(MediaPlayer* player)
@@ -243,7 +235,7 @@ MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer(MediaPlayer* player)
, m_videoTimerHandler(0)
, m_webkitAudioSink(0)
{
- if (doGstInit())
+ if (initializeGStreamerAndRegisterWebKitElements())
createGSTPlayBin();
}
@@ -1365,10 +1357,10 @@ void MediaPlayerPrivateGStreamer::timeChanged()
void MediaPlayerPrivateGStreamer::didEnd()
{
// EOS was reached but in case of reverse playback the position is
- // not always 0. So to not confuse the HTMLMediaElement we
- // synchronize position and duration values.
+ // not always 0. So to not confuse the HTMLMediaElement, if we're
+ // doing reverse playback, we synchronize position and duration values.
float now = currentTime();
- if (now > 0) {
+ if (now > 0 && m_playbackRate < 0) {
m_mediaDuration = now;
m_mediaDurationKnown = true;
m_player->durationChanged();
@@ -1497,13 +1489,13 @@ void MediaPlayerPrivateGStreamer::paint(GraphicsContext* context, const IntRect&
return;
context->drawImage(reinterpret_cast<Image*>(gstImage->image().get()), ColorSpaceSRGB,
- rect, CompositeCopy, false);
+ rect, CompositeCopy, DoNotRespectImageOrientation, false);
}
static HashSet<String> mimeTypeCache()
{
- doGstInit();
+ initializeGStreamerAndRegisterWebKitElements();
DEFINE_STATIC_LOCAL(HashSet<String>, cache, ());
static bool typeListInitialized = false;
diff --git a/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
index 2a0af0c86..d1d914761 100644
--- a/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
@@ -23,19 +23,21 @@
#include "Document.h"
#include "Frame.h"
-#include "GOwnPtr.h"
-#include "GRefPtr.h"
#include "GRefPtrGStreamer.h"
#include "MediaPlayer.h"
#include "NetworkingContext.h"
-#include "Noncopyable.h"
#include "NotImplemented.h"
#include "ResourceHandleClient.h"
#include "ResourceHandleInternal.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
+
#include <gst/app/gstappsrc.h>
#include <gst/pbutils/missing-plugins.h>
+
+#include <wtf/Noncopyable.h>
+#include <wtf/gobject/GOwnPtr.h>
+#include <wtf/gobject/GRefPtr.h>
#include <wtf/text/CString.h>
using namespace WebCore;
diff --git a/Source/WebCore/platform/graphics/gtk/GLContextGtk.cpp b/Source/WebCore/platform/graphics/gtk/GLContextGtk.cpp
index 6b2461a03..d460d12c0 100644
--- a/Source/WebCore/platform/graphics/gtk/GLContextGtk.cpp
+++ b/Source/WebCore/platform/graphics/gtk/GLContextGtk.cpp
@@ -19,6 +19,7 @@
#include "config.h"
#include "GLContext.h"
+#include "GLContextGLX.h"
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
@@ -54,10 +55,14 @@ GLContext* GLContext::getContextForWidget(GtkWidget* widget)
if (!g_signal_handler_find(widget, G_SIGNAL_MATCH_FUNC, 0, 0, 0, reinterpret_cast<void*>(shutdownGLContext), 0))
g_signal_connect(widget, "unmap", G_CALLBACK(shutdownGLContext), 0);
+ GLContext* context = 0;
+
+#if USE(GLX)
// If this GDK window doesn't have its own native window then, we don't want
// to use it for rendering, since we'll be drawing over some other widget's area.
GdkWindow* gdkWindow = gtk_widget_get_window(widget);
- GLContext* context = gdkWindow && gdk_window_has_native(gdkWindow) ? createContext(GDK_WINDOW_XID(gdkWindow)) : createContext(0);
+ context = gdkWindow && gdk_window_has_native(gdkWindow) ? GLContextGLX::createContext(GDK_WINDOW_XID(gdkWindow)) : GLContextGLX::createContext(0);
+#endif
if (!context)
return 0;
diff --git a/Source/WebCore/platform/graphics/gtk/IconGtk.cpp b/Source/WebCore/platform/graphics/gtk/IconGtk.cpp
index 7fdc1f678..3e957b345 100644
--- a/Source/WebCore/platform/graphics/gtk/IconGtk.cpp
+++ b/Source/WebCore/platform/graphics/gtk/IconGtk.cpp
@@ -32,9 +32,11 @@
#include "GraphicsContext.h"
#include "MIMETypeRegistry.h"
-#include "PassRefPtr.h"
#include "PlatformContextCairo.h"
+
#include <gtk/gtk.h>
+
+#include <wtf/PassRefPtr.h>
#include <wtf/text/CString.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp b/Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp
index e664d0fb9..ea3430aa5 100644
--- a/Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp
+++ b/Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp
@@ -16,13 +16,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
#include "config.h"
#include "ImageBuffer.h"
#include "Base64.h"
#include "GdkCairoUtilities.h"
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#include "GRefPtrGtk.h"
#include "MIMETypeRegistry.h"
#include <cairo.h>
@@ -32,42 +31,53 @@
namespace WebCore {
-String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
+static bool encodeImage(cairo_surface_t* surface, const String& mimeType, const double* quality, GOwnPtr<gchar>& buffer, gsize& bufferSize)
{
- ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
-
- if (!mimeType.startsWith("image/"))
- return "data:,";
+ // List of supported image encoding types comes from the GdkPixbuf documentation.
+ // http://developer.gnome.org/gdk-pixbuf/stable/gdk-pixbuf-File-saving.html#gdk-pixbuf-save-to-bufferv
- // List of supported image types comes from the GdkPixbuf documentation.
- // http://library.gnome.org/devel/gdk-pixbuf/stable/gdk-pixbuf-file-saving.html#gdk-pixbuf-save-to-bufferv
String type = mimeType.substring(sizeof "image");
if (type != "jpeg" && type != "png" && type != "tiff" && type != "ico" && type != "bmp")
- return "data:,";
+ return false;
- GRefPtr<GdkPixbuf> pixbuf = cairoImageSurfaceToGdkPixbuf(m_data.m_surface);
+ GRefPtr<GdkPixbuf> pixbuf;
+ if (type == "jpeg") {
+ // JPEG doesn't support alpha channel. The <canvas> spec states that toDataURL() must encode a Porter-Duff
+ // composite source-over black for image types that do not support alpha.
+ RefPtr<cairo_surface_t> newSurface = adoptRef(cairo_image_surface_create_for_data(cairo_image_surface_get_data(surface),
+ CAIRO_FORMAT_RGB24,
+ cairo_image_surface_get_width(surface),
+ cairo_image_surface_get_height(surface),
+ cairo_image_surface_get_stride(surface)));
+ pixbuf = adoptGRef(cairoImageSurfaceToGdkPixbuf(newSurface.get()));
+ } else
+ pixbuf = adoptGRef(cairoImageSurfaceToGdkPixbuf(surface));
if (!pixbuf)
- return "data:,";
+ return false;
- GOwnPtr<gchar> buffer(0);
- gsize bufferSize;
GError* error = 0;
- gboolean success = FALSE;
if (type == "jpeg" && quality && *quality >= 0.0 && *quality <= 1.0) {
- String qualityString = String::format("%f", *quality * 100.0);
- success = gdk_pixbuf_save_to_buffer(pixbuf.get(), &buffer.outPtr(), &bufferSize,
- type.utf8().data(), &error, "quality", qualityString.utf8().data(), NULL);
- } else {
- success = gdk_pixbuf_save_to_buffer(pixbuf.get(), &buffer.outPtr(), &bufferSize, type.utf8().data(), &error, NULL);
- }
+ String qualityString = String::format("%d", static_cast<int>(*quality * 100.0 + 0.5));
+ gdk_pixbuf_save_to_buffer(pixbuf.get(), &buffer.outPtr(), &bufferSize, type.utf8().data(), &error, "quality", qualityString.utf8().data(), NULL);
+ } else
+ gdk_pixbuf_save_to_buffer(pixbuf.get(), &buffer.outPtr(), &bufferSize, type.utf8().data(), &error, NULL);
- if (!success)
+ return !error;
+}
+
+String ImageBuffer::toDataURL(const String& mimeType, const double* quality, CoordinateSystem) const
+{
+ ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
+
+ GOwnPtr<gchar> buffer(0);
+ gsize bufferSize;
+ if (!encodeImage(m_data.m_surface, mimeType, quality, buffer, bufferSize))
return "data:,";
- Vector<char> out;
- base64Encode(reinterpret_cast<const char*>(buffer.get()), bufferSize, out);
+ Vector<char> base64Data;
+ base64Encode(buffer.get(), bufferSize, base64Data);
- return "data:" + mimeType + ";base64," + out;
+ return "data:" + mimeType + ";base64," + base64Data;
}
}
diff --git a/Source/WebCore/platform/graphics/gtk/ImageGtk.cpp b/Source/WebCore/platform/graphics/gtk/ImageGtk.cpp
index c5a5194d0..7555e147c 100644
--- a/Source/WebCore/platform/graphics/gtk/ImageGtk.cpp
+++ b/Source/WebCore/platform/graphics/gtk/ImageGtk.cpp
@@ -112,10 +112,8 @@ PassRefPtr<Image> Image::loadPlatformThemeIcon(const char* name, int size)
GdkPixbuf* BitmapImage::getGdkPixbuf()
{
- cairo_surface_t* frame = frameAtIndex(currentFrame());
- if (!frame)
- return 0;
- return cairoImageSurfaceToGdkPixbuf(frame);
+ NativeImageCairo* image = nativeImageForCurrentFrame();
+ return image ? cairoImageSurfaceToGdkPixbuf(image->surface()) : 0;
}
}
diff --git a/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp b/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp
index f244a94c2..ba46c7f02 100644
--- a/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp
+++ b/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp
@@ -36,6 +36,11 @@
#include "SurrogatePairAwareTextIterator.h"
#include "TextRun.h"
+#if OS(ANDROID)
+#include "FontCache.h"
+#include "SkTypeface_android.h"
+#endif
+
extern "C" {
#include "harfbuzz-unicode.h"
}
@@ -191,6 +196,53 @@ static UChar32 surrogatePairAwareFirstCharacter(const UChar* characters, unsigne
return characters[0];
}
+const FontPlatformData* ComplexTextController::getComplexFontPlatformData()
+{
+#if OS(ANDROID)
+ // There are 2 kinds of font on Android: system fonts and fallback fonts.
+ // System fonts have a name, and are accessible in FontPlatformData.
+ // Fallback fonts do not have specific names, so they are not accessible
+ // from WebKit directly. To feed Harfbuzz, use a trick to get correct
+ // SkTypeface based on script.
+ FallbackScripts fallbackScript = kFallbackScriptNumber; // invalid script value.
+ switch (m_item.item.script) {
+ case HB_Script_Arabic:
+ fallbackScript = kArabic_FallbackScript;
+ break;
+ case HB_Script_Hebrew:
+ if (m_font->fontDescription().weight() >= FontWeightBold)
+ fallbackScript = kHebrewBold_FallbackScript;
+ else
+ fallbackScript = kHebrewRegular_FallbackScript;
+ break;
+ case HB_Script_Thai:
+ fallbackScript = kThai_FallbackScript;
+ break;
+ case HB_Script_Armenian:
+ fallbackScript = kArmenian_FallbackScript;
+ break;
+ case HB_Script_Georgian:
+ fallbackScript = kGeorgian_FallbackScript;
+ break;
+ case HB_Script_Devanagari:
+ fallbackScript = kDevanagari_FallbackScript;
+ break;
+ case HB_Script_Bengali:
+ fallbackScript = kBengali_FallbackScript;
+ break;
+ case HB_Script_Tamil:
+ fallbackScript = kTamil_FallbackScript;
+ break;
+ default:
+ return 0;
+ }
+ return fontCache()->getCachedFontPlatformData(m_font->fontDescription(), SkGetFallbackScriptID(fallbackScript), true);
+#else
+ // Only Android needs the extra logic.
+ return 0;
+#endif
+}
+
void ComplexTextController::setupFontForScriptRun()
{
FontDataVariant fontDataVariant = AutoVariant;
@@ -205,23 +257,26 @@ void ComplexTextController::setupFontForScriptRun()
m_item.item.pos = 0;
fontDataVariant = SmallCapsVariant;
}
- UChar32 current = surrogatePairAwareFirstCharacter(static_cast<const UChar*>(&m_item.string[m_item.item.pos]), m_item.item.length - m_item.item.pos);
- const FontData* fontData = m_font->glyphDataForCharacter(current, false, fontDataVariant).fontData;
- const FontPlatformData& platformData = fontData->fontDataForCharacter(' ')->platformData();
- m_item.face = platformData.harfbuzzFace()->face();
+ const FontPlatformData* platformData = getComplexFontPlatformData();
+ if (!platformData) {
+ UChar32 current = surrogatePairAwareFirstCharacter(static_cast<const UChar*>(&m_item.string[m_item.item.pos]), m_item.item.length - m_item.item.pos);
+ const FontData* fontData = m_font->glyphDataForCharacter(current, false, fontDataVariant).fontData;
+ platformData = &fontData->fontDataForCharacter(' ')->platformData();
+ }
+ m_item.face = platformData->harfbuzzFace()->face();
// We only need to setup font features at the beginning of the run.
if (!m_item.item.pos)
setupFontFeatures(m_font->fontDescription().featureSettings(), m_item.face);
- void* opaquePlatformData = const_cast<FontPlatformData*>(&platformData);
+ void* opaquePlatformData = const_cast<FontPlatformData*>(platformData);
m_item.font->userData = opaquePlatformData;
- int size = platformData.size();
+ int size = platformData->size();
m_item.font->x_ppem = size;
m_item.font->y_ppem = size;
// x_ and y_scale are the conversion factors from font design space (fEmSize) to 1/64th of device pixels in 16.16 format.
const int devicePixelFraction = 64;
const int multiplyFor16Dot16 = 1 << 16;
- int scale = devicePixelFraction * size * multiplyFor16Dot16 / platformData.emSizeInFontUnits();
+ int scale = devicePixelFraction * size * multiplyFor16Dot16 / platformData->emSizeInFontUnits();
m_item.font->x_scale = scale;
m_item.font->y_scale = scale;
}
diff --git a/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.h b/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.h
index 6288d408a..1758a3cab 100644
--- a/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.h
+++ b/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.h
@@ -83,7 +83,7 @@ public:
void glyphsForRange(int from, int to, int& fromGlyph, int& glyphLength);
// Return the length of the array returned by |glyphs|
- const unsigned length() const { return m_item.num_glyphs; }
+ unsigned length() const { return m_item.num_glyphs; }
// Return the offset for each of the glyphs. Note that this is translated
// by the current x offset and that the x offset is updated for each script
@@ -91,10 +91,10 @@ public:
const SkPoint* positions() const { return m_positions; }
// return the number of code points in the current script run
- const unsigned numCodePoints() const { return m_item.item.length; }
+ unsigned numCodePoints() const { return m_item.item.length; }
// Return the current pixel position of the controller.
- const unsigned offsetX() const { return m_offsetX; }
+ unsigned offsetX() const { return m_offsetX; }
const FontPlatformData* fontPlatformDataForScriptRun() { return reinterpret_cast<FontPlatformData*>(m_item.font->userData); }
@@ -105,6 +105,7 @@ private:
// Return the width (in px) of the current script run.
unsigned width() const { return m_pixelWidth; }
+ const FontPlatformData* getComplexFontPlatformData();
void setupFontForScriptRun();
void deleteGlyphArrays();
void createGlyphArrays(int);
diff --git a/Source/WebCore/platform/graphics/harfbuzz/FontHarfBuzz.cpp b/Source/WebCore/platform/graphics/harfbuzz/FontHarfBuzz.cpp
index 03f6836c1..9370f676b 100644
--- a/Source/WebCore/platform/graphics/harfbuzz/FontHarfBuzz.cpp
+++ b/Source/WebCore/platform/graphics/harfbuzz/FontHarfBuzz.cpp
@@ -60,23 +60,6 @@ bool Font::canExpandAroundIdeographsInComplexText()
return false;
}
-static bool isCanvasMultiLayered(SkCanvas* canvas)
-{
- SkCanvas::LayerIter layerIterator(canvas, false);
- layerIterator.next();
- return !layerIterator.done();
-}
-
-static void adjustTextRenderMode(SkPaint* paint, PlatformContextSkia* skiaContext)
-{
- // Our layers only have a single alpha channel. This means that subpixel
- // rendered text cannot be compositied correctly when the layer is
- // collapsed. Therefore, subpixel text is disabled when we are drawing
- // onto a layer or when the compositor is being used.
- if (isCanvasMultiLayered(skiaContext->canvas()) || skiaContext->isDrawingToImageBuffer())
- paint->setLCDRenderText(false);
-}
-
void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
const GlyphBuffer& glyphBuffer, int from, int numGlyphs,
const FloatPoint& point) const {
@@ -118,7 +101,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
SkPaint paint;
gc->platformContext()->setupPaintForFilling(&paint);
font->platformData().setupPaint(&paint);
- adjustTextRenderMode(&paint, gc->platformContext());
+ gc->platformContext()->adjustTextRenderMode(&paint);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
if (isVertical) {
@@ -140,7 +123,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
SkPaint paint;
gc->platformContext()->setupPaintForStroking(&paint, 0, 0);
font->platformData().setupPaint(&paint);
- adjustTextRenderMode(&paint, gc->platformContext());
+ gc->platformContext()->adjustTextRenderMode(&paint);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
if (textMode & TextModeFill) {
@@ -208,13 +191,13 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run,
if (fill) {
controller.fontPlatformDataForScriptRun()->setupPaint(&fillPaint);
- adjustTextRenderMode(&fillPaint, gc->platformContext());
+ gc->platformContext()->adjustTextRenderMode(&fillPaint);
canvas->drawPosText(controller.glyphs() + fromGlyph, glyphLength << 1, controller.positions() + fromGlyph, fillPaint);
}
if (stroke) {
controller.fontPlatformDataForScriptRun()->setupPaint(&strokePaint);
- adjustTextRenderMode(&strokePaint, gc->platformContext());
+ gc->platformContext()->adjustTextRenderMode(&strokePaint);
canvas->drawPosText(controller.glyphs() + fromGlyph, glyphLength << 1, controller.positions() + fromGlyph, strokePaint);
}
}
diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp
index 6ed931f8c..715f6fec4 100644
--- a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp
+++ b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp
@@ -519,7 +519,7 @@ void ComplexTextController::adjustGlyphsAndAdvances()
if (ch == '\t' && m_run.allowTabs()) {
float tabWidth = m_font.tabWidth(*fontData);
advance.width = tabWidth - fmodf(m_run.xPos() + m_totalWidth + widthSinceLastCommit, tabWidth);
- } else if (ch == zeroWidthSpace || (Font::treatAsZeroWidthSpace(ch) && !treatAsSpace)) {
+ } else if (Font::treatAsZeroWidthSpace(ch) && !treatAsSpace) {
advance.width = 0;
glyph = fontData->spaceGlyph();
}
diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp
index 0437bcdfc..be9f74104 100644
--- a/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp
+++ b/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp
@@ -278,15 +278,15 @@ static void disableLigatures(const SimpleFontData* fontData, ATSUStyle atsuStyle
static ATSUStyle initializeATSUStyle(const SimpleFontData* fontData, TypesettingFeatures typesettingFeatures)
{
unsigned key = typesettingFeatures + 1;
- pair<HashMap<unsigned, ATSUStyle>::iterator, bool> addResult = fontData->m_ATSUStyleMap.add(key, 0);
- ATSUStyle& atsuStyle = addResult.first->second;
- if (!addResult.second)
+ HashMap<unsigned, ATSUStyle>::AddResult addResult = fontData->m_ATSUStyleMap.add(key, 0);
+ ATSUStyle& atsuStyle = addResult.iterator->second;
+ if (!addResult.isNewEntry)
return atsuStyle;
ATSUFontID fontID = fontData->platformData().ctFont() ? CTFontGetPlatformFont(fontData->platformData().ctFont(), 0) : 0;
if (!fontID) {
LOG_ERROR("unable to get ATSUFontID for %p", fontData->platformData().font());
- fontData->m_ATSUStyleMap.remove(addResult.first);
+ fontData->m_ATSUStyleMap.remove(addResult.isNewEntry);
return 0;
}
diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm
index 1a544a7a1..ab07f079d 100644
--- a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm
+++ b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm
@@ -271,8 +271,18 @@ void ComplexTextController::collectComplexTextRunsForCharactersCoreText(const UC
continue;
}
runFontData = fontCache()->getCachedFontData(m_font.fontDescription(), fontName.get(), false, FontCache::DoNotRetain);
+#if !PLATFORM(WX)
+ // Core Text may have used a font that is not known to NSFontManager. In that case, fall back on
+ // using the font as returned, even though it may not have the best NSFontRenderingMode.
+ if (!runFontData) {
+ FontPlatformData runFontPlatformData((NSFont *)runFont, CTFontGetSize(runFont), m_font.fontDescription().usePrinterFont());
+ runFontData = fontCache()->getCachedFontData(&runFontPlatformData, FontCache::DoNotRetain);
+ }
+#else
+ // just assert for now, until we can devise a better fix that works with wx.
+ ASSERT(runFontData);
+#endif
}
- ASSERT(runFontData);
if (m_fallbackFonts && runFontData != m_font.primaryFont())
m_fallbackFonts->add(runFontData);
}
diff --git a/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp b/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp
index edf630892..0546f34b5 100644
--- a/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp
+++ b/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp
@@ -45,7 +45,7 @@ static CVReturn displayLinkCallback(CVDisplayLinkRef, const CVTimeStamp* now, co
return kCVReturnSuccess;
}
-
+
DisplayRefreshMonitor::~DisplayRefreshMonitor()
{
if (m_displayLink) {
@@ -61,7 +61,7 @@ bool DisplayRefreshMonitor::requestRefreshCallback()
{
if (!m_active)
return false;
-
+
if (!m_displayLink) {
m_active = false;
CVReturn error = CVDisplayLinkCreateWithCGDisplay(m_displayID, &m_displayLink);
@@ -78,7 +78,7 @@ bool DisplayRefreshMonitor::requestRefreshCallback()
m_active = true;
}
-
+
MutexLocker lock(m_mutex);
m_scheduled = true;
return true;
@@ -92,9 +92,11 @@ void DisplayRefreshMonitor::displayLinkFired(double nowSeconds, double outputTim
m_previousFrameDone = false;
- double webKitNow = currentTime();
- m_timestamp = webKitNow - nowSeconds + outputTimeSeconds;
-
+ double webKitMonotonicNow = monotonicallyIncreasingTime();
+ double timeUntilOutput = outputTimeSeconds - nowSeconds;
+ // FIXME: Should this be using webKitMonotonicNow?
+ m_monotonicAnimationStartTime = webKitMonotonicNow + timeUntilOutput;
+
callOnMainThread(refreshDisplayOnMainThread, this);
}
diff --git a/Source/WebCore/platform/graphics/mac/FontCacheMac.mm b/Source/WebCore/platform/graphics/mac/FontCacheMac.mm
index c6b9f0fc8..91dd426fe 100644
--- a/Source/WebCore/platform/graphics/mac/FontCacheMac.mm
+++ b/Source/WebCore/platform/graphics/mac/FontCacheMac.mm
@@ -158,7 +158,7 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons
substituteFontTraits = [fontManager traitsOfFont:substituteFont];
substituteFontWeight = [fontManager weightOfFont:substituteFont];
- FontPlatformData alternateFont(substituteFont, platformData.size(),
+ FontPlatformData alternateFont(substituteFont, platformData.size(), platformData.isPrinterFont(),
!font.isPlatformFont() && isAppKitFontWeightBold(weight) && !isAppKitFontWeightBold(substituteFontWeight),
!font.isPlatformFont() && (traits & NSFontItalicTrait) && !(substituteFontTraits & NSFontItalicTrait),
platformData.m_orientation);
@@ -230,7 +230,12 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
bool syntheticBold = isAppKitFontWeightBold(weight) && !isAppKitFontWeightBold(actualWeight);
bool syntheticOblique = (traits & NSFontItalicTrait) && !(actualTraits & NSFontItalicTrait);
- return new FontPlatformData(platformFont, size, syntheticBold, syntheticOblique, fontDescription.orientation(), fontDescription.textOrientation(), fontDescription.widthVariant());
+ // FontPlatformData::font() can be null for the case of Chromium out-of-process font loading.
+ // In that case, we don't want to use the platformData.
+ OwnPtr<FontPlatformData> platformData = adoptPtr(new FontPlatformData(platformFont, size, fontDescription.usePrinterFont(), syntheticBold, syntheticOblique, fontDescription.orientation(), fontDescription.textOrientation(), fontDescription.widthVariant()));
+ if (!platformData->font())
+ return 0;
+ return platformData.leakPtr();
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp b/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
index 5aa23d38f..98a53f9f1 100644
--- a/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
+++ b/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
@@ -38,6 +38,8 @@ namespace WebCore {
static bool shouldUseCoreText(UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
+ if (fontData->platformData().isCompositeFontReference())
+ return true;
if (fontData->platformData().widthVariant() != RegularWidth || fontData->hasVerticalGlyphs()) {
// Ideographs don't have a vertical variant or width variants.
for (unsigned i = 0; i < bufferLength; ++i) {
@@ -64,8 +66,8 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b
haveGlyphs = true;
}
}
- } else if ((fontData->platformData().widthVariant() == RegularWidth) ? wkGetVerticalGlyphsForCharacters(fontData->platformData().ctFont(), buffer, glyphs.data(), bufferLength)
- : CTFontGetGlyphsForCharacters(fontData->platformData().ctFont(), buffer, glyphs.data(), bufferLength)) {
+ } else if (!fontData->platformData().isCompositeFontReference() && ((fontData->platformData().widthVariant() == RegularWidth) ? wkGetVerticalGlyphsForCharacters(fontData->platformData().ctFont(), buffer, glyphs.data(), bufferLength)
+ : CTFontGetGlyphsForCharacters(fontData->platformData().ctFont(), buffer, glyphs.data(), bufferLength))) {
for (unsigned i = 0; i < length; ++i) {
if (!glyphs[i])
setGlyphDataForIndex(offset + i, 0, 0);
@@ -105,7 +107,8 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b
CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(attributes, kCTFontAttributeName));
RetainPtr<CGFontRef> runCGFont(AdoptCF, CTFontCopyGraphicsFont(runFont, 0));
// Use CGFont here as CFEqual for CTFont counts all attributes for font.
- if (CFEqual(cgFont.get(), runCGFont.get())) {
+ bool gotBaseFont = CFEqual(cgFont.get(), runCGFont.get());
+ if (gotBaseFont || fontData->platformData().isCompositeFontReference()) {
// This run uses the font we want. Extract glyphs.
CFIndex glyphCount = CTRunGetGlyphCount(ctRun);
const CGGlyph* glyphs = CTRunGetGlyphsPtr(ctRun);
@@ -121,14 +124,30 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b
stringIndices = indexVector.data();
}
- for (CFIndex i = 0; i < glyphCount; ++i) {
- if (stringIndices[i] >= static_cast<CFIndex>(length)) {
- done = true;
- break;
+ if (gotBaseFont) {
+ for (CFIndex i = 0; i < glyphCount; ++i) {
+ if (stringIndices[i] >= static_cast<CFIndex>(length)) {
+ done = true;
+ break;
+ }
+ if (glyphs[i]) {
+ setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], fontData);
+ haveGlyphs = true;
+ }
}
- if (glyphs[i]) {
- setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], fontData);
- haveGlyphs = true;
+ } else {
+ const SimpleFontData* runSimple = fontData->getCompositeFontReferenceFontData((NSFont *)runFont);
+ if (runSimple) {
+ for (CFIndex i = 0; i < glyphCount; ++i) {
+ if (stringIndices[i] >= static_cast<CFIndex>(length)) {
+ done = true;
+ break;
+ }
+ if (glyphs[i]) {
+ setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], runSimple);
+ haveGlyphs = true;
+ }
+ }
}
}
}
diff --git a/Source/WebCore/platform/graphics/mac/GraphicsContextMac.mm b/Source/WebCore/platform/graphics/mac/GraphicsContextMac.mm
index aced96b2f..e08591df4 100644
--- a/Source/WebCore/platform/graphics/mac/GraphicsContextMac.mm
+++ b/Source/WebCore/platform/graphics/mac/GraphicsContextMac.mm
@@ -99,7 +99,7 @@ static NSColor* createPatternColor(NSString* firstChoiceName, NSString* secondCh
}
// WebKit on Mac is a standard platform component, so it must use the standard platform artwork for underline.
-void GraphicsContext::drawLineForTextChecking(const FloatPoint& point, float width, TextCheckingLineStyle style)
+void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& point, float width, DocumentMarkerLineStyle style)
{
if (paintingDisabled())
return;
@@ -111,7 +111,7 @@ void GraphicsContext::drawLineForTextChecking(const FloatPoint& point, float wid
bool usingDot;
NSColor *patternColor;
switch (style) {
- case TextCheckingSpellingLineStyle:
+ case DocumentMarkerSpellingLineStyle:
{
// Constants for spelling pattern color.
static bool usingDotForSpelling = false;
@@ -120,7 +120,7 @@ void GraphicsContext::drawLineForTextChecking(const FloatPoint& point, float wid
patternColor = spellingPatternColor.get();
break;
}
- case TextCheckingGrammarLineStyle:
+ case DocumentMarkerGrammarLineStyle:
{
// Constants for grammar pattern color.
static bool usingDotForGrammar = false;
@@ -131,7 +131,8 @@ void GraphicsContext::drawLineForTextChecking(const FloatPoint& point, float wid
}
#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
// To support correction panel.
- case TextCheckingReplacementLineStyle:
+ case DocumentMarkerAutocorrectionReplacementLineStyle:
+ case DocumentMarkerDictationAlternativesLineStyle:
{
// Constants for spelling pattern color.
static bool usingDotForSpelling = false;
diff --git a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
index 8ab06eb77..98599e96b 100644
--- a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
+++ b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
@@ -1462,6 +1462,11 @@ MediaPlayer::SupportsType MediaPlayerPrivateQTKit::supportsType(const String& ty
// 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.
+ // Due to <rdar://problem/10777059>, avoid calling the mime types cache functions if at
+ // all possible:
+ if (!type.startsWith("video/") && !type.startsWith("audio/"))
+ return MediaPlayer::IsNotSupported;
+
// We check the "modern" type cache first, as it doesn't require QTKitServer to start.
if (mimeModernTypesCache().contains(type) || mimeCommonTypesCache().contains(type))
return codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported;
diff --git a/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp b/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp
index 832bb9ddf..05193742c 100644
--- a/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp
+++ b/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp
@@ -42,9 +42,9 @@ namespace WebCore {
CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typesettingFeatures, FontOrientation orientation) const
{
unsigned key = typesettingFeatures + 1;
- pair<HashMap<unsigned, RetainPtr<CFDictionaryRef> >::iterator, bool> addResult = m_CFStringAttributes.add(key, RetainPtr<CFDictionaryRef>());
- RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.first->second;
- if (!addResult.second)
+ HashMap<unsigned, RetainPtr<CFDictionaryRef> >::AddResult addResult = m_CFStringAttributes.add(key, RetainPtr<CFDictionaryRef>());
+ RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.iterator->second;
+ if (!addResult.isNewEntry)
return attributesDictionary.get();
bool treatLineAsVertical = orientation == Vertical;
diff --git a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
index 8f4a9193e..d5d55606d 100644
--- a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
+++ b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
@@ -109,6 +109,37 @@ static NSString* pathFromFont(NSFont *font)
#endif // __LP64__
#endif // !ERROR_DISABLED
+const SimpleFontData* SimpleFontData::getCompositeFontReferenceFontData(NSFont *key) const
+{
+ if (key && !CFEqual(RetainPtr<CFStringRef>(AdoptCF, CTFontCopyPostScriptName(CTFontRef(key))).get(), CFSTR("LastResort"))) {
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->compositeFontReferences)
+ m_derivedFontData->compositeFontReferences.adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, NULL));
+ else {
+ const SimpleFontData* found = static_cast<const SimpleFontData*>(CFDictionaryGetValue(m_derivedFontData->compositeFontReferences.get(), static_cast<const void *>(key)));
+ if (found)
+ return found;
+ }
+ if (CFMutableDictionaryRef dictionary = m_derivedFontData->compositeFontReferences.get()) {
+ bool isUsingPrinterFont = platformData().isPrinterFont();
+ NSFont *substituteFont = isUsingPrinterFont ? [key printerFont] : [key screenFont];
+
+ CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(toCTFontRef(substituteFont));
+ bool syntheticBold = platformData().syntheticBold() && !(traits & kCTFontBoldTrait);
+ bool syntheticOblique = platformData().syntheticOblique() && !(traits & kCTFontItalicTrait);
+
+ FontPlatformData substitutePlatform(substituteFont, platformData().size(), isUsingPrinterFont, syntheticBold, syntheticOblique, platformData().orientation(), platformData().textOrientation(), platformData().widthVariant());
+ SimpleFontData* value = new SimpleFontData(substitutePlatform, isCustomFont());
+ if (value) {
+ CFDictionaryAddValue(dictionary, key, value);
+ return value;
+ }
+ }
+ }
+ return 0;
+}
+
void SimpleFontData::platformInit()
{
#if USE(ATSUI)
@@ -306,7 +337,7 @@ PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri
BEGIN_BLOCK_OBJC_EXCEPTIONS;
float size = m_platformData.size() * scaleFactor;
- FontPlatformData scaledFontData([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toSize:size], size, false, false, m_platformData.orientation());
+ FontPlatformData scaledFontData([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toSize:size], size, m_platformData.isPrinterFont(), false, false, m_platformData.orientation());
// 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.
@@ -440,9 +471,9 @@ bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters
if (!m_combiningCharacterSequenceSupport)
m_combiningCharacterSequenceSupport = adoptPtr(new HashMap<String, bool>);
- pair<WTF::HashMap<String, bool>::iterator, bool> addResult = m_combiningCharacterSequenceSupport->add(String(characters, length), false);
- if (!addResult.second)
- return addResult.first->second;
+ WTF::HashMap<String, bool>::AddResult addResult = m_combiningCharacterSequenceSupport->add(String(characters, length), false);
+ if (!addResult.isNewEntry)
+ return addResult.iterator->second;
RetainPtr<CGFontRef> cgFont(AdoptCF, CTFontCopyGraphicsFont(platformData().ctFont(), 0));
@@ -462,7 +493,7 @@ bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters
return false;
}
- addResult.first->second = true;
+ addResult.iterator->second = true;
return true;
}
diff --git a/Source/WebCore/platform/graphics/mac/WebLayer.mm b/Source/WebCore/platform/graphics/mac/WebLayer.mm
index 1dbd72b37..97e9f2882 100644
--- a/Source/WebCore/platform/graphics/mac/WebLayer.mm
+++ b/Source/WebCore/platform/graphics/mac/WebLayer.mm
@@ -32,6 +32,7 @@
#import "GraphicsContext.h"
#import "GraphicsLayerCA.h"
#import "PlatformCALayer.h"
+#import "ThemeMac.h"
#import <objc/objc-runtime.h>
#import <QuartzCore/QuartzCore.h>
#import <wtf/UnusedParam.h>
@@ -79,6 +80,10 @@ void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCA
// smaller than the layer bounds (e.g. tiled layers)
FloatRect clipBounds = CGContextGetClipBoundingBox(context);
+ // Set the focus ring clip rect which needs to be in base coordinates.
+ AffineTransform transform = CGContextGetCTM(context);
+ ThemeMac::setFocusRingClipRect(transform.mapRect(clipBounds));
+
#if !defined(BUILDING_ON_SNOW_LEOPARD)
__block GraphicsContext* ctx = &graphicsContext;
@@ -97,6 +102,8 @@ void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCA
layerContents->platformCALayerPaintContents(graphicsContext, clip);
#endif
+ ThemeMac::setFocusRingClipRect(FloatRect());
+
[NSGraphicsContext restoreGraphicsState];
// Re-fetch the layer owner, since <rdar://problem/9125151> indicates that it might have been destroyed during painting.
diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
index 7c477786e..e8519d5c0 100644
--- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
+++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
@@ -42,6 +42,11 @@
namespace WebCore {
+void GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels)
+{
+ ::glReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
+}
+
bool GraphicsContext3D::reshapeFBOs(const IntSize& size)
{
const int width = size.width();
@@ -189,6 +194,37 @@ void GraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value)
}
}
+void GraphicsContext3D::getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, GC3Dint* range, GC3Dint* precision)
+{
+ UNUSED_PARAM(shaderType);
+ ASSERT(range);
+ ASSERT(precision);
+
+ makeContextCurrent();
+
+ switch (precisionType) {
+ case GraphicsContext3D::LOW_INT:
+ case GraphicsContext3D::MEDIUM_INT:
+ case GraphicsContext3D::HIGH_INT:
+ // These values are for a 32-bit twos-complement integer format.
+ range[0] = 31;
+ range[1] = 30;
+ precision[0] = 0;
+ break;
+ case GraphicsContext3D::LOW_FLOAT:
+ case GraphicsContext3D::MEDIUM_FLOAT:
+ case GraphicsContext3D::HIGH_FLOAT:
+ // These values are for an IEEE single-precision floating-point format.
+ range[0] = 127;
+ range[1] = 127;
+ precision[0] = 23;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+}
+
bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels)
{
if (width && height && !pixels) {
diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp
index 9123ed0b2..cb3a5b77e 100644
--- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp
+++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp
@@ -45,6 +45,7 @@
#include <wtf/ArrayBufferView.h>
#include <wtf/Float32Array.h>
#include <wtf/Int32Array.h>
+#include <wtf/OwnArrayPtr.h>
#include <wtf/Uint8Array.h>
#include <wtf/UnusedParam.h>
#include <wtf/text/CString.h>
@@ -94,7 +95,7 @@ void GraphicsContext3D::validateAttributes()
// Currently in Mac we only turn on antialias if vendor is NVIDIA,
// or if ATI and on 10.7.2 and above.
const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR));
- if (!std::strstr(vendor, "NVIDIA") && !(std::strstr(vendor, "ATI") && systemAllowsMultisamplingOnATICards()))
+ if (!vendor || (!std::strstr(vendor, "NVIDIA") && !(std::strstr(vendor, "ATI") && systemAllowsMultisamplingOnATICards())))
isValidVendor = false;
if (!isValidVendor || !extensions->supports("GL_ANGLE_framebuffer_multisample") || isGLES2Compliant())
m_attrs.antialias = false;
@@ -149,7 +150,7 @@ PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData(Drawin
return 0;
RefPtr<ImageData> imageData = ImageData::create(IntSize(m_currentWidth, m_currentHeight));
- unsigned char* pixels = imageData->data()->data()->data();
+ unsigned char* pixels = imageData->data()->data();
int totalBytes = 4 * m_currentWidth * m_currentHeight;
readRenderingResults(pixels, totalBytes);
@@ -183,8 +184,7 @@ void GraphicsContext3D::prepareTexture()
void GraphicsContext3D::readRenderingResults(unsigned char *pixels, int pixelsSize)
{
- int totalBytes = m_currentWidth * m_currentHeight * 4;
- if (pixelsSize < totalBytes)
+ if (pixelsSize < m_currentWidth * m_currentHeight * 4)
return;
makeContextCurrent();
@@ -209,11 +209,7 @@ void GraphicsContext3D::readRenderingResults(unsigned char *pixels, int pixelsSi
mustRestorePackAlignment = true;
}
- ::glReadPixels(0, 0, m_currentWidth, m_currentHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
- if (isGLES2Compliant()) {
- for (int i = 0; i < totalBytes; i += 4)
- std::swap(pixels[i], pixels[i + 2]); // Convert to BGRA.
- }
+ readPixelsAndConvertToBGRAIfNecessary(0, 0, m_currentWidth, m_currentHeight, pixels);
if (mustRestorePackAlignment)
::glPixelStorei(GL_PACK_ALIGNMENT, packAlignment);
diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp
index 4faa6630f..b5657adb8 100644
--- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp
+++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp
@@ -30,6 +30,7 @@
#include "GraphicsContext3D.h"
+#include "Extensions3DOpenGL.h"
#include "IntRect.h"
#include "IntSize.h"
#include "NotImplemented.h"
@@ -40,6 +41,14 @@
namespace WebCore {
+void GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels)
+{
+ const int totalBytes = m_currentWidth * m_currentHeight * 4;
+ ::glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ for (int i = 0; i < totalBytes; i += 4)
+ std::swap(pixels[i], pixels[i + 2]); // Convert to BGRA.
+}
+
bool GraphicsContext3D::reshapeFBOs(const IntSize& size)
{
const int width = size.width();
@@ -80,7 +89,7 @@ bool GraphicsContext3D::reshapeFBOs(const IntSize& size)
if (m_attrs.stencil || m_attrs.depth) {
// Use a 24 bit depth buffer where we know we have it.
if (supportPackedDepthStencilBuffer) {
- ::glBindTexture(GL_TEXTURE_2D, m_depthStencilBuffr);
+ ::glBindTexture(GL_TEXTURE_2D, m_depthStencilBuffer);
::glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL_OES, width, height, 0, GL_DEPTH_STENCIL_OES, GL_UNSIGNED_INT_24_8_OES, 0);
if (m_attrs.stencil)
::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_depthStencilBuffer, 0);
@@ -88,12 +97,12 @@ bool GraphicsContext3D::reshapeFBOs(const IntSize& size)
::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthStencilBuffer, 0);
::glBindTexture(GL_TEXTURE_2D, 0);
} else {
- if (m_attributes.stencil) {
+ if (m_attrs.stencil) {
::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_stencilBuffer);
::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8, width, height);
::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_stencilBuffer);
}
- if (m_attributes.depth) {
+ if (m_attrs.depth) {
::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer);
::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, width, height);
::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer);
@@ -109,7 +118,7 @@ bool GraphicsContext3D::reshapeFBOs(const IntSize& size)
return mustRestoreFBO;
}
-void GraphicsContext3D::resolveMultisamplingIfNecessary(IntRect& rect)
+void GraphicsContext3D::resolveMultisamplingIfNecessary(const IntRect& rect)
{
// FIXME: We don't support antialiasing yet.
notImplemented();
@@ -127,6 +136,15 @@ void GraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value)
::glGetIntegerv(pname, value);
}
+void GraphicsContext3D::getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, GC3Dint* range, GC3Dint* precision)
+{
+ ASSERT(range);
+ ASSERT(precision);
+
+ makeContextCurrent();
+ ::glGetShaderPrecisionFormat(shaderType, precisionType, range, precision);
+}
+
bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels)
{
if (width && height && !pixels) {
@@ -138,4 +156,6 @@ bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum inte
return true;
}
+} // namespace WebCore
+
#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/opentype/OpenTypeTypes.h b/Source/WebCore/platform/graphics/opentype/OpenTypeTypes.h
new file mode 100644
index 000000000..9fc765979
--- /dev/null
+++ b/Source/WebCore/platform/graphics/opentype/OpenTypeTypes.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2012 Koji Ishii <kojiishi@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef OpenTypeTypes_h
+#define OpenTypeTypes_h
+
+namespace WebCore {
+namespace OpenType {
+
+struct BigEndianShort {
+ operator short() const { return (v & 0x00ff) << 8 | v >> 8; }
+ BigEndianShort(short u) : v((u & 0x00ff) << 8 | u >> 8) { }
+ unsigned short v;
+};
+
+struct BigEndianUShort {
+ operator unsigned short() const { return (v & 0x00ff) << 8 | v >> 8; }
+ BigEndianUShort(unsigned short u) : v((u & 0x00ff) << 8 | u >> 8) { }
+ unsigned short v;
+};
+
+struct BigEndianLong {
+ operator int() const { return (v & 0xff) << 24 | (v & 0xff00) << 8 | (v & 0xff0000) >> 8 | v >> 24; }
+ BigEndianLong(int u) : v((u & 0xff) << 24 | (u & 0xff00) << 8 | (u & 0xff0000) >> 8 | u >> 24) { }
+ unsigned v;
+};
+
+struct BigEndianULong {
+ operator unsigned() const { return (v & 0xff) << 24 | (v & 0xff00) << 8 | (v & 0xff0000) >> 8 | v >> 24; }
+ BigEndianULong(unsigned u) : v((u & 0xff) << 24 | (u & 0xff00) << 8 | (u & 0xff0000) >> 8 | u >> 24) { }
+ unsigned v;
+};
+
+typedef BigEndianShort Int16;
+typedef BigEndianUShort UInt16;
+typedef BigEndianLong Int32;
+typedef BigEndianULong UInt32;
+
+typedef UInt32 Fixed;
+typedef UInt16 Offset;
+typedef UInt16 GlyphID;
+
+// OTTag is native because it's only compared against constants, so we don't
+// do endian conversion here but make sure constants are in big-endian order.
+// Note that multi-character literal is implementation-defined in C++0x.
+typedef uint32_t Tag;
+#define OT_MAKE_TAG(ch1, ch2, ch3, ch4) ((((uint32_t)(ch4)) << 24) | (((uint32_t)(ch3)) << 16) | (((uint32_t)(ch2)) << 8) | ((uint32_t)(ch1)))
+
+} // namespace OpenType
+} // namespace WebCore
+
+#endif // OpenTypeTypes_h
diff --git a/Source/WebCore/platform/graphics/opentype/OpenTypeVerticalData.cpp b/Source/WebCore/platform/graphics/opentype/OpenTypeVerticalData.cpp
new file mode 100644
index 000000000..78ebcf8cb
--- /dev/null
+++ b/Source/WebCore/platform/graphics/opentype/OpenTypeVerticalData.cpp
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2012 Koji Ishii <kojiishi@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "OpenTypeVerticalData.h"
+
+#include "FloatRect.h"
+#include "GlyphPage.h"
+#include "OpenTypeTypes.h"
+#include "SharedBuffer.h"
+#include "SimpleFontData.h"
+#include <wtf/RefPtr.h>
+
+using namespace std;
+
+namespace WebCore {
+namespace OpenType {
+
+enum {
+ HheaTag = OT_MAKE_TAG('h', 'h', 'e', 'a'),
+ HmtxTag = OT_MAKE_TAG('h', 'm', 't', 'x'),
+ VheaTag = OT_MAKE_TAG('v', 'h', 'e', 'a'),
+ VmtxTag = OT_MAKE_TAG('v', 'm', 't', 'x'),
+ VORGTag = OT_MAKE_TAG('V', 'O', 'R', 'G'),
+};
+
+#pragma pack(1)
+
+struct HheaTable {
+ OpenType::Fixed version;
+ OpenType::Int16 ascender;
+ OpenType::Int16 descender;
+ OpenType::Int16 lineGap;
+ OpenType::Int16 advanceWidthMax;
+ OpenType::Int16 minLeftSideBearing;
+ OpenType::Int16 minRightSideBearing;
+ OpenType::Int16 xMaxExtent;
+ OpenType::Int16 caretSlopeRise;
+ OpenType::Int16 caretSlopeRun;
+ OpenType::Int16 caretOffset;
+ OpenType::Int16 reserved[4];
+ OpenType::Int16 metricDataFormat;
+ OpenType::UInt16 numberOfHMetrics;
+};
+
+struct VheaTable {
+ OpenType::Fixed version;
+ OpenType::Int16 ascent;
+ OpenType::Int16 descent;
+ OpenType::Int16 lineGap;
+ OpenType::Int16 advanceHeightMax;
+ OpenType::Int16 minTopSideBearing;
+ OpenType::Int16 minBottomSideBearing;
+ OpenType::Int16 yMaxExtent;
+ OpenType::Int16 caretSlopeRise;
+ OpenType::Int16 caretSlopeRun;
+ OpenType::Int16 caretOffset;
+ OpenType::Int16 reserved[4];
+ OpenType::Int16 metricDataFormat;
+ OpenType::UInt16 numOfLongVerMetrics;
+};
+
+struct HmtxTable {
+ struct Entry {
+ OpenType::UInt16 advanceWidth;
+ OpenType::Int16 lsb;
+ } entries[1];
+};
+
+struct VmtxTable {
+ struct Entry {
+ OpenType::UInt16 advanceHeight;
+ OpenType::Int16 topSideBearing;
+ } entries[1];
+};
+
+struct VORGTable {
+ OpenType::UInt16 majorVersion;
+ OpenType::UInt16 minorVersion;
+ OpenType::Int16 defaultVertOriginY;
+ OpenType::UInt16 numVertOriginYMetrics;
+ struct VertOriginYMetrics {
+ OpenType::UInt16 glyphIndex;
+ OpenType::Int16 vertOriginY;
+ } vertOriginYMetrics[1];
+
+ size_t requiredSize() const { return sizeof(*this) + sizeof(VertOriginYMetrics) * (numVertOriginYMetrics - 1); }
+};
+
+#pragma pack()
+
+} // namespace OpenType
+
+template <typename T> const T* validatedPtr(const RefPtr<SharedBuffer>& buffer, size_t count = 1)
+{
+ if (!buffer || buffer->size() < sizeof(T) * count)
+ return 0;
+ return reinterpret_cast<const T*>(buffer->data());
+}
+
+OpenTypeVerticalData::OpenTypeVerticalData(const FontPlatformData& platformData)
+ : m_defaultVertOriginY(0)
+{
+ // Load hhea and hmtx to get x-component of vertical origins.
+ // If these tables are missing, it's not an OpenType font.
+ RefPtr<SharedBuffer> buffer = platformData.openTypeTable(OpenType::HheaTag);
+ const OpenType::HheaTable* hhea = validatedPtr<OpenType::HheaTable>(buffer);
+ if (!hhea)
+ return;
+ uint16_t countHmtxEntries = hhea->numberOfHMetrics;
+ if (!countHmtxEntries) {
+ LOG_ERROR("Invalid numberOfHMetrics");
+ return;
+ }
+
+ buffer = platformData.openTypeTable(OpenType::HmtxTag);
+ const OpenType::HmtxTable* hmtx = validatedPtr<OpenType::HmtxTable>(buffer, countHmtxEntries);
+ if (!hmtx) {
+ LOG_ERROR("hhea exists but hmtx does not (or broken)");
+ return;
+ }
+ m_advanceWidths.resize(countHmtxEntries);
+ for (uint16_t i = 0; i < countHmtxEntries; ++i)
+ m_advanceWidths[i] = hmtx->entries[i].advanceWidth;
+
+ // Load vhea first. This table is required for fonts that support vertical flow.
+ buffer = platformData.openTypeTable(OpenType::VheaTag);
+ const OpenType::VheaTable* vhea = validatedPtr<OpenType::VheaTable>(buffer);
+ if (!vhea)
+ return;
+ uint16_t countVmtxEntries = vhea->numOfLongVerMetrics;
+ if (!countVmtxEntries) {
+ LOG_ERROR("Invalid numOfLongVerMetrics");
+ return;
+ }
+
+ // Load VORG. This table is optional.
+ buffer = platformData.openTypeTable(OpenType::VORGTag);
+ const OpenType::VORGTable* vorg = validatedPtr<OpenType::VORGTable>(buffer);
+ if (vorg && buffer->size() >= vorg->requiredSize()) {
+ m_defaultVertOriginY = vorg->defaultVertOriginY;
+ uint16_t countVertOriginYMetrics = vorg->numVertOriginYMetrics;
+ if (!countVertOriginYMetrics) {
+ // Add one entry so that hasVORG() becomes true
+ m_vertOriginY.set(0, m_defaultVertOriginY);
+ } else {
+ for (uint16_t i = 0; i < countVertOriginYMetrics; ++i) {
+ const OpenType::VORGTable::VertOriginYMetrics& metrics = vorg->vertOriginYMetrics[i];
+ m_vertOriginY.set(metrics.glyphIndex, metrics.vertOriginY);
+ }
+ }
+ }
+
+ // Load vmtx then. This table is required for fonts that support vertical flow.
+ buffer = platformData.openTypeTable(OpenType::VmtxTag);
+ const OpenType::VmtxTable* vmtx = validatedPtr<OpenType::VmtxTable>(buffer, countVmtxEntries);
+ if (!vmtx) {
+ LOG_ERROR("vhea exists but vmtx does not (or broken)");
+ return;
+ }
+ m_advanceHeights.resize(countVmtxEntries);
+ for (uint16_t i = 0; i < countVmtxEntries; ++i)
+ m_advanceHeights[i] = vmtx->entries[i].advanceHeight;
+
+ // VORG is preferred way to calculate vertical origin than vmtx,
+ // so load topSideBearing from vmtx only if VORG is missing.
+ if (hasVORG())
+ return;
+
+ size_t sizeExtra = buffer->size() - sizeof(OpenType::VmtxTable::Entry) * countVmtxEntries;
+ if (sizeExtra % sizeof(OpenType::Int16)) {
+ LOG_ERROR("vmtx has incorrect tsb count");
+ return;
+ }
+ size_t countTopSideBearings = countVmtxEntries + sizeExtra / sizeof(OpenType::Int16);
+ m_topSideBearings.resize(countTopSideBearings);
+ size_t i;
+ for (i = 0; i < countVmtxEntries; ++i)
+ m_topSideBearings[i] = vmtx->entries[i].topSideBearing;
+ if (i < countTopSideBearings) {
+ const OpenType::Int16* pTopSideBearingsExtra = reinterpret_cast<const OpenType::Int16*>(&vmtx->entries[countVmtxEntries]);
+ for (; i < countTopSideBearings; ++i, ++pTopSideBearingsExtra)
+ m_topSideBearings[i] = *pTopSideBearingsExtra;
+ }
+}
+
+float OpenTypeVerticalData::advanceHeight(const SimpleFontData* font, Glyph glyph) const
+{
+ size_t countHeights = m_advanceHeights.size();
+ if (countHeights) {
+ uint16_t advanceFUnit = m_advanceHeights[glyph < countHeights ? glyph : countHeights - 1];
+ float advance = advanceFUnit * font->sizePerUnit();
+ return advance;
+ }
+
+ // No vertical info in the font file; use height as advance.
+ return font->fontMetrics().height();
+}
+
+void OpenTypeVerticalData::getVerticalTranslationsForGlyphs(const SimpleFontData* font, const Glyph* glyphs, size_t count, float* outXYArray) const
+{
+ size_t countWidths = m_advanceWidths.size();
+ ASSERT(countWidths > 0);
+ const FontMetrics& metrics = font->fontMetrics();
+ float sizePerUnit = font->sizePerUnit();
+ float ascent = metrics.ascent();
+ bool useVORG = hasVORG();
+ size_t countTopSideBearings = m_topSideBearings.size();
+ float defaultVertOriginY = std::numeric_limits<float>::quiet_NaN();
+ for (float* end = &(outXYArray[count * 2]); outXYArray != end; ++glyphs, outXYArray += 2) {
+ Glyph glyph = *glyphs;
+ uint16_t widthFUnit = m_advanceWidths[glyph < countWidths ? glyph : countWidths - 1];
+ float width = widthFUnit * sizePerUnit;
+ outXYArray[0] = -width / 2;
+
+ // For Y, try VORG first.
+ if (useVORG) {
+ int16_t vertOriginYFUnit = m_vertOriginY.get(glyph);
+ if (vertOriginYFUnit) {
+ outXYArray[1] = -vertOriginYFUnit * sizePerUnit;
+ continue;
+ }
+ if (isnan(defaultVertOriginY))
+ defaultVertOriginY = -m_defaultVertOriginY * sizePerUnit;
+ outXYArray[1] = defaultVertOriginY;
+ continue;
+ }
+
+ // If no VORG, try vmtx next.
+ if (countTopSideBearings) {
+ int16_t topSideBearingFUnit = m_topSideBearings[glyph < countTopSideBearings ? glyph : countTopSideBearings - 1];
+ float topSideBearing = topSideBearingFUnit * sizePerUnit;
+ FloatRect bounds = font->boundsForGlyph(glyph);
+ outXYArray[1] = bounds.y() - topSideBearing;
+ continue;
+ }
+
+ // No vertical info in the font file; use ascent as vertical origin.
+ outXYArray[1] = -ascent;
+ }
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/opentype/OpenTypeVerticalData.h b/Source/WebCore/platform/graphics/opentype/OpenTypeVerticalData.h
new file mode 100644
index 000000000..85e4ee7a1
--- /dev/null
+++ b/Source/WebCore/platform/graphics/opentype/OpenTypeVerticalData.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 Koji Ishii <kojiishi@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef OpenTypeVerticalData_h
+#define OpenTypeVerticalData_h
+
+#include "Glyph.h"
+#include <wtf/HashMap.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class FontPlatformData;
+class GlyphPage;
+class SimpleFontData;
+
+class OpenTypeVerticalData {
+public:
+ OpenTypeVerticalData(const FontPlatformData&);
+
+ bool isOpenType() const { return !m_advanceWidths.isEmpty(); }
+ bool hasVerticalMetrics() const { return !m_advanceHeights.isEmpty(); }
+ float advanceHeight(const SimpleFontData*, Glyph) const;
+ void getVerticalTranslationsForGlyphs(const SimpleFontData*, const Glyph*, size_t, float* outXYArray) const;
+
+private:
+ bool hasVORG() const { return !m_vertOriginY.isEmpty(); }
+
+ Vector<uint16_t> m_advanceWidths;
+ Vector<uint16_t> m_advanceHeights;
+ Vector<int16_t> m_topSideBearings;
+ int16_t m_defaultVertOriginY;
+ HashMap<Glyph, int16_t> m_vertOriginY;
+};
+
+} // namespace WebCore
+
+#endif // OpenTypeVerticalData_h
diff --git a/Source/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp b/Source/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp
index 4417d7b81..74c94f3d4 100644
--- a/Source/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp
+++ b/Source/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp
@@ -246,7 +246,7 @@ void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool pr
UNUSED_PARAM(printing);
}
-void GraphicsContext::drawLineForTextChecking(const IntPoint& origin, int width, TextCheckingLineStyle style)
+void GraphicsContext::drawLineForDocumentMarker(const IntPoint& origin, int width, DocumentMarkerLineStyle style)
{
if (paintingDisabled())
return;
diff --git a/Source/WebCore/platform/graphics/pango/FontPango.cpp b/Source/WebCore/platform/graphics/pango/FontPango.cpp
index 0c60c767c..cef443db4 100644
--- a/Source/WebCore/platform/graphics/pango/FontPango.cpp
+++ b/Source/WebCore/platform/graphics/pango/FontPango.cpp
@@ -35,7 +35,7 @@
#include "Font.h"
#include "CairoUtilities.h"
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#include "GraphicsContext.h"
#include "NotImplemented.h"
#include "PlatformContextCairo.h"
diff --git a/Source/WebCore/platform/graphics/qt/FontCacheQt.cpp b/Source/WebCore/platform/graphics/qt/FontCacheQt.cpp
index 02ce42a9c..816bccb89 100644
--- a/Source/WebCore/platform/graphics/qt/FontCacheQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/FontCacheQt.cpp
@@ -49,35 +49,29 @@ void FontCache::platformInit()
}
#if HAVE(QRAWFONT)
-static QRawFont rawFontForCharacters(const QString& string, const QFont& requestedFont)
+static QRawFont rawFontForCharacters(const QString& string, const QRawFont& font)
{
- QFont font(requestedFont);
- font.setStyleStrategy(QFont::NoFontMerging);
-
- QTextLayout layout(string, font);
+ QTextLayout layout(string);
+ layout.setRawFont(font);
layout.beginLayout();
layout.createLine();
layout.endLayout();
QList<QGlyphRun> glyphList = layout.glyphRuns();
-
- ASSERT(glyphList.size() == 1);
-
- const QGlyphRun& glyphs(glyphList.at(0));
- QVector<quint32> glyphIndexes = glyphs.glyphIndexes();
-
- if (glyphIndexes.isEmpty())
+ ASSERT(glyphList.size() <= 1);
+ if (!glyphList.size())
return QRawFont();
+ const QGlyphRun& glyphs(glyphList.at(0));
return glyphs.rawFont();
}
-#endif
+#endif // HAVE(QRAWFONT)
const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
{
#if HAVE(QRAWFONT)
QString qstring = QString::fromRawData(reinterpret_cast<const QChar*>(characters), length);
- QRawFont computedFont = rawFontForCharacters(qstring, font.font());
+ QRawFont computedFont = rawFontForCharacters(qstring, font.rawFont());
if (!computedFont.isValid())
return 0;
FontPlatformData alternateFont(computedFont);
@@ -107,11 +101,9 @@ void FontCache::getTraitsInFamily(const AtomicString&, Vector<unsigned>&)
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName)
{
-#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
QFontDatabase db;
if (!db.hasFamily(familyName))
return 0;
-#endif
return new FontPlatformData(fontDescription, familyName);
}
diff --git a/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h
index 3996d223b..7fa9f8c11 100644
--- a/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h
+++ b/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h
@@ -29,6 +29,9 @@
#include <wtf/FastAllocBase.h>
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
+#if HAVE(QRAWFONT)
+#include <QRawFont>
+#endif
namespace WebCore {
@@ -41,8 +44,12 @@ public:
FontCustomPlatformData() { }
~FontCustomPlatformData();
+#if !HAVE(QRAWFONT)
// for use with QFontDatabase::addApplicationFont/removeApplicationFont
int m_handle;
+#else
+ QRawFont m_rawFont;
+#endif
FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight,
FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
diff --git a/Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp b/Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp
index 20f161a8f..4c5b96488 100644
--- a/Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp
@@ -24,40 +24,60 @@
#include "FontPlatformData.h"
#include "SharedBuffer.h"
+#if !HAVE(QRAWFONT)
#include <QFontDatabase>
+#endif
#include <QStringList>
namespace WebCore {
FontCustomPlatformData::~FontCustomPlatformData()
{
+#if !HAVE(QRAWFONT)
QFontDatabase::removeApplicationFont(m_handle);
+#endif
}
FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode)
{
+#if !HAVE(QRAWFONT)
QFont font;
font.setFamily(QFontDatabase::applicationFontFamilies(m_handle)[0]);
font.setPixelSize(size);
if (bold)
font.setWeight(QFont::Bold);
font.setItalic(italic);
-
return FontPlatformData(font);
+#else
+ Q_ASSERT(m_rawFont.isValid());
+ m_rawFont.setPixelSize(qreal(size));
+ return FontPlatformData(m_rawFont);
+#endif
}
FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
{
ASSERT_ARG(buffer, buffer);
- int id = QFontDatabase::addApplicationFontFromData(QByteArray(buffer->data(), buffer->size()));
+ const QByteArray fontData(buffer->data(), buffer->size());
+#if !HAVE(QRAWFONT)
+ int id = QFontDatabase::addApplicationFontFromData(fontData);
if (id == -1)
return 0;
-
Q_ASSERT(QFontDatabase::applicationFontFamilies(id).size() > 0);
+#else
+ // Pixel size doesn't matter at this point, it is set in FontCustomPlatformData::fontPlatformData.
+ QRawFont rawFont(fontData, /*pixelSize = */0, QFont::PreferDefaultHinting);
+ if (!rawFont.isValid())
+ return 0;
+#endif
FontCustomPlatformData *data = new FontCustomPlatformData;
+#if !HAVE(QRAWFONT)
data->m_handle = id;
+#else
+ data->m_rawFont = rawFont;
+#endif
return data;
}
diff --git a/Source/WebCore/platform/graphics/qt/FontPlatformData.h b/Source/WebCore/platform/graphics/qt/FontPlatformData.h
index 7662aa007..f55e19c2b 100644
--- a/Source/WebCore/platform/graphics/qt/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/qt/FontPlatformData.h
@@ -40,8 +40,13 @@ class FontPlatformDataPrivate : public RefCounted<FontPlatformDataPrivate> {
WTF_MAKE_NONCOPYABLE(FontPlatformDataPrivate); WTF_MAKE_FAST_ALLOCATED;
public:
FontPlatformDataPrivate()
+#if !HAVE(QRAWFONT)
: size(font.pixelSize())
, bold(font.bold())
+#else
+ : size(0)
+ , bold(false)
+#endif
, oblique(false)
, isDeletedValue(false)
{ }
@@ -51,20 +56,17 @@ public:
, oblique(oblique)
, isDeletedValue(false)
{ }
+#if !HAVE(QRAWFONT)
FontPlatformDataPrivate(const QFont& font)
: font(font)
-#if HAVE(QRAWFONT)
- , rawFont(QRawFont::fromFont(font, QFontDatabase::Any))
-#endif
, size(font.pixelSize())
, bold(font.bold())
, oblique(false)
, isDeletedValue(false)
{ }
-#if HAVE(QRAWFONT)
+#else
FontPlatformDataPrivate(const QRawFont& rawFont)
- : font()
- , rawFont(rawFont)
+ : rawFont(rawFont)
, size(rawFont.pixelSize())
, bold(rawFont.weight() >= QFont::Bold)
, oblique(false)
@@ -75,8 +77,9 @@ public:
: isDeletedValue(true)
{ }
+#if !HAVE(QRAWFONT)
QFont font;
-#if HAVE(QRAWFONT)
+#else
QRawFont rawFont;
#endif
float size;
@@ -90,10 +93,11 @@ class FontPlatformData {
public:
FontPlatformData(float size, bool bold, bool oblique);
FontPlatformData(const FontDescription&, const AtomicString& familyName, int wordSpacing = 0, int letterSpacing = 0);
+#if !HAVE(QRAWFONT)
FontPlatformData(const QFont& font)
: m_data(adoptRef(new FontPlatformDataPrivate(font)))
{ }
-#if HAVE(QRAWFONT)
+#else
FontPlatformData(const FontPlatformData&, float size);
FontPlatformData(const QRawFont& rawFont)
: m_data(adoptRef(new FontPlatformDataPrivate(rawFont)))
@@ -112,6 +116,7 @@ public:
return m_data && m_data->isDeletedValue;
}
+#if !HAVE(QRAWFONT)
QFont font() const
{
Q_ASSERT(!isHashTableDeletedValue());
@@ -119,7 +124,7 @@ public:
return QFont();
return m_data->font;
}
-#if HAVE(QRAWFONT)
+#else
QRawFont rawFont() const
{
Q_ASSERT(!isHashTableDeletedValue());
diff --git a/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp b/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
index 86fc12e3a..44c9fdfca 100644
--- a/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
@@ -63,7 +63,11 @@ FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
FontPlatformData::FontPlatformData(const FontDescription& description, const AtomicString& familyName, int wordSpacing, int letterSpacing)
: m_data(adoptRef(new FontPlatformDataPrivate()))
{
+#if !HAVE(QRAWFONT)
QFont& font = m_data->font;
+#else
+ QFont font;
+#endif
int requestedSize = description.computedPixelSize();
font.setFamily(familyName);
font.setPixelSize(requestedSize);
@@ -71,17 +75,19 @@ FontPlatformData::FontPlatformData(const FontDescription& description, const Ato
font.setWeight(toQFontWeight(description.weight()));
font.setWordSpacing(wordSpacing);
font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing);
- const bool smallCaps = description.smallCaps();
- font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase);
font.setStyleStrategy(QFont::ForceIntegerMetrics);
m_data->bold = font.bold();
+#if !HAVE(QRAWFONT)
+ const bool smallCaps = description.smallCaps();
+ font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase);
// WebKit allows font size zero but QFont does not. We will return
// m_data->size if a font size of zero is requested and pixelSize()
// otherwise.
m_data->size = (!requestedSize) ? requestedSize : font.pixelSize();
-#if HAVE(QRAWFONT)
+#else
m_data->rawFont = QRawFont::fromFont(font, QFontDatabase::Any);
+ m_data->size = requestedSize;
#endif
}
@@ -89,15 +95,13 @@ FontPlatformData::FontPlatformData(const FontDescription& description, const Ato
FontPlatformData::FontPlatformData(const FontPlatformData& other, float size)
: m_data(adoptRef(new FontPlatformDataPrivate()))
{
- m_data->font = other.m_data->font;
m_data->rawFont = other.m_data->rawFont;
m_data->bold = other.m_data->bold;
m_data->oblique = other.m_data->oblique;
- m_data->font.setPixelSize(size);
m_data->rawFont.setPixelSize(size);
- m_data->size = size ? m_data->font.pixelSize() : 0;
+ m_data->size = m_data->rawFont.pixelSize();
}
-#endif
+#endif // HAVE(QRAWFONT)
bool FontPlatformData::operator==(const FontPlatformData& other) const
{
@@ -110,7 +114,11 @@ bool FontPlatformData::operator==(const FontPlatformData& other) const
const bool equals = (m_data->size == other.m_data->size
&& m_data->bold == other.m_data->bold
&& m_data->oblique == other.m_data->oblique
+#if !HAVE(QRAWFONT)
&& m_data->font == other.m_data->font);
+#else
+ && m_data->rawFont == other.m_data->rawFont);
+#endif
return equals;
}
@@ -120,10 +128,15 @@ unsigned FontPlatformData::hash() const
return 0;
if (m_data->isDeletedValue)
return 1;
- return qHash(m_data->font.toString())
- ^ qHash(*reinterpret_cast<quint32*>(&m_data->size))
- ^ qHash(m_data->bold)
- ^ qHash(m_data->oblique);
+#if !HAVE(QRAWFONT)
+ return (qHash(m_data->font.toString()) ^ qHash(m_data->bold)
+ ^ qHash(m_data->oblique))
+ ^ qHash(*reinterpret_cast<quint32*>(&m_data->size));
+#else
+ return qHash(m_data->rawFont.familyName()) ^ qHash(m_data->rawFont.style())
+ ^ qHash(m_data->rawFont.weight())
+ ^ qHash(*reinterpret_cast<quint32*>(&m_data->size));
+#endif
}
#ifndef NDEBUG
diff --git a/Source/WebCore/platform/graphics/qt/FontQt.cpp b/Source/WebCore/platform/graphics/qt/FontQt.cpp
index 51193349f..b55f0b7b1 100644
--- a/Source/WebCore/platform/graphics/qt/FontQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/FontQt.cpp
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
Copyright (C) 2008, 2010 Holger Hans Peter Freyther
Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
@@ -26,9 +26,7 @@
#include "FontDescription.h"
#include "FontFallbackList.h"
#include "FontSelector.h"
-#if HAVE(QRAWFONT)
#include "GlyphBuffer.h"
-#endif
#include "Gradient.h"
#include "GraphicsContext.h"
#include "NotImplemented.h"
@@ -37,17 +35,12 @@
#include "TextRun.h"
#include <QBrush>
-#include <QFontInfo>
-#include <QFontMetrics>
#include <QPainter>
#include <QPainterPath>
#include <QPen>
-#if HAVE(QRAWFONT)
#include <QPointF>
-#endif
#include <QTextLayout>
#include <qalgorithms.h>
-#include <qdebug.h>
#include <limits.h>
@@ -92,7 +85,7 @@ static QPen fillPenForContext(GraphicsContext* ctx)
return QPen(QBrush(ctx->fillPattern()->createPlatformPattern(affine)), 0);
}
- return QPen(QColor(ctx->fillColor()));
+ return QPen(QColor(ctx->fillColor()), 0);
}
static QPen strokePenForContext(GraphicsContext* ctx)
@@ -112,158 +105,92 @@ static QPen strokePenForContext(GraphicsContext* ctx)
return QPen(QColor(ctx->strokeColor()), ctx->strokeThickness());
}
-static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to, const QFont& font, bool isComplexText)
+static QPainterPath pathForGlyphs(const QGlyphRun& glyphRun, const QPointF& offset)
{
- if (to < 0)
- to = run.length();
-
- QPainter *p = ctx->platformContext();
-
- QPen textFillPen;
- if (ctx->textDrawingMode() & TextModeFill)
- textFillPen = fillPenForContext(ctx);
-
- QPen textStrokePen;
- if (ctx->textDrawingMode() & TextModeStroke)
- textStrokePen = strokePenForContext(ctx);
-
- String sanitized = Font::normalizeSpaces(run.characters(), run.length());
- QString string = fromRawDataWithoutRef(sanitized);
- QPointF pt(point.x(), point.y());
-
- if (from > 0 || to < run.length()) {
- if (isComplexText) {
- QTextLayout layout(string, font);
- QTextLine line = setupLayout(&layout, run);
- float x1 = line.cursorToX(from);
- float x2 = line.cursorToX(to);
- if (x2 < x1)
- qSwap(x1, x2);
-
- QFontMetrics fm(font);
- int ascent = fm.ascent();
- QRectF boundingRect(point.x() + x1, point.y() - ascent, x2 - x1, fm.height());
- QRectF clip = boundingRect;
-
- ShadowBlur* ctxShadow = ctx->shadowBlur();
- if (ctxShadow->type() != ShadowBlur::NoShadow) {
- const QPointF shadowOffset(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height());
- qreal dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0;
- if (shadowOffset.x() > 0)
- dx2 = shadowOffset.x();
- else
- dx1 = -shadowOffset.x();
- if (shadowOffset.y() > 0)
- dy2 = shadowOffset.y();
- else
- dy1 = -shadowOffset.y();
- // expand the clip rect to include the text shadow as well
- const float blurDistance = ctx->state().shadowBlur;
- clip.adjust(dx1, dx2, dy1, dy2);
- clip.adjust(-blurDistance, -blurDistance, blurDistance, blurDistance);
- }
- p->save();
- p->setClipRect(clip.toRect(), Qt::IntersectClip);
- pt.setY(pt.y() - ascent);
-
- if (ctxShadow->type() != ShadowBlur::NoShadow) {
- ShadowBlur* ctxShadow = ctx->shadowBlur();
- if (ctxShadow->type() != ShadowBlur::BlurShadow
- && (!ctxShadow->shadowsIgnoreTransforms() || ctx->getCTM().isIdentity())) {
- p->save();
- p->setPen(ctx->state().shadowColor);
- p->translate(QPointF(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height()));
- line.draw(p, pt);
- p->restore();
- } else {
- GraphicsContext* shadowContext = ctxShadow->beginShadowLayer(ctx, boundingRect);
- if (shadowContext) {
- QPainter* shadowPainter = shadowContext->platformContext();
- // Since it will be blurred anyway, we don't care about render hints.
- shadowPainter->setFont(p->font());
- shadowPainter->setPen(ctx->state().shadowColor);
- line.draw(shadowPainter, pt);
- ctxShadow->endShadowLayer(ctx);
- }
- }
- }
- p->setPen(textFillPen);
- line.draw(p, pt);
- p->restore();
- return;
- }
- int skipWidth = QFontMetrics(font).width(string, from, Qt::TextBypassShaping);
- pt.setX(pt.x() + skipWidth);
- string = fromRawDataWithoutRef(sanitized, from, to - from);
+ QPainterPath path;
+ const QRawFont rawFont(glyphRun.rawFont());
+ const QVector<quint32> glyphIndices = glyphRun.glyphIndexes();
+ const QVector<QPointF> positions = glyphRun.positions();
+ for (int i = 0; i < glyphIndices.size(); ++i) {
+ QPainterPath glyphPath = rawFont.pathForGlyph(glyphIndices.at(i));
+ glyphPath.translate(positions.at(i) + offset);
+ path.addPath(glyphPath);
}
+ return path;
+}
- p->setFont(font);
-
- int flags = run.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
- if (!isComplexText && !(ctx->textDrawingMode() & TextModeStroke))
- flags |= Qt::TextBypassShaping;
+static void drawQtGlyphRun(GraphicsContext* context, const QGlyphRun& qtGlyphRun, const QPointF& point, int baseLineOffset)
+{
+ QPainter* painter = context->platformContext();
QPainterPath textStrokePath;
- if (ctx->textDrawingMode() & TextModeStroke)
- textStrokePath.addText(pt, font, string);
-
- ShadowBlur* ctxShadow = ctx->shadowBlur();
- if (ctx->hasShadow() && ctxShadow->type() != ShadowBlur::NoShadow) {
- if (ctx->textDrawingMode() & TextModeFill) {
- if (ctxShadow->type() != ShadowBlur::BlurShadow) {
- p->save();
- p->setPen(ctx->state().shadowColor);
- p->translate(QPointF(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height()));
- p->drawText(pt, string, flags, run.expansion());
- p->restore();
- } else {
- QFontMetrics fm(font);
- QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string, -1, flags), fm.height());
- GraphicsContext* shadowContext = ctxShadow->beginShadowLayer(ctx, boundingRect);
- if (shadowContext) {
- QPainter* shadowPainter = shadowContext->platformContext();
- // Since it will be blurred anyway, we don't care about render hints.
- shadowPainter->setFont(p->font());
- shadowPainter->setPen(ctx->state().shadowColor);
- shadowPainter->drawText(pt, string, flags, run.expansion());
- ctxShadow->endShadowLayer(ctx);
- }
- }
- } else if (ctx->textDrawingMode() & TextModeStroke) {
- if (ctxShadow->type() != ShadowBlur::BlurShadow) {
- const QPointF shadowOffset(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height());
- p->translate(shadowOffset);
- p->strokePath(textStrokePath, QPen(ctx->state().shadowColor));
- p->translate(-shadowOffset);
- } else {
- QFontMetrics fm(font);
- QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string, -1, flags), fm.height());
- GraphicsContext* shadowContext = ctxShadow->beginShadowLayer(ctx, boundingRect);
- if (shadowContext) {
- QPainter* shadowPainter = shadowContext->platformContext();
- // Since it will be blurred anyway, we don't care about render hints.
- shadowPainter->setFont(p->font());
- shadowPainter->strokePath(textStrokePath, QPen(ctx->state().shadowColor));
- ctxShadow->endShadowLayer(ctx);
- }
+ if (context->textDrawingMode() & TextModeStroke)
+ textStrokePath = pathForGlyphs(qtGlyphRun, point);
+
+ ShadowBlur* shadow = context->shadowBlur();
+ if (context->hasShadow() && shadow->type() != ShadowBlur::NoShadow) {
+ switch (shadow->type()) {
+ case ShadowBlur::SolidShadow: {
+ QPen previousPen = painter->pen();
+ painter->setPen(context->state().shadowColor);
+ const QPointF shadowOffset(context->state().shadowOffset.width(), context->state().shadowOffset.height());
+ painter->translate(shadowOffset);
+ if (context->textDrawingMode() & TextModeFill)
+ painter->drawGlyphRun(point, qtGlyphRun);
+ else if (context->textDrawingMode() & TextModeStroke)
+ painter->strokePath(textStrokePath, painter->pen());
+ painter->translate(-shadowOffset);
+ painter->setPen(previousPen);
+ break;
+ }
+ case ShadowBlur::BlurShadow: {
+ const int width = qtGlyphRun.boundingRect().width();
+ const QRawFont& font = qtGlyphRun.rawFont();
+ const int height = font.ascent() + font.descent();
+ const QRectF boundingRect(point.x(), point.y() - font.ascent() + baseLineOffset, width, height);
+ GraphicsContext* shadowContext = shadow->beginShadowLayer(context, boundingRect);
+ if (shadowContext) {
+ QPainter* shadowPainter = shadowContext->platformContext();
+ shadowPainter->setPen(shadowContext->state().shadowColor);
+ if (shadowContext->textDrawingMode() & TextModeFill)
+ shadowPainter->drawGlyphRun(point, qtGlyphRun);
+ else if (shadowContext->textDrawingMode() & TextModeStroke)
+ shadowPainter->strokePath(textStrokePath, shadowPainter->pen());
+ shadow->endShadowLayer(context);
}
+ break;
+ }
+ case ShadowBlur::NoShadow:
+ default:
+ ASSERT_NOT_REACHED();
+ break;
}
}
- if (ctx->textDrawingMode() & TextModeStroke)
- p->strokePath(textStrokePath, textStrokePen);
+ if (context->textDrawingMode() & TextModeStroke)
+ painter->strokePath(textStrokePath, strokePenForContext(context));
- if (ctx->textDrawingMode() & TextModeFill) {
- QPen previousPen = p->pen();
- p->setPen(textFillPen);
- p->drawText(pt, string, flags, run.expansion());
- p->setPen(previousPen);
+ if (context->textDrawingMode() & TextModeFill) {
+ QPen previousPen = painter->pen();
+ painter->setPen(fillPenForContext(context));
+ painter->drawGlyphRun(point, qtGlyphRun);
+ painter->setPen(previousPen);
}
}
void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
{
- drawTextCommon(ctx, run, point, from, to, font(), /* isComplexText = */true);
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
+ const QString string = fromRawDataWithoutRef(sanitized);
+ QTextLayout layout(string);
+ layout.setRawFont(rawFont());
+ initFormatForTextLayout(&layout);
+ QTextLine line = setupLayout(&layout, run);
+ const QPointF adjustedPoint(point.x(), point.y() - line.ascent());
+
+ QList<QGlyphRun> runs = line.glyphRuns(from, to - from);
+ Q_FOREACH(QGlyphRun glyphRun, runs)
+ drawQtGlyphRun(ctx, glyphRun, adjustedPoint, line.ascent());
}
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const
@@ -275,17 +202,19 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
return 0;
if (run.length() == 1 && treatAsSpace(run[0]))
- return QFontMetrics(font()).width(space) + run.expansion();
-
+ return primaryFont()->spaceWidth() + run.expansion();
String sanitized = Font::normalizeSpaces(run.characters(), run.length());
QString string = fromRawDataWithoutRef(sanitized);
- int w = QFontMetrics(font()).width(string);
- // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does)
- if (treatAsSpace(run[0]))
- w -= m_wordSpacing;
+ QTextLayout layout(string);
+ layout.setRawFont(rawFont());
+ initFormatForTextLayout(&layout);
+ QTextLine line = setupLayout(&layout, run);
+ float x1 = line.cursorToX(0);
+ float x2 = line.cursorToX(run.length());
+ const float width = qAbs(x2 - x1);
- return w + run.expansion();
+ return width + run.expansion();
}
int Font::offsetForPositionForComplexText(const TextRun& run, float position, bool) const
@@ -293,7 +222,9 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float position, bo
String sanitized = Font::normalizeSpaces(run.characters(), run.length());
QString string = fromRawDataWithoutRef(sanitized);
- QTextLayout layout(string, font());
+ QTextLayout layout(string);
+ layout.setRawFont(rawFont());
+ initFormatForTextLayout(&layout);
QTextLine line = setupLayout(&layout, run);
return line.xToCursor(position);
}
@@ -303,7 +234,9 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint
String sanitized = Font::normalizeSpaces(run.characters(), run.length());
QString string = fromRawDataWithoutRef(sanitized);
- QTextLayout layout(string, font());
+ QTextLayout layout(string);
+ layout.setRawFont(rawFont());
+ initFormatForTextLayout(&layout);
QTextLine line = setupLayout(&layout, run);
float x1 = line.cursorToX(from);
@@ -314,6 +247,24 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint
return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h);
}
+void Font::initFormatForTextLayout(QTextLayout* layout) const
+{
+ QTextLayout::FormatRange range;
+ range.start = 0;
+ range.length = layout->text().length();
+ if (m_wordSpacing)
+ range.format.setFontWordSpacing(m_wordSpacing);
+ if (m_letterSpacing)
+ range.format.setFontLetterSpacing(m_letterSpacing);
+ if (typesettingFeatures() & Kerning)
+ range.format.setFontKerning(true);
+ if (isSmallCaps())
+ range.format.setFontCapitalization(QFont::SmallCaps);
+
+ if (range.format.propertyCount())
+ layout->setAdditionalFormats(QList<QTextLayout::FormatRange>() << range);
+}
+
bool Font::canReturnFallbackFontsForComplexText()
{
return false;
@@ -324,7 +275,6 @@ void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const
notImplemented();
}
-#if HAVE(QRAWFONT)
void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* fontData, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
{
if (context->paintingDisabled())
@@ -333,9 +283,6 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* fontData,
bool shouldFill = context->textDrawingMode() & TextModeFill;
bool shouldStroke = context->textDrawingMode() & TextModeStroke;
- // Stroking text should always take the complex path.
- ASSERT(!shouldStroke);
-
if (!shouldFill && !shouldStroke)
return;
@@ -344,6 +291,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* fontData,
glyphIndexes.reserve(numGlyphs);
positions.reserve(numGlyphs);
+ const QRawFont& font(fontData->getQtRawFont());
float width = 0;
@@ -357,166 +305,39 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* fontData,
width += advance;
}
- QRawFont rawFont(fontData->platformData().rawFont());
-
QGlyphRun qtGlyphs;
qtGlyphs.setGlyphIndexes(glyphIndexes);
qtGlyphs.setPositions(positions);
- qtGlyphs.setRawFont(rawFont);
-
- QPainter* painter = context->platformContext();
-
- ShadowBlur* shadow = context->shadowBlur();
- switch (shadow->type()) {
- case ShadowBlur::SolidShadow: {
- QPen previousPen = painter->pen();
- painter->setPen(context->state().shadowColor);
- const QPointF shadowOffset(context->state().shadowOffset.width(), context->state().shadowOffset.height());
- painter->translate(shadowOffset);
- painter->drawGlyphRun(point, qtGlyphs);
- painter->translate(-shadowOffset);
- painter->setPen(previousPen);
- break;
- }
- case ShadowBlur::BlurShadow: {
- qreal height = rawFont.ascent() + rawFont.descent() + 1;
- QRectF boundingRect(point.x(), point.y() - rawFont.ascent(), width, height);
- GraphicsContext* shadowContext = shadow->beginShadowLayer(context, boundingRect);
- if (shadowContext) {
- QPainter* shadowPainter = shadowContext->platformContext();
- shadowPainter->setPen(context->state().shadowColor);
- shadowPainter->drawGlyphRun(point, qtGlyphs);
- shadow->endShadowLayer(context);
- }
- break;
- }
- case ShadowBlur::NoShadow:
- break;
- default:
- ASSERT_NOT_REACHED();
- break;
- }
-
- QPen previousPen = painter->pen();
- painter->setPen(fillPenForContext(context));
- painter->drawGlyphRun(point, qtGlyphs);
- painter->setPen(previousPen);
-}
-
-bool Font::canExpandAroundIdeographsInComplexText()
-{
- return false;
-}
-
-#else // !HAVE(QRAWFONT)
-
-void Font::drawSimpleText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
-{
- drawTextCommon(ctx, run, point, from, to, font(), /* isComplexText = */false);
-}
-
-int Font::offsetForPositionForSimpleText(const TextRun& run, float position, bool includePartialGlyphs) const
-{
- String sanitized = Font::normalizeSpaces(run.characters(), run.length());
- QString string = fromRawDataWithoutRef(sanitized);
-
- QFontMetrics fm(font());
- float delta = position;
- int curPos = 0;
- do {
- float charWidth = fm.width(string[curPos]);
- delta -= charWidth;
- if (includePartialGlyphs) {
- if (delta + charWidth / 2 <= 0)
- break;
- } else {
- if (delta + charWidth <= 0)
- break;
- }
- } while (++curPos < string.size());
+ qtGlyphs.setRawFont(font);
- return curPos;
+ drawQtGlyphRun(context, qtGlyphs, point, /* baselineOffset = */0);
}
-float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
-{
- if (!primaryFont()->platformData().size())
- return 0;
-
- if (!run.length())
- return 0;
-
- String sanitized = Font::normalizeSpaces(run.characters(), run.length());
- QString string = fromRawDataWithoutRef(sanitized);
-
- int w = QFontMetrics(font()).width(string, -1, Qt::TextBypassShaping);
-
- // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does)
- if (treatAsSpace(run[0]))
- w -= m_wordSpacing;
-
- return w + run.expansion();
-}
-
-
-FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const
-{
- String sanitized = Font::normalizeSpaces(run.characters(), run.length());
- QString wholeText = fromRawDataWithoutRef(sanitized);
- QString selectedText = fromRawDataWithoutRef(sanitized, from, qMin(to - from, wholeText.length() - from));
-
- int startX = QFontMetrics(font()).width(wholeText, from, Qt::TextBypassShaping);
- int width = QFontMetrics(font()).width(selectedText, -1, Qt::TextBypassShaping);
-
- return FloatRect(pt.x() + startX, pt.y(), width, h);
-}
-
bool Font::canExpandAroundIdeographsInComplexText()
{
return false;
}
-bool Font::primaryFontHasGlyphForCharacter(UChar32) const
-{
- notImplemented();
- return true;
-}
-
-int Font::emphasisMarkAscent(const AtomicString&) const
+QFont Font::syntheticFont() const
{
- notImplemented();
- return 0;
-}
-
-int Font::emphasisMarkDescent(const AtomicString&) const
-{
- notImplemented();
- return 0;
-}
-
-int Font::emphasisMarkHeight(const AtomicString&) const
-{
- notImplemented();
- return 0;
-}
-
-void Font::drawEmphasisMarksForSimpleText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
-{
- notImplemented();
-}
-#endif // HAVE(QRAWFONT)
-
-QFont Font::font() const
-{
- QFont f = primaryFont()->getQtFont();
- if (m_letterSpacing != 0)
+ QRawFont rawFont(primaryFont()->getQtRawFont());
+ QFont f(rawFont.familyName());
+ if (rawFont.pixelSize())
+ f.setPixelSize(rawFont.pixelSize());
+ f.setWeight(rawFont.weight());
+ f.setStyle(rawFont.style());
+ if (m_letterSpacing)
f.setLetterSpacing(QFont::AbsoluteSpacing, m_letterSpacing);
- if (m_wordSpacing != 0)
+ if (m_wordSpacing)
f.setWordSpacing(m_wordSpacing);
return f;
}
+QRawFont Font::rawFont() const
+{
+ return primaryFont()->getQtRawFont();
}
+}
diff --git a/Source/WebCore/platform/graphics/qt/FontQt4.cpp b/Source/WebCore/platform/graphics/qt/FontQt4.cpp
new file mode 100644
index 000000000..b021f9c64
--- /dev/null
+++ b/Source/WebCore/platform/graphics/qt/FontQt4.cpp
@@ -0,0 +1,434 @@
+/*
+ Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2008, 2010 Holger Hans Peter Freyther
+ Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "Font.h"
+
+#include "AffineTransform.h"
+#include "FontDescription.h"
+#include "FontFallbackList.h"
+#include "FontSelector.h"
+#include "GlyphBuffer.h"
+#include "Gradient.h"
+#include "GraphicsContext.h"
+#include "NotImplemented.h"
+#include "Pattern.h"
+#include "ShadowBlur.h"
+#include "TextRun.h"
+
+#include <QBrush>
+#include <QFontInfo>
+#include <QFontMetrics>
+#include <QPainter>
+#include <QPainterPath>
+#include <QPen>
+#include <QTextLayout>
+#include <limits.h>
+#include <qalgorithms.h>
+#include <qdebug.h>
+
+
+namespace WebCore {
+
+static const QString fromRawDataWithoutRef(const String& string, int start = 0, int len = -1)
+{
+ if (len < 0)
+ len = string.length() - start;
+ Q_ASSERT(start + len <= string.length());
+
+ // We don't detach. This assumes the WebCore string data will stay valid for the
+ // lifetime of the QString we pass back, since we don't ref the WebCore string.
+ return QString::fromRawData(reinterpret_cast<const QChar*>(string.characters() + start), len);
+}
+
+static QTextLine setupLayout(QTextLayout* layout, const TextRun& style)
+{
+ int flags = style.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
+ if (style.expansion())
+ flags |= Qt::TextJustificationForced;
+ layout->setFlags(flags);
+ layout->beginLayout();
+ QTextLine line = layout->createLine();
+ line.setLineWidth(INT_MAX / 256);
+ if (style.expansion())
+ line.setLineWidth(line.naturalTextWidth() + style.expansion());
+ layout->endLayout();
+ return line;
+}
+
+static QPen fillPenForContext(GraphicsContext* ctx)
+{
+ if (ctx->fillGradient()) {
+ QBrush brush(*ctx->fillGradient()->platformGradient());
+ brush.setTransform(ctx->fillGradient()->gradientSpaceTransform());
+ return QPen(brush, 0);
+ }
+
+ if (ctx->fillPattern()) {
+ AffineTransform affine;
+ return QPen(QBrush(ctx->fillPattern()->createPlatformPattern(affine)), 0);
+ }
+
+ return QPen(QColor(ctx->fillColor()));
+}
+
+static QPen strokePenForContext(GraphicsContext* ctx)
+{
+ if (ctx->strokeGradient()) {
+ QBrush brush(*ctx->strokeGradient()->platformGradient());
+ brush.setTransform(ctx->strokeGradient()->gradientSpaceTransform());
+ return QPen(brush, ctx->strokeThickness());
+ }
+
+ if (ctx->strokePattern()) {
+ AffineTransform affine;
+ QBrush brush(ctx->strokePattern()->createPlatformPattern(affine));
+ return QPen(brush, ctx->strokeThickness());
+ }
+
+ return QPen(QColor(ctx->strokeColor()), ctx->strokeThickness());
+}
+
+static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to, const QFont& font, bool isComplexText)
+{
+ if (to < 0)
+ to = run.length();
+
+ QPainter* p = ctx->platformContext();
+
+ QPen textFillPen;
+ if (ctx->textDrawingMode() & TextModeFill)
+ textFillPen = fillPenForContext(ctx);
+
+ QPen textStrokePen;
+ if (ctx->textDrawingMode() & TextModeStroke)
+ textStrokePen = strokePenForContext(ctx);
+
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
+ QString string = fromRawDataWithoutRef(sanitized);
+ QPointF pt(point.x(), point.y());
+
+ if (from > 0 || to < run.length()) {
+ if (isComplexText) {
+ QTextLayout layout(string, font);
+ QTextLine line = setupLayout(&layout, run);
+ float x1 = line.cursorToX(from);
+ float x2 = line.cursorToX(to);
+ if (x2 < x1)
+ qSwap(x1, x2);
+
+ QFontMetrics fm(font);
+ int ascent = fm.ascent();
+ QRectF boundingRect(point.x() + x1, point.y() - ascent, x2 - x1, fm.height());
+ QRectF clip = boundingRect;
+
+ ShadowBlur* ctxShadow = ctx->shadowBlur();
+ if (ctxShadow->type() != ShadowBlur::NoShadow) {
+ const QPointF shadowOffset(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height());
+ qreal dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0;
+ if (shadowOffset.x() > 0)
+ dx2 = shadowOffset.x();
+ else
+ dx1 = -shadowOffset.x();
+ if (shadowOffset.y() > 0)
+ dy2 = shadowOffset.y();
+ else
+ dy1 = -shadowOffset.y();
+ // expand the clip rect to include the text shadow as well
+ const float blurDistance = ctx->state().shadowBlur;
+ clip.adjust(dx1, dx2, dy1, dy2);
+ clip.adjust(-blurDistance, -blurDistance, blurDistance, blurDistance);
+ }
+ p->save();
+ p->setClipRect(clip.toRect(), Qt::IntersectClip);
+ pt.setY(pt.y() - ascent);
+
+ if (ctxShadow->type() != ShadowBlur::NoShadow) {
+ ShadowBlur* ctxShadow = ctx->shadowBlur();
+ if (ctxShadow->type() != ShadowBlur::BlurShadow
+ && (!ctxShadow->shadowsIgnoreTransforms() || ctx->getCTM().isIdentity())) {
+ p->save();
+ p->setPen(ctx->state().shadowColor);
+ p->translate(QPointF(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height()));
+ line.draw(p, pt);
+ p->restore();
+ } else {
+ GraphicsContext* shadowContext = ctxShadow->beginShadowLayer(ctx, boundingRect);
+ if (shadowContext) {
+ QPainter* shadowPainter = shadowContext->platformContext();
+ // Since it will be blurred anyway, we don't care about render hints.
+ shadowPainter->setFont(p->font());
+ shadowPainter->setPen(ctx->state().shadowColor);
+ line.draw(shadowPainter, pt);
+ ctxShadow->endShadowLayer(ctx);
+ }
+ }
+ }
+ p->setPen(textFillPen);
+ line.draw(p, pt);
+ p->restore();
+ return;
+ }
+ int skipWidth = QFontMetrics(font).width(string, from, Qt::TextBypassShaping);
+ pt.setX(pt.x() + skipWidth);
+ string = fromRawDataWithoutRef(sanitized, from, to - from);
+ }
+
+ p->setFont(font);
+
+ int flags = run.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
+ if (!isComplexText && !(ctx->textDrawingMode() & TextModeStroke))
+ flags |= Qt::TextBypassShaping;
+
+ QPainterPath textStrokePath;
+ if (ctx->textDrawingMode() & TextModeStroke)
+ textStrokePath.addText(pt, font, string);
+
+ ShadowBlur* ctxShadow = ctx->shadowBlur();
+ if (ctx->hasShadow() && ctxShadow->type() != ShadowBlur::NoShadow) {
+ if (ctx->textDrawingMode() & TextModeFill) {
+ if (ctxShadow->type() != ShadowBlur::BlurShadow) {
+ p->save();
+ p->setPen(ctx->state().shadowColor);
+ p->translate(QPointF(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height()));
+ p->drawText(pt, string, flags, run.expansion());
+ p->restore();
+ } else {
+ QFontMetrics fm(font);
+ QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string, -1, flags), fm.height());
+ GraphicsContext* shadowContext = ctxShadow->beginShadowLayer(ctx, boundingRect);
+ if (shadowContext) {
+ QPainter* shadowPainter = shadowContext->platformContext();
+ // Since it will be blurred anyway, we don't care about render hints.
+ shadowPainter->setFont(p->font());
+ shadowPainter->setPen(ctx->state().shadowColor);
+ shadowPainter->drawText(pt, string, flags, run.expansion());
+ ctxShadow->endShadowLayer(ctx);
+ }
+ }
+ } else if (ctx->textDrawingMode() & TextModeStroke) {
+ if (ctxShadow->type() != ShadowBlur::BlurShadow) {
+ const QPointF shadowOffset(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height());
+ p->translate(shadowOffset);
+ p->strokePath(textStrokePath, QPen(ctx->state().shadowColor));
+ p->translate(-shadowOffset);
+ } else {
+ QFontMetrics fm(font);
+ QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string, -1, flags), fm.height());
+ GraphicsContext* shadowContext = ctxShadow->beginShadowLayer(ctx, boundingRect);
+ if (shadowContext) {
+ QPainter* shadowPainter = shadowContext->platformContext();
+ // Since it will be blurred anyway, we don't care about render hints.
+ shadowPainter->setFont(p->font());
+ shadowPainter->strokePath(textStrokePath, QPen(ctx->state().shadowColor));
+ ctxShadow->endShadowLayer(ctx);
+ }
+ }
+ }
+ }
+
+ if (ctx->textDrawingMode() & TextModeStroke)
+ p->strokePath(textStrokePath, textStrokePen);
+
+ if (ctx->textDrawingMode() & TextModeFill) {
+ QPen previousPen = p->pen();
+ p->setPen(textFillPen);
+ p->drawText(pt, string, flags, run.expansion());
+ p->setPen(previousPen);
+ }
+}
+
+void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
+{
+ drawTextCommon(ctx, run, point, from, to, font(), /* isComplexText = */true);
+}
+
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const
+{
+ if (!primaryFont()->platformData().size())
+ return 0;
+
+ if (!run.length())
+ return 0;
+
+ if (run.length() == 1 && treatAsSpace(run[0]))
+ return QFontMetrics(font()).width(space) + run.expansion();
+
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
+ QString string = fromRawDataWithoutRef(sanitized);
+
+ int w = QFontMetrics(font()).width(string);
+ // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does)
+ if (treatAsSpace(run[0]))
+ w -= m_wordSpacing;
+
+ return w + run.expansion();
+}
+
+int Font::offsetForPositionForComplexText(const TextRun& run, float position, bool) const
+{
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
+ QString string = fromRawDataWithoutRef(sanitized);
+
+ QTextLayout layout(string, font());
+ QTextLine line = setupLayout(&layout, run);
+ return line.xToCursor(position);
+}
+
+FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const
+{
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
+ QString string = fromRawDataWithoutRef(sanitized);
+
+ QTextLayout layout(string, font());
+ QTextLine line = setupLayout(&layout, run);
+
+ float x1 = line.cursorToX(from);
+ float x2 = line.cursorToX(to);
+ if (x2 < x1)
+ qSwap(x1, x2);
+
+ return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h);
+}
+
+bool Font::canReturnFallbackFontsForComplexText()
+{
+ return false;
+}
+
+void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
+{
+ notImplemented();
+}
+
+void Font::drawSimpleText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
+{
+ drawTextCommon(ctx, run, point, from, to, font(), /* isComplexText = */false);
+}
+
+int Font::offsetForPositionForSimpleText(const TextRun& run, float position, bool includePartialGlyphs) const
+{
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
+ QString string = fromRawDataWithoutRef(sanitized);
+
+ QFontMetrics fm(font());
+ float delta = position;
+ int curPos = 0;
+ do {
+ float charWidth = fm.width(string[curPos]);
+ delta -= charWidth;
+ if (includePartialGlyphs) {
+ if (delta + charWidth / 2 <= 0)
+ break;
+ } else {
+ if (delta + charWidth <= 0)
+ break;
+ }
+ } while (++curPos < string.size());
+
+ return curPos;
+}
+
+
+float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
+{
+ if (!primaryFont()->platformData().size())
+ return 0;
+
+ if (!run.length())
+ return 0;
+
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
+ QString string = fromRawDataWithoutRef(sanitized);
+
+ int w = QFontMetrics(font()).width(string, -1, Qt::TextBypassShaping);
+
+ // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does)
+ if (treatAsSpace(run[0]))
+ w -= m_wordSpacing;
+
+ return w + run.expansion();
+}
+
+
+FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const
+{
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
+ QString wholeText = fromRawDataWithoutRef(sanitized);
+ QString selectedText = fromRawDataWithoutRef(sanitized, from, qMin(to - from, wholeText.length() - from));
+
+ int startX = QFontMetrics(font()).width(wholeText, from, Qt::TextBypassShaping);
+ int width = QFontMetrics(font()).width(selectedText, -1, Qt::TextBypassShaping);
+
+ return FloatRect(pt.x() + startX, pt.y(), width, h);
+}
+
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+ return false;
+}
+
+bool Font::primaryFontHasGlyphForCharacter(UChar32) const
+{
+ notImplemented();
+ return true;
+}
+
+int Font::emphasisMarkAscent(const AtomicString&) const
+{
+ notImplemented();
+ return 0;
+}
+
+int Font::emphasisMarkDescent(const AtomicString&) const
+{
+ notImplemented();
+ return 0;
+}
+
+int Font::emphasisMarkHeight(const AtomicString&) const
+{
+ notImplemented();
+ return 0;
+}
+
+void Font::drawEmphasisMarksForSimpleText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
+{
+ notImplemented();
+}
+
+QFont Font::font() const
+{
+ QFont f = primaryFont()->getQtFont();
+ if (m_letterSpacing)
+ f.setLetterSpacing(QFont::AbsoluteSpacing, m_letterSpacing);
+ if (m_wordSpacing)
+ f.setWordSpacing(m_wordSpacing);
+ return f;
+}
+
+QFont Font::syntheticFont() const
+{
+ return font();
+}
+
+}
+
diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
index 7005785c0..e1c2b4942 100644
--- a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
@@ -124,7 +124,8 @@ void GraphicsContext3DPrivate::paintToTextureMapper(TextureMapper* textureMapper
if (textureMapper->accelerationMode() == TextureMapper::OpenGLMode) {
TextureMapperGL* texmapGL = static_cast<TextureMapperGL*>(textureMapper);
TextureMapperGL::Flags flags = TextureMapperGL::ShouldFlipTexture | (m_context->m_attrs.alpha ? TextureMapperGL::SupportsBlending : 0);
- texmapGL->drawTexture(m_context->m_texture, flags, FloatSize(1, 1), targetRect, matrix, opacity, mask);
+ IntSize textureSize(m_context->m_currentWidth, m_context->m_currentHeight);
+ texmapGL->drawTexture(m_context->m_texture, flags, textureSize, targetRect, matrix, opacity, mask);
return;
}
@@ -347,6 +348,9 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWi
GraphicsContext3D::~GraphicsContext3D()
{
+ // If GraphicsContext3D init failed in constructor, m_private set to nullptr and no buffers are allocated.
+ if (!m_private)
+ return;
makeContextCurrent();
glDeleteTextures(1, &m_texture);
glDeleteFramebuffers(1, &m_fbo);
@@ -386,6 +390,8 @@ PlatformLayer* GraphicsContext3D::platformLayer() const
bool GraphicsContext3D::makeContextCurrent()
{
+ if (!m_private)
+ return false;
return m_private->makeCurrentIfNeeded();
}
@@ -1359,6 +1365,39 @@ String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader)
return result;
}
+void GraphicsContext3D::getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, GC3Dint* range, GC3Dint* precision)
+{
+ // FIXME: this should be retargeted at the real getShaderPrecisionFormat()
+ // call on true ES 2.0 hardware.
+ UNUSED_PARAM(shaderType);
+ ASSERT(range);
+ ASSERT(precision);
+
+ makeContextCurrent();
+
+ switch (precisionType) {
+ case GraphicsContext3D::LOW_INT:
+ case GraphicsContext3D::MEDIUM_INT:
+ case GraphicsContext3D::HIGH_INT:
+ // These values are for a 32-bit twos-complement integer format.
+ range[0] = 31;
+ range[1] = 30;
+ precision[0] = 0;
+ break;
+ case GraphicsContext3D::LOW_FLOAT:
+ case GraphicsContext3D::MEDIUM_FLOAT:
+ case GraphicsContext3D::HIGH_FLOAT:
+ // These values are for an IEEE single-precision floating-point format.
+ range[0] = 127;
+ range[1] = 127;
+ precision[0] = 23;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+}
+
String GraphicsContext3D::getShaderSource(Platform3DObject shader)
{
makeContextCurrent();
diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index aa49e2ddf..b8e95f25f 100644
--- a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -975,7 +975,7 @@ static void drawErrorUnderline(QPainter *painter, qreal x, qreal y, qreal width,
}
-void GraphicsContext::drawLineForTextChecking(const FloatPoint& origin, float width, TextCheckingLineStyle style)
+void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& origin, float width, DocumentMarkerLineStyle style)
{
if (paintingDisabled())
return;
@@ -984,10 +984,10 @@ void GraphicsContext::drawLineForTextChecking(const FloatPoint& origin, float wi
const QPen originalPen = painter->pen();
switch (style) {
- case TextCheckingSpellingLineStyle:
+ case DocumentMarkerSpellingLineStyle:
painter->setPen(Qt::red);
break;
- case TextCheckingGrammarLineStyle:
+ case DocumentMarkerGrammarLineStyle:
painter->setPen(Qt::green);
break;
default:
diff --git a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
index 0f40342e2..effaaf096 100644
--- a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
@@ -22,11 +22,9 @@
#if !defined(QT_NO_GRAPHICSVIEW)
-#include "CurrentTime.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
#include "Image.h"
-#include "RefCounted.h"
#include "TranslateTransformOperation.h"
#include "UnitBezier.h"
#include <qgraphicseffect.h>
@@ -45,6 +43,8 @@
#include <QtGui/qpainter.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qpixmapcache.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/RefCounted.h>
#if USE(TILED_BACKING_STORE)
#include "TiledBackingStore.h"
@@ -950,6 +950,14 @@ GraphicsLayerQt::GraphicsLayerQt(GraphicsLayerClient* client)
GraphicsLayerQt::~GraphicsLayerQt()
{
+ // Do cleanup while we can still safely call methods on the derived class.
+ willBeDestroyed();
+}
+
+void GraphicsLayerQt::willBeDestroyed()
+{
+ m_impl = nullptr;
+ GraphicsLayer::willBeDestroyed();
}
// This is the hook for WebCore compositor to know that Qt implements compositing with GraphicsLayerQt.
diff --git a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h
index 58535b324..ea2bdae68 100644
--- a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h
+++ b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h
@@ -84,6 +84,8 @@ public:
virtual void syncCompositingStateForThisLayerOnly();
private:
+ virtual void willBeDestroyed();
+
OwnPtr<GraphicsLayerQtImpl> m_impl;
};
diff --git a/Source/WebCore/platform/graphics/qt/ImageBufferDataQt.h b/Source/WebCore/platform/graphics/qt/ImageBufferDataQt.h
index 8b4982978..9cf782bea 100644
--- a/Source/WebCore/platform/graphics/qt/ImageBufferDataQt.h
+++ b/Source/WebCore/platform/graphics/qt/ImageBufferDataQt.h
@@ -25,9 +25,10 @@
#include "Image.h"
-#include "OwnPtr.h"
#include <QPainter>
#include <QPixmap>
+
+#include <wtf/OwnPtr.h>
#include <wtf/RefPtr.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp
index 44f860af2..b9b9ebf6c 100644
--- a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp
@@ -94,9 +94,10 @@ QImage ImageBufferData::toQImage() const
return image;
}
-ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode, DeferralMode, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, float /* resolutionScale */, ColorSpace, RenderingMode, DeferralMode, bool& success)
: m_data(size)
, m_size(size)
+ , m_logicalSize(size)
{
success = m_data.m_painter && m_data.m_painter->isActive();
if (!success)
@@ -130,9 +131,9 @@ void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace,
if (destContext == context()) {
// We're drawing into our own buffer. In order for this to work, we need to copy the source buffer first.
RefPtr<Image> copy = copyImage(CopyBackingStore);
- destContext->drawImage(copy.get(), ColorSpaceDeviceRGB, destRect, srcRect, op, useLowQualityScale);
+ destContext->drawImage(copy.get(), ColorSpaceDeviceRGB, destRect, srcRect, op, DoNotRespectImageOrientation, useLowQualityScale);
} else
- destContext->drawImage(m_data.m_image.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
+ destContext->drawImage(m_data.m_image.get(), styleColorSpace, destRect, srcRect, op, DoNotRespectImageOrientation, useLowQualityScale);
}
void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const AffineTransform& patternTransform,
@@ -188,17 +189,17 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
}
template <Multiply multiplied>
-PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& imageData, const IntSize& size)
+PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBufferData& imageData, const IntSize& size)
{
float area = 4.0f * rect.width() * rect.height();
if (area > static_cast<float>(std::numeric_limits<int>::max()))
return 0;
- RefPtr<ByteArray> result = ByteArray::create(rect.width() * rect.height() * 4);
+ RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4);
unsigned char* data = result->data();
if (rect.x() < 0 || rect.y() < 0 || rect.maxX() > size.width() || rect.maxY() > size.height())
- memset(data, 0, result->length());
+ result->zeroFill();
int originx = rect.x();
int destx = 0;
@@ -270,12 +271,12 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& i
return result.release();
}
-PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect, CoordinateSystem) const
{
return getImageData<Unmultiplied>(rect, m_data, m_size);
}
-PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem) const
{
return getImageData<Premultiplied>(rect, m_data, m_size);
}
@@ -296,7 +297,7 @@ static inline unsigned int premultiplyABGRtoARGB(unsigned int x)
return x;
}
-void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
+void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem)
{
ASSERT(sourceRect.width() > 0);
ASSERT(sourceRect.height() > 0);
@@ -376,34 +377,31 @@ void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const Int
m_data.m_painter->restore();
}
-// We get a mimeType here but QImageWriter does not support mimetypes but
-// only formats (png, gif, jpeg..., xpm). So assume we get image/ as image
-// mimetypes and then remove the image/ to get the Qt format.
-String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
+static bool encodeImage(const QPixmap& pixmap, const String& format, const double* quality, QByteArray& data)
{
- ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
-
- if (!mimeType.startsWith("image/"))
- return "data:,";
+ int compressionQuality = 100;
+ if (quality && *quality >= 0.0 && *quality <= 1.0)
+ compressionQuality = static_cast<int>(*quality * 100 + 0.5);
- // prepare our target
- QByteArray data;
QBuffer buffer(&data);
buffer.open(QBuffer::WriteOnly);
+ bool success = pixmap.save(&buffer, format.utf8().data(), compressionQuality);
+ buffer.close();
- if (quality && *quality >= 0.0 && *quality <= 1.0) {
- if (!m_data.m_pixmap.save(&buffer, mimeType.substring(sizeof "image").utf8().data(), *quality * 100 + 0.5)) {
- buffer.close();
- return "data:,";
- }
- } else {
- if (!m_data.m_pixmap.save(&buffer, mimeType.substring(sizeof "image").utf8().data(), 100)) {
- buffer.close();
- return "data:,";
- }
- }
+ return success;
+}
- buffer.close();
+String ImageBuffer::toDataURL(const String& mimeType, const double* quality, CoordinateSystem) const
+{
+ ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
+
+ // QImageWriter does not support mimetypes. It does support Qt image formats (png,
+ // gif, jpeg..., xpm) so skip the image/ to get the Qt image format used to encode
+ // the m_pixmap image.
+
+ QByteArray data;
+ if (!encodeImage(m_data.m_pixmap, mimeType.substring(sizeof "image"), quality, data))
+ return "data:,";
return "data:" + mimeType + ";base64," + data.toBase64().data();
}
diff --git a/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp b/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
index 827e1346e..1bcd6c05b 100644
--- a/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
@@ -61,7 +61,7 @@ bool SimpleFontData::containsCharacters(const UChar* characters, int length) con
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
- if (!platformData().size())
+ if (!glyph || !platformData().size())
return 0;
QVector<quint32> glyphIndexes;
@@ -134,7 +134,7 @@ void SimpleFontData::platformInit()
float descent = rawFont.descent();
float ascent = rawFont.ascent();
float xHeight = rawFont.xHeight();
- float lineSpacing = ascent + descent + rawFont.leading() + 1;
+ float lineSpacing = ascent + descent + rawFont.leading();
QVector<quint32> indexes = rawFont.glyphIndexesForString(QLatin1String(" "));
QVector<QPointF> advances = rawFont.advancesForGlyphIndexes(indexes);
@@ -165,7 +165,8 @@ void SimpleFontData::platformInit()
float lineGap = lineSpacing - ascent - descent;
m_fontMetrics.setAscent(ascent);
- m_fontMetrics.setDescent(descent);
+ // WebKit expects the descent to be positive.
+ m_fontMetrics.setDescent(qAbs(descent));
m_fontMetrics.setLineSpacing(lineSpacing);
m_fontMetrics.setXHeight(xHeight);
m_fontMetrics.setLineGap(lineGap);
diff --git a/Source/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.cpp b/Source/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.cpp
new file mode 100644
index 000000000..28ead8fba
--- /dev/null
+++ b/Source/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.cpp
@@ -0,0 +1,47 @@
+#include "config.h"
+
+#include "BitmapImageSingleFrameSkia.h"
+
+namespace WebCore {
+
+bool BitmapImageSingleFrameSkia::isBitmapImage() const
+{
+ return true;
+}
+
+bool BitmapImageSingleFrameSkia::currentFrameHasAlpha()
+{
+ return !m_nativeImage.bitmap().isOpaque();
+}
+
+IntSize BitmapImageSingleFrameSkia::size() const
+{
+ return IntSize(m_nativeImage.bitmap().width(), m_nativeImage.bitmap().height());
+}
+
+// Do nothing, as we only have the one representation of data (decoded).
+void BitmapImageSingleFrameSkia::destroyDecodedData(bool destroyAll)
+{
+
+}
+
+unsigned BitmapImageSingleFrameSkia::decodedSize() const
+{
+ return m_nativeImage.decodedSize();
+}
+
+// We only have a single frame.
+NativeImagePtr BitmapImageSingleFrameSkia::nativeImageForCurrentFrame()
+{
+ return &m_nativeImage;
+}
+
+#if !ASSERT_DISABLED
+bool BitmapImageSingleFrameSkia::notSolidColor()
+{
+ return m_nativeImage.bitmap().width() != 1 || m_nativeImage.bitmap().height() != 1;
+}
+#endif
+
+} // namespace WebCore
+
diff --git a/Source/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h b/Source/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h
index 9c89c6927..f5203ec8a 100644
--- a/Source/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h
+++ b/Source/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h
@@ -51,34 +51,22 @@ public:
// ref'ed).
static PassRefPtr<BitmapImageSingleFrameSkia> create(const SkBitmap&, bool copyPixels);
- virtual bool isBitmapImage() const { return true; }
+ virtual bool isBitmapImage() const;
- virtual bool currentFrameHasAlpha() { return !m_nativeImage.bitmap().isOpaque(); }
+ virtual bool currentFrameHasAlpha();
- virtual IntSize size() const
- {
- return IntSize(m_nativeImage.bitmap().width(), m_nativeImage.bitmap().height());
- }
+ virtual IntSize size() const;
// Do nothing, as we only have the one representation of data (decoded).
- virtual void destroyDecodedData(bool destroyAll = true) { }
+ virtual void destroyDecodedData(bool destroyAll = true);
- virtual unsigned decodedSize() const
- {
- return m_nativeImage.decodedSize();
- }
+ virtual unsigned decodedSize() const;
// We only have a single frame.
- virtual NativeImagePtr nativeImageForCurrentFrame()
- {
- return &m_nativeImage;
- }
+ virtual NativeImagePtr nativeImageForCurrentFrame();
#if !ASSERT_DISABLED
- virtual bool notSolidColor()
- {
- return m_nativeImage.bitmap().width() != 1 || m_nativeImage.bitmap().height() != 1;
- }
+ virtual bool notSolidColor();
#endif
protected:
diff --git a/Source/WebCore/platform/graphics/skia/FontSkia.cpp b/Source/WebCore/platform/graphics/skia/FontSkia.cpp
index 4980526b7..abd556c83 100644
--- a/Source/WebCore/platform/graphics/skia/FontSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/FontSkia.cpp
@@ -54,23 +54,6 @@ bool Font::canExpandAroundIdeographsInComplexText()
return true;
}
-static bool isCanvasMultiLayered(SkCanvas* canvas)
-{
- SkCanvas::LayerIter layerIterator(canvas, false);
- layerIterator.next();
- return !layerIterator.done();
-}
-
-static void adjustTextRenderMode(SkPaint* paint, PlatformContextSkia* skiaContext)
-{
- // Our layers only have a single alpha channel. This means that subpixel
- // rendered text cannot be compositied correctly when the layer is
- // collapsed. Therefore, subpixel text is disabled when we are drawing
- // onto a layer or when the compositor is being used.
- if (isCanvasMultiLayered(skiaContext->canvas()) || skiaContext->isDrawingToImageBuffer())
- paint->setLCDRenderText(false);
-}
-
static void setupPaint(SkPaint* paint, const SimpleFontData* fontData, const Font* font, bool shouldAntialias, bool shouldSmoothFonts)
{
const FontPlatformData& platformData = fontData->platformData();
@@ -157,7 +140,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
SkPaint paint;
gc->platformContext()->setupPaintForFilling(&paint);
setupPaint(&paint, font, this, shouldAntialias, shouldSmoothFonts);
- adjustTextRenderMode(&paint, gc->platformContext());
+ gc->platformContext()->adjustTextRenderMode(&paint);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
canvas->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, paint);
@@ -170,7 +153,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
SkPaint paint;
gc->platformContext()->setupPaintForStroking(&paint, 0, 0);
setupPaint(&paint, font, this, shouldAntialias, shouldSmoothFonts);
- adjustTextRenderMode(&paint, gc->platformContext());
+ gc->platformContext()->adjustTextRenderMode(&paint);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
if (textMode & TextModeFill) {
diff --git a/Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp b/Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp
index 9a4fef6d0..66882cf4a 100644
--- a/Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp
@@ -96,15 +96,12 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b
}
if (fontData->hasVerticalGlyphs()) {
- bool lookVariants = false;
for (unsigned i = 0; i < bufferLength; ++i) {
if (!Font::isCJKIdeograph(buffer[i])) {
- lookVariants = true;
- continue;
+ substituteWithVerticalGlyphs(fontData, glyphs, length);
+ break;
}
}
- if (lookVariants)
- substituteWithVerticalGlyphs(fontData, glyphs, bufferLength);
}
unsigned allGlyphs = 0; // track if any of the glyphIDs are non-zero
diff --git a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
index 4f79cfb0b..ce44f0c60 100644
--- a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
@@ -82,111 +82,6 @@ inline float square(float n)
} // namespace
-// "Seatbelt" functions ------------------------------------------------------
-//
-// These functions check certain graphics primitives for being "safe".
-// Skia has historically crashed when sent crazy data. These functions do
-// additional checking to prevent crashes.
-//
-// Ideally, all of these would be fixed in the graphics layer and we would not
-// have to do any checking. You can uncomment the ENSURE_VALUE_SAFETY_FOR_SKIA
-// flag to check the graphics layer.
-
-// Disabling these checks (20/01/2010), since we think we've fixed all the Skia
-// bugs. Leaving the code in for now, so we can revert easily if necessary.
-// #define ENSURE_VALUE_SAFETY_FOR_SKIA
-
-#ifdef ENSURE_VALUE_SAFETY_FOR_SKIA
-static bool isCoordinateSkiaSafe(float coord)
-{
- // First check for valid floats.
-#if defined(_MSC_VER)
- if (!_finite(coord))
-#else
- if (!finite(coord))
-#endif
- return false;
-
- // Skia uses 16.16 fixed point and 26.6 fixed point in various places. If
- // the transformed point exceeds 15 bits, we just declare that it's
- // unreasonable to catch both of these cases.
- static const int maxPointMagnitude = 32767;
- if (coord > maxPointMagnitude || coord < -maxPointMagnitude)
- return false;
-
- return true;
-}
-#endif
-
-static bool isPointSkiaSafe(const SkMatrix& transform, const SkPoint& pt)
-{
-#ifdef ENSURE_VALUE_SAFETY_FOR_SKIA
- // Now check for points that will overflow. We check the *transformed*
- // points since this is what will be rasterized.
- SkPoint xPt;
- transform.mapPoints(&xPt, &pt, 1);
- return isCoordinateSkiaSafe(xPt.fX) && isCoordinateSkiaSafe(xPt.fY);
-#else
- return true;
-#endif
-}
-
-static bool isRectSkiaSafe(const SkMatrix& transform, const SkRect& rc)
-{
-#ifdef ENSURE_VALUE_SAFETY_FOR_SKIA
- SkPoint topleft = {rc.fLeft, rc.fTop};
- SkPoint bottomright = {rc.fRight, rc.fBottom};
- return isPointSkiaSafe(transform, topleft) && isPointSkiaSafe(transform, bottomright);
-#else
- return true;
-#endif
-}
-
-bool isPathSkiaSafe(const SkMatrix& transform, const SkPath& path)
-{
-#ifdef ENSURE_VALUE_SAFETY_FOR_SKIA
- SkPoint current_points[4];
- SkPath::Iter iter(path, false);
- for (SkPath::Verb verb = iter.next(current_points);
- verb != SkPath::kDone_Verb;
- verb = iter.next(current_points)) {
- switch (verb) {
- case SkPath::kMove_Verb:
- // This move will be duplicated in the next verb, so we can ignore.
- break;
- case SkPath::kLine_Verb:
- // iter.next returns 2 points.
- if (!isPointSkiaSafe(transform, current_points[0])
- || !isPointSkiaSafe(transform, current_points[1]))
- return false;
- break;
- case SkPath::kQuad_Verb:
- // iter.next returns 3 points.
- if (!isPointSkiaSafe(transform, current_points[0])
- || !isPointSkiaSafe(transform, current_points[1])
- || !isPointSkiaSafe(transform, current_points[2]))
- return false;
- break;
- case SkPath::kCubic_Verb:
- // iter.next returns 4 points.
- if (!isPointSkiaSafe(transform, current_points[0])
- || !isPointSkiaSafe(transform, current_points[1])
- || !isPointSkiaSafe(transform, current_points[2])
- || !isPointSkiaSafe(transform, current_points[3]))
- return false;
- break;
- case SkPath::kClose_Verb:
- case SkPath::kDone_Verb:
- default:
- break;
- }
- }
- return true;
-#else
- return true;
-#endif
-}
-
// Local helper functions ------------------------------------------------------
void addCornerArc(SkPath* path, const SkRect& rect, const IntSize& size, int startAngle)
@@ -271,23 +166,20 @@ void GraphicsContext::beginPlatformTransparencyLayer(float opacity)
// (the surface of the page) but layers on top may have transparent parts.
// Without explicitly setting the alpha flag, the layer will inherit the
// opaque setting of the base and some things won't work properly.
+ SkCanvas::SaveFlags saveFlags = static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag);
SkPaint layerPaint;
layerPaint.setAlpha(static_cast<unsigned char>(opacity * 255));
layerPaint.setXfermodeMode(platformContext()->getXfermodeMode());
- platformContext()->canvas()->saveLayer(
- 0,
- &layerPaint,
- static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag |
- SkCanvas::kFullColorLayer_SaveFlag));
+ platformContext()->saveLayer(0, &layerPaint, saveFlags);
}
void GraphicsContext::endPlatformTransparencyLayer()
{
if (paintingDisabled())
return;
- platformContext()->canvas()->restore();
+ platformContext()->restoreLayer();
}
bool GraphicsContext::supportsTransparencyLayers()
@@ -303,9 +195,6 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
return;
SkRect r(rect);
- if (!isRectSkiaSafe(getCTM(), r))
- return;
-
SkPath path;
path.addOval(r, SkPath::kCW_Direction);
// only perform the inset if we won't invert r
@@ -332,9 +221,6 @@ void GraphicsContext::clearRect(const FloatRect& rect)
return;
SkRect r = rect;
- if (!isRectSkiaSafe(getCTM(), r))
- ClipRectToCanvas(*platformContext()->canvas(), r, &r);
-
SkPaint paint;
platformContext()->setupPaintForFilling(&paint);
paint.setXfermodeMode(SkXfermode::kClear_Mode);
@@ -347,11 +233,7 @@ void GraphicsContext::clip(const FloatRect& rect)
if (paintingDisabled())
return;
- SkRect r(rect);
- if (!isRectSkiaSafe(getCTM(), r))
- return;
-
- platformContext()->canvas()->clipRect(r);
+ platformContext()->canvas()->clipRect(rect);
}
void GraphicsContext::clip(const Path& path)
@@ -359,11 +241,7 @@ void GraphicsContext::clip(const Path& path)
if (paintingDisabled())
return;
- const SkPath& p = *path.platformPath();
- if (!isPathSkiaSafe(getCTM(), p))
- return;
-
- platformContext()->clipPathAntiAliased(p);
+ platformContext()->clipPathAntiAliased(*path.platformPath());
}
void GraphicsContext::canvasClip(const Path& path)
@@ -371,11 +249,7 @@ void GraphicsContext::canvasClip(const Path& path)
if (paintingDisabled())
return;
- const SkPath& p = *path.platformPath();
- if (!isPathSkiaSafe(getCTM(), p))
- return;
-
- platformContext()->canvasClipPath(p);
+ platformContext()->canvasClipPath(*path.platformPath());
}
void GraphicsContext::clipOut(const IntRect& rect)
@@ -383,11 +257,7 @@ void GraphicsContext::clipOut(const IntRect& rect)
if (paintingDisabled())
return;
- SkRect r(rect);
- if (!isRectSkiaSafe(getCTM(), r))
- return;
-
- platformContext()->canvas()->clipRect(r, SkRegion::kDifference_Op);
+ platformContext()->canvas()->clipRect(rect, SkRegion::kDifference_Op);
}
void GraphicsContext::clipOut(const Path& p)
@@ -395,10 +265,8 @@ void GraphicsContext::clipOut(const Path& p)
if (paintingDisabled())
return;
- SkPath path = *p.platformPath();
- if (!isPathSkiaSafe(getCTM(), path))
- return;
-
+ // We must make a copy of the path, to mark it as inverse-filled.
+ SkPath path(*p.platformPath());
path.toggleInverseFillType();
platformContext()->clipPathAntiAliased(path);
}
@@ -408,12 +276,15 @@ void GraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule)
if (paintingDisabled())
return;
- SkPath path = *pathToClip.platformPath();
- if (!isPathSkiaSafe(getCTM(), path))
- return;
-
- path.setFillType(clipRule == RULE_EVENODD ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
- platformContext()->clipPathAntiAliased(path);
+ const SkPath* path = pathToClip.platformPath();
+ SkPath::FillType ftype = (clipRule == RULE_EVENODD) ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType;
+ SkPath storage;
+ if (path->getFillType() != ftype) {
+ storage = *path;
+ storage.setFillType(ftype);
+ path = &storage;
+ }
+ platformContext()->clipPathAntiAliased(*path);
}
void GraphicsContext::concatCTM(const AffineTransform& affine)
@@ -467,9 +338,6 @@ void GraphicsContext::drawConvexPolygon(size_t numPoints,
SkPath path;
setPathFromConvexPoints(&path, numPoints, points);
- if (!isPathSkiaSafe(getCTM(), path))
- return;
-
SkPaint paint;
platformContext()->setupPaintForFilling(&paint);
paint.setAntiAlias(shouldAntialias);
@@ -493,9 +361,6 @@ void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* poin
return;
SkPath path;
- if (!isPathSkiaSafe(getCTM(), path))
- return;
-
setPathFromConvexPoints(&path, numPoints, points);
if (antialiased)
platformContext()->clipPathAntiAliased(path);
@@ -510,9 +375,6 @@ void GraphicsContext::drawEllipse(const IntRect& elipseRect)
return;
SkRect rect = elipseRect;
- if (!isRectSkiaSafe(getCTM(), rect))
- return;
-
SkPaint paint;
platformContext()->setupPaintForFilling(&paint);
platformContext()->canvas()->drawOval(rect, paint);
@@ -603,9 +465,6 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
return;
SkPaint paint;
- if (!isPointSkiaSafe(getCTM(), point1) || !isPointSkiaSafe(getCTM(), point2))
- return;
-
FloatPoint p1 = point1;
FloatPoint p2 = point2;
bool isVerticalLine = (p1.x() == p2.x());
@@ -648,7 +507,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
platformContext()->didDrawPoints(SkCanvas::kLines_PointMode, 2, pts, paint);
}
-void GraphicsContext::drawLineForTextChecking(const FloatPoint& pt, float width, TextCheckingLineStyle style)
+void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float width, DocumentMarkerLineStyle style)
{
if (paintingDisabled())
return;
@@ -788,13 +647,7 @@ void GraphicsContext::drawRect(const IntRect& rect)
if (paintingDisabled())
return;
- SkRect r = rect;
- if (!isRectSkiaSafe(getCTM(), r)) {
- // See the fillRect below.
- ClipRectToCanvas(*platformContext()->canvas(), r, &r);
- }
-
- platformContext()->drawRect(r);
+ platformContext()->drawRect(rect);
}
void GraphicsContext::fillPath(const Path& pathToFill)
@@ -802,19 +655,23 @@ void GraphicsContext::fillPath(const Path& pathToFill)
if (paintingDisabled())
return;
- SkPath path = *pathToFill.platformPath();
- if (!isPathSkiaSafe(getCTM(), path))
- return;
-
const GraphicsContextState& state = m_state;
- path.setFillType(state.fillRule == RULE_EVENODD ?
- SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
+ SkPath::FillType ftype = state.fillRule == RULE_EVENODD ?
+ SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType;
+
+ const SkPath* path = pathToFill.platformPath();
+ SkPath storage;
+ if (path->getFillType() != ftype) {
+ storage = *path;
+ storage.setFillType(ftype);
+ path = &storage;
+ }
SkPaint paint;
platformContext()->setupPaintForFilling(&paint);
- platformContext()->canvas()->drawPath(path, paint);
- platformContext()->didDrawPath(path, paint);
+ platformContext()->canvas()->drawPath(*path, paint);
+ platformContext()->didDrawPath(*path, paint);
}
void GraphicsContext::fillRect(const FloatRect& rect)
@@ -823,19 +680,11 @@ void GraphicsContext::fillRect(const FloatRect& rect)
return;
SkRect r = rect;
- if (!isRectSkiaSafe(getCTM(), r)) {
- // See the other version of fillRect below.
- ClipRectToCanvas(*platformContext()->canvas(), r, &r);
- }
-
- platformContext()->save();
SkPaint paint;
platformContext()->setupPaintForFilling(&paint);
platformContext()->canvas()->drawRect(r, paint);
platformContext()->didDrawRect(r, paint);
-
- platformContext()->restore();
}
void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
@@ -844,20 +693,6 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS
return;
SkRect r = rect;
- if (!isRectSkiaSafe(getCTM(), r)) {
- // Special case when the rectangle overflows fixed point. This is a
- // workaround to fix bug 1212844. When the input rectangle is very
- // large, it can overflow Skia's internal fixed point rect. This
- // should be fixable in Skia (since the output bitmap isn't that
- // large), but until that is fixed, we try to handle it ourselves.
- //
- // We manually clip the rectangle to the current clip rect. This
- // will prevent overflow. The rectangle will be transformed to the
- // canvas' coordinate space before it is converted to fixed point
- // so we are guaranteed not to overflow after doing this.
- ClipRectToCanvas(*platformContext()->canvas(), r, &r);
- }
-
SkPaint paint;
platformContext()->setupPaintCommon(&paint);
paint.setColor(color.rgb());
@@ -876,11 +711,6 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect,
if (paintingDisabled())
return;
- SkRect r = rect;
- if (!isRectSkiaSafe(getCTM(), r))
- // See fillRect().
- ClipRectToCanvas(*platformContext()->canvas(), r, &r);
-
if (topLeft.width() + topRight.width() > rect.width()
|| bottomLeft.width() + bottomRight.width() > rect.width()
|| topLeft.height() + bottomLeft.height() > rect.height()
@@ -892,6 +722,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect,
return;
}
+ SkRect r = rect;
SkPath path;
addCornerArc(&path, r, topRight, 270);
addCornerArc(&path, r, bottomRight, 0);
@@ -1184,8 +1015,6 @@ void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan)
SkPath path;
path.addArc(oval, SkIntToScalar(-startAngle), SkIntToScalar(-angleSpan));
- if (!isPathSkiaSafe(getCTM(), path))
- return;
platformContext()->canvas()->drawPath(path, paint);
platformContext()->didDrawPath(path, paint);
}
@@ -1195,10 +1024,7 @@ void GraphicsContext::strokePath(const Path& pathToStroke)
if (paintingDisabled())
return;
- SkPath path = *pathToStroke.platformPath();
- if (!isPathSkiaSafe(getCTM(), path))
- return;
-
+ const SkPath& path = *pathToStroke.platformPath();
SkPaint paint;
platformContext()->setupPaintForStroking(&paint, 0, 0);
platformContext()->canvas()->drawPath(path, paint);
@@ -1210,9 +1036,6 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
if (paintingDisabled())
return;
- if (!isRectSkiaSafe(getCTM(), rect))
- return;
-
SkPaint paint;
platformContext()->setupPaintForStroking(&paint, 0, 0);
paint.setStrokeWidth(WebCoreFloatToSkScalar(lineWidth));
@@ -1269,4 +1092,29 @@ CGColorSpaceRef deviceRGBColorSpaceRef()
}
#endif
+void GraphicsContext::platformFillEllipse(const FloatRect& ellipse)
+{
+ if (paintingDisabled())
+ return;
+
+ SkRect rect = ellipse;
+ SkPaint paint;
+ platformContext()->setupPaintForFilling(&paint);
+ platformContext()->canvas()->drawOval(rect, paint);
+ platformContext()->didDrawBounded(rect, paint);
+}
+
+void GraphicsContext::platformStrokeEllipse(const FloatRect& ellipse)
+{
+ if (paintingDisabled())
+ return;
+
+ SkRect rect(ellipse);
+ SkPaint paint;
+ platformContext()->setupPaintForStroking(&paint, 0, 0);
+ platformContext()->canvas()->drawOval(rect, paint);
+ platformContext()->didDrawBounded(rect, paint);
+}
+
} // namespace WebCore
+
diff --git a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
index 0d379a42a..8b086a079 100644
--- a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
@@ -36,7 +36,6 @@
#include "Base64.h"
#include "BitmapImage.h"
#include "BitmapImageSingleFrameSkia.h"
-#include "Canvas2DLayerChromium.h"
#include "GrContext.h"
#include "GraphicsContext.h"
#include "ImageData.h"
@@ -51,6 +50,10 @@
#include "SkiaUtils.h"
#include "WEBPImageEncoder.h"
+#if USE(ACCELERATED_COMPOSITING)
+#include "Canvas2DLayerChromium.h"
+#endif
+
#include <wtf/text/WTFString.h>
using namespace std;
@@ -66,26 +69,33 @@ ImageBufferData::ImageBufferData(const IntSize& size)
{
}
+#if USE(ACCELERATED_COMPOSITING)
class AcceleratedDeviceContext : public SkDeferredCanvas::DeviceContext {
public:
- AcceleratedDeviceContext(GraphicsContext3D* context3D)
+ AcceleratedDeviceContext(GraphicsContext3D* context3D, Canvas2DLayerChromium* layer)
+ : m_platformLayer(layer)
+ , m_context3D()
{
ASSERT(context3D);
+ ASSERT(layer);
m_context3D = context3D;
}
virtual void prepareForDraw()
{
+ m_platformLayer->layerWillDraw(Canvas2DLayerChromium::WillDrawUnconditionally);
m_context3D->makeContextCurrent();
}
private:
+ Canvas2DLayerChromium* m_platformLayer;
GraphicsContext3D* m_context3D;
};
+#endif
static SkCanvas* createAcceleratedCanvas(const IntSize& size, ImageBufferData* data, DeferralMode deferralMode)
{
- GraphicsContext3D* context3D = SharedGraphicsContext3D::get();
+ RefPtr<GraphicsContext3D> context3D = SharedGraphicsContext3D::get();
if (!context3D)
return 0;
GrContext* gr = context3D->grContext();
@@ -94,23 +104,27 @@ static SkCanvas* createAcceleratedCanvas(const IntSize& size, ImageBufferData* d
gr->resetContext();
GrTextureDesc desc;
desc.fFlags = kRenderTarget_GrTextureFlagBit;
- desc.fAALevel = kNone_GrAALevel;
+ desc.fSampleCnt = 0;
desc.fWidth = size.width();
desc.fHeight = size.height();
- desc.fConfig = kRGBA_8888_GrPixelConfig;
+ desc.fConfig = kSkia8888_PM_GrPixelConfig;
SkAutoTUnref<GrTexture> texture(gr->createUncachedTexture(desc, 0, 0));
if (!texture.get())
return 0;
SkCanvas* canvas;
SkAutoTUnref<SkDevice> device(new SkGpuDevice(gr, texture.get()));
+#if USE(ACCELERATED_COMPOSITING)
+ data->m_platformLayer = Canvas2DLayerChromium::create(context3D, size, deferralMode);
if (deferralMode == Deferred) {
- SkAutoTUnref<AcceleratedDeviceContext> deviceContext(new AcceleratedDeviceContext(context3D));
+ SkAutoTUnref<AcceleratedDeviceContext> deviceContext(new AcceleratedDeviceContext(context3D.get(), data->m_platformLayer.get()));
canvas = new SkDeferredCanvas(device.get(), deviceContext.get());
} else
canvas = new SkCanvas(device.get());
- data->m_platformContext.setGraphicsContext3D(context3D);
+#else
+ canvas = new SkCanvas(device.get());
+#endif
+ data->m_platformContext.setAccelerated(true);
#if USE(ACCELERATED_COMPOSITING)
- data->m_platformLayer = Canvas2DLayerChromium::create(context3D, size);
data->m_platformLayer->setTextureId(texture.get()->getTextureHandle());
data->m_platformLayer->setCanvas(canvas);
#endif
@@ -124,9 +138,11 @@ static SkCanvas* createNonPlatformCanvas(const IntSize& size)
return canvas;
}
-ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode renderingMode, DeferralMode deferralMode, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, float /* resolutionScale */, ColorSpace, RenderingMode renderingMode, DeferralMode deferralMode, bool& success)
: m_data(size)
, m_size(size)
+ , m_logicalSize(size)
+ , m_resolutionScale(1)
{
OwnPtr<SkCanvas> canvas;
@@ -166,6 +182,10 @@ ImageBuffer::~ImageBuffer()
GraphicsContext* ImageBuffer::context() const
{
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_data.m_platformLayer)
+ m_data.m_platformLayer->layerWillDraw(Canvas2DLayerChromium::WillDrawIfLayerNotDeferred);
+#endif
return m_context.get();
}
@@ -193,7 +213,7 @@ void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, con
CompositeOperator op, bool useLowQualityScale)
{
RefPtr<Image> image = BitmapImageSingleFrameSkia::create(*m_data.m_platformContext.bitmap(), drawNeedsCopy(m_context.get(), context));
- context->drawImage(image.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
+ context->drawImage(image.get(), styleColorSpace, destRect, srcRect, op, DoNotRespectImageOrientation, useLowQualityScale);
}
void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform,
@@ -228,14 +248,14 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
}
template <Multiply multiplied>
-PassRefPtr<ByteArray> getImageData(const IntRect& rect, SkCanvas* canvas,
+PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, SkCanvas* canvas,
const IntSize& size)
{
float area = 4.0f * rect.width() * rect.height();
if (area > static_cast<float>(std::numeric_limits<int>::max()))
return 0;
- RefPtr<ByteArray> result = ByteArray::create(rect.width() * rect.height() * 4);
+ RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4);
unsigned char* data = result->data();
@@ -243,7 +263,7 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, SkCanvas* canvas,
|| rect.y() < 0
|| rect.maxX() > size.width()
|| rect.maxY() > size.height())
- memset(data, 0, result->length());
+ result->zeroFill();
unsigned destBytesPerRow = 4 * rect.width();
SkBitmap destBitmap;
@@ -260,17 +280,17 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, SkCanvas* canvas,
return result.release();
}
-PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect, CoordinateSystem) const
{
return getImageData<Unmultiplied>(rect, context()->platformContext()->canvas(), m_size);
}
-PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem) const
{
return getImageData<Premultiplied>(rect, context()->platformContext()->canvas(), m_size);
}
-void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
+void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem)
{
SkCanvas* canvas = context()->platformContext()->canvas();
ASSERT(sourceRect.width() > 0);
@@ -341,16 +361,18 @@ static bool encodeImage(T& source, const String& mimeType, const double* quality
return true;
}
-String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
+String ImageBuffer::toDataURL(const String& mimeType, const double* quality, CoordinateSystem) const
{
ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
- Vector<char> encodedImage, base64Data;
+ Vector<char> encodedImage;
SkDevice* device = context()->platformContext()->canvas()->getDevice();
if (!encodeImage(device->accessBitmap(false), mimeType, quality, &encodedImage))
return "data:,";
+ Vector<char> base64Data;
base64Encode(encodedImage, base64Data);
+
return "data:" + mimeType + ";base64," + base64Data;
}
@@ -358,11 +380,13 @@ String ImageDataToDataURL(const ImageData& imageData, const String& mimeType, co
{
ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
- Vector<char> encodedImage, base64Data;
+ Vector<char> encodedImage;
if (!encodeImage(imageData, mimeType, quality, &encodedImage))
return "data:,";
+ Vector<char> base64Data;
base64Encode(encodedImage, base64Data);
+
return "data:" + mimeType + ";base64," + base64Data;
}
diff --git a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp
index 1d5d9911b..4732d1d22 100644
--- a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp
@@ -479,7 +479,8 @@ PassRefPtr<BitmapImageSingleFrameSkia> BitmapImageSingleFrameSkia::create(const
{
if (copyPixels) {
SkBitmap temp;
- bitmap.copyTo(&temp, bitmap.config());
+ if (!bitmap.deepCopyTo(&temp, bitmap.config()))
+ bitmap.copyTo(&temp, bitmap.config());
return adoptRef(new BitmapImageSingleFrameSkia(temp));
}
return adoptRef(new BitmapImageSingleFrameSkia(bitmap));
diff --git a/Source/WebCore/platform/graphics/skia/NativeImageSkia.cpp b/Source/WebCore/platform/graphics/skia/NativeImageSkia.cpp
index 5e66ca47b..425f56578 100644
--- a/Source/WebCore/platform/graphics/skia/NativeImageSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/NativeImageSkia.cpp
@@ -127,6 +127,11 @@ bool NativeImageSkia::shouldCacheResampling(const SkIRect& srcSubset,
if (!isDataComplete())
return false;
+ // If the destination bitmap is excessively large, we'll never allow caching.
+ static const unsigned long long kLargeBitmapSize = 4096ULL * 4096ULL;
+ if ((static_cast<unsigned long long>(destWidth) * static_cast<unsigned long long>(destHeight)) > kLargeBitmapSize)
+ return false;
+
// If the destination bitmap is small, we'll always allow caching, since
// there is not very much penalty for computing it and it may come in handy.
static const int kSmallBitmapSize = 4096;
diff --git a/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.cpp b/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.cpp
index 5a4f1534c..3ff3a543b 100644
--- a/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.cpp
@@ -124,10 +124,11 @@ static inline bool xfermodePreservesOpaque(const SkPaint& paint, bool srcIsOpaqu
}
// Returns true if all pixels painted will be opaque.
-static inline bool paintIsOpaque(const SkPaint& paint, const SkBitmap* bitmap = 0, bool checkFillOnly = false)
+static inline bool paintIsOpaque(const SkPaint& paint, OpaqueRegionSkia::DrawType drawType, const SkBitmap* bitmap)
{
if (paint.getAlpha() < 0xFF)
return false;
+ bool checkFillOnly = drawType != OpaqueRegionSkia::FillOrStroke;
if (!checkFillOnly && paint.getStyle() != SkPaint::kFill_Style && paint.isAntiAlias())
return false;
SkShader* shader = paint.getShader();
@@ -147,48 +148,98 @@ static inline bool paintIsOpaque(const SkPaint& paint, const SkBitmap* bitmap =
return true;
}
-void OpaqueRegionSkia::didDrawRect(PlatformContextSkia* context, const AffineTransform& transform, const SkRect& fillRect, const SkPaint& paint, const SkBitmap* bitmap)
+// Returns true if there is a rectangular clip, with the result in |deviceClipRect|.
+static inline bool getDeviceClipAsRect(const PlatformContextSkia* context, SkRect& deviceClipRect)
+{
+ // Get the current clip in device coordinate space.
+ if (context->canvas()->getClipType() != SkCanvas::kRect_ClipType)
+ return false;
+
+ SkIRect deviceClipIRect;
+ if (context->canvas()->getClipDeviceBounds(&deviceClipIRect))
+ deviceClipRect.set(deviceClipIRect);
+ else
+ deviceClipRect.setEmpty();
+
+ return true;
+}
+
+static inline SkRect& currentTrackingOpaqueRect(SkRect& rootOpaqueRect, Vector<OpaqueRegionSkia::CanvasLayerState, 3>& canvasLayerStack)
+{
+ // If we are drawing into a canvas layer, then track the opaque rect in that layer.
+ if (!canvasLayerStack.isEmpty())
+ return canvasLayerStack.last().opaqueRect;
+ return rootOpaqueRect;
+}
+
+void OpaqueRegionSkia::pushCanvasLayer(const SkPaint* paint)
+{
+ CanvasLayerState state;
+ if (paint)
+ state.paint = *paint;
+ m_canvasLayerStack.append(state);
+}
+
+void OpaqueRegionSkia::popCanvasLayer(const PlatformContextSkia* context)
+{
+ const CanvasLayerState& canvasLayer = m_canvasLayerStack.last();
+ SkRect layerOpaqueRect = canvasLayer.opaqueRect;
+ SkPaint layerPaint = canvasLayer.paint;
+
+ // Apply the image mask.
+ if (canvasLayer.hasImageMask && !layerOpaqueRect.intersect(canvasLayer.imageOpaqueRect))
+ layerOpaqueRect.setEmpty();
+
+ m_canvasLayerStack.removeLast();
+
+ applyOpaqueRegionFromLayer(context, layerOpaqueRect, layerPaint);
+}
+
+void OpaqueRegionSkia::setImageMask(const SkRect& imageOpaqueRect)
+{
+ ASSERT(!m_canvasLayerStack.isEmpty());
+ m_canvasLayerStack.last().hasImageMask = true;
+ m_canvasLayerStack.last().imageOpaqueRect = imageOpaqueRect;
+}
+
+void OpaqueRegionSkia::didDrawRect(const PlatformContextSkia* context, const SkRect& fillRect, const SkPaint& paint, const SkBitmap* sourceBitmap)
{
// Any stroking may put alpha in pixels even if the filling part does not.
if (paint.getStyle() != SkPaint::kFill_Style) {
- bool opaque = paintIsOpaque(paint, bitmap);
bool fillsBounds = false;
if (!paint.canComputeFastBounds())
- didDrawUnbounded(paint, opaque);
+ didDrawUnbounded(context, paint, FillOrStroke);
else {
SkRect strokeRect;
strokeRect = paint.computeFastBounds(fillRect, &strokeRect);
- didDraw(context, transform, strokeRect, paint, opaque, fillsBounds);
+ didDraw(context, strokeRect, paint, sourceBitmap, fillsBounds, FillOrStroke);
}
}
- bool checkFillOnly = true;
- bool opaque = paintIsOpaque(paint, bitmap, checkFillOnly);
bool fillsBounds = paint.getStyle() != SkPaint::kStroke_Style;
- didDraw(context, transform, fillRect, paint, opaque, fillsBounds);
+ didDraw(context, fillRect, paint, sourceBitmap, fillsBounds, FillOnly);
}
-void OpaqueRegionSkia::didDrawPath(PlatformContextSkia* context, const AffineTransform& transform, const SkPath& path, const SkPaint& paint)
+void OpaqueRegionSkia::didDrawPath(const PlatformContextSkia* context, const SkPath& path, const SkPaint& paint)
{
SkRect rect;
if (path.isRect(&rect)) {
- didDrawRect(context, transform, rect, paint, 0);
+ didDrawRect(context, rect, paint, 0);
return;
}
- bool opaque = paintIsOpaque(paint);
bool fillsBounds = false;
if (!paint.canComputeFastBounds())
- didDrawUnbounded(paint, opaque);
+ didDrawUnbounded(context, paint, FillOrStroke);
else {
rect = paint.computeFastBounds(path.getBounds(), &rect);
- didDraw(context, transform, rect, paint, opaque, fillsBounds);
+ didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke);
}
}
-void OpaqueRegionSkia::didDrawPoints(PlatformContextSkia* context, const AffineTransform& transform, SkCanvas::PointMode mode, int numPoints, const SkPoint points[], const SkPaint& paint)
+void OpaqueRegionSkia::didDrawPoints(const PlatformContextSkia* context, SkCanvas::PointMode mode, int numPoints, const SkPoint points[], const SkPaint& paint)
{
if (!numPoints)
return;
@@ -206,88 +257,99 @@ void OpaqueRegionSkia::didDrawPoints(PlatformContextSkia* context, const AffineT
rect.fBottom = std::max(rect.fBottom, points[i].fY + 1);
}
- bool opaque = paintIsOpaque(paint);
bool fillsBounds = false;
if (!paint.canComputeFastBounds())
- didDrawUnbounded(paint, opaque);
+ didDrawUnbounded(context, paint, FillOrStroke);
else {
rect = paint.computeFastBounds(rect, &rect);
- didDraw(context, transform, rect, paint, opaque, fillsBounds);
+ didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke);
}
}
-void OpaqueRegionSkia::didDrawBounded(PlatformContextSkia* context, const AffineTransform& transform, const SkRect& bounds, const SkPaint& paint)
+void OpaqueRegionSkia::didDrawBounded(const PlatformContextSkia* context, const SkRect& bounds, const SkPaint& paint)
{
- bool opaque = paintIsOpaque(paint);
bool fillsBounds = false;
if (!paint.canComputeFastBounds())
- didDrawUnbounded(paint, opaque);
+ didDrawUnbounded(context, paint, FillOrStroke);
else {
SkRect rect;
rect = paint.computeFastBounds(bounds, &rect);
- didDraw(context, transform, rect, paint, opaque, fillsBounds);
+ didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke);
}
}
-void OpaqueRegionSkia::didDraw(PlatformContextSkia* context, const AffineTransform& transform, const SkRect& rect, const SkPaint& paint, bool drawsOpaque, bool fillsBounds)
+void OpaqueRegionSkia::didDraw(const PlatformContextSkia* context, const SkRect& rect, const SkPaint& paint, const SkBitmap* sourceBitmap, bool fillsBounds, DrawType drawType)
{
SkRect targetRect = rect;
- bool xfersOpaque = xfermodeIsOpaque(paint, drawsOpaque);
- bool preservesOpaque = xfermodePreservesOpaque(paint, drawsOpaque);
-
// Apply the transform to device coordinate space.
SkMatrix canvasTransform = context->canvas()->getTotalMatrix();
if (!canvasTransform.mapRect(&targetRect))
fillsBounds = false;
- // Apply the current clip in device coordinate space.
- if (context->canvas()->getClipType() != SkCanvas::kRect_ClipType)
+ // Apply the current clip.
+ SkRect deviceClipRect;
+ if (!getDeviceClipAsRect(context, deviceClipRect))
fillsBounds = false;
- else {
- SkIRect deviceClip;
- context->canvas()->getClipDeviceBounds(&deviceClip);
- if (!targetRect.intersect(SkIntToScalar(deviceClip.fLeft), SkIntToScalar(deviceClip.fTop), SkIntToScalar(deviceClip.fRight), SkIntToScalar(deviceClip.fBottom)))
- return;
- }
-
- // Apply any layers that we are drawing into.
- for (SkCanvas::LayerIter it(context->canvas(), false); !it.done(); it.next()) {
- // Apply the layer's clip (which is in device space)
- const SkRegion& deviceLayerClip = it.clip();
- if (deviceLayerClip.isEmpty() || !deviceLayerClip.isRect())
- fillsBounds = false;
- else {
- SkIRect clipBounds = it.clip().getBounds();
- if (!targetRect.intersect(SkIntToScalar(clipBounds.fLeft), SkIntToScalar(clipBounds.fTop), SkIntToScalar(clipBounds.fRight), SkIntToScalar(clipBounds.fBottom)))
- return;
- }
-
- // Make sure the paint stays opaque through the layer.
- bool drawsOpaque = paintIsOpaque(it.paint());
- xfersOpaque = xfersOpaque && xfermodeIsOpaque(it.paint(), drawsOpaque);
- preservesOpaque = preservesOpaque && xfermodePreservesOpaque(it.paint(), drawsOpaque);
- }
+ else if (!targetRect.intersect(deviceClipRect))
+ return;
- // Apply the transform to the tracking space.
- SkMatrix canvasToTargetTransform = transform;
- if (!canvasToTargetTransform.mapRect(&targetRect))
- fillsBounds = false;
+ bool drawsOpaque = paintIsOpaque(paint, drawType, sourceBitmap);
+ bool xfersOpaque = xfermodeIsOpaque(paint, drawsOpaque);
+ bool preservesOpaque = xfermodePreservesOpaque(paint, drawsOpaque);
if (fillsBounds && xfersOpaque)
markRectAsOpaque(targetRect);
- else if (SkRect::Intersects(targetRect, m_opaqueRect) && !preservesOpaque)
+ else if (!preservesOpaque)
markRectAsNonOpaque(targetRect);
}
-void OpaqueRegionSkia::didDrawUnbounded(const SkPaint& paint, bool drawsOpaque)
+void OpaqueRegionSkia::didDrawUnbounded(const PlatformContextSkia* context, const SkPaint& paint, DrawType drawType)
{
- if (!xfermodePreservesOpaque(paint, drawsOpaque)) {
- // We don't know what was drawn on so just destroy the known opaque area.
- m_opaqueRect = SkRect::MakeEmpty();
- }
+ bool drawsOpaque = paintIsOpaque(paint, drawType, 0);
+ bool preservesOpaque = xfermodePreservesOpaque(paint, drawsOpaque);
+
+ if (preservesOpaque)
+ return;
+
+ SkRect deviceClipRect;
+ getDeviceClipAsRect(context, deviceClipRect);
+ markRectAsNonOpaque(deviceClipRect);
+}
+
+void OpaqueRegionSkia::applyOpaqueRegionFromLayer(const PlatformContextSkia* context, const SkRect& layerOpaqueRect, const SkPaint& paint)
+{
+ SkRect deviceClipRect;
+ bool deviceClipIsARect = getDeviceClipAsRect(context, deviceClipRect);
+
+ if (deviceClipRect.isEmpty())
+ return;
+
+ SkRect sourceOpaqueRect = layerOpaqueRect;
+ // Save the opaque area in the destination, so we can preserve the parts of it under the source opaque area if possible.
+ SkRect destinationOpaqueRect = currentTrackingOpaqueRect(m_opaqueRect, m_canvasLayerStack);
+
+ bool outsideSourceOpaqueRectPreservesOpaque = xfermodePreservesOpaque(paint, false);
+ if (!outsideSourceOpaqueRectPreservesOpaque)
+ markRectAsNonOpaque(deviceClipRect);
+
+ if (!deviceClipIsARect)
+ return;
+ if (!sourceOpaqueRect.intersect(deviceClipRect))
+ return;
+
+ bool sourceOpaqueRectDrawsOpaque = paintIsOpaque(paint, FillOnly, 0);
+ bool sourceOpaqueRectXfersOpaque = xfermodeIsOpaque(paint, sourceOpaqueRectDrawsOpaque);
+ bool sourceOpaqueRectPreservesOpaque = xfermodePreservesOpaque(paint, sourceOpaqueRectDrawsOpaque);
+
+ // If the layer's opaque area is being drawn opaque in the layer below, then mark it opaque. Otherwise,
+ // if it preserves opaque then keep the intersection of the two.
+ if (sourceOpaqueRectXfersOpaque)
+ markRectAsOpaque(sourceOpaqueRect);
+ else if (sourceOpaqueRectPreservesOpaque && sourceOpaqueRect.intersect(destinationOpaqueRect))
+ markRectAsOpaque(sourceOpaqueRect);
}
void OpaqueRegionSkia::markRectAsOpaque(const SkRect& rect)
@@ -297,31 +359,33 @@ void OpaqueRegionSkia::markRectAsOpaque(const SkRect& rect)
// rectangle then we do that, as that is the cheapest way to increase the area returned
// without increasing the complexity.
+ SkRect& opaqueRect = currentTrackingOpaqueRect(m_opaqueRect, m_canvasLayerStack);
+
if (rect.isEmpty())
return;
- if (m_opaqueRect.contains(rect))
+ if (opaqueRect.contains(rect))
return;
- if (rect.contains(m_opaqueRect)) {
- m_opaqueRect = rect;
+ if (rect.contains(opaqueRect)) {
+ opaqueRect = rect;
return;
}
- if (rect.fTop <= m_opaqueRect.fTop && rect.fBottom >= m_opaqueRect.fBottom) {
- if (rect.fLeft < m_opaqueRect.fLeft && rect.fRight >= m_opaqueRect.fLeft)
- m_opaqueRect.fLeft = rect.fLeft;
- if (rect.fRight > m_opaqueRect.fRight && rect.fLeft <= m_opaqueRect.fRight)
- m_opaqueRect.fRight = rect.fRight;
- } else if (rect.fLeft <= m_opaqueRect.fLeft && rect.fRight >= m_opaqueRect.fRight) {
- if (rect.fTop < m_opaqueRect.fTop && rect.fBottom >= m_opaqueRect.fTop)
- m_opaqueRect.fTop = rect.fTop;
- if (rect.fBottom > m_opaqueRect.fBottom && rect.fTop <= m_opaqueRect.fBottom)
- m_opaqueRect.fBottom = rect.fBottom;
+ if (rect.fTop <= opaqueRect.fTop && rect.fBottom >= opaqueRect.fBottom) {
+ if (rect.fLeft < opaqueRect.fLeft && rect.fRight >= opaqueRect.fLeft)
+ opaqueRect.fLeft = rect.fLeft;
+ if (rect.fRight > opaqueRect.fRight && rect.fLeft <= opaqueRect.fRight)
+ opaqueRect.fRight = rect.fRight;
+ } else if (rect.fLeft <= opaqueRect.fLeft && rect.fRight >= opaqueRect.fRight) {
+ if (rect.fTop < opaqueRect.fTop && rect.fBottom >= opaqueRect.fTop)
+ opaqueRect.fTop = rect.fTop;
+ if (rect.fBottom > opaqueRect.fBottom && rect.fTop <= opaqueRect.fBottom)
+ opaqueRect.fBottom = rect.fBottom;
}
- long opaqueArea = (long)m_opaqueRect.width() * (long)m_opaqueRect.height();
+ long opaqueArea = (long)opaqueRect.width() * (long)opaqueRect.height();
long area = (long)rect.width() * (long)rect.height();
if (area > opaqueArea)
- m_opaqueRect = rect;
+ opaqueRect = rect;
}
void OpaqueRegionSkia::markRectAsNonOpaque(const SkRect& rect)
@@ -329,34 +393,43 @@ void OpaqueRegionSkia::markRectAsNonOpaque(const SkRect& rect)
// We want to keep as much of the current opaque rectangle as we can, so find the one largest
// rectangle inside m_opaqueRect that does not intersect with |rect|.
- if (rect.contains(m_opaqueRect)) {
- m_opaqueRect.setEmpty();
+ SkRect& opaqueRect = currentTrackingOpaqueRect(m_opaqueRect, m_canvasLayerStack);
+
+ if (!SkRect::Intersects(rect, opaqueRect))
+ return;
+ if (rect.contains(opaqueRect)) {
+ markAllAsNonOpaque();
return;
}
- int deltaLeft = rect.fLeft - m_opaqueRect.fLeft;
- int deltaRight = m_opaqueRect.fRight - rect.fRight;
- int deltaTop = rect.fTop - m_opaqueRect.fTop;
- int deltaBottom = m_opaqueRect.fBottom - rect.fBottom;
+ int deltaLeft = rect.fLeft - opaqueRect.fLeft;
+ int deltaRight = opaqueRect.fRight - rect.fRight;
+ int deltaTop = rect.fTop - opaqueRect.fTop;
+ int deltaBottom = opaqueRect.fBottom - rect.fBottom;
- // horizontal is the larger of the two rectangles to the left or to the right of |rect| and inside m_opaqueRect.
- // vertical is the larger of the two rectangles above or below |rect| and inside m_opaqueRect.
- SkRect horizontal = m_opaqueRect;
+ // horizontal is the larger of the two rectangles to the left or to the right of |rect| and inside opaqueRect.
+ // vertical is the larger of the two rectangles above or below |rect| and inside opaqueRect.
+ SkRect horizontal = opaqueRect;
if (deltaTop > deltaBottom)
horizontal.fBottom = rect.fTop;
else
horizontal.fTop = rect.fBottom;
- SkRect vertical = m_opaqueRect;
+ SkRect vertical = opaqueRect;
if (deltaLeft > deltaRight)
vertical.fRight = rect.fLeft;
else
vertical.fLeft = rect.fRight;
if ((long)horizontal.width() * (long)horizontal.height() > (long)vertical.width() * (long)vertical.height())
- m_opaqueRect = horizontal;
+ opaqueRect = horizontal;
else
- m_opaqueRect = vertical;
+ opaqueRect = vertical;
}
+void OpaqueRegionSkia::markAllAsNonOpaque()
+{
+ SkRect& opaqueRect = currentTrackingOpaqueRect(m_opaqueRect, m_canvasLayerStack);
+ opaqueRect.setEmpty();
+}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.h b/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.h
index 431c6ec19..7bd803918 100644
--- a/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.h
+++ b/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.h
@@ -40,7 +40,6 @@
#include "SkRect.h"
namespace WebCore {
-class AffineTransform;
class PlatformContextSkia;
// This class is an encapsulation of functionality for PlatformContextSkia, and its methods are mirrored
@@ -53,20 +52,48 @@ public:
// The resulting opaque region as a single rect.
IntRect asRect() const;
- // FIXME: make all the PlatformContextSkia* into a const pointer when Skia fixes LayerIter's SkCanvas*.
+ void pushCanvasLayer(const SkPaint*);
+ void popCanvasLayer(const PlatformContextSkia*);
- void didDrawRect(PlatformContextSkia*, const AffineTransform&, const SkRect&, const SkPaint&, const SkBitmap*);
- void didDrawPath(PlatformContextSkia*, const AffineTransform&, const SkPath&, const SkPaint&);
- void didDrawPoints(PlatformContextSkia*, const AffineTransform&, SkCanvas::PointMode, int numPoints, const SkPoint[], const SkPaint&);
- void didDrawBounded(PlatformContextSkia*, const AffineTransform&, const SkRect&, const SkPaint&);
+ void setImageMask(const SkRect& imageOpaqueRect);
+
+ void didDrawRect(const PlatformContextSkia*, const SkRect&, const SkPaint&, const SkBitmap* sourceBitmap);
+ void didDrawPath(const PlatformContextSkia*, const SkPath&, const SkPaint&);
+ void didDrawPoints(const PlatformContextSkia*, SkCanvas::PointMode, int numPoints, const SkPoint[], const SkPaint&);
+ void didDrawBounded(const PlatformContextSkia*, const SkRect&, const SkPaint&);
+
+ enum DrawType {
+ FillOnly,
+ FillOrStroke
+ };
+
+ struct CanvasLayerState {
+ CanvasLayerState()
+ : hasImageMask(false)
+ , opaqueRect(SkRect::MakeEmpty())
+ { }
+
+ SkPaint paint;
+
+ // An image mask is being applied to the layer.
+ bool hasImageMask;
+ // The opaque area in the image mask.
+ SkRect imageOpaqueRect;
+
+ SkRect opaqueRect;
+ };
private:
- void didDraw(PlatformContextSkia*, const AffineTransform&, const SkRect&, const SkPaint&, bool drawsOpaque, bool fillsBounds);
- void didDrawUnbounded(const SkPaint&, bool drawsOpaque);
+ void didDraw(const PlatformContextSkia*, const SkRect&, const SkPaint&, const SkBitmap* sourceBitmap, bool fillsBounds, DrawType);
+ void didDrawUnbounded(const PlatformContextSkia*, const SkPaint&, DrawType);
+ void applyOpaqueRegionFromLayer(const PlatformContextSkia*, const SkRect& layerOpaqueRect, const SkPaint&);
void markRectAsOpaque(const SkRect&);
void markRectAsNonOpaque(const SkRect&);
+ void markAllAsNonOpaque();
SkRect m_opaqueRect;
+
+ Vector<CanvasLayerState, 3> m_canvasLayerStack;
};
}
diff --git a/Source/WebCore/platform/graphics/skia/PatternSkia.cpp b/Source/WebCore/platform/graphics/skia/PatternSkia.cpp
index cc91c63da..78d1a39da 100644
--- a/Source/WebCore/platform/graphics/skia/PatternSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/PatternSkia.cpp
@@ -38,7 +38,11 @@
#include "SkColorShader.h"
#include "SkShader.h"
+#if USE(V8)
#include <v8.h>
+#endif
+
+using namespace std;
namespace WebCore {
@@ -47,7 +51,9 @@ void Pattern::platformDestroy()
SkSafeUnref(m_pattern);
m_pattern = 0;
if (m_externalMemoryAllocated) {
+#if USE(V8)
v8::V8::AdjustAmountOfExternalAllocatedMemory(-m_externalMemoryAllocated);
+#endif
m_externalMemoryAllocated = 0;
}
}
@@ -96,8 +102,11 @@ PlatformPatternPtr Pattern::platformPattern(const AffineTransform& patternTransf
canvas.drawBitmap(image->bitmap(), 0, 0);
m_pattern = SkShader::CreateBitmapShader(bm2, tileModeX, tileModeY);
- m_externalMemoryAllocated = bm2.getSafeSize();
+ // Clamp to int, since that's what the adjust function takes.
+ m_externalMemoryAllocated = static_cast<int>(min(static_cast<size_t>(INT_MAX), bm2.getSafeSize()));
+#if USE(V8)
v8::V8::AdjustAmountOfExternalAllocatedMemory(m_externalMemoryAllocated);
+#endif
}
m_pattern->setLocalMatrix(m_patternSpaceTransformation);
return m_pattern;
diff --git a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
index 7ee90cadd..a373040df 100644
--- a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
@@ -181,9 +181,9 @@ PlatformContextSkia::PlatformContextSkia(SkCanvas* canvas)
: m_canvas(canvas)
, m_trackOpaqueRegion(false)
, m_printing(false)
+ , m_accelerated(false)
, m_deferred(false)
, m_drawingToImageBuffer(false)
- , m_gpuContext(0)
{
m_stateStack.append(State());
m_state = &m_stateStack.last();
@@ -226,28 +226,62 @@ void PlatformContextSkia::save()
canvas()->save();
}
+void PlatformContextSkia::saveLayer(const SkRect* bounds, const SkPaint* paint)
+{
+ m_canvas->saveLayer(bounds, paint);
+ if (bounds)
+ m_canvas->clipRect(*bounds);
+ if (m_trackOpaqueRegion)
+ m_opaqueRegion.pushCanvasLayer(paint);
+}
+
+void PlatformContextSkia::saveLayer(const SkRect* bounds, const SkPaint* paint, SkCanvas::SaveFlags saveFlags)
+{
+ m_canvas->saveLayer(bounds, paint, saveFlags);
+ if (bounds)
+ m_canvas->clipRect(*bounds);
+ if (m_trackOpaqueRegion)
+ m_opaqueRegion.pushCanvasLayer(paint);
+}
+
+void PlatformContextSkia::restoreLayer()
+{
+ m_canvas->restore();
+ if (m_trackOpaqueRegion)
+ m_opaqueRegion.popCanvasLayer(this);
+}
+
void PlatformContextSkia::beginLayerClippedToImage(const FloatRect& rect,
const ImageBuffer* imageBuffer)
{
+ SkRect bounds = { SkFloatToScalar(rect.x()), SkFloatToScalar(rect.y()),
+ SkFloatToScalar(rect.maxX()), SkFloatToScalar(rect.maxY()) };
+
+ if (imageBuffer->internalSize().isEmpty()) {
+ m_canvas->clipRect(bounds);
+ return;
+ }
+
// Skia doesn't support clipping to an image, so we create a layer. The next
// time restore is invoked the layer and |imageBuffer| are combined to
// create the resulting image.
- SkRect bounds = { SkFloatToScalar(rect.x()), SkFloatToScalar(rect.y()),
- SkFloatToScalar(rect.maxX()), SkFloatToScalar(rect.maxY()) };
+
m_state->m_clip = bounds;
// Get the absolute coordinates of the stored clipping rectangle to make it
// independent of any transform changes.
canvas()->getTotalMatrix().mapRect(&m_state->m_clip);
- canvas()->clipRect(bounds);
+ SkCanvas::SaveFlags saveFlags = static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag);
+ saveLayer(&bounds, 0, saveFlags);
- if (imageBuffer->internalSize().isEmpty())
- return;
+ const SkBitmap* bitmap = imageBuffer->context()->platformContext()->bitmap();
+
+ if (m_trackOpaqueRegion) {
+ SkRect opaqueRect = bitmap->isOpaque() ? m_state->m_clip : SkRect::MakeEmpty();
+ m_opaqueRegion.setImageMask(opaqueRect);
+ }
- canvas()->saveLayerAlpha(&bounds, 255,
- static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag));
// Copy off the image as |imageBuffer| may be deleted before restore is invoked.
- const SkBitmap* bitmap = imageBuffer->context()->platformContext()->bitmap();
if (!bitmap->pixelRef()) {
// The bitmap owns it's pixels. This happens when we've allocated the
// pixels in some way and assigned them directly to the bitmap (as
@@ -602,33 +636,50 @@ void PlatformContextSkia::applyClipFromImage(const SkRect& rect, const SkBitmap&
m_canvas->restore();
}
-void PlatformContextSkia::setGraphicsContext3D(GraphicsContext3D* context)
-{
- m_gpuContext = context;
-}
-
void PlatformContextSkia::didDrawRect(const SkRect& rect, const SkPaint& paint, const SkBitmap* bitmap)
{
if (m_trackOpaqueRegion)
- m_opaqueRegion.didDrawRect(this, m_opaqueRegionTransform, rect, paint, bitmap);
+ m_opaqueRegion.didDrawRect(this, rect, paint, bitmap);
}
void PlatformContextSkia::didDrawPath(const SkPath& path, const SkPaint& paint)
{
if (m_trackOpaqueRegion)
- m_opaqueRegion.didDrawPath(this, m_opaqueRegionTransform, path, paint);
+ m_opaqueRegion.didDrawPath(this, path, paint);
}
void PlatformContextSkia::didDrawPoints(SkCanvas::PointMode mode, int numPoints, const SkPoint points[], const SkPaint& paint)
{
if (m_trackOpaqueRegion)
- m_opaqueRegion.didDrawPoints(this, m_opaqueRegionTransform, mode, numPoints, points, paint);
+ m_opaqueRegion.didDrawPoints(this, mode, numPoints, points, paint);
}
void PlatformContextSkia::didDrawBounded(const SkRect& rect, const SkPaint& paint)
{
if (m_trackOpaqueRegion)
- m_opaqueRegion.didDrawBounded(this, m_opaqueRegionTransform, rect, paint);
+ m_opaqueRegion.didDrawBounded(this, rect, paint);
+}
+
+void PlatformContextSkia::adjustTextRenderMode(SkPaint* paint)
+{
+ if (!paint->isLCDRenderText())
+ return;
+
+ paint->setLCDRenderText(couldUseLCDRenderedText());
+}
+
+bool PlatformContextSkia::couldUseLCDRenderedText()
+{
+ // Our layers only have a single alpha channel. This means that subpixel
+ // rendered text cannot be composited correctly when the layer is
+ // collapsed. Therefore, subpixel text is disabled when we are drawing
+ // onto a layer.
+ if (canvas()->isDrawingToLayer())
+ return false;
+
+ // If this text is not in an image buffer and so won't be externally
+ // composited, then subpixel antialiasing is fine.
+ return !isDrawingToImageBuffer();
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h
index 8d7a2e684..b9fcb7b42 100644
--- a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h
+++ b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h
@@ -31,9 +31,7 @@
#ifndef PlatformContextSkia_h
#define PlatformContextSkia_h
-#include "AffineTransform.h"
#include "GraphicsContext.h"
-#include "Noncopyable.h"
#include "OpaqueRegionSkia.h"
#include "SkCanvas.h"
@@ -42,12 +40,12 @@
#include "SkPaint.h"
#include "SkPath.h"
+#include <wtf/Noncopyable.h>
#include <wtf/Vector.h>
namespace WebCore {
enum CompositeOperator;
-class GraphicsContext3D;
class Texture;
// This class holds the platform-specific state for GraphicsContext. We put
@@ -94,6 +92,10 @@ public:
void save();
void restore();
+ void saveLayer(const SkRect* bounds, const SkPaint*);
+ void saveLayer(const SkRect* bounds, const SkPaint*, SkCanvas::SaveFlags);
+ void restoreLayer();
+
// Begins a layer that is clipped to the image |imageBuffer| at the location
// |rect|. This layer is implicitly restored when the next restore is
// invoked.
@@ -181,8 +183,8 @@ public:
void clearImageResamplingHint();
bool hasImageResamplingHint() const;
- bool isAccelerated() const { return m_gpuContext; }
- void setGraphicsContext3D(GraphicsContext3D*);
+ bool isAccelerated() const { return m_accelerated; }
+ void setAccelerated(bool accelerated) { m_accelerated = accelerated; }
// True if this context is deferring draw calls to be executed later.
// We need to know this for context-to-context draws, in order to know if
@@ -191,8 +193,6 @@ public:
void setDeferred(bool deferred) { m_deferred = deferred; }
void setTrackOpaqueRegion(bool track) { m_trackOpaqueRegion = track; }
- // A transform applied to all tracked opaque paints. This is applied at the time the painting is done.
- void setOpaqueRegionTransform(const AffineTransform& transform) { m_opaqueRegionTransform = transform; }
// This will be an empty region unless tracking is enabled.
const OpaqueRegionSkia& opaqueRegion() const { return m_opaqueRegion; }
@@ -204,6 +204,10 @@ public:
// For drawing operations that do not fill the entire rect.
void didDrawBounded(const SkRect&, const SkPaint&);
+ // Turn off LCD text for the paint if not supported on this context.
+ void adjustTextRenderMode(SkPaint*);
+ bool couldUseLCDRenderedText();
+
private:
// Used when restoring and the state has an image clip. Only shows the pixels in
// m_canvas that are also in imageBuffer.
@@ -230,16 +234,15 @@ private:
// Tracks the region painted opaque via the GraphicsContext.
OpaqueRegionSkia m_opaqueRegion;
bool m_trackOpaqueRegion;
- AffineTransform m_opaqueRegionTransform;
// Stores image sizes for a hint to compute image resampling modes.
// Values are used in ImageSkia.cpp
IntSize m_imageResamplingHintSrcSize;
FloatSize m_imageResamplingHintDstSize;
bool m_printing;
+ bool m_accelerated;
bool m_deferred;
bool m_drawingToImageBuffer;
- GraphicsContext3D* m_gpuContext;
};
}
diff --git a/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp b/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp
index 782b02fa9..65a468ef3 100644
--- a/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp
@@ -139,8 +139,14 @@ void SimpleFontData::platformInit()
static const UChar32 xChar = 'x';
const Glyph xGlyph = glyphPageZero->glyphDataForCharacter(xChar).glyph;
- if (xGlyph)
+ if (xGlyph) {
+ // In widthForGlyph(), xGlyph will be compared with
+ // m_zeroWidthSpaceGlyph, which isn't initialized yet here.
+ // Initialize it with zero to make sure widthForGlyph() returns
+ // the right width.
+ m_zeroWidthSpaceGlyph = 0;
m_avgCharWidth = widthForGlyph(xGlyph);
+ }
}
}
}
diff --git a/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp b/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp
index 1087cd0cb..a6f37cff0 100644
--- a/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp
+++ b/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp
@@ -137,24 +137,6 @@ static void skiaDrawText(SkCanvas* canvas,
}
}
-static bool isCanvasMultiLayered(SkCanvas* canvas)
-{
- SkCanvas::LayerIter layerIterator(canvas, false);
- layerIterator.next();
- return !layerIterator.done();
-}
-
-// lifted from FontSkia.cpp
-static bool disableTextLCD(PlatformContextSkia* skiaContext)
-{
- // Our layers only have a single alpha channel. This means that subpixel
- // rendered text cannot be compositied correctly when the layer is
- // collapsed. Therefore, subpixel text is disabled when we are drawing
- // onto a layer or when the compositor is being used.
- return isCanvasMultiLayered(skiaContext->canvas())
- || skiaContext->isDrawingToImageBuffer();
-}
-
// Lookup the current system settings for font smoothing.
// We cache these values for performance, but if the browser has away to be
// notified when these change, we could re-query them at that time.
@@ -205,7 +187,7 @@ static void setupPaintForFont(SkPaint* paint, PlatformContextSkia* pcs,
textFlags &= getDefaultGDITextFlags();
// do this check after our switch on lfQuality
- if (disableTextLCD(pcs)) {
+ if (!pcs->couldUseLCDRenderedText()) {
textFlags &= ~SkPaint::kLCDRenderText_Flag;
// If we *just* clear our request for LCD, then GDI seems to
// sometimes give us AA text, and sometimes give us BW text. Since the
diff --git a/Source/WebCore/platform/graphics/skia/SkiaUtils.cpp b/Source/WebCore/platform/graphics/skia/SkiaUtils.cpp
index ba3d52481..1e2c8dab8 100644
--- a/Source/WebCore/platform/graphics/skia/SkiaUtils.cpp
+++ b/Source/WebCore/platform/graphics/skia/SkiaUtils.cpp
@@ -114,15 +114,6 @@ void ClipRectToCanvas(const SkCanvas& canvas, const SkRect& srcRect, SkRect* des
bool SkPathContainsPoint(SkPath* originalPath, const FloatPoint& point, SkPath::FillType ft)
{
- SkRegion rgn;
- SkRegion clip;
-
- SkPath::FillType originalFillType = originalPath->getFillType();
-
- const SkPath* path = originalPath;
- SkPath scaledPath;
- int scale = 1;
-
SkRect bounds = originalPath->getBounds();
// We can immediately return false if the point is outside the bounding
@@ -134,31 +125,34 @@ bool SkPathContainsPoint(SkPath* originalPath, const FloatPoint& point, SkPath::
if (fX < bounds.fLeft || fX > bounds.fRight || fY < bounds.fTop || fY > bounds.fBottom)
return false;
- originalPath->setFillType(ft);
-
- // Skia has trouble with coordinates close to the max signed 16-bit values
- // If we have those, we need to scale.
- //
- // TODO: remove this code once Skia is patched to work properly with large
- // values
- const SkScalar kMaxCoordinate = SkIntToScalar(1<<15);
+ // Scale the path to a large size before hit testing for two reasons:
+ // 1) Skia has trouble with coordinates close to the max signed 16-bit values, so we scale larger paths down.
+ // TODO: when Skia is patched to work properly with large values, this will not be necessary.
+ // 2) Skia does not support analytic hit testing, so we scale paths up to do raster hit testing with subpixel accuracy.
SkScalar biggestCoord = std::max(std::max(std::max(bounds.fRight, bounds.fBottom), -bounds.fLeft), -bounds.fTop);
+ if (SkScalarNearlyZero(biggestCoord))
+ return false;
+ biggestCoord = std::max(std::max(biggestCoord, fX + 1), fY + 1);
- if (biggestCoord > kMaxCoordinate) {
- scale = SkScalarCeil(SkScalarDiv(biggestCoord, kMaxCoordinate));
+ const SkScalar kMaxCoordinate = SkIntToScalar(1 << 15);
+ SkScalar scale = SkScalarDiv(kMaxCoordinate, biggestCoord);
- SkMatrix m;
- m.setScale(SkScalarInvert(SkIntToScalar(scale)), SkScalarInvert(SkIntToScalar(scale)));
- originalPath->transform(m, &scaledPath);
- path = &scaledPath;
- }
+ SkRegion rgn;
+ SkRegion clip;
+ SkMatrix m;
+ SkPath scaledPath;
- int x = static_cast<int>(floorf(point.x() / scale));
- int y = static_cast<int>(floorf(point.y() / scale));
- clip.setRect(x - 1, y - 1, x + 1, y + 1);
+ SkPath::FillType originalFillType = originalPath->getFillType();
+ originalPath->setFillType(ft);
- bool contains = rgn.setPath(*path, clip);
+ m.setScale(scale, scale);
+ originalPath->transform(m, &scaledPath);
+
+ int x = static_cast<int>(floorf(0.5f + point.x() * scale));
+ int y = static_cast<int>(floorf(0.5f + point.y() * scale));
+ clip.setRect(x - 1, y - 1, x + 1, y + 1);
+ bool contains = rgn.setPath(scaledPath, clip);
originalPath->setFillType(originalFillType);
return contains;
}
diff --git a/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.cpp b/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.cpp
new file mode 100644
index 000000000..b43a1012e
--- /dev/null
+++ b/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.cpp
@@ -0,0 +1,72 @@
+/*
+ Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "GraphicsSurface.h"
+
+#include "NotImplemented.h"
+
+#if USE(GRAPHICS_SURFACE)
+namespace WebCore {
+
+PassRefPtr<GraphicsSurface> GraphicsSurface::create(const IntSize& size, Flags flags, uint32_t token)
+{
+ RefPtr<GraphicsSurface> surface = adoptRef(new GraphicsSurface(size, flags));
+ if (!surface->platformImport(token))
+ return PassRefPtr<GraphicsSurface>();
+ return surface;
+}
+
+PassRefPtr<GraphicsSurface> GraphicsSurface::create(const IntSize& size, GraphicsSurface::Flags flags)
+{
+ RefPtr<GraphicsSurface> surface = adoptRef(new GraphicsSurface(size, flags));
+ if (!surface->platformCreate(size, flags))
+ return PassRefPtr<GraphicsSurface>();
+ return surface;
+}
+
+uint32_t GraphicsSurface::exportToken()
+{
+ return platformExport();
+}
+
+PassOwnPtr<GraphicsContext> GraphicsSurface::beginPaint(const IntRect& rect, LockOptions lockOptions)
+{
+ int stride = 0;
+ char* bits = platformLock(rect, &stride, lockOptions);
+ OwnPtr<GraphicsContext> graphicsContext = platformBeginPaint(rect.size(), bits, stride);
+ return graphicsContext.release();
+}
+
+void GraphicsSurface::copyToGLTexture(uint32_t target, uint32_t texture, const IntRect& targetRect, const IntPoint& offset)
+{
+ platformCopyToGLTexture(target, texture, targetRect, offset);
+}
+
+GraphicsSurface::GraphicsSurface(const IntSize& size, Flags flags)
+ : m_size(size)
+ , m_flags(flags)
+ , m_platformSurface(0)
+ , m_texture(0)
+ , m_fbo(0)
+{
+}
+
+}
+#endif
diff --git a/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h b/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h
new file mode 100644
index 000000000..da941d497
--- /dev/null
+++ b/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h
@@ -0,0 +1,104 @@
+/*
+ Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#ifndef GraphicsSurface_h
+#define GraphicsSurface_h
+
+#include "GraphicsContext.h"
+#include "IntRect.h"
+#include "OwnPtr.h"
+#include "PassOwnPtr.h"
+#include "RefCounted.h"
+#include "RefPtr.h"
+
+#if USE(GRAPHICS_SURFACE)
+
+#if OS(DARWIN)
+typedef struct __IOSurface* IOSurfaceRef;
+typedef IOSurfaceRef PlatformGraphicsSurface;
+#endif
+
+namespace WebCore {
+
+class GraphicsSurface : public RefCounted<GraphicsSurface> {
+public:
+ enum Flag {
+ SupportsAlpha = 0x01,
+ SupportsSoftwareWrite = 0x02,
+ SupportsSoftwareRead = 0x04,
+ SupportsTextureTarget = 0x08,
+ SupportsTextureSource = 0x10,
+ SupportsCopyToTexture = 0x20,
+ SupportsCopyFromTexture = 0x40,
+ SupportsSharing = 0x80
+ };
+
+ enum LockOption {
+ RetainPixels = 0x01,
+ ReadOnly = 0x02
+ };
+
+ typedef int Flags;
+ typedef int LockOptions;
+
+ Flags flags() const { return m_flags; }
+ PlatformGraphicsSurface platformSurface() const { return m_platformSurface; }
+ IntSize size() const { return m_size; }
+
+ static PassRefPtr<GraphicsSurface> create(const IntSize&, Flags);
+ static PassRefPtr<GraphicsSurface> create(const IntSize&, Flags, uint32_t token);
+ void copyToGLTexture(uint32_t target, uint32_t texture, const IntRect& targetRect, const IntPoint& sourceOffset);
+ uint32_t exportToken();
+ PassOwnPtr<GraphicsContext> beginPaint(const IntRect&, LockOptions);
+ PassRefPtr<Image> createReadOnlyImage(const IntRect&);
+
+protected:
+ bool platformCreate(const IntSize&, Flags);
+ bool platformImport(uint32_t);
+ uint32_t platformExport();
+ void platformDestroy();
+
+ char* platformLock(const IntRect&, int* stride, LockOptions);
+ void platformUnlock();
+ void platformCopyToGLTexture(uint32_t target, uint32_t texture, const IntRect&, const IntPoint&);
+
+ PassOwnPtr<GraphicsContext> platformBeginPaint(const IntSize&, char* bits, int stride);
+
+protected:
+ LockOptions m_lockOptions;
+ Flags m_flags;
+
+private:
+ GraphicsSurface(const IntSize&, Flags);
+
+#if PLATFORM(QT)
+ static void didReleaseImage(void*);
+#endif
+
+private:
+ IntSize m_size;
+ PlatformGraphicsSurface m_platformSurface;
+ uint32_t m_texture;
+ uint32_t m_fbo;
+};
+
+}
+#endif // USE(GRAPHICS_SURFACE)
+
+#endif // GraphicsSurface_h
diff --git a/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp b/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp
new file mode 100644
index 000000000..b6a1a0202
--- /dev/null
+++ b/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp
@@ -0,0 +1,178 @@
+/*
+ Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "GraphicsSurface.h"
+
+#if USE(GRAPHICS_SURFACE) && OS(DARWIN)
+#include <CFNumber.h>
+#include <CGLContext.h>
+#include <CGLCurrent.h>
+#include <CGLIOSurface.h>
+#include <IOSurface/IOSurface.h>
+
+
+namespace WebCore {
+
+uint32_t GraphicsSurface::platformExport()
+{
+ return IOSurfaceGetID(m_platformSurface);
+}
+
+static uint32_t createTexture(IOSurfaceRef handle)
+{
+ GLuint texture = 0;
+ GLuint format = GL_BGRA;
+ GLuint type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ GLuint internalFormat = GL_RGBA;
+ CGLContextObj context = CGLGetCurrentContext();
+ if (!context)
+ return 0;
+
+ GLint prevTexture;
+ GLboolean wasEnabled = glIsEnabled(GL_TEXTURE_RECTANGLE_ARB);
+ glGetIntegerv(GL_TEXTURE_RECTANGLE_ARB, &prevTexture);
+ if (!wasEnabled)
+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
+ CGLError error = CGLTexImageIOSurface2D(context, GL_TEXTURE_RECTANGLE_ARB, internalFormat, IOSurfaceGetWidth(handle), IOSurfaceGetHeight(handle), format, type, handle, 0);
+ if (error) {
+ glDeleteTextures(1, &texture);
+ texture = 0;
+ }
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, prevTexture);
+ if (!wasEnabled)
+ glDisable(GL_TEXTURE_RECTANGLE_ARB);
+ return texture;
+}
+
+void GraphicsSurface::platformCopyToGLTexture(uint32_t target, uint32_t id, const IntRect& targetRect, const IntPoint& offset)
+{
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ if (!m_texture)
+ m_texture = createTexture(m_platformSurface);
+ if (!m_fbo)
+ glGenFramebuffers(1, &m_fbo);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
+ glEnable(target);
+ glBindTexture(target, id);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo);
+ glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, m_texture, 0);
+ glCopyTexSubImage2D(target, 0, targetRect.x(), targetRect.y(), offset.x(), offset.y(), targetRect.width(), targetRect.height());
+ glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+ glPopAttrib();
+}
+
+bool GraphicsSurface::platformCreate(const IntSize& size, Flags flags)
+{
+ unsigned pixelFormat = 'BGRA';
+ unsigned bytesPerElement = 4;
+ int width = size.width();
+ int height = size.height();
+
+ unsigned long bytesPerRow = IOSurfaceAlignProperty(kIOSurfaceBytesPerRow, width * bytesPerElement);
+ if (!bytesPerRow)
+ return false;
+
+ unsigned long allocSize = IOSurfaceAlignProperty(kIOSurfaceAllocSize, height * bytesPerRow);
+ if (!allocSize)
+ return false;
+
+ const void *keys[7];
+ const void *values[7];
+ keys[0] = kIOSurfaceWidth;
+ values[0] = CFNumberCreate(0, kCFNumberIntType, &width);
+ keys[1] = kIOSurfaceHeight;
+ values[1] = CFNumberCreate(0, kCFNumberIntType, &height);
+ keys[2] = kIOSurfacePixelFormat;
+ values[2] = CFNumberCreate(0, kCFNumberIntType, &pixelFormat);
+ keys[3] = kIOSurfaceBytesPerElement;
+ values[3] = CFNumberCreate(0, kCFNumberIntType, &bytesPerElement);
+ keys[4] = kIOSurfaceBytesPerRow;
+ values[4] = CFNumberCreate(0, kCFNumberLongType, &bytesPerRow);
+ keys[5] = kIOSurfaceAllocSize;
+ values[5] = CFNumberCreate(0, kCFNumberLongType, &allocSize);
+ keys[6] = kIOSurfaceIsGlobal;
+ values[6] = (flags & GraphicsSurface::SupportsSharing) ? kCFBooleanTrue : kCFBooleanFalse;
+
+ CFDictionaryRef dict = CFDictionaryCreate(0, keys, values, 7, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ for (unsigned i = 0; i < 7; i++)
+ CFRelease(values[i]);
+
+ m_platformSurface = IOSurfaceCreate(dict);
+ return !!m_platformSurface;
+}
+
+bool GraphicsSurface::platformImport(uint32_t token)
+{
+ m_platformSurface = IOSurfaceLookup(token);
+ return !!m_platformSurface;
+}
+
+static int ioSurfaceLockOptions(int lockOptions)
+{
+ int options = 0;
+ if (lockOptions & GraphicsSurface::ReadOnly)
+ options |= kIOSurfaceLockReadOnly;
+ if (!(lockOptions & GraphicsSurface::RetainPixels))
+ options |= kIOSurfaceLockAvoidSync;
+ return options;
+}
+
+static int ioSurfaceUnlockOptions(int lockOptions)
+{
+ int options = 0;
+ if (lockOptions & GraphicsSurface::ReadOnly)
+ options |= (kIOSurfaceLockAvoidSync | kIOSurfaceLockReadOnly);
+ return options;
+}
+
+char* GraphicsSurface::platformLock(const IntRect& rect, int* outputStride, LockOptions lockOptions)
+{
+ m_lockOptions = lockOptions;
+ IOSurfaceLock(m_platformSurface, ioSurfaceLockOptions(m_lockOptions), 0);
+
+ int stride = IOSurfaceGetBytesPerRow(m_platformSurface);
+ if (outputStride)
+ *outputStride = stride;
+
+ char* base = static_cast<char*>(IOSurfaceGetBaseAddress(m_platformSurface));
+ return base + stride * rect.y() + rect.x() * 4;
+}
+
+void GraphicsSurface::platformUnlock()
+{
+ IOSurfaceUnlock(m_platformSurface, ioSurfaceUnlockOptions(m_lockOptions) & (~kIOSurfaceLockAvoidSync), 0);
+}
+
+void GraphicsSurface::platformDestroy()
+{
+ if (m_fbo)
+ glDeleteFramebuffers(1, &m_fbo);
+ if (m_texture)
+ glDeleteTextures(1, &m_texture);
+ CFRelease(IOSurfaceRef(m_platformSurface));
+}
+
+}
+#endif
diff --git a/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceQt.cpp b/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceQt.cpp
new file mode 100644
index 000000000..734a093ae
--- /dev/null
+++ b/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceQt.cpp
@@ -0,0 +1,60 @@
+/*
+ Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "GraphicsSurface.h"
+
+#if USE(GRAPHICS_SURFACE) && PLATFORM(QT)
+
+#include "BitmapImage.h"
+#include <QImage>
+#include <QPainter>
+#include <QPixmap>
+
+namespace WebCore {
+void GraphicsSurface::didReleaseImage(void* data)
+{
+ GraphicsSurface* surface = static_cast<GraphicsSurface*>(data);
+ surface->platformUnlock();
+}
+
+PassOwnPtr<GraphicsContext> GraphicsSurface::platformBeginPaint(const IntSize& size, char* bits, int stride)
+{
+ QImage::Format format = (flags() & SupportsAlpha) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
+
+ // The image and painter will be released when the returned GraphicsContext is released.
+ QImage* image = new QImage(reinterpret_cast<uchar*>(bits), size.width(), size.height(), stride, format, didReleaseImage, this);
+ QPainter* painter = new QPainter(image);
+ painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
+ OwnPtr<GraphicsContext> graphicsContext = adoptPtr(new GraphicsContext(painter));
+ graphicsContext->takeOwnershipOfPlatformContext();
+ return graphicsContext.release();
+}
+
+PassRefPtr<Image> GraphicsSurface::createReadOnlyImage(const IntRect& rect)
+{
+ int stride;
+ QImage::Format format = (flags() & SupportsAlpha) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
+ char* data = platformLock(rect, &stride, RetainPixels | ReadOnly);
+ QImage image(reinterpret_cast<uchar*>(data), rect.width(), rect.height(), stride, format, didReleaseImage, this);
+ return BitmapImage::create(new QPixmap(QPixmap::fromImage(image)));
+}
+
+}
+#endif
diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
index 46169c672..b5d03a1b2 100644
--- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
+++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
@@ -29,6 +29,7 @@ GraphicsLayerTextureMapper::GraphicsLayerTextureMapper(GraphicsLayerClient* clie
, m_layer(adoptPtr(new TextureMapperLayer()))
, m_changeMask(0)
, m_needsDisplay(false)
+ , m_fixedToViewport(false)
, m_contentsLayer(0)
, m_animationStartedTimer(this, &GraphicsLayerTextureMapper::animationStartedTimerFired)
{
@@ -57,6 +58,12 @@ void GraphicsLayerTextureMapper::setName(const String& name)
GraphicsLayerTextureMapper::~GraphicsLayerTextureMapper()
{
+ willBeDestroyed();
+}
+
+void GraphicsLayerTextureMapper::willBeDestroyed()
+{
+ GraphicsLayer::willBeDestroyed();
}
/* \reimp (GraphicsLayer.h): The current size might change, thus we need to update the whole display.
diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
index 07f378629..c82e943eb 100644
--- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
+++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
@@ -94,13 +94,19 @@ public:
virtual bool setFilters(const FilterOperations&);
#endif
+ void setFixedToViewport(bool fixed) { m_fixedToViewport = fixed; }
+ bool fixedToViewport() const { return m_fixedToViewport; }
+
private:
+ virtual void willBeDestroyed();
+
OwnPtr<TextureMapperLayer> m_layer;
RefPtr<TextureMapperBackingStore> m_compositedImage;
RefPtr<Image> m_image;
bool m_syncQueued;
int m_changeMask;
bool m_needsDisplay;
+ bool m_fixedToViewport;
TextureMapperPlatformLayer* m_contentsLayer;
FloatRect m_needsDisplayRect;
TextureMapperAnimations m_animations;
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp
index 58e4f594c..cee45b969 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp
@@ -37,31 +37,10 @@ PassRefPtr<BitmapTexture> TextureMapper::acquireTextureFromPool(const IntSize& s
if (texture->refCount() > 1)
continue;
- // We default to the first available texture.
- if (!selectedTexture) {
+ if (texture->canReuseWith(size)) {
selectedTexture = texture;
- continue;
+ break;
}
-
- IntSize textureSize = texture->size();
- IntSize selectedTextureSize = selectedTexture->size();
-
- // We prefer to pick a texture that's equal or larger than the requested size.
- if (textureSize.width() < size.width() || textureSize.height() < size.height())
- continue;
-
- // We select the new texture if the currently selected texture is smaller than the
- // required size, and the new texture has a smaller area.
- int textureArea = textureSize.width() * textureSize.height();
- int selectedTextureArea = selectedTextureSize.width() * selectedTextureSize.height();
- bool selectedTextureFitsSize =
- selectedTextureSize.width() >= size.width()
- && selectedTextureSize.height() >= size.height();
-
- if (selectedTextureFitsSize && selectedTextureArea <= textureArea)
- continue;
-
- selectedTexture = texture;
}
if (!selectedTexture) {
@@ -69,7 +48,7 @@ PassRefPtr<BitmapTexture> TextureMapper::acquireTextureFromPool(const IntSize& s
m_texturePool.append(selectedTexture);
}
- selectedTexture->reset(size, false);
+ selectedTexture->reset(size, BitmapTexture::SupportsAlpha);
return selectedTexture;
}
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.h b/Source/WebCore/platform/graphics/texmap/TextureMapper.h
index 4c07cab63..ca31d1769 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapper.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.h
@@ -20,16 +20,17 @@
#ifndef TextureMapper_h
#define TextureMapper_h
+#if USE(ACCELERATED_COMPOSITING)
+
#if PLATFORM(QT)
#include <qglobal.h>
-#endif
-#if USE(ACCELERATED_COMPOSITING)
#if defined(QT_OPENGL_LIB) || (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
#if defined(QT_OPENGL_ES_2) && !defined(TEXMAP_OPENGL_ES_2)
#define TEXMAP_OPENGL_ES_2
#endif
#endif
+#endif
#include "FilterOperations.h"
#include "GraphicsContext.h"
@@ -51,7 +52,6 @@ class TextureMapper;
// A 2D texture that can be the target of software or GL rendering.
class BitmapTexture : public RefCounted<BitmapTexture> {
public:
- enum PixelFormat { BGRAFormat, RGBAFormat, BGRFormat, RGBFormat };
enum Flag {
SupportsAlpha = 0x01
};
@@ -64,29 +64,30 @@ public:
}
virtual ~BitmapTexture() { }
- virtual void destroy() { }
+ virtual bool isBackedByOpenGL() const { return false; }
virtual IntSize size() const = 0;
- virtual void updateContents(Image*, const IntRect&, const IntRect&, BitmapTexture::PixelFormat) = 0;
- virtual void updateContents(const void*, const IntRect&) = 0;
+ virtual void updateContents(Image*, const IntRect&, const IntPoint& offset) = 0;
+ virtual void updateContents(const void*, const IntRect& target, const IntPoint& offset, int bytesPerLine) = 0;
virtual bool isValid() const = 0;
inline Flags flags() const { return m_flags; }
virtual int bpp() const { return 32; }
- virtual void didReset() { }
- void reset(const IntSize& size, Flags flags)
+ virtual bool canReuseWith(const IntSize& contentsSize, Flags flags = 0) { return false; }
+ void reset(const IntSize& size, Flags flags = 0)
{
m_flags = flags;
m_contentSize = size;
didReset();
}
+ virtual void didReset() { }
inline IntSize contentSize() const { return m_contentSize; }
inline int numberOfBytes() const { return size().width() * size().height() * bpp() >> 3; }
inline bool isOpaque() const { return !(m_flags & SupportsAlpha); }
#if ENABLE(CSS_FILTERS)
- virtual void applyFilters(const BitmapTexture& contentTexture, const FilterOperations&) { }
+ virtual PassRefPtr<BitmapTexture> applyFilters(const BitmapTexture& contentTexture, const FilterOperations&) { return this; }
#endif
protected:
@@ -103,6 +104,11 @@ class TextureMapper {
public:
enum AccelerationMode { SoftwareMode, OpenGLMode };
+ enum PaintFlag {
+ PaintingMirrored = 1 << 0,
+ };
+ typedef unsigned PaintFlags;
+
static PassOwnPtr<TextureMapper> create(AccelerationMode newMode = SoftwareMode);
virtual ~TextureMapper() { }
@@ -123,7 +129,7 @@ public:
TextDrawingModeFlags textDrawingMode() const { return m_textDrawingMode; }
virtual AccelerationMode accelerationMode() const = 0;
- virtual void beginPainting() { }
+ virtual void beginPainting(PaintFlags flags = 0) { }
virtual void endPainting() { }
virtual IntSize maxTextureSize() const { return IntSize(INT_MAX, INT_MAX); }
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp
index 37374928d..4c92c597d 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp
@@ -20,8 +20,8 @@
#include "config.h"
#include "TextureMapperAnimation.h"
-#include "CurrentTime.h"
#include "UnitBezier.h"
+#include <wtf/CurrentTime.h>
#if USE(TEXTURE_MAPPER)
namespace WebCore {
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.h b/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.h
index a3f1ca60f..7cb8a7c5a 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.h
@@ -21,8 +21,8 @@
#define TextureMapperAnimation_h
#include "GraphicsLayer.h"
-#include "HashMap.h"
#include "TransformationMatrix.h"
+#include <wtf/HashMap.h>
#include <wtf/text/StringHash.h>
#if USE(TEXTURE_MAPPER)
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp
index 6c3e2d8df..43ac7810b 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp
@@ -26,16 +26,16 @@
namespace WebCore {
-void TextureMapperTile::updateContents(TextureMapper* textureMapper, Image* image, const IntRect& dirtyRect, BitmapTexture::PixelFormat format)
+void TextureMapperTile::updateContents(TextureMapper* textureMapper, Image* image, const IntRect& dirtyRect)
{
IntRect targetRect = enclosingIntRect(m_rect);
targetRect.intersect(dirtyRect);
if (targetRect.isEmpty())
return;
- IntRect sourceRect = targetRect;
+ IntPoint sourceOffset = targetRect.location();
// Normalize sourceRect to the buffer's coordinates.
- sourceRect.move(-dirtyRect.x(), -dirtyRect.y());
+ sourceOffset.move(-dirtyRect.x(), -dirtyRect.y());
// Normalize targetRect to the texture's coordinates.
targetRect.move(-m_rect.x(), -m_rect.y());
@@ -44,7 +44,7 @@ void TextureMapperTile::updateContents(TextureMapper* textureMapper, Image* imag
m_texture->reset(targetRect.size(), image->currentFrameHasAlpha() ? BitmapTexture::SupportsAlpha : 0);
}
- m_texture->updateContents(image, targetRect, sourceRect, format);
+ m_texture->updateContents(image, targetRect, sourceOffset);
}
void TextureMapperTile::paint(TextureMapper* textureMapper, const TransformationMatrix& transform, float opacity, BitmapTexture* mask)
@@ -57,7 +57,7 @@ void TextureMapperTiledBackingStore::updateContentsFromImageIfNeeded(TextureMapp
if (!m_image)
return;
- updateContents(textureMapper, m_image.get(), m_image->currentFrameHasAlpha() ? BitmapTexture::BGRAFormat : BitmapTexture::BGRFormat);
+ updateContents(textureMapper, m_image.get());
m_image.clear();
}
@@ -134,11 +134,11 @@ void TextureMapperTiledBackingStore::createOrDestroyTilesIfNeeded(const FloatSiz
m_tiles.remove(tileIndicesToRemove[i]);
}
-void TextureMapperTiledBackingStore::updateContents(TextureMapper* textureMapper, Image* image, const FloatSize& totalSize, const IntRect& dirtyRect, BitmapTexture::PixelFormat format)
+void TextureMapperTiledBackingStore::updateContents(TextureMapper* textureMapper, Image* image, const FloatSize& totalSize, const IntRect& dirtyRect)
{
createOrDestroyTilesIfNeeded(totalSize, textureMapper->maxTextureSize(), image->currentFrameHasAlpha());
for (size_t i = 0; i < m_tiles.size(); ++i)
- m_tiles[i].updateContents(textureMapper, image, dirtyRect, format);
+ m_tiles[i].updateContents(textureMapper, image, dirtyRect);
}
PassRefPtr<BitmapTexture> TextureMapperTiledBackingStore::texture() const
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h
index 9f056e012..df61b8626 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h
@@ -22,10 +22,11 @@
#include "FloatRect.h"
#include "Image.h"
-#include "RefPtr.h"
#include "TextureMapper.h"
#include "TextureMapperPlatformLayer.h"
+#include <wtf/RefPtr.h>
+
namespace WebCore {
class GraphicsLayer;
@@ -44,7 +45,7 @@ public:
inline void setTexture(BitmapTexture* texture) { m_texture = texture; }
inline void setRect(const FloatRect& rect) { m_rect = rect; }
- void updateContents(TextureMapper*, Image*, const IntRect&, BitmapTexture::PixelFormat);
+ void updateContents(TextureMapper*, Image*, const IntRect&);
virtual void paint(TextureMapper*, const TransformationMatrix&, float, BitmapTexture*);
virtual ~TextureMapperTile() { }
@@ -64,8 +65,8 @@ public:
virtual ~TextureMapperTiledBackingStore() { }
virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix&, float, BitmapTexture*);
virtual PassRefPtr<BitmapTexture> texture() const;
- void updateContents(TextureMapper*, Image*, const FloatSize&, const IntRect&, BitmapTexture::PixelFormat);
- void updateContents(TextureMapper* textureMapper, Image* image, BitmapTexture::PixelFormat format) { updateContents(textureMapper, image, image->size(), image->rect(), format); }
+ void updateContents(TextureMapper*, Image*, const FloatSize&, const IntRect&);
+ void updateContents(TextureMapper* textureMapper, Image* image) { updateContents(textureMapper, image, image->size(), image->rect()); }
inline FloatRect rect() const { return FloatRect(FloatPoint::zero(), m_size); }
static PassRefPtr<TextureMapperTiledBackingStore> create() { return adoptRef(new TextureMapperTiledBackingStore); }
void setContentsToImage(Image* image) { m_image = image; }
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp
index 80cf9fa67..df9b8b03e 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp
@@ -31,13 +31,12 @@
#include <wtf/RefCounted.h>
#if PLATFORM(QT)
-#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
+#if QT_VERSION >= 0x050000
+#include <QOpenGLContext>
#include <QPlatformPixmap>
-#endif
-#endif
-
-#if defined(TEXMAP_OPENGL_ES_2)
-#include <EGL/egl.h>
+#else
+#include <QGLContext>
+#endif // QT_VERSION
#elif OS(WINDOWS)
#include <windows.h>
#elif OS(MAC_OS_X)
@@ -50,34 +49,26 @@
#include "CairoUtilities.h"
#include "RefPtrCairo.h"
#include <cairo.h>
-#include <wtf/ByteArray.h>
#endif
+#define GL_CMD(...) do { __VA_ARGS__; ASSERT_ARG(__VA_ARGS__, !glGetError()); } while (0)
namespace WebCore {
-
-inline static void debugGLCommand(const char* command, int line)
-{
- const GLenum err = glGetError();
- if (!err)
- return;
- WTFReportError(__FILE__, line, WTF_PRETTY_FUNCTION, "[TextureMapper GL] Command failed: %s (%x)\n", command, err);
- ASSERT_NOT_REACHED();
-}
-
-#ifndef NDEBUG
-#define GL_CMD(x) {x, debugGLCommand(#x, __LINE__); }
-#else
-#define GL_CMD(x) x;
-#endif
-
struct TextureMapperGLData {
struct SharedGLData : public RefCounted<SharedGLData> {
-#if defined(TEXMAP_OPENGL_ES_2)
- typedef EGLContext GLContext;
+#if PLATFORM(QT)
+#if QT_VERSION >= 0x050000
+ typedef QOpenGLContext* GLContext;
static GLContext getCurrentGLContext()
{
- return eglGetCurrentContext();
+ return QOpenGLContext::currentContext();
}
+#else
+ typedef const QGLContext* GLContext;
+ static GLContext getCurrentGLContext()
+ {
+ return QGLContext::currentContext();
+ }
+#endif
#elif OS(WINDOWS)
typedef HGLRC GLContext;
static GLContext getCurrentGLContext()
@@ -125,55 +116,7 @@ struct TextureMapperGLData {
return adoptRef(new SharedGLData(getCurrentGLContext()));
}
- struct ClipState {
- IntRect scissorBox;
- int stencilIndex;
- ClipState(const IntRect& scissors, int stencil)
- : scissorBox(scissors)
- , stencilIndex(stencil)
- { }
-
- ClipState()
- : stencilIndex(1)
- { }
- };
-
- ClipState clipState;
- Vector<ClipState> clipStack;
- void pushClipState()
- {
- clipStack.append(clipState);
- }
-
- void popClipState()
- {
- if (clipStack.isEmpty())
- return;
- clipState = clipStack.last();
- clipStack.removeLast();
- }
-
- static void scissorClip(const IntRect& rect)
- {
- if (rect.isEmpty())
- return;
-
- GLint viewport[4];
- GL_CMD(glGetIntegerv(GL_VIEWPORT, viewport))
- GL_CMD(glScissor(rect.x(), viewport[3] - rect.maxY() + 1, rect.width() - 1, rect.height() - 1))
- }
-
- void applyCurrentClip()
- {
- scissorClip(clipState.scissorBox);
- GL_CMD(glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP))
- glStencilFunc(GL_EQUAL, clipState.stencilIndex - 1, clipState.stencilIndex - 1);
- if (clipState.stencilIndex == 1)
- glDisable(GL_STENCIL_TEST);
- else
- glEnable(GL_STENCIL_TEST);
- }
TextureMapperShaderManager textureMapperShaderManager;
@@ -194,7 +137,6 @@ struct TextureMapperGLData {
ASSERT(it != end);
glContextDataMap().remove(it);
}
-
};
SharedGLData& sharedGLData() const
@@ -205,7 +147,9 @@ struct TextureMapperGLData {
void initializeStencil();
TextureMapperGLData()
- : previousProgram(0)
+ : PaintFlags(0)
+ , previousProgram(0)
+ , targetFrameBuffer(0)
, didModifyStencil(false)
, previousScissorState(0)
, previousDepthState(0)
@@ -213,7 +157,9 @@ struct TextureMapperGLData {
{ }
TransformationMatrix projectionMatrix;
+ TextureMapper::PaintFlags PaintFlags;
GLint previousProgram;
+ GLint targetFrameBuffer;
bool didModifyStencil;
GLint previousScissorState;
GLint previousDepthState;
@@ -223,6 +169,47 @@ struct TextureMapperGLData {
RefPtr<BitmapTexture> currentSurface;
};
+void TextureMapperGL::ClipStack::init(const IntRect& rect)
+{
+ clipStack.clear();
+ clipState = TextureMapperGL::ClipState(rect);
+}
+
+void TextureMapperGL::ClipStack::push()
+{
+ clipStack.append(clipState);
+}
+
+void TextureMapperGL::ClipStack::pop()
+{
+ if (clipStack.isEmpty())
+ return;
+ clipState = clipStack.last();
+ clipStack.removeLast();
+}
+
+static void scissorClip(const IntRect& rect)
+{
+ if (rect.isEmpty())
+ return;
+
+ GLint viewport[4];
+ GL_CMD(glGetIntegerv(GL_VIEWPORT, viewport));
+ GL_CMD(glScissor(rect.x(), viewport[3] - rect.maxY(), rect.width(), rect.height()));
+}
+
+void TextureMapperGL::ClipStack::apply()
+{
+ scissorClip(clipState.scissorBox);
+ GL_CMD(glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP));
+ GL_CMD(glStencilFunc(GL_EQUAL, clipState.stencilIndex - 1, clipState.stencilIndex - 1));
+ if (clipState.stencilIndex == 1)
+ GL_CMD(glDisable(GL_STENCIL_TEST));
+ else
+ GL_CMD(glEnable(GL_STENCIL_TEST));
+}
+
+
void TextureMapperGLData::initializeStencil()
{
if (currentSurface) {
@@ -233,18 +220,31 @@ void TextureMapperGLData::initializeStencil()
if (didModifyStencil)
return;
- glClearStencil(0);
- glClear(GL_STENCIL_BUFFER_BIT);
+ GL_CMD(glClearStencil(0));
+ GL_CMD(glClear(GL_STENCIL_BUFFER_BIT));
didModifyStencil = true;
}
+BitmapTextureGL* toBitmapTextureGL(BitmapTexture* texture)
+{
+ if (!texture || !texture->isBackedByOpenGL())
+ return 0;
+
+ return static_cast<BitmapTextureGL*>(texture);
+}
+
TextureMapperGL::TextureMapperGL()
: m_data(new TextureMapperGLData)
, m_context(0)
{
}
-void TextureMapperGL::beginPainting()
+TextureMapperGL::ClipStack& TextureMapperGL::clipStack()
+{
+ return data().currentSurface ? toBitmapTextureGL(data().currentSurface.get())->m_clipStack : m_clipStack;
+}
+
+void TextureMapperGL::beginPainting(PaintFlags flags)
{
// Make sure that no GL error code stays from previous operations.
glGetError();
@@ -252,7 +252,7 @@ void TextureMapperGL::beginPainting()
if (!initializeOpenGLShims())
return;
- glGetIntegerv(GL_CURRENT_PROGRAM, &data().previousProgram);
+ GL_CMD(glGetIntegerv(GL_CURRENT_PROGRAM, &data().previousProgram));
data().previousScissorState = glIsEnabled(GL_SCISSOR_TEST);
data().previousDepthState = glIsEnabled(GL_DEPTH_TEST);
glDisable(GL_DEPTH_TEST);
@@ -265,11 +265,13 @@ void TextureMapperGL::beginPainting()
}
#endif
data().didModifyStencil = false;
- glDepthMask(0);
- glGetIntegerv(GL_VIEWPORT, data().viewport);
- glGetIntegerv(GL_SCISSOR_BOX, data().previousScissor);
- data().sharedGLData().clipState.stencilIndex = 1;
- data().sharedGLData().clipState.scissorBox = IntRect(0, 0, data().viewport[2], data().viewport[3]);
+ GL_CMD(glDepthMask(0));
+ GL_CMD(glGetIntegerv(GL_VIEWPORT, data().viewport));
+ GL_CMD(glGetIntegerv(GL_SCISSOR_BOX, data().previousScissor));
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &data().targetFrameBuffer);
+ m_clipStack.init(IntRect(0, 0, data().viewport[2], data().viewport[3]));
+ GL_CMD(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &data().targetFrameBuffer));
+ data().PaintFlags = flags;
bindSurface(0);
}
@@ -293,7 +295,6 @@ void TextureMapperGL::endPainting()
else
glDisable(GL_DEPTH_TEST);
-
#if PLATFORM(QT)
if (!m_context)
return;
@@ -309,28 +310,28 @@ void TextureMapperGL::drawTexture(const BitmapTexture& texture, const FloatRect&
if (!texture.isValid())
return;
- if (data().sharedGLData().clipState.scissorBox.isEmpty())
+ if (clipStack().current().scissorBox.isEmpty())
return;
const BitmapTextureGL& textureGL = static_cast<const BitmapTextureGL&>(texture);
- drawTexture(textureGL.id(), textureGL.isOpaque() ? 0 : SupportsBlending, textureGL.relativeSize(), targetRect, matrix, opacity, mask);
+ drawTexture(textureGL.id(), textureGL.isOpaque() ? 0 : SupportsBlending, textureGL.size(), targetRect, matrix, opacity, mask);
}
-void TextureMapperGL::drawTexture(uint32_t texture, Flags flags, const FloatSize& relativeSize, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture)
+void TextureMapperGL::drawTexture(uint32_t texture, Flags flags, const IntSize& textureSize, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture)
{
RefPtr<TextureMapperShaderProgram> shaderInfo;
if (maskTexture)
- shaderInfo = data().sharedGLData().textureMapperShaderManager.getShaderProgram<TextureMapperShaderProgramOpacityAndMask>();
+ shaderInfo = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::OpacityAndMask);
else
- shaderInfo = data().sharedGLData().textureMapperShaderManager.getShaderProgram<TextureMapperShaderProgramSimple>();
+ shaderInfo = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Simple);
- GL_CMD(glUseProgram(shaderInfo->id()))
- GL_CMD(glEnableVertexAttribArray(shaderInfo->vertexAttrib()))
- GL_CMD(glActiveTexture(GL_TEXTURE0))
- GL_CMD(glBindTexture(GL_TEXTURE_2D, texture))
- GL_CMD(glBindBuffer(GL_ARRAY_BUFFER, 0))
+ GL_CMD(glUseProgram(shaderInfo->id()));
+ GL_CMD(glEnableVertexAttribArray(shaderInfo->vertexAttrib()));
+ GL_CMD(glActiveTexture(GL_TEXTURE0));
+ GL_CMD(glBindTexture(GL_TEXTURE_2D, texture));
+ GL_CMD(glBindBuffer(GL_ARRAY_BUFFER, 0));
const GLfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1};
- GL_CMD(glVertexAttribPointer(shaderInfo->vertexAttrib(), 2, GL_FLOAT, GL_FALSE, 0, unitRect))
+ GL_CMD(glVertexAttribPointer(shaderInfo->vertexAttrib(), 2, GL_FLOAT, GL_FALSE, 0, unitRect));
TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix).multiply(modelViewMatrix).multiply(TransformationMatrix(
targetRect.width(), 0, 0, 0,
@@ -344,27 +345,29 @@ void TextureMapperGL::drawTexture(uint32_t texture, Flags flags, const FloatSize
matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()
};
- const GLfloat m4src[] = {relativeSize.width(), 0, 0, 0,
- 0, relativeSize.height() * ((flags & ShouldFlipTexture) ? -1 : 1), 0, 0,
- 0, 0, 1, 0,
- 0, (flags & ShouldFlipTexture) ? relativeSize.height() : 0, 0, 1};
- GL_CMD(glUniformMatrix4fv(shaderInfo->matrixVariable(), 1, GL_FALSE, m4))
- GL_CMD(glUniformMatrix4fv(shaderInfo->sourceMatrixVariable(), 1, GL_FALSE, m4src))
- GL_CMD(glUniform1i(shaderInfo->sourceTextureVariable(), 0))
+ const GLfloat m4src[] = {
+ 1, 0, 0, 0,
+ 0, (flags & ShouldFlipTexture) ? -1 : 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, (flags & ShouldFlipTexture) ? 1 : 0, 0, 1};
+
+ GL_CMD(glUniformMatrix4fv(shaderInfo->matrixVariable(), 1, GL_FALSE, m4));
+ GL_CMD(glUniformMatrix4fv(shaderInfo->sourceMatrixVariable(), 1, GL_FALSE, m4src));
+ GL_CMD(glUniform1i(shaderInfo->sourceTextureVariable(), 0));
shaderInfo->prepare(opacity, maskTexture);
bool needsBlending = (flags & SupportsBlending) || opacity < 0.99 || maskTexture;
if (needsBlending) {
- GL_CMD(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA))
- GL_CMD(glEnable(GL_BLEND))
+ GL_CMD(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
+ GL_CMD(glEnable(GL_BLEND));
} else
- GL_CMD(glDisable(GL_BLEND))
+ GL_CMD(glDisable(GL_BLEND));
- GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4))
- GL_CMD(glDisableVertexAttribArray(shaderInfo->vertexAttrib()))
+ GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4));
+ GL_CMD(glDisableVertexAttribArray(shaderInfo->vertexAttrib()));
}
const char* TextureMapperGL::type() const
@@ -372,87 +375,118 @@ const char* TextureMapperGL::type() const
return "OpenGL";
}
-void BitmapTextureGL::didReset()
+bool BitmapTextureGL::canReuseWith(const IntSize& contentsSize, Flags)
{
- IntSize newTextureSize = nextPowerOfTwo(contentSize());
- bool justCreated = false;
- if (!m_id) {
- GL_CMD(glGenTextures(1, &m_id))
- justCreated = true;
- }
-
- if (justCreated || newTextureSize.width() > m_textureSize.width() || newTextureSize.height() > m_textureSize.height()) {
- m_textureSize = newTextureSize;
- GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id))
- GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR))
- GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR))
- GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE))
- GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE))
- GL_CMD(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_textureSize.width(), m_textureSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0))
- }
-
- // We decrease the size by one, since this is used as rectangle coordinates and not as size.
- m_relativeSize = FloatSize(float(contentSize().width() - 1) / m_textureSize.width(), float(contentSize().height() - 1) / m_textureSize.height());
- m_surfaceNeedsReset = true;
+ return contentsSize == m_textureSize;
}
-static void swizzleBGRAToRGBA(uint32_t* data, const IntSize& size)
+#if OS(DARWIN)
+#define DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
+#else
+#define DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE GL_UNSIGNED_BYTE
+#endif
+
+static void swizzleBGRAToRGBA(uint32_t* data, const IntRect& rect, int stride = 0)
{
- int width = size.width();
- int height = size.height();
- for (int y = 0; y < height; ++y) {
- uint32_t* p = data + y * width;
- for (int x = 0; x < width; ++x)
+ stride = stride ? stride : rect.width();
+ for (int y = rect.y(); y < rect.maxY(); ++y) {
+ uint32_t* p = data + y * stride;
+ for (int x = rect.x(); x < rect.maxX(); ++x)
p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
}
}
-// FIXME: Move this to Extensions3D when we move TextureMapper to use GC3D.
-static bool hasExtension(const char* extension)
+static bool driverSupportsBGRASwizzling()
{
- static Vector<String> availableExtensions;
- if (!availableExtensions.isEmpty())
- return availableExtensions.contains(extension);
- String extensionsString(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
- extensionsString.split(" ", availableExtensions);
- return availableExtensions.contains(extension);
+#if defined(TEXMAP_OPENGL_ES_2)
+ // FIXME: Implement reliable detection. See also https://bugs.webkit.org/show_bug.cgi?id=81103.
+ return false;
+#else
+ return true;
+#endif
}
-static bool hasBGRAExtension()
+
+static bool driverSupportsSubImage()
{
-#if !defined(TEXMAP_OPENGL_ES_2)
+#if defined(TEXMAP_OPENGL_ES_2)
+ // FIXME: Implement reliable detection.
+ return false;
+#else
return true;
#endif
- static bool hasBGRA = hasExtension("GL_EXT_texture_format_BGRA8888");
- return hasBGRA;
}
-void BitmapTextureGL::updateContents(const void* data, const IntRect& targetRect)
+void BitmapTextureGL::didReset()
+{
+ if (!m_id)
+ GL_CMD(glGenTextures(1, &m_id));
+
+ m_shouldClear = true;
+ if (m_textureSize == contentSize())
+ return;
+
+ GLuint format = driverSupportsBGRASwizzling() ? GL_BGRA : GL_RGBA;
+
+ m_textureSize = contentSize();
+ GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id));
+ GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+ GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+ GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+ GL_CMD(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_textureSize.width(), m_textureSize.height(), 0, format, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, 0));
+}
+
+
+void BitmapTextureGL::updateContents(const void* data, const IntRect& targetRect, const IntPoint& sourceOffset, int bytesPerLine)
{
GLuint glFormat = GL_RGBA;
- GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id))
- if (hasBGRAExtension())
+ GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id));
+
+ if (driverSupportsBGRASwizzling())
glFormat = GL_BGRA;
- else {
- swizzleBGRAToRGBA(static_cast<uint32_t*>(const_cast<void*>(data)), targetRect.size());
- glFormat = GL_RGBA;
+ else
+ swizzleBGRAToRGBA(reinterpret_cast<uint32_t*>(const_cast<void*>(data)), IntRect(sourceOffset, targetRect.size()), bytesPerLine / 4);
+
+ if (bytesPerLine == targetRect.width() / 4 && sourceOffset == IntPoint::zero()) {
+ GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, (const char*)data));
+ return;
}
- GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, GL_UNSIGNED_BYTE, data))
+ // For ES drivers that don't support sub-images, transfer the pixels row-by-row.
+ if (!driverSupportsSubImage()) {
+ const char* bits = static_cast<const char*>(data);
+ for (int y = 0; y < targetRect.height(); ++y) {
+ const char *row = bits + ((sourceOffset.y() + y) * bytesPerLine + sourceOffset.x() * 4);
+ GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, targetRect.x(), targetRect.y() + y, targetRect.width(), 1, glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, row));
+ }
+ return;
+ }
+
+#if !defined(TEXMAP_OPENGL_ES_2)
+ // Use the OpenGL sub-image extension, now that we know it's available.
+ GL_CMD(glPixelStorei(GL_UNPACK_ROW_LENGTH, bytesPerLine / 4));
+ GL_CMD(glPixelStorei(GL_UNPACK_SKIP_ROWS, sourceOffset.y()));
+ GL_CMD(glPixelStorei(GL_UNPACK_SKIP_PIXELS, sourceOffset.x()));
+ GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, (const char*)data));
+ GL_CMD(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
+ GL_CMD(glPixelStorei(GL_UNPACK_SKIP_ROWS, 0));
+ GL_CMD(glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0));
+#endif
}
-void BitmapTextureGL::updateContents(Image* image, const IntRect& targetRect, const IntRect& sourceRect, BitmapTexture::PixelFormat format)
+void BitmapTextureGL::updateContents(Image* image, const IntRect& targetRect, const IntPoint& offset)
{
if (!image)
return;
- GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id))
- GLuint glFormat = isOpaque() ? GL_RGB : GL_RGBA;
NativeImagePtr frameImage = image->nativeImageForCurrentFrame();
if (!frameImage)
return;
+ int bytesPerLine;
+ const char* imageData;
+
#if PLATFORM(QT)
QImage qtImage;
-
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
// With QPA, we can avoid a deep copy.
qtImage = *frameImage->handle()->buffer();
@@ -460,51 +494,70 @@ void BitmapTextureGL::updateContents(Image* image, const IntRect& targetRect, co
// This might be a deep copy, depending on other references to the pixmap.
qtImage = frameImage->toImage();
#endif
+ imageData = reinterpret_cast<const char*>(qtImage.constBits());
+ bytesPerLine = qtImage.bytesPerLine();
+#elif USE(CAIRO)
+ cairo_surface_t* surface = frameImage->surface();
+ imageData = reinterpret_cast<const char*>(cairo_image_surface_get_data(surface));
+ bytesPerLine = cairo_image_surface_get_stride(surface);
+#endif
+
+ updateContents(imageData, targetRect, offset, bytesPerLine);
+}
- if (IntSize(qtImage.size()) != sourceRect.size())
- qtImage = qtImage.copy(sourceRect);
- if (format == BGRAFormat || format == BGRFormat) {
- if (hasBGRAExtension())
- glFormat = isOpaque() ? GL_BGR : GL_BGRA;
- else
- swizzleBGRAToRGBA(reinterpret_cast<uint32_t*>(qtImage.bits()), qtImage.size());
+#if ENABLE(CSS_FILTERS)
+void TextureMapperGL::drawFiltered(const BitmapTexture& sourceTexture, const BitmapTexture& contentTexture, const FilterOperation& filter)
+{
+ // For standard filters, we always draw the whole texture without transformations.
+ RefPtr<StandardFilterProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderForFilter(filter);
+ if (!program) {
+ drawTexture(sourceTexture, FloatRect(FloatPoint::zero(), sourceTexture.size()), TransformationMatrix(), 1, 0);
+ return;
}
- GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, GL_UNSIGNED_BYTE, qtImage.constBits()))
+ GL_CMD(glEnableVertexAttribArray(program->vertexAttrib()));
+ GL_CMD(glEnableVertexAttribArray(program->texCoordAttrib()));
+ GL_CMD(glActiveTexture(GL_TEXTURE0));
+ GL_CMD(glBindTexture(GL_TEXTURE_2D, static_cast<const BitmapTextureGL&>(sourceTexture).id()));
+ glUniform1i(program->textureUniform(), 0);
+ const GLfloat targetVertices[] = {-1, -1, 1, -1, 1, 1, -1, 1};
+ const GLfloat sourceVertices[] = {0, 0, 1, 0, 1, 1, 0, 1};
+ GL_CMD(glVertexAttribPointer(program->vertexAttrib(), 2, GL_FLOAT, GL_FALSE, 0, targetVertices));
+ GL_CMD(glVertexAttribPointer(program->texCoordAttrib(), 2, GL_FLOAT, GL_FALSE, 0, sourceVertices));
+ GL_CMD(glDisable(GL_BLEND));
+ GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4));
+ GL_CMD(glDisableVertexAttribArray(program->vertexAttrib()));
+ GL_CMD(glDisableVertexAttribArray(program->texCoordAttrib()));
+}
-#elif USE(CAIRO)
+PassRefPtr<BitmapTexture> BitmapTextureGL::applyFilters(const BitmapTexture& contentTexture, const FilterOperations& filters)
+{
+ RefPtr<BitmapTexture> previousSurface = m_textureMapper->data().currentSurface;
-#if !CPU(BIG_ENDIAN)
-#if defined(TEXMAP_OPENGL_ES_2)
- swizzleBGRAToRGBA(reinterpret_cast<uint32_t*>(cairo_image_surface_get_data(frameImage)),
- cairo_image_surface_get_stride(frameImage) * cairo_image_surface_get_height(frameImage));
-#else
- glFormat = isOpaque() ? GL_BGR : GL_BGRA;
-#endif
-#endif
+ RefPtr<BitmapTexture> source = this;
+ RefPtr<BitmapTexture> target = m_textureMapper->acquireTextureFromPool(m_textureSize);
+ for (int i = 0; i < filters.size(); ++i) {
+ const FilterOperation* filter = filters.at(i);
+ ASSERT(filter);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, cairo_image_surface_get_stride(frameImage) / 4);
- glPixelStorei(GL_UNPACK_SKIP_ROWS, sourceRect.y());
- glPixelStorei(GL_UNPACK_SKIP_PIXELS, sourceRect.x());
- GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0,
- targetRect.x(), targetRect.y(),
- targetRect.width(), targetRect.height(),
- glFormat, GL_UNSIGNED_BYTE,
- cairo_image_surface_get_data(frameImage)));
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
- glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
-#endif
+ m_textureMapper->bindSurface(target.get());
+ m_textureMapper->drawFiltered(i ? *source.get() : contentTexture, contentTexture, *filter);
+ std::swap(source, target);
+ }
+
+ m_textureMapper->bindSurface(previousSurface.get());
+ return source;
}
+#endif
-static inline TransformationMatrix createProjectionMatrix(const IntSize& size, bool flip)
+static inline TransformationMatrix createProjectionMatrix(const IntSize& size, bool mirrored)
{
const float near = 9999999;
const float far = -99999;
return TransformationMatrix(2.0 / float(size.width()), 0, 0, 0,
- 0, (flip ? -2.0 : 2.0) / float(size.height()), 0, 0,
+ 0, (mirrored ? 2.0 : -2.0) / float(size.height()), 0, 0,
0, 0, -2.f / (far - near), 0,
- -1, flip ? 1 : -1, -(far + near) / (far - near), 1);
+ -1, mirrored ? -1 : 1, -(far + near) / (far - near), 1);
}
void BitmapTextureGL::initializeStencil()
@@ -512,53 +565,62 @@ void BitmapTextureGL::initializeStencil()
if (m_rbo)
return;
GL_CMD(glGenRenderbuffers(1, &m_rbo));
- GL_CMD(glBindRenderbuffer(GL_RENDERBUFFER, m_rbo))
+ GL_CMD(glBindRenderbuffer(GL_RENDERBUFFER, m_rbo));
#ifdef TEXMAP_OPENGL_ES_2
- GL_CMD(glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, m_textureSize.width(), m_textureSize.height()))
+ GL_CMD(glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, m_textureSize.width(), m_textureSize.height()));
#else
- GL_CMD(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, m_textureSize.width(), m_textureSize.height()))
+ GL_CMD(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, m_textureSize.width(), m_textureSize.height()));
#endif
- GL_CMD(glBindRenderbuffer(GL_RENDERBUFFER, 0))
- GL_CMD(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_rbo))
- GL_CMD(glClearStencil(0))
- GL_CMD(glClear(GL_STENCIL_BUFFER_BIT))
+ GL_CMD(glBindRenderbuffer(GL_RENDERBUFFER, 0));
+ GL_CMD(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_rbo));
+ GL_CMD(glClearStencil(0));
+ GL_CMD(glClear(GL_STENCIL_BUFFER_BIT));
}
-void BitmapTextureGL::bind()
+void BitmapTextureGL::clearIfNeeded()
{
- if (m_surfaceNeedsReset || !m_fbo) {
- if (!m_fbo)
- GL_CMD(glGenFramebuffers(1, &m_fbo))
- GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo))
- GL_CMD(glBindTexture(GL_TEXTURE_2D, 0))
- GL_CMD(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id(), 0))
- GL_CMD(glClearColor(0, 0, 0, 0))
- GL_CMD(glClear(GL_COLOR_BUFFER_BIT))
- m_surfaceNeedsReset = false;
- } else
- GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo))
+ if (!m_shouldClear)
+ return;
- GL_CMD(glViewport(0, 0, size().width(), size().height()))
- m_textureMapper->data().projectionMatrix = createProjectionMatrix(size(), false);
- m_textureMapper->beginClip(TransformationMatrix(), FloatRect(IntPoint::zero(), contentSize()));
+ m_clipStack.init(IntRect(IntPoint::zero(), m_textureSize));
+ m_clipStack.apply();
+ GL_CMD(glClearColor(0, 0, 0, 0));
+ GL_CMD(glClear(GL_COLOR_BUFFER_BIT));
+ m_shouldClear = false;
}
-void BitmapTextureGL::destroy()
+void BitmapTextureGL::createFboIfNeeded()
+{
+ if (m_fbo)
+ return;
+
+ GL_CMD(glGenFramebuffers(1, &m_fbo));
+ GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo));
+ GL_CMD(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id(), 0));
+ m_shouldClear = true;
+}
+
+void BitmapTextureGL::bind()
+{
+ GL_CMD(glBindTexture(GL_TEXTURE_2D, 0));
+ createFboIfNeeded();
+ GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo));
+ GL_CMD(glViewport(0, 0, m_textureSize.width(), m_textureSize.height()));
+ clearIfNeeded();
+ m_textureMapper->data().projectionMatrix = createProjectionMatrix(m_textureSize, true /* mirrored */);
+ m_clipStack.apply();
+}
+
+BitmapTextureGL::~BitmapTextureGL()
{
if (m_id)
- GL_CMD(glDeleteTextures(1, &m_id))
+ GL_CMD(glDeleteTextures(1, &m_id));
if (m_fbo)
- GL_CMD(glDeleteFramebuffers(1, &m_fbo))
+ GL_CMD(glDeleteFramebuffers(1, &m_fbo));
if (m_rbo)
- GL_CMD(glDeleteRenderbuffers(1, &m_rbo))
-
- m_fbo = 0;
- m_rbo = 0;
- m_id = 0;
- m_textureSize = IntSize();
- m_relativeSize = FloatSize(1, 1);
+ GL_CMD(glDeleteRenderbuffers(1, &m_rbo));
}
bool BitmapTextureGL::isValid() const
@@ -576,28 +638,34 @@ TextureMapperGL::~TextureMapperGL()
delete m_data;
}
-void TextureMapperGL::bindSurface(BitmapTexture *surfacePointer)
+void TextureMapperGL::bindDefaultSurface()
{
- BitmapTextureGL* surface = static_cast<BitmapTextureGL*>(surfacePointer);
+ GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, data().targetFrameBuffer));
+ IntSize viewportSize(data().viewport[2], data().viewport[3]);
+ data().projectionMatrix = createProjectionMatrix(viewportSize, data().PaintFlags & PaintingMirrored);
+ GL_CMD(glViewport(data().viewport[0], data().viewport[1], viewportSize.width(), viewportSize.height()));
+ m_clipStack.apply();
+ data().currentSurface.clear();
+}
+void TextureMapperGL::bindSurface(BitmapTexture *surface)
+{
if (!surface) {
- IntSize viewportSize(data().viewport[2], data().viewport[3]);
- GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, 0))
- data().projectionMatrix = createProjectionMatrix(viewportSize, true);
- GL_CMD(glViewport(0, 0, viewportSize.width(), viewportSize.height()))
- if (data().currentSurface)
- endClip();
- data().currentSurface.clear();
+ bindDefaultSurface();
return;
}
-
- surface->bind();
+ static_cast<BitmapTextureGL*>(surface)->bind();
data().currentSurface = surface;
}
bool TextureMapperGL::beginScissorClip(const TransformationMatrix& modelViewMatrix, const FloatRect& targetRect)
{
+ // 3D transforms are currently not supported in scissor clipping
+ // resulting in cropped surfaces when z>0.
+ if (!modelViewMatrix.isAffine())
+ return false;
+
FloatQuad quad = modelViewMatrix.projectQuad(targetRect);
IntRect rect = quad.enclosingBoundingBox();
@@ -605,25 +673,25 @@ bool TextureMapperGL::beginScissorClip(const TransformationMatrix& modelViewMatr
if (!quad.isRectilinear() || rect.isEmpty())
return false;
- data().sharedGLData().clipState.scissorBox.intersect(rect);
- data().sharedGLData().applyCurrentClip();
+ clipStack().current().scissorBox.intersect(rect);
+ clipStack().apply();
return true;
}
void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, const FloatRect& targetRect)
{
- data().sharedGLData().pushClipState();
+ clipStack().push();
if (beginScissorClip(modelViewMatrix, targetRect))
return;
data().initializeStencil();
- RefPtr<TextureMapperShaderProgramSimple> shaderInfo = data().sharedGLData().textureMapperShaderManager.getShaderProgram<TextureMapperShaderProgramSimple>();
+ RefPtr<TextureMapperShaderProgram> shaderInfo = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Simple);
- GL_CMD(glUseProgram(shaderInfo->id()))
- GL_CMD(glEnableVertexAttribArray(shaderInfo->vertexAttrib()))
+ GL_CMD(glUseProgram(shaderInfo->id()));
+ GL_CMD(glEnableVertexAttribArray(shaderInfo->vertexAttrib()));
const GLfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1};
- GL_CMD(glVertexAttribPointer(shaderInfo->vertexAttrib(), 2, GL_FLOAT, GL_FALSE, 0, unitRect))
+ GL_CMD(glVertexAttribPointer(shaderInfo->vertexAttrib(), 2, GL_FLOAT, GL_FALSE, 0, unitRect));
TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix)
.multiply(modelViewMatrix)
@@ -646,39 +714,39 @@ void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, con
-1, -1, 0, 1
};
- int& stencilIndex = data().sharedGLData().clipState.stencilIndex;
+ int& stencilIndex = clipStack().current().stencilIndex;
- GL_CMD(glEnable(GL_STENCIL_TEST))
+ GL_CMD(glEnable(GL_STENCIL_TEST));
// Make sure we don't do any actual drawing.
- GL_CMD(glStencilFunc(GL_NEVER, stencilIndex, stencilIndex))
+ GL_CMD(glStencilFunc(GL_NEVER, stencilIndex, stencilIndex));
// Operate only on the stencilIndex and above.
- GL_CMD(glStencilMask(0xff & ~(stencilIndex - 1)))
+ GL_CMD(glStencilMask(0xff & ~(stencilIndex - 1)));
// First clear the entire buffer at the current index.
- GL_CMD(glUniformMatrix4fv(shaderInfo->matrixVariable(), 1, GL_FALSE, m4all))
- GL_CMD(glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO))
- GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4))
+ GL_CMD(glUniformMatrix4fv(shaderInfo->matrixVariable(), 1, GL_FALSE, m4all));
+ GL_CMD(glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
+ GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4));
// Now apply the current index to the new quad.
- GL_CMD(glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE))
- GL_CMD(glUniformMatrix4fv(shaderInfo->matrixVariable(), 1, GL_FALSE, m4))
- GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4))
+ GL_CMD(glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE));
+ GL_CMD(glUniformMatrix4fv(shaderInfo->matrixVariable(), 1, GL_FALSE, m4));
+ GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4));
// Clear the state.
- GL_CMD(glDisableVertexAttribArray(shaderInfo->vertexAttrib()))
- GL_CMD(glStencilMask(0))
+ GL_CMD(glDisableVertexAttribArray(shaderInfo->vertexAttrib()));
+ GL_CMD(glStencilMask(0));
// Increase stencilIndex and apply stencil testing.
stencilIndex *= 2;
- data().sharedGLData().applyCurrentClip();
+ clipStack().apply();
}
void TextureMapperGL::endClip()
{
- data().sharedGLData().popClipState();
- data().sharedGLData().applyCurrentClip();
+ clipStack().pop();
+ clipStack().apply();
}
PassRefPtr<BitmapTexture> TextureMapperGL::createTexture()
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h
index 9e474015b..4279499fc 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h
@@ -49,10 +49,10 @@ public:
// reimps from TextureMapper
virtual void drawTexture(const BitmapTexture&, const FloatRect&, const TransformationMatrix&, float opacity, const BitmapTexture* maskTexture);
- virtual void drawTexture(uint32_t texture, Flags, const FloatSize&, const FloatRect&, const TransformationMatrix&, float opacity, const BitmapTexture* maskTexture);
+ virtual void drawTexture(uint32_t texture, Flags, const IntSize& textureSize, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture);
virtual void bindSurface(BitmapTexture* surface);
virtual void beginClip(const TransformationMatrix&, const FloatRect&);
- virtual void beginPainting();
+ virtual void beginPainting(PaintFlags = 0);
virtual void endPainting();
virtual void endClip();
virtual IntSize maxTextureSize() { return IntSize(2000, 2000); }
@@ -62,75 +62,98 @@ public:
void setGraphicsContext(GraphicsContext* context) { m_context = context; }
GraphicsContext* graphicsContext() { return m_context; }
virtual bool isOpenGLBacked() const { return true; }
- void platformUpdateContents(NativeImagePtr, const IntRect&, const IntRect&, BitmapTexture::PixelFormat);
+ void platformUpdateContents(NativeImagePtr, const IntRect&, const IntRect&);
virtual AccelerationMode accelerationMode() const { return OpenGLMode; }
+#if ENABLE(CSS_FILTERS)
+ void drawFiltered(const BitmapTexture& sourceTexture, const BitmapTexture& contentTexture, const FilterOperation&);
+#endif
+
+
private:
+
+ struct ClipState {
+ IntRect scissorBox;
+ int stencilIndex;
+ ClipState(const IntRect& scissors = IntRect(), int stencil = 1)
+ : scissorBox(scissors)
+ , stencilIndex(stencil)
+ { }
+ };
+
+ class ClipStack {
+ public:
+ void push();
+ void pop();
+ void apply();
+ inline ClipState& current() { return clipState; }
+ void init(const IntRect&);
+
+ private:
+ ClipState clipState;
+ Vector<ClipState> clipStack;
+ };
+
bool beginScissorClip(const TransformationMatrix&, const FloatRect&);
+ void bindDefaultSurface();
+ ClipStack& clipStack();
inline TextureMapperGLData& data() { return *m_data; }
TextureMapperGLData* m_data;
GraphicsContext* m_context;
+ ClipStack m_clipStack;
friend class BitmapTextureGL;
};
class BitmapTextureGL : public BitmapTexture {
public:
- virtual void destroy();
virtual IntSize size() const;
virtual bool isValid() const;
+ virtual bool canReuseWith(const IntSize& contentsSize, Flags = 0);
virtual void didReset();
void bind();
void initializeStencil();
- ~BitmapTextureGL() { destroy(); }
+ ~BitmapTextureGL();
virtual uint32_t id() const { return m_id; }
- inline FloatSize relativeSize() const { return m_relativeSize; }
+ uint32_t textureTarget() const { return GL_TEXTURE_2D; }
+ IntSize textureSize() const { return m_textureSize; }
void setTextureMapper(TextureMapperGL* texmap) { m_textureMapper = texmap; }
- void updateContents(Image*, const IntRect&, const IntRect&, PixelFormat);
- void updateContents(const void*, const IntRect&);
+ void updateContents(Image*, const IntRect&, const IntPoint&);
+ virtual void updateContents(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine);
+ virtual bool isBackedByOpenGL() const { return true; }
+
+#if ENABLE(CSS_FILTERS)
+ virtual PassRefPtr<BitmapTexture> applyFilters(const BitmapTexture& contentTexture, const FilterOperations&);
+#endif
private:
GLuint m_id;
- FloatSize m_relativeSize;
IntSize m_textureSize;
IntRect m_dirtyRect;
GLuint m_fbo;
GLuint m_rbo;
- bool m_surfaceNeedsReset;
+ bool m_shouldClear;
TextureMapperGL* m_textureMapper;
+ TextureMapperGL::ClipStack m_clipStack;
BitmapTextureGL()
: m_id(0)
, m_fbo(0)
, m_rbo(0)
- , m_surfaceNeedsReset(true)
+ , m_shouldClear(true)
, m_textureMapper(0)
{
}
+ void clearIfNeeded();
+ void createFboIfNeeded();
+
friend class TextureMapperGL;
};
-// An offscreen buffer to be rendered by software.
-static inline int nextPowerOfTwo(int num)
-{
- for (int i = 0x10000000; i > 0; i >>= 1) {
- if (num == i)
- return num;
- if (num & i)
- return (i << 1);
- }
- return 1;
-}
-
-static inline IntSize nextPowerOfTwo(const IntSize& size)
-{
- return IntSize(nextPowerOfTwo(size.width()), nextPowerOfTwo(size.height()));
-}
-
typedef uint64_t ImageUID;
ImageUID uidForImage(Image*);
+BitmapTextureGL* toBitmapTextureGL(BitmapTexture*);
-};
-
+}
#endif
#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp
index e53b9f8d6..208b5349f 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp
@@ -25,14 +25,15 @@
#if USE(TEXTURE_MAPPER)
namespace WebCore {
-void BitmapTextureImageBuffer::updateContents(const void* data, const IntRect& targetRect)
+void BitmapTextureImageBuffer::updateContents(const void* data, const IntRect& targetRect, const IntPoint& sourceOffset, int bytesPerLine)
{
#if PLATFORM(QT)
- QImage image(reinterpret_cast<const uchar*>(data), targetRect.width(), targetRect.height(), targetRect.width() * 4, QImage::Format_ARGB32_Premultiplied);
+ QImage image(reinterpret_cast<const uchar*>(data), targetRect.width(), targetRect.height(), bytesPerLine, QImage::Format_ARGB32_Premultiplied);
+
QPainter* painter = m_image->context()->platformContext();
painter->save();
painter->setCompositionMode(QPainter::CompositionMode_Source);
- painter->drawImage(targetRect, image);
+ painter->drawImage(targetRect, image, IntRect(sourceOffset, targetRect.size()));
painter->restore();
#endif
}
@@ -42,9 +43,9 @@ void BitmapTextureImageBuffer::didReset()
m_image = ImageBuffer::create(contentSize());
}
-void BitmapTextureImageBuffer::updateContents(Image* image, const IntRect& targetRect, const IntRect& sourceRect, PixelFormat)
+void BitmapTextureImageBuffer::updateContents(Image* image, const IntRect& targetRect, const IntPoint& offset)
{
- m_image->context()->drawImage(image, ColorSpaceDeviceRGB, targetRect, sourceRect, CompositeCopy);
+ m_image->context()->drawImage(image, ColorSpaceDeviceRGB, targetRect, IntRect(offset, targetRect.size()), CompositeCopy);
}
void TextureMapperImageBuffer::beginClip(const TransformationMatrix& matrix, const FloatRect& rect)
@@ -109,18 +110,19 @@ void TextureMapperImageBuffer::drawTexture(const BitmapTexture& texture, const F
}
#if ENABLE(CSS_FILTERS)
-void BitmapTextureImageBuffer::applyFilters(const BitmapTexture& contentTexture, const FilterOperations& filters)
+PassRefPtr<BitmapTexture> BitmapTextureImageBuffer::applyFilters(const BitmapTexture& contentTexture, const FilterOperations& filters)
{
- RefPtr<FilterEffectRenderer> renderer = FilterEffectRenderer::create(0);
+ RefPtr<FilterEffectRenderer> renderer = FilterEffectRenderer::create();
renderer->setSourceImageRect(FloatRect(FloatPoint::zero(), contentTexture.size()));
// The document parameter is only needed for CSS shaders.
renderer->build(0 /*document */, filters);
- renderer->prepare();
+ renderer->allocateBackingStoreIfNeeded();
GraphicsContext* context = renderer->inputContext();
context->drawImageBuffer(static_cast<const BitmapTextureImageBuffer&>(contentTexture).m_image.get(), ColorSpaceDeviceRGB, IntPoint::zero());
renderer->apply();
m_image->context()->drawImageBuffer(renderer->output(), ColorSpaceDeviceRGB, renderer->outputRect());
+ return this;
}
#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h
index 22e67df5b..8a035628e 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h
@@ -30,16 +30,14 @@ class BitmapTextureImageBuffer : public BitmapTexture {
friend class TextureMapperImageBuffer;
public:
static PassRefPtr<BitmapTexture> create() { return adoptRef(new BitmapTextureImageBuffer); }
- ~BitmapTextureImageBuffer() { destroy(); }
- virtual void destroy() { m_image.clear(); }
virtual IntSize size() const { return m_image->internalSize(); }
virtual void didReset();
virtual bool isValid() const { return m_image; }
inline GraphicsContext* graphicsContext() { return m_image ? m_image->context() : 0; }
- virtual void updateContents(Image*, const IntRect&, const IntRect&, PixelFormat);
- void updateContents(const void* data, const IntRect& targetRect);
+ virtual void updateContents(Image*, const IntRect&, const IntPoint&);
+ virtual void updateContents(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine);
#if ENABLE(CSS_FILTERS)
- void applyFilters(const BitmapTexture&, const FilterOperations&);
+ PassRefPtr<BitmapTexture> applyFilters(const BitmapTexture&, const FilterOperations&);
#endif
private:
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp
index da0b40e36..4b996e98d 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp
@@ -26,7 +26,8 @@
#include "GraphicsLayerTextureMapper.h"
#include "ImageBuffer.h"
-#include "MathExtras.h"
+
+#include <wtf/MathExtras.h>
namespace WebCore {
@@ -130,7 +131,9 @@ void TextureMapperLayer::updateBackingStore(TextureMapper* textureMapper, Graphi
image = imageBuffer->copyImage(CopyBackingStore);
#endif
- static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get())->updateContents(textureMapper, image.get(), m_size, dirtyRect, BitmapTexture::BGRAFormat);
+ static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get())->updateContents(textureMapper, image.get(), m_size, dirtyRect);
+ m_state.needsDisplay = false;
+ m_state.needsDisplayRect = IntRect();
}
void TextureMapperLayer::paint()
@@ -146,10 +149,10 @@ void TextureMapperLayer::paint()
void TextureMapperLayer::paintSelf(const TextureMapperPaintOptions& options)
{
// We apply the following transform to compensate for painting into a surface, and then apply the offset so that the painting fits in the target rect.
- TransformationMatrix transform =
- TransformationMatrix(options.transform)
- .multiply(m_transform.combined())
- .translate(options.offset.width(), options.offset.height());
+ TransformationMatrix transform;
+ transform.translate(options.offset.width(), options.offset.height());
+ transform.multiply(options.transform);
+ transform.multiply(m_transform.combined());
float opacity = options.opacity;
RefPtr<BitmapTexture> mask = options.mask;
@@ -213,6 +216,23 @@ IntRect TextureMapperLayer::intermediateSurfaceRect(const TransformationMatrix&
return rect;
}
+TextureMapperLayer::ContentsLayerCount TextureMapperLayer::countPotentialLayersWithContents() const
+{
+ int selfLayersWithContents = (m_state.drawsContent ? 1 : 0) + (m_contentsLayer ? 1 : 0);
+ int potentialLayersWithContents = selfLayersWithContents + m_children.size();
+
+ if (!potentialLayersWithContents)
+ return NoLayersWithContent;
+
+ if (potentialLayersWithContents > 1)
+ return MultipleLayersWithContents;
+
+ if (m_children.isEmpty())
+ return SingleLayerWithContents;
+
+ return m_children.first()->countPotentialLayersWithContents();
+}
+
bool TextureMapperLayer::shouldPaintToIntermediateSurface() const
{
#if ENABLE(CSS_FILTERS)
@@ -220,7 +240,7 @@ bool TextureMapperLayer::shouldPaintToIntermediateSurface() const
return true;
#endif
bool hasOpacity = m_opacity < 0.99;
- bool hasChildren = !m_children.isEmpty();
+ bool canHaveMultipleLayersWithContent = countPotentialLayersWithContents() == MultipleLayersWithContents;
bool hasReplica = !!m_state.replicaLayer;
bool hasMask = !!m_state.maskLayer;
@@ -230,13 +250,13 @@ bool TextureMapperLayer::shouldPaintToIntermediateSurface() const
// We should use an intermediate surface when blending several items with an ancestor opacity.
// Tested by compositing/reflections/reflection-opacity.html
- if (hasOpacity && (hasChildren || hasReplica))
+ if (hasOpacity && (canHaveMultipleLayersWithContent || hasReplica))
return true;
// We should use an intermediate surface with a masked ancestor.
// In the case of replicas the mask is applied before replicating.
// Tested by compositing/masks/masked-ancestor.html
- if (hasMask && hasChildren && !hasReplica)
+ if (hasMask && canHaveMultipleLayersWithContent && !hasReplica)
return true;
return false;
@@ -286,8 +306,7 @@ static PassRefPtr<BitmapTexture> applyFilters(const FilterOperations& filters, T
filterSurface = textureMapper->acquireTextureFromPool(targetRect.size());
}
- filterSurface->applyFilters(*source, filters);
- return filterSurface;
+ return filterSurface->applyFilters(*source, filters);
}
#endif
@@ -318,8 +337,7 @@ void TextureMapperLayer::paintRecursive(const TextureMapperPaintOptions& options
options.textureMapper->bindSurface(surface.get());
paintOptions.opacity = 1;
- // We have to use combinedForChildren() and not combined(), otherwise preserve-3D doesn't work.
- paintOptions.transform = m_transform.combinedForChildren().inverse();
+ paintOptions.transform = m_transform.combined().inverse();
paintOptions.offset = -IntSize(surfaceRect.x(), surfaceRect.y());
paintSelfAndChildrenWithReplica(paintOptions);
@@ -333,10 +351,11 @@ void TextureMapperLayer::paintRecursive(const TextureMapperPaintOptions& options
#endif
options.textureMapper->bindSurface(options.surface.get());
- TransformationMatrix targetTransform =
- TransformationMatrix(options.transform)
- .multiply(m_transform.combined())
- .translate(options.offset.width(), options.offset.height());
+ TransformationMatrix targetTransform;
+ targetTransform.translate(options.offset.width(), options.offset.height());
+ targetTransform.multiply(options.transform);
+ targetTransform.multiply(m_transform.combined());
+
options.textureMapper->drawTexture(*surface.get(), surfaceRect, targetTransform, opacity, maskTexture.get());
}
@@ -424,8 +443,10 @@ void TextureMapperLayer::syncCompositingStateSelf(GraphicsLayerTextureMapper* gr
m_state.childrenTransform = graphicsLayer->childrenTransform();
m_state.opacity = graphicsLayer->opacity();
#if ENABLE(CSS_FILTERS)
- m_state.filters = graphicsLayer->filters();
+ if (changeMask & FilterChange)
+ m_state.filters = graphicsLayer->filters();
#endif
+ m_fixedToViewport = graphicsLayer->fixedToViewport();
m_state.needsDisplay = m_state.needsDisplay || graphicsLayer->needsDisplay();
if (!m_state.needsDisplay)
@@ -510,5 +531,28 @@ void TextureMapperLayer::syncCompositingState(GraphicsLayerTextureMapper* graphi
}
}
+bool TextureMapperLayer::isAncestorFixedToViewport() const
+{
+ for (TextureMapperLayer* parent = m_parent; parent; parent = parent->m_parent) {
+ if (parent->m_fixedToViewport)
+ return true;
+ }
+
+ return false;
+}
+
+void TextureMapperLayer::setScrollPositionDeltaIfNeeded(const IntPoint& delta)
+{
+ // delta is the difference between the scroll offset in the ui process and the scroll offset
+ // in the web process. We add this delta to the position of fixed layers, to make
+ // sure that they do not move while scrolling. We need to reset this delta to fixed layers
+ // that have an ancestor which is also a fixed layer, because the delta will be added to the ancestor.
+ if (isAncestorFixedToViewport())
+ m_scrollPositionDelta = IntPoint();
+ else
+ m_scrollPositionDelta = delta;
+ m_transform.setPosition(m_state.pos + m_scrollPositionDelta);
+}
+
}
#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h
index e10d5a798..172ca5cb1 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h
@@ -126,6 +126,9 @@ public:
PassRefPtr<TextureMapperBackingStore> backingStore() { return m_backingStore; }
void clearBackingStoresRecursive();
+ void setScrollPositionDeltaIfNeeded(const IntPoint&);
+ void setFixedToViewport(bool fixed) { m_fixedToViewport = fixed; }
+
private:
TextureMapperLayer* rootLayer();
void computeTransformsRecursive();
@@ -143,6 +146,7 @@ private:
static void sortByZOrder(Vector<TextureMapperLayer* >& array, int first, int last);
PassRefPtr<BitmapTexture> texture() { return m_backingStore ? m_backingStore->texture() : 0; }
+ bool isAncestorFixedToViewport() const;
void paintRecursive(const TextureMapperPaintOptions&);
void paintSelf(const TextureMapperPaintOptions&);
@@ -152,6 +156,13 @@ private:
void syncAnimations();
bool isVisible() const;
+ enum ContentsLayerCount {
+ NoLayersWithContent,
+ SingleLayerWithContents,
+ MultipleLayersWithContents
+ };
+
+ ContentsLayerCount countPotentialLayersWithContents() const;
bool shouldPaintToIntermediateSurface() const;
LayerTransform m_transform;
@@ -217,6 +228,8 @@ private:
State m_state;
TextureMapper* m_textureMapper;
TextureMapperAnimations m_animations;
+ IntPoint m_scrollPositionDelta;
+ bool m_fixedToViewport;
};
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h
index c69c1fbca..3d247a256 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h
@@ -29,6 +29,7 @@ class BitmapTexture;
class TextureMapperPlatformLayer {
public:
+ virtual ~TextureMapperPlatformLayer() { }
virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix& modelViewMatrix = TransformationMatrix(), float opacity = 1.0, BitmapTexture* mask = 0) = 0;
virtual void swapBuffers() { }
};
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp
index 9e52ca2b1..a759c5f4c 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp
@@ -57,13 +57,13 @@ static const char* fragmentShaderSourceOpacityAndMask =
static const char* vertexShaderSourceOpacityAndMask =
VERTEX_SHADER(
- uniform mat4 InMatrix, InSourceMatrix, InMaskMatrix;
+ uniform mat4 InMatrix, InSourceMatrix;
attribute vec4 InVertex;
varying highp vec2 OutTexCoordSource, OutTexCoordMask;
void main(void)
{
OutTexCoordSource = vec2(InSourceMatrix * InVertex);
- OutTexCoordMask = vec2(InMaskMatrix * InVertex);
+ OutTexCoordMask = vec2(InVertex);
gl_Position = InMatrix * InVertex;
}
);
@@ -171,7 +171,6 @@ TextureMapperShaderProgramOpacityAndMask::TextureMapperShaderProgramOpacityAndMa
initializeProgram();
getUniformLocation(m_matrixVariable, "InMatrix");
getUniformLocation(m_sourceMatrixVariable, "InSourceMatrix");
- getUniformLocation(m_maskMatrixVariable, "InMaskMatrix");
getUniformLocation(m_sourceTextureVariable, "SourceTexture");
getUniformLocation(m_maskTextureVariable, "MaskTexture");
getUniformLocation(m_opacityVariable, "Opacity");
@@ -196,11 +195,6 @@ void TextureMapperShaderProgramOpacityAndMask::prepare(float opacity, const Bitm
const BitmapTextureGL* maskTextureGL = static_cast<const BitmapTextureGL*>(maskTexture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, maskTextureGL->id());
- const GLfloat m4mask[] = {maskTextureGL->relativeSize().width(), 0, 0, 0,
- 0, maskTextureGL->relativeSize().height(), 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1};
- glUniformMatrix4fv(m_maskMatrixVariable, 1, GL_FALSE, m4mask);
glUniform1i(m_maskTextureVariable, 1);
glActiveTexture(GL_TEXTURE0);
}
@@ -212,9 +206,220 @@ TextureMapperShaderManager::TextureMapperShaderManager()
TextureMapperShaderManager::~TextureMapperShaderManager()
{
- m_textureMapperShaderProgramMap.clear();
}
+#if ENABLE(CSS_FILTERS)
+StandardFilterProgram::~StandardFilterProgram()
+{
+ glDetachShader(m_id, m_vertexShader);
+ glDeleteShader(m_vertexShader);
+ glDetachShader(m_id, m_fragmentShader);
+ glDeleteShader(m_fragmentShader);
+ glDeleteProgram(m_id);
+}
+
+StandardFilterProgram::StandardFilterProgram(FilterOperation::OperationType type)
+ : m_id(0)
+{
+ const char* vertexShaderSource =
+ VERTEX_SHADER(
+ attribute vec4 a_vertex;
+ attribute vec4 a_texCoord;
+ varying highp vec2 v_texCoord;
+ void main(void)
+ {
+ v_texCoord = vec2(a_texCoord);
+ gl_Position = a_vertex;
+ }
+ );
+
+#define STANDARD_FILTER(x...) \
+ OES2_PRECISION_DEFINITIONS\
+ OES2_FRAGMENT_SHADER_DEFAULT_PRECISION\
+ "varying highp vec2 v_texCoord;\n"\
+ "uniform highp float u_amount;\n"\
+ "uniform sampler2D u_texture;\n"\
+ #x\
+ "void main(void)\n { gl_FragColor = shade(texture2D(u_texture, v_texCoord)); }"
+
+ const char* fragmentShaderSource = 0;
+ switch (type) {
+ case FilterOperation::GRAYSCALE:
+ fragmentShaderSource = STANDARD_FILTER(
+ lowp vec4 shade(lowp vec4 color)
+ {
+ lowp float amount = 1.0 - u_amount;
+ return vec4((0.2126 + 0.7874 * amount) * color.r + (0.7152 - 0.7152 * amount) * color.g + (0.0722 - 0.0722 * amount) * color.b,
+ (0.2126 - 0.2126 * amount) * color.r + (0.7152 + 0.2848 * amount) * color.g + (0.0722 - 0.0722 * amount) * color.b,
+ (0.2126 - 0.2126 * amount) * color.r + (0.7152 - 0.7152 * amount) * color.g + (0.0722 + 0.9278 * amount) * color.b,
+ color.a);
+ }
+ );
+ break;
+ case FilterOperation::SEPIA:
+ fragmentShaderSource = STANDARD_FILTER(
+ lowp vec4 shade(lowp vec4 color)
+ {
+ lowp float amount = 1.0 - u_amount;
+ return vec4((0.393 + 0.607 * amount) * color.r + (0.769 - 0.769 * amount) * color.g + (0.189 - 0.189 * amount) * color.b,
+ (0.349 - 0.349 * amount) * color.r + (0.686 + 0.314 * amount) * color.g + (0.168 - 0.168 * amount) * color.b,
+ (0.272 - 0.272 * amount) * color.r + (0.534 - 0.534 * amount) * color.g + (0.131 + 0.869 * amount) * color.b,
+ color.a);
+ }
+ );
+ break;
+ case FilterOperation::SATURATE:
+ fragmentShaderSource = STANDARD_FILTER(
+ lowp vec4 shade(lowp vec4 color)
+ {
+ return vec4((0.213 + 0.787 * u_amount) * color.r + (0.715 - 0.715 * u_amount) * color.g + (0.072 - 0.072 * u_amount) * color.b,
+ (0.213 - 0.213 * u_amount) * color.r + (0.715 + 0.285 * u_amount) * color.g + (0.072 - 0.072 * u_amount) * color.b,
+ (0.213 - 0.213 * u_amount) * color.r + (0.715 - 0.715 * u_amount) * color.g + (0.072 + 0.928 * u_amount) * color.b,
+ color.a);
+ }
+ );
+ break;
+ case FilterOperation::HUE_ROTATE:
+ fragmentShaderSource = STANDARD_FILTER(
+ lowp vec4 shade(lowp vec4 color)
+ {
+ highp float pi = 3.14159265358979323846;
+ highp float c = cos(u_amount * pi / 180.0);
+ highp float s = sin(u_amount * pi / 180.0);
+ return vec4(color.r * (0.213 + c * 0.787 - s * 0.213) + color.g * (0.715 - c * 0.715 - s * 0.715) + color.b * (0.072 - c * 0.072 + s * 0.928),
+ color.r * (0.213 - c * 0.213 + s * 0.143) + color.g * (0.715 + c * 0.285 + s * 0.140) + color.b * (0.072 - c * 0.072 - s * 0.283),
+ color.r * (0.213 - c * 0.213 - s * 0.787) + color.g * (0.715 - c * 0.715 + s * 0.715) + color.b * (0.072 + c * 0.928 + s * 0.072),
+ color.a);
+ }
+ );
+ break;
+ case FilterOperation::INVERT:
+ fragmentShaderSource = STANDARD_FILTER(
+ lowp float invert(lowp float n) { return (1.0 - n) * u_amount + n * (1.0 - u_amount); }
+ lowp vec4 shade(lowp vec4 color)
+ {
+ return vec4(invert(color.r), invert(color.g), invert(color.b), color.a);
+ }
+ );
+ break;
+ case FilterOperation::BRIGHTNESS:
+ fragmentShaderSource = STANDARD_FILTER(
+ lowp vec4 shade(lowp vec4 color)
+ {
+ return vec4(color.rgb * (1.0 + u_amount), color.a);
+ }
+ );
+ break;
+ case FilterOperation::CONTRAST:
+ fragmentShaderSource = STANDARD_FILTER(
+ lowp float contrast(lowp float n) { return (n - 0.5) * u_amount + 0.5; }
+ lowp vec4 shade(lowp vec4 color)
+ {
+ return vec4(contrast(color.r), contrast(color.g), contrast(color.b), color.a);
+ }
+ );
+ break;
+ case FilterOperation::OPACITY:
+ fragmentShaderSource = STANDARD_FILTER(
+ lowp vec4 shade(lowp vec4 color)
+ {
+ return vec4(color.r, color.g, color.b, color.a * u_amount);
+ }
+ );
+ break;
+ default:
+ break;
+ }
+
+ if (!fragmentShaderSource)
+ return;
+ GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
+ GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(vertexShader, 1, &vertexShaderSource, 0);
+ glShaderSource(fragmentShader, 1, &fragmentShaderSource, 0);
+ GLchar log[100];
+ GLint len;
+ GLuint programID = glCreateProgram();
+ glCompileShader(vertexShader);
+ glCompileShader(fragmentShader);
+ glGetShaderInfoLog(fragmentShader, 100, &len, log);
+ glAttachShader(programID, vertexShader);
+ glAttachShader(programID, fragmentShader);
+ glLinkProgram(programID);
+
+ m_vertexAttrib = glGetAttribLocation(programID, "a_vertex");
+ m_texCoordAttrib = glGetAttribLocation(programID, "a_texCoord");
+ m_textureUniformLocation = glGetUniformLocation(programID, "u_texture");
+ switch (type) {
+ case FilterOperation::GRAYSCALE:
+ case FilterOperation::SEPIA:
+ case FilterOperation::SATURATE:
+ case FilterOperation::HUE_ROTATE:
+ case FilterOperation::INVERT:
+ case FilterOperation::BRIGHTNESS:
+ case FilterOperation::CONTRAST:
+ case FilterOperation::OPACITY:
+ m_uniformLocations.amount = glGetUniformLocation(programID, "u_amount");
+ break;
+ default:
+ break;
+ }
+ m_id = programID;
+ m_vertexShader = vertexShader;
+ m_fragmentShader = fragmentShader;
+}
+
+PassRefPtr<StandardFilterProgram> StandardFilterProgram::create(FilterOperation::OperationType type)
+{
+ RefPtr<StandardFilterProgram> program = adoptRef(new StandardFilterProgram(type));
+ if (!program->m_id)
+ return 0;
+
+ return program;
+}
+
+void StandardFilterProgram::prepare(const FilterOperation& operation)
+{
+ double amount = 0;
+ switch (operation.getOperationType()) {
+ case FilterOperation::GRAYSCALE:
+ case FilterOperation::SEPIA:
+ case FilterOperation::SATURATE:
+ case FilterOperation::HUE_ROTATE:
+ amount = static_cast<const BasicColorMatrixFilterOperation&>(operation).amount();
+ break;
+ case FilterOperation::INVERT:
+ case FilterOperation::BRIGHTNESS:
+ case FilterOperation::CONTRAST:
+ case FilterOperation::OPACITY:
+ amount = static_cast<const BasicComponentTransferFilterOperation&>(operation).amount();
+ break;
+ default:
+ break;
+ }
+ glUseProgram(m_id);
+ glUniform1f(m_uniformLocations.amount, amount);
+}
+
+PassRefPtr<StandardFilterProgram> TextureMapperShaderManager::getShaderForFilter(const FilterOperation& filter)
+{
+ RefPtr<StandardFilterProgram> program;
+ FilterOperation::OperationType type = filter.getOperationType();
+ FilterMap::iterator iterator = m_filterMap.find(type);
+ if (iterator == m_filterMap.end()) {
+ program = StandardFilterProgram::create(type);
+ if (!program)
+ return 0;
+
+ m_filterMap.add(type, program);
+ } else
+ program = iterator->second;
+
+ program->prepare(filter);
+ return program;
+}
+
+#endif
};
#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h
index 4502e7e3a..d0593e6c7 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h
@@ -31,9 +31,11 @@
#include <wtf/PassRefPtr.h>
#include <wtf/RefPtr.h>
-namespace WebCore {
+#if ENABLE(CSS_FILTERS)
+#include "FilterOperations.h"
+#endif
-typedef void* ShaderType;
+namespace WebCore {
class BitmapTexture;
class TextureMapperShaderManager;
@@ -45,13 +47,6 @@ public:
virtual ~TextureMapperShaderProgram();
- template<class T>
- static ShaderType shaderType()
- {
- static int type = 0;
- return &type;
- }
-
virtual void prepare(float opacity, const BitmapTexture*) { }
GLint matrixVariable() const { return m_matrixVariable; }
GLint sourceMatrixVariable() const { return m_sourceMatrixVariable; }
@@ -74,6 +69,35 @@ protected:
GLint m_opacityVariable;
};
+#if ENABLE(CSS_FILTERS)
+class StandardFilterProgram : public RefCounted<StandardFilterProgram> {
+public:
+ virtual ~StandardFilterProgram();
+ virtual void prepare(const FilterOperation&);
+ static PassRefPtr<StandardFilterProgram> create(FilterOperation::OperationType);
+ GLuint vertexAttrib() const { return m_vertexAttrib; }
+ GLuint texCoordAttrib() const { return m_texCoordAttrib; }
+ GLuint textureUniform() const { return m_textureUniformLocation; }
+private:
+ StandardFilterProgram(FilterOperation::OperationType);
+ GLuint m_id;
+ GLuint m_vertexShader;
+ GLuint m_fragmentShader;
+ GLuint m_vertexAttrib;
+ GLuint m_texCoordAttrib;
+ GLuint m_textureUniformLocation;
+ union {
+ GLuint amount;
+ GLuint stddev;
+ struct {
+ GLuint stddev;
+ GLuint color;
+ GLuint offset;
+ } shadow;
+ } m_uniformLocations;
+};
+#endif
+
class TextureMapperShaderProgramSimple : public TextureMapperShaderProgram {
public:
static PassRefPtr<TextureMapperShaderProgramSimple> create();
@@ -89,7 +113,6 @@ class TextureMapperShaderProgramOpacityAndMask : public TextureMapperShaderProgr
public:
static PassRefPtr<TextureMapperShaderProgramOpacityAndMask> create();
virtual void prepare(float opacity, const BitmapTexture*);
- GLint maskMatrixVariable() const { return m_maskMatrixVariable; }
GLint maskTextureVariable() const { return m_maskTextureVariable; }
private:
@@ -97,31 +120,57 @@ private:
virtual const char* vertexShaderSource() const;
virtual const char* fragmentShaderSource() const;
TextureMapperShaderProgramOpacityAndMask();
- GLint m_maskMatrixVariable;
GLint m_maskTextureVariable;
};
class TextureMapperShaderManager {
public:
+ enum ShaderType {
+ Invalid = 0, // HashMaps do not like 0 as a key.
+ Simple,
+ OpacityAndMask
+ };
+
TextureMapperShaderManager();
virtual ~TextureMapperShaderManager();
- template<class T>
- PassRefPtr<T> getShaderProgram()
+#if ENABLE(CSS_FILTERS)
+ PassRefPtr<StandardFilterProgram> getShaderForFilter(const FilterOperation&);
+#endif
+
+ PassRefPtr<TextureMapperShaderProgram> getShaderProgram(ShaderType shaderType)
{
- ShaderType shaderType = TextureMapperShaderProgram::shaderType<T>();
+ RefPtr<TextureMapperShaderProgram> program;
+ if (shaderType == Invalid)
+ return program;
+
TextureMapperShaderProgramMap::iterator it = m_textureMapperShaderProgramMap.find(shaderType);
if (it != m_textureMapperShaderProgramMap.end())
- return static_cast<T*>(it->second.get());
-
- RefPtr<T> t = T::create();
- m_textureMapperShaderProgramMap.add(shaderType, t);
- return t;
+ return it->second;
+
+ switch (shaderType) {
+ case Simple:
+ program = TextureMapperShaderProgramSimple::create();
+ break;
+ case OpacityAndMask:
+ program = TextureMapperShaderProgramOpacityAndMask::create();
+ break;
+ case Invalid:
+ ASSERT_NOT_REACHED();
+ }
+ m_textureMapperShaderProgramMap.add(shaderType, program);
+ return program;
}
private:
- typedef HashMap<ShaderType, RefPtr<TextureMapperShaderProgram> > TextureMapperShaderProgramMap;
+ typedef HashMap<ShaderType, RefPtr<TextureMapperShaderProgram>, DefaultHash<int>::Hash, HashTraits<int> > TextureMapperShaderProgramMap;
TextureMapperShaderProgramMap m_textureMapperShaderProgramMap;
+
+#if ENABLE(CSS_FILTERS)
+ typedef HashMap<FilterOperation::OperationType, RefPtr<StandardFilterProgram>, DefaultHash<int>::Hash, HashTraits<int> > FilterMap;
+ FilterMap m_filterMap;
+#endif
+
};
}
diff --git a/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.cpp b/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.cpp
index 6ab605d9e..e8422925c 100644
--- a/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.cpp
+++ b/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.cpp
@@ -39,7 +39,7 @@ PassRefPtr<TransformOperation> PerspectiveTransformOperation::blend(const Transf
return this;
if (blendToIdentity) {
- double p = m_p.calcFloatValue(1);
+ double p = floatValueForLength(m_p, 1);
p = WebCore::blend(p, 1.0, progress); // FIXME: this seems wrong. https://bugs.webkit.org/show_bug.cgi?id=52700
return PerspectiveTransformOperation::create(Length(clampToPositiveInteger(p), Fixed));
}
@@ -50,8 +50,8 @@ PassRefPtr<TransformOperation> PerspectiveTransformOperation::blend(const Transf
TransformationMatrix fromT;
TransformationMatrix toT;
- fromT.applyPerspective(fromP.calcFloatValue(1));
- toT.applyPerspective(toP.calcFloatValue(1));
+ fromT.applyPerspective(floatValueForLength(fromP, 1));
+ toT.applyPerspective(floatValueForLength(toP, 1));
toT.blend(fromT, progress);
TransformationMatrix::DecomposedType decomp;
toT.decompose(decomp);
diff --git a/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h b/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h
index 52452b35c..3730d4275 100644
--- a/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h
+++ b/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h
@@ -27,6 +27,7 @@
#define PerspectiveTransformOperation_h
#include "Length.h"
+#include "LengthFunctions.h"
#include "TransformOperation.h"
namespace WebCore {
@@ -41,7 +42,7 @@ public:
Length perspective() const { return m_p; }
private:
- virtual bool isIdentity() const { return m_p.calcFloatValue(1) == 0; }
+ virtual bool isIdentity() const { return !floatValueForLength(m_p, 1); }
virtual OperationType getOperationType() const { return PERSPECTIVE; }
virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == PERSPECTIVE; }
@@ -55,7 +56,7 @@ private:
virtual bool apply(TransformationMatrix& transform, const FloatSize&) const
{
- transform.applyPerspective(m_p.calcFloatValue(1));
+ transform.applyPerspective(floatValueForLength(m_p, 1));
return false;
}
diff --git a/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp b/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp
index 1cf96f842..24d960fe3 100644
--- a/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp
+++ b/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp
@@ -588,7 +588,7 @@ FloatQuad TransformationMatrix::projectQuad(const FloatQuad& q) const
static float clampEdgeValue(float f)
{
ASSERT(!isnan(f));
- return min<float>(max<float>(f, -numeric_limits<LayoutUnit>::max() / 2), numeric_limits<LayoutUnit>::max() / 2);
+ return min<float>(max<float>(f, -MAX_LAYOUT_UNIT / 2), MAX_LAYOUT_UNIT / 2);
}
LayoutRect TransformationMatrix::clampedBoundsOfProjectedQuad(const FloatQuad& q) const
@@ -600,13 +600,13 @@ LayoutRect TransformationMatrix::clampedBoundsOfProjectedQuad(const FloatQuad& q
float right;
if (isinf(mappedQuadBounds.x()) && isinf(mappedQuadBounds.width()))
- right = numeric_limits<LayoutUnit>::max() / 2;
+ right = MAX_LAYOUT_UNIT / 2;
else
right = clampEdgeValue(ceilf(mappedQuadBounds.maxX()));
float bottom;
if (isinf(mappedQuadBounds.y()) && isinf(mappedQuadBounds.height()))
- bottom = numeric_limits<LayoutUnit>::max() / 2;
+ bottom = MAX_LAYOUT_UNIT / 2;
else
bottom = clampEdgeValue(ceilf(mappedQuadBounds.maxY()));
@@ -1224,4 +1224,32 @@ void TransformationMatrix::toColumnMajorFloatArray(FloatMatrix4& result) const
result[15] = m44();
}
+bool TransformationMatrix::isBackFaceVisible() const
+{
+ // Back-face visibility is determined by transforming the normal vector (0, 0, 1) and
+ // checking the sign of the resulting z component. However, normals cannot be
+ // transformed by the original matrix, they require being transformed by the
+ // inverse-transpose.
+ //
+ // Since we know we will be using (0, 0, 1), and we only care about the z-component of
+ // the transformed normal, then we only need the m33() element of the
+ // inverse-transpose. Therefore we do not need the transpose.
+ //
+ // Additionally, if we only need the m33() element, we do not need to compute a full
+ // inverse. Instead, knowing the inverse of a matrix is adjoint(matrix) / determinant,
+ // we can simply compute the m33() of the adjoint (adjugate) matrix, without computing
+ // the full adjoint.
+
+ double determinant = WebCore::determinant4x4(m_matrix);
+
+ // If the matrix is not invertible, then we assume its backface is not visible.
+ if (fabs(determinant) < SMALL_NUMBER)
+ return false;
+
+ double cofactor33 = determinant3x3(m11(), m12(), m14(), m21(), m22(), m24(), m41(), m42(), m44());
+ double zComponentOfTransformedNormal = cofactor33 / determinant;
+
+ return zComponentOfTransformedNormal < 0;
+}
+
}
diff --git a/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h b/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h
index 5b5dad520..5918efcb7 100644
--- a/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h
+++ b/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h
@@ -360,6 +360,12 @@ public:
typedef float FloatMatrix4[16];
void toColumnMajorFloatArray(FloatMatrix4& result) const;
+ // A local-space layer is implicitly defined at the z = 0 plane, with its front side
+ // facing the positive z-axis (i.e. a camera looking along the negative z-axis sees
+ // the front side of the layer). This function checks if the transformed layer's back
+ // face would be visible to a camera looking along the negative z-axis in the target space.
+ bool isBackFaceVisible() const;
+
private:
// multiply passed 2D point by matrix (assume z=0)
void multVecMatrix(double x, double y, double& dstX, double& dstY) const;
diff --git a/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.h b/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.h
index b194d839b..fc2bc1f27 100644
--- a/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.h
+++ b/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.h
@@ -26,6 +26,7 @@
#define TranslateTransformOperation_h
#include "Length.h"
+#include "LengthFunctions.h"
#include "TransformOperation.h"
namespace WebCore {
@@ -42,16 +43,16 @@ public:
return adoptRef(new TranslateTransformOperation(tx, ty, tz, type));
}
- double x(const FloatSize& borderBoxSize) const { return m_x.calcFloatValue(borderBoxSize.width()); }
- double y(const FloatSize& borderBoxSize) const { return m_y.calcFloatValue(borderBoxSize.height()); }
- double z(const FloatSize&) const { return m_z.calcFloatValue(1); }
+ double x(const FloatSize& borderBoxSize) const { return floatValueForLength(m_x, borderBoxSize.width()); }
+ double y(const FloatSize& borderBoxSize) const { return floatValueForLength(m_y, borderBoxSize.height()); }
+ double z(const FloatSize&) const { return floatValueForLength(m_z, 1); }
Length x() const { return m_x; }
Length y() const { return m_y; }
Length z() const { return m_z; }
private:
- virtual bool isIdentity() const { return m_x.calcFloatValue(1) == 0 && m_y.calcFloatValue(1) == 0 && m_z.calcFloatValue(1) == 0; }
+ virtual bool isIdentity() const { return !floatValueForLength(m_x, 1) && !floatValueForLength(m_y, 1) && !floatValueForLength(m_z, 1); }
virtual OperationType getOperationType() const { return m_type; }
virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == m_type; }
diff --git a/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp b/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
index 9860df6a2..f78368511 100644
--- a/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
+++ b/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
@@ -27,6 +27,7 @@
#include "HWndDC.h"
#include "PlatformString.h"
+#include "SharedBuffer.h"
#include <wtf/HashMap.h>
#include <wtf/RetainPtr.h>
#include <wtf/Vector.h>
@@ -74,6 +75,23 @@ FontPlatformData::FontPlatformData(HFONT font, float size, bool bold, bool obliq
RestoreDC(hdc, -1);
}
+PassRefPtr<SharedBuffer> FontPlatformData::openTypeTable(uint32_t table) const
+{
+ HWndDC hdc(0);
+ HGDIOBJ oldFont = SelectObject(hdc, hfont());
+
+ DWORD size = GetFontData(hdc, table, 0, 0, 0);
+ RefPtr<SharedBuffer> buffer;
+ if (size != GDI_ERROR) {
+ buffer = SharedBuffer::create(size);
+ DWORD result = GetFontData(hdc, table, 0, (PVOID)buffer->data(), size);
+ ASSERT(result == size);
+ }
+
+ SelectObject(hdc, oldFont);
+ return buffer.release();
+}
+
#ifndef NDEBUG
String FontPlatformData::description() const
{
diff --git a/Source/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp b/Source/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
index f3a919d71..063f7cb69 100644
--- a/Source/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
+++ b/Source/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
@@ -181,12 +181,12 @@ static const Color& grammarPatternColor() {
return grammarColor;
}
-void GraphicsContext::drawLineForTextChecking(const FloatPoint& point, float width, TextCheckingLineStyle style)
+void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& point, float width, DocumentMarkerLineStyle style)
{
if (paintingDisabled())
return;
- if (style != TextCheckingSpellingLineStyle && style != TextCheckingGrammarLineStyle)
+ if (style != DocumentMarkerSpellingLineStyle && style != DocumentMarkerGrammarLineStyle)
return;
// These are the same for misspelling or bad grammar
@@ -209,7 +209,7 @@ void GraphicsContext::drawLineForTextChecking(const FloatPoint& point, float wid
CGContextRef context = platformContext();
CGContextSaveGState(context);
- const Color& patternColor = style == TextCheckingGrammarLineStyle ? grammarPatternColor() : spellingPatternColor();
+ const Color& patternColor = style == DocumentMarkerGrammarLineStyle ? grammarPatternColor() : spellingPatternColor();
setCGStrokeColor(context, patternColor);
wkSetPatternPhaseInUserSpace(context, point);
diff --git a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
index d8be4f5f3..b0037c3ab 100644
--- a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
+++ b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
@@ -107,7 +107,8 @@ private:
virtual bool platformCALayerContentsOpaque() const { return false; }
virtual bool platformCALayerDrawsContent() const { return false; }
virtual void platformCALayerLayerDidDisplay(PlatformLayer*) { }
- virtual void platformCALayerDidCreateTiles() { }
+ virtual void platformCALayerDidCreateTiles(const Vector<FloatRect>&) { }
+ virtual float platformCALayerDeviceScaleFactor() { return 1; }
MediaPlayerPrivateQuickTimeVisualContext* m_parent;
};
diff --git a/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp b/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
index ad025b803..96847e7c9 100644
--- a/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
+++ b/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
@@ -29,9 +29,9 @@
#include "config.h"
#include "SimpleFontData.h"
+#include "FloatRect.h"
#include "Font.h"
#include "FontCache.h"
-#include "FloatRect.h"
#include "FontDescription.h"
#include "HWndDC.h"
#include "PlatformString.h"
@@ -46,7 +46,7 @@
namespace WebCore {
-using std::max;
+using namespace std;
void SimpleFontData::platformInit()
{
@@ -103,6 +103,9 @@ void SimpleFontData::platformInit()
FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const
{
+ if (!platformData().size())
+ return FloatRect();
+
if (m_platformData.useGDI())
return boundsForGDIGlyph(glyph);
@@ -119,6 +122,9 @@ FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
+ if (!platformData().size())
+ return 0;
+
if (m_platformData.useGDI())
return widthForGDIGlyph(glyph);
diff --git a/Source/WebCore/platform/graphics/win/UniscribeController.cpp b/Source/WebCore/platform/graphics/win/UniscribeController.cpp
index 336b4e642..60f8d12a1 100644
--- a/Source/WebCore/platform/graphics/win/UniscribeController.cpp
+++ b/Source/WebCore/platform/graphics/win/UniscribeController.cpp
@@ -272,7 +272,7 @@ bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, const S
for (int k = 0; k < len; k++) {
UChar ch = *(str + k);
bool treatAsSpace = Font::treatAsSpace(ch);
- bool treatAsZeroWidthSpace = ch == zeroWidthSpace || Font::treatAsZeroWidthSpace(ch);
+ bool treatAsZeroWidthSpace = Font::treatAsZeroWidthSpace(ch);
if (treatAsSpace || treatAsZeroWidthSpace) {
// Substitute in the space glyph at the appropriate place in the glyphs
// array.
diff --git a/Source/WebCore/platform/graphics/win/UniscribeController.h b/Source/WebCore/platform/graphics/win/UniscribeController.h
index 162ddbe3d..d4feb0a5b 100644
--- a/Source/WebCore/platform/graphics/win/UniscribeController.h
+++ b/Source/WebCore/platform/graphics/win/UniscribeController.h
@@ -29,7 +29,7 @@
#include <usp10.h>
#include "Font.h"
#include "GlyphBuffer.h"
-#include "Vector.h"
+#include <wtf/Vector.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp b/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp
index 692fd6d0d..19790ad49 100644
--- a/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp
+++ b/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp
@@ -285,11 +285,11 @@ PassRefPtr<FixedSizeFontData> FixedSizeFontData::create(const AtomicString& fami
static PassRefPtr<FixedSizeFontData> createFixedSizeFontData(const AtomicString& family, unsigned weight, bool italic)
{
FixedSizeFontDataKey key(family, weight, italic);
- pair<FixedSizeFontCache::iterator, bool> result = g_fixedSizeFontCache.add(key, RefPtr<FixedSizeFontData>());
- if (result.second)
- result.first->second = FixedSizeFontData::create(family, weight, italic);
+ FixedSizeFontCache::AddResult result = g_fixedSizeFontCache.add(key, RefPtr<FixedSizeFontData>());
+ if (result.isNewEntry)
+ result.iterator->second = FixedSizeFontData::create(family, weight, italic);
- return result.first->second;
+ return result.iterator->second;
}
static LONG toGDIFontWeight(FontWeight fontWeight)
diff --git a/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp b/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp
index 96bc3dc55..92e02a056 100644
--- a/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp
+++ b/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp
@@ -1032,7 +1032,7 @@ void GraphicsContext::drawLineForText(const FloatPoint& origin, float width, boo
setStrokeStyle(oldStyle);
}
-void GraphicsContext::drawLineForTextChecking(const FloatPoint&, float width, TextCheckingLineStyle style)
+void GraphicsContext::drawLineForDocumentMarker(const FloatPoint&, float width, DocumentMarkerLineStyle style)
{
notImplemented();
}
diff --git a/Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp b/Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp
index bdbe62db9..9c4225a3e 100644
--- a/Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp
+++ b/Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp
@@ -27,7 +27,6 @@
#include "ImageData.h"
#include "NotImplemented.h"
#include "SharedBitmap.h"
-#include "UnusedParam.h"
#include <wtf/UnusedParam.h>
namespace WebCore {
@@ -72,10 +71,13 @@ ImageBufferData::ImageBufferData(const IntSize& size)
m_bitmap->setHasAlpha(true);
}
-ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace colorSpace, RenderingMode, DeferralMode, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, float resolutionScale, ColorSpace colorSpace, RenderingMode, DeferralMode, bool& success)
: m_data(size)
, m_size(size)
+ , m_logicalSize(size)
{
+ // FIXME: Respect resoutionScale to support high-DPI canvas.
+ UNUSED_PARAM(resolutionScale);
// FIXME: colorSpace is not used
UNUSED_PARAM(colorSpace);
@@ -108,7 +110,7 @@ void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, con
CompositeOperator op , bool useLowQualityScale)
{
RefPtr<Image> imageCopy = copyImage(CopyBackingStore);
- context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
+ context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, DoNotRespectImageOrientation, useLowQualityScale);
}
void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform,
@@ -119,9 +121,9 @@ void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect
}
template <bool premultiplied>
-static PassRefPtr<ByteArray> getImageData(const IntRect& rect, const SharedBitmap* bitmap)
+static PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const SharedBitmap* bitmap)
{
- RefPtr<ByteArray> imageData = ByteArray::create(rect.width() * rect.height() * 4);
+ RefPtr<Uint8ClampedArray> imageData = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4);
const unsigned char* src = static_cast<const unsigned char*>(bitmap->bytes());
if (!src)
@@ -133,7 +135,7 @@ static PassRefPtr<ByteArray> getImageData(const IntRect& rect, const SharedBitma
return imageData.release();
unsigned char* dst = imageData->data();
- memset(dst, 0, imageData->length());
+ imageData->zeroFill();
src += (sourceRect.y() * bitmap->width() + sourceRect.x()) * 4;
dst += ((sourceRect.y() - rect.y()) * rect.width() + sourceRect.x() - rect.x()) * 4;
int bytesToCopy = sourceRect.width() * 4;
@@ -168,17 +170,17 @@ static PassRefPtr<ByteArray> getImageData(const IntRect& rect, const SharedBitma
return imageData.release();
}
-PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect, CoordinateSystem) const
{
return getImageData<false>(rect, m_data.m_bitmap.get());
}
-PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem) const
{
return getImageData<true>(rect, m_data.m_bitmap.get());
}
-void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
+void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem)
{
SharedBitmap* bitmap = m_data.m_bitmap.get();
unsigned char* dst = (unsigned char*)bitmap->bytes();
@@ -229,7 +231,7 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
notImplemented();
}
-String ImageBuffer::toDataURL(const String& mimeType, const double*) const
+String ImageBuffer::toDataURL(const String& mimeType, const double*, CoordinateSystem) const
{
if (!m_data.m_bitmap->bytes())
return "data:,";
diff --git a/Source/WebCore/platform/graphics/wx/FontPlatformData.h b/Source/WebCore/platform/graphics/wx/FontPlatformData.h
index 93be5a9a8..c03377b19 100644
--- a/Source/WebCore/platform/graphics/wx/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/wx/FontPlatformData.h
@@ -152,6 +152,8 @@ public:
// We don't support this yet, so just return the default value for now.
FontWidthVariant widthVariant() const { return RegularWidth; }
+
+ bool isCompositeFontReference() const { return false; }
#if OS(WINDOWS)
bool useGDI() const;
diff --git a/Source/WebCore/platform/graphics/wx/GradientWx.cpp b/Source/WebCore/platform/graphics/wx/GradientWx.cpp
index fc4661e1b..056deda13 100644
--- a/Source/WebCore/platform/graphics/wx/GradientWx.cpp
+++ b/Source/WebCore/platform/graphics/wx/GradientWx.cpp
@@ -27,24 +27,81 @@
#include "Gradient.h"
#include "CSSParser.h"
+#include "GraphicsContext.h"
#include "NotImplemented.h"
+#include <algorithm>
+
+#include <wx/dc.h>
+#include <wx/dcgraph.h>
+#include <wx/graphics.h>
+
+using namespace std;
+
namespace WebCore {
void Gradient::platformDestroy()
{
- notImplemented();
+ delete m_gradient;
}
PlatformGradient Gradient::platformGradient()
{
- notImplemented();
- return 0;
+ if (m_gradient)
+ return m_gradient;
+
+#if wxCHECK_VERSION(2, 9, 1)
+ sortStopsIfNecessary();
+
+ wxGraphicsRenderer* renderer = 0;
+#if wxUSE_CAIRO
+ renderer = wxGraphicsRenderer::GetCairoRenderer();
+#else
+ renderer = wxGraphicsRenderer::GetDefaultRenderer();
+#endif
+ if (renderer) {
+ wxGraphicsGradientStops stops;
+ Vector<ColorStop>::iterator stopIterator = m_stops.begin();
+ int numStops = 0;
+ stops.SetStartColour(wxColour(255*stopIterator->red, 255*stopIterator->green, 255*stopIterator->blue, 255*stopIterator->alpha));
+
+ while (stopIterator != m_stops.end()) {
+ double position = stopIterator->stop;
+ if (m_radial && m_r0)
+ position = min((m_r0 / m_r1+position*(1.0f-m_r0 / m_r1)), 1.0);
+ stops.Add(wxGraphicsGradientStop(wxColour(255*stopIterator->red, 255*stopIterator->green, 255*stopIterator->blue, 255*stopIterator->alpha), position));
+ stopIterator++;
+ numStops++;
+ }
+ stopIterator--;
+ stops.SetEndColour(wxColour(255*stopIterator->red, 255*stopIterator->green, 255*stopIterator->blue, 255*stopIterator->alpha));
+
+ wxGraphicsBrush gradient;
+ if (numStops >= 2) {
+ if (m_radial)
+ gradient = renderer->CreateRadialGradientBrush(m_p1.x(), m_p1.y(), m_p0.x(), m_p0.y(), m_r1, stops);
+ else
+ gradient = renderer->CreateLinearGradientBrush(m_p0.x(), m_p0.y(), m_p1.x(), m_p1.y(), stops);
+ }
+ m_gradient = new wxGraphicsBrush(gradient);
+ }
+#endif
+ return m_gradient;
}
-void Gradient::fill(GraphicsContext*, const FloatRect&)
-{
- notImplemented();
+void Gradient::fill(GraphicsContext* c, const FloatRect& r)
+{
+#if wxCHECK_VERSION(2, 9, 1)
+ wxGCDC* context = dynamic_cast<wxGCDC*>(c->platformContext());
+
+ if (!context)
+ return;
+ wxGraphicsContext* gradientContext = context->GetGraphicsContext();
+
+ gradientContext->SetPen(*wxTRANSPARENT_PEN);
+ gradientContext->SetBrush(*platformGradient());
+ gradientContext->DrawRectangle(r.x(), r.y(), r.width(), r.height());
+#endif
}
} //namespace
diff --git a/Source/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/Source/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
index 452638b01..54c0d98b6 100644
--- a/Source/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
+++ b/Source/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
@@ -442,13 +442,13 @@ void GraphicsContext::drawLineForText(const FloatPoint& origin, float width, boo
restore();
}
-void GraphicsContext::drawLineForTextChecking(const FloatPoint& origin, float width, TextCheckingLineStyle style)
+void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& origin, float width, DocumentMarkerLineStyle style)
{
switch (style) {
- case TextCheckingSpellingLineStyle:
+ case DocumentMarkerSpellingLineStyle:
m_data->context->SetPen(wxPen(*wxRED, 2, wxLONG_DASH));
break;
- case TextCheckingGrammarLineStyle:
+ case DocumentMarkerGrammarLineStyle:
m_data->context->SetPen(wxPen(*wxGREEN, 2, wxLONG_DASH));
break;
default:
diff --git a/Source/WebCore/platform/graphics/wx/ImageBufferDataWx.h b/Source/WebCore/platform/graphics/wx/ImageBufferDataWx.h
index 9961fee6a..67f87c924 100644
--- a/Source/WebCore/platform/graphics/wx/ImageBufferDataWx.h
+++ b/Source/WebCore/platform/graphics/wx/ImageBufferDataWx.h
@@ -23,7 +23,14 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "OwnPtr.h"
+#include <wtf/OwnPtr.h>
+
+#include <wx/bitmap.h>
+#include <wx/dcmemory.h>
+
+class wxGCDC;
+class wxGraphicsContext;
+class wxMemoryDC;
namespace WebCore {
@@ -32,6 +39,11 @@ class IntSize;
class ImageBufferData {
public:
ImageBufferData(const IntSize&);
+ ~ImageBufferData();
+ wxBitmap m_bitmap;
+ wxMemoryDC* m_memDC;
+ wxGCDC* m_gcdc;
+ wxGraphicsContext* m_graphics;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp b/Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp
index 800bc8709..0cdbc7b3b 100644
--- a/Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp
+++ b/Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp
@@ -27,51 +27,119 @@
#include "config.h"
#include "ImageBuffer.h"
+#include "Base64.h"
+#include "BitmapImage.h"
#include "GraphicsContext.h"
+#include "Image.h"
#include "ImageData.h"
#include "NotImplemented.h"
+#include "UnusedParam.h"
+#include <wtf/UnusedParam.h>
+
+// see http://trac.wxwidgets.org/ticket/11482
+#ifdef __WXMSW__
+# include "wx/msw/winundef.h"
+#endif
+
+#include <wx/defs.h>
+#include <wx/bitmap.h>
+#include <wx/dc.h>
+#include <wx/dcgraph.h>
+#include <wx/dcmemory.h>
+#include <wx/graphics.h>
+#include <wx/image.h>
+#include <wx/rawbmp.h>
+
namespace WebCore {
-ImageBufferData::ImageBufferData(const IntSize&)
+ImageBufferData::ImageBufferData(const IntSize& size)
{
+ m_bitmap.Create(size.width(), size.height(), 32);
+ {
+ wxAlphaPixelData pixData(m_bitmap, wxPoint(0, 0), wxSize(size.width(), size.height()));
+ ASSERT(pixData);
+ if (pixData) {
+ wxAlphaPixelData::Iterator p(pixData);
+ for (int y = 0; y < size.height(); y++) {
+ wxAlphaPixelData::Iterator rowStart = p;
+ for (int x = 0; x < size.width(); x++) {
+ p.Red() = 0;
+ p.Blue() = 0;
+ p.Green() = 0;
+ // FIXME: The below should be transparent but cannot be on GDI/GDK (see wxWidgets bugs #10066 and #2474)
+#if wxUSE_CAIRO || defined(__WXMAC__)
+ p.Alpha() = 0;
+#endif
+ ++p;
+ }
+ p = rowStart;
+ p.OffsetY(pixData, 1);
+ }
+ }
+ }
+ // http://www.w3.org/TR/2009/WD-html5-20090212/the-canvas-element.html#canvaspixelarray
+ // "When the canvas is initialized it must be set to fully transparent black."
+
+ m_memDC = new wxMemoryDC(m_bitmap);
+ wxGraphicsRenderer* renderer = wxGraphicsRenderer::GetCairoRenderer();
+ if (!renderer)
+ renderer = wxGraphicsRenderer::GetDefaultRenderer();
+ m_graphics = renderer->CreateContext(*m_memDC);
+ m_gcdc = new wxGCDC(m_graphics);
}
-ImageBuffer::ImageBuffer(const IntSize&, ColorSpace imageColorSpace, RenderingMode, DeferralMode, bool& success) :
- m_data(IntSize())
+ImageBufferData::~ImageBufferData()
{
- notImplemented();
- success = false;
+ delete m_gcdc;
+ delete m_memDC;
+}
+
+ImageBuffer::ImageBuffer(const IntSize& size, float resolutionScale, ColorSpace colorSpace, RenderingMode, DeferralMode, bool& success)
+ : m_data(size)
+ , m_size(size)
+ , m_logicalSize(size)
+{
+ // FIXME: Respect resoutionScale to support high-DPI canvas.
+ UNUSED_PARAM(resolutionScale);
+ // FIXME: colorSpace is not used
+ UNUSED_PARAM(colorSpace);
+
+ if (m_data.m_gcdc->IsOk()) {
+ m_context = adoptPtr(new WebCore::GraphicsContext(m_data.m_gcdc));
+ success = true;
+ } else
+ success = false;
}
ImageBuffer::~ImageBuffer()
{
+
}
GraphicsContext* ImageBuffer::context() const
{
- notImplemented();
- return 0;
+ return m_context.get();
}
-PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect, CoordinateSystem) const
{
notImplemented();
return 0;
}
-PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem) const
{
notImplemented();
return 0;
}
-void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
+void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem)
{
notImplemented();
}
-
-String ImageBuffer::toDataURL(const String&, const double*) const
+
+String ImageBuffer::toDataURL(const String& mimeType, const double*, CoordinateSystem) const
{
notImplemented();
return String();
@@ -80,25 +148,26 @@ String ImageBuffer::toDataURL(const String&, const double*) const
PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior) const
{
ASSERT(copyBehavior == CopyBackingStore);
- notImplemented();
- return 0;
+
+ RefPtr<BitmapImage> img = BitmapImage::create(m_data.m_bitmap);
+ return img.release();
}
-void ImageBuffer::clip(GraphicsContext*, const FloatRect&) const
+void ImageBuffer::clip(GraphicsContext* context, const FloatRect& rect) const
{
- notImplemented();
+ context->clip(rect);
}
-void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
- CompositeOperator op, bool useLowQualityScale)
+void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, bool useLowQualityScale)
{
RefPtr<Image> imageCopy = copyImage(CopyBackingStore);
- context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
+ context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, DoNotRespectImageOrientation, useLowQualityScale);
}
void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform,
const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
{
+ ASSERT(context);
RefPtr<Image> imageCopy = copyImage(CopyBackingStore);
imageCopy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
}
diff --git a/Source/WebCore/platform/graphics/wx/ImageWx.cpp b/Source/WebCore/platform/graphics/wx/ImageWx.cpp
index 28a6dd8fb..85667dd36 100644
--- a/Source/WebCore/platform/graphics/wx/ImageWx.cpp
+++ b/Source/WebCore/platform/graphics/wx/ImageWx.cpp
@@ -85,13 +85,51 @@ void BitmapImage::initPlatformData()
// FIXME: NYI
}
+BitmapImage::BitmapImage(const wxBitmap& bitmap)
+ : Image(0)
+ , m_currentFrame(0)
+ , m_frames(0)
+ , m_frameTimer(0)
+ , m_repetitionCount(cAnimationNone)
+ , m_repetitionCountStatus(Unknown)
+ , m_repetitionsComplete(0)
+ , m_isSolidColor(false)
+ , m_checkedForSolidColor(false)
+ , m_animationFinished(true)
+ , m_allDataReceived(true)
+ , m_haveSize(true)
+ , m_sizeAvailable(true)
+ , m_decodedSize(0)
+ , m_haveFrameCount(true)
+ , m_frameCount(1)
+{
+ initPlatformData();
+
+ m_decodedSize = bitmap.GetWidth() * bitmap.GetHeight() * 4;
+ m_size = IntSize(bitmap.GetWidth(), bitmap.GetHeight());
+
+ wxGraphicsRenderer* renderer = 0;
+#if wxUSE_CAIRO
+ renderer = wxGraphicsRenderer::GetCairoRenderer();
+#else
+ renderer = wxGraphicsRenderer::GetDefaultRenderer();
+#endif
+ if (renderer) {
+ wxGraphicsBitmap* gbmp = new wxGraphicsBitmap(renderer->CreateBitmap(bitmap));
+ ASSERT(!gbmp->IsNull());
+
+ m_frames.grow(1);
+ m_frames[0].m_frame = gbmp;
+ m_frames[0].m_haveMetadata = true;
+ checkForSolidColor();
+ }
+}
+
+
// Drawing Routines
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
{
- if (!m_source.initialized())
- return;
-
if (mayFillWithSolidColor()) {
fillWithSolidColor(ctxt, dst, solidColor(), styleColorSpace, op);
return;
diff --git a/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp b/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
index cb7fb3d7a..c2e4f2b84 100644
--- a/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
+++ b/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
@@ -193,5 +193,13 @@ float SimpleFontData::widthForGDIGlyph(Glyph glyph) const
return width;
}
#endif
+
+#if OS(DARWIN)
+const SimpleFontData* SimpleFontData::getCompositeFontReferenceFontData(NSFont *key) const
+{
+ return 0;
+}
+
+#endif
}
diff --git a/Source/WebCore/platform/graphics/wx/TransformationMatrixWx.cpp b/Source/WebCore/platform/graphics/wx/TransformationMatrixWx.cpp
index e87c7ed52..0f4230df8 100644
--- a/Source/WebCore/platform/graphics/wx/TransformationMatrixWx.cpp
+++ b/Source/WebCore/platform/graphics/wx/TransformationMatrixWx.cpp
@@ -27,7 +27,7 @@
#include "AffineTransform.h"
#include "TransformationMatrix.h"
-#include "Assertions.h"
+#include <wtf/Assertions.h>
#include "FloatRect.h"
#include "IntRect.h"
diff --git a/Source/WebCore/platform/gtk/AsyncFileSystemGtk.cpp b/Source/WebCore/platform/gtk/AsyncFileSystemGtk.cpp
index c1db006a8..6b018843f 100644
--- a/Source/WebCore/platform/gtk/AsyncFileSystemGtk.cpp
+++ b/Source/WebCore/platform/gtk/AsyncFileSystemGtk.cpp
@@ -35,30 +35,30 @@ bool AsyncFileSystem::isAvailable()
return false;
}
-bool AsyncFileSystem::isValidType(Type type)
+bool AsyncFileSystem::isValidType(FileSystemType type)
{
notImplemented();
return false;
}
-PassOwnPtr<AsyncFileSystem> AsyncFileSystem::create(Type type)
+PassOwnPtr<AsyncFileSystem> AsyncFileSystem::create(FileSystemType type)
{
return adoptPtr(new AsyncFileSystemGtk(type));
}
-void AsyncFileSystem::openFileSystem(const String& basePath, const String& storageIdentifier, Type type, bool, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
+void AsyncFileSystem::openFileSystem(const String& basePath, const String& storageIdentifier, FileSystemType type, bool, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
{
notImplemented();
callbacks->didFail(NOT_SUPPORTED_ERR);
}
-bool AsyncFileSystem::crackFileSystemURL(const KURL& url, AsyncFileSystem::Type& type, String& filePath)
+bool AsyncFileSystem::crackFileSystemURL(const KURL& url, FileSystemType& type, String& filePath)
{
notImplemented();
return false;
}
-AsyncFileSystemGtk::AsyncFileSystemGtk(AsyncFileSystem::Type type)
+AsyncFileSystemGtk::AsyncFileSystemGtk(FileSystemType type)
: AsyncFileSystem(type)
{
notImplemented();
@@ -69,10 +69,10 @@ AsyncFileSystemGtk::~AsyncFileSystemGtk()
notImplemented();
}
-String AsyncFileSystemGtk::toURL(const String& originString, const String& fullPath)
+KURL AsyncFileSystemGtk::toURL(const String& originString, const String& fullPath) const
{
notImplemented();
- return String();
+ return KURL();
}
void AsyncFileSystemGtk::move(const String& sourcePath, const String& destinationPath, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
diff --git a/Source/WebCore/platform/gtk/AsyncFileSystemGtk.h b/Source/WebCore/platform/gtk/AsyncFileSystemGtk.h
index cb45b6ea4..0bda3674f 100644
--- a/Source/WebCore/platform/gtk/AsyncFileSystemGtk.h
+++ b/Source/WebCore/platform/gtk/AsyncFileSystemGtk.h
@@ -31,10 +31,10 @@ class AsyncFileSystemCallbacks;
class AsyncFileSystemGtk : public AsyncFileSystem {
public:
- AsyncFileSystemGtk(AsyncFileSystem::Type);
+ AsyncFileSystemGtk(FileSystemType);
virtual ~AsyncFileSystemGtk();
- virtual String toURL(const String& originString, const String& fullPath);
+ virtual KURL toURL(const String& originString, const String& fullPath) const;
virtual void move(const String& sourcePath, const String& destinationPath, PassOwnPtr<AsyncFileSystemCallbacks>);
virtual void copy(const String& sourcePath, const String& destinationPath, PassOwnPtr<AsyncFileSystemCallbacks>);
virtual void remove(const String& path, PassOwnPtr<AsyncFileSystemCallbacks>);
diff --git a/Source/WebCore/platform/gtk/CompositionResults.h b/Source/WebCore/platform/gtk/CompositionResults.h
new file mode 100644
index 000000000..87f5bf7c9
--- /dev/null
+++ b/Source/WebCore/platform/gtk/CompositionResults.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 CompositionResults_h
+#define CompositionResults_h
+
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+struct CompositionResults {
+ CompositionResults()
+ : preeditCursorOffset(0)
+ {
+ }
+
+ CompositionResults(String simpleString)
+ : simpleString(simpleString)
+ , preeditCursorOffset(0)
+ {
+ }
+
+ CompositionResults(String confirmedComposition, String preedit, int preeditCursorOffset)
+ : confirmedComposition(confirmedComposition)
+ , preedit(preedit)
+ , preeditCursorOffset(preeditCursorOffset)
+ {
+ }
+
+ bool compositionUpdated() const
+ {
+ return !confirmedComposition.isNull() || !preedit.isNull();
+ }
+
+ // Some simple input methods return a string for all keyboard events. This
+ // value should be treated as the string representation of the keycode.
+ String simpleString;
+
+ // If the input method had a "real" composition it will be stored here.
+ String confirmedComposition;
+
+ // The event may have caused the preedit to update.
+ String preedit;
+ int preeditCursorOffset;
+};
+
+}
+
+#endif // CompositionResults_h
diff --git a/Source/WebCore/platform/gtk/ContextMenuGtk.cpp b/Source/WebCore/platform/gtk/ContextMenuGtk.cpp
index 51072f7f5..62a7eecd2 100644
--- a/Source/WebCore/platform/gtk/ContextMenuGtk.cpp
+++ b/Source/WebCore/platform/gtk/ContextMenuGtk.cpp
@@ -18,9 +18,12 @@
*/
#include "config.h"
+
+#if ENABLE(CONTEXT_MENUS)
+
#include "ContextMenu.h"
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#include <gtk/gtk.h>
namespace WebCore {
@@ -113,3 +116,5 @@ PlatformMenuDescription platformMenuDescription(Vector<ContextMenuItem>& subMenu
}
}
+
+#endif // ENABLE(CONTEXT_MENUS)
diff --git a/Source/WebCore/platform/gtk/ContextMenuItemGtk.cpp b/Source/WebCore/platform/gtk/ContextMenuItemGtk.cpp
index 227a7a1b2..68ae5a5de 100644
--- a/Source/WebCore/platform/gtk/ContextMenuItemGtk.cpp
+++ b/Source/WebCore/platform/gtk/ContextMenuItemGtk.cpp
@@ -20,11 +20,13 @@
#include "config.h"
+#if ENABLE(CONTEXT_MENUS)
+
#include "ContextMenuItem.h"
#include "ContextMenu.h"
-#include "GOwnPtr.h"
-#include "GRefPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
+#include <wtf/gobject/GRefPtr.h>
#include <gtk/gtk.h>
#include <wtf/text/CString.h>
@@ -271,3 +273,5 @@ GtkAction* ContextMenuItem::gtkAction() const
}
}
+
+#endif // ENABLE(CONTEXT_MENUS)
diff --git a/Source/WebCore/platform/gtk/DataObjectGtk.h b/Source/WebCore/platform/gtk/DataObjectGtk.h
index b5a81e3d5..5281b1e17 100644
--- a/Source/WebCore/platform/gtk/DataObjectGtk.h
+++ b/Source/WebCore/platform/gtk/DataObjectGtk.h
@@ -20,10 +20,10 @@
#define DataObjectGtk_h
#include "FileList.h"
-#include <GRefPtr.h>
#include "KURL.h"
#include "Range.h"
#include <wtf/RefCounted.h>
+#include <wtf/gobject/GRefPtr.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringHash.h>
diff --git a/Source/WebCore/platform/gtk/DragImageGtk.cpp b/Source/WebCore/platform/gtk/DragImageGtk.cpp
index 71a65e113..0198dec28 100644
--- a/Source/WebCore/platform/gtk/DragImageGtk.cpp
+++ b/Source/WebCore/platform/gtk/DragImageGtk.cpp
@@ -73,9 +73,10 @@ DragImageRef dissolveDragImageToFraction(DragImageRef image, float fraction)
return image;
}
-DragImageRef createDragImageFromImage(Image* image)
+DragImageRef createDragImageFromImage(Image* image, RespectImageOrientationEnum)
{
- return cairo_surface_reference(image->nativeImageForCurrentFrame());
+ NativeImageCairo* nativeImage = image->nativeImageForCurrentFrame();
+ return nativeImage ? cairo_surface_reference(nativeImage->surface()) : 0;
}
DragImageRef createDragImageIconForCachedImage(CachedImage*)
diff --git a/Source/WebCore/platform/gtk/ErrorsGtk.cpp b/Source/WebCore/platform/gtk/ErrorsGtk.cpp
index 81ca8fd4d..754d55e76 100644
--- a/Source/WebCore/platform/gtk/ErrorsGtk.cpp
+++ b/Source/WebCore/platform/gtk/ErrorsGtk.cpp
@@ -20,6 +20,9 @@
#include "config.h"
#include "ErrorsGtk.h"
+#include "DocumentLoader.h"
+#include "Frame.h"
+#include "PrintContext.h"
#include "ResourceError.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
@@ -87,4 +90,25 @@ ResourceError downloadDestinationError(const ResourceResponse& response, const S
response.url().string(), errorMessage);
}
+ResourceError printError(const PrintContext* printContext, const String& errorMessage)
+{
+ DocumentLoader* documentLoader = printContext->frame()->loader()->documentLoader();
+ return ResourceError(errorDomainPrint, PrintErrorGeneral,
+ documentLoader ? documentLoader->url() : KURL(), errorMessage);
+}
+
+ResourceError printerNotFoundError(const PrintContext* printContext)
+{
+ DocumentLoader* documentLoader = printContext->frame()->loader()->documentLoader();
+ return ResourceError(errorDomainPrint, PrintErrorPrinterNotFound,
+ documentLoader ? documentLoader->url() : KURL(), _("Printer not found"));
+}
+
+ResourceError invalidPageRangeToPrint(const PrintContext* printContext)
+{
+ DocumentLoader* documentLoader = printContext->frame()->loader()->documentLoader();
+ return ResourceError(errorDomainPrint, PrintErrorInvalidPageRange,
+ documentLoader ? documentLoader->url() : KURL(), _("Invalid page range"));
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/gtk/ErrorsGtk.h b/Source/WebCore/platform/gtk/ErrorsGtk.h
index 7a9105d23..198d1fbd9 100644
--- a/Source/WebCore/platform/gtk/ErrorsGtk.h
+++ b/Source/WebCore/platform/gtk/ErrorsGtk.h
@@ -24,6 +24,7 @@
namespace WebCore {
+class PrintContext;
class ResourceError;
class ResourceRequest;
class ResourceResponse;
@@ -32,6 +33,7 @@ const char* const errorDomainNetwork = "WebKitNetworkError";
const char* const errorDomainPolicy = "WebKitPolicyError";
const char* const errorDomainPlugin = "WebKitPluginError";
const char* const errorDomainDownload = "WebKitDownloadError";
+const char* const errorDomainPrint = "WebKitPrintError";
enum NetworkError {
NetworkErrorFailed = 399,
@@ -65,6 +67,12 @@ enum DownloadError {
DownloadErrorDestination = 401
};
+enum PrintError {
+ PrintErrorGeneral = 599,
+ PrintErrorPrinterNotFound = 500,
+ PrintErrorInvalidPageRange = 501
+};
+
ResourceError cancelledError(const ResourceRequest&);
ResourceError blockedError(const ResourceRequest&);
ResourceError cannotShowURLError(const ResourceRequest&);
@@ -75,6 +83,9 @@ ResourceError pluginWillHandleLoadError(const ResourceResponse&);
ResourceError downloadNetworkError(const ResourceError&);
ResourceError downloadCancelledByUserError(const ResourceResponse&);
ResourceError downloadDestinationError(const ResourceResponse&, const String& errorMessage);
+ResourceError printError(const PrintContext*, const String& errorMessage);
+ResourceError printerNotFoundError(const PrintContext*);
+ResourceError invalidPageRangeToPrint(const PrintContext*);
}
diff --git a/Source/WebCore/platform/gtk/FileSystemGtk.cpp b/Source/WebCore/platform/gtk/FileSystemGtk.cpp
index 950d61823..a3b448df4 100644
--- a/Source/WebCore/platform/gtk/FileSystemGtk.cpp
+++ b/Source/WebCore/platform/gtk/FileSystemGtk.cpp
@@ -23,7 +23,7 @@
#include "config.h"
#include "FileSystem.h"
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#include "PlatformString.h"
#include "UUID.h"
#include <gio/gio.h>
diff --git a/Source/WebCore/platform/gtk/GOwnPtrGtk.h b/Source/WebCore/platform/gtk/GOwnPtrGtk.h
index c5d9cdcba..bd5e8371e 100644
--- a/Source/WebCore/platform/gtk/GOwnPtrGtk.h
+++ b/Source/WebCore/platform/gtk/GOwnPtrGtk.h
@@ -20,7 +20,7 @@
#ifndef GOwnPtrGtk_h
#define GOwnPtrGtk_h
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
namespace WTF {
diff --git a/Source/WebCore/platform/gtk/GtkAuthenticationDialog.h b/Source/WebCore/platform/gtk/GtkAuthenticationDialog.h
index f00ee299f..23f6f5574 100644
--- a/Source/WebCore/platform/gtk/GtkAuthenticationDialog.h
+++ b/Source/WebCore/platform/gtk/GtkAuthenticationDialog.h
@@ -22,7 +22,7 @@
#define LIBSOUP_I_HAVE_READ_BUG_594377_AND_KNOW_SOUP_PASSWORD_MANAGER_MIGHT_GO_AWAY
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#include "GRefPtrGtk.h"
#include <libsoup/soup.h>
#include <wtf/FastAllocBase.h>
diff --git a/Source/WebCore/platform/gtk/GtkInputMethodFilter.cpp b/Source/WebCore/platform/gtk/GtkInputMethodFilter.cpp
new file mode 100644
index 000000000..3e06cd481
--- /dev/null
+++ b/Source/WebCore/platform/gtk/GtkInputMethodFilter.cpp
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "GtkInputMethodFilter.h"
+
+#include "GOwnPtrGtk.h"
+#include "GtkVersioning.h"
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#include <wtf/MathExtras.h>
+
+// The Windows composition key event code is 299 or VK_PROCESSKEY. We need to
+// emit this code for web compatibility reasons when key events trigger
+// composition results. GDK doesn't have an equivalent, so we send VoidSymbol
+// here to WebCore. PlatformKeyEvent knows to convert this code into
+// VK_PROCESSKEY.
+const int gCompositionEventKeyCode = GDK_KEY_VoidSymbol;
+
+namespace WebCore {
+
+static void handleCommitCallback(GtkIMContext*, const char* compositionString, GtkInputMethodFilter* filter)
+{
+ filter->handleCommit(compositionString);
+}
+
+static void handlePreeditStartCallback(GtkIMContext*, GtkInputMethodFilter* filter)
+{
+ filter->handlePreeditStart();
+}
+
+static void handlePreeditChangedCallback(GtkIMContext*, GtkInputMethodFilter* filter)
+{
+ filter->handlePreeditChanged();
+}
+
+static void handlePreeditEndCallback(GtkIMContext*, GtkInputMethodFilter* filter)
+{
+ filter->handlePreeditEnd();
+}
+
+static void handleWidgetRealize(GtkWidget* widget, GtkInputMethodFilter* filter)
+{
+ GdkWindow* window = gtk_widget_get_window(widget);
+ ASSERT(window);
+ gtk_im_context_set_client_window(filter->context(), window);
+}
+
+void GtkInputMethodFilter::setWidget(GtkWidget* widget)
+{
+ ASSERT(!m_widget);
+
+ m_widget = widget;
+ if (GdkWindow* window = gtk_widget_get_window(m_widget))
+ handleWidgetRealize(m_widget, this);
+ else
+ g_signal_connect_after(widget, "realize", G_CALLBACK(handleWidgetRealize), this);
+}
+
+void GtkInputMethodFilter::setCursorRect(const IntRect& cursorRect)
+{
+ // Don't move the window unless the cursor actually moves more than 10
+ // pixels. This prevents us from making the window flash during minor
+ // cursor adjustments.
+ static const int windowMovementThreshold = 10 * 10;
+ if (cursorRect.location().distanceSquaredToPoint(m_lastCareLocation) < windowMovementThreshold)
+ return;
+
+ m_lastCareLocation = cursorRect.location();
+ IntRect translatedRect = cursorRect;
+
+ ASSERT(m_widget);
+ GtkAllocation allocation;
+ gtk_widget_get_allocation(m_widget, &allocation);
+ translatedRect.move(allocation.x, allocation.y);
+
+ GdkRectangle gdkCursorRect = cursorRect;
+ gtk_im_context_set_cursor_location(m_context.get(), &gdkCursorRect);
+}
+
+GtkInputMethodFilter::GtkInputMethodFilter()
+ : m_cursorOffset(0)
+ , m_context(adoptGRef(gtk_im_multicontext_new()))
+ , m_widget(0)
+ , m_enabled(false)
+ , m_composingTextCurrently(false)
+ , m_filteringKeyEvent(false)
+ , m_preeditChanged(false)
+ , m_preventNextCommit(false)
+ , m_justSentFakeKeyUp(false)
+ , m_lastFilteredKeyPressCodeWithNoResults(GDK_KEY_VoidSymbol)
+{
+ g_signal_connect(m_context.get(), "commit", G_CALLBACK(handleCommitCallback), this);
+ g_signal_connect(m_context.get(), "preedit-start", G_CALLBACK(handlePreeditStartCallback), this);
+ g_signal_connect(m_context.get(), "preedit-changed", G_CALLBACK(handlePreeditChangedCallback), this);
+ g_signal_connect(m_context.get(), "preedit-end", G_CALLBACK(handlePreeditEndCallback), this);
+}
+
+GtkInputMethodFilter::~GtkInputMethodFilter()
+{
+ g_signal_handlers_disconnect_by_func(m_context.get(), reinterpret_cast<void*>(handleCommitCallback), this);
+ g_signal_handlers_disconnect_by_func(m_context.get(), reinterpret_cast<void*>(handlePreeditStartCallback), this);
+ g_signal_handlers_disconnect_by_func(m_context.get(), reinterpret_cast<void*>(handlePreeditChangedCallback), this);
+ g_signal_handlers_disconnect_by_func(m_context.get(), reinterpret_cast<void*>(handlePreeditEndCallback), this);
+ g_signal_handlers_disconnect_by_func(m_widget, reinterpret_cast<void*>(handleWidgetRealize), this);
+}
+
+void GtkInputMethodFilter::setEnabled(bool enabled)
+{
+ m_enabled = enabled;
+ if (enabled)
+ gtk_im_context_focus_in(m_context.get());
+ else
+ gtk_im_context_focus_out(m_context.get());
+}
+
+bool GtkInputMethodFilter::filterKeyEvent(GdkEventKey* event)
+{
+ if (!canEdit() || !m_enabled)
+ return sendSimpleKeyEvent(event);
+
+ m_preeditChanged = false;
+ m_filteringKeyEvent = true;
+
+ unsigned int lastFilteredKeyPressCodeWithNoResults = m_lastFilteredKeyPressCodeWithNoResults;
+ m_lastFilteredKeyPressCodeWithNoResults = GDK_KEY_VoidSymbol;
+
+ bool filtered = gtk_im_context_filter_keypress(m_context.get(), event);
+ m_filteringKeyEvent = false;
+
+ bool justSentFakeKeyUp = m_justSentFakeKeyUp;
+ m_justSentFakeKeyUp = false;
+ if (justSentFakeKeyUp && event->type == GDK_KEY_RELEASE)
+ return true;
+
+ // Simple input methods work such that even normal keystrokes fire the
+ // commit signal. We detect those situations and treat them as normal
+ // key events, supplying the commit string as the key character.
+ if (filtered && !m_composingTextCurrently && !m_preeditChanged && m_confirmedComposition.length() == 1) {
+ bool result = sendSimpleKeyEvent(event, m_confirmedComposition);
+ m_confirmedComposition = String();
+ return result;
+ }
+
+ if (filtered && event->type == GDK_KEY_PRESS) {
+ if (!m_preeditChanged && m_confirmedComposition.isNull()) {
+ m_composingTextCurrently = true;
+ m_lastFilteredKeyPressCodeWithNoResults = event->keyval;
+ return true;
+ }
+
+ bool result = sendKeyEventWithCompositionResults(event);
+ if (!m_confirmedComposition.isEmpty()) {
+ m_composingTextCurrently = false;
+ m_confirmedComposition = String();
+ }
+ return result;
+ }
+
+ // If we previously filtered a key press event and it yielded no results. Suppress
+ // the corresponding key release event to avoid confusing the web content.
+ if (event->type == GDK_KEY_RELEASE && lastFilteredKeyPressCodeWithNoResults == event->keyval)
+ return true;
+
+ // At this point a keystroke was either:
+ // 1. Unfiltered
+ // 2. A filtered keyup event. As the IME code in EditorClient.h doesn't
+ // ever look at keyup events, we send any composition results before
+ // the key event.
+ // Both might have composition results or not.
+ //
+ // It's important to send the composition results before the event
+ // because some IM modules operate that way. For example (taken from
+ // the Chromium source), the latin-post input method gives this sequence
+ // when you press 'a' and then backspace:
+ // 1. keydown 'a' (filtered)
+ // 2. preedit changed to "a"
+ // 3. keyup 'a' (unfiltered)
+ // 4. keydown Backspace (unfiltered)
+ // 5. commit "a"
+ // 6. preedit end
+ if (!m_confirmedComposition.isEmpty())
+ confirmComposition();
+ if (m_preeditChanged)
+ updatePreedit();
+ return sendSimpleKeyEvent(event);
+}
+
+void GtkInputMethodFilter::notifyMouseButtonPress()
+{
+ // Confirming the composition may trigger a selection change, which
+ // might trigger further unwanted actions on the context, so we prevent
+ // that by setting m_composingTextCurrently to false.
+ m_composingTextCurrently = false;
+ confirmCurrentComposition();
+ cancelContextComposition();
+}
+
+void GtkInputMethodFilter::resetContext()
+{
+
+ // We always cancel the current WebCore composition here, in case the
+ // composition was set outside the GTK+ IME path (via a script, for
+ // instance) and we aren't tracking it.
+ cancelCurrentComposition();
+
+ if (!m_composingTextCurrently)
+ return;
+ m_composingTextCurrently = false;
+ cancelContextComposition();
+}
+
+void GtkInputMethodFilter::cancelContextComposition()
+{
+ m_preventNextCommit = !m_preedit.isEmpty();
+
+ gtk_im_context_reset(m_context.get());
+
+ m_composingTextCurrently = false;
+ m_justSentFakeKeyUp = false;
+ m_preedit = String();
+ m_confirmedComposition = String();
+}
+
+void GtkInputMethodFilter::notifyFocusedIn()
+{
+ m_enabled = true;
+ gtk_im_context_focus_in(m_context.get());
+}
+
+void GtkInputMethodFilter::notifyFocusedOut()
+{
+ if (!m_enabled)
+ return;
+
+ m_composingTextCurrently = false;
+ confirmCurrentComposition();
+ cancelContextComposition();
+ gtk_im_context_focus_out(m_context.get());
+ m_enabled = false;
+}
+
+void GtkInputMethodFilter::confirmComposition()
+{
+ confirmCompositionText(m_confirmedComposition);
+ m_confirmedComposition = String();
+}
+
+void GtkInputMethodFilter::updatePreedit()
+{
+ setPreedit(m_preedit, m_cursorOffset);
+ m_preeditChanged = false;
+}
+
+void GtkInputMethodFilter::sendCompositionAndPreeditWithFakeKeyEvents(ResultsToSend resultsToSend)
+{
+ GOwnPtr<GdkEvent> event(gdk_event_new(GDK_KEY_PRESS));
+ event->key.time = GDK_CURRENT_TIME;
+ event->key.keyval = gCompositionEventKeyCode;
+ sendKeyEventWithCompositionResults(&event->key, resultsToSend);
+
+ m_confirmedComposition = String();
+ m_composingTextCurrently = false;
+
+ event->type = GDK_KEY_RELEASE;
+ sendSimpleKeyEvent(&event->key);
+ m_justSentFakeKeyUp = true;
+}
+
+void GtkInputMethodFilter::handleCommit(const char* compositionString)
+{
+ if (m_preventNextCommit) {
+ m_preventNextCommit = false;
+ return;
+ }
+
+ if (!m_enabled)
+ return;
+
+ m_confirmedComposition += String::fromUTF8(compositionString);
+
+ // If the commit was triggered outside of a key event, just send
+ // the IME event now. If we are handling a key event, we'll decide
+ // later how to handle this.
+ if (!m_filteringKeyEvent)
+ sendCompositionAndPreeditWithFakeKeyEvents(Composition);
+}
+
+void GtkInputMethodFilter::handlePreeditStart()
+{
+ if (m_preventNextCommit || !m_enabled)
+ return;
+ m_preeditChanged = true;
+ m_preedit = "";
+}
+
+void GtkInputMethodFilter::handlePreeditChanged()
+{
+ if (!m_enabled)
+ return;
+
+ GOwnPtr<gchar> newPreedit;
+ gtk_im_context_get_preedit_string(m_context.get(), &newPreedit.outPtr(), 0, &m_cursorOffset);
+
+ if (m_preventNextCommit) {
+ if (strlen(newPreedit.get()) > 0)
+ m_preventNextCommit = false;
+ else
+ return;
+ }
+
+ m_preedit = String::fromUTF8(newPreedit.get());
+ m_cursorOffset = std::min(std::max(m_cursorOffset, 0), static_cast<int>(m_preedit.length()));
+
+ m_composingTextCurrently = !m_preedit.isEmpty();
+ m_preeditChanged = true;
+
+ if (!m_filteringKeyEvent)
+ sendCompositionAndPreeditWithFakeKeyEvents(Preedit);
+}
+
+void GtkInputMethodFilter::handlePreeditEnd()
+{
+ if (m_preventNextCommit || !m_enabled)
+ return;
+
+ m_preedit = String();
+ m_cursorOffset = 0;
+ m_preeditChanged = true;
+
+ if (!m_filteringKeyEvent)
+ updatePreedit();
+}
+
+}
diff --git a/Source/WebCore/platform/gtk/GtkInputMethodFilter.h b/Source/WebCore/platform/gtk/GtkInputMethodFilter.h
new file mode 100644
index 000000000..97a773675
--- /dev/null
+++ b/Source/WebCore/platform/gtk/GtkInputMethodFilter.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU 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 "GRefPtrGtk.h"
+#include "IntRect.h"
+#include <gdk/gdk.h>
+#include <wtf/text/WTFString.h>
+
+typedef struct _GtkIMContext GtkIMContext;
+typedef struct _GtkWidget GtkWidget;
+
+namespace WebCore {
+
+class GtkInputMethodFilter {
+public:
+ GtkInputMethodFilter();
+ ~GtkInputMethodFilter();
+
+ bool filterKeyEvent(GdkEventKey*);
+ void notifyMouseButtonPress();
+ void notifyFocusedIn();
+ void notifyFocusedOut();
+ void resetContext();
+ void setEnabled(bool);
+
+ void handleCommit(const char* compositionString);
+ void handlePreeditChanged();
+ void handlePreeditStart();
+ void handlePreeditEnd();
+
+ void confirmComposition();
+ void cancelContextComposition();
+ void updatePreedit();
+ void setCursorRect(const IntRect& location);
+
+ GtkIMContext* context() { return m_context.get(); }
+
+protected:
+ enum ResultsToSend {
+ Preedit = 1 << 1,
+ Composition = 1 << 2,
+ PreeditAndComposition = Preedit + Composition
+ };
+
+ void setWidget(GtkWidget*);
+ virtual bool canEdit() = 0;
+ virtual bool sendSimpleKeyEvent(GdkEventKey*, WTF::String eventString = String()) = 0;
+ virtual bool sendKeyEventWithCompositionResults(GdkEventKey*, ResultsToSend = PreeditAndComposition) = 0;
+ virtual void confirmCompositionText(String composition) = 0;
+ virtual void confirmCurrentComposition() = 0;
+ virtual void cancelCurrentComposition() = 0;
+ virtual void setPreedit(String, int cursorOffset) = 0;
+
+ WTF::String m_confirmedComposition;
+ WTF::String m_preedit;
+ int m_cursorOffset;
+
+private:
+ void sendCompositionAndPreeditWithFakeKeyEvents(ResultsToSend);
+
+ GRefPtr<GtkIMContext> m_context;
+ GtkWidget* m_widget;
+ bool m_enabled;
+ bool m_composingTextCurrently;
+ bool m_filteringKeyEvent;
+ bool m_preeditChanged;
+ bool m_preventNextCommit;
+ bool m_justSentFakeKeyUp;
+ unsigned int m_lastFilteredKeyPressCodeWithNoResults;
+ IntPoint m_lastCareLocation;
+};
+
+} // namespace WebCore
+
diff --git a/Source/WebCore/platform/gtk/GtkPopupMenu.cpp b/Source/WebCore/platform/gtk/GtkPopupMenu.cpp
index fd7c84c53..6f57a17dc 100644
--- a/Source/WebCore/platform/gtk/GtkPopupMenu.cpp
+++ b/Source/WebCore/platform/gtk/GtkPopupMenu.cpp
@@ -27,7 +27,7 @@
#include "config.h"
#include "GtkPopupMenu.h"
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#include "GtkVersioning.h"
#include <gtk/gtk.h>
#include <wtf/text/CString.h>
diff --git a/Source/WebCore/platform/gtk/GtkWidgetBackingStoreX11.cpp b/Source/WebCore/platform/gtk/GtkWidgetBackingStoreX11.cpp
index 1b13b0666..afead805b 100644
--- a/Source/WebCore/platform/gtk/GtkWidgetBackingStoreX11.cpp
+++ b/Source/WebCore/platform/gtk/GtkWidgetBackingStoreX11.cpp
@@ -94,15 +94,18 @@ void WidgetBackingStore::scroll(const IntRect& scrollRect, const IntSize& scroll
{
IntRect targetRect(scrollRect);
targetRect.move(scrollOffset);
- targetRect.shiftMaxXEdgeTo(targetRect.maxX() - scrollOffset.width());
- targetRect.shiftMaxYEdgeTo(targetRect.maxY() - scrollOffset.height());
+ targetRect.intersect(scrollRect);
if (targetRect.isEmpty())
return;
+ cairo_surface_flush(m_private->m_surface.get());
XCopyArea(m_private->m_display, m_private->m_pixmap, m_private->m_pixmap, m_private->m_gc,
targetRect.x() - scrollOffset.width(), targetRect.y() - scrollOffset.height(),
targetRect.width(), targetRect.height(),
targetRect.x(), targetRect.y());
+ cairo_surface_mark_dirty_rectangle(m_private->m_surface.get(),
+ targetRect.x(), targetRect.y(),
+ targetRect.width(), targetRect.height());
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/gtk/LanguageGtk.cpp b/Source/WebCore/platform/gtk/LanguageGtk.cpp
index f0fae5300..23282e441 100644
--- a/Source/WebCore/platform/gtk/LanguageGtk.cpp
+++ b/Source/WebCore/platform/gtk/LanguageGtk.cpp
@@ -20,7 +20,7 @@
#include "config.h"
#include "Language.h"
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#include "PlatformString.h"
#include <wtf/Vector.h>
#include <wtf/text/CString.h>
diff --git a/Source/WebCore/platform/gtk/LocalizedStringsGtk.cpp b/Source/WebCore/platform/gtk/LocalizedStringsGtk.cpp
index 07bed8db3..824938e09 100644
--- a/Source/WebCore/platform/gtk/LocalizedStringsGtk.cpp
+++ b/Source/WebCore/platform/gtk/LocalizedStringsGtk.cpp
@@ -31,7 +31,7 @@
#include "config.h"
#include "LocalizedStrings.h"
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#include "IntSize.h"
#include "NotImplemented.h"
#include "PlatformString.h"
@@ -342,6 +342,56 @@ String contextMenuItemTagInspectElement()
return String::fromUTF8(_("Inspect _Element"));
}
+String contextMenuItemTagUnicodeInsertLRMMark()
+{
+ return String::fromUTF8(_("LRM _Left-to-right mark"));
+}
+
+String contextMenuItemTagUnicodeInsertRLMMark()
+{
+ return String::fromUTF8(_("RLM _Right-to-left mark"));
+}
+
+String contextMenuItemTagUnicodeInsertLREMark()
+{
+ return String::fromUTF8(_("LRE Left-to-right _embedding"));
+}
+
+String contextMenuItemTagUnicodeInsertRLEMark()
+{
+ return String::fromUTF8(_("RLE Right-to-left e_mbedding"));
+}
+
+String contextMenuItemTagUnicodeInsertLROMark()
+{
+ return String::fromUTF8(_("LRO Left-to-right _override"));
+}
+
+String contextMenuItemTagUnicodeInsertRLOMark()
+{
+ return String::fromUTF8(_("RLO Right-to-left o_verride"));
+}
+
+String contextMenuItemTagUnicodeInsertPDFMark()
+{
+ return String::fromUTF8(_("PDF _Pop directional formatting"));
+}
+
+String contextMenuItemTagUnicodeInsertZWSMark()
+{
+ return String::fromUTF8(_("ZWS _Zero width space"));
+}
+
+String contextMenuItemTagUnicodeInsertZWJMark()
+{
+ return String::fromUTF8(_("ZWJ Zero width _joiner"));
+}
+
+String contextMenuItemTagUnicodeInsertZWNJMark()
+{
+ return String::fromUTF8(_("ZWNJ Zero width _non-joiner"));
+}
+
String searchMenuNoRecentSearchesText()
{
return String::fromUTF8(_("No recent searches"));
@@ -367,6 +417,11 @@ String AXDefinitionListDefinitionText()
return String::fromUTF8(_("definition"));
}
+String AXFooterRoleDescriptionText()
+{
+ return String::fromUTF8(_("footer"));
+}
+
String AXButtonActionVerb()
{
return String::fromUTF8(_("press"));
@@ -479,8 +534,10 @@ String localizedMediaControlElementString(const String& name)
return String::fromUTF8(_("remaining time"));
if (name == "StatusDisplay")
return String::fromUTF8(_("status"));
- if (name == "FullscreenButton")
- return String::fromUTF8(_("fullscreen"));
+ if (name == "EnterFullscreenButton")
+ return String::fromUTF8(_("enter fullscreen"));
+ if (name == "ExitFullscreenButton")
+ return String::fromUTF8(_("exit fullscreen"));
if (name == "SeekForwardButton")
return String::fromUTF8(_("fast forward"));
if (name == "SeekBackButton")
@@ -526,8 +583,10 @@ String localizedMediaControlElementHelpText(const String& name)
return String::fromUTF8(_("seek quickly back"));
if (name == "SeekForwardButton")
return String::fromUTF8(_("seek quickly forward"));
- if (name == "FullscreenButton")
+ if (name == "EnterFullscreenButton")
return String::fromUTF8(_("Play movie in fullscreen mode"));
+ if (name == "EnterFullscreenButton")
+ return String::fromUTF8(_("Exit fullscreen mode"));
if (name == "ShowClosedCaptionsButton")
return String::fromUTF8(_("start displaying closed captions"));
if (name == "HideClosedCaptionsButton")
diff --git a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
index 3a2409dcf..81be9306c 100644
--- a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
+++ b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
@@ -510,7 +510,8 @@ int PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode(unsigned keycode)
case GDK_F23:
case GDK_F24:
return VK_F1 + (keycode - GDK_F1);
-
+ case GDK_KEY_VoidSymbol:
+ return VK_PROCESSKEY;
default:
return 0;
}
@@ -545,12 +546,30 @@ String PlatformKeyboardEvent::singleCharacterString(unsigned val)
}
}
+static PlatformEvent::Type eventTypeForGdkKeyEvent(GdkEventKey* event)
+{
+ return event->type == GDK_KEY_RELEASE ? PlatformEvent::KeyUp : PlatformEvent::KeyDown;
+}
+
+static PlatformEvent::Modifiers modifiersForGdkKeyEvent(GdkEventKey* event)
+{
+ unsigned int modifiers = 0;
+ if (event->state & GDK_SHIFT_MASK || event->keyval == GDK_3270_BackTab)
+ modifiers |= PlatformEvent::ShiftKey;
+ if (event->state & GDK_CONTROL_MASK)
+ modifiers |= PlatformEvent::CtrlKey;
+ if (event->state & GDK_MOD1_MASK)
+ modifiers |= PlatformEvent::AltKey;
+ if (event->state & GDK_META_MASK)
+ modifiers |= PlatformEvent::MetaKey;
+ return static_cast<PlatformEvent::Modifiers>(modifiers);
+}
+
// Keep this in sync with the other platform event constructors
-// TODO: m_gdkEventKey should be refcounted
-PlatformKeyboardEvent::PlatformKeyboardEvent(GdkEventKey* event)
- : PlatformEvent((event->type == GDK_KEY_RELEASE) ? PlatformEvent::KeyUp : PlatformEvent::KeyDown, (event->state & GDK_SHIFT_MASK) || (event->keyval == GDK_3270_BackTab), event->state & GDK_CONTROL_MASK, event->state & GDK_MOD1_MASK, event->state & GDK_META_MASK, currentTime())
- , m_text(singleCharacterString(event->keyval))
- , m_unmodifiedText(singleCharacterString(event->keyval))
+PlatformKeyboardEvent::PlatformKeyboardEvent(GdkEventKey* event, const CompositionResults& compositionResults)
+ : PlatformEvent(eventTypeForGdkKeyEvent(event), modifiersForGdkKeyEvent(event), currentTime())
+ , m_text(compositionResults.simpleString.length() ? compositionResults.simpleString : singleCharacterString(event->keyval))
+ , m_unmodifiedText(m_text)
, m_keyIdentifier(keyIdentifierForGdkKeyCode(event->keyval))
, m_windowsVirtualKeyCode(windowsKeyCodeForGdkKeyCode(event->keyval))
, m_nativeVirtualKeyCode(event->keyval)
@@ -559,7 +578,11 @@ PlatformKeyboardEvent::PlatformKeyboardEvent(GdkEventKey* event)
, m_isKeypad(event->keyval >= GDK_KP_Space && event->keyval <= GDK_KP_9)
, m_isSystemKey(false)
, m_gdkEventKey(event)
+ , m_compositionResults(compositionResults)
{
+ // To match the behavior of IE, we return VK_PROCESSKEY for keys that triggered composition results.
+ if (compositionResults.compositionUpdated())
+ m_windowsVirtualKeyCode = VK_PROCESSKEY;
}
void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardCompatibilityMode)
@@ -574,6 +597,12 @@ void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardCom
if (type == PlatformEvent::RawKeyDown) {
m_text = String();
m_unmodifiedText = String();
+ } else if (type == PlatformEvent::Char && m_compositionResults.compositionUpdated()) {
+ // Having empty text, prevents this Char (which is a DOM keypress) event
+ // from going to the DOM. Keys that trigger composition events should not
+ // fire keypress.
+ m_text = String();
+ m_unmodifiedText = String();
} else {
m_keyIdentifier = String();
m_windowsVirtualKeyCode = 0;
@@ -596,9 +625,4 @@ void PlatformKeyboardEvent::getCurrentModifierState(bool& shiftKey, bool& ctrlKe
metaKey = state & GDK_META_MASK;
}
-GdkEventKey* PlatformKeyboardEvent::gdkEventKey() const
-{
- return m_gdkEventKey;
-}
-
}
diff --git a/Source/WebCore/platform/gtk/PlatformMouseEventGtk.cpp b/Source/WebCore/platform/gtk/PlatformMouseEventGtk.cpp
index 4e6200fcd..04101c1fa 100644
--- a/Source/WebCore/platform/gtk/PlatformMouseEventGtk.cpp
+++ b/Source/WebCore/platform/gtk/PlatformMouseEventGtk.cpp
@@ -27,7 +27,7 @@
#include "config.h"
#include "PlatformMouseEvent.h"
-#include "Assertions.h"
+#include <wtf/Assertions.h>
#include <gdk/gdk.h>
diff --git a/Source/WebCore/platform/gtk/PopupMenuGtk.cpp b/Source/WebCore/platform/gtk/PopupMenuGtk.cpp
index 350e082af..2f517b01e 100644
--- a/Source/WebCore/platform/gtk/PopupMenuGtk.cpp
+++ b/Source/WebCore/platform/gtk/PopupMenuGtk.cpp
@@ -28,7 +28,7 @@
#include "PopupMenuGtk.h"
#include "FrameView.h"
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#include "GtkUtilities.h"
#include "HostWindow.h"
#include <gtk/gtk.h>
diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk.cpp b/Source/WebCore/platform/gtk/RenderThemeGtk.cpp
index bb67eaf37..f05e219a2 100644
--- a/Source/WebCore/platform/gtk/RenderThemeGtk.cpp
+++ b/Source/WebCore/platform/gtk/RenderThemeGtk.cpp
@@ -26,8 +26,9 @@
#include "RenderThemeGtk.h"
#include "CSSValueKeywords.h"
+#include "FileList.h"
#include "FileSystem.h"
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#include "Gradient.h"
#include "GraphicsContext.h"
#include "GtkVersioning.h"
@@ -203,14 +204,14 @@ static GtkStateType gtkIconState(RenderTheme* theme, RenderObject* renderObject)
return GTK_STATE_NORMAL;
}
-void RenderThemeGtk::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const
+void RenderThemeGtk::adjustButtonStyle(StyleResolver*, RenderStyle* style, WebCore::Element*) const
{
// Some layout tests check explicitly that buttons ignore line-height.
if (style->appearance() == PushButtonPart)
style->setLineHeight(RenderStyle::initialLineHeight());
}
-void RenderThemeGtk::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeGtk::adjustMenuListStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// The tests check explicitly that select menu buttons ignore line height.
style->setLineHeight(RenderStyle::initialLineHeight());
@@ -219,9 +220,9 @@ void RenderThemeGtk::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle
style->resetBorderRadius();
}
-void RenderThemeGtk::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeGtk::adjustMenuListButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
{
- adjustMenuListStyle(selector, style, e);
+ adjustMenuListStyle(styleResolver, style, e);
}
bool RenderThemeGtk::paintMenuListButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
@@ -275,9 +276,9 @@ static GtkIconSize getIconSizeForPixelSize(gint pixelSize)
return GTK_ICON_SIZE_DIALOG;
}
-void RenderThemeGtk::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeGtk::adjustSearchFieldResultsButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
{
- adjustSearchFieldCancelButtonStyle(selector, style, e);
+ adjustSearchFieldCancelButtonStyle(styleResolver, style, e);
}
bool RenderThemeGtk::paintSearchFieldResultsButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
@@ -303,7 +304,7 @@ static void adjustSearchFieldIconStyle(RenderStyle* style)
style->setHeight(Length(height, Fixed));
}
-void RenderThemeGtk::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeGtk::adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
{
adjustSearchFieldIconStyle(style);
}
@@ -340,7 +341,7 @@ bool RenderThemeGtk::paintSearchFieldResultsDecoration(RenderObject* renderObjec
return false;
}
-void RenderThemeGtk::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeGtk::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
adjustSearchFieldIconStyle(style);
}
@@ -359,7 +360,7 @@ bool RenderThemeGtk::paintSearchFieldCancelButton(RenderObject* renderObject, co
return false;
}
-void RenderThemeGtk::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeGtk::adjustSearchFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// We cannot give a proper rendering when border radius is active, unfortunately.
style->resetBorderRadius();
@@ -396,14 +397,14 @@ bool RenderThemeGtk::paintCapsLockIndicator(RenderObject* renderObject, const Pa
return true;
}
-void RenderThemeGtk::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeGtk::adjustSliderTrackStyle(StyleResolver*, RenderStyle* style, Element*) const
{
style->setBoxShadow(nullptr);
}
-void RenderThemeGtk::adjustSliderThumbStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeGtk::adjustSliderThumbStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
- RenderTheme::adjustSliderThumbStyle(selector, style, element);
+ RenderTheme::adjustSliderThumbStyle(styleResolver, style, element);
style->setBoxShadow(nullptr);
}
@@ -640,7 +641,7 @@ bool RenderThemeGtk::paintMediaCurrentTime(RenderObject* renderObject, const Pai
#endif
#if ENABLE(PROGRESS_TAG)
-void RenderThemeGtk::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeGtk::adjustProgressBarStyle(StyleResolver*, RenderStyle* style, Element*) const
{
style->setBoxShadow(nullptr);
}
@@ -690,32 +691,21 @@ IntRect RenderThemeGtk::calculateProgressRect(RenderObject* renderObject, const
}
#endif
-static bool stringByAdoptingFileSystemRepresentation(gchar* systemFilename, String& result)
-{
- if (!systemFilename)
- return false;
-
- result = filenameToString(systemFilename);
- g_free(systemFilename);
-
- return true;
-}
-
-String RenderThemeGtk::fileListNameForWidth(const Vector<String>& filenames, const Font& font, int width, bool multipleFilesAllowed) const
+String RenderThemeGtk::fileListNameForWidth(const FileList* fileList, const Font& font, int width, bool multipleFilesAllowed) const
{
if (width <= 0)
return String();
- String string = fileButtonNoFileSelectedLabel();
- if (multipleFilesAllowed)
- string = fileButtonNoFilesSelectedLabel();
+ if (fileList->length() > 1)
+ return StringTruncator::rightTruncate(multipleFileUploadText(fileList->length()), width, font, StringTruncator::EnableRoundingHacks);
- if (filenames.size() == 1) {
- CString systemFilename = fileSystemRepresentation(filenames[0]);
- gchar* systemBasename = g_path_get_basename(systemFilename.data());
- stringByAdoptingFileSystemRepresentation(systemBasename, string);
- } else if (filenames.size() > 1)
- return StringTruncator::rightTruncate(multipleFileUploadText(filenames.size()), width, font, StringTruncator::EnableRoundingHacks);
+ String string;
+ if (fileList->length())
+ string = pathGetFileName(fileList->item(0)->path());
+ else if (multipleFilesAllowed)
+ string = fileButtonNoFilesSelectedLabel();
+ else
+ string = fileButtonNoFileSelectedLabel();
return StringTruncator::centerTruncate(string, width, font, StringTruncator::EnableRoundingHacks);
}
diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk.h b/Source/WebCore/platform/gtk/RenderThemeGtk.h
index c26f9c967..23b08ffea 100644
--- a/Source/WebCore/platform/gtk/RenderThemeGtk.h
+++ b/Source/WebCore/platform/gtk/RenderThemeGtk.h
@@ -28,7 +28,7 @@
#ifndef RenderThemeGtk_h
#define RenderThemeGtk_h
-#include "GRefPtr.h"
+#include <wtf/gobject/GRefPtr.h>
#include "RenderTheme.h"
typedef struct _GdkColormap GdkColormap;
@@ -110,7 +110,7 @@ protected:
virtual bool paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& r);
virtual void setRadioSize(RenderStyle* style) const;
- virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
@@ -125,28 +125,28 @@ protected:
// The former is used when a menu list button has been styled. This is used to ensure
// Aqua themed controls whenever possible. We always want to use GTK+ theming, so
// we don't maintain this differentiation.
- virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
- virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element* e) const;
+ virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSliderTrackStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSliderThumbStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual void adjustSliderThumbSize(RenderStyle*) const;
@@ -171,17 +171,17 @@ protected:
#if ENABLE(PROGRESS_TAG)
virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const;
virtual double animationDurationForProgressBar(RenderProgress*) const;
- virtual void adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&);
#endif
virtual bool paintCapsLockIndicator(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&);
private:
- virtual String fileListNameForWidth(const Vector<String>& filenames, const Font&, int width, bool multipleFilesAllowed) const;
+ virtual String fileListNameForWidth(const FileList*, const Font&, int width, bool multipleFilesAllowed) const OVERRIDE;
void platformInit();
static void setTextInputBorders(RenderStyle*);
diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk2.cpp b/Source/WebCore/platform/gtk/RenderThemeGtk2.cpp
index 50675d1e9..060383ac1 100644
--- a/Source/WebCore/platform/gtk/RenderThemeGtk2.cpp
+++ b/Source/WebCore/platform/gtk/RenderThemeGtk2.cpp
@@ -574,7 +574,7 @@ bool RenderThemeGtk::paintProgressBar(RenderObject* renderObject, const PaintInf
}
#endif
-void RenderThemeGtk::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeGtk::adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
GtkStyle* gtkStyle = gtk_widget_get_style(gtkSpinButton());
const PangoFontDescription* fontDescription = gtkStyle->font_desc;
diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp b/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp
index 356300257..5413bb795 100644
--- a/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp
+++ b/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp
@@ -77,9 +77,9 @@ static StyleContextMap& styleContextMap()
static GtkStyleContext* getStyleContext(GType widgetType)
{
- std::pair<StyleContextMap::iterator, bool> result = styleContextMap().add(widgetType, 0);
- if (!result.second)
- return result.first->second.get();
+ StyleContextMap::AddResult result = styleContextMap().add(widgetType, 0);
+ if (!result.isNewEntry)
+ return result.iterator->second.get();
GtkWidgetPath* path = gtk_widget_path_new();
gtk_widget_path_append_type(path, widgetType);
@@ -111,7 +111,7 @@ static GtkStyleContext* getStyleContext(GType widgetType)
gtk_style_context_set_path(context.get(), path);
gtk_widget_path_free(path);
- result.first->second = context;
+ result.iterator->second = context;
return context.get();
}
@@ -218,11 +218,28 @@ static void setToggleSize(GtkStyleContext* context, RenderStyle* style)
style->setHeight(Length(indicatorSize, Fixed));
}
-static void paintToggle(const RenderThemeGtk* theme, GType widgetType, RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+static void paintToggle(const RenderThemeGtk* theme, GType widgetType, RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& fullRect)
{
GtkStyleContext* context = getStyleContext(widgetType);
gtk_style_context_save(context);
+ // Some themes do not render large toggle buttons properly, so we simply
+ // shrink the rectangle back down to the default size and then center it
+ // in the full toggle button region. The reason for not simply forcing toggle
+ // buttons to be a smaller size is that we don't want to break site layouts.
+ gint indicatorSize;
+ gtk_style_context_get_style(context, "indicator-size", &indicatorSize, NULL);
+ IntRect rect(fullRect);
+ if (rect.width() > indicatorSize) {
+ rect.inflateX(-(rect.width() - indicatorSize) / 2);
+ rect.setWidth(indicatorSize); // In case rect.width() was equal to indicatorSize + 1.
+ }
+
+ if (rect.height() > indicatorSize) {
+ rect.inflateY(-(rect.height() - indicatorSize) / 2);
+ rect.setHeight(indicatorSize); // In case rect.height() was equal to indicatorSize + 1.
+ }
+
gtk_style_context_set_direction(context, static_cast<GtkTextDirection>(gtkTextDirection(renderObject->style()->direction())));
gtk_style_context_add_class(context, widgetType == GTK_TYPE_CHECK_BUTTON ? GTK_STYLE_CLASS_CHECK : GTK_STYLE_CLASS_RADIO);
@@ -366,7 +383,7 @@ static void getComboBoxMetrics(RenderStyle* style, GtkBorder& border, int& focus
if (style->appearance() == NoControlPart)
return;
- GtkStyleContext* context = getStyleContext(GTK_TYPE_BUTTON);
+ GtkStyleContext* context = getStyleContext(GTK_TYPE_COMBO_BOX);
gtk_style_context_save(context);
gtk_style_context_add_class(context, GTK_STYLE_CLASS_BUTTON);
@@ -522,12 +539,11 @@ bool RenderThemeGtk::paintMenuList(RenderObject* renderObject, const PaintInfo&
gtk_style_context_restore(arrowStyleContext);
// Paint the separator if needed.
- GtkStyleContext* separatorStyleContext = getStyleContext(GTK_TYPE_SEPARATOR);
+ GtkStyleContext* separatorStyleContext = getStyleContext(GTK_TYPE_COMBO_BOX);
gtk_style_context_save(separatorStyleContext);
gtk_style_context_set_direction(separatorStyleContext, direction);
gtk_style_context_add_class(separatorStyleContext, "separator");
- gtk_style_context_add_class(separatorStyleContext, GTK_STYLE_CLASS_BUTTON);
gboolean wideSeparators;
gint separatorWidth;
@@ -758,7 +774,7 @@ static gint spinButtonArrowSize(GtkStyleContext* context)
return arrowSize - arrowSize % 2; // Force even.
}
-void RenderThemeGtk::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeGtk::adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
GtkStyleContext* context = getStyleContext(GTK_TYPE_SPIN_BUTTON);
diff --git a/Source/WebCore/platform/gtk/TemporaryLinkStubs.cpp b/Source/WebCore/platform/gtk/TemporaryLinkStubs.cpp
index eee07cec4..cb344493d 100644
--- a/Source/WebCore/platform/gtk/TemporaryLinkStubs.cpp
+++ b/Source/WebCore/platform/gtk/TemporaryLinkStubs.cpp
@@ -47,8 +47,5 @@ namespace WebCore {
void getSupportedKeySizes(Vector<String>&) { notImplemented(); }
String signedPublicKeyAndChallengeString(unsigned keySizeIndex, const String &challengeString, const KURL &url) { return String(); }
float userIdleTime() { notImplemented(); return FLT_MAX; } // return an arbitrarily high userIdleTime so that releasing pages from the page cache isn't postponed
-void setCookieStoragePrivateBrowsingEnabled(bool) { notImplemented(); }
-void startObservingCookieChanges() { notImplemented(); }
-void stopObservingCookieChanges() { notImplemented(); }
}
diff --git a/Source/WebCore/platform/image-decoders/cairo/ImageDecoderCairo.cpp b/Source/WebCore/platform/image-decoders/cairo/ImageDecoderCairo.cpp
index 618c1d0f5..417628d32 100644
--- a/Source/WebCore/platform/image-decoders/cairo/ImageDecoderCairo.cpp
+++ b/Source/WebCore/platform/image-decoders/cairo/ImageDecoderCairo.cpp
@@ -32,10 +32,9 @@ namespace WebCore {
NativeImagePtr ImageFrame::asNewNativeImage() const
{
- return cairo_image_surface_create_for_data(
- reinterpret_cast<unsigned char*>(const_cast<PixelData*>(
- m_bytes)), CAIRO_FORMAT_ARGB32, width(), height(),
- width() * sizeof(PixelData));
+ return new NativeImageCairo(cairo_image_surface_create_for_data(
+ reinterpret_cast<unsigned char*>(const_cast<PixelData*>(m_bytes)),
+ CAIRO_FORMAT_ARGB32, width(), height(), width() * sizeof(PixelData)));
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
index d9910c92b..fb867532b 100644
--- a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
@@ -83,6 +83,14 @@ inline J_DCT_METHOD dctMethod() { return JDCT_ISLOW; }
inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_RGB; }
#endif
+#if OS(ANDROID)
+inline J_DITHER_MODE ditherMode() { return JDITHER_NONE; }
+inline bool doFancyUpsampling() { return false; }
+#else
+inline J_DITHER_MODE ditherMode() { return JDITHER_FS; }
+inline bool doFancyUpsampling() { return true; }
+#endif
+
namespace WebCore {
struct decoder_error_mgr {
@@ -306,8 +314,8 @@ public:
// FIXME -- Should reset dct_method and dither mode for final pass
// of progressive JPEG.
m_info.dct_method = dctMethod();
- m_info.dither_mode = JDITHER_FS;
- m_info.do_fancy_upsampling = true;
+ m_info.dither_mode = ditherMode();
+ m_info.do_fancy_upsampling = doFancyUpsampling();
m_info.enable_2pass_quant = false;
m_info.do_block_smoothing = true;
@@ -572,8 +580,8 @@ void JPEGImageDecoder::jpegComplete()
// Hand back an appropriately sized buffer, even if the image ended up being
// empty.
ImageFrame& buffer = m_frameBufferCache[0];
- buffer.setStatus(ImageFrame::FrameComplete);
buffer.setHasAlpha(false);
+ buffer.setStatus(ImageFrame::FrameComplete);
}
void JPEGImageDecoder::decode(bool onlySize)
diff --git a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
index bcca47401..815b0961d 100644
--- a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
@@ -361,26 +361,31 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex,
// Initialize the framebuffer if needed.
ImageFrame& buffer = m_frameBufferCache[0];
if (buffer.status() == ImageFrame::FrameEmpty) {
+ png_structp png = m_reader->pngPtr();
if (!buffer.setSize(scaledSize().width(), scaledSize().height())) {
- longjmp(JMPBUF(m_reader->pngPtr()), 1);
+ longjmp(JMPBUF(png), 1);
return;
}
+
+ if (PNG_INTERLACE_ADAM7 == png_get_interlace_type(png, m_reader->infoPtr())) {
+ unsigned colorChannels = m_reader->hasAlpha() ? 4 : 3;
+ m_reader->createInterlaceBuffer(colorChannels * size().width() * size().height());
+ if (!m_reader->interlaceBuffer()) {
+ longjmp(JMPBUF(png), 1);
+ return;
+ }
+ }
+
buffer.setStatus(ImageFrame::FramePartial);
buffer.setHasAlpha(false);
buffer.setColorProfile(m_colorProfile);
// For PNGs, the frame always fills the entire image.
buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
-
- if (png_get_interlace_type(m_reader->pngPtr(), m_reader->infoPtr()) != PNG_INTERLACE_NONE)
- m_reader->createInterlaceBuffer((m_reader->hasAlpha() ? 4 : 3) * size().width() * size().height());
}
- if (!rowBuffer)
- return;
-
- // libpng comments (pasted in here to explain what follows)
- /*
+ /* libpng comments (here to explain what follows).
+ *
* this function is called for every row in the image. If the
* image is interlacing, and you turned on the interlace handler,
* this function will be called for every row in every pass.
@@ -389,6 +394,18 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex,
* The rows and passes are called in order, so you don't really
* need the row_num and pass, but I'm supplying them because it
* may make your life easier.
+ */
+
+ // Nothing to do if the row is unchanged, or the row is outside
+ // the image bounds: libpng may send extra rows, ignore them to
+ // make our lives easier.
+ if (!rowBuffer)
+ return;
+ int y = !m_scaled ? rowIndex : scaledY(rowIndex);
+ if (y < 0 || y >= scaledSize().height())
+ return;
+
+ /* libpng comments (continued).
*
* For the non-NULL rows of interlaced images, you must call
* png_progressive_combine_row() passing in the row and the
@@ -407,31 +424,36 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex,
* old row and the new row.
*/
- png_structp png = m_reader->pngPtr();
bool hasAlpha = m_reader->hasAlpha();
unsigned colorChannels = hasAlpha ? 4 : 3;
- png_bytep row;
- png_bytep interlaceBuffer = m_reader->interlaceBuffer();
- if (interlaceBuffer) {
+ png_bytep row = rowBuffer;
+
+ if (png_bytep interlaceBuffer = m_reader->interlaceBuffer()) {
row = interlaceBuffer + (rowIndex * colorChannels * size().width());
- png_progressive_combine_row(png, row, rowBuffer);
- } else
- row = rowBuffer;
+ png_progressive_combine_row(m_reader->pngPtr(), row, rowBuffer);
+ }
- // Copy the data into our buffer.
+ // Write the decoded row pixels to the frame buffer.
int width = scaledSize().width();
- int destY = scaledY(rowIndex);
-
- // Check that the row is within the image bounds. LibPNG may supply an extra row.
- if (destY < 0 || destY >= scaledSize().height())
- return;
bool nonTrivialAlpha = false;
+
+#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
for (int x = 0; x < width; ++x) {
png_bytep pixel = row + (m_scaled ? m_scaledColumns[x] : x) * colorChannels;
unsigned alpha = hasAlpha ? pixel[3] : 255;
- buffer.setRGBA(x, destY, pixel[0], pixel[1], pixel[2], alpha);
+ buffer.setRGBA(x, y, pixel[0], pixel[1], pixel[2], alpha);
nonTrivialAlpha |= alpha < 255;
}
+#else
+ ASSERT(!m_scaled);
+ png_bytep pixel = row;
+ for (int x = 0; x < width; ++x, pixel += colorChannels) {
+ unsigned alpha = hasAlpha ? pixel[3] : 255;
+ buffer.setRGBA(x, y, pixel[0], pixel[1], pixel[2], alpha);
+ nonTrivialAlpha |= alpha < 255;
+ }
+#endif
+
if (nonTrivialAlpha && !buffer.hasAlpha())
buffer.setHasAlpha(nonTrivialAlpha);
}
diff --git a/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp b/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
index f3fd769cd..d2f06d907 100644
--- a/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
+++ b/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
@@ -119,7 +119,7 @@ static void resolveColorSpace(const SkBitmap& bitmap, CGColorSpaceRef colorSpace
{
int width = bitmap.width();
int height = bitmap.height();
- CGImageRef srcImage = SkCreateCGImageRefWithColorspace(bitmap, colorSpace);
+ RetainPtr<CGImageRef> srcImage(AdoptCF, SkCreateCGImageRefWithColorspace(bitmap, colorSpace));
SkAutoLockPixels lock(bitmap);
void* pixels = bitmap.getPixels();
RetainPtr<CGContextRef> cgBitmap(AdoptCF, CGBitmapContextCreate(pixels, width, height, 8, width * 4, deviceRGBColorSpaceRef(), kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst));
@@ -127,7 +127,7 @@ static void resolveColorSpace(const SkBitmap& bitmap, CGColorSpaceRef colorSpace
return;
CGContextSetBlendMode(cgBitmap.get(), kCGBlendModeCopy);
CGRect bounds = { {0, 0}, {width, height} };
- CGContextDrawImage(cgBitmap.get(), bounds, srcImage);
+ CGContextDrawImage(cgBitmap.get(), bounds, srcImage.get());
}
static CGColorSpaceRef createColorSpace(const ColorProfile& colorProfile)
diff --git a/Source/WebCore/platform/image-encoders/skia/JPEGImageEncoder.cpp b/Source/WebCore/platform/image-encoders/skia/JPEGImageEncoder.cpp
index eb3341cc5..22d514aa7 100644
--- a/Source/WebCore/platform/image-encoders/skia/JPEGImageEncoder.cpp
+++ b/Source/WebCore/platform/image-encoders/skia/JPEGImageEncoder.cpp
@@ -81,7 +81,7 @@ static void handleError(j_common_ptr common)
static void preMultipliedBGRAtoRGB(const unsigned char* pixels, unsigned int pixelCount, unsigned char* output)
{
- const SkPMColor* input = reinterpret_cast<const SkPMColor*>(pixels);
+ const SkPMColor* input = reinterpret_cast_ptr<const SkPMColor*>(pixels);
for (; pixelCount-- > 0; ++input) {
*output++ = SkGetPackedR32(*input);
*output++ = SkGetPackedG32(*input);
@@ -195,7 +195,7 @@ bool JPEGImageEncoder::encode(const SkBitmap& bitmap, int quality, Vector<unsign
bool JPEGImageEncoder::encode(const ImageData& imageData, int quality, Vector<unsigned char>* output)
{
- return encodePixels(imageData.size(), imageData.data()->data()->data(), false, quality, output);
+ return encodePixels(imageData.size(), imageData.data()->data(), false, quality, output);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp b/Source/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp
index 5c1162bfb..eacaa7cdb 100644
--- a/Source/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp
+++ b/Source/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp
@@ -126,7 +126,7 @@ bool PNGImageEncoder::encode(const SkBitmap& bitmap, Vector<unsigned char>* outp
bool PNGImageEncoder::encode(const ImageData& imageData, Vector<unsigned char>* output)
{
- return encodePixels(imageData.size(), imageData.data()->data()->data(), false, output);
+ return encodePixels(imageData.size(), imageData.data()->data(), false, output);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/image-encoders/skia/WEBPImageEncoder.cpp b/Source/WebCore/platform/image-encoders/skia/WEBPImageEncoder.cpp
index 9cb24fc02..ebc299d5f 100644
--- a/Source/WebCore/platform/image-encoders/skia/WEBPImageEncoder.cpp
+++ b/Source/WebCore/platform/image-encoders/skia/WEBPImageEncoder.cpp
@@ -130,7 +130,7 @@ bool WEBPImageEncoder::encode(const SkBitmap& bitmap, int quality, Vector<unsign
bool WEBPImageEncoder::encode(const ImageData& imageData, int quality, Vector<unsigned char>* output)
{
- return encodePixels(imageData.size(), imageData.data()->data()->data(), false, quality, output);
+ return encodePixels(imageData.size(), imageData.data()->data(), false, quality, output);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/leveldb/LevelDBDatabase.cpp b/Source/WebCore/platform/leveldb/LevelDBDatabase.cpp
index 41a1aefb3..273afd4de 100644
--- a/Source/WebCore/platform/leveldb/LevelDBDatabase.cpp
+++ b/Source/WebCore/platform/leveldb/LevelDBDatabase.cpp
@@ -112,6 +112,13 @@ static leveldb::Status openDB(leveldb::Comparator* comparator, leveldb::Env* env
return leveldb::DB::Open(options, path.utf8().data(), db);
}
+bool LevelDBDatabase::destroy(const String& fileName)
+{
+ leveldb::Options options;
+ const leveldb::Status s = leveldb::DestroyDB(fileName.utf8().data(), options);
+ return s.ok();
+}
+
PassOwnPtr<LevelDBDatabase> LevelDBDatabase::open(const String& fileName, const LevelDBComparator* comparator)
{
OwnPtr<ComparatorAdapter> comparatorAdapter = adoptPtr(new ComparatorAdapter(comparator));
diff --git a/Source/WebCore/platform/leveldb/LevelDBDatabase.h b/Source/WebCore/platform/leveldb/LevelDBDatabase.h
index c6ce21c03..e80b49a24 100644
--- a/Source/WebCore/platform/leveldb/LevelDBDatabase.h
+++ b/Source/WebCore/platform/leveldb/LevelDBDatabase.h
@@ -50,6 +50,7 @@ class LevelDBDatabase {
public:
static PassOwnPtr<LevelDBDatabase> open(const String& fileName, const LevelDBComparator*);
static PassOwnPtr<LevelDBDatabase> openInMemory(const LevelDBComparator*);
+ static bool destroy(const String& fileName);
~LevelDBDatabase();
bool put(const LevelDBSlice& key, const Vector<char>& value);
diff --git a/Source/WebCore/platform/leveldb/LevelDBSlice.h b/Source/WebCore/platform/leveldb/LevelDBSlice.h
index cfea1411f..22a4e4e73 100644
--- a/Source/WebCore/platform/leveldb/LevelDBSlice.h
+++ b/Source/WebCore/platform/leveldb/LevelDBSlice.h
@@ -29,7 +29,7 @@
#if USE(LEVELDB)
#include "PlatformString.h"
-#include <Vector.h>
+#include <wtf/Vector.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/leveldb/LevelDBTransaction.cpp b/Source/WebCore/platform/leveldb/LevelDBTransaction.cpp
index 9ea169cb8..5bb1b4550 100644
--- a/Source/WebCore/platform/leveldb/LevelDBTransaction.cpp
+++ b/Source/WebCore/platform/leveldb/LevelDBTransaction.cpp
@@ -370,13 +370,14 @@ void LevelDBTransaction::TransactionIterator::refreshTreeIterator() const
{
ASSERT(m_treeChanged);
- if (m_treeIterator->isValid()) {
+ m_treeChanged = false;
+
+ if (m_treeIterator->isValid() && m_treeIterator == m_current) {
m_treeIterator->reset();
return;
}
if (m_dbIterator->isValid()) {
- ASSERT(!m_treeIterator->isValid());
// There could be new nodes in the tree that we should iterate over.
@@ -393,8 +394,16 @@ void LevelDBTransaction::TransactionIterator::refreshTreeIterator() const
m_treeIterator->prev();
}
}
+}
- m_treeChanged = false;
+bool LevelDBTransaction::TransactionIterator::treeIteratorIsLower() const
+{
+ return m_comparator->compare(m_treeIterator->key(), m_dbIterator->key()) < 0;
+}
+
+bool LevelDBTransaction::TransactionIterator::treeIteratorIsHigher() const
+{
+ return m_comparator->compare(m_treeIterator->key(), m_dbIterator->key()) > 0;
}
void LevelDBTransaction::TransactionIterator::handleConflictsAndDeletes()
@@ -412,14 +421,15 @@ void LevelDBTransaction::TransactionIterator::handleConflictsAndDeletes()
m_dbIterator->prev();
}
+ // Skip over delete markers in the tree iterator until it catches up with the db iterator.
if (m_treeIterator->isValid() && m_treeIterator->isDeleted()) {
- // If the tree iterator is on a delete marker, take another step.
- if (m_direction == kForward)
+ if (m_direction == kForward && (!m_dbIterator->isValid() || treeIteratorIsLower())) {
m_treeIterator->next();
- else
+ loop = true;
+ } else if (m_direction == kReverse && (!m_dbIterator->isValid() || treeIteratorIsHigher())) {
m_treeIterator->prev();
-
- loop = true;
+ loop = true;
+ }
}
}
}
diff --git a/Source/WebCore/platform/leveldb/LevelDBTransaction.h b/Source/WebCore/platform/leveldb/LevelDBTransaction.h
index 4be91b726..6d22850c2 100644
--- a/Source/WebCore/platform/leveldb/LevelDBTransaction.h
+++ b/Source/WebCore/platform/leveldb/LevelDBTransaction.h
@@ -139,6 +139,8 @@ private:
void setCurrentIteratorToSmallestKey();
void setCurrentIteratorToLargestKey();
void refreshTreeIterator() const;
+ bool treeIteratorIsLower() const;
+ bool treeIteratorIsHigher() const;
RefPtr<LevelDBTransaction> m_transaction;
const LevelDBComparator* m_comparator;
diff --git a/Source/WebCore/platform/mac/ClipboardMac.h b/Source/WebCore/platform/mac/ClipboardMac.h
index 7f6ad85a7..1fe7398e2 100644
--- a/Source/WebCore/platform/mac/ClipboardMac.h
+++ b/Source/WebCore/platform/mac/ClipboardMac.h
@@ -40,9 +40,15 @@ class FileList;
class ClipboardMac : public Clipboard, public CachedImageClient {
WTF_MAKE_FAST_ALLOCATED;
public:
- static PassRefPtr<ClipboardMac> create(ClipboardType clipboardType, const String& pasteboardName, ClipboardAccessPolicy policy, Frame* frame)
+ enum ClipboardContents {
+ DragAndDropData,
+ DragAndDropFiles,
+ CopyAndPasteGeneric
+ };
+
+ static PassRefPtr<ClipboardMac> create(ClipboardType clipboardType, const String& pasteboardName, ClipboardAccessPolicy policy, ClipboardContents clipboardContents, Frame* frame)
{
- return adoptRef(new ClipboardMac(clipboardType, pasteboardName, policy, frame));
+ return adoptRef(new ClipboardMac(clipboardType, pasteboardName, policy, clipboardContents, frame));
}
virtual ~ClipboardMac();
@@ -74,12 +80,13 @@ public:
const String& pasteboardName() { return m_pasteboardName; }
private:
- ClipboardMac(ClipboardType, const String& pasteboardName, ClipboardAccessPolicy, Frame*);
+ ClipboardMac(ClipboardType, const String& pasteboardName, ClipboardAccessPolicy, ClipboardContents, Frame*);
void setDragImage(CachedImage*, Node*, const IntPoint&);
String m_pasteboardName;
int m_changeCount;
+ ClipboardContents m_clipboardContents;
Frame* m_frame; // used on the source side to generate dragging images
};
diff --git a/Source/WebCore/platform/mac/ClipboardMac.mm b/Source/WebCore/platform/mac/ClipboardMac.mm
index a4933f335..efc76ac88 100644
--- a/Source/WebCore/platform/mac/ClipboardMac.mm
+++ b/Source/WebCore/platform/mac/ClipboardMac.mm
@@ -48,12 +48,13 @@ namespace WebCore {
PassRefPtr<Clipboard> Clipboard::create(ClipboardAccessPolicy policy, DragData* dragData, Frame* frame)
{
- return ClipboardMac::create(DragAndDrop, dragData->pasteboardName(), policy, frame);
+ return ClipboardMac::create(DragAndDrop, dragData->pasteboardName(), policy, dragData->containsFiles() ? ClipboardMac::DragAndDropFiles : ClipboardMac::DragAndDropData, frame);
}
-ClipboardMac::ClipboardMac(ClipboardType clipboardType, const String& pasteboardName, ClipboardAccessPolicy policy, Frame *frame)
+ClipboardMac::ClipboardMac(ClipboardType clipboardType, const String& pasteboardName, ClipboardAccessPolicy policy, ClipboardContents clipboardContents, Frame *frame)
: Clipboard(policy, clipboardType)
, m_pasteboardName(pasteboardName)
+ , m_clipboardContents(clipboardContents)
, m_frame(frame)
{
m_changeCount = platformStrategies()->pasteboardStrategy()->changeCount(m_pasteboardName);
@@ -87,6 +88,10 @@ static String cocoaTypeFromHTMLClipboardType(const String& type)
// special case because UTI doesn't work with Cocoa's URL type
return String(NSURLPboardType); // note special case in getData to read NSFilenamesType
+ // Blacklist types that might contain subframe information
+ if (qType == "text/rtf" || qType == "public.rtf" || qType == "com.apple.traditional-mac-plain-text")
+ return String();
+
// Try UTI now
String mimeType = qType;
RetainPtr<CFStringRef> utiType(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType.createCFString(), NULL));
@@ -102,7 +107,8 @@ static String cocoaTypeFromHTMLClipboardType(const String& type)
static String utiTypeFromCocoaType(const String& type)
{
- RetainPtr<CFStringRef> utiType(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassNSPboardType, type.createCFString(), NULL));
+ RetainPtr<CFStringRef> typeCF = adoptCF(type.createCFString());
+ RetainPtr<CFStringRef> utiType(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassNSPboardType, typeCF.get(), 0));
if (utiType) {
RetainPtr<CFStringRef> mimeType(AdoptCF, UTTypeCopyPreferredTagWithClass(utiType.get(), kUTTagClassMIMEType));
if (mimeType)
@@ -202,9 +208,8 @@ static Vector<String> absoluteURLsFromPasteboard(const String& pasteboardName, b
// Fallback to NSURLPboardType (which is a single URL)
if (availableTypes.contains(String(NSURLPboardType))) {
- platformStrategies()->pasteboardStrategy()->getPathnamesForType(absoluteURLs, String(NSURLPboardType), pasteboardName);
- if (!absoluteURLs.isEmpty())
- return absoluteURLs;
+ absoluteURLs.append(platformStrategies()->pasteboardStrategy()->stringForType(String(NSURLPboardType), pasteboardName));
+ return absoluteURLs;
}
// No file paths on the pasteboard, return nil
@@ -213,7 +218,7 @@ static Vector<String> absoluteURLsFromPasteboard(const String& pasteboardName, b
String ClipboardMac::getData(const String& type) const
{
- if (policy() != ClipboardReadable)
+ if (policy() != ClipboardReadable || m_clipboardContents == DragAndDropFiles)
return String();
const String& cocoaType = cocoaTypeFromHTMLClipboardType(type);
@@ -242,30 +247,23 @@ String ClipboardMac::getData(const String& type) const
bool ClipboardMac::setData(const String &type, const String &data)
{
- if (policy() != ClipboardWritable)
+ if (policy() != ClipboardWritable || m_clipboardContents == DragAndDropFiles)
return false;
// note NSPasteboard enforces changeCount itself on writing - can't write if not the owner
const String& cocoaType = cocoaTypeFromHTMLClipboardType(type);
String cocoaData = data;
- if (cocoaType == String(NSURLPboardType)) {
- Vector<String> types;
- types.append(String(NSURLPboardType));
+ if (cocoaType == String(NSURLPboardType) || cocoaType == String(kUTTypeFileURL)) {
+ NSURL *url = [NSURL URLWithString:cocoaData];
+ if ([url isFileURL])
+ return false;
+ Vector<String> types;
+ types.append(cocoaType);
platformStrategies()->pasteboardStrategy()->setTypes(types, m_pasteboardName);
- platformStrategies()->pasteboardStrategy()->setStringForType(cocoaData, String(NSURLPboardType), m_pasteboardName);
- NSURL *url = [[NSURL alloc] initWithString:cocoaData];
-
- if ([url isFileURL] && m_frame->document()->securityOrigin()->canLoadLocalResources()) {
- types.append(String(NSFilenamesPboardType));
- platformStrategies()->pasteboardStrategy()->setTypes(types, m_pasteboardName);
- Vector<String> fileList;
- fileList.append(String([url path]));
- platformStrategies()->pasteboardStrategy()->setPathnamesForType(fileList, String(NSFilenamesPboardType), m_pasteboardName);
- }
+ platformStrategies()->pasteboardStrategy()->setStringForType(cocoaData, cocoaType, m_pasteboardName);
- [url release];
return true;
}
@@ -273,7 +271,7 @@ bool ClipboardMac::setData(const String &type, const String &data)
// everything else we know of goes on the pboard as a string
Vector<String> types;
types.append(cocoaType);
- platformStrategies()->pasteboardStrategy()->setTypes(types, m_pasteboardName);
+ platformStrategies()->pasteboardStrategy()->addTypes(types, m_pasteboardName);
platformStrategies()->pasteboardStrategy()->setStringForType(cocoaData, cocoaType, m_pasteboardName);
return true;
}
@@ -312,7 +310,7 @@ HashSet<String> ClipboardMac::types() const
// clipboard are not reflected in any FileList objects the page has accessed and stored
PassRefPtr<FileList> ClipboardMac::files() const
{
- if (policy() != ClipboardReadable)
+ if (policy() != ClipboardReadable || m_clipboardContents == DragAndDropData)
return FileList::create();
Vector<String> absoluteURLs = absoluteURLsFromPasteboardFilenames(m_pasteboardName);
diff --git a/Source/WebCore/platform/mac/DragDataMac.mm b/Source/WebCore/platform/mac/DragDataMac.mm
index 61eac930e..27f1ed84a 100644
--- a/Source/WebCore/platform/mac/DragDataMac.mm
+++ b/Source/WebCore/platform/mac/DragDataMac.mm
@@ -160,15 +160,19 @@ String DragData::asURL(Frame* frame, FilenameConversionPolicy filenamePolicy, St
if (types.contains(String(NSURLPboardType))) {
NSURL *URLFromPasteboard = [NSURL URLWithString:platformStrategies()->pasteboardStrategy()->stringForType(String(NSURLPboardType), m_pasteboardName)];
NSString *scheme = [URLFromPasteboard scheme];
- if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]) {
+ // Cannot drop other schemes unless <rdar://problem/10562662> and <rdar://problem/11187315> are fixed.
+ if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"])
return [frame->editor()->client()->canonicalizeURL(URLFromPasteboard) absoluteString];
- }
}
if (types.contains(String(NSStringPboardType))) {
- NSURL *URL = frame->editor()->client()->canonicalizeURLString(platformStrategies()->pasteboardStrategy()->stringForType(String(NSStringPboardType), m_pasteboardName));
- if (URL)
- return [URL absoluteString];
+ NSURL *URLFromPasteboard = [NSURL URLWithString:platformStrategies()->pasteboardStrategy()->stringForType(String(NSStringPboardType), m_pasteboardName)];
+ NSString *scheme = [URLFromPasteboard scheme];
+ // Pasteboard content is not trusted, because JavaScript code can modify it. We can sanitize it for URLs and other typed content, but not for strings.
+ // The result of this function is used to initiate navigation, so we shouldn't allow arbitrary file URLs.
+ // FIXME: Should we allow only http family schemes, or anything non-local?
+ if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"])
+ return [frame->editor()->client()->canonicalizeURL(URLFromPasteboard) absoluteString];
}
if (types.contains(String(NSFilenamesPboardType))) {
diff --git a/Source/WebCore/platform/mac/DragImageMac.mm b/Source/WebCore/platform/mac/DragImageMac.mm
index d57648fad..3379f39ca 100644
--- a/Source/WebCore/platform/mac/DragImageMac.mm
+++ b/Source/WebCore/platform/mac/DragImageMac.mm
@@ -27,6 +27,7 @@
#import "DragImage.h"
#if ENABLE(DRAG_SUPPORT)
+#import "BitmapImage.h"
#import "CachedImage.h"
#import "Font.h"
#import "FontCache.h"
@@ -84,10 +85,40 @@ RetainPtr<NSImage> dissolveDragImageToFraction(RetainPtr<NSImage> image, float d
return image;
}
-RetainPtr<NSImage> createDragImageFromImage(Image* image)
+RetainPtr<NSImage> createDragImageFromImage(Image* image, RespectImageOrientationEnum shouldRespectImageOrientation)
{
+ IntSize size = image->size();
+
+ if (image->isBitmapImage()) {
+ ImageOrientation orientation = DefaultImageOrientation;
+ BitmapImage* bitmapImage = static_cast<BitmapImage *>(image);
+ IntSize sizeRespectingOrientation = bitmapImage->sizeRespectingOrientation();
+
+ if (shouldRespectImageOrientation == RespectImageOrientation)
+ orientation = bitmapImage->currentFrameOrientation();
+
+ if (orientation != DefaultImageOrientation) {
+ // Construct a correctly-rotated copy of the image to use as the drag image.
+ RetainPtr<NSAffineTransform> cocoaTransform(AdoptNS, [[NSAffineTransform alloc] init]);
+ CGAffineTransform transform = orientation.transformFromDefault(sizeRespectingOrientation);
+ [cocoaTransform.get() setTransformStruct:*(NSAffineTransformStruct*)&transform];
+
+ FloatRect destRect(FloatPoint(), sizeRespectingOrientation);
+
+ RetainPtr<NSImage> rotatedDragImage(AdoptNS, [[NSImage alloc] initWithSize:(NSSize)(sizeRespectingOrientation)]);
+ [rotatedDragImage.get() lockFocus];
+ [cocoaTransform.get() concat];
+ if (orientation.usesWidthAsHeight())
+ destRect = FloatRect(destRect.x(), destRect.y(), destRect.height(), destRect.width());
+ [image->getNSImage() drawInRect:destRect fromRect:NSMakeRect(0, 0, size.width(), size.height()) operation:NSCompositeSourceOver fraction:1.0];
+ [rotatedDragImage.get() unlockFocus];
+
+ return rotatedDragImage;
+ }
+ }
+
RetainPtr<NSImage> dragImage(AdoptNS, [image->getNSImage() copy]);
- [dragImage.get() setSize:(NSSize)(image->size())];
+ [dragImage.get() setSize:(NSSize)size];
return dragImage;
}
diff --git a/Source/WebCore/platform/mac/FileSystemMac.mm b/Source/WebCore/platform/mac/FileSystemMac.mm
index efb7d452e..f9a034366 100644
--- a/Source/WebCore/platform/mac/FileSystemMac.mm
+++ b/Source/WebCore/platform/mac/FileSystemMac.mm
@@ -78,7 +78,7 @@ typedef struct MetaDataInfo
static void* setMetaData(void* context)
{
MetaDataInfo *info = (MetaDataInfo *)context;
- wkSetMetadataURL((NSString *)info->URLString, (NSString *)info->referrer, (NSString *)fileSystemRepresentation(info->path).data());
+ wkSetMetadataURL((NSString *)info->URLString, (NSString *)info->referrer, (NSString *)String(fileSystemRepresentation(info->path).data()));
delete info;
diff --git a/Source/WebCore/platform/mac/HTMLConverter.mm b/Source/WebCore/platform/mac/HTMLConverter.mm
index 47d5fe058..22db81c38 100644
--- a/Source/WebCore/platform/mac/HTMLConverter.mm
+++ b/Source/WebCore/platform/mac/HTMLConverter.mm
@@ -1695,8 +1695,8 @@ static NSInteger _colCompare(id block1, id block2, void *)
RenderStyle* style = renderer->style();
if (style->textDecorationsInEffect() & UNDERLINE)
[attrs.get() setObject:[NSNumber numberWithInteger:NSUnderlineStyleSingle] forKey:NSUnderlineStyleAttributeName];
- NSFont *font = style->font().primaryFont()->getNSFont();
- [attrs.get() setObject:font forKey:NSFontAttributeName];
+ if (NSFont *font = style->font().primaryFont()->getNSFont())
+ [attrs.get() setObject:font forKey:NSFontAttributeName];
if (style->visitedDependentColor(CSSPropertyColor).alpha())
[attrs.get() setObject:nsColor(style->visitedDependentColor(CSSPropertyColor)) forKey:NSForegroundColorAttributeName];
else
diff --git a/Source/WebCore/platform/mac/LoggingMac.mm b/Source/WebCore/platform/mac/LoggingMac.mm
index 45cf6e5a4..4c9b30351 100644
--- a/Source/WebCore/platform/mac/LoggingMac.mm
+++ b/Source/WebCore/platform/mac/LoggingMac.mm
@@ -73,6 +73,7 @@ void initializeLoggingChannelsIfNecessary()
initializeWithUserDefault(LogPlugins);
initializeWithUserDefault(LogArchives);
initializeWithUserDefault(LogWebAudio);
+ initializeWithUserDefault(LogCompositing);
}
}
diff --git a/Source/WebCore/platform/mac/MemoryPressureHandlerMac.mm b/Source/WebCore/platform/mac/MemoryPressureHandlerMac.mm
index 0e410d94f..1e1b773cf 100644
--- a/Source/WebCore/platform/mac/MemoryPressureHandlerMac.mm
+++ b/Source/WebCore/platform/mac/MemoryPressureHandlerMac.mm
@@ -30,6 +30,7 @@
#import <WebCore/FontCache.h>
#import <WebCore/MemoryCache.h>
#import <WebCore/PageCache.h>
+#import <wtf/CurrentTime.h>
#import <wtf/FastMalloc.h>
#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) && !PLATFORM(IOS)
@@ -37,6 +38,8 @@
#import <notify.h>
#endif
+using std::max;
+
namespace WebCore {
#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
@@ -46,10 +49,14 @@ static dispatch_source_t _cache_event_source = 0;
static dispatch_source_t _timer_event_source = 0;
static int _notifyToken;
-// Disable memory event reception for 5 seconds after receiving an event.
-// This value seems reasonable and testing verifies that it throttles frequent
+// Disable memory event reception for a minimum of s_minimumHoldOffTime
+// seconds after receiving an event. Don't let events fire any sooner than
+// s_holdOffMultiplier times the last cleanup processing time. Effectively
+// this is 1 / s_holdOffMultiplier percent of the time.
+// These value seems reasonable and testing verifies that it throttles frequent
// low memory events, greatly reducing CPU usage.
-static const time_t s_secondsBetweenMemoryCleanup = 5;
+static const unsigned s_minimumHoldOffTime = 5;
+static const unsigned s_holdOffMultiplier = 20;
void MemoryPressureHandler::install()
{
@@ -93,13 +100,11 @@ void MemoryPressureHandler::uninstall()
void MemoryPressureHandler::holdOff(unsigned seconds)
{
- uninstall();
-
dispatch_async(dispatch_get_main_queue(), ^{
_timer_event_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
if (_timer_event_source) {
dispatch_set_context(_timer_event_source, this);
- dispatch_source_set_timer(_timer_event_source, dispatch_time(DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC), DISPATCH_TIME_FOREVER, 1 * s_secondsBetweenMemoryCleanup);
+ dispatch_source_set_timer(_timer_event_source, dispatch_time(DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC), DISPATCH_TIME_FOREVER, 1 * s_minimumHoldOffTime);
dispatch_source_set_event_handler(_timer_event_source, ^{
dispatch_source_cancel(_timer_event_source);
dispatch_release(_timer_event_source);
@@ -113,9 +118,15 @@ void MemoryPressureHandler::holdOff(unsigned seconds)
void MemoryPressureHandler::respondToMemoryPressure()
{
- holdOff(s_secondsBetweenMemoryCleanup);
+ uninstall();
+
+ double startTime = monotonicallyIncreasingTime();
releaseMemory(false);
+
+ unsigned holdOffTime = (monotonicallyIncreasingTime() - startTime) * s_holdOffMultiplier;
+
+ holdOff(max(holdOffTime, s_minimumHoldOffTime));
}
#endif // !PLATFORM(IOS)
@@ -135,7 +146,7 @@ void MemoryPressureHandler::releaseMemory(bool critical)
memoryCache()->pruneToPercentage(critical ? 0 : 0.5f);
- gcController().garbageCollectNow();
+ gcController().discardAllCompiledCode();
WTF::releaseFastMallocFreeMemory();
}
diff --git a/Source/WebCore/platform/mac/NSScrollerImpDetails.h b/Source/WebCore/platform/mac/NSScrollerImpDetails.h
index f06800c16..c6a235f93 100644
--- a/Source/WebCore/platform/mac/NSScrollerImpDetails.h
+++ b/Source/WebCore/platform/mac/NSScrollerImpDetails.h
@@ -62,6 +62,7 @@ typedef NSInteger NSScrollerKnobStyle;
- (void)setKnobProportion:(CGFloat)proportion;
- (void)setKnobStyle:(NSScrollerKnobStyle)knobStyle;
- (void)setExpanded:(BOOL)expanded;
+- (BOOL)isExpanded;
- (void)setDelegate:(id)delegate;
- (void)setUiStateTransitionProgress:(CGFloat)uiStateTransitionProgress;
- (BOOL)isHorizontal;
diff --git a/Source/WebCore/platform/mac/PasteboardMac.mm b/Source/WebCore/platform/mac/PasteboardMac.mm
index 6e4bda87d..00391ee36 100644
--- a/Source/WebCore/platform/mac/PasteboardMac.mm
+++ b/Source/WebCore/platform/mac/PasteboardMac.mm
@@ -133,63 +133,72 @@ void Pasteboard::clear()
platformStrategies()->pasteboardStrategy()->setTypes(Vector<String>(), m_pasteboardName);
}
-void Pasteboard::writeSelectionForTypes(const Vector<String>& pasteboardTypes, Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
+String Pasteboard::getStringSelection(Frame* frame)
{
- if (!WebArchivePboardType)
- Pasteboard::generalPasteboard(); // Initializes pasteboard types.
- ASSERT(selectedRange);
-
- // If the selection is at the beginning of content inside an anchor tag
- // we move the selection start to include the anchor.
- // This way the attributed string will contain the url attribute as well.
- // See <rdar://problem/9084267>.
+ String text = frame->editor()->selectedText();
+ text.replace(noBreakSpace, ' ');
+ return text;
+}
+
+PassRefPtr<SharedBuffer> Pasteboard::getDataSelection(Frame* frame, const String& pasteboardType)
+{
+ if (pasteboardType == WebArchivePboardType) {
+ RefPtr<LegacyWebArchive> archive = LegacyWebArchive::createFromSelection(frame);
+ RetainPtr<CFDataRef> data = archive ? archive->rawDataRepresentation() : 0;
+ return SharedBuffer::wrapNSData((NSData *)data.get());
+ }
+
ExceptionCode ec;
- Node* commonAncestor = selectedRange->commonAncestorContainer(ec);
+ RefPtr<Range> range = frame->editor()->selectedRange();
+ Node* commonAncestor = range->commonAncestorContainer(ec);
ASSERT(commonAncestor);
Node* enclosingAnchor = enclosingNodeWithTag(firstPositionInNode(commonAncestor), HTMLNames::aTag);
- if (enclosingAnchor && comparePositions(firstPositionInOrBeforeNode(selectedRange->startPosition().anchorNode()), selectedRange->startPosition()) >= 0)
- selectedRange->setStart(enclosingAnchor, 0, ec);
-
- NSAttributedString *attributedString = nil;
- RetainPtr<WebHTMLConverter> converter(AdoptNS, [[WebHTMLConverter alloc] initWithDOMRange:kit(selectedRange)]);
+ if (enclosingAnchor && comparePositions(firstPositionInOrBeforeNode(range->startPosition().anchorNode()), range->startPosition()) >= 0)
+ range->setStart(enclosingAnchor, 0, ec);
+
+ NSAttributedString* attributedString = nil;
+ RetainPtr<WebHTMLConverter> converter(AdoptNS, [[WebHTMLConverter alloc] initWithDOMRange:kit(range.get())]);
if (converter)
attributedString = [converter.get() attributedString];
+
+ if (pasteboardType == String(NSRTFDPboardType)) {
+ NSData *RTFDData = [attributedString RTFDFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
+ return SharedBuffer::wrapNSData((NSData *)RTFDData);
+ }
+ if (pasteboardType == String(NSRTFPboardType)) {
+ if ([attributedString containsAttachments])
+ attributedString = attributedStringByStrippingAttachmentCharacters(attributedString);
+ NSData *RTFData = [attributedString RTFFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
+ return SharedBuffer::wrapNSData((NSData *)RTFData);
+ }
+ return 0;
+}
+void Pasteboard::writeSelectionForTypes(const Vector<String>& pasteboardTypes, bool canSmartCopyOrDelete, Frame* frame)
+{
+ NSAttributedString* attributedString = nil;
+ RetainPtr<WebHTMLConverter> converter(AdoptNS, [[WebHTMLConverter alloc] initWithDOMRange:kit(frame->editor()->selectedRange().get())]);
+ if (converter)
+ attributedString = [converter.get() attributedString];
+
const Vector<String> types = !pasteboardTypes.isEmpty() ? pasteboardTypes : selectionPasteboardTypes(canSmartCopyOrDelete, [attributedString containsAttachments]);
platformStrategies()->pasteboardStrategy()->setTypes(types, m_pasteboardName);
frame->editor()->client()->didSetSelectionTypesForPasteboard();
// Put HTML on the pasteboard.
- if (types.contains(WebArchivePboardType)) {
- RefPtr<LegacyWebArchive> archive = LegacyWebArchive::createFromSelection(frame);
- RetainPtr<CFDataRef> data = archive ? archive->rawDataRepresentation() : 0;
- platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::wrapNSData((NSData *)data.get()), WebArchivePboardType, m_pasteboardName);
- }
+ if (types.contains(WebArchivePboardType))
+ platformStrategies()->pasteboardStrategy()->setBufferForType(getDataSelection(frame, WebArchivePboardType), WebArchivePboardType, m_pasteboardName);
// Put the attributed string on the pasteboard (RTF/RTFD format).
- if (types.contains(String(NSRTFDPboardType))) {
- NSData *RTFDData = [attributedString RTFDFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
- platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::wrapNSData((NSData *)RTFDData).get(), NSRTFDPboardType, m_pasteboardName);
- }
- if (types.contains(String(NSRTFPboardType))) {
- if ([attributedString containsAttachments])
- attributedString = attributedStringByStrippingAttachmentCharacters(attributedString);
- NSData *RTFData = [attributedString RTFFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
- platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::wrapNSData((NSData *)RTFData).get(), NSRTFPboardType, m_pasteboardName);
- }
+ if (types.contains(String(NSRTFDPboardType)))
+ platformStrategies()->pasteboardStrategy()->setBufferForType(getDataSelection(frame, NSRTFDPboardType), NSRTFDPboardType, m_pasteboardName);
+
+ if (types.contains(String(NSRTFPboardType)))
+ platformStrategies()->pasteboardStrategy()->setBufferForType(getDataSelection(frame, NSRTFPboardType), NSRTFPboardType, m_pasteboardName);
// Put plain string on the pasteboard.
- if (types.contains(String(NSStringPboardType))) {
- // Map &nbsp; to a plain old space because this is better for source code, other browsers do it,
- // and because HTML forces you to do this any time you want two spaces in a row.
- String text = frame->editor()->selectedText();
- NSMutableString *s = [[[(NSString*)text copy] autorelease] mutableCopy];
-
- NSString *NonBreakingSpaceString = [NSString stringWithCharacters:&noBreakSpace length:1];
- [s replaceOccurrencesOfString:NonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])];
- platformStrategies()->pasteboardStrategy()->setStringForType(s, NSStringPboardType, m_pasteboardName);
- [s release];
- }
+ if (types.contains(String(NSStringPboardType)))
+ platformStrategies()->pasteboardStrategy()->setStringForType(getStringSelection(frame), NSStringPboardType, m_pasteboardName);
if (types.contains(WebSmartPastePboardType))
platformStrategies()->pasteboardStrategy()->setBufferForType(0, WebSmartPastePboardType, m_pasteboardName);
@@ -203,9 +212,9 @@ void Pasteboard::writePlainText(const String& text)
platformStrategies()->pasteboardStrategy()->setStringForType(text, NSStringPboardType, m_pasteboardName);
}
-void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
+void Pasteboard::writeSelection(Range*, bool canSmartCopyOrDelete, Frame* frame)
{
- writeSelectionForTypes(Vector<String>(), selectedRange, canSmartCopyOrDelete, frame);
+ writeSelectionForTypes(Vector<String>(), canSmartCopyOrDelete, frame);
}
static void writeURLForTypes(const Vector<String>& types, const String& pasteboardName, const KURL& url, const String& titleStr, Frame* frame)
@@ -225,7 +234,7 @@ static void writeURLForTypes(const Vector<String>& types, const String& pasteboa
}
if (types.contains(WebURLsWithTitlesPboardType)) {
Vector<String> paths;
- paths.append(userVisibleString);
+ paths.append([cocoaURL absoluteString]);
paths.append(titleStr.stripWhiteSpace());
platformStrategies()->pasteboardStrategy()->setPathnamesForType(paths, WebURLsWithTitlesPboardType, pasteboardName);
}
@@ -513,7 +522,7 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP
return fragment.release();
if (types.contains(String(NSURLPboardType))) {
- NSURL *URL = [NSURL URLWithString:platformStrategies()->pasteboardStrategy()->stringForType(NSURLPboardType, m_pasteboardName)];
+ NSURL *URL = platformStrategies()->pasteboardStrategy()->url(m_pasteboardName);
Document* document = frame->document();
ASSERT(document);
if (!document)
diff --git a/Source/WebCore/platform/mac/PlatformPasteboardMac.mm b/Source/WebCore/platform/mac/PlatformPasteboardMac.mm
index d6a47e6f7..1d8a1f8e4 100644
--- a/Source/WebCore/platform/mac/PlatformPasteboardMac.mm
+++ b/Source/WebCore/platform/mac/PlatformPasteboardMac.mm
@@ -20,11 +20,12 @@
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "config.h"
#import "Color.h"
+#import "KURL.h"
#import "PlatformPasteboard.h"
namespace WebCore {
@@ -64,6 +65,9 @@ void PlatformPasteboard::getPathnamesForType(Vector<String>& pathnames, const St
String PlatformPasteboard::stringForType(const String& pasteboardType)
{
+ if (pasteboardType == String(NSURLPboardType))
+ return [[NSURL URLFromPasteboard:m_pasteboard.get()] absoluteString];
+
return [m_pasteboard.get() stringForType:pasteboardType];
}
@@ -90,6 +94,11 @@ Color PlatformPasteboard::color()
(int)([color blueComponent] * 255.0 + 0.5), (int)([color alphaComponent] * 255.0 + 0.5));
}
+KURL PlatformPasteboard::url()
+{
+ return [NSURL URLFromPasteboard:m_pasteboard.get()];
+}
+
void PlatformPasteboard::copy(const String& fromPasteboard)
{
NSPasteboard* pasteboard = [NSPasteboard pasteboardWithName:fromPasteboard];
@@ -102,6 +111,15 @@ void PlatformPasteboard::copy(const String& fromPasteboard)
}
}
+void PlatformPasteboard::addTypes(const Vector<String>& pasteboardTypes)
+{
+ RetainPtr<NSMutableArray> types(AdoptNS, [[NSMutableArray alloc] init]);
+ for (size_t i = 0; i < pasteboardTypes.size(); ++i)
+ [types.get() addObject:pasteboardTypes[i]];
+
+ [m_pasteboard.get() addTypes:types.get() owner:nil];
+}
+
void PlatformPasteboard::setTypes(const Vector<String>& pasteboardTypes)
{
if (pasteboardTypes.isEmpty()) {
@@ -131,7 +149,10 @@ void PlatformPasteboard::setPathnamesForType(const Vector<String>& pathnames, co
void PlatformPasteboard::setStringForType(const String& string, const String& pasteboardType)
{
- [m_pasteboard.get() setString:string forType:pasteboardType];
+ if (pasteboardType == String(NSURLPboardType))
+ [[NSURL URLWithString:string] writeToPasteboard:m_pasteboard.get()];
+ else
+ [m_pasteboard.get() setString:string forType:pasteboardType];
}
}
diff --git a/Source/WebCore/platform/mac/ScrollAnimatorMac.h b/Source/WebCore/platform/mac/ScrollAnimatorMac.h
index 4ea6904a5..caf3514e8 100644
--- a/Source/WebCore/platform/mac/ScrollAnimatorMac.h
+++ b/Source/WebCore/platform/mac/ScrollAnimatorMac.h
@@ -120,6 +120,8 @@ private:
void immediateScrollTo(const FloatPoint&);
+ virtual bool isRubberBandInProgress() const OVERRIDE;
+
#if ENABLE(RUBBER_BANDING)
/// ScrollElasticityControllerClient member functions.
virtual IntSize stretchAmount() OVERRIDE;
diff --git a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm b/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
index 78b71b01e..edeee38d0 100644
--- a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
+++ b/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
@@ -589,11 +589,20 @@ ScrollAnimatorMac::~ScrollAnimatorMac()
}
}
+static bool scrollAnimationEnabledForSystem()
+{
+#if defined(BUILDING_ON_SNOW_LEOPARD) || defined(BUILDING_ON_LION)
+ return [[NSUserDefaults standardUserDefaults] boolForKey:@"AppleScrollAnimationEnabled"];
+#else
+ return [[NSUserDefaults standardUserDefaults] boolForKey:@"NSScrollAnimationEnabled"];
+#endif
+}
+
bool ScrollAnimatorMac::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier)
{
m_haveScrolledSincePageLoad = true;
- if (![[NSUserDefaults standardUserDefaults] boolForKey:@"AppleScrollAnimationEnabled"] || !m_scrollableArea->scrollAnimatorEnabled())
+ if (!scrollAnimationEnabledForSystem() || !m_scrollableArea->scrollAnimatorEnabled())
return ScrollAnimator::scroll(orientation, granularity, step, multiplier);
if (granularity == ScrollByPixel)
@@ -645,6 +654,15 @@ void ScrollAnimatorMac::immediateScrollTo(const FloatPoint& newPosition)
notifyPositionChanged();
}
+bool ScrollAnimatorMac::isRubberBandInProgress() const
+{
+#if !ENABLE(RUBBER_BANDING)
+ return false;
+#else
+ return m_scrollElasticityController.isRubberBandInProgress();
+#endif
+}
+
void ScrollAnimatorMac::immediateScrollToPointForScrollAnimation(const FloatPoint& newPosition)
{
ASSERT(m_scrollAnimationHelper);
diff --git a/Source/WebCore/platform/mac/ScrollElasticityController.h b/Source/WebCore/platform/mac/ScrollElasticityController.h
index 9f52443b8..368871360 100644
--- a/Source/WebCore/platform/mac/ScrollElasticityController.h
+++ b/Source/WebCore/platform/mac/ScrollElasticityController.h
@@ -68,6 +68,8 @@ public:
bool handleWheelEvent(const PlatformWheelEvent&);
void snapRubberBandTimerFired();
+ bool isRubberBandInProgress() const;
+
private:
void stopSnapRubberbandTimer();
void snapRubberBand();
diff --git a/Source/WebCore/platform/mac/ScrollElasticityController.mm b/Source/WebCore/platform/mac/ScrollElasticityController.mm
index d3247142b..a81784696 100644
--- a/Source/WebCore/platform/mac/ScrollElasticityController.mm
+++ b/Source/WebCore/platform/mac/ScrollElasticityController.mm
@@ -367,6 +367,14 @@ void ScrollElasticityController::snapRubberBandTimerFired()
}
}
+bool ScrollElasticityController::isRubberBandInProgress() const
+{
+ if (!m_inScrollGesture && !m_momentumScrollInProgress && !m_snapRubberbandTimerIsActive)
+ return false;
+
+ return !m_client->stretchAmount().isZero();
+}
+
void ScrollElasticityController::stopSnapRubberbandTimer()
{
m_client->stopSnapRubberbandTimer();
diff --git a/Source/WebCore/platform/mac/ScrollbarThemeMac.mm b/Source/WebCore/platform/mac/ScrollbarThemeMac.mm
index e47468bd5..2fe336f74 100644
--- a/Source/WebCore/platform/mac/ScrollbarThemeMac.mm
+++ b/Source/WebCore/platform/mac/ScrollbarThemeMac.mm
@@ -140,7 +140,7 @@ static ScrollbarButtonsPlacement gButtonPlacement = ScrollbarButtonsDoubleEnd;
static bool supportsExpandedScrollbars()
{
// FIXME: This is temporary until all platforms that support ScrollbarPainter support this part of the API.
- static bool globalSupportsExpandedScrollbars = [NSClassFromString(@"NSScrollerImp") instancesRespondToSelector:@selector(isExpanded)];
+ static bool globalSupportsExpandedScrollbars = [NSClassFromString(@"NSScrollerImp") instancesRespondToSelector:@selector(setExpanded:)];
return globalSupportsExpandedScrollbars;
}
diff --git a/Source/WebCore/platform/mac/SoftLinking.h b/Source/WebCore/platform/mac/SoftLinking.h
index e61bb7ad4..a102ae538 100644
--- a/Source/WebCore/platform/mac/SoftLinking.h
+++ b/Source/WebCore/platform/mac/SoftLinking.h
@@ -52,10 +52,15 @@
return frameworkLibrary; \
}
-#define SOFT_LINK_PRIVATE_FRAMEWORK_OPTIONAL(framework) \
+#define SOFT_LINK_STAGED_FRAMEWORK_OPTIONAL(framework, unstagedLocation) \
static void* framework##Library() \
{ \
- static void* frameworkLibrary = dlopen("/System/Library/PrivateFrameworks/" #framework ".framework/" #framework, RTLD_NOW); \
+ static void* frameworkLibrary = ^{ \
+ void* result = dlopen("/System/Library/" #unstagedLocation "/" #framework ".framework/" #framework, RTLD_LAZY); \
+ if (!result) \
+ result = dlopen("/System/Library/StagedFrameworks/Safari/" #framework ".framework/" #framework, RTLD_LAZY); \
+ return result; \
+ }(); \
return frameworkLibrary; \
}
diff --git a/Source/WebCore/platform/mac/ThemeMac.h b/Source/WebCore/platform/mac/ThemeMac.h
index bf2d6916b..d9244c7a1 100644
--- a/Source/WebCore/platform/mac/ThemeMac.h
+++ b/Source/WebCore/platform/mac/ThemeMac.h
@@ -52,6 +52,7 @@ public:
// FIXME: Once RenderThemeMac is converted over to use Theme then this can be internal to ThemeMac.
static NSView* ensuredView(ScrollView*);
+ static void setFocusRingClipRect(const FloatRect&);
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/mac/ThemeMac.mm b/Source/WebCore/platform/mac/ThemeMac.mm
index 90bf52aa8..d45509120 100644
--- a/Source/WebCore/platform/mac/ThemeMac.mm
+++ b/Source/WebCore/platform/mac/ThemeMac.mm
@@ -36,6 +36,8 @@
using namespace std;
+NSRect focusRingClipRect;
+
// This is a view whose sole purpose is to tell AppKit that it's flipped.
@interface WebCoreFlippedView : NSControl
@end
@@ -59,7 +61,13 @@ using namespace std;
- (NSRect)_focusRingVisibleRect
{
- return [self visibleRect];
+ if (NSIsEmptyRect(focusRingClipRect))
+ return [self visibleRect];
+
+ NSRect rect = focusRingClipRect;
+ rect.origin.y = [self bounds].size.height - NSMaxY(rect);
+
+ return rect;
}
- (NSView *)_focusRingClipAncestor
@@ -404,14 +412,6 @@ static const IntSize* buttonSizes()
return sizes;
}
-#if ENABLE(DATALIST)
-static const IntSize* listButtonSizes()
-{
- static const IntSize sizes[3] = { IntSize(21, 21), IntSize(19, 18), IntSize(17, 16) };
- return sizes;
-}
-#endif
-
static const int* buttonMargins(NSControlSize controlSize)
{
static const int margins[3][4] =
@@ -439,12 +439,6 @@ static void setUpButtonCell(NSButtonCell *cell, ControlPart part, ControlStates
{
// Set the control size based off the rectangle we're painting into.
const IntSize* sizes = buttonSizes();
-#if ENABLE(DATALIST)
- if (part == ListButtonPart) {
- [cell setBezelStyle:NSRoundedDisclosureBezelStyle];
- sizes = listButtonSizes();
- } else
-#endif
if (part == SquareButtonPart || zoomedRect.height() > buttonSizes()[NSRegularControlSize].height() * zoomFactor) {
// Use the square button
if ([cell bezelStyle] != NSShadowlessSquareBezelStyle)
@@ -481,11 +475,7 @@ static void paintButton(ControlPart part, ControlStates states, GraphicsContext*
LocalCurrentGraphicsContext localContext(context);
NSControlSize controlSize = [buttonCell controlSize];
-#if ENABLE(DATALIST)
- IntSize zoomedSize = (part == ListButtonPart ? listButtonSizes() : buttonSizes())[controlSize];
-#else
IntSize zoomedSize = buttonSizes()[controlSize];
-#endif
zoomedSize.setWidth(zoomedRect.width()); // Buttons don't ever constrain width, so the zoomed width can just be honored.
zoomedSize.setHeight(zoomedSize.height() * zoomFactor);
IntRect inflatedRect = zoomedRect;
@@ -602,7 +592,12 @@ NSView *ThemeMac::ensuredView(ScrollView* scrollView)
return flippedView;
}
-
+
+void ThemeMac::setFocusRingClipRect(const FloatRect& rect)
+{
+ focusRingClipRect = rect;
+}
+
// Theme overrides
int ThemeMac::baselinePositionAdjustment(ControlPart part) const
@@ -641,10 +636,6 @@ LengthSize ThemeMac::controlSize(ControlPart part, const Font& font, const Lengt
case PushButtonPart:
// Height is reset to auto so that specified heights can be ignored.
return sizeFromFont(font, LengthSize(zoomedSize.width(), Length()), zoomFactor, buttonSizes());
-#if ENABLE(DATALIST)
- case ListButtonPart:
- return sizeFromFont(font, LengthSize(zoomedSize.width(), Length()), zoomFactor, listButtonSizes());
-#endif
case InnerSpinButtonPart:
if (!zoomedSize.width().isIntrinsicOrAuto() && !zoomedSize.height().isIntrinsicOrAuto())
return zoomedSize;
@@ -660,7 +651,6 @@ LengthSize ThemeMac::minimumControlSize(ControlPart part, const Font& font, floa
case SquareButtonPart:
case DefaultButtonPart:
case ButtonPart:
- case ListButtonPart:
return LengthSize(Length(0, Fixed), Length(static_cast<int>(15 * zoomFactor), Fixed));
case InnerSpinButtonPart:{
IntSize base = stepperSizes()[NSMiniControlSize];
@@ -678,7 +668,6 @@ LengthBox ThemeMac::controlBorder(ControlPart part, const Font& font, const Leng
case SquareButtonPart:
case DefaultButtonPart:
case ButtonPart:
- case ListButtonPart:
return LengthBox(0, zoomedBox.right().value(), 0, zoomedBox.left().value());
default:
return Theme::controlBorder(part, font, zoomedBox, zoomFactor);
@@ -771,7 +760,6 @@ void ThemeMac::paint(ControlPart part, ControlStates states, GraphicsContext* co
case DefaultButtonPart:
case ButtonPart:
case SquareButtonPart:
- case ListButtonPart:
paintButton(part, states, context, zoomedRect, zoomFactor, scrollView);
break;
case InnerSpinButtonPart:
diff --git a/Source/WebCore/platform/mac/ThreadCheck.mm b/Source/WebCore/platform/mac/ThreadCheck.mm
index 479219196..89fef0309 100644
--- a/Source/WebCore/platform/mac/ThreadCheck.mm
+++ b/Source/WebCore/platform/mac/ThreadCheck.mm
@@ -103,7 +103,7 @@ void WebCoreReportThreadViolation(const char* function, WebCore::ThreadViolation
case NoThreadCheck:
break;
case LogOnFirstThreadViolation:
- if (loggedFunctions.add(function).second) {
+ if (loggedFunctions.add(function).isNewEntry) {
NSLog(@"WebKit Threading Violation - %s called from secondary thread", function);
NSLog(@"Additional threading violations for this function will not be logged.");
}
diff --git a/Source/WebCore/platform/mac/WebCoreFullScreenWindow.h b/Source/WebCore/platform/mac/WebCoreFullScreenWindow.h
index 214e673a7..de6365a94 100644
--- a/Source/WebCore/platform/mac/WebCoreFullScreenWindow.h
+++ b/Source/WebCore/platform/mac/WebCoreFullScreenWindow.h
@@ -26,7 +26,11 @@
#ifndef WebCoreFullScreenWindow_h
#define WebCoreFullScreenWindow_h
+#if ENABLE(FULLSCREEN_API)
+
@interface WebCoreFullScreenWindow : NSWindow
@end
+#endif // ENABLE(FULLSCREEN_API)
+
#endif // WebCoreFullScreenWindow_h
diff --git a/Source/WebCore/platform/mac/WebCoreFullScreenWindow.mm b/Source/WebCore/platform/mac/WebCoreFullScreenWindow.mm
index b62483b30..f62d14a03 100644
--- a/Source/WebCore/platform/mac/WebCoreFullScreenWindow.mm
+++ b/Source/WebCore/platform/mac/WebCoreFullScreenWindow.mm
@@ -24,6 +24,9 @@
*/
#import "config.h"
+
+#if ENABLE(FULLSCREEN_API)
+
#import "WebCoreFullScreenWindow.h"
@implementation WebCoreFullScreenWindow
@@ -66,3 +69,4 @@
}
@end
+#endif // ENABLE(FULLSCREEN_API)
diff --git a/Source/WebCore/platform/mac/WebCoreNSURLExtras.mm b/Source/WebCore/platform/mac/WebCoreNSURLExtras.mm
index b0751875f..3b87d5370 100644
--- a/Source/WebCore/platform/mac/WebCoreNSURLExtras.mm
+++ b/Source/WebCore/platform/mac/WebCoreNSURLExtras.mm
@@ -53,7 +53,7 @@ static inline BOOL isLookalikeCharacter(int charCode)
{
// This function treats the following as unsafe, lookalike characters:
// any non-printable character, any character considered as whitespace that isn't already converted to a space by ICU,
- // and any ignorable character.
+ // any ignorable character, and emoji characters related to locks.
// We also considered the characters in Mozilla's blacklist (http://kb.mozillazine.org/Network.IDN.blacklist_chars),
// and included all of these characters that ICU can encode.
@@ -66,6 +66,7 @@ static inline BOOL isLookalikeCharacter(int charCode)
case 0x01C3: /* LATIN LETTER RETROFLEX CLICK */
case 0x0251: /* LATIN SMALL LETTER ALPHA */
case 0x0261: /* LATIN SMALL LETTER SCRIPT G */
+ case 0x0335: /* COMBINING SHORT STROKE OVERLAY */
case 0x0337: /* COMBINING SHORT SOLIDUS OVERLAY */
case 0x0338: /* COMBINING LONG SOLIDUS OVERLAY */
case 0x05B4: /* HEBREW POINT HIRIQ */
@@ -103,6 +104,11 @@ static inline BOOL isLookalikeCharacter(int charCode)
case 0xFE3F: /* PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET */
case 0xFE5D: /* SMALL LEFT TORTOISE SHELL BRACKET */
case 0xFE5E: /* SMALL RIGHT TORTOISE SHELL BRACKET */
+ case 0x1F50F: /* LOCK WITH INK PEN */
+ case 0x1F510: /* CLOSED LOCK WITH KEY */
+ case 0x1F511: /* KEY */
+ case 0x1F512: /* LOCK */
+ case 0x1F513: /* OPEN LOCK */
return YES;
default:
return NO;
diff --git a/Source/WebCore/platform/mac/WebCoreObjCExtras.h b/Source/WebCore/platform/mac/WebCoreObjCExtras.h
index 62383898d..c032c4eed 100644
--- a/Source/WebCore/platform/mac/WebCoreObjCExtras.h
+++ b/Source/WebCore/platform/mac/WebCoreObjCExtras.h
@@ -26,6 +26,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <CoreFoundation/CFBase.h>
#include <objc/objc.h>
#ifdef __cplusplus
diff --git a/Source/WebCore/platform/mac/WebCoreSystemInterface.h b/Source/WebCore/platform/mac/WebCoreSystemInterface.h
index b2afadd12..12efb9848 100644
--- a/Source/WebCore/platform/mac/WebCoreSystemInterface.h
+++ b/Source/WebCore/platform/mac/WebCoreSystemInterface.h
@@ -41,6 +41,7 @@ typedef struct CGColor *CGColorRef;
typedef struct CGFont *CGFontRef;
typedef struct CGColorSpace *CGColorSpaceRef;
typedef struct CGPattern *CGPatternRef;
+typedef struct CGPath *CGMutablePathRef;
typedef unsigned short CGGlyph;
typedef struct __CFReadStream * CFReadStreamRef;
typedef struct __CFRunLoop * CFRunLoopRef;
@@ -101,6 +102,7 @@ OBJC_CLASS NSView;
OBJC_CLASS NSWindow;
OBJC_CLASS QTMovie;
OBJC_CLASS QTMovieView;
+OBJC_CLASS WebFilterEvaluator;
extern "C" {
@@ -306,6 +308,19 @@ extern NSString *(*wkGetMacOSXVersionString)(void);
extern bool (*wkExecutableWasLinkedOnOrBeforeLion)(void);
#endif
+#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+extern void (*wkCGPathAddRoundedRect)(CGMutablePathRef path, const CGAffineTransform* matrix, CGRect rect, CGFloat cornerWidth, CGFloat cornerHeight);
+#endif
+
+#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) && !PLATFORM(IOS)
+extern BOOL (*wkFilterIsManagedSession)(void);
+extern WebFilterEvaluator *(*wkFilterCreateInstance)(NSURLResponse *);
+extern void (*wkFilterRelease)(WebFilterEvaluator *);
+extern BOOL (*wkFilterWasBlocked)(WebFilterEvaluator *);
+extern const char* (*wkFilterAddData)(WebFilterEvaluator *, const char* data, int* length);
+extern const char* (*wkFilterDataComplete)(WebFilterEvaluator *, int* length);
+#endif
+
}
#endif
diff --git a/Source/WebCore/platform/mac/WebCoreSystemInterface.mm b/Source/WebCore/platform/mac/WebCoreSystemInterface.mm
index 4cce2afb0..2cd6af2d3 100644
--- a/Source/WebCore/platform/mac/WebCoreSystemInterface.mm
+++ b/Source/WebCore/platform/mac/WebCoreSystemInterface.mm
@@ -186,3 +186,16 @@ dispatch_source_t (*wkCreateVMPressureDispatchOnMainQueue)(void);
NSString *(*wkGetMacOSXVersionString)(void);
bool (*wkExecutableWasLinkedOnOrBeforeLion)(void);
#endif
+
+#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+void (*wkCGPathAddRoundedRect)(CGMutablePathRef path, const CGAffineTransform* matrix, CGRect rect, CGFloat cornerWidth, CGFloat cornerHeight);
+#endif
+
+#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) && !PLATFORM(IOS)
+BOOL (*wkFilterIsManagedSession)(void);
+WebFilterEvaluator *(*wkFilterCreateInstance)(NSURLResponse *);
+void (*wkFilterRelease)(WebFilterEvaluator *);
+BOOL (*wkFilterWasBlocked)(WebFilterEvaluator *);
+const char* (*wkFilterAddData)(WebFilterEvaluator *, const char* data, int* length);
+const char* (*wkFilterDataComplete)(WebFilterEvaluator *, int* length);
+#endif
diff --git a/Source/WebCore/platform/mac/WebWindowAnimation.mm b/Source/WebCore/platform/mac/WebWindowAnimation.mm
index 1b1189497..b068965e2 100644
--- a/Source/WebCore/platform/mac/WebWindowAnimation.mm
+++ b/Source/WebCore/platform/mac/WebWindowAnimation.mm
@@ -183,13 +183,13 @@ static CGFloat squaredDistance(NSPoint point1, NSPoint point2)
- (id)initWithDuration:(NSTimeInterval)duration window:(NSWindow *)window initialAlpha:(CGFloat)initialAlpha finalAlpha:(CGFloat)finalAlpha
{
- UNUSED_PARAM(duration);
self = [self init];
if (!self)
return nil;
_window = window;
_initialAlpha = initialAlpha;
_finalAlpha = finalAlpha;
+ [self setDuration:duration];
return self;
}
diff --git a/Source/WebCore/platform/mediastream/PeerConnectionHandler.h b/Source/WebCore/platform/mediastream/DeprecatedPeerConnectionHandler.h
index fa22cf4c7..6e34de56d 100644
--- a/Source/WebCore/platform/mediastream/PeerConnectionHandler.h
+++ b/Source/WebCore/platform/mediastream/DeprecatedPeerConnectionHandler.h
@@ -28,8 +28,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef PeerConnectionHandler_h
-#define PeerConnectionHandler_h
+#ifndef DeprecatedPeerConnectionHandler_h
+#define DeprecatedPeerConnectionHandler_h
#if ENABLE(MEDIA_STREAM)
@@ -40,18 +40,18 @@
namespace WebCore {
-class PeerConnectionHandlerClient;
+class DeprecatedPeerConnectionHandlerClient;
#if PLATFORM(CHROMIUM)
-class PeerConnectionHandlerInternal;
+class DeprecatedPeerConnectionHandlerInternal;
#endif
-class PeerConnectionHandler {
- WTF_MAKE_NONCOPYABLE(PeerConnectionHandler);
+class DeprecatedPeerConnectionHandler {
+ WTF_MAKE_NONCOPYABLE(DeprecatedPeerConnectionHandler);
WTF_MAKE_FAST_ALLOCATED;
public:
- static PassOwnPtr<PeerConnectionHandler> create(PeerConnectionHandlerClient*, const String& serverConfiguration, const String& username);
- ~PeerConnectionHandler();
+ static PassOwnPtr<DeprecatedPeerConnectionHandler> create(DeprecatedPeerConnectionHandlerClient*, const String& serverConfiguration, const String& username);
+ ~DeprecatedPeerConnectionHandler();
void produceInitialOffer(const MediaStreamDescriptorVector& pendingAddStreams);
void handleInitialOffer(const String& sdp);
@@ -62,12 +62,12 @@ public:
void stop();
private:
- PeerConnectionHandler(PeerConnectionHandlerClient*, const String& serverConfiguration, const String& username);
+ DeprecatedPeerConnectionHandler(DeprecatedPeerConnectionHandlerClient*, const String& serverConfiguration, const String& username);
#if PLATFORM(CHROMIUM)
- OwnPtr<PeerConnectionHandlerInternal> m_private;
+ OwnPtr<DeprecatedPeerConnectionHandlerInternal> m_private;
#elif USE(GSTREAMER)
- PeerConnectionHandlerClient* m_client;
+ DeprecatedPeerConnectionHandlerClient* m_client;
#endif
};
@@ -75,4 +75,4 @@ private:
#endif // ENABLE(MEDIA_STREAM)
-#endif // PeerConnectionHandler_h
+#endif // DeprecatedPeerConnectionHandler_h
diff --git a/Source/WebCore/platform/mediastream/PeerConnectionHandlerClient.h b/Source/WebCore/platform/mediastream/DeprecatedPeerConnectionHandlerClient.h
index e67ef3a55..86c7f09ea 100644
--- a/Source/WebCore/platform/mediastream/PeerConnectionHandlerClient.h
+++ b/Source/WebCore/platform/mediastream/DeprecatedPeerConnectionHandlerClient.h
@@ -28,8 +28,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef PeerConnectionHandlerClient_h
-#define PeerConnectionHandlerClient_h
+#ifndef DeprecatedPeerConnectionHandlerClient_h
+#define DeprecatedPeerConnectionHandlerClient_h
#if ENABLE(MEDIA_STREAM)
@@ -40,7 +40,7 @@ namespace WebCore {
class MediaStreamDescriptor;
-class PeerConnectionHandlerClient {
+class DeprecatedPeerConnectionHandlerClient {
public:
// Name and values of the enum must match the corressponding constants in the PeerConnection.idl file.
enum ReadyState {
@@ -50,7 +50,7 @@ public:
CLOSED = 3
};
- virtual ~PeerConnectionHandlerClient() { }
+ virtual ~DeprecatedPeerConnectionHandlerClient() { }
virtual void didCompleteICEProcessing() = 0;
virtual void didGenerateSDP(const String& sdp) = 0;
@@ -64,4 +64,4 @@ public:
#endif // ENABLE(MEDIA_STREAM)
-#endif // PeerConnectionHandlerClient_h
+#endif // DeprecatedPeerConnectionHandlerClient_h
diff --git a/Source/WebCore/platform/mediastream/IceCandidateDescriptor.cpp b/Source/WebCore/platform/mediastream/IceCandidateDescriptor.cpp
new file mode 100644
index 000000000..d1f1c60eb
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/IceCandidateDescriptor.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Google Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "IceCandidateDescriptor.h"
+
+#include "MediaStreamCenter.h"
+
+namespace WebCore {
+
+PassRefPtr<IceCandidateDescriptor> IceCandidateDescriptor::create(const String& label, const String& candidateLine)
+{
+ return adoptRef(new IceCandidateDescriptor(label, candidateLine));
+}
+
+IceCandidateDescriptor::IceCandidateDescriptor(const String& label, const String& candidateLine)
+ : m_label(label)
+ , m_candidateLine(candidateLine)
+{
+}
+
+IceCandidateDescriptor::~IceCandidateDescriptor()
+{
+}
+
+String IceCandidateDescriptor::toSDP()
+{
+ return MediaStreamCenter::instance().constructSDP(this);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
diff --git a/Source/WebCore/platform/mediastream/IceCandidateDescriptor.h b/Source/WebCore/platform/mediastream/IceCandidateDescriptor.h
new file mode 100644
index 000000000..b7754907a
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/IceCandidateDescriptor.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Google Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef IceCandidateDescriptor_h
+#define IceCandidateDescriptor_h
+
+#if ENABLE(MEDIA_STREAM)
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class IceCandidateDescriptor : public RefCounted<IceCandidateDescriptor> {
+public:
+ static PassRefPtr<IceCandidateDescriptor> create(const String& label, const String& candidateLine);
+ virtual ~IceCandidateDescriptor();
+
+ const String& label() { return m_label; }
+ const String& candidateLine() { return m_candidateLine; }
+
+ String toSDP();
+
+private:
+ IceCandidateDescriptor(const String& label, const String& candidateLine);
+
+ String m_label;
+ String m_candidateLine;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif // IceCandidateDescriptor_h
diff --git a/Source/WebCore/platform/mediastream/IceOptions.cpp b/Source/WebCore/platform/mediastream/IceOptions.cpp
new file mode 100644
index 000000000..ee3d29ebc
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/IceOptions.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Google Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "IceOptions.h"
+
+namespace WebCore {
+
+PassRefPtr<IceOptions> IceOptions::create(UseCandidatesOption useCandidates)
+{
+ return adoptRef(new IceOptions(useCandidates));
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
diff --git a/Source/WebCore/platform/mediastream/IceOptions.h b/Source/WebCore/platform/mediastream/IceOptions.h
new file mode 100644
index 000000000..87b5db180
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/IceOptions.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Google Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef IceOptions_h
+#define IceOptions_h
+
+#if ENABLE(MEDIA_STREAM)
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class IceOptions : public RefCounted<IceOptions> {
+public:
+ enum UseCandidatesOption {
+ ALL,
+ NO_RELAY,
+ ONLY_RELAY,
+ };
+
+ static PassRefPtr<IceOptions> create(UseCandidatesOption);
+ virtual ~IceOptions() { }
+
+ UseCandidatesOption useCandidates() { return m_useCandidates; }
+
+ private:
+ explicit IceOptions(UseCandidatesOption useCandidates) : m_useCandidates(useCandidates) { }
+
+ UseCandidatesOption m_useCandidates;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif // IceOptions_h
diff --git a/Source/WebCore/platform/mediastream/MediaHints.cpp b/Source/WebCore/platform/mediastream/MediaHints.cpp
new file mode 100644
index 000000000..4bc5695d8
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/MediaHints.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Google Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "MediaHints.h"
+
+namespace WebCore {
+
+PassRefPtr<MediaHints> MediaHints::create(bool audio, bool video)
+{
+ return adoptRef(new MediaHints(audio, video));
+}
+
+bool MediaHints::audio()
+{
+ return m_audio;
+}
+
+bool MediaHints::video()
+{
+ return m_video;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
diff --git a/Source/WebCore/platform/mediastream/MediaHints.h b/Source/WebCore/platform/mediastream/MediaHints.h
new file mode 100644
index 000000000..6455eb6dd
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/MediaHints.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Google Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MediaHints_h
+#define MediaHints_h
+
+#if ENABLE(MEDIA_STREAM)
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class MediaHints : public RefCounted<MediaHints> {
+public:
+ static PassRefPtr<MediaHints> create(bool audio, bool video);
+ virtual ~MediaHints() { }
+
+ bool audio();
+ bool video();
+
+ private:
+ MediaHints(bool audio, bool video) : m_audio(audio), m_video(video) { }
+
+ bool m_audio;
+ bool m_video;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif // MediaHints_h
diff --git a/Source/WebCore/platform/mediastream/MediaStreamCenter.cpp b/Source/WebCore/platform/mediastream/MediaStreamCenter.cpp
index abccf5b9b..9dd4bb176 100644
--- a/Source/WebCore/platform/mediastream/MediaStreamCenter.cpp
+++ b/Source/WebCore/platform/mediastream/MediaStreamCenter.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2011 Ericsson AB. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,16 +35,16 @@
#include "MediaStreamCenter.h"
-#include "MainThread.h"
#include "MediaStreamDescriptor.h"
namespace WebCore {
-MediaStreamCenter& MediaStreamCenter::instance()
+MediaStreamCenter::MediaStreamCenter()
+{
+}
+
+MediaStreamCenter::~MediaStreamCenter()
{
- ASSERT(isMainThread());
- DEFINE_STATIC_LOCAL(MediaStreamCenter, center, ());
- return center;
}
void MediaStreamCenter::endLocalMediaStream(MediaStreamDescriptor* streamDescriptor)
@@ -55,38 +56,6 @@ void MediaStreamCenter::endLocalMediaStream(MediaStreamDescriptor* streamDescrip
streamDescriptor->setEnded();
}
-#if !PLATFORM(CHROMIUM)
-
-// Empty implementations for ports that build with MEDIA_STREAM enabled by default, but haven't yet implemented MediaStreamCenter.
-
-MediaStreamCenter::MediaStreamCenter()
-{
-}
-
-MediaStreamCenter::~MediaStreamCenter()
-{
-}
-
-void MediaStreamCenter::queryMediaStreamSources(PassRefPtr<MediaStreamSourcesQueryClient> client)
-{
- MediaStreamSourceVector audioSources, videoSources;
- client->didCompleteQuery(audioSources, videoSources);
-}
-
-void MediaStreamCenter::didSetMediaStreamTrackEnabled(MediaStreamDescriptor*, MediaStreamComponent*)
-{
-}
-
-void MediaStreamCenter::didStopLocalMediaStream(MediaStreamDescriptor*)
-{
-}
-
-void MediaStreamCenter::didConstructMediaStream(MediaStreamDescriptor*)
-{
-}
-
-#endif // !PLATFORM(CHROMIUM)
-
} // namespace WebCore
#endif // ENABLE(MEDIA_STREAM)
diff --git a/Source/WebCore/platform/mediastream/MediaStreamCenter.h b/Source/WebCore/platform/mediastream/MediaStreamCenter.h
index a37d66a26..76a8b556e 100644
--- a/Source/WebCore/platform/mediastream/MediaStreamCenter.h
+++ b/Source/WebCore/platform/mediastream/MediaStreamCenter.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2011 Ericsson AB. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,56 +34,39 @@
#if ENABLE(MEDIA_STREAM)
-#include "MediaStreamSource.h"
-#include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/text/WTFString.h>
namespace WebCore {
-#if PLATFORM(CHROMIUM)
-class MediaStreamCenterInternal;
-#endif
-
+class IceCandidateDescriptor;
class MediaStreamComponent;
class MediaStreamDescriptor;
-
-class MediaStreamSourcesQueryClient : public RefCounted<MediaStreamSourcesQueryClient> {
-public:
- virtual ~MediaStreamSourcesQueryClient() { }
-
- virtual bool audio() const = 0;
- virtual bool video() const = 0;
- virtual bool cameraPreferenceUser() const = 0;
- virtual bool cameraPreferenceEnvironment() const = 0;
-
- virtual void didCompleteQuery(const MediaStreamSourceVector& audioSources, const MediaStreamSourceVector& videoSources) = 0;
-};
+class MediaStreamSourcesQueryClient;
+class SessionDescriptionDescriptor;
class MediaStreamCenter {
- WTF_MAKE_NONCOPYABLE(MediaStreamCenter);
- WTF_MAKE_FAST_ALLOCATED;
public:
- ~MediaStreamCenter();
+ virtual ~MediaStreamCenter();
static MediaStreamCenter& instance();
- void queryMediaStreamSources(PassRefPtr<MediaStreamSourcesQueryClient>);
+ virtual void queryMediaStreamSources(PassRefPtr<MediaStreamSourcesQueryClient>) = 0;
// FIXME: add a way to mute a MediaStreamSource from the WebKit API layer
// Calls from the DOM objects to notify the platform
- void didSetMediaStreamTrackEnabled(MediaStreamDescriptor*, MediaStreamComponent*);
- void didStopLocalMediaStream(MediaStreamDescriptor*);
- void didConstructMediaStream(MediaStreamDescriptor*);
+ virtual void didSetMediaStreamTrackEnabled(MediaStreamDescriptor*, MediaStreamComponent*) = 0;
+ virtual void didStopLocalMediaStream(MediaStreamDescriptor*) = 0;
+ virtual void didConstructMediaStream(MediaStreamDescriptor*) = 0;
- // Calls from the platform to update the DOM objects
- void endLocalMediaStream(MediaStreamDescriptor*);
+ virtual String constructSDP(IceCandidateDescriptor*) = 0;
+ virtual String constructSDP(SessionDescriptionDescriptor*) = 0;
-private:
+protected:
MediaStreamCenter();
-#if PLATFORM(CHROMIUM)
- OwnPtr<MediaStreamCenterInternal> m_private;
-#endif
+ void endLocalMediaStream(MediaStreamDescriptor*);
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/mediastream/MediaStreamSourcesQueryClient.h b/Source/WebCore/platform/mediastream/MediaStreamSourcesQueryClient.h
new file mode 100644
index 000000000..66ccbaa37
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/MediaStreamSourcesQueryClient.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 Ericsson AB. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Ericsson nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MediaStreamSourcesQueryClient_h
+#define MediaStreamSourcesQueryClient_h
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "MediaStreamSource.h"
+
+namespace WebCore {
+
+class MediaStreamSourcesQueryClient : public RefCounted<MediaStreamSourcesQueryClient> {
+public:
+ virtual ~MediaStreamSourcesQueryClient() { }
+
+ virtual bool audio() const = 0;
+ virtual bool video() const = 0;
+
+ virtual void didCompleteQuery(const MediaStreamSourceVector& audioSources, const MediaStreamSourceVector& videoSources) = 0;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif // MediaStreamSourcesQueryClient_h
diff --git a/Source/WebCore/platform/mediastream/PeerConnection00Handler.cpp b/Source/WebCore/platform/mediastream/PeerConnection00Handler.cpp
new file mode 100644
index 000000000..f646e27ea
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/PeerConnection00Handler.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2012 Google AB. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Google Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "PeerConnection00Handler.h"
+
+#include "IceCandidateDescriptor.h"
+#include "IceOptions.h"
+#include "MediaHints.h"
+#include "MediaStreamDescriptor.h"
+#include "PeerConnection00HandlerClient.h"
+#include "SessionDescriptionDescriptor.h"
+
+namespace WebCore {
+
+// Dummy implementations below for ports that build with MEDIA_STREAM enabled by default.
+
+PassOwnPtr<PeerConnection00Handler> PeerConnection00Handler::create(PeerConnection00HandlerClient* client, const String& serverConfiguration, const String& username)
+{
+ return adoptPtr(new PeerConnection00Handler(client, serverConfiguration, username));
+}
+
+PeerConnection00Handler::PeerConnection00Handler(PeerConnection00HandlerClient* client, const String&, const String&)
+ : m_client(client)
+{
+}
+
+PeerConnection00Handler::~PeerConnection00Handler()
+{
+}
+
+PassRefPtr<SessionDescriptionDescriptor> PeerConnection00Handler::createOffer(PassRefPtr<MediaHints>)
+{
+ return 0;
+}
+
+PassRefPtr<SessionDescriptionDescriptor> PeerConnection00Handler::createAnswer(const String&, PassRefPtr<MediaHints>)
+{
+ return 0;
+}
+
+bool PeerConnection00Handler::setLocalDescription(int, PassRefPtr<SessionDescriptionDescriptor>)
+{
+ return false;
+}
+
+bool PeerConnection00Handler::setRemoteDescription(int, PassRefPtr<SessionDescriptionDescriptor>)
+{
+ return false;
+}
+
+PassRefPtr<SessionDescriptionDescriptor> PeerConnection00Handler::localDescription()
+{
+ return 0;
+}
+
+PassRefPtr<SessionDescriptionDescriptor> PeerConnection00Handler::remoteDescription()
+{
+ return 0;
+}
+
+bool PeerConnection00Handler::startIce(PassRefPtr<IceOptions>)
+{
+ return false;
+}
+
+bool PeerConnection00Handler::processIceMessage(PassRefPtr<IceCandidateDescriptor>)
+{
+ return false;
+}
+
+void PeerConnection00Handler::addStream(PassRefPtr<MediaStreamDescriptor>)
+{
+}
+
+void PeerConnection00Handler::removeStream(PassRefPtr<MediaStreamDescriptor>)
+{
+}
+
+void PeerConnection00Handler::stop()
+{
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
diff --git a/Source/WebCore/platform/mediastream/PeerConnection00Handler.h b/Source/WebCore/platform/mediastream/PeerConnection00Handler.h
new file mode 100644
index 000000000..170f06246
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/PeerConnection00Handler.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Google Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PeerConnection00Handler_h
+#define PeerConnection00Handler_h
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "MediaStreamDescriptor.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class IceCandidateDescriptor;
+class IceOptions;
+class MediaHints;
+class PeerConnection00HandlerClient;
+class SessionDescriptionDescriptor;
+
+#if PLATFORM(CHROMIUM)
+class PeerConnection00HandlerInternal;
+#endif
+
+class PeerConnection00Handler {
+ WTF_MAKE_NONCOPYABLE(PeerConnection00Handler);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ static PassOwnPtr<PeerConnection00Handler> create(PeerConnection00HandlerClient*, const String& serverConfiguration, const String& username);
+ ~PeerConnection00Handler();
+
+ PassRefPtr<SessionDescriptionDescriptor> createOffer(PassRefPtr<MediaHints>);
+ PassRefPtr<SessionDescriptionDescriptor> createAnswer(const String& offer, PassRefPtr<MediaHints>);
+ bool setLocalDescription(int action, PassRefPtr<SessionDescriptionDescriptor>);
+ bool setRemoteDescription(int action, PassRefPtr<SessionDescriptionDescriptor>);
+ PassRefPtr<SessionDescriptionDescriptor> localDescription();
+ PassRefPtr<SessionDescriptionDescriptor> remoteDescription();
+ bool startIce(PassRefPtr<IceOptions>);
+ bool processIceMessage(PassRefPtr<IceCandidateDescriptor>);
+ void addStream(PassRefPtr<MediaStreamDescriptor>);
+ void removeStream(PassRefPtr<MediaStreamDescriptor>);
+ void stop();
+
+private:
+ PeerConnection00Handler(PeerConnection00HandlerClient*, const String& serverConfiguration, const String& username);
+
+#if PLATFORM(CHROMIUM)
+ OwnPtr<PeerConnection00HandlerInternal> m_private;
+#else
+ PeerConnection00HandlerClient* m_client;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif // PeerConnection00Handler_h
diff --git a/Source/WebCore/platform/mediastream/PeerConnection00HandlerClient.h b/Source/WebCore/platform/mediastream/PeerConnection00HandlerClient.h
new file mode 100644
index 000000000..610381b9e
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/PeerConnection00HandlerClient.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 Google AB. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Google Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PeerConnection00HandlerClient_h
+#define PeerConnection00HandlerClient_h
+
+#if ENABLE(MEDIA_STREAM)
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class IceCandidateDescriptor;
+class MediaStreamDescriptor;
+
+class PeerConnection00HandlerClient {
+public:
+ virtual ~PeerConnection00HandlerClient() { }
+
+ virtual void didGenerateIceCandidate(PassRefPtr<IceCandidateDescriptor>, bool moreToFollow) = 0;
+ virtual void didChangeReadyState(uint32_t state) = 0;
+ virtual void didChangeIceState(uint32_t state) = 0;
+ virtual void didAddRemoteStream(PassRefPtr<MediaStreamDescriptor>) = 0;
+ virtual void didRemoveRemoteStream(MediaStreamDescriptor*) = 0;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif // PeerConnection00HandlerClient_h
diff --git a/Source/WebCore/platform/mediastream/SessionDescriptionDescriptor.cpp b/Source/WebCore/platform/mediastream/SessionDescriptionDescriptor.cpp
new file mode 100644
index 000000000..48c609570
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/SessionDescriptionDescriptor.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Google Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "SessionDescriptionDescriptor.h"
+
+#include "IceCandidateDescriptor.h"
+#include "MediaStreamCenter.h"
+
+namespace WebCore {
+
+PassRefPtr<SessionDescriptionDescriptor> SessionDescriptionDescriptor::create(const String& sdp)
+{
+ return adoptRef(new SessionDescriptionDescriptor(sdp));
+}
+
+SessionDescriptionDescriptor::SessionDescriptionDescriptor(const String& sdp)
+ : m_initialSDP(sdp)
+{
+}
+
+SessionDescriptionDescriptor::~SessionDescriptionDescriptor()
+{
+}
+
+void SessionDescriptionDescriptor::addCandidate(PassRefPtr<IceCandidateDescriptor> candidate)
+{
+ m_candidates.append(candidate);
+}
+
+String SessionDescriptionDescriptor::toSDP()
+{
+ return MediaStreamCenter::instance().constructSDP(this);
+}
+
+size_t SessionDescriptionDescriptor::numberOfAddedCandidates() const
+{
+ return m_candidates.size();
+}
+
+IceCandidateDescriptor* SessionDescriptionDescriptor::candidate(size_t index) const
+{
+ return m_candidates[index].get();
+}
+
+const String& SessionDescriptionDescriptor::initialSDP()
+{
+ return m_initialSDP;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
diff --git a/Source/WebCore/platform/mediastream/SessionDescriptionDescriptor.h b/Source/WebCore/platform/mediastream/SessionDescriptionDescriptor.h
new file mode 100644
index 000000000..45128432a
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/SessionDescriptionDescriptor.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Google Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SessionDescriptionDescriptor_h
+#define SessionDescriptionDescriptor_h
+
+#if ENABLE(MEDIA_STREAM)
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class IceCandidateDescriptor;
+
+class SessionDescriptionDescriptor : public RefCounted<SessionDescriptionDescriptor> {
+public:
+ static PassRefPtr<SessionDescriptionDescriptor> create(const String& sdp);
+ virtual ~SessionDescriptionDescriptor();
+
+ void addCandidate(PassRefPtr<IceCandidateDescriptor>);
+ String toSDP();
+
+ size_t numberOfAddedCandidates() const;
+ IceCandidateDescriptor* candidate(size_t index) const;
+ const String& initialSDP();
+
+private:
+ explicit SessionDescriptionDescriptor(const String& sdp);
+
+ String m_initialSDP;
+ Vector<RefPtr<IceCandidateDescriptor> > m_candidates;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif // SessionDescriptionDescriptor_h
diff --git a/Source/WebCore/platform/mediastream/chromium/DeprecatedPeerConnectionHandler.cpp b/Source/WebCore/platform/mediastream/chromium/DeprecatedPeerConnectionHandler.cpp
new file mode 100644
index 000000000..10d5f17e3
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/chromium/DeprecatedPeerConnectionHandler.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "DeprecatedPeerConnectionHandler.h"
+
+#include "DeprecatedPeerConnectionHandlerClient.h"
+#include "DeprecatedPeerConnectionHandlerInternal.h"
+
+namespace WebCore {
+
+PassOwnPtr<DeprecatedPeerConnectionHandler> DeprecatedPeerConnectionHandler::create(DeprecatedPeerConnectionHandlerClient* client, const String& serverConfiguration, const String& username)
+{
+ return adoptPtr(new DeprecatedPeerConnectionHandler(client, serverConfiguration, username));
+}
+
+DeprecatedPeerConnectionHandler::DeprecatedPeerConnectionHandler(DeprecatedPeerConnectionHandlerClient* client, const String& serverConfiguration, const String& username)
+ : m_private(adoptPtr(new DeprecatedPeerConnectionHandlerInternal(client, serverConfiguration, username)))
+{
+}
+
+DeprecatedPeerConnectionHandler::~DeprecatedPeerConnectionHandler()
+{
+}
+
+void DeprecatedPeerConnectionHandler::produceInitialOffer(const MediaStreamDescriptorVector& pendingAddStreams)
+{
+ m_private->produceInitialOffer(pendingAddStreams);
+}
+
+void DeprecatedPeerConnectionHandler::handleInitialOffer(const String& sdp)
+{
+ m_private->handleInitialOffer(sdp);
+}
+
+void DeprecatedPeerConnectionHandler::processSDP(const String& sdp)
+{
+ m_private->processSDP(sdp);
+}
+
+void DeprecatedPeerConnectionHandler::processPendingStreams(const MediaStreamDescriptorVector& pendingAddStreams, const MediaStreamDescriptorVector& pendingRemoveStreams)
+{
+ m_private->processPendingStreams(pendingAddStreams, pendingRemoveStreams);
+}
+
+void DeprecatedPeerConnectionHandler::sendDataStreamMessage(const char* data, size_t length)
+{
+ m_private->sendDataStreamMessage(data, length);
+}
+
+void DeprecatedPeerConnectionHandler::stop()
+{
+ m_private->stop();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
diff --git a/Source/WebCore/platform/mediastream/chromium/DeprecatedPeerConnectionHandlerInternal.cpp b/Source/WebCore/platform/mediastream/chromium/DeprecatedPeerConnectionHandlerInternal.cpp
new file mode 100644
index 000000000..d5e963811
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/chromium/DeprecatedPeerConnectionHandlerInternal.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "DeprecatedPeerConnectionHandlerInternal.h"
+
+#include "DeprecatedPeerConnectionHandlerClient.h"
+#include <public/Platform.h>
+#include <public/WebMediaStreamDescriptor.h>
+#include <public/WebPeerConnectionHandler.h>
+#include <public/WebPeerConnectionHandlerClient.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+DeprecatedPeerConnectionHandlerInternal::DeprecatedPeerConnectionHandlerInternal(DeprecatedPeerConnectionHandlerClient* client, const String& serverConfiguration, const String& username)
+ : m_client(client)
+{
+ ASSERT(m_client);
+ m_webHandler = adoptPtr(WebKit::Platform::current()->createPeerConnectionHandler(this));
+ // FIXME: When there is some error reporting avaliable in the PeerConnection object report
+ // if we didn't get a WebPeerConnectionHandler instance.
+
+ if (m_webHandler)
+ m_webHandler->initialize(serverConfiguration, username);
+}
+
+DeprecatedPeerConnectionHandlerInternal::~DeprecatedPeerConnectionHandlerInternal()
+{
+}
+
+void DeprecatedPeerConnectionHandlerInternal::produceInitialOffer(const MediaStreamDescriptorVector& pendingAddStreams)
+{
+ if (m_webHandler)
+ m_webHandler->produceInitialOffer(pendingAddStreams);
+}
+
+void DeprecatedPeerConnectionHandlerInternal::handleInitialOffer(const String& sdp)
+{
+ if (m_webHandler)
+ m_webHandler->handleInitialOffer(sdp);
+}
+
+void DeprecatedPeerConnectionHandlerInternal::processSDP(const String& sdp)
+{
+ if (m_webHandler)
+ m_webHandler->processSDP(sdp);
+}
+
+void DeprecatedPeerConnectionHandlerInternal::processPendingStreams(const MediaStreamDescriptorVector& pendingAddStreams, const MediaStreamDescriptorVector& pendingRemoveStreams)
+{
+ if (m_webHandler)
+ m_webHandler->processPendingStreams(pendingAddStreams, pendingRemoveStreams);
+}
+
+void DeprecatedPeerConnectionHandlerInternal::sendDataStreamMessage(const char* data, size_t length)
+{
+ if (m_webHandler)
+ m_webHandler->sendDataStreamMessage(data, length);
+}
+
+void DeprecatedPeerConnectionHandlerInternal::stop()
+{
+ if (m_webHandler)
+ m_webHandler->stop();
+}
+
+void DeprecatedPeerConnectionHandlerInternal::didCompleteICEProcessing()
+{
+ if (m_webHandler)
+ m_client->didCompleteICEProcessing();
+}
+
+void DeprecatedPeerConnectionHandlerInternal::didGenerateSDP(const WebKit::WebString& sdp)
+{
+ if (m_webHandler)
+ m_client->didGenerateSDP(sdp);
+}
+
+void DeprecatedPeerConnectionHandlerInternal::didReceiveDataStreamMessage(const char* data, size_t length)
+{
+ if (m_webHandler)
+ m_client->didReceiveDataStreamMessage(data, length);
+}
+
+void DeprecatedPeerConnectionHandlerInternal::didAddRemoteStream(const WebKit::WebMediaStreamDescriptor& webMediaStreamDescriptor)
+{
+ if (m_webHandler)
+ m_client->didAddRemoteStream(webMediaStreamDescriptor);
+}
+
+void DeprecatedPeerConnectionHandlerInternal::didRemoveRemoteStream(const WebKit::WebMediaStreamDescriptor& webMediaStreamDescriptor)
+{
+ if (m_webHandler)
+ m_client->didRemoveRemoteStream(webMediaStreamDescriptor);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
diff --git a/Source/WebCore/platform/mediastream/chromium/DeprecatedPeerConnectionHandlerInternal.h b/Source/WebCore/platform/mediastream/chromium/DeprecatedPeerConnectionHandlerInternal.h
new file mode 100644
index 000000000..17fcb93b4
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/chromium/DeprecatedPeerConnectionHandlerInternal.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DeprecatedPeerConnectionHandlerInternal_h
+#define DeprecatedPeerConnectionHandlerInternal_h
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "MediaStreamDescriptor.h"
+#include <public/WebPeerConnectionHandlerClient.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+class WebPeerConnectionHandler;
+class WebString;
+class WebMediaStreamDescriptor;
+}
+
+namespace WebCore {
+
+class DeprecatedPeerConnectionHandlerClient;
+
+class DeprecatedPeerConnectionHandlerInternal : public WebKit::WebPeerConnectionHandlerClient {
+public:
+ DeprecatedPeerConnectionHandlerInternal(DeprecatedPeerConnectionHandlerClient*, const String& serverConfiguration, const String& username);
+ ~DeprecatedPeerConnectionHandlerInternal();
+
+ virtual void produceInitialOffer(const MediaStreamDescriptorVector& pendingAddStreams);
+ virtual void handleInitialOffer(const String& sdp);
+ virtual void processSDP(const String& sdp);
+ virtual void processPendingStreams(const MediaStreamDescriptorVector& pendingAddStreams, const MediaStreamDescriptorVector& pendingRemoveStreams);
+ virtual void sendDataStreamMessage(const char* data, size_t length);
+ virtual void stop();
+
+ // WebKit::WebPeerConnectionHandlerClient implementation.
+ virtual void didCompleteICEProcessing();
+ virtual void didGenerateSDP(const WebKit::WebString& sdp);
+ virtual void didReceiveDataStreamMessage(const char* data, size_t length);
+ virtual void didAddRemoteStream(const WebKit::WebMediaStreamDescriptor&);
+ virtual void didRemoveRemoteStream(const WebKit::WebMediaStreamDescriptor&);
+
+private:
+ OwnPtr<WebKit::WebPeerConnectionHandler> m_webHandler;
+ DeprecatedPeerConnectionHandlerClient* m_client;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif // DeprecatedPeerConnectionHandlerInternal_h
diff --git a/Source/WebCore/platform/mediastream/chromium/MediaStreamCenterChromium.cpp b/Source/WebCore/platform/mediastream/chromium/MediaStreamCenterChromium.cpp
new file mode 100644
index 000000000..152d392bf
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/chromium/MediaStreamCenterChromium.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "MediaStreamCenterChromium.h"
+
+#include "IceCandidateDescriptor.h"
+#include "MediaStreamDescriptor.h"
+#include "MediaStreamSourcesQueryClient.h"
+#include "SessionDescriptionDescriptor.h"
+#include <public/Platform.h>
+#include <public/WebICECandidateDescriptor.h>
+#include <public/WebMediaStreamCenter.h>
+#include <public/WebMediaStreamComponent.h>
+#include <public/WebMediaStreamDescriptor.h>
+#include <public/WebMediaStreamSourcesRequest.h>
+#include <public/WebSessionDescriptionDescriptor.h>
+#include <wtf/MainThread.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+MediaStreamCenter& MediaStreamCenter::instance()
+{
+ ASSERT(isMainThread());
+ DEFINE_STATIC_LOCAL(MediaStreamCenterChromium, center, ());
+ return center;
+}
+
+MediaStreamCenterChromium::MediaStreamCenterChromium()
+ : m_private(adoptPtr(WebKit::Platform::current()->createMediaStreamCenter(this)))
+{
+}
+
+MediaStreamCenterChromium::~MediaStreamCenterChromium()
+{
+}
+
+void MediaStreamCenterChromium::queryMediaStreamSources(PassRefPtr<MediaStreamSourcesQueryClient> client)
+{
+ // FIXME: Remove this "short-circuit" and forward to m_private when Chrome and DumpRenderTree has implemented WebMediaStreamCenter.
+ MediaStreamSourceVector audioSources, videoSources;
+ client->didCompleteQuery(audioSources, videoSources);
+}
+
+void MediaStreamCenterChromium::didSetMediaStreamTrackEnabled(MediaStreamDescriptor* stream, MediaStreamComponent* component)
+{
+ if (m_private) {
+ if (component->enabled())
+ m_private->didEnableMediaStreamTrack(stream, component);
+ else
+ m_private->didDisableMediaStreamTrack(stream, component);
+ }
+}
+
+void MediaStreamCenterChromium::didStopLocalMediaStream(MediaStreamDescriptor* stream)
+{
+ if (m_private)
+ m_private->didStopLocalMediaStream(stream);
+}
+
+void MediaStreamCenterChromium::didConstructMediaStream(MediaStreamDescriptor* stream)
+{
+ if (m_private)
+ m_private->didConstructMediaStream(stream);
+}
+
+String MediaStreamCenterChromium::constructSDP(IceCandidateDescriptor* iceCandidate)
+{
+ return m_private ? m_private->constructSDP(WebKit::WebICECandidateDescriptor(iceCandidate)) : "";
+}
+
+String MediaStreamCenterChromium::constructSDP(SessionDescriptionDescriptor* sessionDescription)
+{
+ return m_private ? m_private->constructSDP(WebKit::WebSessionDescriptionDescriptor(sessionDescription)) : "";
+}
+
+void MediaStreamCenterChromium::stopLocalMediaStream(const WebKit::WebMediaStreamDescriptor& stream)
+{
+ endLocalMediaStream(stream);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
diff --git a/Source/WebCore/platform/mediastream/chromium/MediaStreamCenterChromium.h b/Source/WebCore/platform/mediastream/chromium/MediaStreamCenterChromium.h
new file mode 100644
index 000000000..ec858d149
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/chromium/MediaStreamCenterChromium.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Google Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MediaStreamCenterChromium_h
+#define MediaStreamCenterChromium_h
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "MediaStreamCenter.h"
+
+#include <public/WebMediaStreamCenterClient.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+class WebMediaStreamCenter;
+class WebMediaStreamDescriptor;
+}
+
+namespace WebCore {
+
+class IceCandidateDescriptor;
+class MediaStreamComponent;
+class MediaStreamDescriptor;
+class MediaStreamSourcesQueryClient;
+class SessionDescriptionDescriptor;
+
+class MediaStreamCenterChromium : public MediaStreamCenter, public WebKit::WebMediaStreamCenterClient {
+public:
+ MediaStreamCenterChromium();
+ ~MediaStreamCenterChromium();
+
+ // MediaStreamCenter
+ virtual void queryMediaStreamSources(PassRefPtr<MediaStreamSourcesQueryClient>) OVERRIDE;
+ virtual void didSetMediaStreamTrackEnabled(MediaStreamDescriptor*, MediaStreamComponent*) OVERRIDE;
+ virtual void didStopLocalMediaStream(MediaStreamDescriptor*) OVERRIDE;
+ virtual void didConstructMediaStream(MediaStreamDescriptor*) OVERRIDE;
+ virtual String constructSDP(IceCandidateDescriptor*) OVERRIDE;
+ virtual String constructSDP(SessionDescriptionDescriptor*) OVERRIDE;
+
+ // WebKit::WebMediaStreamCenterClient
+ virtual void stopLocalMediaStream(const WebKit::WebMediaStreamDescriptor&) OVERRIDE;
+
+private:
+ OwnPtr<WebKit::WebMediaStreamCenter> m_private;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif // MediaStreamCenterChromium_h
diff --git a/Source/WebCore/platform/mediastream/chromium/PeerConnection00Handler.cpp b/Source/WebCore/platform/mediastream/chromium/PeerConnection00Handler.cpp
new file mode 100644
index 000000000..b04e0a837
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/chromium/PeerConnection00Handler.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Google Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "PeerConnection00Handler.h"
+
+#include "IceCandidateDescriptor.h"
+#include "IceOptions.h"
+#include "MediaHints.h"
+#include "MediaStreamDescriptor.h"
+#include "PeerConnection00HandlerClient.h"
+#include "PeerConnection00HandlerInternal.h"
+#include "SessionDescriptionDescriptor.h"
+
+namespace WebCore {
+
+PassOwnPtr<PeerConnection00Handler> PeerConnection00Handler::create(PeerConnection00HandlerClient* client, const String& serverConfiguration, const String& username)
+{
+ return adoptPtr(new PeerConnection00Handler(client, serverConfiguration, username));
+}
+
+PeerConnection00Handler::PeerConnection00Handler(PeerConnection00HandlerClient* client, const String& serverConfiguration, const String& username)
+ : m_private(adoptPtr(new PeerConnection00HandlerInternal(client, serverConfiguration, username)))
+{
+}
+
+PeerConnection00Handler::~PeerConnection00Handler()
+{
+}
+
+PassRefPtr<SessionDescriptionDescriptor> PeerConnection00Handler::createOffer(PassRefPtr<MediaHints> mediaHints)
+{
+ return m_private->createOffer(mediaHints);
+}
+
+PassRefPtr<SessionDescriptionDescriptor> PeerConnection00Handler::createAnswer(const String& offer, PassRefPtr<MediaHints> mediaHints)
+{
+ return m_private->createAnswer(offer, mediaHints);
+}
+
+bool PeerConnection00Handler::setLocalDescription(int action, PassRefPtr<SessionDescriptionDescriptor> sessionDescription)
+{
+ return m_private->setLocalDescription(action, sessionDescription);
+}
+
+bool PeerConnection00Handler::setRemoteDescription(int action, PassRefPtr<SessionDescriptionDescriptor> sessionDescription)
+{
+ return m_private->setRemoteDescription(action, sessionDescription);
+}
+
+PassRefPtr<SessionDescriptionDescriptor> PeerConnection00Handler::localDescription()
+{
+ return m_private->localDescription();
+}
+
+PassRefPtr<SessionDescriptionDescriptor> PeerConnection00Handler::remoteDescription()
+{
+ return m_private->remoteDescription();
+}
+
+bool PeerConnection00Handler::startIce(PassRefPtr<IceOptions> iceOptions)
+{
+ return m_private->startIce(iceOptions);
+}
+
+bool PeerConnection00Handler::processIceMessage(PassRefPtr<IceCandidateDescriptor> iceCandidate)
+{
+ return m_private->processIceMessage(iceCandidate);
+}
+
+void PeerConnection00Handler::addStream(PassRefPtr<MediaStreamDescriptor> mediaStream)
+{
+ m_private->addStream(mediaStream);
+}
+
+void PeerConnection00Handler::removeStream(PassRefPtr<MediaStreamDescriptor> mediaStream)
+{
+ m_private->removeStream(mediaStream);
+}
+
+void PeerConnection00Handler::stop()
+{
+ m_private->stop();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
diff --git a/Source/WebCore/platform/mediastream/chromium/PeerConnection00HandlerInternal.cpp b/Source/WebCore/platform/mediastream/chromium/PeerConnection00HandlerInternal.cpp
new file mode 100644
index 000000000..5a90bf18e
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/chromium/PeerConnection00HandlerInternal.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "PeerConnection00HandlerInternal.h"
+
+#include "IceCandidateDescriptor.h"
+#include "IceOptions.h"
+#include "MediaHints.h"
+#include "PeerConnection00.h"
+#include "PeerConnection00HandlerClient.h"
+#include "SessionDescriptionDescriptor.h"
+#include <public/Platform.h>
+#include <public/WebICECandidateDescriptor.h>
+#include <public/WebICEOptions.h>
+#include <public/WebMediaHints.h>
+#include <public/WebMediaStreamDescriptor.h>
+#include <public/WebPeerConnection00Handler.h>
+#include <public/WebPeerConnection00HandlerClient.h>
+#include <public/WebSessionDescriptionDescriptor.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+PeerConnection00HandlerInternal::PeerConnection00HandlerInternal(PeerConnection00HandlerClient* client, const String& serverConfiguration, const String& username)
+ : m_client(client)
+{
+ ASSERT(m_client);
+ m_webHandler = adoptPtr(WebKit::Platform::current()->createPeerConnection00Handler(this));
+ // FIXME: When there is some error reporting avaliable in the PeerConnection object report
+ // if we didn't get a WebPeerConnection00Handler instance.
+
+ if (m_webHandler)
+ m_webHandler->initialize(serverConfiguration, username);
+}
+
+PeerConnection00HandlerInternal::~PeerConnection00HandlerInternal()
+{
+}
+
+PassRefPtr<SessionDescriptionDescriptor> PeerConnection00HandlerInternal::createOffer(PassRefPtr<MediaHints> mediaHints)
+{
+ if (!m_webHandler)
+ return 0;
+
+ return m_webHandler->createOffer(mediaHints);
+}
+
+PassRefPtr<SessionDescriptionDescriptor> PeerConnection00HandlerInternal::createAnswer(const String& offer, PassRefPtr<MediaHints> mediaHints)
+{
+ if (!m_webHandler)
+ return 0;
+
+ return m_webHandler->createAnswer(offer, mediaHints);
+}
+
+bool PeerConnection00HandlerInternal::setLocalDescription(int action, PassRefPtr<SessionDescriptionDescriptor> sessionDescription)
+{
+ if (!m_webHandler)
+ return false;
+
+ return m_webHandler->setLocalDescription(static_cast<WebKit::WebPeerConnection00Handler::Action>(action), sessionDescription);
+}
+
+bool PeerConnection00HandlerInternal::setRemoteDescription(int action, PassRefPtr<SessionDescriptionDescriptor> sessionDescription)
+{
+ if (!m_webHandler)
+ return false;
+
+ return m_webHandler->setRemoteDescription(static_cast<WebKit::WebPeerConnection00Handler::Action>(action), sessionDescription);
+}
+
+PassRefPtr<SessionDescriptionDescriptor> PeerConnection00HandlerInternal::localDescription()
+{
+ if (!m_webHandler)
+ return 0;
+
+ return m_webHandler->localDescription();
+}
+
+PassRefPtr<SessionDescriptionDescriptor> PeerConnection00HandlerInternal::remoteDescription()
+{
+ if (!m_webHandler)
+ return 0;
+
+ return m_webHandler->remoteDescription();
+}
+
+bool PeerConnection00HandlerInternal::startIce(PassRefPtr<IceOptions> iceOptions)
+{
+ if (!m_webHandler)
+ return true;
+
+ return m_webHandler->startIce(iceOptions);
+}
+
+bool PeerConnection00HandlerInternal::processIceMessage(PassRefPtr<IceCandidateDescriptor> iceCandidate)
+{
+ if (!m_webHandler)
+ return false;
+
+ return m_webHandler->processIceMessage(iceCandidate);
+}
+
+void PeerConnection00HandlerInternal::addStream(PassRefPtr<MediaStreamDescriptor> mediaStream)
+{
+ if (!m_webHandler)
+ return;
+
+ m_webHandler->addStream(mediaStream);
+}
+
+void PeerConnection00HandlerInternal::removeStream(PassRefPtr<MediaStreamDescriptor> mediaStream)
+{
+ if (!m_webHandler)
+ return;
+
+ m_webHandler->removeStream(mediaStream);
+}
+
+void PeerConnection00HandlerInternal::stop()
+{
+ if (!m_webHandler)
+ return;
+
+ m_webHandler->stop();
+}
+
+void PeerConnection00HandlerInternal::didGenerateICECandidate(const WebKit::WebICECandidateDescriptor& iceCandidate, bool moreToFollow)
+{
+ m_client->didGenerateIceCandidate(iceCandidate, moreToFollow);
+}
+
+void PeerConnection00HandlerInternal::didChangeReadyState(ReadyState state)
+{
+ m_client->didChangeReadyState(state);
+}
+
+void PeerConnection00HandlerInternal::didChangeICEState(ICEState state)
+{
+ m_client->didChangeIceState(state);
+}
+
+void PeerConnection00HandlerInternal::didAddRemoteStream(const WebKit::WebMediaStreamDescriptor& webMediaStreamDescriptor)
+{
+ m_client->didAddRemoteStream(webMediaStreamDescriptor);
+}
+
+void PeerConnection00HandlerInternal::didRemoveRemoteStream(const WebKit::WebMediaStreamDescriptor& webMediaStreamDescriptor)
+{
+ m_client->didRemoveRemoteStream(webMediaStreamDescriptor);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
diff --git a/Source/WebCore/platform/mediastream/chromium/PeerConnection00HandlerInternal.h b/Source/WebCore/platform/mediastream/chromium/PeerConnection00HandlerInternal.h
new file mode 100644
index 000000000..2151edf5d
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/chromium/PeerConnection00HandlerInternal.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PeerConnection00HandlerInternal_h
+#define PeerConnection00HandlerInternal_h
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "MediaStreamDescriptor.h"
+#include <public/WebPeerConnection00HandlerClient.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+class WebICECandidateDescriptor;
+class WebPeerConnection00Handler;
+class WebMediaStreamDescriptor;
+class WebString;
+}
+
+namespace WebCore {
+
+class IceCandidateDescriptor;
+class IceOptions;
+class MediaHints;
+class PeerConnection00HandlerClient;
+class SessionDescriptionDescriptor;
+
+class PeerConnection00HandlerInternal : public WebKit::WebPeerConnection00HandlerClient {
+public:
+ PeerConnection00HandlerInternal(PeerConnection00HandlerClient*, const String& serverConfiguration, const String& username);
+ ~PeerConnection00HandlerInternal();
+
+ PassRefPtr<SessionDescriptionDescriptor> createOffer(PassRefPtr<MediaHints>);
+ PassRefPtr<SessionDescriptionDescriptor> createAnswer(const String& offer, PassRefPtr<MediaHints>);
+ bool setLocalDescription(int action, PassRefPtr<SessionDescriptionDescriptor>);
+ bool setRemoteDescription(int action, PassRefPtr<SessionDescriptionDescriptor>);
+ PassRefPtr<SessionDescriptionDescriptor> localDescription();
+ PassRefPtr<SessionDescriptionDescriptor> remoteDescription();
+ bool startIce(PassRefPtr<IceOptions>);
+ bool processIceMessage(PassRefPtr<IceCandidateDescriptor>);
+ void addStream(PassRefPtr<MediaStreamDescriptor>);
+ void removeStream(PassRefPtr<MediaStreamDescriptor>);
+ void stop();
+
+ // WebKit::WebJSEPPeerConnectionHandlerClient implementation.
+ virtual void didGenerateICECandidate(const WebKit::WebICECandidateDescriptor&, bool moreToFollow);
+ virtual void didChangeReadyState(ReadyState);
+ virtual void didChangeICEState(ICEState);
+ virtual void didAddRemoteStream(const WebKit::WebMediaStreamDescriptor&);
+ virtual void didRemoveRemoteStream(const WebKit::WebMediaStreamDescriptor&);
+
+private:
+ OwnPtr<WebKit::WebPeerConnection00Handler> m_webHandler;
+ PeerConnection00HandlerClient* m_client;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif // PeerConnection00HandlerInternal_h
diff --git a/Source/WebCore/platform/mediastream/gstreamer/PeerConnectionHandler.cpp b/Source/WebCore/platform/mediastream/gstreamer/DeprecatedPeerConnectionHandler.cpp
index 371293412..d6e3d5866 100644
--- a/Source/WebCore/platform/mediastream/gstreamer/PeerConnectionHandler.cpp
+++ b/Source/WebCore/platform/mediastream/gstreamer/DeprecatedPeerConnectionHandler.cpp
@@ -32,47 +32,47 @@
#if ENABLE(MEDIA_STREAM)
-#include "PeerConnectionHandler.h"
+#include "DeprecatedPeerConnectionHandler.h"
-#include "PeerConnectionHandlerClient.h"
+#include "DeprecatedPeerConnectionHandlerClient.h"
namespace WebCore {
-PassOwnPtr<PeerConnectionHandler> PeerConnectionHandler::create(PeerConnectionHandlerClient* client, const String& serverConfiguration, const String& username)
+PassOwnPtr<DeprecatedPeerConnectionHandler> DeprecatedPeerConnectionHandler::create(DeprecatedPeerConnectionHandlerClient* client, const String& serverConfiguration, const String& username)
{
- return adoptPtr(new PeerConnectionHandler(client, serverConfiguration, username));
+ return adoptPtr(new DeprecatedPeerConnectionHandler(client, serverConfiguration, username));
}
// Empty implementations for ports that build with MEDIA_STREAM enabled by default.
-PeerConnectionHandler::PeerConnectionHandler(PeerConnectionHandlerClient*, const String&, const String&)
+DeprecatedPeerConnectionHandler::DeprecatedPeerConnectionHandler(DeprecatedPeerConnectionHandlerClient*, const String&, const String&)
{
}
-PeerConnectionHandler::~PeerConnectionHandler()
+DeprecatedPeerConnectionHandler::~DeprecatedPeerConnectionHandler()
{
}
-void PeerConnectionHandler::produceInitialOffer(const MediaStreamDescriptorVector&)
+void DeprecatedPeerConnectionHandler::produceInitialOffer(const MediaStreamDescriptorVector&)
{
}
-void PeerConnectionHandler::handleInitialOffer(const String&)
+void DeprecatedPeerConnectionHandler::handleInitialOffer(const String&)
{
}
-void PeerConnectionHandler::processSDP(const String&)
+void DeprecatedPeerConnectionHandler::processSDP(const String&)
{
}
-void PeerConnectionHandler::processPendingStreams(const MediaStreamDescriptorVector&, const MediaStreamDescriptorVector&)
+void DeprecatedPeerConnectionHandler::processPendingStreams(const MediaStreamDescriptorVector&, const MediaStreamDescriptorVector&)
{
}
-void PeerConnectionHandler::sendDataStreamMessage(const char*, size_t)
+void DeprecatedPeerConnectionHandler::sendDataStreamMessage(const char*, size_t)
{
}
-void PeerConnectionHandler::stop()
+void DeprecatedPeerConnectionHandler::stop()
{
}
diff --git a/Source/WebCore/platform/mediastream/gstreamer/MediaStreamCenterGStreamer.cpp b/Source/WebCore/platform/mediastream/gstreamer/MediaStreamCenterGStreamer.cpp
new file mode 100644
index 000000000..8836f57c3
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/gstreamer/MediaStreamCenterGStreamer.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2011 Ericsson AB. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Ericsson nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "MediaStreamCenterGStreamer.h"
+
+#include "IceCandidateDescriptor.h"
+#include "MediaStreamDescriptor.h"
+#include "MediaStreamSourcesQueryClient.h"
+#include "SessionDescriptionDescriptor.h"
+#include <wtf/MainThread.h>
+
+namespace WebCore {
+
+MediaStreamCenter& MediaStreamCenter::instance()
+{
+ ASSERT(isMainThread());
+ DEFINE_STATIC_LOCAL(MediaStreamCenterGStreamer, center, ());
+ return center;
+}
+
+MediaStreamCenterGStreamer::MediaStreamCenterGStreamer()
+{
+}
+
+MediaStreamCenterGStreamer::~MediaStreamCenterGStreamer()
+{
+}
+
+void MediaStreamCenterGStreamer::queryMediaStreamSources(PassRefPtr<MediaStreamSourcesQueryClient> client)
+{
+ MediaStreamSourceVector audioSources, videoSources;
+ client->didCompleteQuery(audioSources, videoSources);
+}
+
+void MediaStreamCenterGStreamer::didSetMediaStreamTrackEnabled(MediaStreamDescriptor*, MediaStreamComponent*)
+{
+}
+
+void MediaStreamCenterGStreamer::didStopLocalMediaStream(MediaStreamDescriptor*)
+{
+}
+
+void MediaStreamCenterGStreamer::didConstructMediaStream(MediaStreamDescriptor*)
+{
+}
+
+String MediaStreamCenterGStreamer::constructSDP(IceCandidateDescriptor*)
+{
+ return "";
+}
+
+String MediaStreamCenterGStreamer::constructSDP(SessionDescriptionDescriptor*)
+{
+ return "";
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
diff --git a/Source/WebCore/platform/mediastream/gstreamer/MediaStreamCenterGStreamer.h b/Source/WebCore/platform/mediastream/gstreamer/MediaStreamCenterGStreamer.h
new file mode 100644
index 000000000..c17e55886
--- /dev/null
+++ b/Source/WebCore/platform/mediastream/gstreamer/MediaStreamCenterGStreamer.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2011 Ericsson AB. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Ericsson nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MediaStreamCenterGStreamer_h
+#define MediaStreamCenterGStreamer_h
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "MediaStreamCenter.h"
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class IceCandidateDescriptor;
+class MediaStreamComponent;
+class MediaStreamDescriptor;
+class MediaStreamSourcesQueryClient;
+class SessionDescriptionDescriptor;
+
+class MediaStreamCenterGStreamer : public MediaStreamCenter {
+public:
+ MediaStreamCenterGStreamer();
+ ~MediaStreamCenterGStreamer();
+
+ // MediaStreamCenter
+ virtual void queryMediaStreamSources(PassRefPtr<MediaStreamSourcesQueryClient>) OVERRIDE;
+ virtual void didSetMediaStreamTrackEnabled(MediaStreamDescriptor*, MediaStreamComponent*) OVERRIDE;
+ virtual void didStopLocalMediaStream(MediaStreamDescriptor*) OVERRIDE;
+ virtual void didConstructMediaStream(MediaStreamDescriptor*) OVERRIDE;
+ virtual String constructSDP(IceCandidateDescriptor*) OVERRIDE;
+ virtual String constructSDP(SessionDescriptionDescriptor*) OVERRIDE;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif // MediaStreamCenterGStreamer_h
diff --git a/Source/WebCore/platform/mock/GeolocationClientMock.cpp b/Source/WebCore/platform/mock/GeolocationClientMock.cpp
index d067c8ae0..276b4a343 100644
--- a/Source/WebCore/platform/mock/GeolocationClientMock.cpp
+++ b/Source/WebCore/platform/mock/GeolocationClientMock.cpp
@@ -31,7 +31,7 @@
#include "config.h"
#include "GeolocationClientMock.h"
-#if ENABLE(CLIENT_BASED_GEOLOCATION)
+#if ENABLE(GEOLOCATION)
#include "GeolocationController.h"
#include "GeolocationError.h"
@@ -179,4 +179,4 @@ void GeolocationClientMock::controllerTimerFired(Timer<GeolocationClientMock>* t
} // WebCore
-#endif // ENABLE(CLIENT_BASED_GEOLOCATION)
+#endif // ENABLE(GEOLOCATION)
diff --git a/Source/WebCore/platform/mock/GeolocationClientMock.h b/Source/WebCore/platform/mock/GeolocationClientMock.h
index b40016616..4c238ce57 100644
--- a/Source/WebCore/platform/mock/GeolocationClientMock.h
+++ b/Source/WebCore/platform/mock/GeolocationClientMock.h
@@ -31,8 +31,6 @@
#ifndef GeolocationClientMock_h
#define GeolocationClientMock_h
-#if ENABLE(CLIENT_BASED_GEOLOCATION)
-
#include "GeolocationClient.h"
#include "PlatformString.h"
#include "Timer.h"
@@ -95,6 +93,4 @@ private:
}
-#endif // ENABLE(CLIENT_BASED_GEOLOCATION)
-
#endif
diff --git a/Source/WebCore/platform/mock/GeolocationServiceMock.cpp b/Source/WebCore/platform/mock/GeolocationServiceMock.cpp
deleted file mode 100644
index 6f534ddbf..000000000
--- a/Source/WebCore/platform/mock/GeolocationServiceMock.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2009 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "GeolocationServiceMock.h"
-
-#if ENABLE(GEOLOCATION)
-
-#include "Logging.h"
-#include "Geolocation.h"
-#include "Geoposition.h"
-#include "PositionError.h"
-#include "PositionOptions.h"
-
-namespace WebCore {
-
-GeolocationServiceMock::GeolocationServiceSet* GeolocationServiceMock::s_instances = 0;
-RefPtr<Geoposition>* GeolocationServiceMock::s_lastPosition;
-RefPtr<PositionError>* GeolocationServiceMock::s_lastError;
-
-PassOwnPtr<GeolocationService> GeolocationServiceMock::create(GeolocationServiceClient* client)
-{
- initStatics();
- return adoptPtr(new GeolocationServiceMock(client));
-}
-
-GeolocationServiceMock::GeolocationServiceMock(GeolocationServiceClient* client)
- : GeolocationService(client)
- , m_timer(this, &GeolocationServiceMock::timerFired)
- , m_isActive(false)
-{
- s_instances->add(this);
-}
-
-GeolocationServiceMock::~GeolocationServiceMock()
-{
- GeolocationServiceSet::iterator iter = s_instances->find(this);
- ASSERT(iter != s_instances->end());
- s_instances->remove(iter);
- cleanUpStatics();
-}
-
-void GeolocationServiceMock::setPosition(PassRefPtr<Geoposition> position)
-{
- initStatics();
- GeolocationService::useMock();
- *s_lastPosition = position;
- *s_lastError = 0;
- makeGeolocationCallbackFromAllInstances();
-}
-
-void GeolocationServiceMock::setError(PassRefPtr<PositionError> error)
-{
- initStatics();
- GeolocationService::useMock();
- *s_lastError = error;
- *s_lastPosition = 0;
- makeGeolocationCallbackFromAllInstances();
-}
-
-bool GeolocationServiceMock::startUpdating(PositionOptions*)
-{
- m_isActive = true;
- m_timer.startOneShot(0);
- return true;
-}
-
-void GeolocationServiceMock::stopUpdating()
-{
- m_isActive = false;
-}
-
-void GeolocationServiceMock::timerFired(Timer<GeolocationServiceMock>* timer)
-{
- ASSERT_UNUSED(timer, timer == &m_timer);
- makeGeolocationCallback();
-}
-
-void GeolocationServiceMock::makeGeolocationCallbackFromAllInstances()
-{
- GeolocationServiceSet::const_iterator end = s_instances->end();
- for (GeolocationServiceSet::const_iterator iter = s_instances->begin(); iter != end; ++iter)
- (*iter)->makeGeolocationCallback();
-}
-
-void GeolocationServiceMock::makeGeolocationCallback()
-{
- if (!m_isActive)
- return;
-
- if (*s_lastPosition)
- positionChanged();
- else if (*s_lastError)
- errorOccurred();
-}
-
-void GeolocationServiceMock::initStatics()
-{
- if (s_instances == 0) {
- s_instances = new GeolocationServiceSet;
- s_lastPosition = new RefPtr<Geoposition>;
- s_lastError = new RefPtr<PositionError>;
- }
-}
-
-void GeolocationServiceMock::cleanUpStatics()
-{
- if (s_instances->size() == 0) {
- delete s_instances;
- s_instances = 0;
- delete s_lastPosition;
- delete s_lastError;
- }
-}
-
-} // namespace WebCore
-
-#endif
diff --git a/Source/WebCore/platform/mock/GeolocationServiceMock.h b/Source/WebCore/platform/mock/GeolocationServiceMock.h
deleted file mode 100644
index c3978febb..000000000
--- a/Source/WebCore/platform/mock/GeolocationServiceMock.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2009 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef GeolocationServiceMock_h
-#define GeolocationServiceMock_h
-
-#include "GeolocationService.h"
-#include "Timer.h"
-#include <wtf/HashSet.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefPtr.h>
-
-namespace WebCore {
-
-// This class provides a mock implementation of a GeolocationService for testing
-// purposes. It allows the position or error that will be reported by this class
-// to be set manually using the setPosition and setError methods. Objects of
-// this class call back to their respective GeolocationServiceClient with the
-// position or error every time either of these is updated.
-class GeolocationServiceMock : public GeolocationService {
- public:
- static PassOwnPtr<GeolocationService> create(GeolocationServiceClient*);
-
- GeolocationServiceMock(GeolocationServiceClient*);
- virtual ~GeolocationServiceMock();
-
- virtual bool startUpdating(PositionOptions*);
- virtual void stopUpdating();
-
- static void setPosition(PassRefPtr<Geoposition> position);
- static void setError(PassRefPtr<PositionError> position);
-
- virtual Geoposition* lastPosition() const { return s_lastPosition->get(); }
- virtual PositionError* lastError() const { return s_lastError->get(); }
-
- private:
- static void makeGeolocationCallbackFromAllInstances();
- void makeGeolocationCallback();
-
- void timerFired(Timer<GeolocationServiceMock>*);
-
- static void initStatics();
- static void cleanUpStatics();
-
- typedef HashSet<GeolocationServiceMock*> GeolocationServiceSet;
- static GeolocationServiceSet* s_instances;
-
- static RefPtr<Geoposition>* s_lastPosition;
- static RefPtr<PositionError>* s_lastError;
-
- Timer<GeolocationServiceMock> m_timer;
-
- bool m_isActive;
-};
-
-} // namespace WebCore
-
-#endif // GeolocationServiceMock_h
diff --git a/Source/WebCore/platform/network/DNS.h b/Source/WebCore/platform/network/DNS.h
index 21d9c8026..c6b748db8 100644
--- a/Source/WebCore/platform/network/DNS.h
+++ b/Source/WebCore/platform/network/DNS.h
@@ -30,9 +30,7 @@
namespace WebCore {
-#if !USE(SOUP)
- void prefetchDNS(const String& hostname);
-#endif
+void prefetchDNS(const String& hostname);
}
#endif
diff --git a/Source/WebCore/platform/network/DNSResolveQueue.cpp b/Source/WebCore/platform/network/DNSResolveQueue.cpp
new file mode 100644
index 000000000..b9d011379
--- /dev/null
+++ b/Source/WebCore/platform/network/DNSResolveQueue.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DNSResolveQueue.h"
+
+namespace WebCore {
+
+// When resolve queue is empty, we fire async resolution requests immediately (which is important if the prefetch is triggered by hovering).
+// But during page parsing, we should coalesce identical requests to avoid stressing out the DNS resolver.
+static const int gNamesToResolveImmediately = 4;
+
+// Coalesce prefetch requests for this long before sending them out.
+static const double gCoalesceDelayInSeconds = 1.0;
+
+// Sending many DNS requests at once can overwhelm some gateways. See <rdar://8105550> for specific CFNET issues with CFHost throttling.
+static const int gMaxSimultaneousRequests = 8;
+
+// For a page has links to many outside sites, it is likely that the system DNS resolver won't be able to cache them all anyway, and we don't want
+// to negatively affect other applications' performance by pushing their cached entries out.
+// If we end up with lots of names to prefetch, some will be dropped.
+static const int gMaxRequestsToQueue = 64;
+
+// If there were queued names that couldn't be sent simultaneously, check the state of resolvers after this delay.
+static const double gRetryResolvingInSeconds = 0.1;
+
+void DNSResolveQueue::add(const String& hostname)
+{
+ // If there are no names queued, and few enough are in flight, resolve immediately (the mouse may be over a link).
+ if (!m_names.size()) {
+ if (platformProxyIsEnabledInSystemPreferences())
+ return;
+
+ if (atomicIncrement(&m_requestsInFlight) <= gNamesToResolveImmediately) {
+ platformResolve(hostname);
+ return;
+ }
+ atomicDecrement(&m_requestsInFlight);
+ }
+
+ // It's better to not prefetch some names than to clog the queue.
+ // Dropping the newest names, because on a single page, these are likely to be below oldest ones.
+ if (m_names.size() < gMaxRequestsToQueue) {
+ m_names.add(hostname);
+ if (!isActive())
+ startOneShot(gCoalesceDelayInSeconds);
+ }
+}
+
+void DNSResolveQueue::fired()
+{
+ if (platformProxyIsEnabledInSystemPreferences()) {
+ m_names.clear();
+ return;
+ }
+
+ int requestsAllowed = gMaxSimultaneousRequests - m_requestsInFlight;
+
+ for (; !m_names.isEmpty() && requestsAllowed > 0; --requestsAllowed) {
+ atomicIncrement(&m_requestsInFlight);
+ HashSet<String>::iterator currentName = m_names.begin();
+ platformResolve(*currentName);
+ m_names.remove(currentName);
+ }
+
+ if (!m_names.isEmpty())
+ startOneShot(gRetryResolvingInSeconds);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/network/DNSResolveQueue.h b/Source/WebCore/platform/network/DNSResolveQueue.h
new file mode 100644
index 000000000..e4b96f810
--- /dev/null
+++ b/Source/WebCore/platform/network/DNSResolveQueue.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 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 DNSResolveQueue_h
+#define DNSResolveQueue_h
+
+#include "Timer.h"
+#include <wtf/Forward.h>
+#include <wtf/HashSet.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+class DNSResolveQueue : public TimerBase {
+
+public:
+ static DNSResolveQueue& shared()
+ {
+ DEFINE_STATIC_LOCAL(DNSResolveQueue, queue, ());
+ return queue;
+ }
+
+ void add(const String& hostname);
+ void decrementRequestCount()
+ {
+ atomicDecrement(&m_requestsInFlight);
+ }
+
+private:
+ bool platformProxyIsEnabledInSystemPreferences();
+ void platformResolve(const String&);
+
+ void fired();
+
+ HashSet<String> m_names;
+ int m_requestsInFlight;
+};
+
+}
+
+#endif // DNSResolveQueue_h
diff --git a/Source/WebCore/platform/network/FormData.cpp b/Source/WebCore/platform/network/FormData.cpp
index 9665bbd1c..f58174621 100644
--- a/Source/WebCore/platform/network/FormData.cpp
+++ b/Source/WebCore/platform/network/FormData.cpp
@@ -43,6 +43,7 @@ inline FormData::FormData()
: m_identifier(0)
, m_hasGeneratedFiles(false)
, m_alwaysStream(false)
+ , m_containsPasswordData(false)
{
}
@@ -52,6 +53,7 @@ inline FormData::FormData(const FormData& data)
, m_identifier(data.m_identifier)
, m_hasGeneratedFiles(false)
, m_alwaysStream(false)
+ , m_containsPasswordData(data.m_containsPasswordData)
{
// We shouldn't be copying FormData that hasn't already removed its generated files
// but just in case, make sure the new FormData is ready to generate its own files.
diff --git a/Source/WebCore/platform/network/FormData.h b/Source/WebCore/platform/network/FormData.h
index 213ddde1c..14981366b 100644
--- a/Source/WebCore/platform/network/FormData.h
+++ b/Source/WebCore/platform/network/FormData.h
@@ -135,6 +135,9 @@ public:
void setIdentifier(int64_t identifier) { m_identifier = identifier; }
int64_t identifier() const { return m_identifier; }
+ bool containsPasswordData() const { return m_containsPasswordData; }
+ void setContainsPasswordData(bool containsPasswordData) { m_containsPasswordData = containsPasswordData; }
+
static EncodingType parseEncodingType(const String& type)
{
if (equalIgnoringCase(type, "text/plain"))
@@ -156,6 +159,7 @@ private:
bool m_hasGeneratedFiles;
bool m_alwaysStream;
Vector<char> m_boundary;
+ bool m_containsPasswordData;
};
inline bool operator==(const FormData& a, const FormData& b)
diff --git a/Source/WebCore/platform/network/HTTPHeaderMap.cpp b/Source/WebCore/platform/network/HTTPHeaderMap.cpp
index 44c5681fb..50091e19d 100644
--- a/Source/WebCore/platform/network/HTTPHeaderMap.cpp
+++ b/Source/WebCore/platform/network/HTTPHeaderMap.cpp
@@ -72,7 +72,7 @@ String HTTPHeaderMap::get(const AtomicString& name) const
return HashMap<AtomicString, String, CaseFoldingHash>::get(name);
}
-pair<HTTPHeaderMap::iterator, bool> HTTPHeaderMap::add(const AtomicString& name, const String& value)
+HTTPHeaderMap::AddResult HTTPHeaderMap::add(const AtomicString& name, const String& value)
{
return HashMap<AtomicString, String, CaseFoldingHash>::add(name, value);
}
@@ -108,7 +108,7 @@ bool HTTPHeaderMap::contains(const char* name) const
return find<const char*, CaseFoldingCStringTranslator>(name) != end();
}
-pair<HTTPHeaderMap::iterator, bool> HTTPHeaderMap::add(const char* name, const String& value)
+HTTPHeaderMap::AddResult HTTPHeaderMap::add(const char* name, const String& value)
{
return HashMap<AtomicString, String, CaseFoldingHash>::add<const char*, CaseFoldingCStringTranslator>(name, value);
}
diff --git a/Source/WebCore/platform/network/HTTPHeaderMap.h b/Source/WebCore/platform/network/HTTPHeaderMap.h
index 02071e361..12bde0689 100644
--- a/Source/WebCore/platform/network/HTTPHeaderMap.h
+++ b/Source/WebCore/platform/network/HTTPHeaderMap.h
@@ -51,12 +51,12 @@ namespace WebCore {
String get(const AtomicString& name) const;
- pair<iterator, bool> add(const AtomicString& name, const String& value);
+ AddResult add(const AtomicString& name, const String& value);
// Alternate accessors that are faster than converting the char* to AtomicString first.
bool contains(const char*) const;
String get(const char*) const;
- pair<iterator, bool> add(const char* name, const String& value);
+ AddResult add(const char* name, const String& value);
};
diff --git a/Source/WebCore/platform/network/HTTPParsers.cpp b/Source/WebCore/platform/network/HTTPParsers.cpp
index 8cbd4ff14..9702132cc 100644
--- a/Source/WebCore/platform/network/HTTPParsers.cpp
+++ b/Source/WebCore/platform/network/HTTPParsers.cpp
@@ -3,6 +3,7 @@
* Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/
* Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2011 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,12 +32,12 @@
#include "config.h"
#include "HTTPParsers.h"
-#include "ResourceResponseBase.h"
#include "PlatformString.h"
+#include <wtf/DateMath.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>
-#include <wtf/DateMath.h>
+#include <wtf/unicode/CharacterNames.h>
using namespace WTF;
@@ -90,6 +91,15 @@ bool isRFC2616Token(const String& characters)
return true;
}
+static const size_t maxInputSampleSize = 128;
+static String trimInputSample(const char* p, size_t length)
+{
+ String s = String(p, std::min<size_t>(length, maxInputSampleSize));
+ if (length > maxInputSampleSize)
+ s.append(horizontalEllipsis);
+ return s;
+}
+
ContentDispositionType contentDispositionType(const String& contentDisposition)
{
if (contentDisposition.isEmpty())
@@ -395,4 +405,145 @@ bool parseRange(const String& range, long long& rangeOffset, long long& rangeEnd
return true;
}
+// HTTP/1.1 - RFC 2616
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1
+// Request-Line = Method SP Request-URI SP HTTP-Version CRLF
+size_t parseHTTPRequestLine(const char* data, size_t length, String& failureReason, String& method, String& url, HTTPVersion& httpVersion)
+{
+ method = String();
+ url = String();
+ httpVersion = Unknown;
+
+ const char* space1 = 0;
+ const char* space2 = 0;
+ const char* p;
+ size_t consumedLength;
+
+ for (p = data, consumedLength = 0; consumedLength < length; p++, consumedLength++) {
+ if (*p == ' ') {
+ if (!space1)
+ space1 = p;
+ else if (!space2)
+ space2 = p;
+ } else if (*p == '\n')
+ break;
+ }
+
+ // Haven't finished header line.
+ if (consumedLength == length) {
+ failureReason = "Incomplete Request Line";
+ return 0;
+ }
+
+ // RequestLine does not contain 3 parts.
+ if (!space1 || !space2) {
+ failureReason = "Request Line does not appear to contain: <Method> <Url> <HTTPVersion>.";
+ return 0;
+ }
+
+ // The line must end with "\r\n".
+ const char* end = p + 1;
+ if (*(end - 2) != '\r') {
+ failureReason = "Request line does not end with CRLF";
+ return 0;
+ }
+
+ // Request Method.
+ method = String(data, space1 - data); // For length subtract 1 for space, but add 1 for data being the first character.
+
+ // Request URI.
+ url = String(space1 + 1, space2 - space1 - 1); // For length subtract 1 for space.
+
+ // HTTP Version.
+ String httpVersionString(space2 + 1, end - space2 - 3); // For length subtract 1 for space, and 2 for "\r\n".
+ if (httpVersionString.length() != 8 || !httpVersionString.startsWith("HTTP/1."))
+ httpVersion = Unknown;
+ else if (httpVersionString[7] == '0')
+ httpVersion = HTTP_1_0;
+ else if (httpVersionString[7] == '1')
+ httpVersion = HTTP_1_1;
+ else
+ httpVersion = Unknown;
+
+ return end - data;
+}
+
+size_t parseHTTPHeader(const char* start, size_t length, String& failureReason, AtomicString& nameStr, String& valueStr)
+{
+ const char* p = start;
+ const char* end = start + length;
+
+ Vector<char> name;
+ Vector<char> value;
+ nameStr = AtomicString();
+ valueStr = String();
+
+ for (; p < end; p++) {
+ switch (*p) {
+ case '\r':
+ if (name.isEmpty()) {
+ if (p + 1 < end && *(p + 1) == '\n')
+ return (p + 2) - start;
+ failureReason = "CR doesn't follow LF at " + trimInputSample(p, end - p);
+ return 0;
+ }
+ failureReason = "Unexpected CR in name at " + trimInputSample(name.data(), name.size());
+ return 0;
+ case '\n':
+ failureReason = "Unexpected LF in name at " + trimInputSample(name.data(), name.size());
+ return 0;
+ case ':':
+ break;
+ default:
+ name.append(*p);
+ continue;
+ }
+ if (*p == ':') {
+ ++p;
+ break;
+ }
+ }
+
+ for (; p < end && *p == 0x20; p++) { }
+
+ for (; p < end; p++) {
+ switch (*p) {
+ case '\r':
+ break;
+ case '\n':
+ failureReason = "Unexpected LF in value at " + trimInputSample(value.data(), value.size());
+ return 0;
+ default:
+ value.append(*p);
+ }
+ if (*p == '\r') {
+ ++p;
+ break;
+ }
+ }
+ if (p >= end || *p != '\n') {
+ failureReason = "CR doesn't follow LF after value at " + trimInputSample(p, end - p);
+ return 0;
+ }
+ nameStr = AtomicString::fromUTF8(name.data(), name.size());
+ valueStr = String::fromUTF8(value.data(), value.size());
+ if (nameStr.isNull()) {
+ failureReason = "Invalid UTF-8 sequence in header name";
+ return 0;
+ }
+ if (valueStr.isNull()) {
+ failureReason = "Invalid UTF-8 sequence in header value";
+ return 0;
+ }
+ return p - start;
+}
+
+size_t parseHTTPRequestBody(const char* data, size_t length, Vector<unsigned char>& body)
+{
+ body.clear();
+ body.append(data, length);
+
+ return length;
+}
+
}
diff --git a/Source/WebCore/platform/network/HTTPParsers.h b/Source/WebCore/platform/network/HTTPParsers.h
index 3c808af62..02ec13ebc 100644
--- a/Source/WebCore/platform/network/HTTPParsers.h
+++ b/Source/WebCore/platform/network/HTTPParsers.h
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
* Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2011 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,9 +32,11 @@
#define HTTPParsers_h
#include <wtf/Forward.h>
+#include <wtf/Vector.h>
namespace WebCore {
+class HTTPHeaderMap;
class ResourceResponseBase;
enum XSSProtectionDisposition {
@@ -63,6 +66,12 @@ String extractReasonPhraseFromHTTPStatusLine(const String&);
// -1 could be set to one of the return parameters to indicate the value is not specified.
bool parseRange(const String&, long long& rangeOffset, long long& rangeEnd, long long& rangeSuffixLength);
+// Parsing Complete HTTP Messages.
+enum HTTPVersion { Unknown, HTTP_1_0, HTTP_1_1 };
+size_t parseHTTPRequestLine(const char* data, size_t length, String& failureReason, String& method, String& url, HTTPVersion&);
+size_t parseHTTPHeader(const char* data, size_t length, String& failureReason, AtomicString& nameStr, String& valueStr);
+size_t parseHTTPRequestBody(const char* data, size_t length, Vector<unsigned char>& body);
+
}
#endif
diff --git a/Source/WebCore/platform/network/HTTPRequest.cpp b/Source/WebCore/platform/network/HTTPRequest.cpp
new file mode 100644
index 000000000..f4f9d4f37
--- /dev/null
+++ b/Source/WebCore/platform/network/HTTPRequest.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "HTTPRequest.h"
+
+#include <wtf/text/CString.h>
+
+namespace WebCore {
+
+PassRefPtr<HTTPRequest> HTTPRequest::parseHTTPRequestFromBuffer(const char* data, size_t length, String& failureReason)
+{
+ if (!length) {
+ failureReason = "No data to parse.";
+ return 0;
+ }
+
+ // Request we will be building.
+ RefPtr<HTTPRequest> request = HTTPRequest::create();
+
+ // Advance a pointer through the data as needed.
+ const char* pos = data;
+ size_t remainingLength = length;
+
+ // 1. Parse Method + URL.
+ size_t requestLineLength = request->parseRequestLine(pos, remainingLength, failureReason);
+ if (!requestLineLength)
+ return 0;
+ pos += requestLineLength;
+ remainingLength -= requestLineLength;
+
+ // 2. Parse HTTP Headers.
+ size_t headersLength = request->parseHeaders(pos, remainingLength, failureReason);
+ if (!headersLength)
+ return 0;
+ pos += headersLength;
+ remainingLength -= headersLength;
+
+ // 3. Parse HTTP Data.
+ size_t dataLength = request->parseRequestBody(pos, remainingLength);
+ pos += dataLength;
+ remainingLength -= dataLength;
+
+ // We should have processed the entire input.
+ ASSERT(!remainingLength);
+ return request.release();
+}
+
+size_t HTTPRequest::parseRequestLine(const char* data, size_t length, String& failureReason)
+{
+ String url;
+ size_t result = parseHTTPRequestLine(data, length, failureReason, m_requestMethod, url, m_httpVersion);
+ m_url = KURL(KURL(), url);
+ return result;
+}
+
+size_t HTTPRequest::parseHeaders(const char* data, size_t length, String& failureReason)
+{
+ const char* p = data;
+ const char* end = data + length;
+ AtomicString name;
+ String value;
+ for (; p < data + length; p++) {
+ size_t consumedLength = parseHTTPHeader(p, end - p, failureReason, name, value);
+ if (!consumedLength)
+ return 0;
+ p += consumedLength;
+ if (name.isEmpty())
+ break;
+ m_headerFields.add(name, value);
+ }
+ return p - data;
+}
+
+size_t HTTPRequest::parseRequestBody(const char* data, size_t length)
+{
+ return parseHTTPRequestBody(data, length, m_body);
+}
+
+HTTPRequest::HTTPRequest()
+ : m_httpVersion(Unknown)
+{
+}
+
+HTTPRequest::HTTPRequest(const String& requestMethod, const KURL& url, HTTPVersion version)
+ : m_url(url)
+ , m_httpVersion(version)
+ , m_requestMethod(requestMethod)
+{
+}
+
+HTTPRequest::~HTTPRequest()
+{
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/network/HTTPRequest.h b/Source/WebCore/platform/network/HTTPRequest.h
new file mode 100644
index 000000000..33522e33e
--- /dev/null
+++ b/Source/WebCore/platform/network/HTTPRequest.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2011 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef HTTPRequest_h
+#define HTTPRequest_h
+
+#include "HTTPHeaderMap.h"
+#include "HTTPParsers.h"
+#include "KURL.h"
+#include "PlatformString.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class HTTPRequest : public RefCounted<HTTPRequest> {
+public:
+ static PassRefPtr<HTTPRequest> create() { return adoptRef(new HTTPRequest()); }
+ static PassRefPtr<HTTPRequest> create(const String& requestMethod, const KURL& url, HTTPVersion version) { return adoptRef(new HTTPRequest(requestMethod, url, version)); }
+ static PassRefPtr<HTTPRequest> parseHTTPRequestFromBuffer(const char* data, size_t length, String& failureReason);
+ virtual ~HTTPRequest();
+
+ String requestMethod() const { return m_requestMethod; }
+ void setRequestMethod(const String& method) { m_requestMethod = method; }
+
+ KURL url() const { return m_url; }
+ void setURL(const KURL& url) { m_url = url; }
+
+ const Vector<unsigned char>& body() const { return m_body; }
+
+ const HTTPHeaderMap& headerFields() const { return m_headerFields; }
+ void addHeaderField(const AtomicString& name, const String& value) { m_headerFields.add(name, value); }
+ void addHeaderField(const char* name, const String& value) { m_headerFields.add(name, value); }
+
+protected:
+ HTTPRequest();
+ HTTPRequest(const String& requestMethod, const KURL&, HTTPVersion);
+
+ // Parsing helpers.
+ size_t parseRequestLine(const char* data, size_t length, String& failureReason);
+ size_t parseHeaders(const char* data, size_t length, String& failureReason);
+ size_t parseRequestBody(const char* data, size_t length);
+
+ KURL m_url;
+ HTTPVersion m_httpVersion;
+ String m_requestMethod;
+ HTTPHeaderMap m_headerFields;
+ Vector<unsigned char> m_body;
+};
+
+} // namespace WebCore
+
+#endif // HTTPRequest_h
diff --git a/Source/WebCore/platform/network/MIMESniffing.cpp b/Source/WebCore/platform/network/MIMESniffing.cpp
index f9868c1df..5efd17f13 100644
--- a/Source/WebCore/platform/network/MIMESniffing.cpp
+++ b/Source/WebCore/platform/network/MIMESniffing.cpp
@@ -22,6 +22,9 @@
#include <cstring>
#include <stdint.h>
+#include <wtf/StdLibExtras.h>
+
+using namespace std;
// MIME type sniffing implementation based on http://tools.ietf.org/html/draft-abarth-mime-sniff-06
@@ -223,7 +226,7 @@ const size_t imageTypesSize = sizeof(imageTypes) / sizeof(imageTypes[0]);
static inline size_t dataSizeNeededForImageSniffing()
{
size_t result = 0;
- for (int i = 0; i < imageTypesSize; ++i) {
+ for (size_t i = 0; i < imageTypesSize; ++i) {
if (imageTypes[i].size > result)
result = imageTypes[i].size;
}
@@ -235,9 +238,9 @@ static inline bool maskedCompare(const MagicNumbers& info, const char* data, siz
if (dataSize < info.size)
return false;
- const uint32_t* pattern32 = reinterpret_cast<const uint32_t*>(info.pattern);
- const uint32_t* mask32 = reinterpret_cast<const uint32_t*>(info.mask);
- const uint32_t* data32 = reinterpret_cast<const uint32_t*>(data);
+ const uint32_t* pattern32 = reinterpret_cast_ptr<const uint32_t*>(info.pattern);
+ const uint32_t* mask32 = reinterpret_cast_ptr<const uint32_t*>(info.mask);
+ const uint32_t* data32 = reinterpret_cast_ptr<const uint32_t*>(data);
size_t count = info.size >> 2;
diff --git a/Source/WebCore/platform/network/ResourceHandle.cpp b/Source/WebCore/platform/network/ResourceHandle.cpp
index 6f2be27b0..7ddc47e4e 100644
--- a/Source/WebCore/platform/network/ResourceHandle.cpp
+++ b/Source/WebCore/platform/network/ResourceHandle.cpp
@@ -28,7 +28,6 @@
#include "ResourceHandleInternal.h"
#include "BlobRegistry.h"
-#include "DNS.h"
#include "Logging.h"
#include "ResourceHandleClient.h"
#include "Timer.h"
@@ -185,13 +184,6 @@ void ResourceHandle::setDefersLoading(bool defers)
platformSetDefersLoading(defers);
}
-#if !USE(SOUP)
-void ResourceHandle::prepareForURL(const KURL& url)
-{
- return prefetchDNS(url.host());
-}
-#endif
-
void ResourceHandle::cacheMetadata(const ResourceResponse&, const Vector<char>&)
{
// Optionally implemented by platform.
diff --git a/Source/WebCore/platform/network/ResourceHandle.h b/Source/WebCore/platform/network/ResourceHandle.h
index 8626e09e8..ddca0d22f 100644
--- a/Source/WebCore/platform/network/ResourceHandle.h
+++ b/Source/WebCore/platform/network/ResourceHandle.h
@@ -104,12 +104,8 @@ public:
static PassRefPtr<ResourceHandle> create(NetworkingContext*, const ResourceRequest&, ResourceHandleClient*, bool defersLoading, bool shouldContentSniff);
static void loadResourceSynchronously(NetworkingContext*, const ResourceRequest&, StoredCredentials, ResourceError&, ResourceResponse&, Vector<char>& data);
- static void prepareForURL(const KURL&);
static bool willLoadFromCache(ResourceRequest&, Frame*);
static void cacheMetadata(const ResourceResponse&, const Vector<char>&);
-#if PLATFORM(MAC)
- static bool didSendBodyDataDelegateExists();
-#endif
virtual ~ResourceHandle();
diff --git a/Source/WebCore/platform/network/ResourceHandleInternal.h b/Source/WebCore/platform/network/ResourceHandleInternal.h
index bc79ed12b..e4a4c3829 100644
--- a/Source/WebCore/platform/network/ResourceHandleInternal.h
+++ b/Source/WebCore/platform/network/ResourceHandleInternal.h
@@ -46,7 +46,7 @@
#endif
#if USE(SOUP)
-#include <GRefPtr.h>
+#include <wtf/gobject/GRefPtr.h>
#define LIBSOUP_USE_UNSTABLE_REQUEST_API
#include <libsoup/soup-request.h>
#include <libsoup/soup.h>
diff --git a/Source/WebCore/platform/network/ResourceRequestBase.cpp b/Source/WebCore/platform/network/ResourceRequestBase.cpp
index 23ece24dc..350979292 100644
--- a/Source/WebCore/platform/network/ResourceRequestBase.cpp
+++ b/Source/WebCore/platform/network/ResourceRequestBase.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
- * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009, 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -251,6 +251,16 @@ void ResourceRequestBase::clearHTTPAuthorization()
m_platformRequestUpdated = false;
}
+void ResourceRequestBase::clearHTTPContentType()
+{
+ updateResourceRequest();
+
+ m_httpHeaderFields.remove("Content-Type");
+
+ if (url().protocolIsInHTTPFamily())
+ m_platformRequestUpdated = false;
+}
+
void ResourceRequestBase::clearHTTPReferrer()
{
updateResourceRequest();
@@ -271,6 +281,26 @@ void ResourceRequestBase::clearHTTPOrigin()
m_platformRequestUpdated = false;
}
+void ResourceRequestBase::clearHTTPUserAgent()
+{
+ updateResourceRequest();
+
+ m_httpHeaderFields.remove("User-Agent");
+
+ if (url().protocolIsInHTTPFamily())
+ m_platformRequestUpdated = false;
+}
+
+void ResourceRequestBase::clearHTTPAccept()
+{
+ updateResourceRequest();
+
+ m_httpHeaderFields.remove("Accept");
+
+ if (url().protocolIsInHTTPFamily())
+ m_platformRequestUpdated = false;
+}
+
void ResourceRequestBase::setResponseContentDispositionEncodingFallbackArray(const String& encoding1, const String& encoding2, const String& encoding3)
{
updateResourceRequest();
@@ -341,9 +371,9 @@ void ResourceRequestBase::setPriority(ResourceLoadPriority priority)
void ResourceRequestBase::addHTTPHeaderField(const AtomicString& name, const String& value)
{
updateResourceRequest();
- pair<HTTPHeaderMap::iterator, bool> result = m_httpHeaderFields.add(name, value);
- if (!result.second)
- result.first->second += "," + value;
+ HTTPHeaderMap::AddResult result = m_httpHeaderFields.add(name, value);
+ if (!result.isNewEntry)
+ result.iterator->second += "," + value;
if (url().protocolIsInHTTPFamily())
m_platformRequestUpdated = false;
diff --git a/Source/WebCore/platform/network/ResourceRequestBase.h b/Source/WebCore/platform/network/ResourceRequestBase.h
index 0b154d60f..86dd62e8e 100644
--- a/Source/WebCore/platform/network/ResourceRequestBase.h
+++ b/Source/WebCore/platform/network/ResourceRequestBase.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
- * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009, 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -88,7 +88,8 @@ namespace WebCore {
String httpContentType() const { return httpHeaderField("Content-Type"); }
void setHTTPContentType(const String& httpContentType) { setHTTPHeaderField("Content-Type", httpContentType); }
-
+ void clearHTTPContentType();
+
String httpReferrer() const { return httpHeaderField("Referer"); }
void setHTTPReferrer(const String& httpReferrer) { setHTTPHeaderField("Referer", httpReferrer); }
void clearHTTPReferrer();
@@ -99,9 +100,11 @@ namespace WebCore {
String httpUserAgent() const { return httpHeaderField("User-Agent"); }
void setHTTPUserAgent(const String& httpUserAgent) { setHTTPHeaderField("User-Agent", httpUserAgent); }
+ void clearHTTPUserAgent();
String httpAccept() const { return httpHeaderField("Accept"); }
void setHTTPAccept(const String& httpAccept) { setHTTPHeaderField("Accept", httpAccept); }
+ void clearHTTPAccept();
void setResponseContentDispositionEncodingFallbackArray(const String& encoding1, const String& encoding2 = String(), const String& encoding3 = String());
diff --git a/Source/WebCore/platform/network/ResourceResponseBase.cpp b/Source/WebCore/platform/network/ResourceResponseBase.cpp
index 67d8203cb..111c6dc01 100644
--- a/Source/WebCore/platform/network/ResourceResponseBase.cpp
+++ b/Source/WebCore/platform/network/ResourceResponseBase.cpp
@@ -339,6 +339,10 @@ void ResourceResponseBase::parseCacheControlDirectives() const
else if (equalIgnoringCase(directives[i].first, mustRevalidateDirective))
m_cacheControlContainsMustRevalidate = true;
else if (equalIgnoringCase(directives[i].first, maxAgeDirective)) {
+ if (!isnan(m_cacheControlMaxAge)) {
+ // First max-age directive wins if there are multiple ones.
+ continue;
+ }
bool ok;
double maxAge = directives[i].second.toDouble(&ok);
if (ok)
@@ -626,7 +630,7 @@ static bool isControlCharacter(UChar c)
static inline String trimToNextSeparator(const String& str)
{
- return str.substring(0, str.find(isCacheHeaderSeparator, 0));
+ return str.substring(0, str.find(isCacheHeaderSeparator));
}
static void parseCacheHeader(const String& header, Vector<pair<String, String> >& result)
@@ -662,7 +666,7 @@ static void parseCacheHeader(const String& header, Vector<pair<String, String> >
}
} else {
// The value is a token until the next comma
- size_t nextCommaPosition2 = value.find(',', 0);
+ size_t nextCommaPosition2 = value.find(',');
if (nextCommaPosition2 != notFound) {
// The value is delimited by the next comma
result.append(pair<String, String>(directive, trimToNextSeparator(value.substring(0, nextCommaPosition2).stripWhiteSpace())));
diff --git a/Source/WebCore/platform/network/SocketStreamHandleClient.h b/Source/WebCore/platform/network/SocketStreamHandleClient.h
index 573986a89..bff6676b9 100644
--- a/Source/WebCore/platform/network/SocketStreamHandleClient.h
+++ b/Source/WebCore/platform/network/SocketStreamHandleClient.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2009, 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2009, 2011, 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -43,6 +43,7 @@ namespace WebCore {
public:
virtual ~SocketStreamHandleClient() { }
+ virtual void willOpenSocketStream(SocketStreamHandle*) { }
virtual void didOpenSocketStream(SocketStreamHandle*) { }
virtual void didCloseSocketStream(SocketStreamHandle*) { }
virtual void didReceiveSocketStreamData(SocketStreamHandle*, const char* /*data*/, int /*length*/) { }
diff --git a/Source/WebCore/platform/network/blackberry/AutofillBackingStore.cpp b/Source/WebCore/platform/network/blackberry/AutofillBackingStore.cpp
new file mode 100644
index 000000000..21ff9578c
--- /dev/null
+++ b/Source/WebCore/platform/network/blackberry/AutofillBackingStore.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include "AutofillBackingStore.h"
+
+#include "FileSystem.h"
+#include "SQLiteStatement.h"
+#include <BlackBerryPlatformClient.h>
+
+#define HANDLE_SQL_EXEC_FAILURE(statement, returnValue, ...) \
+ if (statement) { \
+ LOG_ERROR(__VA_ARGS__); \
+ return returnValue; \
+ }
+
+namespace WebCore {
+
+AutofillBackingStore& autofillBackingStore()
+{
+ DEFINE_STATIC_LOCAL(AutofillBackingStore, backingStore, ());
+ if (!backingStore.m_database.isOpen())
+ backingStore.open(pathByAppendingComponent(BlackBerry::Platform::Client::get()->getApplicationDataDirectory().c_str(), "/autofill.db"));
+ return backingStore;
+}
+
+AutofillBackingStore::AutofillBackingStore()
+ : m_addStatement(0)
+ , m_updateStatement(0)
+ , m_containsStatement(0)
+ , m_getStatement(0)
+{
+}
+
+AutofillBackingStore::~AutofillBackingStore()
+{
+ delete m_addStatement;
+ m_addStatement = 0;
+ delete m_updateStatement;
+ m_updateStatement = 0;
+ delete m_containsStatement;
+ m_containsStatement = 0;
+ delete m_getStatement;
+ m_getStatement = 0;
+
+ if (m_database.isOpen())
+ m_database.close();
+}
+
+bool AutofillBackingStore::open(const String& dbPath)
+{
+ ASSERT(!m_database.isOpen());
+
+ HANDLE_SQL_EXEC_FAILURE(!m_database.open(dbPath), false,
+ "Failed to open database file %s for autofill database", dbPath.utf8().data());
+
+ if (!m_database.tableExists("autofill")) {
+ HANDLE_SQL_EXEC_FAILURE(!m_database.executeCommand("CREATE TABLE autofill (id INTEGER PRIMARY KEY, name VARCHAR NOT NULL, value VARCHAR NOT NULL, count INTEGER DEFAULT 1)"),
+ false, "Failed to create table autofill for autofill database");
+
+ // Create index for table autofill.
+ HANDLE_SQL_EXEC_FAILURE(!m_database.executeCommand("CREATE INDEX autofill_name ON autofill (name)"),
+ false, "Failed to create autofill_name index for table autofill");
+ }
+
+ // Prepare the statements.
+ m_addStatement = new SQLiteStatement(m_database, "INSERT INTO autofill (name, value) VALUES (?, ?)");
+ HANDLE_SQL_EXEC_FAILURE(m_addStatement->prepare() != SQLResultOk,
+ false, "Failed to prepare add statement");
+
+ m_updateStatement = new SQLiteStatement(m_database, "UPDATE autofill SET count = (SELECT count + 1 from autofill WHERE name = ? AND value = ?) WHERE name = ? AND value = ?");
+ HANDLE_SQL_EXEC_FAILURE(m_updateStatement->prepare() != SQLResultOk,
+ false, "Failed to prepare update statement");
+
+ m_containsStatement = new SQLiteStatement(m_database, "SELECT COUNT(*) FROM autofill WHERE name = ? AND value = ?");
+ HANDLE_SQL_EXEC_FAILURE(m_containsStatement->prepare() != SQLResultOk,
+ false, "Failed to prepare contains statement");
+
+ m_getStatement = new SQLiteStatement(m_database, "SELECT value FROM autofill WHERE name = ? and value like ? ORDER BY count DESC");
+ HANDLE_SQL_EXEC_FAILURE(m_getStatement->prepare() != SQLResultOk,
+ false, "Failed to prepare get statement");
+
+ return true;
+}
+
+bool AutofillBackingStore::add(const String& name, const String& value)
+{
+ if (name.isEmpty() || value.isEmpty())
+ return false;
+
+ ASSERT(m_database.isOpen());
+ ASSERT(m_database.tableExists("autofill"));
+
+ if (contains(name, value))
+ return update(name, value);
+
+ if (!m_addStatement)
+ return false;
+
+ m_addStatement->bindText(1, name);
+ m_addStatement->bindText(2, value);
+
+ int result = m_addStatement->step();
+ m_addStatement->reset();
+ HANDLE_SQL_EXEC_FAILURE(result != SQLResultDone, false,
+ "Failed to add autofill item into table autofill - %i", result);
+
+ return true;
+}
+
+bool AutofillBackingStore::update(const String& name, const String& value)
+{
+ if (!m_updateStatement)
+ return false;
+
+ m_updateStatement->bindText(1, name);
+ m_updateStatement->bindText(2, value);
+ m_updateStatement->bindText(3, name);
+ m_updateStatement->bindText(4, value);
+
+ int result = m_updateStatement->step();
+ m_updateStatement->reset();
+ HANDLE_SQL_EXEC_FAILURE(result != SQLResultDone, false,
+ "Failed to update autofill item in table autofill - %i", result);
+
+ return true;
+}
+
+bool AutofillBackingStore::contains(const String& name, const String& value) const
+{
+ if (!m_containsStatement)
+ return false;
+
+ m_containsStatement->bindText(1, name);
+ m_containsStatement->bindText(2, value);
+
+ int result = m_containsStatement->step();
+ int numberOfRows = m_containsStatement->getColumnInt(0);
+ m_containsStatement->reset();
+ HANDLE_SQL_EXEC_FAILURE(result != SQLResultRow, false,
+ "Failed to execute select autofill item from table autofill in contains - %i", result);
+
+ return numberOfRows;
+}
+
+Vector<String> AutofillBackingStore::get(const String& name, const String& valueHint)
+{
+ ASSERT(m_database.isOpen());
+ ASSERT(m_database.tableExists("autofill"));
+
+ Vector<String> candidates;
+ if (name.isEmpty() || valueHint.isEmpty() || !m_getStatement)
+ return candidates;
+
+ String value = valueHint + "%";
+ m_getStatement->bindText(1, name);
+ m_getStatement->bindText(2, value);
+
+ int result;
+ while ((result = m_getStatement->step()) == SQLResultRow)
+ candidates.append(m_getStatement->getColumnText(0));
+ m_getStatement->reset();
+ HANDLE_SQL_EXEC_FAILURE(result != SQLResultDone, candidates,
+ "Failed to execute select autofill item from table autofill in get - %i", result);
+
+ return candidates;
+}
+
+bool AutofillBackingStore::clear()
+{
+ ASSERT(m_database.isOpen());
+ ASSERT(m_database.tableExists("autofill"));
+
+ HANDLE_SQL_EXEC_FAILURE(!m_database.executeCommand("DELETE FROM autofill"),
+ false, "Failed to clear table autofill");
+
+ return true;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/network/blackberry/AutofillBackingStore.h b/Source/WebCore/platform/network/blackberry/AutofillBackingStore.h
new file mode 100644
index 000000000..c9e35660e
--- /dev/null
+++ b/Source/WebCore/platform/network/blackberry/AutofillBackingStore.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AutofillBackingStore_h
+#define AutofillBackingStore_h
+
+#include "SQLiteDatabase.h"
+
+namespace WebCore {
+
+class AutofillBackingStore {
+public:
+ friend AutofillBackingStore& autofillBackingStore();
+
+ ~AutofillBackingStore();
+ bool open(const String& dbPath);
+ bool add(const String& name, const String& value);
+ Vector<String> get(const String& name, const String& valueHint);
+ bool clear();
+
+private:
+ AutofillBackingStore();
+ bool update(const String& name, const String& value);
+ bool contains(const String& name, const String& value) const;
+
+ SQLiteDatabase m_database;
+ SQLiteStatement* m_addStatement;
+ SQLiteStatement* m_updateStatement;
+ SQLiteStatement* m_containsStatement;
+ SQLiteStatement* m_getStatement;
+};
+
+AutofillBackingStore& autofillBackingStore();
+
+} // namespace WebCore
+
+#endif // AutofillBackingStore_h
diff --git a/Source/WebCore/platform/network/blackberry/CredentialBackingStore.cpp b/Source/WebCore/platform/network/blackberry/CredentialBackingStore.cpp
index e024c2775..42ad91fcd 100644
--- a/Source/WebCore/platform/network/blackberry/CredentialBackingStore.cpp
+++ b/Source/WebCore/platform/network/blackberry/CredentialBackingStore.cpp
@@ -28,6 +28,7 @@
#include "ProtectionSpaceHash.h"
#include "SQLiteStatement.h"
#include <BlackBerryPlatformClient.h>
+#include <BlackBerryPlatformEncryptor.h>
#define HANDLE_SQL_EXEC_FAILURE(statement, returnValue, ...) \
if (statement) { \
@@ -37,13 +38,11 @@
namespace WebCore {
-CredentialBackingStore* CredentialBackingStore::instance()
+CredentialBackingStore& credentialBackingStore()
{
- static CredentialBackingStore* backingStore = 0;
- if (!backingStore) {
- backingStore = new CredentialBackingStore;
- backingStore->open(pathByAppendingComponent(BlackBerry::Platform::Client::get()->getApplicationDataDirectory().c_str(), "/credentials.db"));
- }
+ DEFINE_STATIC_LOCAL(CredentialBackingStore, backingStore, ());
+ if (!backingStore.m_database.isOpen())
+ backingStore.open(pathByAppendingComponent(BlackBerry::Platform::Client::get()->getApplicationDataDirectory().c_str(), "/credentials.db"));
return backingStore;
}
@@ -63,6 +62,27 @@ CredentialBackingStore::CredentialBackingStore()
CredentialBackingStore::~CredentialBackingStore()
{
+ delete m_addLoginStatement;
+ m_addLoginStatement = 0;
+ delete m_updateLoginStatement;
+ m_updateLoginStatement = 0;
+ delete m_hasLoginStatement;
+ m_hasLoginStatement = 0;
+ delete m_getLoginStatement;
+ m_getLoginStatement = 0;
+ delete m_getLoginByURLStatement;
+ m_getLoginByURLStatement = 0;
+ delete m_removeLoginStatement;
+ m_removeLoginStatement = 0;
+ delete m_addNeverRememberStatement;
+ m_addNeverRememberStatement = 0;
+ delete m_hasNeverRememberStatement;
+ m_hasNeverRememberStatement = 0;
+ delete m_getNeverRememberStatement;
+ m_getNeverRememberStatement = 0;
+ delete m_removeNeverRememberStatement;
+ m_removeNeverRememberStatement = 0;
+
if (m_database.isOpen())
m_database.close();
}
@@ -136,33 +156,6 @@ bool CredentialBackingStore::open(const String& dbPath)
return true;
}
-void CredentialBackingStore::close()
-{
- delete m_addLoginStatement;
- m_addLoginStatement = 0;
- delete m_updateLoginStatement;
- m_updateLoginStatement = 0;
- delete m_hasLoginStatement;
- m_hasLoginStatement = 0;
- delete m_getLoginStatement;
- m_getLoginStatement = 0;
- delete m_getLoginByURLStatement;
- m_getLoginByURLStatement = 0;
- delete m_removeLoginStatement;
- m_removeLoginStatement = 0;
- delete m_addNeverRememberStatement;
- m_addNeverRememberStatement = 0;
- delete m_hasNeverRememberStatement;
- m_hasNeverRememberStatement = 0;
- delete m_getNeverRememberStatement;
- m_getNeverRememberStatement = 0;
- delete m_removeNeverRememberStatement;
- m_removeNeverRememberStatement = 0;
-
- if (m_database.isOpen())
- m_database.close();
-}
-
bool CredentialBackingStore::addLogin(const KURL& url, const ProtectionSpace& protectionSpace, const Credential& credential)
{
ASSERT(m_database.isOpen());
@@ -404,7 +397,7 @@ bool CredentialBackingStore::clearLogins()
ASSERT(m_database.isOpen());
ASSERT(m_database.tableExists("logins"));
- HANDLE_SQL_EXEC_FAILURE(!m_database.executeCommand("DELETE * FROM logins"),
+ HANDLE_SQL_EXEC_FAILURE(!m_database.executeCommand("DELETE FROM logins"),
false, "Failed to clear table logins");
return true;
@@ -415,7 +408,7 @@ bool CredentialBackingStore::clearNeverRemember()
ASSERT(m_database.isOpen());
ASSERT(m_database.tableExists("never_remember"));
- HANDLE_SQL_EXEC_FAILURE(!m_database.executeCommand("DELETE * FROM never_remember"),
+ HANDLE_SQL_EXEC_FAILURE(!m_database.executeCommand("DELETE FROM never_remember"),
false, "Failed to clear table never_remember");
return true;
@@ -423,16 +416,16 @@ bool CredentialBackingStore::clearNeverRemember()
String CredentialBackingStore::encryptedString(const String& plainText) const
{
- // FIXME: Need encrypt plainText here
- notImplemented();
- return plainText;
+ std::string cipherText;
+ BlackBerry::Platform::Encryptor::encryptString(std::string(plainText.latin1().data()), &cipherText);
+ return String(cipherText.c_str());
}
String CredentialBackingStore::decryptedString(const String& cipherText) const
{
- // FIXME: Need decrypt cipherText here
- notImplemented();
- return cipherText;
+ std::string plainText;
+ BlackBerry::Platform::Encryptor::decryptString(std::string(cipherText.latin1().data()), &plainText);
+ return String(plainText.c_str());
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/blackberry/CredentialBackingStore.h b/Source/WebCore/platform/network/blackberry/CredentialBackingStore.h
index fc12c6b66..7cd49e22c 100644
--- a/Source/WebCore/platform/network/blackberry/CredentialBackingStore.h
+++ b/Source/WebCore/platform/network/blackberry/CredentialBackingStore.h
@@ -31,10 +31,10 @@ class ProtectionSpace;
class CredentialBackingStore {
public:
- static CredentialBackingStore* instance();
+ friend CredentialBackingStore& credentialBackingStore();
+
~CredentialBackingStore();
bool open(const String& dbPath);
- void close();
bool addLogin(const KURL&, const ProtectionSpace&, const Credential&);
bool updateLogin(const KURL&, const ProtectionSpace&, const Credential&);
bool hasLogin(const KURL&, const ProtectionSpace&);
@@ -66,6 +66,8 @@ private:
SQLiteStatement* m_removeNeverRememberStatement;
};
+CredentialBackingStore& credentialBackingStore();
+
} // namespace WebCore
#endif // ENABLE(BLACKBERRY_CREDENTIAL_PERSIST)
diff --git a/Source/WebCore/platform/network/blackberry/CredentialStorageBlackBerry.cpp b/Source/WebCore/platform/network/blackberry/CredentialStorageBlackBerry.cpp
index 4ea783f9c..d62230633 100644
--- a/Source/WebCore/platform/network/blackberry/CredentialStorageBlackBerry.cpp
+++ b/Source/WebCore/platform/network/blackberry/CredentialStorageBlackBerry.cpp
@@ -30,7 +30,7 @@ namespace WebCore {
Credential CredentialStorage::getFromPersistentStorage(const ProtectionSpace& protectionSpace)
{
#if ENABLE(BLACKBERRY_CREDENTIAL_PERSIST)
- return CredentialBackingStore::instance()->getLogin(protectionSpace);
+ return credentialBackingStore().getLogin(protectionSpace);
#else
UNUSED_PARAM(protectionSpace);
return Credential();
diff --git a/Source/WebCore/platform/network/blackberry/DeferredData.cpp b/Source/WebCore/platform/network/blackberry/DeferredData.cpp
index dfe18d8b7..05ce58096 100644
--- a/Source/WebCore/platform/network/blackberry/DeferredData.cpp
+++ b/Source/WebCore/platform/network/blackberry/DeferredData.cpp
@@ -28,7 +28,6 @@ DeferredData::DeferredData(NetworkJob& job)
, m_processDataTimer(this, &DeferredData::fireProcessDataTimer)
, m_deferredStatusReceived(false)
, m_status(0)
- , m_deferredWMLOverride(false)
, m_bytesSent(0)
, m_totalBytesToBeSent(0)
, m_deferredCloseStatus(BlackBerry::Platform::FilterStream::StatusSuccess)
@@ -44,11 +43,6 @@ void DeferredData::deferOpen(int status, const String& message)
m_message = message;
}
-void DeferredData::deferWMLOverride()
-{
- m_deferredWMLOverride = true;
-}
-
void DeferredData::deferHeaderReceived(const String& key, const String& value)
{
m_headerKeys.append(key);
@@ -123,13 +117,6 @@ void DeferredData::processDeferredData()
return;
}
- if (m_deferredWMLOverride) {
- m_job.handleNotifyWMLOverride();
- m_deferredWMLOverride = false;
- if (m_job.isDeferringLoading() || m_job.isCancelled())
- return;
- }
-
if (!processHeaders(m_headerKeys, m_headerValues, &NetworkJob::handleNotifyHeaderReceived)
|| !processHeaders(m_multipartHeaderKeys, m_multipartheaderValues, &NetworkJob::handleNotifyMultipartHeaderReceived))
return;
diff --git a/Source/WebCore/platform/network/blackberry/DeferredData.h b/Source/WebCore/platform/network/blackberry/DeferredData.h
index b5de7a98d..d183662cd 100644
--- a/Source/WebCore/platform/network/blackberry/DeferredData.h
+++ b/Source/WebCore/platform/network/blackberry/DeferredData.h
@@ -51,7 +51,6 @@ class DeferredData {
public:
DeferredData(NetworkJob&);
void deferOpen(int status, const String& message);
- void deferWMLOverride();
void deferHeaderReceived(const String& key, const String& value);
void deferMultipartHeaderReceived(const String& key, const String& value);
void deferDataReceived(const char* buf, size_t len);
@@ -60,7 +59,7 @@ public:
bool hasDeferredData() const
{
- return m_deferredStatusReceived || m_deferredWMLOverride || !m_headerKeys.isEmpty() || !m_multipartHeaderKeys.isEmpty() || !m_dataSegments.isEmpty() || m_deferredClose;
+ return m_deferredStatusReceived || !m_headerKeys.isEmpty() || !m_multipartHeaderKeys.isEmpty() || !m_dataSegments.isEmpty() || m_deferredClose;
}
void processDeferredData();
@@ -83,7 +82,6 @@ private:
bool m_deferredStatusReceived;
int m_status;
String m_message;
- bool m_deferredWMLOverride;
Vector<String> m_headerKeys;
Vector<String> m_headerValues;
Vector<String> m_multipartHeaderKeys;
diff --git a/Source/WebCore/platform/network/blackberry/NetworkJob.cpp b/Source/WebCore/platform/network/blackberry/NetworkJob.cpp
index 912b7e996..6de5e4dbd 100644
--- a/Source/WebCore/platform/network/blackberry/NetworkJob.cpp
+++ b/Source/WebCore/platform/network/blackberry/NetworkJob.cpp
@@ -21,6 +21,8 @@
#include "AboutData.h"
#include "Base64.h"
+#include "Chrome.h"
+#include "ChromeClient.h"
#include "CookieManager.h"
#include "CredentialStorage.h"
#include "Frame.h"
@@ -30,6 +32,7 @@
#include "MIMESniffing.h"
#include "MIMETypeRegistry.h"
#include "NetworkManager.h"
+#include "Page.h"
#include "ResourceHandleClient.h"
#include "ResourceHandleInternal.h"
#include "ResourceRequest.h"
@@ -106,7 +109,6 @@ NetworkJob::NetworkJob()
, m_dataReceived(false)
, m_responseSent(false)
, m_callingClient(false)
- , m_isXHR(false)
, m_needsRetryAsFTPDirectory(false)
, m_isOverrideContentType(false)
, m_extendedStatusCode(0)
@@ -162,13 +164,16 @@ bool NetworkJob::initialize(int playerId,
if (m_isData || m_isAbout)
return true;
+ if (!request.getSuggestedSaveName().empty()) {
+ m_contentDisposition = "filename=";
+ m_contentDisposition += request.getSuggestedSaveName().c_str();
+ }
+
BlackBerry::Platform::FilterStream* wrappedStream = m_streamFactory->createNetworkStream(request, m_playerId);
if (!wrappedStream)
return false;
setWrappedStream(wrappedStream);
- m_isXHR = request.getTargetType() == BlackBerry::Platform::NetworkRequest::TargetIsXMLHTTPRequest;
-
return true;
}
@@ -240,37 +245,32 @@ void NetworkJob::handleNotifyStatusReceived(int status, const String& message)
m_response.setHTTPStatusText(message);
}
-void NetworkJob::notifyWMLOverride()
+void NetworkJob::notifyHeadersReceived(BlackBerry::Platform::NetworkRequest::HeaderList& headers)
{
- if (shouldDeferLoading())
- m_deferredData.deferWMLOverride();
- else
- handleNotifyWMLOverride();
-}
-
-void NetworkJob::notifyHeaderReceived(const char* key, const char* value)
-{
- if (shouldDeferLoading())
- m_deferredData.deferHeaderReceived(key, value);
- else {
- String keyString(key);
- String valueString;
- if (equalIgnoringCase(keyString, "Location")) {
- // Location, like all headers, is supposed to be Latin-1. But some sites (wikipedia) send it in UTF-8.
- // All byte strings that are valid UTF-8 are also valid Latin-1 (although outside ASCII, the meaning will
- // differ), but the reverse isn't true. So try UTF-8 first and fall back to Latin-1 if it's invalid.
- // (High Latin-1 should be url-encoded anyway.)
- //
- // FIXME: maybe we should do this with other headers?
- // Skip it for now - we don't want to rewrite random bytes unless we're sure. (Definitely don't want to
- // rewrite cookies, for instance.) Needs more investigation.
- valueString = String::fromUTF8(value);
- if (valueString.isNull())
- valueString = value;
- } else
- valueString = value;
-
- handleNotifyHeaderReceived(keyString, valueString);
+ BlackBerry::Platform::NetworkRequest::HeaderList::const_iterator endIt = headers.end();
+ for (BlackBerry::Platform::NetworkRequest::HeaderList::const_iterator it = headers.begin(); it != endIt; ++it) {
+ if (shouldDeferLoading())
+ m_deferredData.deferHeaderReceived(it->first.c_str(), it->second.c_str());
+ else {
+ String keyString(it->first.c_str());
+ String valueString;
+ if (equalIgnoringCase(keyString, "Location")) {
+ // Location, like all headers, is supposed to be Latin-1. But some sites (wikipedia) send it in UTF-8.
+ // All byte strings that are valid UTF-8 are also valid Latin-1 (although outside ASCII, the meaning will
+ // differ), but the reverse isn't true. So try UTF-8 first and fall back to Latin-1 if it's invalid.
+ // (High Latin-1 should be url-encoded anyway.)
+ //
+ // FIXME: maybe we should do this with other headers?
+ // Skip it for now - we don't want to rewrite random bytes unless we're sure. (Definitely don't want to
+ // rewrite cookies, for instance.) Needs more investigation.
+ valueString = String::fromUTF8(it->second.c_str());
+ if (valueString.isNull())
+ valueString = it->second.c_str();
+ } else
+ valueString = it->second.c_str();
+
+ handleNotifyHeaderReceived(keyString, valueString);
+ }
}
}
@@ -299,22 +299,26 @@ void NetworkJob::handleNotifyHeaderReceived(const String& key, const String& val
String lowerKey = key.lower();
if (lowerKey == "content-type")
m_contentType = value.lower();
-
- if (lowerKey == "content-disposition")
+ else if (lowerKey == "content-disposition")
m_contentDisposition = value;
-
- if (lowerKey == "set-cookie") {
- if (m_frame && m_frame->loader() && m_frame->loader()->client()
+ else if (lowerKey == "set-cookie") {
+ // FIXME: If a tab is closed, sometimes network data will come in after the frame has been detached from its page but before it is deleted.
+ // If this happens, m_frame->page() will return 0, and m_frame->loader()->client() will be in a bad state and calling into it will crash.
+ // For now we check for this explicitly by checking m_frame->page(). But we should find out why the network job hasn't been cancelled when the frame was detached.
+ // See RIM PR 134207
+ if (m_frame && m_frame->page() && m_frame->loader() && m_frame->loader()->client()
&& static_cast<FrameLoaderClientBlackBerry*>(m_frame->loader()->client())->cookiesEnabled())
handleSetCookieHeader(value);
- }
- if (lowerKey == "www-authenticate")
+ if (m_response.httpHeaderFields().contains("Set-Cookie")) {
+ m_response.setHTTPHeaderField(key, m_response.httpHeaderField(key) + "\r\n" + value);
+ return;
+ }
+ } else if (lowerKey == "www-authenticate")
handleAuthHeader(ProtectionSpaceServerHTTP, value);
else if (lowerKey == "proxy-authenticate" && !BlackBerry::Platform::Client::get()->getProxyAddress().empty())
handleAuthHeader(ProtectionSpaceProxyHTTP, value);
-
- if (equalIgnoringCase(key, BlackBerry::Platform::NetworkRequest::HEADER_BLACKBERRY_FTP))
+ else if (equalIgnoringCase(key, BlackBerry::Platform::NetworkRequest::HEADER_BLACKBERRY_FTP))
handleFTPHeader(value);
m_response.setHTTPHeaderField(key, value);
@@ -397,7 +401,7 @@ void NetworkJob::handleNotifyDataReceived(const char* buf, size_t len)
if (m_isFile) {
String urlFilename = m_response.url().lastPathComponent();
size_t pos = urlFilename.reverseFind('.');
- if (pos != WTF::notFound) {
+ if (pos != notFound) {
String extension = urlFilename.substring(pos + 1);
String mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension);
if (!mimeType.isEmpty())
@@ -488,7 +492,7 @@ void NetworkJob::handleNotifyClose(int status)
if (isClientAvailable()) {
RecursionGuard guard(m_callingClient);
- if (isError(m_extendedStatusCode) && !m_dataReceived) {
+ if (isError(m_extendedStatusCode) && !m_dataReceived && m_handle->firstRequest().httpMethod() != "HEAD") {
String domain = m_extendedStatusCode < 0 ? ResourceError::platformErrorDomain : ResourceError::httpErrorDomain;
ResourceError error(domain, m_extendedStatusCode, m_response.url().string(), m_response.httpStatusText());
m_handle->client()->didFail(m_handle.get(), error);
@@ -585,11 +589,11 @@ bool NetworkJob::handleRedirect()
newRequest.setMustHandleInternally(true);
String method = newRequest.httpMethod().upper();
- if ((method != "GET") && (method != "HEAD")) {
+ if (method != "GET" && method != "HEAD") {
newRequest.setHTTPMethod("GET");
newRequest.setHTTPBody(0);
- newRequest.setHTTPHeaderField("Content-Length", String());
- newRequest.setHTTPHeaderField("Content-Type", String());
+ newRequest.clearHTTPContentLength();
+ newRequest.clearHTTPContentType();
}
// Do not send existing credentials with the new request.
@@ -653,8 +657,8 @@ void NetworkJob::sendResponseIfNeeded()
m_response.setSuggestedFilename(suggestedFilename);
}
- // Make sure local files aren't cached, since this just duplicates them.
- if (m_isFile || m_isData || m_isAbout)
+ // Don't cache resources for "about:"
+ if (m_isAbout)
m_response.setHTTPHeaderField("Cache-Control", "no-cache");
if (isClientAvailable()) {
@@ -856,17 +860,27 @@ bool NetworkJob::sendRequestWithCredentials(ProtectionSpaceServerType type, Prot
if (!m_frame || !m_frame->loader() || !m_frame->loader()->client())
return false;
- // Before asking the user for credentials, we check if the URL contains that.
- if (!m_handle->getInternal()->m_user.isEmpty() && !m_handle->getInternal()->m_pass.isEmpty()) {
- username = m_handle->getInternal()->m_user.utf8().data();
- password = m_handle->getInternal()->m_pass.utf8().data();
+ if (type == ProtectionSpaceProxyHTTP) {
+ username = BlackBerry::Platform::Client::get()->getProxyUsername().c_str();
+ password = BlackBerry::Platform::Client::get()->getProxyPassword().c_str();
+ }
- // Prevent them from been used again if they are wrong.
- // If they are correct, they will the put into CredentialStorage.
- m_handle->getInternal()->m_user = "";
- m_handle->getInternal()->m_pass = "";
- } else
- m_frame->loader()->client()->authenticationChallenge(realm, username, password);
+ if (username.isEmpty() || password.isEmpty()) {
+ // Before asking the user for credentials, we check if the URL contains that.
+ if (!m_handle->getInternal()->m_user.isEmpty() && !m_handle->getInternal()->m_pass.isEmpty()) {
+ username = m_handle->getInternal()->m_user.utf8().data();
+ password = m_handle->getInternal()->m_pass.utf8().data();
+
+ // Prevent them from been used again if they are wrong.
+ // If they are correct, they will the put into CredentialStorage.
+ m_handle->getInternal()->m_user = "";
+ m_handle->getInternal()->m_pass = "";
+ } else {
+ Credential inputCredential = m_frame->page()->chrome()->client()->platformPageClient()->authenticationChallenge(newURL, protectionSpace);
+ username = inputCredential.user();
+ password = inputCredential.password();
+ }
+ }
if (username.isEmpty() && password.isEmpty())
return false;
@@ -932,7 +946,7 @@ void NetworkJob::handleAbout()
String result;
bool handled = false;
- if (aboutWhat.isEmpty() || equalIgnoringCase(aboutWhat, "blank")) {
+ if (equalIgnoringCase(aboutWhat, "blank")) {
handled = true;
} else if (equalIgnoringCase(aboutWhat, "credits")) {
result.append(String("<html><head><title>Open Source Credits</title> <style> .about {padding:14px;} </style> <meta name=\"viewport\" content=\"width=device-width, user-scalable=no\"></head><body>"));
@@ -1003,10 +1017,9 @@ void NetworkJob::handleAbout()
handled = true;
#endif
}
-
if (handled) {
CString resultString = result.utf8();
- notifyStatusReceived(404, 0);
+ notifyStatusReceived(BlackBerry::Platform::FilterStream::StatusSuccess, 0);
notifyStringHeaderReceived("Content-Length", String::number(resultString.length()));
notifyStringHeaderReceived("Content-Type", "text/html");
notifyDataReceivedPlain(resultString.data(), resultString.length());
diff --git a/Source/WebCore/platform/network/blackberry/NetworkJob.h b/Source/WebCore/platform/network/blackberry/NetworkJob.h
index a50059ab1..a16117ac0 100644
--- a/Source/WebCore/platform/network/blackberry/NetworkJob.h
+++ b/Source/WebCore/platform/network/blackberry/NetworkJob.h
@@ -67,9 +67,7 @@ public:
void updateDeferLoadingCount(int delta);
virtual void notifyStatusReceived(int status, const char* message);
void handleNotifyStatusReceived(int status, const String& message);
- virtual void notifyWMLOverride();
- void handleNotifyWMLOverride() { m_response.setIsWML(true); }
- virtual void notifyHeaderReceived(const char* key, const char* value);
+ virtual void notifyHeadersReceived(BlackBerry::Platform::NetworkRequest::HeaderList& headers);
virtual void notifyMultipartHeaderReceived(const char* key, const char* value);
// Exists only to resolve ambiguity between char* and String parameters
void notifyStringHeaderReceived(const String& key, const String& value);
@@ -145,7 +143,7 @@ private:
bool isError(int statusCode)
{
- return statusCode < 0 || (!m_isXHR && (400 <= statusCode && statusCode < 600));
+ return statusCode < 0 || (400 <= statusCode && statusCode < 600);
}
private:
@@ -174,7 +172,6 @@ private:
bool m_dataReceived;
bool m_responseSent;
bool m_callingClient;
- bool m_isXHR; // FIXME - After 7.0, remove this. Only the Qt port reports HTTP error statuses as didFails, so we probably shouldn't.
bool m_needsRetryAsFTPDirectory;
bool m_isOverrideContentType;
diff --git a/Source/WebCore/platform/network/blackberry/NetworkManager.cpp b/Source/WebCore/platform/network/blackberry/NetworkManager.cpp
index 7c628f005..458efb032 100644
--- a/Source/WebCore/platform/network/blackberry/NetworkManager.cpp
+++ b/Source/WebCore/platform/network/blackberry/NetworkManager.cpp
@@ -20,7 +20,6 @@
#include "NetworkManager.h"
#include "Chrome.h"
-#include "CookieManager.h"
#include "CredentialStorage.h"
#include "Frame.h"
#include "FrameLoaderClientBlackBerry.h"
@@ -29,6 +28,10 @@
#include "ResourceHandleInternal.h"
#include "ResourceRequest.h"
+#include <BlackBerryPlatformClient.h>
+#include <BlackBerryPlatformLog.h>
+#include <BuildInformation.h>
+#include <network/FilterStream.h>
#include <network/NetworkRequest.h>
namespace WebCore {
@@ -73,7 +76,7 @@ bool NetworkManager::startJob(int playerId, const String& pageGroupName, PassRef
m_initialURL = KURL();
BlackBerry::Platform::NetworkRequest platformRequest;
- request.initializePlatformRequest(platformRequest, isInitial);
+ request.initializePlatformRequest(platformRequest, frame.loader() && frame.loader()->client() && static_cast<FrameLoaderClientBlackBerry*>(frame.loader()->client())->cookiesEnabled(), isInitial, redirectCount);
// Attach any applicable auth credentials to the NetworkRequest.
AuthenticationChallenge& challenge = guardJob->getInternal()->m_currentWebChallenge;
@@ -117,16 +120,6 @@ bool NetworkManager::startJob(int playerId, const String& pageGroupName, PassRef
platformRequest.setCredentials(credential.user().utf8().data(), credential.password().utf8().data(), BlackBerry::Platform::NetworkRequest::AuthHTTPBasic);
}
- if ((&frame) && (&frame)->loader() && (&frame)->loader()->client()
- && static_cast<FrameLoaderClientBlackBerry*>((&frame)->loader()->client())->cookiesEnabled()) {
- // Prepare a cookie header if there are cookies related to this url.
- String cookiePairs = cookieManager().getCookie(url, WithHttpOnlyCookies);
- if (!cookiePairs.isEmpty()) {
- // We need to check the encoding and encode the cookie header data using latin1 or utf8 to support unicode characters.
- platformRequest.setCookieData(cookiePairs.containsOnlyLatin1() ? cookiePairs.latin1().data() : cookiePairs.utf8().data());
- }
- }
-
if (!request.overrideContentType().isEmpty())
platformRequest.setOverrideContentType(request.overrideContentType().latin1().data());
diff --git a/Source/WebCore/platform/network/blackberry/ResourceRequest.h b/Source/WebCore/platform/network/blackberry/ResourceRequest.h
index 7072eb1f3..29bb25c1a 100644
--- a/Source/WebCore/platform/network/blackberry/ResourceRequest.h
+++ b/Source/WebCore/platform/network/blackberry/ResourceRequest.h
@@ -57,6 +57,7 @@ public:
, m_mustHandleInternally(false)
, m_isRequestedByPlugin(false)
, m_forceDownload(false)
+ , m_targetType(TargetIsUnspecified)
{
}
@@ -66,6 +67,7 @@ public:
, m_mustHandleInternally(false)
, m_isRequestedByPlugin(false)
, m_forceDownload(false)
+ , m_targetType(TargetIsUnspecified)
{
}
@@ -75,6 +77,7 @@ public:
, m_mustHandleInternally(false)
, m_isRequestedByPlugin(false)
, m_forceDownload(false)
+ , m_targetType(TargetIsUnspecified)
{
setHTTPReferrer(referrer);
}
@@ -85,6 +88,7 @@ public:
, m_mustHandleInternally(false)
, m_isRequestedByPlugin(false)
, m_forceDownload(false)
+ , m_targetType(TargetIsUnspecified)
{
}
@@ -110,9 +114,11 @@ public:
void setMustHandleInternally(bool mustHandleInternally) { m_mustHandleInternally = mustHandleInternally; }
bool mustHandleInternally() const { return m_mustHandleInternally; }
- void initializePlatformRequest(BlackBerry::Platform::NetworkRequest&, bool isInitial = false) const;
+ void initializePlatformRequest(BlackBerry::Platform::NetworkRequest&, bool cookiesEnabled, bool isInitial = false, bool isRedirect = false) const;
void setForceDownload(bool forceDownload) { m_forceDownload = true; }
bool forceDownload() const { return m_forceDownload; }
+ void setSuggestedSaveName(const String& name) { m_suggestedSaveName = name; }
+ String suggestedSaveName() const { return m_suggestedSaveName; }
// What this request is for.
TargetType targetType() const { return m_targetType; }
@@ -120,12 +126,16 @@ public:
static TargetType targetTypeFromMimeType(const String& mimeType);
+ void clearHTTPContentLength();
+ void clearHTTPContentType();
+
private:
friend class ResourceRequestBase;
String m_token;
String m_anchorText;
String m_overrideContentType;
+ String m_suggestedSaveName;
bool m_isXMLHTTPRequest;
bool m_mustHandleInternally;
bool m_isRequestedByPlugin;
@@ -142,10 +152,13 @@ private:
struct CrossThreadResourceRequestData : public CrossThreadResourceRequestDataBase {
String m_token;
String m_anchorText;
+ String m_overrideContentType;
+ String m_suggestedSaveName;
bool m_isXMLHTTPRequest;
bool m_mustHandleInternally;
bool m_isRequestedByPlugin;
bool m_forceDownload;
+ ResourceRequest::TargetType m_targetType;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/blackberry/ResourceRequestBlackBerry.cpp b/Source/WebCore/platform/network/blackberry/ResourceRequestBlackBerry.cpp
index 5b6792fa7..948534647 100644
--- a/Source/WebCore/platform/network/blackberry/ResourceRequestBlackBerry.cpp
+++ b/Source/WebCore/platform/network/blackberry/ResourceRequestBlackBerry.cpp
@@ -20,6 +20,7 @@
#include "ResourceRequest.h"
#include "BlobRegistryImpl.h"
+#include "CookieManager.h"
#include <BlackBerryPlatformClient.h>
#include <network/NetworkRequest.h>
#include <wtf/HashMap.h>
@@ -31,7 +32,7 @@ namespace WebCore {
unsigned initializeMaximumHTTPConnectionCountPerHost()
{
- return 6;
+ return 10000;
}
static inline NetworkRequest::CachePolicy platformCachePolicyForRequest(const ResourceRequest& request)
@@ -46,7 +47,6 @@ static inline NetworkRequest::CachePolicy platformCachePolicyForRequest(const Re
case WebCore::ReturnCacheDataDontLoad:
return NetworkRequest::ReturnCacheDataDontLoad;
default:
- ASSERT_NOT_REACHED();
return NetworkRequest::UseProtocolCachePolicy;
}
}
@@ -79,6 +79,22 @@ static inline NetworkRequest::TargetType platformTargetTypeForRequest(const Reso
return NetworkRequest::TargetIsWorker;
case ResourceRequest::TargetIsSharedWorker:
return NetworkRequest::TargetIsSharedWorker;
+
+ // FIXME: this need to be updated to the right value, but
+ // we need to coordinate with AIR api change.
+ case ResourceRequest::TargetIsFavicon:
+ return NetworkRequest::TargetIsImage;
+ case ResourceRequest::TargetIsPrefetch:
+ return NetworkRequest::TargetIsSubresource;
+ case ResourceRequest::TargetIsPrerender:
+ return NetworkRequest::TargetIsSubresource;
+ case ResourceRequest::TargetIsXHR:
+ return NetworkRequest::TargetIsSubresource;
+ case ResourceRequest::TargetIsTextTrack:
+ return NetworkRequest::TargetIsSubresource;
+ case ResourceRequest::TargetIsUnspecified:
+ return NetworkRequest::TargetIsSubresource;
+
default:
ASSERT_NOT_REACHED();
return NetworkRequest::TargetIsUnknown;
@@ -126,7 +142,7 @@ ResourceRequest::TargetType ResourceRequest::targetTypeFromMimeType(const String
return iter->second;
}
-void ResourceRequest::initializePlatformRequest(NetworkRequest& platformRequest, bool isInitial) const
+void ResourceRequest::initializePlatformRequest(NetworkRequest& platformRequest, bool cookiesEnabled, bool isInitial, bool isRedirect) const
{
// If this is the initial load, skip the request body and headers.
if (isInitial)
@@ -139,6 +155,7 @@ void ResourceRequest::initializePlatformRequest(NetworkRequest& platformRequest,
timeoutInterval());
platformRequest.setConditional(isConditional());
+ platformRequest.setSuggestedSaveName(suggestedSaveName().utf8().data());
if (httpBody() && !httpBody()->isEmpty()) {
const Vector<FormDataElement>& elements = httpBody()->elements();
@@ -174,22 +191,42 @@ void ResourceRequest::initializePlatformRequest(NetworkRequest& platformRequest,
}
}
+ // When ResourceRequest is reused by CacheResourceLoader, page refreshing or redirection, its cookies may be dirtied. We won't use these cookies any more.
+ bool cookieHeaderMayBeDirty = isRedirect || cachePolicy() == WebCore::ReloadIgnoringCacheData || cachePolicy() == WebCore::ReturnCacheDataElseLoad;
+
for (HTTPHeaderMap::const_iterator it = httpHeaderFields().begin(); it != httpHeaderFields().end(); ++it) {
String key = it->first;
String value = it->second;
- if (!key.isEmpty() && !value.isEmpty())
- platformRequest.addHeader(key.latin1().data(), value.latin1().data());
+ if (!key.isEmpty()) {
+ // We need to check the encoding and encode the cookie's value using latin1 or utf8 to support unicode characters.
+ // We wo't use the old cookies of resourceRequest for new location because these cookies may be changed by redirection.
+ if (!equalIgnoringCase(key, "Cookie"))
+ platformRequest.addHeader(key.latin1().data(), value.latin1().data());
+ else if (!cookieHeaderMayBeDirty)
+ platformRequest.addHeader(key.latin1().data(), value.containsOnlyLatin1() ? value.latin1().data() : value.utf8().data());
+ }
+ }
+
+ // If request's cookies may be dirty, they must be set again.
+ // If there aren't cookies in the header list, we need trying to add cookies.
+ if (cookiesEnabled && (cookieHeaderMayBeDirty || !httpHeaderFields().contains("Cookie")) && !url().isNull()) {
+ // Prepare a cookie header if there are cookies related to this url.
+ String cookiePairs = cookieManager().getCookie(url(), WithHttpOnlyCookies);
+ if (!cookiePairs.isEmpty())
+ platformRequest.addHeader("Cookie", cookiePairs.containsOnlyLatin1() ? cookiePairs.latin1().data() : cookiePairs.utf8().data());
}
- // Locale has the form "en-US". Construct accept language like "en-US, en;q=0.8".
- std::string locale = BlackBerry::Platform::Client::get()->getLocale();
- // POSIX locale has '_' instead of '-'.
- // Replace to conform to HTTP spec.
- size_t underscore = locale.find('_');
- if (underscore != std::string::npos)
- locale.replace(underscore, 1, "-");
- std::string acceptLanguage = locale + ", " + locale.substr(0, 2) + ";q=0.8";
- platformRequest.addHeader("Accept-Language", acceptLanguage.c_str());
+ if (!httpHeaderFields().contains("Accept-Language")) {
+ // Locale has the form "en-US". Construct accept language like "en-US, en;q=0.8".
+ std::string locale = BlackBerry::Platform::Client::get()->getLocale();
+ // POSIX locale has '_' instead of '-'.
+ // Replace to conform to HTTP spec.
+ size_t underscore = locale.find('_');
+ if (underscore != std::string::npos)
+ locale.replace(underscore, 1, "-");
+ std::string acceptLanguage = locale + ", " + locale.substr(0, 2) + ";q=0.8";
+ platformRequest.addHeader("Accept-Language", acceptLanguage.c_str());
+ }
}
}
@@ -197,8 +234,13 @@ PassOwnPtr<CrossThreadResourceRequestData> ResourceRequest::doPlatformCopyData(P
{
data->m_token = m_token;
data->m_anchorText = m_anchorText;
+ data->m_overrideContentType = m_overrideContentType;
+ data->m_suggestedSaveName = m_suggestedSaveName;
data->m_isXMLHTTPRequest = m_isXMLHTTPRequest;
data->m_mustHandleInternally = m_mustHandleInternally;
+ data->m_isRequestedByPlugin = m_isRequestedByPlugin;
+ data->m_forceDownload = m_forceDownload;
+ data->m_targetType = m_targetType;
return data;
}
@@ -206,9 +248,33 @@ void ResourceRequest::doPlatformAdopt(PassOwnPtr<CrossThreadResourceRequestData>
{
m_token = data->m_token;
m_anchorText = data->m_anchorText;
+ m_overrideContentType = data->m_overrideContentType;
+ m_suggestedSaveName = data->m_suggestedSaveName;
m_isXMLHTTPRequest = data->m_isXMLHTTPRequest;
m_mustHandleInternally = data->m_mustHandleInternally;
+ m_isRequestedByPlugin = data->m_isRequestedByPlugin;
m_forceDownload = data->m_forceDownload;
+ m_targetType = data->m_targetType;
+}
+
+void ResourceRequest::clearHTTPContentLength()
+{
+ updateResourceRequest();
+
+ m_httpHeaderFields.remove("Content-Length");
+
+ if (url().protocolInHTTPFamily())
+ m_platformRequestUpdated = false;
+}
+
+void ResourceRequest::clearHTTPContentType()
+{
+ updateResourceRequest();
+
+ m_httpHeaderFields.remove("Content-Type");
+
+ if (url().protocolInHTTPFamily())
+ m_platformRequestUpdated = false;
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/blackberry/ResourceResponse.h b/Source/WebCore/platform/network/blackberry/ResourceResponse.h
index 1cea83ee9..8bff29df4 100644
--- a/Source/WebCore/platform/network/blackberry/ResourceResponse.h
+++ b/Source/WebCore/platform/network/blackberry/ResourceResponse.h
@@ -26,20 +26,16 @@ namespace WebCore {
class ResourceResponse : public ResourceResponseBase {
public:
ResourceResponse()
- : m_isWML(false)
+ : m_isMultipartPayload(false)
{
}
ResourceResponse(const KURL& url, const String& mimeType, long long expectedLength, const String& textEncodingName, const String& filename)
: ResourceResponseBase(url, mimeType, expectedLength, textEncodingName, filename)
, m_isMultipartPayload(false)
- , m_isWML(false)
{
}
- void setIsWML(bool isWML) { m_isWML = isWML; }
- bool isWML() const { return m_isWML; }
-
PassOwnPtr<CrossThreadResourceResponseData> doPlatformCopyData(PassOwnPtr<CrossThreadResourceResponseData>) const;
void doPlatformAdopt(PassOwnPtr<CrossThreadResourceResponseData>);
@@ -48,11 +44,9 @@ public:
private:
bool m_isMultipartPayload;
- bool m_isWML;
};
struct CrossThreadResourceResponseData : public CrossThreadResourceResponseDataBase {
- bool m_isWML;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/blackberry/ResourceResponseBlackBerry.cpp b/Source/WebCore/platform/network/blackberry/ResourceResponseBlackBerry.cpp
index ae46c5e13..a3b5e1bce 100644
--- a/Source/WebCore/platform/network/blackberry/ResourceResponseBlackBerry.cpp
+++ b/Source/WebCore/platform/network/blackberry/ResourceResponseBlackBerry.cpp
@@ -23,13 +23,11 @@ namespace WebCore {
PassOwnPtr<CrossThreadResourceResponseData> ResourceResponse::doPlatformCopyData(PassOwnPtr<CrossThreadResourceResponseData> data) const
{
- data->m_isWML = m_isWML;
return data;
}
void ResourceResponse::doPlatformAdopt(PassOwnPtr<CrossThreadResourceResponseData> data)
{
- m_isWML = data->m_isWML;
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/blackberry/SocketStreamHandle.h b/Source/WebCore/platform/network/blackberry/SocketStreamHandle.h
index cc3ed7b93..73b118fef 100644
--- a/Source/WebCore/platform/network/blackberry/SocketStreamHandle.h
+++ b/Source/WebCore/platform/network/blackberry/SocketStreamHandle.h
@@ -65,12 +65,6 @@ protected:
private:
SocketStreamHandle(const String& groupName, const KURL&, SocketStreamHandleClient*);
- // No authentication for streams per se, but proxy may ask for credentials.
- void didReceiveAuthenticationChallenge(const AuthenticationChallenge&);
- void receivedCredential(const AuthenticationChallenge&, const Credential&);
- void receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&);
- void receivedCancellation(const AuthenticationChallenge&);
-
OwnPtr<BlackBerry::Platform::FilterStream> m_socketStream;
};
diff --git a/Source/WebCore/platform/network/blackberry/SocketStreamHandleBlackBerry.cpp b/Source/WebCore/platform/network/blackberry/SocketStreamHandleBlackBerry.cpp
index 7e20e1723..0fd0e6961 100644
--- a/Source/WebCore/platform/network/blackberry/SocketStreamHandleBlackBerry.cpp
+++ b/Source/WebCore/platform/network/blackberry/SocketStreamHandleBlackBerry.cpp
@@ -36,7 +36,6 @@
#include "FrameLoaderClientBlackBerry.h"
#include "KURL.h"
#include "Logging.h"
-#include "NotImplemented.h"
#include "Page.h"
#include "PageClientBlackBerry.h"
#include "PageGroup.h"
@@ -98,26 +97,6 @@ void SocketStreamHandle::platformClose()
m_socketStream->streamClose();
}
-void SocketStreamHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge&)
-{
- notImplemented();
-}
-
-void SocketStreamHandle::receivedCredential(const AuthenticationChallenge&, const Credential&)
-{
- notImplemented();
-}
-
-void SocketStreamHandle::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&)
-{
- notImplemented();
-}
-
-void SocketStreamHandle::receivedCancellation(const AuthenticationChallenge&)
-{
- notImplemented();
-}
-
// FilterStream interface
void SocketStreamHandle::notifyStatusReceived(int status, const char* message)
diff --git a/Source/WebCore/platform/network/cf/DNSCFNet.cpp b/Source/WebCore/platform/network/cf/DNSCFNet.cpp
index a6a8d925f..28c95df97 100644
--- a/Source/WebCore/platform/network/cf/DNSCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/DNSCFNet.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2008 Collin Jackson <collinj@webkit.org>
* Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2012 Igalia S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,6 +27,7 @@
#include "config.h"
#include "DNS.h"
+#include "DNSResolveQueue.h"
#include "KURL.h"
#include "Timer.h"
@@ -47,25 +49,7 @@
namespace WebCore {
-// When resolve queue is empty, we fire async resolution requests immediately (which is important if the prefetch is triggered by hovering).
-// But during page parsing, we should coalesce identical requests to avoid stressing out CFHost.
-const int namesToResolveImmediately = 4;
-
-// Coalesce prefetch requests for this long before sending them out.
-const double coalesceDelayInSeconds = 1.0;
-
-// Sending many DNS requests at once can overwhelm some gateways. CFHost doesn't currently throttle for us, see <rdar://8105550>.
-const int maxSimultaneousRequests = 8;
-
-// For a page has links to many outside sites, it is likely that the system DNS resolver won't be able to cache them all anyway, and we don't want
-// to negatively affect other applications' performance by pushing their cached entries out.
-// If we end up with lots of names to prefetch, some will be dropped.
-const int maxRequestsToQueue = 64;
-
-// If there were queued names that couldn't be sent simultaneously, check the state of resolvers after this delay.
-const double retryResolvingInSeconds = 0.1;
-
-static bool proxyIsEnabledInSystemPreferences()
+bool DNSResolveQueue::platformProxyIsEnabledInSystemPreferences()
{
// Don't do DNS prefetch if proxies are involved. For many proxy types, the user agent is never exposed
// to the IP address during normal operation. Querying an internal DNS server may not help performance,
@@ -96,94 +80,20 @@ static bool proxyIsEnabledInSystemPreferences()
return httpProxyCount || httpsProxyCount;
}
-class DNSResolveQueue : public TimerBase {
-public:
- static DNSResolveQueue& shared();
- void add(const String&);
- void decrementRequestCount();
-
-private:
- DNSResolveQueue();
-
- void resolve(const String&);
- virtual void fired();
- HashSet<String> m_names;
- int m_requestsInFlight;
-};
-
-DNSResolveQueue::DNSResolveQueue()
- : m_requestsInFlight(0)
-{
-}
-
-DNSResolveQueue& DNSResolveQueue::shared()
-{
- DEFINE_STATIC_LOCAL(DNSResolveQueue, names, ());
- return names;
-}
-
-void DNSResolveQueue::add(const String& name)
-{
- // If there are no names queued, and few enough are in flight, resolve immediately (the mouse may be over a link).
- if (!m_names.size()) {
- if (proxyIsEnabledInSystemPreferences())
- return;
-
- if (atomicIncrement(&m_requestsInFlight) <= namesToResolveImmediately) {
- resolve(name);
- return;
- }
- atomicDecrement(&m_requestsInFlight);
- }
-
- // It's better to not prefetch some names than to clog the queue.
- // Dropping the newest names, because on a single page, these are likely to be below oldest ones.
- if (m_names.size() < maxRequestsToQueue) {
- m_names.add(name);
- if (!isActive())
- startOneShot(coalesceDelayInSeconds);
- }
-}
-
-void DNSResolveQueue::decrementRequestCount()
-{
- atomicDecrement(&m_requestsInFlight);
-}
-
-void DNSResolveQueue::fired()
-{
- if (proxyIsEnabledInSystemPreferences()) {
- m_names.clear();
- return;
- }
-
- int requestsAllowed = maxSimultaneousRequests - m_requestsInFlight;
-
- for (; !m_names.isEmpty() && requestsAllowed > 0; --requestsAllowed) {
- atomicIncrement(&m_requestsInFlight);
- HashSet<String>::iterator currentName = m_names.begin();
- resolve(*currentName);
- m_names.remove(currentName);
- }
-
- if (!m_names.isEmpty())
- startOneShot(retryResolvingInSeconds);
-}
-
static void clientCallback(CFHostRef theHost, CFHostInfoType, const CFStreamError*, void*)
{
DNSResolveQueue::shared().decrementRequestCount(); // It's ok to call shared() from a secondary thread, the static variable has already been initialized by now.
CFRelease(theHost);
}
-void DNSResolveQueue::resolve(const String& hostname)
+void DNSResolveQueue::platformResolve(const String& hostname)
{
ASSERT(isMainThread());
RetainPtr<CFStringRef> hostnameCF(AdoptCF, hostname.createCFString());
RetainPtr<CFHostRef> host(AdoptCF, CFHostCreateWithName(0, hostnameCF.get()));
if (!host) {
- atomicDecrement(&m_requestsInFlight);
+ decrementRequestCount();
return;
}
CFHostClientContext context = { 0, 0, 0, 0, 0 };
diff --git a/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp b/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp
index a213cbff7..dec9dc21c 100644
--- a/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,99 +26,469 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* originally written by Becky Willrich, additional code by Darin Adler */
-
#include "config.h"
#include "FormDataStreamCFNet.h"
-#if USE(CFNETWORK)
-
+#include "BlobRegistryImpl.h"
#include "FileSystem.h"
#include "FormData.h"
-#include <CFNetwork/CFURLRequestPriv.h>
+#include "SchedulePair.h"
+#include <sys/stat.h>
#include <sys/types.h>
#include <wtf/Assertions.h>
#include <wtf/HashMap.h>
+#include <wtf/MainThread.h>
#include <wtf/RetainPtr.h>
-#include <wtf/text/CString.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/Threading.h>
+
+#if PLATFORM(IOS)
+#include <MacErrors.h>
+#elif PLATFORM(MAC)
+#include <CoreServices/CoreServices.h>
+#endif
#if PLATFORM(MAC)
-#include "WebCoreSystemInterface.h"
+extern "C" void CFURLRequestSetHTTPRequestBody(CFMutableURLRequestRef mutableHTTPRequest, CFDataRef httpBody);
+extern "C" void CFURLRequestSetHTTPHeaderFieldValue(CFMutableURLRequestRef mutableHTTPRequest, CFStringRef httpHeaderField, CFStringRef httpHeaderFieldValue);
+extern "C" void CFURLRequestSetHTTPRequestBodyStream(CFMutableURLRequestRef req, CFReadStreamRef bodyStream);
+extern "C" CFReadStreamRef CFURLRequestCopyHTTPRequestBodyStream(CFURLRequestRef request);
#elif PLATFORM(WIN)
-#include <WebKitSystemInterface/WebKitSystemInterface.h>
+#include <CFNetwork/CFURLRequest.h>
#endif
+typedef struct {
+ CFIndex version; /* == 1 */
+ void *(*create)(CFReadStreamRef stream, void *info);
+ void (*finalize)(CFReadStreamRef stream, void *info);
+ CFStringRef (*copyDescription)(CFReadStreamRef stream, void *info);
+ Boolean (*open)(CFReadStreamRef stream, CFStreamError *error, Boolean *openComplete, void *info);
+ Boolean (*openCompleted)(CFReadStreamRef stream, CFStreamError *error, void *info);
+ CFIndex (*read)(CFReadStreamRef stream, UInt8 *buffer, CFIndex bufferLength, CFStreamError *error, Boolean *atEOF, void *info);
+ const UInt8 *(*getBuffer)(CFReadStreamRef stream, CFIndex maxBytesToRead, CFIndex *numBytesRead, CFStreamError *error, Boolean *atEOF, void *info);
+ Boolean (*canRead)(CFReadStreamRef stream, void *info);
+ void (*close)(CFReadStreamRef stream, void *info);
+ CFTypeRef (*copyProperty)(CFReadStreamRef stream, CFStringRef propertyName, void *info);
+ Boolean (*setProperty)(CFReadStreamRef stream, CFStringRef propertyName, CFTypeRef propertyValue, void *info);
+ void (*requestEvents)(CFReadStreamRef stream, CFOptionFlags streamEvents, void *info);
+ void (*schedule)(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode, void *info);
+ void (*unschedule)(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode, void *info);
+} CFReadStreamCallBacksV1;
+
+#if PLATFORM(WIN)
+#define EXTERN extern "C" __declspec(dllimport)
+#else
+#define EXTERN extern "C"
+#endif
+
+EXTERN void CFReadStreamSignalEvent(CFReadStreamRef stream, CFStreamEventType event, const void *error);
+EXTERN CFReadStreamRef CFReadStreamCreate(CFAllocatorRef alloc, const void *callbacks, void *info);
+
namespace WebCore {
-void setHTTPBody(CFMutableURLRequestRef request, PassRefPtr<FormData> formData)
+static Mutex& streamFieldsMapMutex()
{
- if (!formData) {
- wkCFURLRequestSetHTTPRequestBodyParts(request, 0);
- return;
+ DEFINE_STATIC_LOCAL(Mutex, staticMutex, ());
+ return staticMutex;
+}
+
+static void formEventCallback(CFReadStreamRef stream, CFStreamEventType type, void* context);
+
+struct FormContext {
+ RefPtr<FormData> formData;
+ unsigned long long streamLength;
+};
+
+struct FormStreamFields {
+ RefPtr<FormData> formData;
+ SchedulePairHashSet scheduledRunLoopPairs;
+ Vector<FormDataElement> remainingElements; // in reverse order
+ CFReadStreamRef currentStream;
+#if ENABLE(BLOB)
+ long long currentStreamRangeLength;
+#endif
+ char* currentData;
+ CFReadStreamRef formStream;
+ unsigned long long streamLength;
+ unsigned long long bytesSent;
+};
+
+typedef HashMap<CFReadStreamRef, FormStreamFields*> StreamFieldsMap;
+static StreamFieldsMap& streamFieldsMap()
+{
+ DEFINE_STATIC_LOCAL(StreamFieldsMap, streamFieldsMap, ());
+ return streamFieldsMap;
+}
+
+static void closeCurrentStream(FormStreamFields *form)
+{
+ if (form->currentStream) {
+ CFReadStreamClose(form->currentStream);
+ CFReadStreamSetClient(form->currentStream, kCFStreamEventNone, 0, 0);
+ CFRelease(form->currentStream);
+ form->currentStream = 0;
+#if ENABLE(BLOB)
+ form->currentStreamRangeLength = BlobDataItem::toEndOfFile;
+#endif
}
+ if (form->currentData) {
+ fastFree(form->currentData);
+ form->currentData = 0;
+ }
+}
- size_t count = formData->elements().size();
+// Return false if we cannot advance the stream. Currently the only possible failure is that the underlying file has been removed or changed since File.slice.
+static bool advanceCurrentStream(FormStreamFields* form)
+{
+ closeCurrentStream(form);
+
+ if (form->remainingElements.isEmpty())
+ return true;
+
+ // Create the new stream.
+ FormDataElement& nextInput = form->remainingElements.last();
+
+ if (nextInput.m_type == FormDataElement::data) {
+ size_t size = nextInput.m_data.size();
+ char* data = nextInput.m_data.releaseBuffer();
+ form->currentStream = CFReadStreamCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data), size, kCFAllocatorNull);
+ form->currentData = data;
+ } else {
+#if ENABLE(BLOB)
+ // Check if the file has been changed or not if required.
+ if (nextInput.m_expectedFileModificationTime != BlobDataItem::doNotCheckFileChange) {
+ time_t fileModificationTime;
+ if (!getFileModificationTime(nextInput.m_filename, fileModificationTime) || fileModificationTime != static_cast<time_t>(nextInput.m_expectedFileModificationTime))
+ return false;
+ }
+#endif
+ const String& path = nextInput.m_shouldGenerateFile ? nextInput.m_generatedFilename : nextInput.m_filename;
+ form->currentStream = CFReadStreamCreateWithFile(0, pathAsURL(path).get());
+ if (!form->currentStream) {
+ // The file must have been removed or become unreadable.
+ return false;
+ }
+#if ENABLE(BLOB)
+ if (nextInput.m_fileStart > 0) {
+ RetainPtr<CFNumberRef> position(AdoptCF, CFNumberCreate(0, kCFNumberLongLongType, &nextInput.m_fileStart));
+ CFReadStreamSetProperty(form->currentStream, kCFStreamPropertyFileCurrentOffset, position.get());
+ }
+ form->currentStreamRangeLength = nextInput.m_fileLength;
+#endif
+ }
+ form->remainingElements.removeLast();
+
+ // Set up the callback.
+ CFStreamClientContext context = { 0, form, 0, 0, 0 };
+ CFReadStreamSetClient(form->currentStream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered,
+ formEventCallback, &context);
+
+ // Schedule with the current set of run loops.
+ SchedulePairHashSet::iterator end = form->scheduledRunLoopPairs.end();
+ for (SchedulePairHashSet::iterator it = form->scheduledRunLoopPairs.begin(); it != end; ++it)
+ CFReadStreamScheduleWithRunLoop(form->currentStream, (*it)->runLoop(), (*it)->mode());
+
+ return true;
+}
+
+static bool openNextStream(FormStreamFields* form)
+{
+ // Skip over any streams we can't open.
+ if (!advanceCurrentStream(form))
+ return false;
+ while (form->currentStream && !CFReadStreamOpen(form->currentStream)) {
+ if (!advanceCurrentStream(form))
+ return false;
+ }
+ return true;
+}
+
+static void* formCreate(CFReadStreamRef stream, void* context)
+{
+ FormContext* formContext = static_cast<FormContext*>(context);
+
+ FormStreamFields* newInfo = new FormStreamFields;
+ newInfo->formData = formContext->formData.release();
+ newInfo->currentStream = 0;
+#if ENABLE(BLOB)
+ newInfo->currentStreamRangeLength = BlobDataItem::toEndOfFile;
+#endif
+ newInfo->currentData = 0;
+ newInfo->formStream = stream; // Don't retain. That would create a reference cycle.
+ newInfo->streamLength = formContext->streamLength;
+ newInfo->bytesSent = 0;
+
+ // Append in reverse order since we remove elements from the end.
+ size_t size = newInfo->formData->elements().size();
+ newInfo->remainingElements.reserveInitialCapacity(size);
+ for (size_t i = 0; i < size; ++i)
+ newInfo->remainingElements.append(newInfo->formData->elements()[size - i - 1]);
+
+ MutexLocker locker(streamFieldsMapMutex());
+ ASSERT(!streamFieldsMap().contains(stream));
+ streamFieldsMap().add(stream, newInfo);
+
+ return newInfo;
+}
+
+static void formFinishFinalizationOnMainThread(void* context)
+{
+ OwnPtr<FormStreamFields> form = adoptPtr(static_cast<FormStreamFields*>(context));
+
+ closeCurrentStream(form.get());
+}
+
+static void formFinalize(CFReadStreamRef stream, void* context)
+{
+ FormStreamFields* form = static_cast<FormStreamFields*>(context);
+
+ MutexLocker locker(streamFieldsMapMutex());
+
+ ASSERT(form->formStream == stream);
+ ASSERT(streamFieldsMap().get(stream) == context);
+
+ // Do this right away because the CFReadStreamRef is being deallocated.
+ // We can't wait to remove this from the map until we finish finalizing
+ // on the main thread because in theory the freed memory could be reused
+ // for a new CFReadStream before that runs.
+ streamFieldsMap().remove(stream);
+
+ callOnMainThread(formFinishFinalizationOnMainThread, form);
+}
+
+static Boolean formOpen(CFReadStreamRef, CFStreamError* error, Boolean* openComplete, void* context)
+{
+ FormStreamFields* form = static_cast<FormStreamFields*>(context);
+
+ bool opened = openNextStream(form);
+
+ *openComplete = opened;
+ error->error = opened ? 0 :
+#if PLATFORM(WIN)
+ ENOENT;
+#else
+ fnfErr;
+#endif
+ return opened;
+}
+
+static CFIndex formRead(CFReadStreamRef, UInt8* buffer, CFIndex bufferLength, CFStreamError* error, Boolean* atEOF, void* context)
+{
+ FormStreamFields* form = static_cast<FormStreamFields*>(context);
+
+ while (form->currentStream) {
+ CFIndex bytesToRead = bufferLength;
+#if ENABLE(BLOB)
+ if (form->currentStreamRangeLength != BlobDataItem::toEndOfFile && form->currentStreamRangeLength < bytesToRead)
+ bytesToRead = static_cast<CFIndex>(form->currentStreamRangeLength);
+#endif
+ CFIndex bytesRead = CFReadStreamRead(form->currentStream, buffer, bytesToRead);
+ if (bytesRead < 0) {
+ *error = CFReadStreamGetError(form->currentStream);
+ return -1;
+ }
+ if (bytesRead > 0) {
+ error->error = 0;
+ *atEOF = FALSE;
+ form->bytesSent += bytesRead;
+#if ENABLE(BLOB)
+ if (form->currentStreamRangeLength != BlobDataItem::toEndOfFile)
+ form->currentStreamRangeLength -= bytesRead;
+#endif
+
+ return bytesRead;
+ }
+ openNextStream(form);
+ }
+
+ error->error = 0;
+ *atEOF = TRUE;
+ return 0;
+}
+
+static Boolean formCanRead(CFReadStreamRef stream, void* context)
+{
+ FormStreamFields* form = static_cast<FormStreamFields*>(context);
+
+ while (form->currentStream && CFReadStreamGetStatus(form->currentStream) == kCFStreamStatusAtEnd)
+ openNextStream(form);
+
+ if (!form->currentStream) {
+ CFReadStreamSignalEvent(stream, kCFStreamEventEndEncountered, 0);
+ return FALSE;
+ }
+ return CFReadStreamHasBytesAvailable(form->currentStream);
+}
+
+static void formClose(CFReadStreamRef, void* context)
+{
+ FormStreamFields* form = static_cast<FormStreamFields*>(context);
+
+ closeCurrentStream(form);
+}
+
+static void formSchedule(CFReadStreamRef, CFRunLoopRef runLoop, CFStringRef runLoopMode, void* context)
+{
+ FormStreamFields* form = static_cast<FormStreamFields*>(context);
+
+ if (form->currentStream)
+ CFReadStreamScheduleWithRunLoop(form->currentStream, runLoop, runLoopMode);
+ form->scheduledRunLoopPairs.add(SchedulePair::create(runLoop, runLoopMode));
+}
+
+static void formUnschedule(CFReadStreamRef, CFRunLoopRef runLoop, CFStringRef runLoopMode, void* context)
+{
+ FormStreamFields* form = static_cast<FormStreamFields*>(context);
+
+ if (form->currentStream)
+ CFReadStreamUnscheduleFromRunLoop(form->currentStream, runLoop, runLoopMode);
+ form->scheduledRunLoopPairs.remove(SchedulePair::create(runLoop, runLoopMode));
+}
- if (count == 0)
+static void formEventCallback(CFReadStreamRef stream, CFStreamEventType type, void* context)
+{
+ FormStreamFields* form = static_cast<FormStreamFields*>(context);
+
+ switch (type) {
+ case kCFStreamEventHasBytesAvailable:
+ CFReadStreamSignalEvent(form->formStream, kCFStreamEventHasBytesAvailable, 0);
+ break;
+ case kCFStreamEventErrorOccurred: {
+ CFStreamError readStreamError = CFReadStreamGetError(stream);
+ CFReadStreamSignalEvent(form->formStream, kCFStreamEventErrorOccurred, &readStreamError);
+ break;
+ }
+ case kCFStreamEventEndEncountered:
+ openNextStream(form);
+ if (!form->currentStream)
+ CFReadStreamSignalEvent(form->formStream, kCFStreamEventEndEncountered, 0);
+ break;
+ case kCFStreamEventNone:
+ LOG_ERROR("unexpected kCFStreamEventNone");
+ break;
+ case kCFStreamEventOpenCompleted:
+ LOG_ERROR("unexpected kCFStreamEventOpenCompleted");
+ break;
+ case kCFStreamEventCanAcceptBytes:
+ LOG_ERROR("unexpected kCFStreamEventCanAcceptBytes");
+ break;
+ }
+}
+
+void setHTTPBody(CFMutableURLRequestRef request, PassRefPtr<FormData> prpFormData)
+{
+ RefPtr<FormData> formData = prpFormData;
+
+ if (!formData)
return;
+
+ size_t count = formData->elements().size();
// Handle the common special case of one piece of form data, with no files.
- if (count == 1) {
+ if (count == 1 && !formData->alwaysStream()) {
const FormDataElement& element = formData->elements()[0];
if (element.m_type == FormDataElement::data) {
- CFDataRef data = CFDataCreate(0, reinterpret_cast<const UInt8 *>(element.m_data.data()), element.m_data.size());
- CFURLRequestSetHTTPRequestBody(request, data);
- CFRelease(data);
+ RetainPtr<CFDataRef> data = adoptCF(CFDataCreate(0, reinterpret_cast<const UInt8 *>(element.m_data.data()), element.m_data.size()));
+ CFURLRequestSetHTTPRequestBody(request, data.get());
return;
}
}
- RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks));
+#if ENABLE(BLOB)
+ // Check if there is a blob in the form data.
+ bool hasBlob = false;
+ for (size_t i = 0; i < count; ++i) {
+ const FormDataElement& element = formData->elements()[i];
+ if (element.m_type == FormDataElement::encodedBlob) {
+ hasBlob = true;
+ break;
+ }
+ }
+
+ // If yes, we have to resolve all the blob references and regenerate the form data with only data and file types.
+ if (hasBlob) {
+ RefPtr<FormData> newFormData = FormData::create();
+ newFormData->setAlwaysStream(formData->alwaysStream());
+ newFormData->setIdentifier(formData->identifier());
+ for (size_t i = 0; i < count; ++i) {
+ const FormDataElement& element = formData->elements()[i];
+ if (element.m_type == FormDataElement::data)
+ newFormData->appendData(element.m_data.data(), element.m_data.size());
+ else if (element.m_type == FormDataElement::encodedFile)
+ newFormData->appendFile(element.m_filename, element.m_shouldGenerateFile);
+ else {
+ ASSERT(element.m_type == FormDataElement::encodedBlob);
+ RefPtr<BlobStorageData> blobData = static_cast<BlobRegistryImpl&>(blobRegistry()).getBlobDataFromURL(KURL(ParsedURLString, element.m_blobURL));
+ if (blobData) {
+ for (size_t j = 0; j < blobData->items().size(); ++j) {
+ const BlobDataItem& blobItem = blobData->items()[j];
+ if (blobItem.type == BlobDataItem::Data)
+ newFormData->appendData(blobItem.data->data() + static_cast<int>(blobItem.offset), static_cast<int>(blobItem.length));
+ else {
+ ASSERT(blobItem.type == BlobDataItem::File);
+ newFormData->appendFileRange(blobItem.path, blobItem.offset, blobItem.length, blobItem.expectedModificationTime);
+ }
+ }
+ }
+ }
+ }
+ formData = newFormData.release();
+ count = formData->elements().size();
+ }
+#endif
+ // Precompute the content length so NSURLConnection doesn't use chunked mode.
+ long long length = 0;
for (size_t i = 0; i < count; ++i) {
const FormDataElement& element = formData->elements()[i];
- if (element.m_type == FormDataElement::data) {
- RetainPtr<CFDataRef> data(AdoptCF, CFDataCreate(0, reinterpret_cast<const UInt8*>(element.m_data.data()), element.m_data.size()));
- CFArrayAppendValue(array.get(), data.get());
- } else {
- RetainPtr<CFStringRef> filename(AdoptCF, element.m_filename.createCFString());
- CFArrayAppendValue(array.get(), filename.get());
+ if (element.m_type == FormDataElement::data)
+ length += element.m_data.size();
+ else {
+#if ENABLE(BLOB)
+ // If we're sending the file range, use the existing range length for now. We will detect if the file has been changed right before we read the file and abort the operation if necessary.
+ if (element.m_fileLength != BlobDataItem::toEndOfFile) {
+ length += element.m_fileLength;
+ continue;
+ }
+#endif
+ long long fileSize;
+ if (getFileSize(element.m_shouldGenerateFile ? element.m_generatedFilename : element.m_filename, fileSize))
+ length += fileSize;
}
}
- wkCFURLRequestSetHTTPRequestBodyParts(request, array.get());
+ // Set the length.
+ RetainPtr<CFStringRef> lengthString = adoptCF(CFStringCreateWithFormat(0, 0, CFSTR("%lld"), length));
+ CFURLRequestSetHTTPHeaderFieldValue(request, CFSTR("Content-Length"), lengthString.get());
+
+ // Create and set the stream.
+
+ // Pass the length along with the formData so it does not have to be recomputed.
+ FormContext formContext = { formData.release(), length };
+
+ CFReadStreamCallBacksV1 callBacks = { 1, formCreate, formFinalize, 0, formOpen, 0, formRead, 0, formCanRead, formClose, 0, 0, 0, formSchedule, formUnschedule
+ };
+ RetainPtr<CFReadStreamRef> stream = adoptCF(CFReadStreamCreate(0, static_cast<const void*>(&callBacks), &formContext));
+
+ CFURLRequestSetHTTPRequestBodyStream(request, stream.get());
}
-PassRefPtr<FormData> httpBodyFromRequest(CFURLRequestRef request)
+FormData* httpBodyFromStream(CFReadStreamRef stream)
{
- RetainPtr<CFDataRef> bodyData(AdoptCF, CFURLRequestCopyHTTPRequestBody(request));
- if (bodyData)
- return FormData::create(CFDataGetBytePtr(bodyData.get()), CFDataGetLength(bodyData.get()));
-
- RetainPtr<CFArrayRef> bodyParts(AdoptCF, wkCFURLRequestCopyHTTPRequestBodyParts(request));
- if (bodyParts) {
- RefPtr<FormData> formData = FormData::create();
-
- CFIndex count = CFArrayGetCount(bodyParts.get());
- for (CFIndex i = 0; i < count; i++) {
- CFTypeRef bodyPart = CFArrayGetValueAtIndex(bodyParts.get(), i);
- CFTypeID typeID = CFGetTypeID(bodyPart);
- if (typeID == CFStringGetTypeID()) {
- String filename = (CFStringRef)bodyPart;
- formData->appendFile(filename);
- } else if (typeID == CFDataGetTypeID()) {
- CFDataRef data = (CFDataRef)bodyPart;
- formData->appendData(CFDataGetBytePtr(data), CFDataGetLength(data));
- } else
- ASSERT_NOT_REACHED();
- }
- return formData.release();
- }
+ if (!stream)
+ return 0;
- // FIXME: what to do about arbitrary body streams?
- return 0;
+ MutexLocker locker(streamFieldsMapMutex());
+ FormStreamFields* formStream = streamFieldsMap().get(stream);
+ if (!formStream)
+ return 0;
+ return formStream->formData.get();
}
-} // namespace WebCore
+PassRefPtr<FormData> httpBodyFromRequest(CFURLRequestRef request)
+{
+ RetainPtr<CFReadStreamRef> bodyStream = adoptCF(CFURLRequestCopyHTTPRequestBodyStream(request));
+ return httpBodyFromStream(bodyStream.get());
+}
-#endif // USE(CFNETWORK)
+} // namespace WebCore
diff --git a/Source/WebCore/platform/network/cf/FormDataStreamCFNet.h b/Source/WebCore/platform/network/cf/FormDataStreamCFNet.h
index 726003283..b76b123a4 100644
--- a/Source/WebCore/platform/network/cf/FormDataStreamCFNet.h
+++ b/Source/WebCore/platform/network/cf/FormDataStreamCFNet.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,20 +29,21 @@
#ifndef FormDataStreamCFNet_h
#define FormDataStreamCFNet_h
-#if USE(CFNETWORK)
-
-#include <CoreFoundation/CoreFoundation.h>
#include <wtf/Forward.h>
typedef struct _CFURLRequest* CFMutableURLRequestRef;
+typedef struct __CFReadStream* CFReadStreamRef;
typedef const struct _CFURLRequest* CFURLRequestRef;
namespace WebCore {
- class FormData;
- void setHTTPBody(CFMutableURLRequestRef, PassRefPtr<FormData>);
- PassRefPtr<FormData> httpBodyFromRequest(CFURLRequestRef);
-}
-#endif // USE(CFNETWORK)
+class FormData;
+
+void setHTTPBody(CFMutableURLRequestRef, PassRefPtr<FormData>);
+PassRefPtr<FormData> httpBodyFromRequest(CFURLRequestRef);
+
+FormData* httpBodyFromStream(CFReadStreamRef);
+
+} // namespace WebCore
#endif // FormDataStreamCFNet_h
diff --git a/Source/WebCore/platform/network/cf/ResourceErrorCF.cpp b/Source/WebCore/platform/network/cf/ResourceErrorCF.cpp
index 58c729fa0..aa318e665 100644
--- a/Source/WebCore/platform/network/cf/ResourceErrorCF.cpp
+++ b/Source/WebCore/platform/network/cf/ResourceErrorCF.cpp
@@ -148,7 +148,7 @@ CFErrorRef ResourceError::cfError() const
if (!m_failingURL.isEmpty()) {
RetainPtr<CFStringRef> failingURLString(AdoptCF, m_failingURL.createCFString());
CFDictionarySetValue(userInfo.get(), failingURLStringKey, failingURLString.get());
- RetainPtr<CFURLRef> url(AdoptCF, KURL(ParsedURLString, m_failingURL).createCFURL());
+ RetainPtr<CFURLRef> url(AdoptCF, CFURLCreateWithString(0, failingURLString.get(), 0));
CFDictionarySetValue(userInfo.get(), failingURLKey, url.get());
}
diff --git a/Source/WebCore/platform/network/chromium/DNSChromium.cpp b/Source/WebCore/platform/network/chromium/DNSChromium.cpp
index 59714e36f..a7a8d9abf 100644
--- a/Source/WebCore/platform/network/chromium/DNSChromium.cpp
+++ b/Source/WebCore/platform/network/chromium/DNSChromium.cpp
@@ -26,19 +26,13 @@
#include "config.h"
#include "DNS.h"
-#include "PlatformSupport.h"
-#include "ResourceHandle.h"
+#include <public/Platform.h>
namespace WebCore {
void prefetchDNS(const String& hostname)
{
- PlatformSupport::prefetchDNS(hostname);
-}
-
-void ResourceHandle::prepareForURL(const KURL& url)
-{
- return prefetchDNS(url.host());
+ WebKit::Platform::current()->prefetchHostName(hostname);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/chromium/ResourceHandle.cpp b/Source/WebCore/platform/network/chromium/ResourceHandle.cpp
new file mode 100644
index 000000000..b753da6e5
--- /dev/null
+++ b/Source/WebCore/platform/network/chromium/ResourceHandle.cpp
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ResourceHandle.h"
+
+#include "ResourceHandleClient.h"
+#include "ResourceHandleInternal.h"
+#include "ResourceRequest.h"
+#include "SharedBuffer.h"
+#include "WrappedResourceRequest.h"
+#include "WrappedResourceResponse.h"
+#include <public/Platform.h>
+#include <public/WebURLError.h>
+#include <public/WebURLLoader.h>
+#include <public/WebURLLoaderClient.h>
+#include <public/WebURLRequest.h>
+#include <public/WebURLResponse.h>
+
+using namespace WebKit;
+
+namespace WebCore {
+
+// ResourceHandleInternal -----------------------------------------------------
+ResourceHandleInternal::ResourceHandleInternal(const ResourceRequest& request, ResourceHandleClient* client)
+ : m_request(request)
+ , m_owner(0)
+ , m_client(client)
+ , m_state(ConnectionStateNew)
+{
+}
+
+void ResourceHandleInternal::start()
+{
+ if (m_state != ConnectionStateNew)
+ CRASH();
+ m_state = ConnectionStateStarted;
+
+ m_loader = adoptPtr(Platform::current()->createURLLoader());
+ ASSERT(m_loader);
+
+ WrappedResourceRequest wrappedRequest(m_request);
+ wrappedRequest.setAllowStoredCredentials(allowStoredCredentials());
+ m_loader->loadAsynchronously(wrappedRequest, this);
+}
+
+void ResourceHandleInternal::cancel()
+{
+ m_state = ConnectionStateCanceled;
+ m_loader->cancel();
+
+ // Do not make any further calls to the client.
+ m_client = 0;
+}
+
+void ResourceHandleInternal::setDefersLoading(bool value)
+{
+ m_loader->setDefersLoading(value);
+}
+
+bool ResourceHandleInternal::allowStoredCredentials() const
+{
+ return m_client && m_client->shouldUseCredentialStorage(m_owner);
+}
+
+void ResourceHandleInternal::willSendRequest(
+ WebURLLoader*, WebURLRequest& request, const WebURLResponse& response)
+{
+ ASSERT(m_client);
+ ASSERT(!request.isNull());
+ ASSERT(!response.isNull());
+ m_client->willSendRequest(m_owner, request.toMutableResourceRequest(), response.toResourceResponse());
+}
+
+void ResourceHandleInternal::didSendData(
+ WebURLLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
+{
+ ASSERT(m_client);
+ m_client->didSendData(m_owner, bytesSent, totalBytesToBeSent);
+}
+
+void ResourceHandleInternal::didReceiveResponse(WebURLLoader*, const WebURLResponse& response)
+{
+ ASSERT(m_client);
+ ASSERT(!response.isNull());
+ bool isMultipart = response.isMultipartPayload();
+ bool isValidStateTransition = (m_state == ConnectionStateStarted || m_state == ConnectionStateReceivedResponse);
+ // In the case of multipart loads, calls to didReceiveData & didReceiveResponse can be interleaved.
+ if (!isMultipart && !isValidStateTransition)
+ CRASH();
+ m_state = ConnectionStateReceivedResponse;
+ m_client->didReceiveResponse(m_owner, response.toResourceResponse());
+}
+
+void ResourceHandleInternal::didDownloadData(WebURLLoader*, int dataLength)
+{
+ ASSERT(m_client);
+ if (m_state != ConnectionStateReceivedResponse)
+ CRASH();
+
+ m_client->didDownloadData(m_owner, dataLength);
+}
+
+void ResourceHandleInternal::didReceiveData(WebURLLoader*, const char* data, int dataLength, int encodedDataLength)
+{
+ ASSERT(m_client);
+ if (m_state != ConnectionStateReceivedResponse && m_state != ConnectionStateReceivingData)
+ CRASH();
+ m_state = ConnectionStateReceivingData;
+
+ m_client->didReceiveData(m_owner, data, dataLength, encodedDataLength);
+}
+
+void ResourceHandleInternal::didReceiveCachedMetadata(WebURLLoader*, const char* data, int dataLength)
+{
+ ASSERT(m_client);
+ if (m_state != ConnectionStateReceivedResponse && m_state != ConnectionStateReceivingData)
+ CRASH();
+
+ m_client->didReceiveCachedMetadata(m_owner, data, dataLength);
+}
+
+void ResourceHandleInternal::didFinishLoading(WebURLLoader*, double finishTime)
+{
+ ASSERT(m_client);
+ if (m_state != ConnectionStateReceivedResponse && m_state != ConnectionStateReceivingData)
+ CRASH();
+ m_state = ConnectionStateFinishedLoading;
+ m_client->didFinishLoading(m_owner, finishTime);
+}
+
+void ResourceHandleInternal::didFail(WebURLLoader*, const WebURLError& error)
+{
+ ASSERT(m_client);
+ m_state = ConnectionStateFailed;
+ m_client->didFail(m_owner, error);
+}
+
+ResourceHandleInternal* ResourceHandleInternal::FromResourceHandle(ResourceHandle* handle)
+{
+ return handle->d.get();
+}
+
+// ResourceHandle -------------------------------------------------------------
+
+ResourceHandle::ResourceHandle(const ResourceRequest& request,
+ ResourceHandleClient* client,
+ bool defersLoading,
+ bool shouldContentSniff)
+ : d(adoptPtr(new ResourceHandleInternal(request, client)))
+{
+ d->setOwner(this);
+
+ // FIXME: Figure out what to do with the bool params.
+}
+
+PassRefPtr<ResourceHandle> ResourceHandle::create(NetworkingContext* context,
+ const ResourceRequest& request,
+ ResourceHandleClient* client,
+ bool defersLoading,
+ bool shouldContentSniff)
+{
+ RefPtr<ResourceHandle> newHandle = adoptRef(new ResourceHandle(
+ request, client, defersLoading, shouldContentSniff));
+
+ if (newHandle->start(context))
+ return newHandle.release();
+
+ return 0;
+}
+
+ResourceRequest& ResourceHandle::firstRequest()
+{
+ return d->request();
+}
+
+ResourceHandleClient* ResourceHandle::client() const
+{
+ return d->client();
+}
+
+void ResourceHandle::setClient(ResourceHandleClient* client)
+{
+ d->setClient(client);
+}
+
+void ResourceHandle::setDefersLoading(bool value)
+{
+ d->setDefersLoading(value);
+}
+
+bool ResourceHandle::start(NetworkingContext* context)
+{
+ d->start();
+ return true;
+}
+
+bool ResourceHandle::hasAuthenticationChallenge() const
+{
+ return false;
+}
+
+void ResourceHandle::clearAuthentication()
+{
+}
+
+void ResourceHandle::cancel()
+{
+ d->cancel();
+}
+
+ResourceHandle::~ResourceHandle()
+{
+ d->setOwner(0);
+}
+
+bool ResourceHandle::loadsBlocked()
+{
+ return false; // This seems to be related to sync XMLHttpRequest...
+}
+
+// static
+void ResourceHandle::loadResourceSynchronously(NetworkingContext* context,
+ const ResourceRequest& request,
+ StoredCredentials storedCredentials,
+ ResourceError& error,
+ ResourceResponse& response,
+ Vector<char>& data)
+{
+ OwnPtr<WebURLLoader> loader = adoptPtr(Platform::current()->createURLLoader());
+ ASSERT(loader);
+
+ WrappedResourceRequest requestIn(request);
+ requestIn.setAllowStoredCredentials(storedCredentials == AllowStoredCredentials);
+ WrappedResourceResponse responseOut(response);
+ WebURLError errorOut;
+ WebData dataOut;
+
+ loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut);
+
+ error = errorOut;
+ data.clear();
+ data.append(dataOut.data(), dataOut.size());
+}
+
+// static
+bool ResourceHandle::willLoadFromCache(ResourceRequest& request, Frame*)
+{
+ // This method is used to determine if a POST request can be repeated from
+ // cache, but you cannot really know until you actually try to read from the
+ // cache. Even if we checked now, something else could come along and wipe
+ // out the cache entry by the time we fetch it.
+ //
+ // So, we always say yes here, to prevent the FrameLoader from initiating a
+ // reload. Then in FrameLoaderClientImpl::dispatchWillSendRequest, we
+ // fix-up the cache policy of the request to force a load from the cache.
+ //
+ ASSERT(request.httpMethod() == "POST");
+ return true;
+}
+
+// static
+void ResourceHandle::cacheMetadata(const ResourceResponse& response, const Vector<char>& data)
+{
+ WebKit::Platform::current()->cacheMetadata(response.url(), response.responseTime(), data.data(), data.size());
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/network/chromium/ResourceHandleInternal.h b/Source/WebCore/platform/network/chromium/ResourceHandleInternal.h
new file mode 100644
index 000000000..9eefee8b2
--- /dev/null
+++ b/Source/WebCore/platform/network/chromium/ResourceHandleInternal.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ResourceHandleInternal_h
+#define ResourceHandleInternal_h
+
+#include "ResourceRequest.h"
+#include <public/WebCommon.h>
+#include <public/WebURLLoader.h>
+#include <public/WebURLLoaderClient.h>
+
+namespace WebCore {
+
+class ResourceHandle;
+class ResourceHandleClient;
+
+class ResourceHandleInternal : public WebKit::WebURLLoaderClient {
+public:
+ ResourceHandleInternal(const ResourceRequest&, ResourceHandleClient*);
+
+ virtual ~ResourceHandleInternal() { }
+
+ void start();
+ void cancel();
+ void setDefersLoading(bool);
+ bool allowStoredCredentials() const;
+
+ // WebURLLoaderClient methods:
+ virtual void willSendRequest(WebKit::WebURLLoader*, WebKit::WebURLRequest&, const WebKit::WebURLResponse&);
+ virtual void didSendData(WebKit::WebURLLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent);
+ virtual void didReceiveResponse(WebKit::WebURLLoader*, const WebKit::WebURLResponse&);
+ virtual void didDownloadData(WebKit::WebURLLoader*, int dataLength);
+ virtual void didReceiveData(WebKit::WebURLLoader*, const char* data, int dataLength, int encodedDataLength);
+
+ virtual void didReceiveCachedMetadata(WebKit::WebURLLoader*, const char* data, int dataLength);
+ virtual void didFinishLoading(WebKit::WebURLLoader*, double finishTime);
+ virtual void didFail(WebKit::WebURLLoader*, const WebKit::WebURLError&);
+
+ enum ConnectionState {
+ ConnectionStateNew,
+ ConnectionStateStarted,
+ ConnectionStateReceivedResponse,
+ ConnectionStateReceivingData,
+ ConnectionStateFinishedLoading,
+ ConnectionStateCanceled,
+ ConnectionStateFailed,
+ };
+
+ void setOwner(ResourceHandle* owner) { m_owner = owner; }
+ ResourceRequest& request() { return m_request; }
+ ResourceHandleClient* client() const { return m_client; }
+ void setClient(ResourceHandleClient* client) { m_client = client; }
+ WebKit::WebURLLoader* loader() const { return m_loader.get(); }
+
+ static ResourceHandleInternal* FromResourceHandle(ResourceHandle*);
+
+private:
+ ResourceRequest m_request;
+ ResourceHandle* m_owner;
+ ResourceHandleClient* m_client;
+ OwnPtr<WebKit::WebURLLoader> m_loader;
+
+ // Used for sanity checking to make sure we don't experience illegal state
+ // transitions.
+ ConnectionState m_state;
+};
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/platform/network/mac/FormDataStreamMac.h b/Source/WebCore/platform/network/mac/FormDataStreamMac.h
index 4bc996859..54d390ad3 100644
--- a/Source/WebCore/platform/network/mac/FormDataStreamMac.h
+++ b/Source/WebCore/platform/network/mac/FormDataStreamMac.h
@@ -31,21 +31,18 @@
#if !USE(CFNETWORK)
-#include "FormData.h"
+#include <wtf/Forward.h>
+@class NSInputStream;
@class NSMutableURLRequest;
namespace WebCore {
class FormData;
- class ResourceHandle;
void setHTTPBody(NSMutableURLRequest *, PassRefPtr<FormData>);
FormData* httpBodyFromStream(NSInputStream *);
- void associateStreamWithResourceHandle(NSInputStream *, ResourceHandle*);
- void disassociateStreamWithResourceHandle(NSInputStream *);
-
} // namespace WebCore
#endif // !USE(CFNETWORK)
diff --git a/Source/WebCore/platform/network/mac/FormDataStreamMac.mm b/Source/WebCore/platform/network/mac/FormDataStreamMac.mm
index b82ddf238..2e6538dd0 100644
--- a/Source/WebCore/platform/network/mac/FormDataStreamMac.mm
+++ b/Source/WebCore/platform/network/mac/FormDataStreamMac.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2006, 2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2008, 2011, 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,492 +26,29 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* originally written by Becky Willrich, additional code by Darin Adler */
-
#import "config.h"
#import "FormDataStreamMac.h"
#if !USE(CFNETWORK)
-#import "BlobRegistryImpl.h"
-#import "FileSystem.h"
#import "FormData.h"
-#import "ResourceHandle.h"
-#import "ResourceHandleClient.h"
-#import "SchedulePair.h"
-#import "WebCoreSystemInterface.h"
-#import <sys/stat.h>
-#import <sys/types.h>
-#import <wtf/Assertions.h>
-#import <wtf/HashMap.h>
-#import <wtf/MainThread.h>
-#import <wtf/StdLibExtras.h>
-#import <wtf/Threading.h>
+#import "FormDataStreamCFNet.h"
+#import <wtf/PassRefPtr.h>
-#if PLATFORM(IOS)
-#import <MacErrors.h>
-#else
-#import <CoreServices/CoreServices.h>
-#endif
+@interface NSURLRequest (WebNSURLRequestDetails)
+- (CFURLRequestRef)_CFURLRequest;
+@end
namespace WebCore {
-static Mutex& streamFieldsMapMutex()
-{
- DEFINE_STATIC_LOCAL(Mutex, staticMutex, ());
- return staticMutex;
-}
-
-static NSMapTable *streamFieldsMap()
-{
- static NSMapTable *streamFieldsMap = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 1);
- return streamFieldsMap;
-}
-
-typedef HashMap<CFReadStreamRef, RefPtr<ResourceHandle> > StreamResourceHandleMap;
-static StreamResourceHandleMap& getStreamResourceHandleMap()
-{
- DEFINE_STATIC_LOCAL(StreamResourceHandleMap, streamResourceHandleMap, ());
- return streamResourceHandleMap;
-}
-
-void associateStreamWithResourceHandle(NSInputStream *stream, ResourceHandle* resourceHandle)
-{
- ASSERT(isMainThread());
-
- ASSERT(resourceHandle);
-
- if (!stream)
- return;
-
- {
- MutexLocker locker(streamFieldsMapMutex());
- if (!NSMapGet(streamFieldsMap(), stream))
- return;
- }
-
- ASSERT(!getStreamResourceHandleMap().contains((CFReadStreamRef)stream));
- getStreamResourceHandleMap().set((CFReadStreamRef)stream, resourceHandle);
-}
-
-void disassociateStreamWithResourceHandle(NSInputStream *stream)
-{
- ASSERT(isMainThread());
-
- if (!stream)
- return;
-
- getStreamResourceHandleMap().remove((CFReadStreamRef)stream);
-}
-
-struct DidSendDataCallbackData {
- DidSendDataCallbackData(CFReadStreamRef stream_, unsigned long long bytesSent_, unsigned long long streamLength_)
- : stream(stream_)
- , bytesSent(bytesSent_)
- , streamLength(streamLength_)
- {
- }
-
- CFReadStreamRef stream;
- unsigned long long bytesSent;
- unsigned long long streamLength;
-};
-
-static void performDidSendDataCallback(void* context)
-{
- ASSERT(isMainThread());
-
- DidSendDataCallbackData* data = static_cast<DidSendDataCallbackData*>(context);
- ResourceHandle* resourceHandle = getStreamResourceHandleMap().get(data->stream).get();
-
- if (resourceHandle && resourceHandle->client())
- resourceHandle->client()->didSendData(resourceHandle, data->bytesSent, data->streamLength);
-
- delete data;
-}
-
-static void formEventCallback(CFReadStreamRef stream, CFStreamEventType type, void* context);
-
-struct FormContext {
- RefPtr<FormData> formData;
- unsigned long long streamLength;
-};
-
-struct FormStreamFields {
- RefPtr<FormData> formData;
- SchedulePairHashSet scheduledRunLoopPairs;
- Vector<FormDataElement> remainingElements; // in reverse order
- CFReadStreamRef currentStream;
-#if ENABLE(BLOB)
- long long currentStreamRangeLength;
-#endif
- char* currentData;
- CFReadStreamRef formStream;
- unsigned long long streamLength;
- unsigned long long bytesSent;
-};
-
-static void closeCurrentStream(FormStreamFields *form)
-{
- if (form->currentStream) {
- CFReadStreamClose(form->currentStream);
- CFReadStreamSetClient(form->currentStream, kCFStreamEventNone, NULL, NULL);
- CFRelease(form->currentStream);
- form->currentStream = NULL;
-#if ENABLE(BLOB)
- form->currentStreamRangeLength = BlobDataItem::toEndOfFile;
-#endif
- }
- if (form->currentData) {
- fastFree(form->currentData);
- form->currentData = 0;
- }
-}
-
-// Return false if we cannot advance the stream. Currently the only possible failure is that the underlying file has been removed or changed since File.slice.
-static bool advanceCurrentStream(FormStreamFields* form)
-{
- closeCurrentStream(form);
-
- if (form->remainingElements.isEmpty())
- return true;
-
- // Create the new stream.
- FormDataElement& nextInput = form->remainingElements.last();
-
- if (nextInput.m_type == FormDataElement::data) {
- size_t size = nextInput.m_data.size();
- char* data = nextInput.m_data.releaseBuffer();
- form->currentStream = CFReadStreamCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data), size, kCFAllocatorNull);
- form->currentData = data;
- } else {
-#if ENABLE(BLOB)
- // Check if the file has been changed or not if required.
- if (nextInput.m_expectedFileModificationTime != BlobDataItem::doNotCheckFileChange) {
- time_t fileModificationTime;
- if (!getFileModificationTime(nextInput.m_filename, fileModificationTime) || fileModificationTime != static_cast<time_t>(nextInput.m_expectedFileModificationTime))
- return false;
- }
-#endif
- const String& path = nextInput.m_shouldGenerateFile ? nextInput.m_generatedFilename : nextInput.m_filename;
- form->currentStream = CFReadStreamCreateWithFile(0, pathAsURL(path).get());
- if (!form->currentStream) {
- // The file must have been removed or become unreadable.
- return false;
- }
-#if ENABLE(BLOB)
- if (nextInput.m_fileStart > 0) {
- RetainPtr<CFNumberRef> position(AdoptCF, CFNumberCreate(0, kCFNumberLongLongType, &nextInput.m_fileStart));
- CFReadStreamSetProperty(form->currentStream, kCFStreamPropertyFileCurrentOffset, position.get());
- }
- form->currentStreamRangeLength = nextInput.m_fileLength;
-#endif
- }
- form->remainingElements.removeLast();
-
- // Set up the callback.
- CFStreamClientContext context = { 0, form, NULL, NULL, NULL };
- CFReadStreamSetClient(form->currentStream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered,
- formEventCallback, &context);
-
- // Schedule with the current set of run loops.
- SchedulePairHashSet::iterator end = form->scheduledRunLoopPairs.end();
- for (SchedulePairHashSet::iterator it = form->scheduledRunLoopPairs.begin(); it != end; ++it)
- CFReadStreamScheduleWithRunLoop(form->currentStream, (*it)->runLoop(), (*it)->mode());
-
- return true;
-}
-
-static bool openNextStream(FormStreamFields* form)
-{
- // Skip over any streams we can't open.
- if (!advanceCurrentStream(form))
- return false;
- while (form->currentStream && !CFReadStreamOpen(form->currentStream)) {
- if (!advanceCurrentStream(form))
- return false;
- }
- return true;
-}
-
-static void* formCreate(CFReadStreamRef stream, void* context)
-{
- FormContext* formContext = static_cast<FormContext*>(context);
-
- FormStreamFields* newInfo = new FormStreamFields;
- newInfo->formData = formContext->formData.release();
- newInfo->currentStream = NULL;
-#if ENABLE(BLOB)
- newInfo->currentStreamRangeLength = BlobDataItem::toEndOfFile;
-#endif
- newInfo->currentData = 0;
- newInfo->formStream = stream; // Don't retain. That would create a reference cycle.
- newInfo->streamLength = formContext->streamLength;
- newInfo->bytesSent = 0;
-
- // Append in reverse order since we remove elements from the end.
- size_t size = newInfo->formData->elements().size();
- newInfo->remainingElements.reserveInitialCapacity(size);
- for (size_t i = 0; i < size; ++i)
- newInfo->remainingElements.append(newInfo->formData->elements()[size - i - 1]);
-
- MutexLocker locker(streamFieldsMapMutex());
- ASSERT(!NSMapGet(streamFieldsMap(), stream));
- NSMapInsertKnownAbsent(streamFieldsMap(), stream, newInfo);
-
- return newInfo;
-}
-
-static void formFinishFinalizationOnMainThread(void* context)
-{
- OwnPtr<FormStreamFields> form = adoptPtr(static_cast<FormStreamFields*>(context));
-
- closeCurrentStream(form.get());
-}
-
-static void formFinalize(CFReadStreamRef stream, void* context)
-{
- FormStreamFields* form = static_cast<FormStreamFields*>(context);
-
- MutexLocker locker(streamFieldsMapMutex());
-
- ASSERT(form->formStream == stream);
- ASSERT(NSMapGet(streamFieldsMap(), stream) == context);
-
- // Do this right away because the CFReadStreamRef is being deallocated.
- // We can't wait to remove this from the map until we finish finalizing
- // on the main thread because in theory the freed memory could be reused
- // for a new CFReadStream before that runs.
- NSMapRemove(streamFieldsMap(), stream);
-
- callOnMainThread(formFinishFinalizationOnMainThread, form);
-}
-
-static Boolean formOpen(CFReadStreamRef, CFStreamError* error, Boolean* openComplete, void* context)
-{
- FormStreamFields* form = static_cast<FormStreamFields*>(context);
-
- bool opened = openNextStream(form);
-
- *openComplete = opened;
- error->error = opened ? 0 : fnfErr;
- return opened;
-}
-
-static CFIndex formRead(CFReadStreamRef stream, UInt8* buffer, CFIndex bufferLength, CFStreamError* error, Boolean* atEOF, void* context)
-{
- FormStreamFields* form = static_cast<FormStreamFields*>(context);
-
- while (form->currentStream) {
- CFIndex bytesToRead = bufferLength;
-#if ENABLE(BLOB)
- if (form->currentStreamRangeLength != BlobDataItem::toEndOfFile && form->currentStreamRangeLength < bytesToRead)
- bytesToRead = static_cast<CFIndex>(form->currentStreamRangeLength);
-#endif
- CFIndex bytesRead = CFReadStreamRead(form->currentStream, buffer, bytesToRead);
- if (bytesRead < 0) {
- *error = CFReadStreamGetError(form->currentStream);
- return -1;
- }
- if (bytesRead > 0) {
- error->error = 0;
- *atEOF = FALSE;
- form->bytesSent += bytesRead;
-#if ENABLE(BLOB)
- if (form->currentStreamRangeLength != BlobDataItem::toEndOfFile)
- form->currentStreamRangeLength -= bytesRead;
-#endif
-
- if (!ResourceHandle::didSendBodyDataDelegateExists()) {
- // FIXME: Figure out how to only do this when a ResourceHandleClient is available.
- DidSendDataCallbackData* data = new DidSendDataCallbackData(stream, form->bytesSent, form->streamLength);
- callOnMainThread(performDidSendDataCallback, data);
- }
-
- return bytesRead;
- }
- openNextStream(form);
- }
-
- error->error = 0;
- *atEOF = TRUE;
- return 0;
-}
-
-static Boolean formCanRead(CFReadStreamRef stream, void* context)
-{
- FormStreamFields* form = static_cast<FormStreamFields*>(context);
-
- while (form->currentStream && CFReadStreamGetStatus(form->currentStream) == kCFStreamStatusAtEnd) {
- openNextStream(form);
- }
- if (!form->currentStream) {
- wkSignalCFReadStreamEnd(stream);
- return FALSE;
- }
- return CFReadStreamHasBytesAvailable(form->currentStream);
-}
-
-static void formClose(CFReadStreamRef, void* context)
-{
- FormStreamFields* form = static_cast<FormStreamFields*>(context);
-
- closeCurrentStream(form);
-}
-
-static void formSchedule(CFReadStreamRef, CFRunLoopRef runLoop, CFStringRef runLoopMode, void* context)
-{
- FormStreamFields* form = static_cast<FormStreamFields*>(context);
-
- if (form->currentStream)
- CFReadStreamScheduleWithRunLoop(form->currentStream, runLoop, runLoopMode);
- form->scheduledRunLoopPairs.add(SchedulePair::create(runLoop, runLoopMode));
-}
-
-static void formUnschedule(CFReadStreamRef, CFRunLoopRef runLoop, CFStringRef runLoopMode, void* context)
-{
- FormStreamFields* form = static_cast<FormStreamFields*>(context);
-
- if (form->currentStream)
- CFReadStreamUnscheduleFromRunLoop(form->currentStream, runLoop, runLoopMode);
- form->scheduledRunLoopPairs.remove(SchedulePair::create(runLoop, runLoopMode));
-}
-
-static void formEventCallback(CFReadStreamRef stream, CFStreamEventType type, void* context)
-{
- FormStreamFields* form = static_cast<FormStreamFields*>(context);
-
- switch (type) {
- case kCFStreamEventHasBytesAvailable:
- wkSignalCFReadStreamHasBytes(form->formStream);
- break;
- case kCFStreamEventErrorOccurred: {
- CFStreamError readStreamError = CFReadStreamGetError(stream);
- wkSignalCFReadStreamError(form->formStream, &readStreamError);
- break;
- }
- case kCFStreamEventEndEncountered:
- openNextStream(form);
- if (!form->currentStream) {
- wkSignalCFReadStreamEnd(form->formStream);
- }
- break;
- case kCFStreamEventNone:
- LOG_ERROR("unexpected kCFStreamEventNone");
- break;
- case kCFStreamEventOpenCompleted:
- LOG_ERROR("unexpected kCFStreamEventOpenCompleted");
- break;
- case kCFStreamEventCanAcceptBytes:
- LOG_ERROR("unexpected kCFStreamEventCanAcceptBytes");
- break;
- }
-}
-
void setHTTPBody(NSMutableURLRequest *request, PassRefPtr<FormData> prpFormData)
{
- RefPtr<FormData> formData = prpFormData;
-
- if (!formData)
- return;
-
- size_t count = formData->elements().size();
-
- // Handle the common special case of one piece of form data, with no files.
- if (count == 1 && !formData->alwaysStream()) {
- const FormDataElement& element = formData->elements()[0];
- if (element.m_type == FormDataElement::data) {
- NSData *data = [[NSData alloc] initWithBytes:element.m_data.data() length:element.m_data.size()];
- [request setHTTPBody:data];
- [data release];
- return;
- }
- }
-
-#if ENABLE(BLOB)
- // Check if there is a blob in the form data.
- bool hasBlob = false;
- for (size_t i = 0; i < count; ++i) {
- const FormDataElement& element = formData->elements()[i];
- if (element.m_type == FormDataElement::encodedBlob) {
- hasBlob = true;
- break;
- }
- }
-
- // If yes, we have to resolve all the blob references and regenerate the form data with only data and file types.
- if (hasBlob) {
- RefPtr<FormData> newFormData = FormData::create();
- newFormData->setAlwaysStream(formData->alwaysStream());
- newFormData->setIdentifier(formData->identifier());
- for (size_t i = 0; i < count; ++i) {
- const FormDataElement& element = formData->elements()[i];
- if (element.m_type == FormDataElement::data)
- newFormData->appendData(element.m_data.data(), element.m_data.size());
- else if (element.m_type == FormDataElement::encodedFile)
- newFormData->appendFile(element.m_filename, element.m_shouldGenerateFile);
- else {
- ASSERT(element.m_type == FormDataElement::encodedBlob);
- RefPtr<BlobStorageData> blobData = static_cast<BlobRegistryImpl&>(blobRegistry()).getBlobDataFromURL(KURL(ParsedURLString, element.m_blobURL));
- if (blobData) {
- for (size_t j = 0; j < blobData->items().size(); ++j) {
- const BlobDataItem& blobItem = blobData->items()[j];
- if (blobItem.type == BlobDataItem::Data) {
- newFormData->appendData(blobItem.data->data() + static_cast<int>(blobItem.offset), static_cast<int>(blobItem.length));
- } else {
- ASSERT(blobItem.type == BlobDataItem::File);
- newFormData->appendFileRange(blobItem.path, blobItem.offset, blobItem.length, blobItem.expectedModificationTime);
- }
- }
- }
- }
- }
- formData = newFormData.release();
- count = formData->elements().size();
- }
-#endif
-
- // Precompute the content length so NSURLConnection doesn't use chunked mode.
- long long length = 0;
- for (size_t i = 0; i < count; ++i) {
- const FormDataElement& element = formData->elements()[i];
- if (element.m_type == FormDataElement::data)
- length += element.m_data.size();
- else {
-#if ENABLE(BLOB)
- // If we're sending the file range, use the existing range length for now. We will detect if the file has been changed right before we read the file and abort the operation if necessary.
- if (element.m_fileLength != BlobDataItem::toEndOfFile) {
- length += element.m_fileLength;
- continue;
- }
-#endif
- long long fileSize;
- if (getFileSize(element.m_shouldGenerateFile ? element.m_generatedFilename : element.m_filename, fileSize))
- length += fileSize;
- }
- }
-
- // Set the length.
- [request setValue:[NSString stringWithFormat:@"%lld", length] forHTTPHeaderField:@"Content-Length"];
-
- // Create and set the stream.
-
- // Pass the length along with the formData so it does not have to be recomputed.
- FormContext formContext = { formData.release(), length };
-
- RetainPtr<CFReadStreamRef> stream(AdoptCF, wkCreateCustomCFReadStream(formCreate, formFinalize,
- formOpen, formRead, formCanRead, formClose, formSchedule, formUnschedule,
- &formContext));
- [request setHTTPBodyStream:(NSInputStream *)stream.get()];
+ setHTTPBody(const_cast<CFMutableURLRequestRef>([request _CFURLRequest]), prpFormData);
}
-FormData* httpBodyFromStream(NSInputStream* stream)
+FormData* httpBodyFromStream(NSInputStream *stream)
{
- MutexLocker locker(streamFieldsMapMutex());
- FormStreamFields* formStream = static_cast<FormStreamFields*>(NSMapGet(streamFieldsMap(), stream));
- if (!formStream)
- return 0;
- return formStream->formData.get();
+ return httpBodyFromStream(reinterpret_cast<CFReadStreamRef>(stream));
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/mac/ResourceErrorMac.mm b/Source/WebCore/platform/network/mac/ResourceErrorMac.mm
index 2209afa84..e83990c3d 100644
--- a/Source/WebCore/platform/network/mac/ResourceErrorMac.mm
+++ b/Source/WebCore/platform/network/mac/ResourceErrorMac.mm
@@ -121,9 +121,9 @@ NSError *ResourceError::nsError() const
[userInfo.get() setValue:m_localizedDescription forKey:NSLocalizedDescriptionKey];
if (!m_failingURL.isEmpty()) {
- NSURL *cocoaURL = KURL(ParsedURLString, m_failingURL);
+ RetainPtr<NSURL> cocoaURL = adoptNS([[NSURL alloc] initWithString:m_failingURL]);
[userInfo.get() setValue:m_failingURL forKey:@"NSErrorFailingURLStringKey"];
- [userInfo.get() setValue:cocoaURL forKey:@"NSErrorFailingURLKey"];
+ [userInfo.get() setValue:cocoaURL.get() forKey:@"NSErrorFailingURLKey"];
}
m_platformError.adoptNS([[NSError alloc] initWithDomain:m_domain code:m_errorCode userInfo:userInfo.get()]);
diff --git a/Source/WebCore/platform/network/mac/ResourceHandleMac.mm b/Source/WebCore/platform/network/mac/ResourceHandleMac.mm
index 594db8e91..414d0b82a 100644
--- a/Source/WebCore/platform/network/mac/ResourceHandleMac.mm
+++ b/Source/WebCore/platform/network/mac/ResourceHandleMac.mm
@@ -147,12 +147,6 @@ ResourceHandle::~ResourceHandle()
LOG(Network, "Handle %p destroyed", this);
}
-static const double MaxFoundationVersionWithoutdidSendBodyDataDelegate = 677.21;
-bool ResourceHandle::didSendBodyDataDelegateExists()
-{
- return NSFoundationVersionNumber > MaxFoundationVersionWithoutdidSendBodyDataDelegate;
-}
-
static bool shouldRelaxThirdPartyCookiePolicy(const KURL& url)
{
// If a URL already has cookies, then we'll relax the 3rd party cookie policy and accept new cookies.
@@ -266,10 +260,6 @@ bool ResourceHandle::start(NetworkingContext* context)
bool shouldUseCredentialStorage = !client() || client()->shouldUseCredentialStorage(this);
- if (!ResourceHandle::didSendBodyDataDelegateExists())
- associateStreamWithResourceHandle([firstRequest().nsURLRequest() HTTPBodyStream], this);
-
-
d->m_needsSiteSpecificQuirks = context->needsSiteSpecificQuirks();
createNSURLConnection(
@@ -321,8 +311,6 @@ void ResourceHandle::cancel()
if (d->m_currentMacChallenge)
[[d->m_currentMacChallenge sender] cancelAuthenticationChallenge:d->m_currentMacChallenge];
- if (!ResourceHandle::didSendBodyDataDelegateExists())
- disassociateStreamWithResourceHandle([firstRequest().nsURLRequest() HTTPBodyStream]);
[d->m_connection.get() cancel];
}
@@ -723,17 +711,6 @@ String ResourceHandle::privateBrowsingStorageSessionIdentifierDefaultBase()
m_handle->willSendRequest(request, redirectResponse);
- if (!ResourceHandle::didSendBodyDataDelegateExists()) {
- // The client may change the request's body stream, in which case we have to re-associate
- // the handle with the new stream so upload progress callbacks continue to work correctly.
- NSInputStream* oldBodyStream = [newRequest HTTPBodyStream];
- NSInputStream* newBodyStream = [request.nsURLRequest() HTTPBodyStream];
- if (oldBodyStream != newBodyStream) {
- disassociateStreamWithResourceHandle(oldBodyStream);
- associateStreamWithResourceHandle(newBodyStream, m_handle);
- }
- }
-
return request.nsURLRequest();
}
@@ -880,9 +857,6 @@ String ResourceHandle::privateBrowsingStorageSessionIdentifierDefaultBase()
if (!m_handle || !m_handle->client())
return;
- if (!ResourceHandle::didSendBodyDataDelegateExists())
- disassociateStreamWithResourceHandle([m_handle->firstRequest().nsURLRequest() HTTPBodyStream]);
-
m_handle->client()->didFinishLoading(m_handle, 0);
}
@@ -895,9 +869,6 @@ String ResourceHandle::privateBrowsingStorageSessionIdentifierDefaultBase()
if (!m_handle || !m_handle->client())
return;
- if (!ResourceHandle::didSendBodyDataDelegateExists())
- disassociateStreamWithResourceHandle([m_handle->firstRequest().nsURLRequest() HTTPBodyStream]);
-
m_handle->client()->didFail(m_handle, error);
}
diff --git a/Source/WebCore/platform/network/qt/SocketStreamHandle.h b/Source/WebCore/platform/network/qt/SocketStreamHandle.h
index e72534408..9e6eac0fc 100644
--- a/Source/WebCore/platform/network/qt/SocketStreamHandle.h
+++ b/Source/WebCore/platform/network/qt/SocketStreamHandle.h
@@ -42,6 +42,10 @@
#error This should only be built on Qt
#endif
+QT_BEGIN_NAMESPACE
+class QTcpSocket;
+QT_END_NAMESPACE
+
namespace WebCore {
class AuthenticationChallenge;
@@ -52,6 +56,7 @@ namespace WebCore {
class SocketStreamHandle : public RefCounted<SocketStreamHandle>, public SocketStreamHandleBase {
public:
static PassRefPtr<SocketStreamHandle> create(const KURL& url, SocketStreamHandleClient* client) { return adoptRef(new SocketStreamHandle(url, client)); }
+ static PassRefPtr<SocketStreamHandle> create(QTcpSocket* socket, SocketStreamHandleClient* client) { return adoptRef(new SocketStreamHandle(socket, client)); }
virtual ~SocketStreamHandle();
@@ -61,6 +66,7 @@ namespace WebCore {
private:
SocketStreamHandle(const KURL&, SocketStreamHandleClient*);
+ SocketStreamHandle(QTcpSocket*, SocketStreamHandleClient*);
// No authentication for streams per se, but proxy may ask for credentials.
void didReceiveAuthenticationChallenge(const AuthenticationChallenge&);
diff --git a/Source/WebCore/platform/network/qt/SocketStreamHandlePrivate.h b/Source/WebCore/platform/network/qt/SocketStreamHandlePrivate.h
index d074f4272..301927904 100644
--- a/Source/WebCore/platform/network/qt/SocketStreamHandlePrivate.h
+++ b/Source/WebCore/platform/network/qt/SocketStreamHandlePrivate.h
@@ -47,6 +47,7 @@ class SocketStreamHandlePrivate : public QObject {
Q_OBJECT
public:
SocketStreamHandlePrivate(SocketStreamHandle*, const KURL&);
+ SocketStreamHandlePrivate(SocketStreamHandle*, QTcpSocket*);
~SocketStreamHandlePrivate();
public slots:
@@ -63,6 +64,7 @@ public slots:
void socketSslErrors(const QList<QSslError>&);
#endif
public:
+ void initConnections();
QTcpSocket* m_socket;
SocketStreamHandle* m_streamHandle;
};
diff --git a/Source/WebCore/platform/network/qt/SocketStreamHandleQt.cpp b/Source/WebCore/platform/network/qt/SocketStreamHandleQt.cpp
index d463909e7..28101a650 100644
--- a/Source/WebCore/platform/network/qt/SocketStreamHandleQt.cpp
+++ b/Source/WebCore/platform/network/qt/SocketStreamHandleQt.cpp
@@ -40,7 +40,7 @@
namespace WebCore {
-SocketStreamHandlePrivate::SocketStreamHandlePrivate(SocketStreamHandle* streamHandle, const KURL& url) : QObject()
+SocketStreamHandlePrivate::SocketStreamHandlePrivate(SocketStreamHandle* streamHandle, const KURL& url)
{
m_streamHandle = streamHandle;
m_socket = 0;
@@ -56,12 +56,7 @@ SocketStreamHandlePrivate::SocketStreamHandlePrivate(SocketStreamHandle* streamH
if (!m_socket)
return;
- connect(m_socket, SIGNAL(connected()), this, SLOT(socketConnected()));
- connect(m_socket, SIGNAL(readyRead()), this, SLOT(socketReadyRead()));
- connect(m_socket, SIGNAL(disconnected()), this, SLOT(socketClosed()));
- connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
- if (isSecure)
- connect(m_socket, SIGNAL(sslErrors(const QList<QSslError>&)), this, SLOT(socketSslErrors(const QList<QSslError>&)));
+ initConnections();
unsigned int port = url.hasPort() ? url.port() : (isSecure ? 443 : 80);
@@ -74,11 +69,36 @@ SocketStreamHandlePrivate::SocketStreamHandlePrivate(SocketStreamHandle* streamH
m_socket->connectToHost(host, port);
}
+SocketStreamHandlePrivate::SocketStreamHandlePrivate(SocketStreamHandle* streamHandle, QTcpSocket* socket)
+{
+ m_streamHandle = streamHandle;
+ m_socket = socket;
+ initConnections();
+}
+
SocketStreamHandlePrivate::~SocketStreamHandlePrivate()
{
Q_ASSERT(!(m_socket && m_socket->state() == QAbstractSocket::ConnectedState));
}
+void SocketStreamHandlePrivate::initConnections()
+{
+ connect(m_socket, SIGNAL(connected()), this, SLOT(socketConnected()));
+ connect(m_socket, SIGNAL(readyRead()), this, SLOT(socketReadyRead()));
+ connect(m_socket, SIGNAL(disconnected()), this, SLOT(socketClosed()));
+ connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
+#ifndef QT_NO_OPENSSL
+ if (qobject_cast<QSslSocket*>(m_socket))
+ connect(m_socket, SIGNAL(sslErrors(const QList<QSslError>&)), this, SLOT(socketSslErrors(const QList<QSslError>&)));
+#endif
+
+ // Check for missed signals and call the slots asynchronously to allow a client to be set first.
+ if (m_socket->state() >= QAbstractSocket::ConnectedState)
+ QMetaObject::invokeMethod(this, "socketConnected", Qt::QueuedConnection);
+ if (m_socket->bytesAvailable())
+ QMetaObject::invokeMethod(this, "socketReadyRead", Qt::QueuedConnection);
+}
+
void SocketStreamHandlePrivate::socketConnected()
{
if (m_streamHandle && m_streamHandle->client()) {
@@ -106,7 +126,7 @@ int SocketStreamHandlePrivate::send(const char* data, int len)
void SocketStreamHandlePrivate::close()
{
- if (m_streamHandle->m_state == SocketStreamHandleBase::Connecting) {
+ if (m_streamHandle && m_streamHandle->m_state == SocketStreamHandleBase::Connecting) {
m_socket->abort();
m_streamHandle->client()->didCloseSocketStream(m_streamHandle);
return;
@@ -166,6 +186,13 @@ SocketStreamHandle::SocketStreamHandle(const KURL& url, SocketStreamHandleClient
m_p = new SocketStreamHandlePrivate(this, url);
}
+SocketStreamHandle::SocketStreamHandle(QTcpSocket* socket, SocketStreamHandleClient* client)
+ : SocketStreamHandleBase(KURL(), client)
+{
+ LOG(Network, "SocketStreamHandle %p new client %p", this, m_client);
+ m_p = new SocketStreamHandlePrivate(this, socket);
+}
+
SocketStreamHandle::~SocketStreamHandle()
{
LOG(Network, "SocketStreamHandle %p delete", this);
diff --git a/Source/WebCore/platform/network/soup/CookieJarSoup.cpp b/Source/WebCore/platform/network/soup/CookieJarSoup.cpp
index 3b8a544cf..a1387e7d2 100644
--- a/Source/WebCore/platform/network/soup/CookieJarSoup.cpp
+++ b/Source/WebCore/platform/network/soup/CookieJarSoup.cpp
@@ -29,13 +29,11 @@
#include "KURL.h"
#include "NetworkingContext.h"
#include "ResourceHandle.h"
+#include <wtf/gobject/GRefPtr.h>
#include <wtf/text/CString.h>
namespace WebCore {
-static bool cookiesInitialized;
-static SoupCookieJar* cookieJar;
-
static SoupCookieJar* cookieJarForDocument(const Document* document)
{
if (!document)
@@ -52,29 +50,26 @@ static SoupCookieJar* cookieJarForDocument(const Document* document)
return SOUP_COOKIE_JAR(soup_session_get_feature(context->soupSession(), SOUP_TYPE_COOKIE_JAR));
}
-SoupCookieJar* defaultCookieJar()
+static GRefPtr<SoupCookieJar>& defaultCookieJar()
{
- if (!cookiesInitialized) {
- cookiesInitialized = true;
-
- cookieJar = soup_cookie_jar_new();
- soup_cookie_jar_set_accept_policy(cookieJar, SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY);
- }
-
+ DEFINE_STATIC_LOCAL(GRefPtr<SoupCookieJar>, cookieJar, ());
return cookieJar;
}
-void setDefaultCookieJar(SoupCookieJar* jar)
+SoupCookieJar* soupCookieJar()
{
- cookiesInitialized = true;
-
- if (cookieJar)
- g_object_unref(cookieJar);
+ if (GRefPtr<SoupCookieJar>& jar = defaultCookieJar())
+ return jar.get();
- cookieJar = jar;
+ SoupCookieJar* jar = soup_cookie_jar_new();
+ soup_cookie_jar_set_accept_policy(jar, SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY);
+ setSoupCookieJar(jar);
+ return jar;
+}
- if (cookieJar)
- g_object_ref(cookieJar);
+void setSoupCookieJar(SoupCookieJar* jar)
+{
+ defaultCookieJar() = jar;
}
void setCookies(Document* document, const KURL& url, const String& value)
@@ -84,45 +79,29 @@ void setCookies(Document* document, const KURL& url, const String& value)
return;
GOwnPtr<SoupURI> origin(soup_uri_new(url.string().utf8().data()));
-
GOwnPtr<SoupURI> firstParty(soup_uri_new(document->firstPartyForCookies().string().utf8().data()));
-
- soup_cookie_jar_set_cookie_with_first_party(jar,
- origin.get(),
- firstParty.get(),
- value.utf8().data());
+ soup_cookie_jar_set_cookie_with_first_party(jar, origin.get(), firstParty.get(), value.utf8().data());
}
-String cookies(const Document* document, const KURL& url)
+static String cookiesForDocument(const Document* document, const KURL& url, bool forHTTPHeader)
{
SoupCookieJar* jar = cookieJarForDocument(document);
if (!jar)
return String();
- SoupURI* uri = soup_uri_new(url.string().utf8().data());
- char* cookies = soup_cookie_jar_get_cookies(jar, uri, FALSE);
- soup_uri_free(uri);
-
- String result(String::fromUTF8(cookies));
- g_free(cookies);
+ GOwnPtr<SoupURI> uri(soup_uri_new(url.string().utf8().data()));
+ GOwnPtr<char> cookies(soup_cookie_jar_get_cookies(jar, uri.get(), forHTTPHeader));
+ return String::fromUTF8(cookies.get());
+}
- return result;
+String cookies(const Document* document, const KURL& url)
+{
+ return cookiesForDocument(document, url, false);
}
String cookieRequestHeaderFieldValue(const Document* document, const KURL& url)
{
- SoupCookieJar* jar = cookieJarForDocument(document);
- if (!jar)
- return String();
-
- SoupURI* uri = soup_uri_new(url.string().utf8().data());
- char* cookies = soup_cookie_jar_get_cookies(jar, uri, TRUE);
- soup_uri_free(uri);
-
- String result(String::fromUTF8(cookies));
- g_free(cookies);
-
- return result;
+ return cookiesForDocument(document, url, true);
}
bool cookiesEnabled(const Document* document)
@@ -130,54 +109,87 @@ bool cookiesEnabled(const Document* document)
return !!cookieJarForDocument(document);
}
-bool getRawCookies(const Document*, const KURL&, Vector<Cookie>& rawCookies)
+bool getRawCookies(const Document* document, const KURL& url, Vector<Cookie>& rawCookies)
{
- // FIXME: Not yet implemented
rawCookies.clear();
- return false; // return true when implemented
+ SoupCookieJar* jar = cookieJarForDocument(document);
+ if (!jar)
+ return false;
+
+ GOwnPtr<GSList> cookies(soup_cookie_jar_all_cookies(jar));
+ if (!cookies)
+ return false;
+
+ GOwnPtr<SoupURI> uri(soup_uri_new(url.string().utf8().data()));
+ for (GSList* iter = cookies.get(); iter; iter = g_slist_next(iter)) {
+ GOwnPtr<SoupCookie> cookie(static_cast<SoupCookie*>(iter->data));
+ if (!soup_cookie_applies_to_uri(cookie.get(), uri.get()))
+ continue;
+ // FIXME: we are currently passing false always for session because there's no API to know
+ // whether SoupCookieJar is persistent or not. We could probably add soup_cookie_jar_is_persistent().
+ rawCookies.append(Cookie(String::fromUTF8(cookie->name), String::fromUTF8(cookie->value), String::fromUTF8(cookie->domain),
+ String::fromUTF8(cookie->path), static_cast<double>(soup_date_to_time_t(cookie->expires)) * 1000,
+ cookie->http_only, cookie->secure, false));
+ }
+
+ return true;
}
-void deleteCookie(const Document*, const KURL&, const String&)
+void deleteCookie(const Document* document, const KURL& url, const String& name)
{
- // FIXME: Not yet implemented
+ SoupCookieJar* jar = cookieJarForDocument(document);
+ if (!jar)
+ return;
+
+ GOwnPtr<GSList> cookies(soup_cookie_jar_all_cookies(jar));
+ if (!cookies)
+ return;
+
+ CString cookieName = name.utf8();
+ GOwnPtr<SoupURI> uri(soup_uri_new(url.string().utf8().data()));
+ for (GSList* iter = cookies.get(); iter; iter = g_slist_next(iter)) {
+ GOwnPtr<SoupCookie> cookie(static_cast<SoupCookie*>(iter->data));
+ if (!soup_cookie_applies_to_uri(cookie.get(), uri.get()))
+ continue;
+ if (cookieName == cookie->name)
+ soup_cookie_jar_delete_cookie(jar, cookie.get());
+ }
}
void getHostnamesWithCookies(HashSet<String>& hostnames)
{
- SoupCookieJar* cookieJar = WebCore::defaultCookieJar();
- GSList* cookies = soup_cookie_jar_all_cookies(cookieJar);
- for (GSList* item = cookies; item; item = item->next) {
- SoupCookie* soupCookie = static_cast<SoupCookie*>(item->data);
- if (char* domain = const_cast<char*>(soup_cookie_get_domain(soupCookie)))
- hostnames.add(String::fromUTF8(domain));
+ SoupCookieJar* cookieJar = soupCookieJar();
+ GOwnPtr<GSList> cookies(soup_cookie_jar_all_cookies(cookieJar));
+ for (GSList* item = cookies.get(); item; item = g_slist_next(item)) {
+ GOwnPtr<SoupCookie> cookie(static_cast<SoupCookie*>(item->data));
+ if (!cookie->domain)
+ continue;
+ hostnames.add(String::fromUTF8(cookie->domain));
}
-
- soup_cookies_free(cookies);
}
void deleteCookiesForHostname(const String& hostname)
{
CString hostNameString = hostname.utf8();
-
- SoupCookieJar* cookieJar = WebCore::defaultCookieJar();
- GSList* cookies = soup_cookie_jar_all_cookies(cookieJar);
- for (GSList* item = cookies; item; item = item->next) {
- SoupCookie* soupCookie = static_cast<SoupCookie*>(item->data);
- if (hostNameString == soup_cookie_get_domain(soupCookie))
- soup_cookie_jar_delete_cookie(cookieJar, soupCookie);
+ SoupCookieJar* cookieJar = soupCookieJar();
+ GOwnPtr<GSList> cookies(soup_cookie_jar_all_cookies(cookieJar));
+ for (GSList* item = cookies.get(); item; item = g_slist_next(item)) {
+ SoupCookie* cookie = static_cast<SoupCookie*>(item->data);
+ if (soup_cookie_domain_matches(cookie, hostNameString.data()))
+ soup_cookie_jar_delete_cookie(cookieJar, cookie);
+ soup_cookie_free(cookie);
}
-
- soup_cookies_free(cookies);
}
void deleteAllCookies()
{
- SoupCookieJar* cookieJar = WebCore::defaultCookieJar();
- GSList* cookies = soup_cookie_jar_all_cookies(cookieJar);
- for (GSList* item = cookies; item; item = item->next)
- soup_cookie_jar_delete_cookie(cookieJar, static_cast<SoupCookie*>(item->data));
-
- soup_cookies_free(cookies);
+ SoupCookieJar* cookieJar = soupCookieJar();
+ GOwnPtr<GSList> cookies(soup_cookie_jar_all_cookies(cookieJar));
+ for (GSList* item = cookies.get(); item; item = g_slist_next(item)) {
+ SoupCookie* cookie = static_cast<SoupCookie*>(item->data);
+ soup_cookie_jar_delete_cookie(cookieJar, cookie);
+ soup_cookie_free(cookie);
+ }
}
}
diff --git a/Source/WebCore/platform/network/soup/CookieJarSoup.h b/Source/WebCore/platform/network/soup/CookieJarSoup.h
index ab1f95c12..251b13663 100644
--- a/Source/WebCore/platform/network/soup/CookieJarSoup.h
+++ b/Source/WebCore/platform/network/soup/CookieJarSoup.h
@@ -31,8 +31,10 @@
#include <libsoup/soup.h>
namespace WebCore {
- SoupCookieJar* defaultCookieJar();
- void setDefaultCookieJar(SoupCookieJar* jar);
+
+SoupCookieJar* soupCookieJar();
+void setSoupCookieJar(SoupCookieJar*);
+
}
#endif
diff --git a/Source/WebCore/platform/network/soup/CookieStorageSoup.cpp b/Source/WebCore/platform/network/soup/CookieStorageSoup.cpp
new file mode 100644
index 000000000..2d7174799
--- /dev/null
+++ b/Source/WebCore/platform/network/soup/CookieStorageSoup.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "CookieStorage.h"
+
+#include "CookieJarSoup.h"
+#include "NotImplemented.h"
+
+#if USE(PLATFORM_STRATEGIES)
+#include "CookiesStrategy.h"
+#include "PlatformStrategies.h"
+#endif
+
+#include <stdio.h>
+
+namespace WebCore {
+
+void setCookieStoragePrivateBrowsingEnabled(bool enabled)
+{
+ notImplemented();
+}
+
+#if USE(PLATFORM_STRATEGIES)
+static void soupCookiesChanged(SoupCookieJar*, SoupCookie*, SoupCookie*, gpointer)
+{
+ platformStrategies()->cookiesStrategy()->notifyCookiesChanged();
+}
+#endif
+
+void startObservingCookieChanges()
+{
+#if USE(PLATFORM_STRATEGIES)
+ g_signal_connect(soupCookieJar(), "changed", G_CALLBACK(soupCookiesChanged), 0);
+#endif
+}
+
+void stopObservingCookieChanges()
+{
+#if USE(PLATFORM_STRATEGIES)
+ g_signal_handlers_disconnect_by_func(soupCookieJar(), reinterpret_cast<void*>(soupCookiesChanged), 0);
+#endif
+}
+
+}
diff --git a/Source/WebCore/platform/network/soup/DNSSoup.cpp b/Source/WebCore/platform/network/soup/DNSSoup.cpp
new file mode 100644
index 000000000..1f22e21c7
--- /dev/null
+++ b/Source/WebCore/platform/network/soup/DNSSoup.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2009, 2012 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DNS.h"
+#include "DNSResolveQueue.h"
+
+#include "GOwnPtrSoup.h"
+#include "ResourceHandle.h"
+#include <wtf/MainThread.h>
+#include <wtf/text/CString.h>
+
+namespace WebCore {
+
+// There is no current reliable way to know if we're behind a proxy at
+// this level. We'll have to implement it in
+// SoupSession/SoupProxyURIResolver/GProxyResolver
+bool DNSResolveQueue::platformProxyIsEnabledInSystemPreferences()
+{
+ return false;
+}
+
+static void resolvedCallback(SoupAddress* soupAddress, guint status, void* userData)
+{
+ DNSResolveQueue::shared().decrementRequestCount();
+}
+
+void DNSResolveQueue::platformResolve(const String& hostname)
+{
+ ASSERT(isMainThread());
+
+ soup_session_prefetch_dns(ResourceHandle::defaultSession(), hostname.utf8().data(), 0, resolvedCallback, 0);
+}
+
+void prefetchDNS(const String& hostname)
+{
+ ASSERT(isMainThread());
+ if (hostname.isEmpty())
+ return;
+
+ DNSResolveQueue::shared().add(hostname);
+}
+
+}
diff --git a/Source/WebCore/platform/network/soup/GOwnPtrSoup.cpp b/Source/WebCore/platform/network/soup/GOwnPtrSoup.cpp
index 56fe69236..47080ec0f 100644
--- a/Source/WebCore/platform/network/soup/GOwnPtrSoup.cpp
+++ b/Source/WebCore/platform/network/soup/GOwnPtrSoup.cpp
@@ -20,6 +20,7 @@
#include "config.h"
#include "GOwnPtrSoup.h"
+#include <libsoup/soup-cookie.h>
#include <libsoup/soup-uri.h>
namespace WTF {
@@ -30,4 +31,10 @@ template <> void freeOwnedGPtr<SoupURI>(SoupURI* ptr)
soup_uri_free(ptr);
}
+template <> void freeOwnedGPtr<SoupCookie>(SoupCookie* ptr)
+{
+ if (ptr)
+ soup_cookie_free(ptr);
+}
+
}
diff --git a/Source/WebCore/platform/network/soup/GOwnPtrSoup.h b/Source/WebCore/platform/network/soup/GOwnPtrSoup.h
index c129f840c..bfdcd8486 100644
--- a/Source/WebCore/platform/network/soup/GOwnPtrSoup.h
+++ b/Source/WebCore/platform/network/soup/GOwnPtrSoup.h
@@ -20,13 +20,15 @@
#ifndef GOwnPtrSoup_h
#define GOwnPtrSoup_h
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
typedef struct _SoupURI SoupURI;
+typedef struct _SoupCookie SoupCookie;
namespace WTF {
template<> void freeOwnedGPtr<SoupURI>(SoupURI* ptr);
+template<> void freeOwnedGPtr<SoupCookie>(SoupCookie* ptr);
}
diff --git a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
index 92c66e54c..dc0cb6243 100644
--- a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
+++ b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
@@ -69,81 +69,117 @@ namespace WebCore {
#define READ_BUFFER_SIZE 8192
+static bool loadingSynchronousRequest = false;
+
class WebCoreSynchronousLoader : public ResourceHandleClient {
WTF_MAKE_NONCOPYABLE(WebCoreSynchronousLoader);
public:
- WebCoreSynchronousLoader(ResourceError&, ResourceResponse &, Vector<char>&);
- ~WebCoreSynchronousLoader();
- virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&);
- virtual void didReceiveData(ResourceHandle*, const char*, int, int encodedDataLength);
- virtual void didFinishLoading(ResourceHandle*, double /*finishTime*/);
- virtual void didFail(ResourceHandle*, const ResourceError&);
+ WebCoreSynchronousLoader(ResourceError& error, ResourceResponse& response, SoupSession* session, Vector<char>& data)
+ : m_error(error)
+ , m_response(response)
+ , m_session(session)
+ , m_data(data)
+ , m_finished(false)
+ {
+ // We don't want any timers to fire while we are doing our synchronous load
+ // so we replace the thread default main context. The main loop iterations
+ // will only process GSources associated with this inner context.
+ loadingSynchronousRequest = true;
+ GRefPtr<GMainContext> innerMainContext = adoptGRef(g_main_context_new());
+ g_main_context_push_thread_default(innerMainContext.get());
+ m_mainLoop = g_main_loop_new(innerMainContext.get(), false);
+
+ adjustMaxConnections(1);
+ }
- void run();
+ ~WebCoreSynchronousLoader()
+ {
+ adjustMaxConnections(-1);
+ g_main_context_pop_thread_default(g_main_context_get_thread_default());
+ loadingSynchronousRequest = false;
+ }
-private:
- ResourceError& m_error;
- ResourceResponse& m_response;
- Vector<char>& m_data;
- bool m_finished;
- GRefPtr<GMainLoop> m_mainLoop;
-};
+ void adjustMaxConnections(int adjustment)
+ {
+ int maxConnections, maxConnectionsPerHost;
+ g_object_get(m_session,
+ SOUP_SESSION_MAX_CONNS, &maxConnections,
+ SOUP_SESSION_MAX_CONNS_PER_HOST, &maxConnectionsPerHost,
+ NULL);
+ maxConnections += adjustment;
+ maxConnectionsPerHost += adjustment;
+ g_object_set(m_session,
+ SOUP_SESSION_MAX_CONNS, maxConnections,
+ SOUP_SESSION_MAX_CONNS_PER_HOST, maxConnectionsPerHost,
+ NULL);
-WebCoreSynchronousLoader::WebCoreSynchronousLoader(ResourceError& error, ResourceResponse& response, Vector<char>& data)
- : m_error(error)
- , m_response(response)
- , m_data(data)
- , m_finished(false)
-{
- m_mainLoop = adoptGRef(g_main_loop_new(0, false));
-}
+ }
-WebCoreSynchronousLoader::~WebCoreSynchronousLoader()
-{
-}
+ virtual bool isSynchronousClient()
+ {
+ return true;
+ }
-void WebCoreSynchronousLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
-{
- m_response = response;
-}
+ virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
+ {
+ m_response = response;
+ }
-void WebCoreSynchronousLoader::didReceiveData(ResourceHandle*, const char* data, int length, int)
-{
- m_data.append(data, length);
-}
+ virtual void didReceiveData(ResourceHandle*, const char* data, int length, int)
+ {
+ m_data.append(data, length);
+ }
-void WebCoreSynchronousLoader::didFinishLoading(ResourceHandle*, double)
-{
- g_main_loop_quit(m_mainLoop.get());
- m_finished = true;
-}
+ virtual void didFinishLoading(ResourceHandle*, double)
+ {
+ if (g_main_loop_is_running(m_mainLoop.get()))
+ g_main_loop_quit(m_mainLoop.get());
+ m_finished = true;
+ }
-void WebCoreSynchronousLoader::didFail(ResourceHandle* handle, const ResourceError& error)
-{
- m_error = error;
- didFinishLoading(handle, 0);
-}
+ virtual void didFail(ResourceHandle* handle, const ResourceError& error)
+ {
+ m_error = error;
+ didFinishLoading(handle, 0);
+ }
-void WebCoreSynchronousLoader::run()
-{
- if (!m_finished)
- g_main_loop_run(m_mainLoop.get());
-}
+ void run()
+ {
+ if (!m_finished)
+ g_main_loop_run(m_mainLoop.get());
+ }
+
+private:
+ ResourceError& m_error;
+ ResourceResponse& m_response;
+ SoupSession* m_session;
+ Vector<char>& m_data;
+ bool m_finished;
+ GRefPtr<GMainLoop> m_mainLoop;
+};
static void cleanupSoupRequestOperation(ResourceHandle*, bool isDestroying);
static void sendRequestCallback(GObject*, GAsyncResult*, gpointer);
static void readCallback(GObject*, GAsyncResult*, gpointer);
static void closeCallback(GObject*, GAsyncResult*, gpointer);
static bool startNonHTTPRequest(ResourceHandle*, KURL);
+#if ENABLE(WEB_TIMING)
+static int milisecondsSinceRequest(double requestTime);
+#endif
ResourceHandleInternal::~ResourceHandleInternal()
{
}
+static SoupSession* sessionFromContext(NetworkingContext* context)
+{
+ return (context && context->isValid()) ? context->soupSession() : ResourceHandle::defaultSession();
+}
+
SoupSession* ResourceHandleInternal::soupSession()
{
- return (m_context && m_context->isValid()) ? m_context->soupSession() : ResourceHandle::defaultSession();
+ return sessionFromContext(m_context.get());
}
ResourceHandle::~ResourceHandle()
@@ -159,9 +195,9 @@ static void ensureSessionIsInitialized(SoupSession* session)
if (session == ResourceHandle::defaultSession()) {
SoupCookieJar* jar = SOUP_COOKIE_JAR(soup_session_get_feature(session, SOUP_TYPE_COOKIE_JAR));
if (!jar)
- soup_session_add_feature(session, SOUP_SESSION_FEATURE(defaultCookieJar()));
+ soup_session_add_feature(session, SOUP_SESSION_FEATURE(soupCookieJar()));
else
- setDefaultCookieJar(jar);
+ setSoupCookieJar(jar);
}
if (!soup_session_get_feature(session, SOUP_TYPE_LOGGER) && LogNetwork.state == WTFLogChannelOn) {
@@ -179,12 +215,27 @@ static void ensureSessionIsInitialized(SoupSession* session)
g_object_set_data(G_OBJECT(session), "webkit-init", reinterpret_cast<void*>(0xdeadbeef));
}
-void ResourceHandle::prepareForURL(const KURL& url)
+static void gotHeadersCallback(SoupMessage* msg, gpointer data)
{
- GOwnPtr<SoupURI> soupURI(soup_uri_new(url.string().utf8().data()));
- if (!soupURI)
+ ResourceHandle* handle = static_cast<ResourceHandle*>(data);
+ if (!handle)
return;
- soup_session_prepare_for_uri(ResourceHandle::defaultSession(), soupURI.get());
+ ResourceHandleInternal* d = handle->getInternal();
+ if (d->m_cancelled)
+ return;
+
+#if ENABLE(WEB_TIMING)
+ if (d->m_response.resourceLoadTiming())
+ d->m_response.resourceLoadTiming()->receiveHeadersEnd = milisecondsSinceRequest(d->m_response.resourceLoadTiming()->requestTime);
+#endif
+
+ // The original response will be needed later to feed to willSendRequest in
+ // restartedCallback() in case we are redirected. For this reason, so we store it
+ // here.
+ ResourceResponse response;
+ response.updateFromSoupMessage(msg);
+
+ d->m_response = response;
}
// Called each time the message is going to be sent again except the first time.
@@ -203,10 +254,8 @@ static void restartedCallback(SoupMessage* msg, gpointer data)
KURL newURL = KURL(handle->firstRequest().url(), location);
ResourceRequest request = handle->firstRequest();
- ResourceResponse response;
request.setURL(newURL);
request.setHTTPMethod(msg->method);
- response.updateFromSoupMessage(msg);
// Should not set Referer after a redirect from a secure resource to non-secure one.
if (!request.url().protocolIs("https") && protocolIs(request.httpReferrer(), "https")) {
@@ -215,11 +264,16 @@ static void restartedCallback(SoupMessage* msg, gpointer data)
}
if (d->client())
- d->client()->willSendRequest(handle, request, response);
+ d->client()->willSendRequest(handle, request, d->m_response);
if (d->m_cancelled)
return;
+#if ENABLE(WEB_TIMING)
+ d->m_response.setResourceLoadTiming(ResourceLoadTiming::create());
+ d->m_response.resourceLoadTiming()->requestTime = monotonicallyIncreasingTime();
+#endif
+
// Update the first party in case the base URL changed with the redirect
String firstPartyString = request.firstPartyForCookies().string();
if (!firstPartyString.isEmpty()) {
@@ -307,6 +361,11 @@ static void sendRequestCallback(GObject* source, GAsyncResult* res, gpointer dat
return;
}
+ if (d->m_defersLoading) {
+ d->m_deferredResult = res;
+ return;
+ }
+
GOwnPtr<GError> error;
GInputStream* in = soup_request_send_finish(d->m_soupRequest.get(), res, &error.outPtr());
if (error) {
@@ -324,9 +383,6 @@ static void sendRequestCallback(GObject* source, GAsyncResult* res, gpointer dat
d->m_response.setSniffedContentType(sniffedType);
}
d->m_response.updateFromSoupMessage(soupMessage);
-
- if (d->m_defersLoading)
- soup_session_pause_message(d->soupSession(), soupMessage);
} else {
d->m_response.setURL(handle->firstRequest().url());
const gchar* contentType = soup_request_get_content_type(d->m_soupRequest.get());
@@ -445,6 +501,101 @@ static bool addFormElementsToSoupMessage(SoupMessage* message, const char* conte
return true;
}
+#if ENABLE(WEB_TIMING)
+static int milisecondsSinceRequest(double requestTime)
+{
+ return static_cast<int>((monotonicallyIncreasingTime() - requestTime) * 1000.0);
+}
+
+static void wroteBodyCallback(SoupMessage*, gpointer data)
+{
+ RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data);
+ if (!handle)
+ return;
+
+ ResourceHandleInternal* d = handle->getInternal();
+ if (!d->m_response.resourceLoadTiming())
+ return;
+
+ d->m_response.resourceLoadTiming()->sendEnd = milisecondsSinceRequest(d->m_response.resourceLoadTiming()->requestTime);
+}
+
+static void requestStartedCallback(SoupSession*, SoupMessage* soupMessage, SoupSocket*, gpointer data)
+{
+ RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(g_object_get_data(G_OBJECT(soupMessage), "handle"));
+ if (!handle)
+ return;
+
+ ResourceHandleInternal* d = handle->getInternal();
+ if (!d->m_response.resourceLoadTiming())
+ return;
+
+ d->m_response.resourceLoadTiming()->sendStart = milisecondsSinceRequest(d->m_response.resourceLoadTiming()->requestTime);
+ if (d->m_response.resourceLoadTiming()->sslStart != -1) {
+ // WebCore/inspector/front-end/RequestTimingView.js assumes
+ // that SSL time is included in connection time so must
+ // substract here the SSL delta that will be added later (see
+ // WebInspector.RequestTimingView.createTimingTable in the
+ // file above for more details).
+ d->m_response.resourceLoadTiming()->sendStart -=
+ d->m_response.resourceLoadTiming()->sslEnd - d->m_response.resourceLoadTiming()->sslStart;
+ }
+}
+
+static void networkEventCallback(SoupMessage*, GSocketClientEvent event, GIOStream*, gpointer data)
+{
+ ResourceHandle* handle = static_cast<ResourceHandle*>(data);
+ if (!handle)
+ return;
+ ResourceHandleInternal* d = handle->getInternal();
+ if (d->m_cancelled)
+ return;
+
+ int deltaTime = milisecondsSinceRequest(d->m_response.resourceLoadTiming()->requestTime);
+ switch (event) {
+ case G_SOCKET_CLIENT_RESOLVING:
+ d->m_response.resourceLoadTiming()->dnsStart = deltaTime;
+ break;
+ case G_SOCKET_CLIENT_RESOLVED:
+ d->m_response.resourceLoadTiming()->dnsEnd = deltaTime;
+ break;
+ case G_SOCKET_CLIENT_CONNECTING:
+ d->m_response.resourceLoadTiming()->connectStart = deltaTime;
+ if (d->m_response.resourceLoadTiming()->dnsStart != -1)
+ // WebCore/inspector/front-end/RequestTimingView.js assumes
+ // that DNS time is included in connection time so must
+ // substract here the DNS delta that will be added later (see
+ // WebInspector.RequestTimingView.createTimingTable in the
+ // file above for more details).
+ d->m_response.resourceLoadTiming()->connectStart -=
+ d->m_response.resourceLoadTiming()->dnsEnd - d->m_response.resourceLoadTiming()->dnsStart;
+ break;
+ case G_SOCKET_CLIENT_CONNECTED:
+ // Web Timing considers that connection time involves dns, proxy & TLS negotiation...
+ // so we better pick G_SOCKET_CLIENT_COMPLETE for connectEnd
+ break;
+ case G_SOCKET_CLIENT_PROXY_NEGOTIATING:
+ d->m_response.resourceLoadTiming()->proxyStart = deltaTime;
+ break;
+ case G_SOCKET_CLIENT_PROXY_NEGOTIATED:
+ d->m_response.resourceLoadTiming()->proxyEnd = deltaTime;
+ break;
+ case G_SOCKET_CLIENT_TLS_HANDSHAKING:
+ d->m_response.resourceLoadTiming()->sslStart = deltaTime;
+ break;
+ case G_SOCKET_CLIENT_TLS_HANDSHAKED:
+ d->m_response.resourceLoadTiming()->sslEnd = deltaTime;
+ break;
+ case G_SOCKET_CLIENT_COMPLETE:
+ d->m_response.resourceLoadTiming()->connectEnd = deltaTime;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+}
+#endif
+
static bool startHTTPRequest(ResourceHandle* handle)
{
ASSERT(handle);
@@ -477,9 +628,16 @@ static bool startHTTPRequest(ResourceHandle* handle)
if (!handle->shouldContentSniff())
soup_message_disable_feature(soupMessage, SOUP_TYPE_CONTENT_SNIFFER);
+ g_signal_connect(soupMessage, "got-headers", G_CALLBACK(gotHeadersCallback), handle);
g_signal_connect(soupMessage, "restarted", G_CALLBACK(restartedCallback), handle);
g_signal_connect(soupMessage, "wrote-body-data", G_CALLBACK(wroteBodyDataCallback), handle);
+#if ENABLE(WEB_TIMING)
+ g_signal_connect(soupMessage, "network-event", G_CALLBACK(networkEventCallback), handle);
+ g_signal_connect(soupMessage, "wrote-body", G_CALLBACK(wroteBodyCallback), handle);
+ g_object_set_data(G_OBJECT(soupMessage), "handle", handle);
+#endif
+
String firstPartyString = request.firstPartyForCookies().string();
if (!firstPartyString.isEmpty()) {
GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data()));
@@ -499,13 +657,29 @@ static bool startHTTPRequest(ResourceHandle* handle)
// balanced by a deref() in cleanupSoupRequestOperation, which should always run
handle->ref();
+#if ENABLE(WEB_TIMING)
+ d->m_response.setResourceLoadTiming(ResourceLoadTiming::create());
+#endif
+
// Make sure we have an Accept header for subresources; some sites
// want this to serve some of their subresources
if (!soup_message_headers_get_one(soupMessage->request_headers, "Accept"))
soup_message_headers_append(soupMessage->request_headers, "Accept", "*/*");
+ // In the case of XHR .send() and .send("") explicitly tell libsoup
+ // to send a zero content-lenght header for consistency
+ // with other backends (e.g. Chromium's) and other UA implementations like FF.
+ // It's done in the backend here instead of in XHR code since in XHR CORS checking
+ // prevents us from this kind of late header manipulation.
+ if ((request.httpMethod() == "POST" || request.httpMethod() == "PUT")
+ && (!request.httpBody() || request.httpBody()->isEmpty()))
+ soup_message_headers_set_content_length(soupMessage->request_headers, 0);
+
// Send the request only if it's not been explicitly deferred.
if (!d->m_defersLoading) {
+#if ENABLE(WEB_TIMING)
+ d->m_response.resourceLoadTiming()->requestTime = monotonicallyIncreasingTime();
+#endif
d->m_cancellable = adoptGRef(g_cancellable_new());
soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, handle);
}
@@ -585,6 +759,10 @@ void ResourceHandle::platformSetDefersLoading(bool defersLoading)
// simply check for d->m_scheduledFailure because it's cleared as
// soon as the failure event is fired.
if (!hasBeenSent(this) && d->m_soupRequest) {
+#if ENABLE(WEB_TIMING)
+ if (d->m_response.resourceLoadTiming())
+ d->m_response.resourceLoadTiming()->requestTime = monotonicallyIncreasingTime();
+#endif
d->m_cancellable = adoptGRef(g_cancellable_new());
soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, this);
return;
@@ -592,7 +770,11 @@ void ResourceHandle::platformSetDefersLoading(bool defersLoading)
if (d->m_deferredResult) {
GRefPtr<GAsyncResult> asyncResult = adoptGRef(d->m_deferredResult.leakRef());
- readCallback(G_OBJECT(d->m_inputStream.get()), asyncResult.get(), this);
+
+ if (d->m_inputStream)
+ readCallback(G_OBJECT(d->m_inputStream.get()), asyncResult.get(), this);
+ else
+ sendRequestCallback(G_OBJECT(d->m_soupRequest.get()), asyncResult.get(), this);
}
}
@@ -617,8 +799,12 @@ void ResourceHandle::loadResourceSynchronously(NetworkingContext* context, const
return;
}
#endif
+
+ ASSERT(!loadingSynchronousRequest);
+ if (loadingSynchronousRequest) // In practice this cannot happen, but if for some reason it does,
+ return; // we want to avoid accidentally going into an infinite loop of requests.
- WebCoreSynchronousLoader syncLoader(error, response, data);
+ WebCoreSynchronousLoader syncLoader(error, response, sessionFromContext(context), data);
RefPtr<ResourceHandle> handle = create(context, request, &syncLoader, false /*defersLoading*/, false /*shouldContentSniff*/);
if (!handle)
return;
@@ -633,9 +819,14 @@ void ResourceHandle::loadResourceSynchronously(NetworkingContext* context, const
static void closeCallback(GObject* source, GAsyncResult* res, gpointer data)
{
RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data);
-
ResourceHandleInternal* d = handle->getInternal();
+
g_input_stream_close_finish(d->m_inputStream.get(), res, 0);
+
+ ResourceHandleClient* client = handle->client();
+ if (client && loadingSynchronousRequest)
+ client->didFinishLoading(handle.get(), 0);
+
cleanupSoupRequestOperation(handle.get());
}
@@ -666,8 +857,14 @@ static void readCallback(GObject* source, GAsyncResult* asyncResult, gpointer da
if (!bytesRead) {
// We inform WebCore of load completion now instead of waiting for the input
- // stream to close because the input stream is closed asynchronously.
- client->didFinishLoading(handle.get(), 0);
+ // stream to close because the input stream is closed asynchronously. If this
+ // is a synchronous request, we wait until the closeCallback, because we don't
+ // want to halt the internal main loop before the input stream closes.
+ if (client && !loadingSynchronousRequest) {
+ client->didFinishLoading(handle.get(), 0);
+ handle->setClient(0); // Unset the client so that we do not try to access th
+ // client in the closeCallback.
+ }
g_input_stream_close_async(d->m_inputStream.get(), G_PRIORITY_DEFAULT, 0, closeCallback, handle.get());
return;
}
@@ -739,7 +936,11 @@ SoupSession* ResourceHandle::defaultSession()
SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER,
SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_SNIFFER,
SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_DEFAULT,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
NULL);
+#if ENABLE(WEB_TIMING)
+ g_signal_connect(G_OBJECT(session), "request-started", G_CALLBACK(requestStartedCallback), 0);
+#endif
}
return session;
diff --git a/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp b/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp
index 63a7acf43..d7127b4b5 100644
--- a/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp
+++ b/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp
@@ -20,7 +20,7 @@
#include "config.h"
#include "ResourceRequest.h"
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#include "GOwnPtrSoup.h"
#include "HTTPParsers.h"
#include "MIMETypeRegistry.h"
diff --git a/Source/WebCore/platform/network/soup/ResourceResponseSoup.cpp b/Source/WebCore/platform/network/soup/ResourceResponseSoup.cpp
index 3f2355b3f..155048b2b 100644
--- a/Source/WebCore/platform/network/soup/ResourceResponseSoup.cpp
+++ b/Source/WebCore/platform/network/soup/ResourceResponseSoup.cpp
@@ -21,7 +21,7 @@
#include "config.h"
#include "ResourceResponse.h"
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#include "HTTPParsers.h"
#include "MIMETypeRegistry.h"
#include "PlatformString.h"
diff --git a/Source/WebCore/platform/network/soup/SocketStreamHandle.h b/Source/WebCore/platform/network/soup/SocketStreamHandle.h
index c8fe3b3b6..c2449c798 100644
--- a/Source/WebCore/platform/network/soup/SocketStreamHandle.h
+++ b/Source/WebCore/platform/network/soup/SocketStreamHandle.h
@@ -32,7 +32,7 @@
#ifndef SocketStreamHandle_h
#define SocketStreamHandle_h
-#include "GRefPtr.h"
+#include <wtf/gobject/GRefPtr.h>
#include "SocketStreamHandleBase.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
diff --git a/Source/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp b/Source/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp
index 29247c3f9..a8c2baa70 100644
--- a/Source/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp
+++ b/Source/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp
@@ -31,16 +31,18 @@
#include "config.h"
#include "SocketStreamHandle.h"
-#include "GOwnPtr.h"
#include "KURL.h"
#include "Logging.h"
-#include "NotFound.h"
#include "NotImplemented.h"
#include "SocketStreamError.h"
#include "SocketStreamHandleClient.h"
-#include "Vector.h"
+
#include <gio/gio.h>
#include <glib.h>
+
+#include <wtf/NotFound.h>
+#include <wtf/Vector.h>
+#include <wtf/gobject/GOwnPtr.h>
#include <wtf/text/CString.h>
#define READ_BUFFER_SIZE 1024
@@ -242,7 +244,8 @@ static void connectedCallback(GSocketClient* client, GAsyncResult* result, void*
// The SocketStreamHandle has been deactivated, so just close the connection, ignoring errors.
SocketStreamHandle* handle = getHandleFromId(id);
if (!handle) {
- g_io_stream_close(G_IO_STREAM(socketConnection), 0, &error.outPtr());
+ if (socketConnection)
+ g_io_stream_close(G_IO_STREAM(socketConnection), 0, 0);
return;
}
diff --git a/Source/WebCore/platform/network/soup/SoupURIUtils.cpp b/Source/WebCore/platform/network/soup/SoupURIUtils.cpp
index 1f656157c..f07ad7f6c 100644
--- a/Source/WebCore/platform/network/soup/SoupURIUtils.cpp
+++ b/Source/WebCore/platform/network/soup/SoupURIUtils.cpp
@@ -19,7 +19,7 @@
#include "config.h"
#include "SoupURIUtils.h"
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#include <libsoup/soup.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/network/win/ResourceHandleWin.cpp b/Source/WebCore/platform/network/win/ResourceHandleWin.cpp
index 167f1fd3c..0212d0cda 100644
--- a/Source/WebCore/platform/network/win/ResourceHandleWin.cpp
+++ b/Source/WebCore/platform/network/win/ResourceHandleWin.cpp
@@ -30,15 +30,17 @@
#include "DataURL.h"
#include "HTTPParsers.h"
#include "MIMETypeRegistry.h"
-#include "MainThread.h"
#include "NotImplemented.h"
#include "ResourceError.h"
#include "ResourceHandleClient.h"
#include "ResourceHandleInternal.h"
#include "SharedBuffer.h"
#include "Timer.h"
-#include "UnusedParam.h"
+
+#include <wtf/MainThread.h>
+#include <wtf/UnusedParam.h>
#include <wtf/text/CString.h>
+
#include <windows.h>
#include <wininet.h>
diff --git a/Source/WebCore/platform/posix/FileSystemPOSIX.cpp b/Source/WebCore/platform/posix/FileSystemPOSIX.cpp
index 28f802991..fda81265b 100644
--- a/Source/WebCore/platform/posix/FileSystemPOSIX.cpp
+++ b/Source/WebCore/platform/posix/FileSystemPOSIX.cpp
@@ -35,6 +35,7 @@
#include <fcntl.h>
#include <fnmatch.h>
#include <libgen.h>
+#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
@@ -182,10 +183,9 @@ bool getFileModificationTime(const String& path, time_t& result)
String pathByAppendingComponent(const String& path, const String& component)
{
- if (path.endsWith("/"))
+ if (path.endsWith('/'))
return path + component;
- else
- return path + "/" + component;
+ return path + "/" + component;
}
bool makeAllDirectories(const String& path)
@@ -255,4 +255,28 @@ Vector<String> listDirectory(const String& path, const String& filter)
}
#endif
+#if !PLATFORM(MAC)
+String openTemporaryFile(const String& prefix, PlatformFileHandle& handle)
+{
+ char buffer[PATH_MAX];
+ const char* tmpDir = getenv("TMPDIR");
+
+ if (!tmpDir)
+ tmpDir = "/tmp";
+
+ if (snprintf(buffer, PATH_MAX, "%s/%sXXXXXX", tmpDir, prefix.utf8().data()) >= PATH_MAX)
+ goto end;
+
+ handle = mkstemp(buffer);
+ if (handle < 0)
+ goto end;
+
+ return String::fromUTF8(buffer);
+
+end:
+ handle = invalidPlatformFileHandle;
+ return String();
+}
+#endif
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/qt/CookieJarQt.cpp b/Source/WebCore/platform/qt/CookieJarQt.cpp
index f76ce94fe..d07d6ef92 100644
--- a/Source/WebCore/platform/qt/CookieJarQt.cpp
+++ b/Source/WebCore/platform/qt/CookieJarQt.cpp
@@ -202,6 +202,9 @@ void SharedCookieJarQt::getHostnamesWithCookies(HashSet<String>& hostnames)
void SharedCookieJarQt::deleteCookiesForHostname(const String& hostname)
{
+ if (!m_database.isOpen())
+ return;
+
QList<QNetworkCookie> cookies = allCookies();
QList<QNetworkCookie>::Iterator it = cookies.begin();
QList<QNetworkCookie>::Iterator end = cookies.end();
@@ -220,6 +223,9 @@ void SharedCookieJarQt::deleteCookiesForHostname(const String& hostname)
void SharedCookieJarQt::deleteAllCookies()
{
+ if (!m_database.isOpen())
+ return;
+
QSqlQuery sqlQuery(m_database);
sqlQuery.prepare(QLatin1String("DELETE * FROM cookies"));
sqlQuery.exec();
@@ -245,6 +251,10 @@ bool SharedCookieJarQt::setCookiesFromUrl(const QList<QNetworkCookie>& cookieLis
{
if (!QNetworkCookieJar::setCookiesFromUrl(cookieList, url))
return false;
+
+ if (!m_database.isOpen())
+ return false;
+
QSqlQuery sqlQuery(m_database);
sqlQuery.prepare(QLatin1String("INSERT OR REPLACE INTO cookies (cookieId, cookie) VALUES (:cookieIdvalue, :cookievalue)"));
QVariantList cookiesIds;
@@ -267,6 +277,8 @@ void SharedCookieJarQt::ensureDatabaseTable()
qWarning("Can't open cookie database");
return;
}
+ m_database.exec(QLatin1String("PRAGMA synchronous=OFF"));
+
QSqlQuery sqlQuery(m_database);
sqlQuery.prepare(QLatin1String("CREATE TABLE IF NOT EXISTS cookies (cookieId VARCHAR PRIMARY KEY, cookie BLOB);"));
sqlQuery.exec();
@@ -274,6 +286,9 @@ void SharedCookieJarQt::ensureDatabaseTable()
void SharedCookieJarQt::loadCookies()
{
+ if (!m_database.isOpen())
+ return;
+
QList<QNetworkCookie> cookies;
QSqlQuery sqlQuery(m_database);
sqlQuery.prepare(QLatin1String("SELECT cookie FROM cookies"));
diff --git a/Source/WebCore/platform/qt/DeviceMotionClientQt.cpp b/Source/WebCore/platform/qt/DeviceMotionClientQt.cpp
new file mode 100644
index 000000000..9b26087ec
--- /dev/null
+++ b/Source/WebCore/platform/qt/DeviceMotionClientQt.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "DeviceMotionClientQt.h"
+
+#include "DeviceMotionProviderQt.h"
+
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+DeviceMotionClientQt::~DeviceMotionClientQt()
+{
+}
+
+void DeviceMotionClientQt::deviceMotionControllerDestroyed()
+{
+ delete this;
+}
+
+void DeviceMotionClientQt::setController(DeviceMotionController* controller)
+{
+ // Initialize lazily.
+ if (!m_provider)
+ m_provider = adoptPtr(new DeviceMotionProviderQt);
+
+ m_provider->setController(controller);
+}
+
+void DeviceMotionClientQt::startUpdating()
+{
+ if (m_provider)
+ m_provider->start();
+}
+
+void DeviceMotionClientQt::stopUpdating()
+{
+ if (m_provider)
+ m_provider->stop();
+}
+
+DeviceMotionData* DeviceMotionClientQt::currentDeviceMotion() const
+{
+ return m_provider->currentDeviceMotion();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/qt/DeviceMotionClientQt.h b/Source/WebCore/platform/qt/DeviceMotionClientQt.h
new file mode 100644
index 000000000..d6eaf905d
--- /dev/null
+++ b/Source/WebCore/platform/qt/DeviceMotionClientQt.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef DeviceMotionClientQt_h
+#define DeviceMotionClientQt_h
+
+#include "DeviceMotionClient.h"
+#include "DeviceMotionData.h"
+
+#include "DeviceMotionProviderQt.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class DeviceMotionController;
+class DeviceMotionProviderQt;
+
+class DeviceMotionClientQt : public DeviceMotionClient {
+public:
+ DeviceMotionClientQt() { }
+ virtual ~DeviceMotionClientQt();
+
+private:
+ virtual void deviceMotionControllerDestroyed();
+
+ virtual void startUpdating();
+ virtual void stopUpdating();
+
+ virtual DeviceMotionData* currentDeviceMotion() const;
+
+ virtual void setController(DeviceMotionController*);
+
+ OwnPtr<DeviceMotionProviderQt> m_provider;
+};
+
+} // namespece WebCore
+
+#endif // DeviceMotionClientQt_h
diff --git a/Source/WebCore/platform/qt/DeviceMotionProviderQt.cpp b/Source/WebCore/platform/qt/DeviceMotionProviderQt.cpp
new file mode 100644
index 000000000..b7332b654
--- /dev/null
+++ b/Source/WebCore/platform/qt/DeviceMotionProviderQt.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "DeviceMotionProviderQt.h"
+
+#include "DeviceMotionController.h"
+#include "DeviceOrientationProviderQt.h"
+
+namespace WebCore {
+
+DeviceMotionProviderQt::DeviceMotionProviderQt()
+ : m_motion(DeviceMotionData::create())
+ , m_deviceOrientation(new DeviceOrientationProviderQt)
+ , m_controller(0)
+{
+ m_acceleration.addFilter(this);
+}
+
+DeviceMotionProviderQt::~DeviceMotionProviderQt()
+{
+ delete m_deviceOrientation;
+}
+
+void DeviceMotionProviderQt::setController(DeviceMotionController* controller)
+{
+ ASSERT(controller);
+ ASSERT(!m_controller);
+ m_controller = controller;
+}
+
+void DeviceMotionProviderQt::start()
+{
+ m_acceleration.start();
+ m_deviceOrientation->start();
+}
+
+void DeviceMotionProviderQt::stop()
+{
+ m_acceleration.stop();
+ m_deviceOrientation->stop();
+}
+
+bool DeviceMotionProviderQt::filter(QAccelerometerReading* reading)
+{
+ if (!m_controller) {
+ // We are the only filter. No need to propagate from here.
+ return false;
+ }
+
+ RefPtr<DeviceMotionData::Acceleration> accel = DeviceMotionData::Acceleration::create(
+ /* x available */ true, reading->x(),
+ /* y available */ true, reading->y(),
+ /* z available */ true, reading->z());
+
+ RefPtr<DeviceMotionData::RotationRate> rotation = DeviceMotionData::RotationRate::create(
+ m_deviceOrientation->hasAlpha(), m_deviceOrientation->lastOrientation()->alpha(),
+ /* beta available */ true, m_deviceOrientation->lastOrientation()->beta(),
+ /* gamma available */ true, m_deviceOrientation->lastOrientation()->gamma());
+
+ m_motion = DeviceMotionData::create(accel,
+ accel, /* FIXME: Needs to provide acceleration include gravity. */
+ rotation,
+ false, 0 /* The interval is treated internally by Qt mobility (QtSensors in Qt5) */);
+
+ m_controller->didChangeDeviceMotion(m_motion.get());
+
+ // We are the only filter. No need to propagate from here.
+ return false;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/qt/DeviceMotionProviderQt.h b/Source/WebCore/platform/qt/DeviceMotionProviderQt.h
new file mode 100644
index 000000000..cf3d589e4
--- /dev/null
+++ b/Source/WebCore/platform/qt/DeviceMotionProviderQt.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef DeviceMotionProviderQt_h
+#define DeviceMotionProviderQt_h
+
+#include "DeviceMotionData.h"
+#include <QAccelerometerFilter>
+#include <wtf/RefPtr.h>
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+using QTM_NAMESPACE::QAccelerometer;
+using QTM_NAMESPACE::QAccelerometerFilter;
+using QTM_NAMESPACE::QAccelerometerReading;
+#endif
+
+namespace WebCore {
+
+class DeviceMotionController;
+class DeviceOrientationProviderQt;
+
+class DeviceMotionProviderQt : public QAccelerometerFilter {
+public:
+ DeviceMotionProviderQt();
+ virtual ~DeviceMotionProviderQt();
+
+ void setController(DeviceMotionController*);
+
+ bool filter(QAccelerometerReading*);
+
+ void start();
+ void stop();
+ DeviceMotionData* currentDeviceMotion() const { return m_motion.get(); }
+
+private:
+ RefPtr<DeviceMotionData> m_motion;
+ QAccelerometer m_acceleration;
+ DeviceOrientationProviderQt* m_deviceOrientation;
+ DeviceMotionController* m_controller;
+};
+
+} // namespace WebCore
+
+#endif // DeviceMotionProviderQt_h
diff --git a/Source/WebCore/platform/qt/DeviceOrientationClientQt.cpp b/Source/WebCore/platform/qt/DeviceOrientationClientQt.cpp
new file mode 100644
index 000000000..5fca859fc
--- /dev/null
+++ b/Source/WebCore/platform/qt/DeviceOrientationClientQt.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#include "config.h"
+#include "DeviceOrientationClientQt.h"
+
+#include "DeviceOrientationProviderQt.h"
+
+namespace WebCore {
+
+void DeviceOrientationClientQt::deviceOrientationControllerDestroyed()
+{
+ delete this;
+}
+
+void DeviceOrientationClientQt::setController(DeviceOrientationController* controller)
+{
+ // Initialize lazily.
+ if (!m_provider)
+ m_provider = adoptPtr(new DeviceOrientationProviderQt);
+
+ m_provider->setController(controller);
+}
+
+void DeviceOrientationClientQt::startUpdating()
+{
+ if (m_provider)
+ m_provider->start();
+}
+
+void DeviceOrientationClientQt::stopUpdating()
+{
+ if (m_provider)
+ m_provider->stop();
+}
+
+DeviceOrientation* DeviceOrientationClientQt::lastOrientation() const
+{
+ return (m_provider) ? m_provider->lastOrientation() : 0;
+}
+
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/qt/DeviceOrientationClientQt.h b/Source/WebCore/platform/qt/DeviceOrientationClientQt.h
new file mode 100644
index 000000000..91244dba6
--- /dev/null
+++ b/Source/WebCore/platform/qt/DeviceOrientationClientQt.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef DeviceOrientationClientQt_h
+#define DeviceOrientationClientQt_h
+
+#include "DeviceOrientation.h"
+#include "DeviceOrientationClient.h"
+
+#include "DeviceOrientationController.h"
+#include "DeviceOrientationProviderQt.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class DeviceOrientationProviderQt;
+
+class DeviceOrientationClientQt : public DeviceOrientationClient {
+public:
+ virtual void setController(DeviceOrientationController*);
+ virtual void startUpdating();
+ virtual void stopUpdating();
+ virtual DeviceOrientation* lastOrientation() const;
+ virtual void deviceOrientationControllerDestroyed();
+
+private:
+ OwnPtr<DeviceOrientationProviderQt> m_provider;
+};
+
+} // namespace WebCore
+
+#endif // DeviceOrientationClientQt_h
diff --git a/Source/WebCore/platform/qt/DeviceOrientationProviderQt.cpp b/Source/WebCore/platform/qt/DeviceOrientationProviderQt.cpp
new file mode 100644
index 000000000..488530bb3
--- /dev/null
+++ b/Source/WebCore/platform/qt/DeviceOrientationProviderQt.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#include "config.h"
+#include "DeviceOrientationProviderQt.h"
+
+namespace WebCore {
+
+DeviceOrientationProviderQt::DeviceOrientationProviderQt()
+ : m_controller(0)
+{
+ m_sensor.addFilter(this);
+ m_lastOrientation = DeviceOrientation::create();
+}
+
+DeviceOrientationProviderQt::~DeviceOrientationProviderQt()
+{
+
+}
+
+void DeviceOrientationProviderQt::setController(DeviceOrientationController* controller)
+{
+ if (!controller)
+ stop();
+
+ m_controller = controller;
+}
+
+void DeviceOrientationProviderQt::start()
+{
+ m_sensor.start();
+}
+
+void DeviceOrientationProviderQt::stop()
+{
+ m_sensor.stop();
+}
+
+bool DeviceOrientationProviderQt::filter(QRotationReading* reading)
+{
+ if (m_controller) {
+ // Provide device orientation data according W3C spec:
+ // http://dev.w3.org/geo/api/spec-source-orientation.html
+ // Qt mobility (QtSensors in Qt5) provide these data via QRotationSensor
+ // using the QRotationReading class:
+ // - the rotation around z axis (alpha) is given as z in QRotationReading;
+ // - the rotation around x axis (beta) is given as x in QRotationReading;
+ // - the rotation around y axis (gamma) is given as y in QRotationReading;
+ // See: http://doc.qt.nokia.com/qtmobility-1.0/qrotationreading.html
+ // The Z (alpha) rotation angle is checked via hasAlpha() private method,
+ // depending if the device is able do detect the alpha rotation. X (beta) and
+ // Y (gamma) axis are availble in this context.
+ m_lastOrientation = DeviceOrientation::create(hasAlpha(), reading->z(),
+ /* x available */ true, reading->x(),
+ /* y available */ true, reading->y());
+ m_controller->didChangeDeviceOrientation(m_lastOrientation.get());
+ }
+
+ // We are the only filter, so no need to propagate.
+ return false;
+}
+
+}
diff --git a/Source/WebCore/platform/qt/DeviceOrientationProviderQt.h b/Source/WebCore/platform/qt/DeviceOrientationProviderQt.h
new file mode 100644
index 000000000..6d3e19902
--- /dev/null
+++ b/Source/WebCore/platform/qt/DeviceOrientationProviderQt.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef DeviceOrientationProviderQt_h
+#define DeviceOrientationProviderQt_h
+
+#include "DeviceOrientation.h"
+#include "DeviceOrientationController.h"
+#include <QRotationFilter>
+#include <wtf/RefPtr.h>
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+using QTM_NAMESPACE::QRotationFilter;
+using QTM_NAMESPACE::QRotationReading;
+using QTM_NAMESPACE::QRotationSensor;
+#endif
+
+namespace WebCore {
+
+class DeviceOrientationProviderQt : public QRotationFilter {
+public:
+ DeviceOrientationProviderQt();
+ virtual ~DeviceOrientationProviderQt();
+
+ void setController(DeviceOrientationController*);
+
+ bool filter(QRotationReading*);
+
+ void start();
+ void stop();
+ bool isActive() const { return m_sensor.isActive(); }
+ DeviceOrientation* lastOrientation() const { return m_lastOrientation.get(); }
+ bool hasAlpha() const { return m_sensor.property("hasZ").toBool(); }
+
+private:
+ RefPtr<DeviceOrientation> m_lastOrientation;
+ DeviceOrientationController* m_controller;
+ QRotationSensor m_sensor;
+};
+
+}
+
+#endif // DeviceOrientationProviderQt_h
diff --git a/Source/WebCore/platform/qt/DragImageQt.cpp b/Source/WebCore/platform/qt/DragImageQt.cpp
index 42ad6e979..0e7ce0465 100644
--- a/Source/WebCore/platform/qt/DragImageQt.cpp
+++ b/Source/WebCore/platform/qt/DragImageQt.cpp
@@ -61,7 +61,7 @@ DragImageRef dissolveDragImageToFraction(DragImageRef image, float)
return image;
}
-DragImageRef createDragImageFromImage(Image* image)
+DragImageRef createDragImageFromImage(Image* image, RespectImageOrientationEnum)
{
if (!image || !image->nativeImageForCurrentFrame())
return 0;
diff --git a/Source/WebCore/platform/qt/LocalizedStringsQt.cpp b/Source/WebCore/platform/qt/LocalizedStringsQt.cpp
index a48d6b846..1ff8006cc 100644
--- a/Source/WebCore/platform/qt/LocalizedStringsQt.cpp
+++ b/Source/WebCore/platform/qt/LocalizedStringsQt.cpp
@@ -501,8 +501,10 @@ String localizedMediaControlElementString(const String& name)
return QCoreApplication::translate("QWebPage", "Remaining Time", "Media controller element");
if (name == "StatusDisplay")
return QCoreApplication::translate("QWebPage", "Status Display", "Media controller element");
- if (name == "FullscreenButton")
- return QCoreApplication::translate("QWebPage", "Fullscreen Button", "Media controller element");
+ if (name == "EnterFullscreenButton")
+ return QCoreApplication::translate("QWebPage", "EnterFullscreen Button", "Media controller element");
+ if (name == "ExitFullscreenButton")
+ return QCoreApplication::translate("QWebPage", "ExitFullscreen Button", "Media controller element");
if (name == "SeekForwardButton")
return QCoreApplication::translate("QWebPage", "Seek Forward Button", "Media controller element");
if (name == "SeekBackButton")
@@ -539,8 +541,10 @@ String localizedMediaControlElementHelpText(const String& name)
return QCoreApplication::translate("QWebPage", "Remaining movie time", "Media controller element");
if (name == "StatusDisplay")
return QCoreApplication::translate("QWebPage", "Current movie status", "Media controller element");
- if (name == "FullscreenButton")
+ if (name == "EnterFullscreenButton")
return QCoreApplication::translate("QWebPage", "Play movie in full-screen mode", "Media controller element");
+ if (name == "ExitFullscreenButton")
+ return QCoreApplication::translate("QWebPage", "Exit full-screen mode", "Media controller element");
if (name == "SeekForwardButton")
return QCoreApplication::translate("QWebPage", "Seek quickly back", "Media controller element");
if (name == "SeekBackButton")
diff --git a/Source/WebCore/platform/qt/PlatformMouseEventQt.cpp b/Source/WebCore/platform/qt/PlatformMouseEventQt.cpp
deleted file mode 100644
index 9946c4e49..000000000
--- a/Source/WebCore/platform/qt/PlatformMouseEventQt.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2006 Zack Rusin <zack@kde.org>
- * Copyright (C) 2011 Research In Motion Limited.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "PlatformMouseEvent.h"
-
-#include <QGraphicsSceneMouseEvent>
-#include <QMouseEvent>
-#include <wtf/CurrentTime.h>
-
-namespace WebCore {
-
-static void mouseEventModifiersFromQtKeyboardModifiers(Qt::KeyboardModifiers keyboardModifiers, unsigned& modifiers)
-{
- modifiers = 0;
- if (keyboardModifiers & Qt::ShiftModifier)
- modifiers |= PlatformEvent::ShiftKey;
- if (keyboardModifiers & Qt::ControlModifier)
- modifiers |= PlatformEvent::CtrlKey;
- if (keyboardModifiers & Qt::AltModifier)
- modifiers |= PlatformEvent::AltKey;
- if (keyboardModifiers & Qt::MetaModifier)
- modifiers |= PlatformEvent::MetaKey;
-}
-
-static void mouseEventTypeAndMouseButtonFromQEvent(const QEvent* event, PlatformEvent::Type& mouseEventType, MouseButton& mouseButton)
-{
- enum { MouseEvent, GraphicsSceneMouseEvent } frameworkMouseEventType;
- switch (event->type()) {
- case QEvent::MouseButtonDblClick:
- case QEvent::MouseButtonPress:
- frameworkMouseEventType = MouseEvent;
- mouseEventType = PlatformEvent::MousePressed;
- break;
- case QEvent::MouseButtonRelease:
- frameworkMouseEventType = MouseEvent;
- mouseEventType = PlatformEvent::MouseReleased;
- break;
- case QEvent::MouseMove:
- frameworkMouseEventType = MouseEvent;
- mouseEventType = PlatformEvent::MouseMoved;
- break;
-#if !defined(QT_NO_GRAPHICSVIEW)
- case QEvent::GraphicsSceneMouseDoubleClick:
- case QEvent::GraphicsSceneMousePress:
- frameworkMouseEventType = GraphicsSceneMouseEvent;
- mouseEventType = PlatformEvent::MousePressed;
- break;
- case QEvent::GraphicsSceneMouseRelease:
- frameworkMouseEventType = GraphicsSceneMouseEvent;
- mouseEventType = PlatformEvent::MouseReleased;
- break;
- case QEvent::GraphicsSceneMouseMove:
- frameworkMouseEventType = GraphicsSceneMouseEvent;
- mouseEventType = PlatformEvent::MouseMoved;
- break;
-#endif
- default:
- ASSERT_NOT_REACHED();
- frameworkMouseEventType = MouseEvent;
- mouseEventType = PlatformEvent::MouseMoved;
- break;
- }
-
- Qt::MouseButtons mouseButtons;
- switch (frameworkMouseEventType) {
- case MouseEvent: {
- const QMouseEvent* mouseEvent = static_cast<const QMouseEvent*>(event);
- mouseButtons = mouseEventType == PlatformEvent::MouseMoved ? mouseEvent->buttons() : mouseEvent->button();
- break;
- }
- case GraphicsSceneMouseEvent: {
- const QGraphicsSceneMouseEvent* mouseEvent = static_cast<const QGraphicsSceneMouseEvent*>(event);
- mouseButtons = mouseEventType == PlatformEvent::MouseMoved ? mouseEvent->buttons() : mouseEvent->button();
- break;
- }
- }
-
- if (mouseButtons & Qt::LeftButton)
- mouseButton = LeftButton;
- else if (mouseButtons & Qt::RightButton)
- mouseButton = RightButton;
- else if (mouseButtons & Qt::MidButton)
- mouseButton = MiddleButton;
- else
- mouseButton = NoButton;
-}
-
-#if !defined(QT_NO_GRAPHICSVIEW)
-PlatformMouseEvent::PlatformMouseEvent(QGraphicsSceneMouseEvent* event, int clickCount)
-{
- m_timestamp = WTF::currentTime();
-
- // FIXME: Why don't we handle a context menu event here as we do in PlatformMouseEvent(QInputEvent*, int)?
- // See <https://bugs.webkit.org/show_bug.cgi?id=60728>.
- PlatformEvent::Type type;
- mouseEventTypeAndMouseButtonFromQEvent(event, type, m_button);
-
- m_type = type;
- m_position = IntPoint(event->pos().toPoint());
- m_globalPosition = IntPoint(event->screenPos());
-
- m_clickCount = clickCount;
- mouseEventModifiersFromQtKeyboardModifiers(event->modifiers(), m_modifiers);
-}
-#endif // QT_NO_GRAPHICSVIEW
-
-PlatformMouseEvent::PlatformMouseEvent(QInputEvent* event, int clickCount)
-{
- m_timestamp = WTF::currentTime();
-
- bool isContextMenuEvent = false;
-#ifndef QT_NO_CONTEXTMENU
- if (event->type() == QEvent::ContextMenu) {
- isContextMenuEvent = true;
- m_type = PlatformEvent::MousePressed;
- QContextMenuEvent* ce = static_cast<QContextMenuEvent*>(event);
- m_position = IntPoint(ce->pos());
- m_globalPosition = IntPoint(ce->globalPos());
- m_button = RightButton;
- }
-#endif
- if (!isContextMenuEvent) {
- PlatformEvent::Type type;
- mouseEventTypeAndMouseButtonFromQEvent(event, type, m_button);
- QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
-
- m_type = type;
- m_position = IntPoint(mouseEvent->pos());
- m_globalPosition = IntPoint(mouseEvent->globalPos());
- }
-
- m_clickCount = clickCount;
- mouseEventModifiersFromQtKeyboardModifiers(event->modifiers(), m_modifiers);
-}
-
-}
-
-// vim: ts=4 sw=4 et
diff --git a/Source/WebCore/platform/qt/PlatformSupportQt.cpp b/Source/WebCore/platform/qt/PlatformSupportQt.cpp
index 4e33a9f05..55a5cfab8 100644
--- a/Source/WebCore/platform/qt/PlatformSupportQt.cpp
+++ b/Source/WebCore/platform/qt/PlatformSupportQt.cpp
@@ -31,8 +31,10 @@ namespace WebCore {
bool PlatformSupport::popupsAllowed(NPP npp)
{
+#if ENABLE(NETSCAPE_PLUGIN_API)
if (npp && npp->ndata)
return static_cast<PluginView*>(npp->ndata)->arePopupsAllowed();
+#endif
return false;
}
diff --git a/Source/WebCore/platform/qt/PlatformTouchEventQt.cpp b/Source/WebCore/platform/qt/PlatformTouchEventQt.cpp
deleted file mode 100644
index 17a51e9ed..000000000
--- a/Source/WebCore/platform/qt/PlatformTouchEventQt.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * This file is part of the WebKit project.
- *
- * Copyright (C) 2009 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 "PlatformTouchEvent.h"
-#include <wtf/CurrentTime.h>
-
-#if ENABLE(TOUCH_EVENTS)
-
-namespace WebCore {
-
-PlatformTouchEvent::PlatformTouchEvent(QTouchEvent* event)
-{
- switch (event->type()) {
- case QEvent::TouchBegin:
- m_type = PlatformEvent::TouchStart;
- break;
- case QEvent::TouchUpdate:
- m_type = PlatformEvent::TouchMove;
- break;
- case QEvent::TouchEnd:
- m_type = PlatformEvent::TouchEnd;
- break;
-#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
- case QEvent::TouchCancel:
- m_type = PlatformEvent::TouchCancel;
- break;
-#endif
- }
-
- const QList<QTouchEvent::TouchPoint>& points = event->touchPoints();
- for (int i = 0; i < points.count(); ++i) {
- PlatformTouchPoint::State state = PlatformTouchPoint::TouchStateEnd;
-
- switch (points.at(i).state()) {
- case Qt::TouchPointReleased:
- state = PlatformTouchPoint::TouchReleased;
- break;
- case Qt::TouchPointMoved:
- state = PlatformTouchPoint::TouchMoved;
- break;
- case Qt::TouchPointPressed:
- state = PlatformTouchPoint::TouchPressed;
- break;
- case Qt::TouchPointStationary:
- state = PlatformTouchPoint::TouchStationary;
- break;
- }
-
- // Qt does not have a Qt::TouchPointCancelled point state, so if we receive a touch cancel event,
- // simply cancel all touch points here.
- if (m_type == PlatformEvent::TouchCancel)
- state = PlatformTouchPoint::TouchCancelled;
-
- m_touchPoints.append(PlatformTouchPoint(points.at(i), state));
- }
-
- m_modifiers = 0;
- if (event->modifiers() & Qt::ShiftModifier)
- m_modifiers |= ShiftKey;
- if (event->modifiers() & Qt::ControlModifier)
- m_modifiers |= CtrlKey;
- if (event->modifiers() & Qt::AltModifier)
- m_modifiers |= AltKey;
- if (event->modifiers() & Qt::MetaModifier)
- m_modifiers |= MetaKey;
-
- m_timestamp = WTF::currentTime();
-}
-
-}
-
-#endif
diff --git a/Source/WebCore/platform/qt/PlatformTouchPointQt.cpp b/Source/WebCore/platform/qt/PlatformTouchPointQt.cpp
deleted file mode 100644
index 0f9afa48e..000000000
--- a/Source/WebCore/platform/qt/PlatformTouchPointQt.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * This file is part of the WebKit project.
- *
- * Copyright (C) 2009,2012 Nokia Corporation and/or its subsidiary(-ies)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "PlatformTouchPoint.h"
-
-#if ENABLE(TOUCH_EVENTS)
-
-namespace WebCore {
-
-PlatformTouchPoint::PlatformTouchPoint(const QTouchEvent::TouchPoint& point, State state)
- // The QTouchEvent::TouchPoint API states that ids will be >= 0.
- : m_id(point.id())
- , m_state(state)
- , m_screenPos(point.screenPos().toPoint())
- , m_pos(point.pos().toPoint())
-{
- // Qt reports touch point size as rectangles, but we will pretend it is an oval.
- QRect touchRect = point.rect().toAlignedRect();
- if (touchRect.isValid()) {
- m_radiusX = point.rect().width() / 2;
- m_radiusY = point.rect().height() / 2;
- } else {
- // http://www.w3.org/TR/2011/WD-touch-events-20110505: 1 if no value is known.
- m_radiusX = 1;
- m_radiusY = 1;
- }
- m_force = point.pressure();
- // FIXME: Support m_rotationAngle if QTouchEvent at some point supports it.
-}
-
-}
-
-#endif
diff --git a/Source/WebCore/platform/qt/RenderThemeQt.cpp b/Source/WebCore/platform/qt/RenderThemeQt.cpp
index 83b0d82a2..61623b9f9 100644
--- a/Source/WebCore/platform/qt/RenderThemeQt.cpp
+++ b/Source/WebCore/platform/qt/RenderThemeQt.cpp
@@ -30,11 +30,11 @@
#include "config.h"
#include "RenderThemeQt.h"
-#include "CSSStyleSelector.h"
#include "CSSValueKeywords.h"
#include "Chrome.h"
#include "ChromeClient.h"
#include "Color.h"
+#include "FileList.h"
#include "Font.h"
#include "FontSelector.h"
#include "GraphicsContext.h"
@@ -56,6 +56,7 @@
#include "RenderTheme.h"
#include "RenderThemeQtMobile.h"
#include "ScrollbarTheme.h"
+#include "StyleResolver.h"
#include "TimeRanges.h"
#include "UserAgentStyleSheets.h"
#include <wtf/text/StringBuilder.h>
@@ -318,7 +319,7 @@ void RenderThemeQt::setButtonSize(RenderStyle* style) const
computeSizeBasedOnStyle(style);
}
-void RenderThemeQt::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeQt::adjustTextFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// Resetting the style like this leads to differences like:
// - RenderTextControl {INPUT} at (2,2) size 168x25 [bgcolor=#FFFFFF] border: (2px inset #000000)]
@@ -331,7 +332,7 @@ void RenderThemeQt::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style,
computeSizeBasedOnStyle(style);
}
-void RenderThemeQt::adjustTextAreaStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeQt::adjustTextAreaStyle(StyleResolver* selector, RenderStyle* style, Element* element) const
{
adjustTextFieldStyle(selector, style, element);
}
@@ -341,7 +342,7 @@ bool RenderThemeQt::paintTextArea(RenderObject* o, const PaintInfo& i, const Int
return paintTextField(o, i, r);
}
-void RenderThemeQt::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeQt::adjustMenuListStyle(StyleResolver*, RenderStyle* style, Element*) const
{
style->resetBorder();
@@ -357,7 +358,7 @@ void RenderThemeQt::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, E
setPopupPadding(style);
}
-void RenderThemeQt::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeQt::adjustMenuListButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// Height is locked to auto.
style->setHeight(Length(Auto));
@@ -382,20 +383,20 @@ double RenderThemeQt::animationRepeatIntervalForProgressBar(RenderProgress* rend
return 0.1;
}
-void RenderThemeQt::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeQt::adjustProgressBarStyle(StyleResolver*, RenderStyle* style, Element*) const
{
style->setBoxShadow(nullptr);
}
#endif
-void RenderThemeQt::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeQt::adjustSliderTrackStyle(StyleResolver*, RenderStyle* style, Element*) const
{
style->setBoxShadow(nullptr);
}
-void RenderThemeQt::adjustSliderThumbStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeQt::adjustSliderThumbStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
- RenderTheme::adjustSliderThumbStyle(selector, style, element);
+ RenderTheme::adjustSliderThumbStyle(styleResolver, style, element);
style->setBoxShadow(nullptr);
}
@@ -405,8 +406,7 @@ bool RenderThemeQt::paintSearchField(RenderObject* o, const PaintInfo& pi,
return paintTextField(o, pi, r);
}
-void RenderThemeQt::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style,
- Element* e) const
+void RenderThemeQt::adjustSearchFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// Resetting the style like this leads to differences like:
// - RenderTextControl {INPUT} at (2,2) size 168x25 [bgcolor=#FFFFFF] border: (2px inset #000000)]
@@ -419,8 +419,7 @@ void RenderThemeQt::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderSty
computeSizeBasedOnStyle(style);
}
-void RenderThemeQt::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style,
- Element* e) const
+void RenderThemeQt::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// Logic taken from RenderThemeChromium.cpp.
// Scale the button size based on the font size.
@@ -434,7 +433,7 @@ void RenderThemeQt::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selecto
IntRect RenderThemeQt::convertToPaintingRect(RenderObject* inputRenderer, const RenderObject* partRenderer, IntRect partRect, const IntRect& localOffset) const
{
// Compute an offset between the part renderer and the input renderer.
- IntSize offsetFromInputRenderer = -(partRenderer->offsetFromAncestorContainer(inputRenderer));
+ IntSize offsetFromInputRenderer = -roundedIntSize(partRenderer->offsetFromAncestorContainer(inputRenderer));
// Move the rect into partRenderer's coords.
partRect.move(offsetFromInputRenderer);
// Account for the local drawing offset.
@@ -453,7 +452,7 @@ bool RenderThemeQt::paintSearchFieldCancelButton(RenderObject* o, const PaintInf
if (!input->renderer()->isBox())
return false;
RenderBox* inputRenderBox = toRenderBox(input->renderer());
- IntRect inputContentBox = inputRenderBox->contentBoxRect();
+ IntRect inputContentBox = pixelSnappedIntRect(inputRenderBox->contentBoxRect());
// Make sure the scaled button stays square and will fit in its parent's box.
int cancelButtonSize = qMin(inputContentBox.width(), qMin(inputContentBox.height(), r.height()));
@@ -471,11 +470,10 @@ bool RenderThemeQt::paintSearchFieldCancelButton(RenderObject* o, const PaintInf
return false;
}
-void RenderThemeQt::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style,
- Element* e) const
+void RenderThemeQt::adjustSearchFieldDecorationStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
{
notImplemented();
- RenderTheme::adjustSearchFieldDecorationStyle(selector, style, e);
+ RenderTheme::adjustSearchFieldDecorationStyle(styleResolver, style, e);
}
bool RenderThemeQt::paintSearchFieldDecoration(RenderObject* o, const PaintInfo& pi,
@@ -485,11 +483,10 @@ bool RenderThemeQt::paintSearchFieldDecoration(RenderObject* o, const PaintInfo&
return RenderTheme::paintSearchFieldDecoration(o, pi, r);
}
-void RenderThemeQt::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style,
- Element* e) const
+void RenderThemeQt::adjustSearchFieldResultsDecorationStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
{
notImplemented();
- RenderTheme::adjustSearchFieldResultsDecorationStyle(selector, style, e);
+ RenderTheme::adjustSearchFieldResultsDecorationStyle(styleResolver, style, e);
}
bool RenderThemeQt::paintSearchFieldResultsDecoration(RenderObject* o, const PaintInfo& pi,
@@ -500,8 +497,7 @@ bool RenderThemeQt::paintSearchFieldResultsDecoration(RenderObject* o, const Pai
}
#ifndef QT_NO_SPINBOX
-void RenderThemeQt::adjustInnerSpinButtonStyle(CSSStyleSelector* selector, RenderStyle* style,
- Element* e) const
+void RenderThemeQt::adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// Use the same width as our native scrollbar
int width = ScrollbarTheme::theme()->scrollbarThickness();
@@ -741,7 +737,7 @@ bool RenderThemeQt::paintMediaVolumeSliderTrack(RenderObject *o, const PaintInfo
if (!o->isSlider())
return false;
- IntRect b = toRenderBox(o)->contentBoxRect();
+ IntRect b = pixelSnappedIntRect(toRenderBox(o)->contentBoxRect());
// Position the outer rectangle
int top = r.y() + b.y();
@@ -868,20 +864,21 @@ double RenderThemeQt::caretBlinkInterval() const
return static_cast<QGuiApplication*>(qApp)->styleHints()->cursorFlashTime() / 1000.0 / 2.0;
}
-String RenderThemeQt::fileListNameForWidth(const Vector<String>& filenames, const Font& font, int width) const
+String RenderThemeQt::fileListNameForWidth(const FileList* fileList, const Font& font, int width, bool multipleFilesAllowed) const
{
+ UNUSED_PARAM(multipleFilesAllowed);
if (width <= 0)
return String();
String string;
- if (filenames.isEmpty())
+ if (fileList->isEmpty())
string = fileButtonNoFileSelectedLabel();
- else if (filenames.size() == 1) {
- String fname = filenames[0];
- QFontMetrics fm(font.font());
+ else if (fileList->length() == 1) {
+ String fname = fileList->item(0)->path();
+ QFontMetrics fm(font.syntheticFont());
string = fm.elidedText(fname, Qt::ElideLeft, width);
} else {
- int n = filenames.size();
+ int n = fileList->length();
string = QCoreApplication::translate("QWebPage", "%n file(s)",
"number of chosen file",
QCoreApplication::DefaultCodec, n);
diff --git a/Source/WebCore/platform/qt/RenderThemeQt.h b/Source/WebCore/platform/qt/RenderThemeQt.h
index 83e729d88..5185afe6d 100644
--- a/Source/WebCore/platform/qt/RenderThemeQt.h
+++ b/Source/WebCore/platform/qt/RenderThemeQt.h
@@ -99,39 +99,39 @@ protected:
virtual void setButtonSize(RenderStyle*) const;
- virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
#if ENABLE(PROGRESS_TAG)
- virtual void adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const;
// Returns the repeat interval of the animation for the progress bar.
virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const;
#endif
- virtual void adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSliderTrackStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual void adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSliderThumbStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&);
#ifndef QT_NO_SPINBOX
- virtual void adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
#endif
#if ENABLE(VIDEO)
@@ -155,7 +155,7 @@ protected:
#endif
virtual void computeSizeBasedOnStyle(RenderStyle*) const = 0;
- virtual String fileListNameForWidth(const Vector<String>& filenames, const Font&, int width) const;
+ virtual String fileListNameForWidth(const FileList*, const Font&, int width, bool multipleFilesAllowed) const OVERRIDE;
virtual QRect inflateButtonRect(const QRect& originalRect) const;
diff --git a/Source/WebCore/platform/qt/RenderThemeQtMobile.cpp b/Source/WebCore/platform/qt/RenderThemeQtMobile.cpp
index 201a1b206..9155cd411 100644
--- a/Source/WebCore/platform/qt/RenderThemeQtMobile.cpp
+++ b/Source/WebCore/platform/qt/RenderThemeQtMobile.cpp
@@ -23,7 +23,6 @@
#include "config.h"
#include "RenderThemeQtMobile.h"
-#include "CSSStyleSelector.h"
#include "CSSValueKeywords.h"
#include "Color.h"
#include "Document.h"
@@ -35,15 +34,17 @@
#include "NotImplemented.h"
#include "Page.h"
#include "PaintInfo.h"
-#include "PassRefPtr.h"
#include "QWebPageClient.h"
#include "RenderBox.h"
#if ENABLE(PROGRESS_TAG)
#include "RenderProgress.h"
#endif
+#include "StyleResolver.h"
+
+#include <wtf/PassRefPtr.h>
+
#include <QColor>
#include <QFile>
-#include <QFontMetrics>
#include <QPainter>
#include <QPixmapCache>
@@ -56,7 +57,7 @@ static const int arrowBoxWidth = 26;
static const int frameWidth = 2;
static const int checkBoxWidth = 21;
static const int radioWidth = 21;
-static const int sliderSize = 19;
+static const int sliderSize = 20;
static const int buttonHeightRatio = 1.5;
static const float multipleComboDotsOffsetFactor = 1.8;
@@ -465,13 +466,16 @@ void StylePainterMobile::drawComboBox(const QRect& rect, bool multiple, bool ena
painter->drawPixmap(targetRect.toRect(), pic);
}
-void StylePainterMobile::drawProgress(const QRect& rect, double progress, bool leftToRight, bool animated) const
+void StylePainterMobile::drawProgress(const QRect& rect, double progress, bool leftToRight, bool animated, bool vertical) const
{
- const int border = rect.height() / 4;
- const QRect targetRect = rect.adjusted(0, border, 0, -border);
+ const int horizontalBorder = (vertical ? rect.width() / 4 : 0);
+ const int verticalBorder = (vertical ? 0 : rect.height() / 4);
+ const QRect targetRect = rect.adjusted(horizontalBorder, verticalBorder, -horizontalBorder, -verticalBorder);
QPixmap result;
- const QSize imageSize = sizeForPainterScale(targetRect);
+ QSize imageSize = sizeForPainterScale(targetRect);
+ if (vertical)
+ qSwap(imageSize.rheight(), imageSize.rwidth());
KeyIdentifier id;
id.type = KeyIdentifier::Progress;
id.width = imageSize.width();
@@ -516,7 +520,9 @@ void StylePainterMobile::drawProgress(const QRect& rect, double progress, bool l
}
insertIntoCache(id, result);
}
- painter->drawPixmap(targetRect, result);
+ QTransform transform;
+ transform.rotate(-90);
+ painter->drawPixmap(targetRect, vertical ? result.transformed(transform) : result);
}
void StylePainterMobile::drawSliderThumb(const QRect & rect, bool pressed) const
@@ -574,7 +580,6 @@ int RenderThemeQtMobile::popupInternalPaddingBottom(RenderStyle* style) const
void RenderThemeQtMobile::computeSizeBasedOnStyle(RenderStyle* renderStyle) const
{
QSize size(0, 0);
- const QFontMetrics fm(renderStyle->font().font());
switch (renderStyle->appearance()) {
case TextAreaPart:
@@ -607,11 +612,10 @@ void RenderThemeQtMobile::computeSizeBasedOnStyle(RenderStyle* renderStyle) cons
}
case PushButtonPart:
case SquareButtonPart:
- case ListButtonPart:
case DefaultButtonPart:
case ButtonPart:
case MenulistPart: {
- const int height = fm.height() * buttonHeightRatio * renderStyle->effectiveZoom();
+ const int height = renderStyle->fontMetrics().height() * buttonHeightRatio * renderStyle->effectiveZoom();
size = QSize(renderStyle->width().value(), height);
break;
}
@@ -626,7 +630,7 @@ void RenderThemeQtMobile::computeSizeBasedOnStyle(RenderStyle* renderStyle) cons
renderStyle->setMinHeight(Length(size.height(), Fixed));
}
-void RenderThemeQtMobile::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element*) const
+void RenderThemeQtMobile::adjustButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// Ditch the border.
style->resetBorder();
@@ -669,7 +673,7 @@ bool RenderThemeQtMobile::paintButton(RenderObject* o, const PaintInfo& i, const
return false;
}
-void RenderThemeQtMobile::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeQtMobile::adjustTextFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// Resetting the style like this leads to differences like:
// - RenderTextControl {INPUT} at (2,2) size 168x25 [bgcolor=#FFFFFF] border: (2px inset #000000)]
@@ -717,9 +721,9 @@ bool RenderThemeQtMobile::paintTextField(RenderObject* o, const PaintInfo& i, co
return false;
}
-void RenderThemeQtMobile::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeQtMobile::adjustMenuListStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
{
- RenderThemeQt::adjustMenuListStyle(selector, style, e);
+ RenderThemeQt::adjustMenuListStyle(styleResolver, style, e);
style->setPaddingLeft(Length(menuListPadding, Fixed));
}
@@ -801,10 +805,14 @@ bool RenderThemeQtMobile::paintSliderTrack(RenderObject* o, const PaintInfo& pi,
const double max = slider->maximum();
const double progress = (max - min > 0) ? (slider->valueAsNumber() - min) / (max - min) : 0;
- // Render the spin buttons for LTR or RTL accordingly.
- const int groovePadding = r.height() * sliderGrooveBorderRatio;
- const QRect rect(r);
- p.drawProgress(rect.adjusted(0, groovePadding, 0, -groovePadding), progress, o->style()->isLeftToRightDirection());
+ QRect rect(r);
+ const bool vertical = (o->style()->appearance() == SliderVerticalPart);
+ const int groovePadding = vertical ? r.width() * sliderGrooveBorderRatio : r.height() * sliderGrooveBorderRatio;
+ if (vertical)
+ rect.adjust(groovePadding, 0, -groovePadding, 0);
+ else
+ rect.adjust(0, groovePadding, 0, -groovePadding);
+ p.drawProgress(rect, progress, o->style()->isLeftToRightDirection(), /*animated = */ false, vertical);
return false;
}
diff --git a/Source/WebCore/platform/qt/RenderThemeQtMobile.h b/Source/WebCore/platform/qt/RenderThemeQtMobile.h
index c57a18029..952aa4f8a 100644
--- a/Source/WebCore/platform/qt/RenderThemeQtMobile.h
+++ b/Source/WebCore/platform/qt/RenderThemeQtMobile.h
@@ -53,16 +53,19 @@ public:
virtual bool delegatesMenuListRendering() const { return true; }
+ // drawFocusRing() will return early if the color is invalid.
+ virtual Color platformFocusRingColor() const { return Color(); }
+
protected:
- virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
@@ -135,7 +138,7 @@ public:
void drawRadioButton(const QRect&, bool checked, bool enabled = true);
void drawPushButton(const QRect&, bool sunken, bool enabled = true);
void drawComboBox(const QRect&, bool multiple, bool enabled = true);
- void drawProgress(const QRect&, double progress, bool leftToRight = true, bool animated = false) const;
+ void drawProgress(const QRect&, double progress, bool leftToRight = true, bool animated = false, bool vertical = false) const;
void drawSliderThumb(const QRect&, bool pressed) const;
private:
diff --git a/Source/WebCore/platform/qt/RunLoopQt.cpp b/Source/WebCore/platform/qt/RunLoopQt.cpp
index 2a87e2fc8..28ab67bde 100644
--- a/Source/WebCore/platform/qt/RunLoopQt.cpp
+++ b/Source/WebCore/platform/qt/RunLoopQt.cpp
@@ -39,13 +39,30 @@ namespace WebCore {
class RunLoop::TimerObject : public QObject {
Q_OBJECT
public:
- TimerObject(RunLoop* runLoop) : m_runLoop(runLoop)
+ TimerObject(RunLoop* runLoop)
+ : m_runLoop(runLoop)
+ , m_pendingPerformWorkInvocations(0)
{
int methodIndex = metaObject()->indexOfMethod("performWork()");
m_method = metaObject()->method(methodIndex);
}
- Q_SLOT void performWork() { m_runLoop->performWork(); }
+ Q_SLOT void performWork() {
+ // It may happen that a secondary thread adds more method invocations via
+ // RunLoop::dispatch(), which will schedule a call to this function. If during
+ // performWork() event loop messages get processed, it may happen that this
+ // function is called again. In this case we should protected ourselves against
+ // recursive - and thus out-of-order - message dispatching and instead perform
+ // the work serially.
+ m_pendingPerformWorkInvocations++;
+ if (m_pendingPerformWorkInvocations > 1)
+ return;
+
+ while (m_pendingPerformWorkInvocations) {
+ m_runLoop->performWork();
+ m_pendingPerformWorkInvocations--;
+ }
+ }
inline void wakeUp() { m_method.invoke(this, Qt::QueuedConnection); }
protected:
@@ -57,6 +74,7 @@ protected:
private:
RunLoop* m_runLoop;
QMetaMethod m_method;
+ int m_pendingPerformWorkInvocations;
};
static QEventLoop* currentEventLoop;
diff --git a/Source/WebCore/platform/qt/WheelEventQt.cpp b/Source/WebCore/platform/qt/WheelEventQt.cpp
deleted file mode 100644
index 3bd0da3ca..000000000
--- a/Source/WebCore/platform/qt/WheelEventQt.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- Copyright (C) 2008 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 "WheelEvent.h"
-
-#include "PlatformMouseEvent.h"
-#include "PlatformWheelEvent.h"
-#include "Scrollbar.h"
-
-#include <QGraphicsSceneWheelEvent>
-#include <QWheelEvent>
-#include <qapplication.h>
-#include <wtf/CurrentTime.h>
-
-namespace WebCore {
-
-void PlatformWheelEvent::applyDelta(int delta, Qt::Orientation orientation)
-{
- // A delta that is not mod 120 indicates a device that is sending
- // fine-resolution scroll events, so use the delta as number of wheel ticks
- // and number of pixels to scroll.See also webkit.org/b/29601
- bool fullTick = !(delta % 120);
-
- if (orientation == Qt::Horizontal) {
- m_deltaX = (fullTick) ? delta / 120.0f : delta;
- m_deltaY = 0;
- } else {
- m_deltaX = 0;
- m_deltaY = (fullTick) ? delta / 120.0f : delta;
- }
-
- m_wheelTicksX = m_deltaX;
- m_wheelTicksY = m_deltaY;
-
-#ifndef QT_NO_WHEELEVENT
- // Use the same single scroll step as QTextEdit
- // (in QTextEditPrivate::init [h,v]bar->setSingleStep)
- static const float cDefaultQtScrollStep = 20.f;
- m_deltaX *= (fullTick) ? QApplication::wheelScrollLines() * cDefaultQtScrollStep : 1;
- m_deltaY *= (fullTick) ? QApplication::wheelScrollLines() * cDefaultQtScrollStep : 1;
-#endif
-}
-
-PlatformWheelEvent::PlatformWheelEvent(QGraphicsSceneWheelEvent* e)
-#ifndef QT_NO_WHEELEVENT
- : PlatformEvent(PlatformEvent::Wheel, e->modifiers() & Qt::ShiftModifier, e->modifiers() & Qt::ControlModifier, e->modifiers() & Qt::AltModifier, e->modifiers() & Qt::MetaModifier, WTF::currentTime())
- , m_position(e->pos().toPoint())
- , m_globalPosition(e->screenPos())
- , m_granularity(ScrollByPixelWheelEvent)
- , m_directionInvertedFromDevice(false)
-#endif
-{
-#ifndef QT_NO_WHEELEVENT
- applyDelta(e->delta(), e->orientation());
-#else
- Q_UNUSED(e);
-#endif
-}
-
-PlatformWheelEvent::PlatformWheelEvent(QWheelEvent* e)
-#ifndef QT_NO_WHEELEVENT
- : PlatformEvent(PlatformEvent::Wheel, e->modifiers() & Qt::ShiftModifier, e->modifiers() & Qt::ControlModifier, e->modifiers() & Qt::AltModifier, e->modifiers() & Qt::MetaModifier, WTF::currentTime())
- , m_position(e->pos())
- , m_globalPosition(e->globalPos())
- , m_granularity(ScrollByPixelWheelEvent)
- , m_directionInvertedFromDevice(false)
-#endif
-{
-#ifndef QT_NO_WHEELEVENT
- applyDelta(e->delta(), e->orientation());
-#else
- Q_UNUSED(e);
-#endif
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/text/BidiContext.cpp b/Source/WebCore/platform/text/BidiContext.cpp
index aa196f0b8..6c08b08f2 100644
--- a/Source/WebCore/platform/text/BidiContext.cpp
+++ b/Source/WebCore/platform/text/BidiContext.cpp
@@ -27,6 +27,13 @@ namespace WebCore {
using namespace WTF::Unicode;
+struct SameSizeAsBidiContext : public RefCounted<SameSizeAsBidiContext> {
+ uint32_t bitfields : 16;
+ void* parent;
+};
+
+COMPILE_ASSERT(sizeof(BidiContext) == sizeof(SameSizeAsBidiContext), BidiContext_should_stay_small);
+
inline PassRefPtr<BidiContext> BidiContext::createUncached(unsigned char level, Direction direction, bool override, BidiEmbeddingSource source, BidiContext* parent)
{
return adoptRef(new BidiContext(level, direction, override, source, parent));
diff --git a/Source/WebCore/platform/text/BidiContext.h b/Source/WebCore/platform/text/BidiContext.h
index 9f45d6553..1d48d366f 100644
--- a/Source/WebCore/platform/text/BidiContext.h
+++ b/Source/WebCore/platform/text/BidiContext.h
@@ -59,9 +59,9 @@ private:
static PassRefPtr<BidiContext> createUncached(unsigned char level, WTF::Unicode::Direction, bool override, BidiEmbeddingSource, BidiContext* parent);
- unsigned char m_level;
+ unsigned m_level : 6; // The maximium bidi level is 62: http://unicode.org/reports/tr9/#Explicit_Levels_and_Directions
unsigned m_direction : 5; // Direction
- bool m_override : 1;
+ unsigned m_override : 1;
unsigned m_source : 1; // BidiEmbeddingSource
RefPtr<BidiContext> m_parent;
};
diff --git a/Source/WebCore/platform/text/BidiResolver.h b/Source/WebCore/platform/text/BidiResolver.h
index 5806ca55e..5f4ce15d6 100644
--- a/Source/WebCore/platform/text/BidiResolver.h
+++ b/Source/WebCore/platform/text/BidiResolver.h
@@ -854,7 +854,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
m_direction = m_status.lastStrong == LeftToRight ? LeftToRight : EuropeanNumber;
break;
default:
- ASSERT(false);
+ ASSERT_NOT_REACHED();
}
appendRun();
}
diff --git a/Source/WebCore/platform/text/LocaleICU.cpp b/Source/WebCore/platform/text/LocaleICU.cpp
new file mode 100644
index 000000000..f27c4e014
--- /dev/null
+++ b/Source/WebCore/platform/text/LocaleICU.cpp
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LocaleICU.h"
+
+#include "LocalizedStrings.h"
+#include <limits>
+#include <wtf/DateMath.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/StringBuilder.h>
+
+using namespace icu;
+using namespace std;
+
+namespace WebCore {
+
+LocaleICU::LocaleICU(const char* locale)
+ : m_locale(locale)
+ , m_numberFormat(0)
+ , m_shortDateFormat(0)
+ , m_didCreateDecimalFormat(false)
+ , m_didCreateShortDateFormat(false)
+#if ENABLE(CALENDAR_PICKER)
+ , m_firstDayOfWeek(0)
+#endif
+{
+}
+
+LocaleICU::~LocaleICU()
+{
+ unum_close(m_numberFormat);
+ udat_close(m_shortDateFormat);
+}
+
+PassOwnPtr<LocaleICU> LocaleICU::create(const char* localeString)
+{
+ return adoptPtr(new LocaleICU(localeString));
+}
+
+PassOwnPtr<LocaleICU> LocaleICU::createForCurrentLocale()
+{
+ return adoptPtr(new LocaleICU(0));
+}
+
+LocaleICU* LocaleICU::currentLocale()
+{
+ static LocaleICU* currentLocale = LocaleICU::createForCurrentLocale().leakPtr();
+ return currentLocale;
+}
+
+void LocaleICU::setDecimalSymbol(unsigned index, UNumberFormatSymbol symbol)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t bufferLength = unum_getSymbol(m_numberFormat, symbol, 0, 0, &status);
+ ASSERT(U_SUCCESS(status) || status == U_BUFFER_OVERFLOW_ERROR);
+ if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR)
+ return;
+ Vector<UChar> buffer(bufferLength);
+ status = U_ZERO_ERROR;
+ unum_getSymbol(m_numberFormat, symbol, buffer.data(), bufferLength, &status);
+ if (U_FAILURE(status))
+ return;
+ m_decimalSymbols[index] = String::adopt(buffer);
+}
+
+void LocaleICU::setDecimalTextAttribute(String& destination, UNumberFormatTextAttribute tag)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t bufferLength = unum_getTextAttribute(m_numberFormat, tag, 0, 0, &status);
+ ASSERT(U_SUCCESS(status) || status == U_BUFFER_OVERFLOW_ERROR);
+ if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR)
+ return;
+ Vector<UChar> buffer(bufferLength);
+ status = U_ZERO_ERROR;
+ unum_getTextAttribute(m_numberFormat, tag, buffer.data(), bufferLength, &status);
+ ASSERT(U_SUCCESS(status));
+ if (U_FAILURE(status))
+ return;
+ destination = String::adopt(buffer);
+}
+
+void LocaleICU::initializeDecimalFormat()
+{
+ if (m_didCreateDecimalFormat)
+ return;
+ m_didCreateDecimalFormat = true;
+ UErrorCode status = U_ZERO_ERROR;
+ m_numberFormat = unum_open(UNUM_DECIMAL, 0, 0, m_locale.data(), 0, &status);
+ if (!U_SUCCESS(status))
+ return;
+
+ setDecimalSymbol(0, UNUM_ZERO_DIGIT_SYMBOL);
+ setDecimalSymbol(1, UNUM_ONE_DIGIT_SYMBOL);
+ setDecimalSymbol(2, UNUM_TWO_DIGIT_SYMBOL);
+ setDecimalSymbol(3, UNUM_THREE_DIGIT_SYMBOL);
+ setDecimalSymbol(4, UNUM_FOUR_DIGIT_SYMBOL);
+ setDecimalSymbol(5, UNUM_FIVE_DIGIT_SYMBOL);
+ setDecimalSymbol(6, UNUM_SIX_DIGIT_SYMBOL);
+ setDecimalSymbol(7, UNUM_SEVEN_DIGIT_SYMBOL);
+ setDecimalSymbol(8, UNUM_EIGHT_DIGIT_SYMBOL);
+ setDecimalSymbol(9, UNUM_NINE_DIGIT_SYMBOL);
+ setDecimalSymbol(DecimalSeparatorIndex, UNUM_DECIMAL_SEPARATOR_SYMBOL);
+ setDecimalSymbol(GroupSeparatorIndex, UNUM_GROUPING_SEPARATOR_SYMBOL);
+ setDecimalTextAttribute(m_positivePrefix, UNUM_POSITIVE_PREFIX);
+ setDecimalTextAttribute(m_positiveSuffix, UNUM_POSITIVE_SUFFIX);
+ setDecimalTextAttribute(m_negativePrefix, UNUM_NEGATIVE_PREFIX);
+ setDecimalTextAttribute(m_negativeSuffix, UNUM_NEGATIVE_SUFFIX);
+ ASSERT(!m_positivePrefix.isEmpty() || !m_positiveSuffix.isEmpty() || !m_negativePrefix.isEmpty() || !m_negativeSuffix.isEmpty());
+}
+
+String LocaleICU::convertToLocalizedNumber(const String& input)
+{
+ initializeDecimalFormat();
+ if (!m_numberFormat || input.isEmpty())
+ return input;
+
+ unsigned i = 0;
+ bool isNegative = false;
+ UnicodeString ustring;
+ StringBuilder builder;
+ builder.reserveCapacity(input.length());
+
+ if (input[0] == '-') {
+ ++i;
+ isNegative = true;
+ builder.append(m_negativePrefix);
+ } else
+ builder.append(m_positivePrefix);
+
+ for (; i < input.length(); ++i) {
+ switch (input[i]) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ builder.append(m_decimalSymbols[input[i] - '0']);
+ break;
+ case '.':
+ builder.append(m_decimalSymbols[DecimalSeparatorIndex]);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ }
+
+ builder.append(isNegative ? m_negativeSuffix : m_positiveSuffix);
+
+ return builder.toString();
+}
+
+static bool matches(const String& text, unsigned position, const String& part)
+{
+ if (part.isEmpty())
+ return true;
+ if (position + part.length() > text.length())
+ return false;
+ for (unsigned i = 0; i < part.length(); ++i) {
+ if (text[position + i] != part[i])
+ return false;
+ }
+ return true;
+}
+
+bool LocaleICU::detectSignAndGetDigitRange(const String& input, bool& isNegative, unsigned& startIndex, unsigned& endIndex)
+{
+ startIndex = 0;
+ endIndex = input.length();
+ if (m_negativePrefix.isEmpty() && m_negativeSuffix.isEmpty()) {
+ if (input.startsWith(m_positivePrefix) && input.endsWith(m_positiveSuffix)) {
+ isNegative = false;
+ startIndex = m_positivePrefix.length();
+ endIndex -= m_positiveSuffix.length();
+ } else
+ isNegative = true;
+ } else {
+ if (input.startsWith(m_negativePrefix) && input.endsWith(m_negativeSuffix)) {
+ isNegative = true;
+ startIndex = m_negativePrefix.length();
+ endIndex -= m_negativeSuffix.length();
+ } else {
+ isNegative = false;
+ if (input.startsWith(m_positivePrefix) && input.endsWith(m_positiveSuffix)) {
+ startIndex = m_positivePrefix.length();
+ endIndex -= m_positiveSuffix.length();
+ } else
+ return false;
+ }
+ }
+ return true;
+}
+
+unsigned LocaleICU::matchedDecimalSymbolIndex(const String& input, unsigned& position)
+{
+ for (unsigned symbolIndex = 0; symbolIndex < DecimalSymbolsSize; ++symbolIndex) {
+ if (m_decimalSymbols[symbolIndex].length() && matches(input, position, m_decimalSymbols[symbolIndex])) {
+ position += m_decimalSymbols[symbolIndex].length();
+ return symbolIndex;
+ }
+ }
+ return DecimalSymbolsSize;
+}
+
+String LocaleICU::convertFromLocalizedNumber(const String& localized)
+{
+ initializeDecimalFormat();
+ String input = localized.stripWhiteSpace();
+ if (!m_numberFormat || input.isEmpty())
+ return input;
+
+ bool isNegative;
+ unsigned startIndex;
+ unsigned endIndex;
+ if (!detectSignAndGetDigitRange(input, isNegative, startIndex, endIndex)) {
+ // Input is broken. Returning an invalid number string.
+ return "*";
+ }
+
+ StringBuilder builder;
+ builder.reserveCapacity(input.length());
+ if (isNegative)
+ builder.append("-");
+ for (unsigned i = startIndex; i < endIndex;) {
+ unsigned symbolIndex = matchedDecimalSymbolIndex(input, i);
+ if (symbolIndex >= DecimalSymbolsSize)
+ return "*";
+ if (symbolIndex == DecimalSeparatorIndex)
+ builder.append('.');
+ else if (symbolIndex == GroupSeparatorIndex) {
+ // Ignore group separators.
+
+ } else
+ builder.append(static_cast<UChar>('0' + symbolIndex));
+ }
+ return builder.toString();
+}
+
+bool LocaleICU::initializeShortDateFormat()
+{
+ if (m_didCreateShortDateFormat)
+ return m_shortDateFormat;
+ const UChar gmtTimezone[3] = {'G', 'M', 'T'};
+ UErrorCode status = U_ZERO_ERROR;
+ m_shortDateFormat = udat_open(UDAT_NONE, UDAT_SHORT, m_locale.data(), gmtTimezone, WTF_ARRAY_LENGTH(gmtTimezone), 0, -1, &status);
+ m_didCreateShortDateFormat = true;
+ return m_shortDateFormat;
+}
+
+double LocaleICU::parseLocalizedDate(const String& input)
+{
+ if (!initializeShortDateFormat())
+ return numeric_limits<double>::quiet_NaN();
+ if (input.length() > static_cast<unsigned>(numeric_limits<int32_t>::max()))
+ return numeric_limits<double>::quiet_NaN();
+ int32_t inputLength = static_cast<int32_t>(input.length());
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t parsePosition = 0;
+ UDate date = udat_parse(m_shortDateFormat, input.characters(), inputLength, &parsePosition, &status);
+ if (parsePosition != inputLength || U_FAILURE(status))
+ return numeric_limits<double>::quiet_NaN();
+ // UDate, which is an alias of double, is compatible with our expectation.
+ return date;
+}
+
+String LocaleICU::formatLocalizedDate(const DateComponents& dateComponents)
+{
+ if (!initializeShortDateFormat())
+ return String();
+ double input = dateComponents.millisecondsSinceEpoch();
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t length = udat_format(m_shortDateFormat, input, 0, 0, 0, &status);
+ if (status != U_BUFFER_OVERFLOW_ERROR)
+ return String();
+ Vector<UChar> buffer(length);
+ status = U_ZERO_ERROR;
+ udat_format(m_shortDateFormat, input, buffer.data(), length, 0, &status);
+ if (U_FAILURE(status))
+ return String();
+ return String::adopt(buffer);
+}
+
+#if ENABLE(CALENDAR_PICKER)
+static inline bool isICUYearSymbol(UChar letter)
+{
+ return letter == 'y' || letter == 'Y';
+}
+
+static inline bool isICUMonthSymbol(UChar letter)
+{
+ return letter == 'M';
+}
+
+static inline bool isICUDayInMonthSymbol(UChar letter)
+{
+ return letter == 'd';
+}
+
+// Specification of the input:
+// http://icu-project.org/apiref/icu4c/classSimpleDateFormat.html#details
+static String localizeFormat(const Vector<UChar>& buffer)
+{
+ StringBuilder builder;
+ UChar lastChar = 0;
+ bool inQuote = false;
+ for (unsigned i = 0; i < buffer.size(); ++i) {
+ if (inQuote) {
+ if (buffer[i] == '\'') {
+ inQuote = false;
+ lastChar = 0;
+ ASSERT(i);
+ if (buffer[i - 1] == '\'')
+ builder.append('\'');
+ } else
+ builder.append(buffer[i]);
+ } else {
+ if (isASCIIAlpha(lastChar) && lastChar == buffer[i])
+ continue;
+ lastChar = buffer[i];
+ if (isICUYearSymbol(lastChar)) {
+ String text = dateFormatYearText();
+ builder.append(text.isEmpty() ? "Year" : text);
+ } else if (isICUMonthSymbol(lastChar)) {
+ String text = dateFormatMonthText();
+ builder.append(text.isEmpty() ? "Month" : text);
+ } else if (isICUDayInMonthSymbol(lastChar)) {
+ String text = dateFormatDayInMonthText();
+ builder.append(text.isEmpty() ? "Day" : text);
+ } else if (lastChar == '\'')
+ inQuote = true;
+ else
+ builder.append(lastChar);
+ }
+ }
+ return builder.toString();
+}
+
+void LocaleICU::initializeLocalizedDateFormatText()
+{
+ if (!m_localizedDateFormatText.isNull())
+ return;
+ m_localizedDateFormatText = String("");
+ if (!initializeShortDateFormat())
+ return;
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t length = udat_toPattern(m_shortDateFormat, TRUE, 0, 0, &status);
+ if (status != U_BUFFER_OVERFLOW_ERROR)
+ return;
+ Vector<UChar> buffer(length);
+ status = U_ZERO_ERROR;
+ udat_toPattern(m_shortDateFormat, TRUE, buffer.data(), length, &status);
+ if (U_FAILURE(status))
+ return;
+ m_localizedDateFormatText = localizeFormat(buffer);
+}
+
+String LocaleICU::localizedDateFormatText()
+{
+ initializeLocalizedDateFormatText();
+ return m_localizedDateFormatText;
+}
+
+PassOwnPtr<Vector<String> > LocaleICU::createLabelVector(UDateFormatSymbolType type, int32_t startIndex, int32_t size)
+{
+ if (!m_shortDateFormat)
+ return PassOwnPtr<Vector<String> >();
+ if (udat_countSymbols(m_shortDateFormat, type) != startIndex + size)
+ return PassOwnPtr<Vector<String> >();
+
+ OwnPtr<Vector<String> > labels = adoptPtr(new Vector<String>());
+ labels->reserveCapacity(size);
+ for (int32_t i = 0; i < size; ++i) {
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t length = udat_getSymbols(m_shortDateFormat, type, startIndex + i, 0, 0, &status);
+ if (status != U_BUFFER_OVERFLOW_ERROR)
+ return PassOwnPtr<Vector<String> >();
+ Vector<UChar> buffer(length);
+ status = U_ZERO_ERROR;
+ udat_getSymbols(m_shortDateFormat, type, startIndex + i, buffer.data(), length, &status);
+ if (U_FAILURE(status))
+ return PassOwnPtr<Vector<String> >();
+ labels->append(String::adopt(buffer));
+ }
+ return labels.release();
+}
+
+static PassOwnPtr<Vector<String> > createFallbackMonthLabels()
+{
+ OwnPtr<Vector<String> > labels = adoptPtr(new Vector<String>());
+ labels->reserveCapacity(WTF_ARRAY_LENGTH(WTF::monthFullName));
+ for (unsigned i = 0; i < WTF_ARRAY_LENGTH(WTF::monthFullName); ++i)
+ labels->append(WTF::monthFullName[i]);
+ return labels.release();
+}
+
+static PassOwnPtr<Vector<String> > createFallbackWeekDayShortLabels()
+{
+ OwnPtr<Vector<String> > labels = adoptPtr(new Vector<String>());
+ labels->reserveCapacity(7);
+ labels->append("Sun");
+ labels->append("Mon");
+ labels->append("Tue");
+ labels->append("Wed");
+ labels->append("Thu");
+ labels->append("Fri");
+ labels->append("Sat");
+ return labels.release();
+}
+
+void LocaleICU::initializeCalendar()
+{
+ if (m_monthLabels && m_weekDayShortLabels)
+ return;
+
+ if (!initializeShortDateFormat()) {
+ m_firstDayOfWeek = 0;
+ m_monthLabels = createFallbackMonthLabels();
+ m_weekDayShortLabels = createFallbackWeekDayShortLabels();
+ return;
+ }
+ m_firstDayOfWeek = ucal_getAttribute(udat_getCalendar(m_shortDateFormat), UCAL_FIRST_DAY_OF_WEEK) - UCAL_SUNDAY;
+
+ m_monthLabels = createLabelVector(UDAT_MONTHS, UCAL_JANUARY, 12);
+ if (!m_monthLabels)
+ m_monthLabels = createFallbackMonthLabels();
+
+ m_weekDayShortLabels = createLabelVector(UDAT_SHORT_WEEKDAYS, UCAL_SUNDAY, 7);
+ if (!m_weekDayShortLabels)
+ m_weekDayShortLabels = createFallbackWeekDayShortLabels();
+}
+
+const Vector<String>& LocaleICU::monthLabels()
+{
+ initializeCalendar();
+ return *m_monthLabels;
+}
+
+const Vector<String>& LocaleICU::weekDayShortLabels()
+{
+ initializeCalendar();
+ return *m_weekDayShortLabels;
+}
+
+unsigned LocaleICU::firstDayOfWeek()
+{
+ initializeCalendar();
+ return m_firstDayOfWeek;
+}
+#endif
+
+} // namespace WebCore
+
diff --git a/Source/WebCore/platform/text/LocalizedNumberICU.h b/Source/WebCore/platform/text/LocaleICU.h
index fd85622cd..77360a2aa 100644
--- a/Source/WebCore/platform/text/LocalizedNumberICU.h
+++ b/Source/WebCore/platform/text/LocaleICU.h
@@ -28,9 +28,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef LocalizedNumberICU_h
-#define LocalizedNumberICU_h
+#ifndef LocaleICU_h
+#define LocaleICU_h
+#include "DateComponents.h"
+#include <unicode/udat.h>
#include <unicode/unum.h>
#include <wtf/Forward.h>
#include <wtf/OwnPtr.h>
@@ -39,17 +41,32 @@
namespace WebCore {
-// We should use this class only for LocalizedNumberICU.cpp and LocalizedNumberICUTest.cpp.
-class ICULocale {
+// We should use this class only for LocalizedNumberICU.cpp, LocalizedDateICU.cpp,
+// and LocalizedNumberICUTest.cpp.
+class LocaleICU {
public:
- static PassOwnPtr<ICULocale> create(const char* localeString);
- static PassOwnPtr<ICULocale> createForCurrentLocale();
- ~ICULocale();
+ static PassOwnPtr<LocaleICU> create(const char* localeString);
+ static LocaleICU* currentLocale();
+ ~LocaleICU();
+
+ // For LocalizedNumber
String convertToLocalizedNumber(const String&);
String convertFromLocalizedNumber(const String&);
+ // For LocalizedDate
+ double parseLocalizedDate(const String&);
+ String formatLocalizedDate(const DateComponents&);
+#if ENABLE(CALENDAR_PICKER)
+ String localizedDateFormatText();
+
+ const Vector<String>& monthLabels();
+ const Vector<String>& weekDayShortLabels();
+ unsigned firstDayOfWeek();
+#endif
+
private:
- explicit ICULocale(const char*);
+ static PassOwnPtr<LocaleICU> createForCurrentLocale();
+ explicit LocaleICU(const char*);
void setDecimalSymbol(unsigned index, UNumberFormatSymbol);
void setDecimalTextAttribute(String&, UNumberFormatTextAttribute);
void initializeDecimalFormat();
@@ -57,8 +74,17 @@ private:
bool detectSignAndGetDigitRange(const String& input, bool& isNegative, unsigned& startIndex, unsigned& endIndex);
unsigned matchedDecimalSymbolIndex(const String& input, unsigned& position);
+ bool initializeShortDateFormat();
+
+#if ENABLE(CALENDAR_PICKER)
+ void initializeLocalizedDateFormatText();
+ PassOwnPtr<Vector<String> > createLabelVector(UDateFormatSymbolType, int32_t startIndex, int32_t size);
+ void initializeCalendar();
+#endif
+
CString m_locale;
UNumberFormat* m_numberFormat;
+ UDateFormat* m_shortDateFormat;
enum {
// 0-9 for digits.
DecimalSeparatorIndex = 10,
@@ -71,6 +97,14 @@ private:
String m_negativePrefix;
String m_negativeSuffix;
bool m_didCreateDecimalFormat;
+ bool m_didCreateShortDateFormat;
+
+#if ENABLE(CALENDAR_PICKER)
+ String m_localizedDateFormatText;
+ OwnPtr<Vector<String> > m_monthLabels;
+ OwnPtr<Vector<String> > m_weekDayShortLabels;
+ unsigned m_firstDayOfWeek;
+#endif
};
}
diff --git a/Source/WebCore/platform/text/LocaleToScriptMapping.h b/Source/WebCore/platform/text/LocaleToScriptMapping.h
index 0cedb59fb..d5c8c7603 100644
--- a/Source/WebCore/platform/text/LocaleToScriptMapping.h
+++ b/Source/WebCore/platform/text/LocaleToScriptMapping.h
@@ -36,7 +36,8 @@
namespace WebCore {
-UScriptCode localeToScriptCodeForFontSelection(const String& locale);
+UScriptCode localeToScriptCodeForFontSelection(const String&);
+UScriptCode scriptNameToCode(const String&);
}
diff --git a/Source/WebCore/platform/text/LocaleToScriptMappingDefault.cpp b/Source/WebCore/platform/text/LocaleToScriptMappingDefault.cpp
index 7c34e74d5..4ed03ce4e 100644
--- a/Source/WebCore/platform/text/LocaleToScriptMappingDefault.cpp
+++ b/Source/WebCore/platform/text/LocaleToScriptMappingDefault.cpp
@@ -37,7 +37,7 @@
namespace WebCore {
-static UScriptCode getScriptCode(const String& scriptName)
+UScriptCode scriptNameToCode(const String& scriptName)
{
struct ScriptNameCode {
const char* name;
@@ -158,7 +158,7 @@ static UScriptCode getScriptCode(const String& scriptName)
scriptNameCodeMap.set(scriptNameCodeList[i].name, scriptNameCodeList[i].code);
}
- HashMap<String, UScriptCode>::iterator it = scriptNameCodeMap.find(scriptName);
+ HashMap<String, UScriptCode>::iterator it = scriptNameCodeMap.find(scriptName.lower());
if (it != scriptNameCodeMap.end())
return it->second;
return USCRIPT_INVALID_CODE;
@@ -387,7 +387,7 @@ UScriptCode localeToScriptCodeForFontSelection(const String& locale)
size_t pos = canonicalLocale.reverseFind('_');
if (pos == notFound)
break;
- UScriptCode code = getScriptCode(canonicalLocale.substring(pos + 1));
+ UScriptCode code = scriptNameToCode(canonicalLocale.substring(pos + 1));
if (code != USCRIPT_INVALID_CODE && code != USCRIPT_UNKNOWN)
return code;
canonicalLocale = canonicalLocale.substring(0, pos);
diff --git a/Source/WebCore/platform/text/LocaleToScriptMappingICU.cpp b/Source/WebCore/platform/text/LocaleToScriptMappingICU.cpp
index 1710c7969..6c60d821e 100644
--- a/Source/WebCore/platform/text/LocaleToScriptMappingICU.cpp
+++ b/Source/WebCore/platform/text/LocaleToScriptMappingICU.cpp
@@ -77,4 +77,12 @@ UScriptCode localeToScriptCodeForFontSelection(const String& locale)
return scriptCodeForFontSelection(scriptCode);
}
+UScriptCode scriptNameToCode(const String& name)
+{
+ int32_t code = u_getPropertyValueEnum(UCHAR_SCRIPT, name.utf8().data());
+ if (code >= 0 && code < USCRIPT_CODE_LIMIT)
+ return static_cast<UScriptCode>(code);
+ return USCRIPT_INVALID_CODE;
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/text/LocaleWin.cpp b/Source/WebCore/platform/text/LocaleWin.cpp
new file mode 100644
index 000000000..82f927551
--- /dev/null
+++ b/Source/WebCore/platform/text/LocaleWin.cpp
@@ -0,0 +1,593 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LocaleWin.h"
+
+#include "DateComponents.h"
+#include "LocalizedStrings.h"
+#include <limits>
+#include <windows.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/DateMath.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/StringBuilder.h>
+
+using namespace std;
+
+namespace WebCore {
+
+// Windows doesn't have an API to parse locale-specific date string,
+// and GetDateFormat() and GetDateFormatEx() don't support years older
+// than 1600, which we should support according to the HTML
+// standard. So, we obtain the date format from the system, but we
+// format/parse a date by our own code.
+
+inline LocaleWin::LocaleWin(LCID lcid)
+ : m_lcid(lcid)
+{
+ struct tm tm;
+ getCurrentLocalTime(&tm);
+ m_baseYear = tm.tm_year + 1900;
+
+#if ENABLE(CALENDAR_PICKER)
+ DWORD value = 0;
+ ::GetLocaleInfo(m_lcid, LOCALE_IFIRSTDAYOFWEEK | LOCALE_RETURN_NUMBER, reinterpret_cast<LPWSTR>(&value), sizeof(value) / sizeof(TCHAR));
+ // 0:Monday, ..., 6:Sunday.
+ // We need 1 for Monday, 0 for Sunday.
+ m_firstDayOfWeek = (value + 1) % 7;
+#endif
+}
+
+PassOwnPtr<LocaleWin> LocaleWin::create(LCID lcid)
+{
+ return adoptPtr(new LocaleWin(lcid));
+}
+
+LocaleWin* LocaleWin::currentLocale()
+{
+ // Ideally we should make LCID from defaultLanguage(). But
+ // ::LocaleNameToLCID() is available since Windows Vista.
+ static LocaleWin* currentLocale = LocaleWin::create(LOCALE_USER_DEFAULT).leakPtr();
+ return currentLocale;
+}
+
+LocaleWin::~LocaleWin()
+{
+}
+
+String LocaleWin::getLocaleInfoString(LCTYPE type)
+{
+ int bufferSizeWithNUL = ::GetLocaleInfo(m_lcid, type, 0, 0);
+ if (bufferSizeWithNUL <= 0)
+ return String();
+ Vector<UChar> buffer(bufferSizeWithNUL);
+ ::GetLocaleInfo(m_lcid, type, buffer.data(), bufferSizeWithNUL);
+ buffer.shrink(bufferSizeWithNUL - 1);
+ return String::adopt(buffer);
+}
+
+void LocaleWin::ensureShortMonthLabels()
+{
+ if (!m_shortMonthLabels.isEmpty())
+ return;
+ const LCTYPE types[12] = {
+ LOCALE_SABBREVMONTHNAME1,
+ LOCALE_SABBREVMONTHNAME2,
+ LOCALE_SABBREVMONTHNAME3,
+ LOCALE_SABBREVMONTHNAME4,
+ LOCALE_SABBREVMONTHNAME5,
+ LOCALE_SABBREVMONTHNAME6,
+ LOCALE_SABBREVMONTHNAME7,
+ LOCALE_SABBREVMONTHNAME8,
+ LOCALE_SABBREVMONTHNAME9,
+ LOCALE_SABBREVMONTHNAME10,
+ LOCALE_SABBREVMONTHNAME11,
+ LOCALE_SABBREVMONTHNAME12,
+ };
+ m_shortMonthLabels.reserveCapacity(WTF_ARRAY_LENGTH(types));
+ for (unsigned i = 0; i < WTF_ARRAY_LENGTH(types); ++i) {
+ m_shortMonthLabels.append(getLocaleInfoString(types[i]));
+ if (m_shortMonthLabels.last().isEmpty()) {
+ m_shortMonthLabels.shrink(0);
+ m_shortMonthLabels.reserveCapacity(WTF_ARRAY_LENGTH(WTF::monthName));
+ for (unsigned m = 0; m < WTF_ARRAY_LENGTH(WTF::monthName); ++m)
+ m_shortMonthLabels.append(WTF::monthName[m]);
+ return;
+ }
+ }
+}
+
+// -------------------------------- Tokenized date format
+
+struct DateFormatToken {
+ enum Type {
+ Literal,
+ Day1,
+ Day2,
+ Month1,
+ Month2,
+ Month3,
+ Month4,
+ Year1,
+ Year2,
+ Year4,
+ };
+ Type type;
+ String data; // This is valid only if type==Literal.
+
+ DateFormatToken(Type type)
+ : type(type)
+ { }
+
+ DateFormatToken(const String& data)
+ : type(Literal)
+ , data(data)
+ { }
+
+ DateFormatToken(const DateFormatToken& token)
+ : type(token.type)
+ , data(token.data)
+ { }
+};
+
+static inline bool isEraSymbol(UChar letter) { return letter == 'g'; }
+static inline bool isYearSymbol(UChar letter) { return letter == 'y'; }
+static inline bool isMonthSymbol(UChar letter) { return letter == 'M'; }
+static inline bool isDaySymbol(UChar letter) { return letter == 'd'; }
+
+static unsigned countContinuousLetters(const String& format, unsigned index)
+{
+ unsigned count = 1;
+ UChar reference = format[index];
+ while (index + 1 < format.length()) {
+ if (format[++index] != reference)
+ break;
+ ++count;
+ }
+ return count;
+}
+
+static void commitLiteralToken(StringBuilder& literalBuffer, Vector<DateFormatToken>& tokens)
+{
+ if (literalBuffer.length() <= 0)
+ return;
+ tokens.append(DateFormatToken(literalBuffer.toString()));
+ literalBuffer.clear();
+}
+
+// See http://msdn.microsoft.com/en-us/library/dd317787(v=vs.85).aspx
+static Vector<DateFormatToken> parseDateFormat(const String format)
+{
+ Vector<DateFormatToken> tokens;
+ StringBuilder literalBuffer;
+ bool inQuote = false;
+ for (unsigned i = 0; i < format.length(); ++i) {
+ UChar ch = format[i];
+ if (inQuote) {
+ if (ch == '\'') {
+ inQuote = false;
+ ASSERT(i);
+ if (format[i - 1] == '\'')
+ literalBuffer.append('\'');
+ } else
+ literalBuffer.append(ch);
+ continue;
+ }
+
+ if (ch == '\'') {
+ inQuote = true;
+ if (i > 0 && format[i - 1] == '\'')
+ literalBuffer.append(ch);
+ } else if (isYearSymbol(ch)) {
+ commitLiteralToken(literalBuffer, tokens);
+ unsigned count = countContinuousLetters(format, i);
+ i += count - 1;
+ if (count == 1)
+ tokens.append(DateFormatToken(DateFormatToken::Year1));
+ else if (count == 2)
+ tokens.append(DateFormatToken(DateFormatToken::Year2));
+ else
+ tokens.append(DateFormatToken(DateFormatToken::Year4));
+ } else if (isMonthSymbol(ch)) {
+ commitLiteralToken(literalBuffer, tokens);
+ unsigned count = countContinuousLetters(format, i);
+ i += count - 1;
+ if (count == 1)
+ tokens.append(DateFormatToken(DateFormatToken::Month1));
+ else if (count == 2)
+ tokens.append(DateFormatToken(DateFormatToken::Month2));
+ else if (count == 3)
+ tokens.append(DateFormatToken(DateFormatToken::Month3));
+ else
+ tokens.append(DateFormatToken(DateFormatToken::Month4));
+ } else if (isDaySymbol(ch)) {
+ commitLiteralToken(literalBuffer, tokens);
+ unsigned count = countContinuousLetters(format, i);
+ i += count - 1;
+ if (count == 1)
+ tokens.append(DateFormatToken(DateFormatToken::Day1));
+ else
+ tokens.append(DateFormatToken(DateFormatToken::Day2));
+ } else if (isEraSymbol(ch)) {
+ // Just ignore era.
+ // HTML5 date supports only A.D.
+ } else
+ literalBuffer.append(ch);
+ }
+ commitLiteralToken(literalBuffer, tokens);
+ return tokens;
+}
+
+// -------------------------------- Parsing
+
+// Returns -1 if parsing fails.
+static int parseNumber(const String& input, unsigned& index)
+{
+ unsigned digitsStart = index;
+ while (index < input.length() && isASCIIDigit(input[index]))
+ index++;
+ if (digitsStart == index)
+ return -1;
+ bool ok = false;
+ int number = input.substring(digitsStart, index - digitsStart).toInt(&ok);
+ return ok ? number : -1;
+}
+
+// Returns 0-based month number. Returns -1 if parsing fails.
+int LocaleWin::parseNumberOrMonth(const String& input, unsigned& index)
+{
+ int result = parseNumber(input, index);
+ if (result >= 0) {
+ if (result < 1 || result > 12)
+ return -1;
+ return result - 1;
+ }
+ for (unsigned m = 0; m < m_monthLabels.size(); ++m) {
+ unsigned labelLength = m_monthLabels[m].length();
+ if (equalIgnoringCase(input.substring(index, labelLength), m_monthLabels[m])) {
+ index += labelLength;
+ return m;
+ }
+ }
+ for (unsigned m = 0; m < m_shortMonthLabels.size(); ++m) {
+ unsigned labelLength = m_shortMonthLabels[m].length();
+ if (equalIgnoringCase(input.substring(index, labelLength), m_shortMonthLabels[m])) {
+ index += labelLength;
+ return m;
+ }
+ }
+ return -1;
+}
+
+double LocaleWin::parseDate(const String& input)
+{
+ ensureShortDateTokens();
+ return parseDate(m_shortDateTokens, m_baseYear, input);
+}
+
+double LocaleWin::parseDate(const String& format, int baseYear, const String& input)
+{
+ return parseDate(parseDateFormat(format), baseYear, input);
+}
+
+double LocaleWin::parseDate(const Vector<DateFormatToken>& tokens, int baseYear, const String& input)
+{
+ ensureShortMonthLabels();
+ ensureMonthLabels();
+ const double NaN = numeric_limits<double>::quiet_NaN();
+ unsigned inputIndex = 0;
+ int day = -1, month = -1, year = -1;
+ for (unsigned i = 0; i < tokens.size(); ++i) {
+ switch (tokens[i].type) {
+ case DateFormatToken::Literal: {
+ String data = tokens[i].data;
+ unsigned literalLength = data.length();
+ if (input.substring(inputIndex, literalLength) == data)
+ inputIndex += literalLength;
+ // Go ahead even if the input doesn't have this string.
+ break;
+ }
+ case DateFormatToken::Day1:
+ case DateFormatToken::Day2:
+ day = parseNumber(input, inputIndex);
+ if (day < 1 || day > 31)
+ return NaN;
+ break;
+ case DateFormatToken::Month1:
+ case DateFormatToken::Month2:
+ case DateFormatToken::Month3:
+ case DateFormatToken::Month4:
+ month = parseNumberOrMonth(input, inputIndex);
+ if (month < 0 || month > 11)
+ return NaN;
+ break;
+ case DateFormatToken::Year1: {
+ unsigned oldIndex = inputIndex;
+ year = parseNumber(input, inputIndex);
+ if (year <= 0)
+ return NaN;
+ if (inputIndex - oldIndex == 1) {
+ int shortYear = baseYear % 10;
+ int decade = baseYear - shortYear;
+ if (shortYear >= 5)
+ year += shortYear - 4 <= year ? decade : decade + 10;
+ else
+ year += shortYear + 5 >= year ? decade : decade - 10;
+ }
+ break;
+ }
+ case DateFormatToken::Year2: {
+ unsigned oldIndex = inputIndex;
+ year = parseNumber(input, inputIndex);
+ if (year <= 0)
+ return NaN;
+ if (inputIndex - oldIndex == 2) {
+ int shortYear = baseYear % 100;
+ int century = baseYear - shortYear;
+ if (shortYear >= 50)
+ year += shortYear - 49 <= year ? century : century + 100;
+ else
+ year += shortYear + 50 >= year ? century : century - 100;
+ }
+ break;
+ }
+ case DateFormatToken::Year4:
+ year = parseNumber(input, inputIndex);
+ if (year <= 0)
+ return NaN;
+ break;
+ }
+ }
+ if (year <= 0 || month < 0 || day <= 0)
+ return NaN;
+ return dateToDaysFrom1970(year, month, day) * msPerDay;
+}
+
+// -------------------------------- Formatting
+
+static inline void appendNumber(int value, StringBuilder& buffer)
+{
+ buffer.append(String::number(value));
+}
+
+static void appendTwoDigitsNumber(int value, StringBuilder& buffer)
+{
+ if (value >= 0 && value < 10)
+ buffer.append("0");
+ buffer.append(String::number(value));
+}
+
+static void appendFourDigitsNumber(int value, StringBuilder& buffer)
+{
+ if (value < 0) {
+ buffer.append(String::number(value));
+ return;
+ }
+ if (value < 10)
+ buffer.append("000");
+ else if (value < 100)
+ buffer.append("00");
+ else if (value < 1000)
+ buffer.append("0");
+ buffer.append(String::number(value));
+}
+
+String LocaleWin::formatDate(const DateComponents& dateComponents)
+{
+ ensureShortDateTokens();
+ return formatDate(m_shortDateTokens, m_baseYear, dateComponents.fullYear(), dateComponents.month(), dateComponents.monthDay());
+}
+
+String LocaleWin::formatDate(const String& format, int baseYear, int year, int month, int day)
+{
+ return formatDate(parseDateFormat(format), baseYear, year, month, day);
+}
+
+String LocaleWin::formatDate(const Vector<DateFormatToken>& tokens, int baseYear, int year, int month, int day)
+{
+ ensureShortMonthLabels();
+ ensureMonthLabels();
+ StringBuilder buffer;
+ for (unsigned i = 0; i < tokens.size(); ++i) {
+ switch (tokens[i].type) {
+ case DateFormatToken::Literal:
+ buffer.append(tokens[i].data);
+ break;
+ case DateFormatToken::Day1:
+ appendNumber(day, buffer);
+ break;
+ case DateFormatToken::Day2:
+ appendTwoDigitsNumber(day, buffer);
+ break;
+ case DateFormatToken::Month1:
+ appendNumber(month + 1, buffer);
+ break;
+ case DateFormatToken::Month2:
+ appendTwoDigitsNumber(month + 1, buffer);
+ break;
+ case DateFormatToken::Month3:
+ if (0 <= month && month < static_cast<int>(m_shortMonthLabels.size()))
+ buffer.append(m_shortMonthLabels[month]);
+ else
+ appendNumber(month + 1, buffer);
+ break;
+ case DateFormatToken::Month4:
+ if (0 <= month && month < static_cast<int>(m_monthLabels.size()))
+ buffer.append(m_monthLabels[month]);
+ else
+ appendNumber(month + 1, buffer);
+ break;
+ case DateFormatToken::Year1: {
+ if (baseYear - 4 <= year && year <= baseYear + 5)
+ appendNumber(year % 10, buffer);
+ else
+ appendFourDigitsNumber(year, buffer);
+ break;
+ }
+ case DateFormatToken::Year2: {
+ if (baseYear - 49 <= year && year <= baseYear + 50)
+ appendTwoDigitsNumber(year % 100, buffer);
+ else
+ appendFourDigitsNumber(year, buffer);
+ break;
+ }
+ case DateFormatToken::Year4:
+ appendFourDigitsNumber(year, buffer);
+ break;
+ }
+ }
+ return buffer.toString();
+}
+
+void LocaleWin::ensureShortDateTokens()
+{
+ if (!m_shortDateTokens.isEmpty())
+ return;
+ m_shortDateTokens = parseDateFormat(getLocaleInfoString(LOCALE_SSHORTDATE));
+}
+
+static String substituteLabelsIntoFormat(const Vector<DateFormatToken>& tokens, const String& yearText, const String& monthText, const String& dayText)
+{
+ String nonEmptyDayText = dayText.isEmpty() ? "Day" : dayText;
+ String nonEmptyMonthText = monthText.isEmpty() ? "Month" : monthText;
+ String nonEmptyYearText = yearText.isEmpty() ? "Year" : yearText;
+ StringBuilder buffer;
+ for (unsigned i = 0; i < tokens.size(); ++i) {
+ switch (tokens[i].type) {
+ case DateFormatToken::Literal:
+ buffer.append(tokens[i].data);
+ break;
+ case DateFormatToken::Day1:
+ case DateFormatToken::Day2:
+ buffer.append(nonEmptyDayText);
+ break;
+ case DateFormatToken::Month1:
+ case DateFormatToken::Month2:
+ case DateFormatToken::Month3:
+ case DateFormatToken::Month4:
+ buffer.append(nonEmptyMonthText);
+ break;
+ case DateFormatToken::Year1:
+ case DateFormatToken::Year2:
+ case DateFormatToken::Year4:
+ buffer.append(nonEmptyYearText);
+ break;
+ }
+ }
+ return buffer.toString();
+}
+
+String LocaleWin::dateFormatText()
+{
+ ensureShortDateTokens();
+ return substituteLabelsIntoFormat(m_shortDateTokens, dateFormatYearText(), dateFormatMonthText(), dateFormatDayInMonthText());
+}
+
+String LocaleWin::dateFormatText(const String& format, const String& yearText, const String& monthText, const String& dayText)
+{
+ return substituteLabelsIntoFormat(parseDateFormat(format), yearText, monthText, dayText);
+}
+
+void LocaleWin::ensureMonthLabels()
+{
+ if (!m_monthLabels.isEmpty())
+ return;
+ const LCTYPE types[12] = {
+ LOCALE_SMONTHNAME1,
+ LOCALE_SMONTHNAME2,
+ LOCALE_SMONTHNAME3,
+ LOCALE_SMONTHNAME4,
+ LOCALE_SMONTHNAME5,
+ LOCALE_SMONTHNAME6,
+ LOCALE_SMONTHNAME7,
+ LOCALE_SMONTHNAME8,
+ LOCALE_SMONTHNAME9,
+ LOCALE_SMONTHNAME10,
+ LOCALE_SMONTHNAME11,
+ LOCALE_SMONTHNAME12,
+ };
+ m_monthLabels.reserveCapacity(WTF_ARRAY_LENGTH(types));
+ for (unsigned i = 0; i < WTF_ARRAY_LENGTH(types); ++i) {
+ m_monthLabels.append(getLocaleInfoString(types[i]));
+ if (m_monthLabels.last().isEmpty()) {
+ m_monthLabels.shrink(0);
+ m_monthLabels.reserveCapacity(WTF_ARRAY_LENGTH(WTF::monthFullName));
+ for (unsigned m = 0; m < WTF_ARRAY_LENGTH(WTF::monthFullName); ++m)
+ m_monthLabels.append(WTF::monthFullName[m]);
+ return;
+ }
+ }
+}
+
+void LocaleWin::ensureWeekDayShortLabels()
+{
+ if (!m_weekDayShortLabels.isEmpty())
+ return;
+ const LCTYPE types[7] = {
+ LOCALE_SABBREVDAYNAME7, // Sunday
+ LOCALE_SABBREVDAYNAME1, // Monday
+ LOCALE_SABBREVDAYNAME2,
+ LOCALE_SABBREVDAYNAME3,
+ LOCALE_SABBREVDAYNAME4,
+ LOCALE_SABBREVDAYNAME5,
+ LOCALE_SABBREVDAYNAME6
+ };
+ m_weekDayShortLabels.reserveCapacity(WTF_ARRAY_LENGTH(types));
+ for (unsigned i = 0; i < WTF_ARRAY_LENGTH(types); ++i) {
+ m_weekDayShortLabels.append(getLocaleInfoString(types[i]));
+ if (m_weekDayShortLabels.last().isEmpty()) {
+ m_weekDayShortLabels.shrink(0);
+ m_weekDayShortLabels.reserveCapacity(WTF_ARRAY_LENGTH(WTF::weekdayName));
+ for (unsigned w = 0; w < WTF_ARRAY_LENGTH(WTF::weekdayName); ++w) {
+ // weekdayName starts with Monday.
+ m_weekDayShortLabels.append(WTF::weekdayName[(w + 6) % 7]);
+ }
+ return;
+ }
+ }
+}
+
+#if ENABLE(CALENDAR_PICKER)
+const Vector<String>& LocaleWin::monthLabels()
+{
+ ensureMonthLabels();
+ return m_monthLabels;
+}
+
+const Vector<String>& LocaleWin::weekDayShortLabels()
+{
+ ensureWeekDayShortLabels();
+ return m_weekDayShortLabels;
+}
+#endif
+
+}
diff --git a/Source/WebCore/platform/text/LocaleWin.h b/Source/WebCore/platform/text/LocaleWin.h
new file mode 100644
index 000000000..6a75c9945
--- /dev/null
+++ b/Source/WebCore/platform/text/LocaleWin.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LocaleWin_h
+#define LocaleWin_h
+
+#include <windows.h>
+#include <wtf/Forward.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class DateComponents;
+struct DateFormatToken;
+
+class LocaleWin {
+public:
+ static PassOwnPtr<LocaleWin> create(LCID);
+ static LocaleWin* currentLocale();
+ ~LocaleWin();
+ double parseDate(const String&);
+ String formatDate(const DateComponents&);
+#if ENABLE(CALENDAR_PICKER)
+ String dateFormatText();
+ const Vector<String>& monthLabels();
+ const Vector<String>& weekDayShortLabels();
+ unsigned firstDayOfWeek() { return m_firstDayOfWeek; }
+#endif
+
+ // For testing.
+ double parseDate(const String& format, int baseYear, const String& input);
+ String formatDate(const String& format, int baseYear, int year, int month, int day);
+ static String dateFormatText(const String& format, const String& yearText, const String& monthText, const String& dayText);
+
+private:
+ explicit LocaleWin(LCID);
+ String getLocaleInfoString(LCTYPE);
+ void ensureShortMonthLabels();
+ void ensureMonthLabels();
+ void ensureShortDateTokens();
+ int parseNumberOrMonth(const String&, unsigned& index);
+ double parseDate(const Vector<DateFormatToken>&, int baseYear, const String&);
+ String formatDate(const Vector<DateFormatToken>&, int baseYear, int year, int month, int day);
+#if ENABLE(CALENDAR_PICKER)
+ void ensureWeekDayShortLabels();
+#endif
+
+ LCID m_lcid;
+ int m_baseYear;
+ Vector<DateFormatToken> m_shortDateTokens;
+ Vector<String> m_shortMonthLabels;
+ Vector<String> m_monthLabels;
+#if ENABLE(CALENDAR_PICKER)
+ Vector<String> m_weekDayShortLabels;
+ unsigned m_firstDayOfWeek;
+#endif
+
+};
+
+}
+#endif
diff --git a/Source/WebCore/platform/text/LocalizedDate.h b/Source/WebCore/platform/text/LocalizedDate.h
index 283f65adf..4db5eac8e 100644
--- a/Source/WebCore/platform/text/LocalizedDate.h
+++ b/Source/WebCore/platform/text/LocalizedDate.h
@@ -27,6 +27,7 @@
#define LocalizedDate_h
#include "DateComponents.h"
+#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>
namespace WebCore {
@@ -44,6 +45,22 @@ double parseLocalizedDate(const String&, DateComponents::Type);
// localized dates the function should return an empty string.
String formatLocalizedDate(const DateComponents& dateComponents);
+#if ENABLE(CALENDAR_PICKER)
+String localizedDateFormatText();
+
+// Returns a vector of string of which size is 12. The first item is a
+// localized string of January, and the last item is a localized
+// string of December. These strings should not be abbreviations.
+const Vector<String>& monthLabels();
+
+// Returns a vector of string of which size is 7. The first item is a
+// localized short string of Monday, and the last item is a localized
+// short string of Saturday. These strings should be short.
+const Vector<String>& weekDayShortLabels();
+
+// The first day of a week. 0 is Sunday, and 6 is Saturday.
+unsigned firstDayOfWeek();
+#endif
} // namespace WebCore
#endif // LocalizedDate_h
diff --git a/Source/WebCore/platform/text/LocalizedDateICU.cpp b/Source/WebCore/platform/text/LocalizedDateICU.cpp
new file mode 100644
index 000000000..10cb6f132
--- /dev/null
+++ b/Source/WebCore/platform/text/LocalizedDateICU.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LocalizedDate.h"
+
+#include "LocaleICU.h"
+#include <limits>
+
+using namespace std;
+
+namespace WebCore {
+
+double parseLocalizedDate(const String& input, DateComponents::Type type)
+{
+ switch (type) {
+ case DateComponents::Date:
+ return LocaleICU::currentLocale()->parseLocalizedDate(input);
+ case DateComponents::DateTime:
+ case DateComponents::DateTimeLocal:
+ case DateComponents::Month:
+ case DateComponents::Time:
+ case DateComponents::Week:
+ case DateComponents::Invalid:
+ break;
+ }
+ return numeric_limits<double>::quiet_NaN();
+}
+
+String formatLocalizedDate(const DateComponents& dateComponents)
+{
+ switch (dateComponents.type()) {
+ case DateComponents::Date:
+ return LocaleICU::currentLocale()->formatLocalizedDate(dateComponents);
+ case DateComponents::DateTime:
+ case DateComponents::DateTimeLocal:
+ case DateComponents::Month:
+ case DateComponents::Time:
+ case DateComponents::Week:
+ case DateComponents::Invalid:
+ break;
+ }
+ return String();
+}
+
+#if ENABLE(CALENDAR_PICKER)
+String localizedDateFormatText()
+{
+ return LocaleICU::currentLocale()->localizedDateFormatText();
+}
+
+const Vector<String>& monthLabels()
+{
+ return LocaleICU::currentLocale()->monthLabels();
+}
+
+const Vector<String>& weekDayShortLabels()
+{
+ return LocaleICU::currentLocale()->weekDayShortLabels();
+}
+
+unsigned firstDayOfWeek()
+{
+ return LocaleICU::currentLocale()->firstDayOfWeek();
+}
+#endif
+
+}
diff --git a/Source/WebCore/platform/graphics/chromium/VideoFrameChromium.h b/Source/WebCore/platform/text/LocalizedDateWin.cpp
index 2d76c4755..bd8f367f3 100644
--- a/Source/WebCore/platform/graphics/chromium/VideoFrameChromium.h
+++ b/Source/WebCore/platform/text/LocalizedDateWin.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -28,56 +28,68 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef VideoFrameChromium_h
-#define VideoFrameChromium_h
+#include "config.h"
+#include "LocalizedDate.h"
-#include "IntSize.h"
+#include "LocaleWin.h"
+#include <limits>
+
+using namespace std;
namespace WebCore {
-// A class that represents a video frame in chromium.
-class VideoFrameChromium {
-public:
- static const unsigned maxPlanes;
- static const unsigned numRGBPlanes;
- static const unsigned rgbPlane;
- static const unsigned numYUVPlanes;
- static const unsigned yPlane;
- static const unsigned uPlane;
- static const unsigned vPlane;
+double parseLocalizedDate(const String& input, DateComponents::Type type)
+{
+ switch (type) {
+ case DateComponents::Date:
+ return LocaleWin::currentLocale()->parseDate(input);
+ case DateComponents::DateTime:
+ case DateComponents::DateTimeLocal:
+ case DateComponents::Month:
+ case DateComponents::Time:
+ case DateComponents::Week:
+ case DateComponents::Invalid:
+ break;
+ }
+ return numeric_limits<double>::quiet_NaN();
+}
+
+String formatLocalizedDate(const DateComponents& dateComponents)
+{
+ switch (dateComponents.type()) {
+ case DateComponents::Date:
+ return LocaleWin::currentLocale()->formatDate(dateComponents);
+ case DateComponents::DateTime:
+ case DateComponents::DateTimeLocal:
+ case DateComponents::Month:
+ case DateComponents::Time:
+ case DateComponents::Week:
+ case DateComponents::Invalid:
+ break;
+ }
+ return String();
+}
- // These enums must be kept in sync with WebKit::WebVideoFrame.
- enum Format {
- Invalid,
- RGB555,
- RGB565,
- RGB24,
- RGB32,
- RGBA,
- YV12,
- YV16,
- NV12,
- Empty,
- ASCII,
- I420,
- NativeTexture,
- };
+#if ENABLE(CALENDAR_PICKER)
+String localizedDateFormatText()
+{
+ return LocaleWin::currentLocale()->dateFormatText();
+}
- virtual ~VideoFrameChromium();
- virtual Format format() const = 0;
- virtual unsigned width() const = 0;
- virtual unsigned width(unsigned plane) const = 0;
- virtual unsigned height() const = 0;
- virtual unsigned height(unsigned plane) const = 0;
- virtual unsigned planes() const = 0;
- virtual int stride(unsigned plane) const = 0;
- virtual const void* data(unsigned plane) const = 0;
- virtual const IntSize requiredTextureSize(unsigned plane) const = 0;
- virtual bool hasPaddingBytes(unsigned plane) const = 0;
- virtual unsigned textureId() const = 0;
- virtual unsigned textureTarget() const = 0;
-};
+const Vector<String>& monthLabels()
+{
+ return LocaleWin::currentLocale()->monthLabels();
+}
-} // namespace WebCore
+const Vector<String>& weekDayShortLabels()
+{
+ return LocaleWin::currentLocale()->weekDayShortLabels();
+}
+unsigned firstDayOfWeek()
+{
+ return LocaleWin::currentLocale()->firstDayOfWeek();
+}
#endif
+
+}
diff --git a/Source/WebCore/platform/text/LocalizedNumberICU.cpp b/Source/WebCore/platform/text/LocalizedNumberICU.cpp
index 76f7d2c32..d8a3f98bf 100644
--- a/Source/WebCore/platform/text/LocalizedNumberICU.cpp
+++ b/Source/WebCore/platform/text/LocalizedNumberICU.cpp
@@ -29,244 +29,20 @@
*/
#include "config.h"
-#include "LocalizedNumberICU.h"
+#include "LocaleICU.h"
#include "LocalizedNumber.h"
-#include <wtf/PassOwnPtr.h>
-#include <wtf/text/StringBuilder.h>
-
-using namespace icu;
namespace WebCore {
-ICULocale::ICULocale(const char* locale)
- : m_locale(locale)
- , m_numberFormat(0)
- , m_didCreateDecimalFormat(false)
-{
-}
-
-ICULocale::~ICULocale()
-{
- unum_close(m_numberFormat);
-}
-
-PassOwnPtr<ICULocale> ICULocale::create(const char* localeString)
-{
- return adoptPtr(new ICULocale(localeString));
-}
-
-PassOwnPtr<ICULocale> ICULocale::createForCurrentLocale()
-{
- return adoptPtr(new ICULocale(0));
-}
-
-void ICULocale::setDecimalSymbol(unsigned index, UNumberFormatSymbol symbol)
-{
- UErrorCode status = U_ZERO_ERROR;
- int32_t bufferLength = unum_getSymbol(m_numberFormat, symbol, 0, 0, &status);
- ASSERT(U_SUCCESS(status) || status == U_BUFFER_OVERFLOW_ERROR);
- if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR)
- return;
- Vector<UChar> buffer(bufferLength);
- status = U_ZERO_ERROR;
- unum_getSymbol(m_numberFormat, symbol, buffer.data(), bufferLength, &status);
- if (U_FAILURE(status))
- return;
- m_decimalSymbols[index] = String::adopt(buffer);
-}
-
-void ICULocale::setDecimalTextAttribute(String& destination, UNumberFormatTextAttribute tag)
-{
- UErrorCode status = U_ZERO_ERROR;
- int32_t bufferLength = unum_getTextAttribute(m_numberFormat, tag, 0, 0, &status);
- ASSERT(U_SUCCESS(status) || status == U_BUFFER_OVERFLOW_ERROR);
- if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR)
- return;
- Vector<UChar> buffer(bufferLength);
- status = U_ZERO_ERROR;
- unum_getTextAttribute(m_numberFormat, tag, buffer.data(), bufferLength, &status);
- ASSERT(U_SUCCESS(status));
- if (U_FAILURE(status))
- return;
- destination = String::adopt(buffer);
-}
-
-void ICULocale::initializeDecimalFormat()
-{
- if (m_didCreateDecimalFormat)
- return;
- m_didCreateDecimalFormat = true;
- UErrorCode status = U_ZERO_ERROR;
- m_numberFormat = unum_open(UNUM_DECIMAL, 0, 0, m_locale.data(), 0, &status);
- if (!U_SUCCESS(status))
- return;
-
- setDecimalSymbol(0, UNUM_ZERO_DIGIT_SYMBOL);
- setDecimalSymbol(1, UNUM_ONE_DIGIT_SYMBOL);
- setDecimalSymbol(2, UNUM_TWO_DIGIT_SYMBOL);
- setDecimalSymbol(3, UNUM_THREE_DIGIT_SYMBOL);
- setDecimalSymbol(4, UNUM_FOUR_DIGIT_SYMBOL);
- setDecimalSymbol(5, UNUM_FIVE_DIGIT_SYMBOL);
- setDecimalSymbol(6, UNUM_SIX_DIGIT_SYMBOL);
- setDecimalSymbol(7, UNUM_SEVEN_DIGIT_SYMBOL);
- setDecimalSymbol(8, UNUM_EIGHT_DIGIT_SYMBOL);
- setDecimalSymbol(9, UNUM_NINE_DIGIT_SYMBOL);
- setDecimalSymbol(DecimalSeparatorIndex, UNUM_DECIMAL_SEPARATOR_SYMBOL);
- setDecimalSymbol(GroupSeparatorIndex, UNUM_GROUPING_SEPARATOR_SYMBOL);
- setDecimalTextAttribute(m_positivePrefix, UNUM_POSITIVE_PREFIX);
- setDecimalTextAttribute(m_positiveSuffix, UNUM_POSITIVE_SUFFIX);
- setDecimalTextAttribute(m_negativePrefix, UNUM_NEGATIVE_PREFIX);
- setDecimalTextAttribute(m_negativeSuffix, UNUM_NEGATIVE_SUFFIX);
- ASSERT(!m_positivePrefix.isEmpty() || !m_positiveSuffix.isEmpty() || !m_negativePrefix.isEmpty() || !m_negativeSuffix.isEmpty());
-}
-
-String ICULocale::convertToLocalizedNumber(const String& input)
-{
- initializeDecimalFormat();
- if (!m_numberFormat || input.isEmpty())
- return input;
-
- unsigned i = 0;
- bool isNegative = false;
- UnicodeString ustring;
- StringBuilder builder;
- builder.reserveCapacity(input.length());
-
- if (input[0] == '-') {
- ++i;
- isNegative = true;
- builder.append(m_negativePrefix);
- } else
- builder.append(m_positivePrefix);
-
- for (; i < input.length(); ++i) {
- switch (input[i]) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- builder.append(m_decimalSymbols[input[i] - '0']);
- break;
- case '.':
- builder.append(m_decimalSymbols[DecimalSeparatorIndex]);
- break;
- default:
- ASSERT_NOT_REACHED();
- }
- }
-
- builder.append(isNegative ? m_negativeSuffix : m_positiveSuffix);
-
- return builder.toString();
-}
-
-static bool matches(const String& text, unsigned position, const String& part)
-{
- if (part.isEmpty())
- return true;
- if (position + part.length() > text.length())
- return false;
- for (unsigned i = 0; i < part.length(); ++i) {
- if (text[position + i] != part[i])
- return false;
- }
- return true;
-}
-
-bool ICULocale::detectSignAndGetDigitRange(const String& input, bool& isNegative, unsigned& startIndex, unsigned& endIndex)
-{
- startIndex = 0;
- endIndex = input.length();
- if (m_negativePrefix.isEmpty() && m_negativeSuffix.isEmpty()) {
- if (input.startsWith(m_positivePrefix) && input.endsWith(m_positiveSuffix)) {
- isNegative = false;
- startIndex = m_positivePrefix.length();
- endIndex -= m_positiveSuffix.length();
- } else
- isNegative = true;
- } else {
- if (input.startsWith(m_negativePrefix) && input.endsWith(m_negativeSuffix)) {
- isNegative = true;
- startIndex = m_negativePrefix.length();
- endIndex -= m_negativeSuffix.length();
- } else {
- isNegative = false;
- if (input.startsWith(m_positivePrefix) && input.endsWith(m_positiveSuffix)) {
- startIndex = m_positivePrefix.length();
- endIndex -= m_positiveSuffix.length();
- } else
- return false;
- }
- }
- return true;
-}
-
-unsigned ICULocale::matchedDecimalSymbolIndex(const String& input, unsigned& position)
-{
- for (unsigned symbolIndex = 0; symbolIndex < DecimalSymbolsSize; ++symbolIndex) {
- if (m_decimalSymbols[symbolIndex].length() && matches(input, position, m_decimalSymbols[symbolIndex])) {
- position += m_decimalSymbols[symbolIndex].length();
- return symbolIndex;
- }
- }
- return DecimalSymbolsSize;
-}
-
-String ICULocale::convertFromLocalizedNumber(const String& localized)
-{
- initializeDecimalFormat();
- String input = localized.stripWhiteSpace();
- if (!m_numberFormat || input.isEmpty())
- return input;
-
- bool isNegative;
- unsigned startIndex;
- unsigned endIndex;
- if (!detectSignAndGetDigitRange(input, isNegative, startIndex, endIndex)) {
- // Input is broken. Returning an invalid number string.
- return "*";
- }
-
- StringBuilder builder;
- builder.reserveCapacity(input.length());
- if (isNegative)
- builder.append("-");
- for (unsigned i = startIndex; i < endIndex;) {
- unsigned symbolIndex = matchedDecimalSymbolIndex(input, i);
- if (symbolIndex >= DecimalSymbolsSize)
- return "*";
- if (symbolIndex == DecimalSeparatorIndex)
- builder.append('.');
- else if (symbolIndex == GroupSeparatorIndex) {
- // Ignore group separators.
-
- } else
- builder.append(static_cast<UChar>('0' + symbolIndex));
- }
- return builder.toString();
-}
-
-static ICULocale* currentLocale()
-{
- static ICULocale* currentICULocale = ICULocale::createForCurrentLocale().leakPtr();
- return currentICULocale;
-}
-
String convertToLocalizedNumber(const String& canonicalNumberString, unsigned fractionDigits)
{
- return currentLocale()->convertToLocalizedNumber(canonicalNumberString);
+ return LocaleICU::currentLocale()->convertToLocalizedNumber(canonicalNumberString);
}
String convertFromLocalizedNumber(const String& localizedNumberString)
{
- return currentLocale()->convertFromLocalizedNumber(localizedNumberString);
+ return LocaleICU::currentLocale()->convertFromLocalizedNumber(localizedNumberString);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/text/RegularExpression.cpp b/Source/WebCore/platform/text/RegularExpression.cpp
index 3fbe3f866..f74f957dc 100644
--- a/Source/WebCore/platform/text/RegularExpression.cpp
+++ b/Source/WebCore/platform/text/RegularExpression.cpp
@@ -112,7 +112,7 @@ int RegularExpression::match(const String& str, int startFrom, int* matchLength)
unsigned result;
if (str.length() <= INT_MAX)
- result = JSC::Yarr::interpret(d->m_regExpByteCode.get(), JSC::UString(str.impl()), startFrom, str.length(), offsetVector);
+ result = JSC::Yarr::interpret(d->m_regExpByteCode.get(), JSC::UString(str.impl()), startFrom, offsetVector);
else {
// This code can't handle unsigned offsets. Limit our processing to strings with offsets that
// can be represented as ints.
diff --git a/Source/WebCore/platform/text/TextBreakIterator.h b/Source/WebCore/platform/text/TextBreakIterator.h
index 521ba8654..3c9c8c952 100644
--- a/Source/WebCore/platform/text/TextBreakIterator.h
+++ b/Source/WebCore/platform/text/TextBreakIterator.h
@@ -56,6 +56,7 @@ namespace WebCore {
int textBreakPreceding(TextBreakIterator*, int);
int textBreakFollowing(TextBreakIterator*, int);
bool isTextBreak(TextBreakIterator*, int);
+ bool isWordTextBreak(TextBreakIterator*);
const int TextBreakDone = -1;
diff --git a/Source/WebCore/platform/text/TextBreakIteratorICU.cpp b/Source/WebCore/platform/text/TextBreakIteratorICU.cpp
index 82471bd32..5c8ffbcc4 100644
--- a/Source/WebCore/platform/text/TextBreakIteratorICU.cpp
+++ b/Source/WebCore/platform/text/TextBreakIteratorICU.cpp
@@ -139,6 +139,12 @@ bool isTextBreak(TextBreakIterator* iterator, int position)
return ubrk_isBoundary(reinterpret_cast<UBreakIterator*>(iterator), position);
}
+bool isWordTextBreak(TextBreakIterator* iterator)
+{
+ int ruleStatus = ubrk_getRuleStatus(reinterpret_cast<UBreakIterator*>(iterator));
+ return ruleStatus != UBRK_WORD_NONE;
+}
+
static TextBreakIterator* setUpIteratorWithRules(bool& createdIterator, TextBreakIterator*& iterator,
const char* breakRules, const UChar* string, int length)
{
diff --git a/Source/WebCore/platform/text/TextEncoding.cpp b/Source/WebCore/platform/text/TextEncoding.cpp
index 03c77c0c3..26ab82a5c 100644
--- a/Source/WebCore/platform/text/TextEncoding.cpp
+++ b/Source/WebCore/platform/text/TextEncoding.cpp
@@ -37,7 +37,7 @@
#include <QString>
#elif USE(GLIB_UNICODE)
#include <glib.h>
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#endif
#include <wtf/text/CString.h>
#include <wtf/OwnPtr.h>
diff --git a/Source/WebCore/platform/text/gtk/TextBreakIteratorGtk.cpp b/Source/WebCore/platform/text/gtk/TextBreakIteratorGtk.cpp
index e067962c2..b49c115d8 100644
--- a/Source/WebCore/platform/text/gtk/TextBreakIteratorGtk.cpp
+++ b/Source/WebCore/platform/text/gtk/TextBreakIteratorGtk.cpp
@@ -26,7 +26,7 @@
#include "TextBreakIterator.h"
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#include <pango/pango.h>
using namespace std;
@@ -385,4 +385,9 @@ bool isTextBreak(TextBreakIterator* iterator, int offset)
return iterator->m_charIterator.getIndex() == index;
}
+bool isWordTextBreak(TextBreakIterator*)
+{
+ return true;
+}
+
}
diff --git a/Source/WebCore/platform/text/gtk/TextCodecGtk.cpp b/Source/WebCore/platform/text/gtk/TextCodecGtk.cpp
index 5f6cef14a..42759edc5 100644
--- a/Source/WebCore/platform/text/gtk/TextCodecGtk.cpp
+++ b/Source/WebCore/platform/text/gtk/TextCodecGtk.cpp
@@ -30,7 +30,7 @@
#include "TextCodecGtk.h"
#include <gio/gio.h>
-#include "GOwnPtr.h"
+#include <wtf/gobject/GOwnPtr.h>
#include "Logging.h"
#include "PlatformString.h"
#include <wtf/Assertions.h>
diff --git a/Source/WebCore/platform/text/gtk/TextCodecGtk.h b/Source/WebCore/platform/text/gtk/TextCodecGtk.h
index bb3a44527..a670484d9 100644
--- a/Source/WebCore/platform/text/gtk/TextCodecGtk.h
+++ b/Source/WebCore/platform/text/gtk/TextCodecGtk.h
@@ -29,7 +29,7 @@
#ifndef TextCodecGTK_h
#define TextCodecGTK_h
-#include "GRefPtr.h"
+#include <wtf/gobject/GRefPtr.h>
#include <glib.h>
#include "TextCodec.h"
#include "TextEncoding.h"
diff --git a/Source/WebCore/platform/text/mac/LocalizedDateMac.mm b/Source/WebCore/platform/text/mac/LocalizedDateMac.mm
new file mode 100644
index 000000000..08876f9d3
--- /dev/null
+++ b/Source/WebCore/platform/text/mac/LocalizedDateMac.mm
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LocalizedDate.h"
+
+#import <Foundation/NSDateFormatter.h>
+#include "LocalizedStrings.h"
+#include <limits>
+#include <wtf/DateMath.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/text/StringBuilder.h>
+
+using namespace std;
+
+namespace WebCore {
+
+static NSDateFormatter *createShortDateFormatter()
+{
+ NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
+ [formatter setDateStyle:NSDateFormatterShortStyle];
+ [formatter setTimeStyle:NSDateFormatterNoStyle];
+ [formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
+ [formatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]];
+ return formatter;
+}
+
+double parseLocalizedDate(const String& input, DateComponents::Type type)
+{
+ switch (type) {
+ case DateComponents::Date: {
+ RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortDateFormatter());
+ NSDate *date = [formatter.get() dateFromString:input];
+ if (!date)
+ break;
+ return [date timeIntervalSince1970] * msPerSecond;
+ }
+ case DateComponents::DateTime:
+ case DateComponents::DateTimeLocal:
+ case DateComponents::Month:
+ case DateComponents::Time:
+ case DateComponents::Week:
+ case DateComponents::Invalid:
+ break;
+ }
+ return numeric_limits<double>::quiet_NaN();
+}
+
+String formatLocalizedDate(const DateComponents& dateComponents)
+{
+ switch (dateComponents.type()) {
+ case DateComponents::Date: {
+ RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortDateFormatter());
+ NSTimeInterval interval = dateComponents.millisecondsSinceEpoch() / msPerSecond;
+ return String([formatter.get() stringFromDate:[NSDate dateWithTimeIntervalSince1970:interval]]);
+ }
+ case DateComponents::DateTime:
+ case DateComponents::DateTimeLocal:
+ case DateComponents::Month:
+ case DateComponents::Time:
+ case DateComponents::Week:
+ case DateComponents::Invalid:
+ break;
+ }
+ return String();
+}
+
+#if ENABLE(CALENDAR_PICKER)
+static bool isYearSymbol(UChar letter) { return letter == 'y' || letter == 'Y' || letter == 'u'; }
+static bool isMonthSymbol(UChar letter) { return letter == 'M' || letter == 'L'; }
+static bool isDaySymbol(UChar letter) { return letter == 'd'; }
+
+// http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns
+static String localizeDateFormat(const String& format)
+{
+ String yearText = dateFormatYearText().isEmpty() ? "Year" : dateFormatYearText();
+ String monthText = dateFormatMonthText().isEmpty() ? "Month" : dateFormatMonthText();
+ String dayText = dateFormatDayInMonthText().isEmpty() ? "Day" : dateFormatDayInMonthText();
+ StringBuilder buffer;
+ bool inQuote = false;
+ for (unsigned i = 0; i < format.length(); ++i) {
+ UChar ch = format[i];
+ if (inQuote) {
+ if (ch == '\'') {
+ inQuote = false;
+ ASSERT(i);
+ if (format[i - 1] == '\'')
+ buffer.append('\'');
+ } else
+ buffer.append(ch);
+ continue;
+ }
+
+ if (ch == '\'') {
+ inQuote = true;
+ if (i > 0 && format[i - 1] == '\'')
+ buffer.append(ch);
+ } else if (isYearSymbol(ch)) {
+ if (i > 0 && format[i - 1] == ch)
+ continue;
+ buffer.append(yearText);
+ } else if (isMonthSymbol(ch)) {
+ if (i > 0 && format[i - 1] == ch)
+ continue;
+ buffer.append(monthText);
+ } else if (isDaySymbol(ch)) {
+ if (i > 0 && format[i - 1] == ch)
+ continue;
+ buffer.append(dayText);
+ } else
+ buffer.append(ch);
+ }
+ return buffer.toString();
+}
+
+String localizedDateFormatText()
+{
+ DEFINE_STATIC_LOCAL(String, text, ());
+ if (!text.isEmpty())
+ return text;
+ RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortDateFormatter());
+ text = localizeDateFormat(String([formatter.get() dateFormat]));
+ return text;
+}
+
+const Vector<String>& monthLabels()
+{
+ DEFINE_STATIC_LOCAL(Vector<String>, labels, ());
+ if (!labels.isEmpty())
+ return labels;
+ labels.reserveCapacity(12);
+ RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortDateFormatter());
+ NSArray *array = [formatter.get() monthSymbols];
+ if ([array count] == 12) {
+ for (unsigned i = 0; i < 12; ++i)
+ labels.append(String([array objectAtIndex:i]));
+ return labels;
+ }
+ for (unsigned i = 0; i < WTF_ARRAY_LENGTH(WTF::monthFullName); ++i)
+ labels.append(WTF::monthFullName[i]);
+ return labels;
+}
+
+const Vector<String>& weekDayShortLabels()
+{
+ DEFINE_STATIC_LOCAL(Vector<String>, labels, ());
+ if (!labels.isEmpty())
+ return labels;
+ labels.reserveCapacity(7);
+ RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortDateFormatter());
+ NSArray *array = [formatter.get() shortWeekdaySymbols];
+ if ([array count] == 7) {
+ for (unsigned i = 0; i < 7; ++i)
+ labels.append(String([array objectAtIndex:i]));
+ return labels;
+ }
+ for (unsigned i = 0; i < WTF_ARRAY_LENGTH(WTF::weekdayName); ++i) {
+ // weekdayName starts with Monday.
+ labels.append(WTF::weekdayName[(i + 6) % 7]);
+ }
+ return labels;
+}
+
+unsigned firstDayOfWeek()
+{
+ RetainPtr<NSCalendar> calendar(AdoptNS, [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]);
+ // The document for NSCalendar - firstWeekday doesn't have an explanation of
+ // firstWeekday value. We can guess it by the document of NSDateComponents -
+ // weekDay, so it can be 1 through 7 and 1 is Sunday.
+ return [calendar.get() firstWeekday] - 1;
+}
+#endif
+
+}
diff --git a/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm b/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm
index c2a7ea013..031362b2b 100644
--- a/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm
+++ b/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm
@@ -54,7 +54,7 @@ static RetainPtr<NSNumberFormatter> createFormatterForCurrentLocale()
static RetainPtr<NSNumberFormatter> createFormatterForCurrentLocaleForDisplay()
{
RetainPtr<NSNumberFormatter> formatter = createFormatterForCurrentLocale();
- [formatter.get() setHasThousandSeparators:NO];
+ [formatter.get() setUsesGroupingSeparator:NO];
return formatter;
}
diff --git a/Source/WebCore/platform/text/qt/TextBreakIteratorQt.cpp b/Source/WebCore/platform/text/qt/TextBreakIteratorQt.cpp
index 653ede39a..8ac1538d2 100644
--- a/Source/WebCore/platform/text/qt/TextBreakIteratorQt.cpp
+++ b/Source/WebCore/platform/text/qt/TextBreakIteratorQt.cpp
@@ -150,4 +150,9 @@ namespace WebCore {
return true;
}
+ bool isWordTextBreak(TextBreakIterator*)
+ {
+ return true;
+ }
+
}
diff --git a/Source/WebCore/platform/text/wince/TextBreakIteratorWinCE.cpp b/Source/WebCore/platform/text/wince/TextBreakIteratorWinCE.cpp
index 7927d7769..468544ccb 100644
--- a/Source/WebCore/platform/text/wince/TextBreakIteratorWinCE.cpp
+++ b/Source/WebCore/platform/text/wince/TextBreakIteratorWinCE.cpp
@@ -317,6 +317,11 @@ bool isTextBreak(TextBreakIterator*, int)
return true;
}
+bool isWordTextBreak(TextBreakIterator*)
+{
+ return true;
+}
+
TextBreakIterator* cursorMovementIterator(const UChar* string, int length)
{
return characterBreakIterator(string, length);
diff --git a/Source/WebCore/platform/text/wince/TextCodecWinCE.cpp b/Source/WebCore/platform/text/wince/TextCodecWinCE.cpp
index a03df4ba1..0c4ec5012 100644
--- a/Source/WebCore/platform/text/wince/TextCodecWinCE.cpp
+++ b/Source/WebCore/platform/text/wince/TextCodecWinCE.cpp
@@ -98,7 +98,7 @@ LanguageManager::LanguageManager()
CharsetInfo info;
info.m_codePage = cpInfo.uiCodePage;
knownCharsets().set(name.data(), info);
- i = codePageCharsets().set(cpInfo.uiCodePage, name).first;
+ i = codePageCharsets().set(cpInfo.uiCodePage, name).iterator;
}
if (i != codePageCharsets().end()) {
HashMap<String, CharsetInfo>::iterator j = knownCharsets().find(String(i->second.data(), i->second.length()));
diff --git a/Source/WebCore/platform/win/DragImageCGWin.cpp b/Source/WebCore/platform/win/DragImageCGWin.cpp
index 741016846..cb49f95b5 100644
--- a/Source/WebCore/platform/win/DragImageCGWin.cpp
+++ b/Source/WebCore/platform/win/DragImageCGWin.cpp
@@ -31,9 +31,9 @@
#include "GraphicsContextCG.h"
#include "HWndDC.h"
#include "Image.h"
-#include "RetainPtr.h"
#include <CoreGraphics/CoreGraphics.h>
+#include <wtf/RetainPtr.h>
#include <windows.h>
@@ -120,7 +120,7 @@ exit:
return hbmp;
}
-DragImageRef createDragImageFromImage(Image* img)
+DragImageRef createDragImageFromImage(Image* img, RespectImageOrientationEnum)
{
HBITMAP hbmp = 0;
HWndDC dc(0);
diff --git a/Source/WebCore/platform/win/DragImageCairoWin.cpp b/Source/WebCore/platform/win/DragImageCairoWin.cpp
index a67a82c26..f65211f80 100644
--- a/Source/WebCore/platform/win/DragImageCairoWin.cpp
+++ b/Source/WebCore/platform/win/DragImageCairoWin.cpp
@@ -31,7 +31,7 @@
#include "GraphicsContext.h"
#include "GraphicsContextPlatformPrivateCairo.h"
#include "Image.h"
-#include "RetainPtr.h"
+#include <wtf/RetainPtr.h>
#include <cairo-win32.h>
#include <windows.h>
@@ -150,7 +150,7 @@ exit:
return hbmp;
}
-DragImageRef createDragImageFromImage(Image* img)
+DragImageRef createDragImageFromImage(Image* img, RespectImageOrientationEnum)
{
HBITMAP hbmp = 0;
HDC dc = GetDC(0);
diff --git a/Source/WebCore/platform/win/DragImageWin.cpp b/Source/WebCore/platform/win/DragImageWin.cpp
index 1f6b73e89..b5055a980 100644
--- a/Source/WebCore/platform/win/DragImageWin.cpp
+++ b/Source/WebCore/platform/win/DragImageWin.cpp
@@ -35,11 +35,11 @@
#include "GraphicsContext.h"
#include "HWndDC.h"
#include "Image.h"
-#include "RetainPtr.h"
#include "Settings.h"
#include "StringTruncator.h"
#include "TextRun.h"
#include "WebCoreTextRenderer.h"
+#include <wtf/RetainPtr.h>
#include <windows.h>
diff --git a/Source/WebCore/platform/win/FileSystemWin.cpp b/Source/WebCore/platform/win/FileSystemWin.cpp
index 118754455..4ce518771 100644
--- a/Source/WebCore/platform/win/FileSystemWin.cpp
+++ b/Source/WebCore/platform/win/FileSystemWin.cpp
@@ -123,11 +123,16 @@ String pathByAppendingComponent(const String& path, const String& component)
return String::adopt(buffer);
}
+#if !USE(CF)
+
CString fileSystemRepresentation(const String&)
{
+ ASSERT_NOT_REACHED();
return "";
}
+#endif !USE(CF)
+
bool makeAllDirectories(const String& path)
{
String fullPath = path;
diff --git a/Source/WebCore/platform/win/PopupMenuWin.cpp b/Source/WebCore/platform/win/PopupMenuWin.cpp
index 9ac2674c4..7ebcfdc02 100644
--- a/Source/WebCore/platform/win/PopupMenuWin.cpp
+++ b/Source/WebCore/platform/win/PopupMenuWin.cpp
@@ -33,6 +33,7 @@
#include "HTMLNames.h"
#include "HWndDC.h"
#include "HostWindow.h"
+#include "LengthFunctions.h"
#include "Page.h"
#include "PlatformMouseEvent.h"
#include "PlatformScreen.h"
@@ -340,7 +341,7 @@ void PopupMenuWin::calculatePositionAndSize(const IntRect& r, FrameView* v)
popupWidth += ScrollbarTheme::theme()->scrollbarThickness(SmallScrollbar);
// Add padding to align the popup text with the <select> text
- popupWidth += max(0, client()->clientPaddingRight() - client()->clientInsetRight()) + max(0, client()->clientPaddingLeft() - client()->clientInsetLeft());
+ popupWidth += max<int>(0, client()->clientPaddingRight() - client()->clientInsetRight()) + max<int>(0, client()->clientPaddingLeft() - client()->clientInsetLeft());
// Leave room for the border
popupWidth += 2 * popupWindowBorderWidth;
@@ -652,9 +653,9 @@ void PopupMenuWin::paint(const IntRect& damageRect, HDC hdc)
// Draw the item text
if (itemStyle.isVisible()) {
- int textX = max(0, client()->clientPaddingLeft() - client()->clientInsetLeft());
+ int textX = max<int>(0, client()->clientPaddingLeft() - client()->clientInsetLeft());
if (RenderTheme::defaultTheme()->popupOptionSupportsTextIndent() && itemStyle.textDirection() == LTR)
- textX += itemStyle.textIndent().calcMinValue(itemRect.width());
+ textX += minimumIntValueForLength(itemStyle.textIndent(), itemRect.width());
int textY = itemRect.y() + itemFont.fontMetrics().ascent() + (itemRect.height() - itemFont.fontMetrics().height()) / 2;
context.drawBidiText(itemFont, textRun, IntPoint(textX, textY));
}
diff --git a/Source/WebCore/platform/wince/DragImageWinCE.cpp b/Source/WebCore/platform/wince/DragImageWinCE.cpp
index f639b41eb..14df4805f 100644
--- a/Source/WebCore/platform/wince/DragImageWinCE.cpp
+++ b/Source/WebCore/platform/wince/DragImageWinCE.cpp
@@ -50,7 +50,7 @@ DragImageRef dissolveDragImageToFraction(DragImageRef image, float)
return image;
}
-DragImageRef createDragImageFromImage(Image*)
+DragImageRef createDragImageFromImage(Image*, RespectImageOrientationEnum)
{
return 0;
}
diff --git a/Source/WebCore/platform/wx/DragImageWx.cpp b/Source/WebCore/platform/wx/DragImageWx.cpp
index df2dcee7f..38833304d 100644
--- a/Source/WebCore/platform/wx/DragImageWx.cpp
+++ b/Source/WebCore/platform/wx/DragImageWx.cpp
@@ -50,7 +50,7 @@ DragImageRef dissolveDragImageToFraction(DragImageRef image, float)
return image;
}
-DragImageRef createDragImageFromImage(Image*)
+DragImageRef createDragImageFromImage(Image*, RespectImageOrientationEnum)
{
return 0;
}
diff --git a/Source/WebCore/platform/wx/LocalDC.h b/Source/WebCore/platform/wx/LocalDC.h
index 8dc315ef4..7670c5ccc 100644
--- a/Source/WebCore/platform/wx/LocalDC.h
+++ b/Source/WebCore/platform/wx/LocalDC.h
@@ -23,20 +23,22 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef LocalDC_h
+#define LocalDC_h
+
#include "IntRect.h"
#include <wtf/Assertions.h>
#include <wx/defs.h>
+#include <wx/bitmap.h>
#include <wx/dc.h>
#include <wx/dcmemory.h>
#include <wx/rawbmp.h>
namespace WebCore {
-wxBitmap* transparentBitmap(int width, int height);
-
class LocalDC {
public:
@@ -102,3 +104,4 @@ private:
}
+#endif // LocalDC_h
diff --git a/Source/WebCore/platform/wx/MouseEventWx.cpp b/Source/WebCore/platform/wx/MouseEventWx.cpp
index 31132e349..932f06fa0 100644
--- a/Source/WebCore/platform/wx/MouseEventWx.cpp
+++ b/Source/WebCore/platform/wx/MouseEventWx.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "PlatformMouseEvent.h"
-#include "Assertions.h"
+#include <wtf/Assertions.h>
#include <wx/defs.h>
#include <wx/event.h>
#include <wtf/CurrentTime.h>
diff --git a/Source/WebCore/platform/wx/RenderThemeWx.cpp b/Source/WebCore/platform/wx/RenderThemeWx.cpp
index c8a1750ee..2691e7f43 100644
--- a/Source/WebCore/platform/wx/RenderThemeWx.cpp
+++ b/Source/WebCore/platform/wx/RenderThemeWx.cpp
@@ -73,18 +73,18 @@ public:
virtual void adjustRepaintRect(const RenderObject*, IntRect&);
- virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
virtual int minimumMenuListSize(RenderStyle*) const;
- virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool isControlStyled(const RenderStyle*, const BorderData&,
@@ -257,7 +257,7 @@ bool RenderThemeWx::supportsFocus(ControlPart part) const
}
}
-void RenderThemeWx::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeWx::adjustButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
addIntrinsicMargins(style);
}
@@ -303,7 +303,7 @@ bool RenderThemeWx::paintButton(RenderObject* o, const PaintInfo& i, const IntRe
return false;
}
-void RenderThemeWx::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeWx::adjustTextFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
{
}
@@ -335,7 +335,7 @@ int RenderThemeWx::minimumMenuListSize(RenderStyle*) const
return MINIMUM_MENU_LIST_SIZE;
}
-void RenderThemeWx::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeWx::adjustMenuListStyle(StyleResolver*, RenderStyle* style, Element*) const
{
style->resetBorder();
@@ -373,7 +373,7 @@ bool RenderThemeWx::paintMenuList(RenderObject* o, const PaintInfo& i, const Int
return false;
}
-void RenderThemeWx::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderThemeWx::adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const
{
notImplemented();
}
diff --git a/Source/WebCore/platform/wx/wxcode/win/fontprops.cpp b/Source/WebCore/platform/wx/wxcode/win/fontprops.cpp
index f3e4fda70..cc02b9492 100644
--- a/Source/WebCore/platform/wx/wxcode/win/fontprops.cpp
+++ b/Source/WebCore/platform/wx/wxcode/win/fontprops.cpp
@@ -24,12 +24,14 @@
*/
#include "config.h"
-// this needs to be included before fontprops.h for UChar* to be defined.
+
+#include <wtf/MathExtras.h>
+// Unicode.h needs to be included before fontprops.h for UChar* to be defined.
+// FIXME: This is wrong, fontprops.h should just forward-declare UChar.
#include <wtf/unicode/Unicode.h>
#include "fontprops.h"
#include "math.h"
-#include "MathExtras.h"
#include <wx/defs.h>
#include <wx/gdicmn.h>