summaryrefslogtreecommitdiff
path: root/Source/WebCore/platform
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform')
-rw-r--r--Source/WebCore/platform/AsyncFileSystem.cpp10
-rw-r--r--Source/WebCore/platform/AsyncFileSystem.h14
-rw-r--r--Source/WebCore/platform/AutodrainedPool.h6
-rwxr-xr-xSource/WebCore/platform/CalculationValue.cpp36
-rwxr-xr-x[-rw-r--r--]Source/WebCore/platform/CalculationValue.h (renamed from Source/WebCore/platform/mock/SpeechInputClientMock.h)56
-rw-r--r--Source/WebCore/platform/ContextMenuItem.h9
-rw-r--r--Source/WebCore/platform/Cursor.h6
-rw-r--r--Source/WebCore/platform/DragData.h6
-rw-r--r--Source/WebCore/platform/DragImage.h6
-rw-r--r--Source/WebCore/platform/KURL.cpp83
-rw-r--r--Source/WebCore/platform/KURL.h13
-rw-r--r--Source/WebCore/platform/KURLGoogle.cpp55
-rw-r--r--Source/WebCore/platform/KURLGooglePrivate.h8
-rw-r--r--Source/WebCore/platform/Language.cpp83
-rw-r--r--Source/WebCore/platform/Language.h11
-rw-r--r--Source/WebCore/platform/LocalizationStrategy.h2
-rw-r--r--Source/WebCore/platform/LocalizedStrings.cpp2
-rw-r--r--Source/WebCore/platform/LocalizedStrings.h2
-rw-r--r--Source/WebCore/platform/Logging.cpp5
-rw-r--r--Source/WebCore/platform/Logging.h1
-rw-r--r--Source/WebCore/platform/MIMETypeRegistry.cpp4
-rw-r--r--Source/WebCore/platform/MemoryPressureHandler.cpp2
-rw-r--r--Source/WebCore/platform/MemoryPressureHandler.h1
-rw-r--r--Source/WebCore/platform/Pasteboard.h20
-rw-r--r--Source/WebCore/platform/PlatformKeyboardEvent.h6
-rw-r--r--Source/WebCore/platform/PlatformMenuDescription.h6
-rw-r--r--Source/WebCore/platform/PlatformScreen.h23
-rw-r--r--Source/WebCore/platform/PlatformWheelEvent.h11
-rw-r--r--Source/WebCore/platform/PopupMenuClient.h2
-rw-r--r--Source/WebCore/platform/RunLoop.cpp78
-rw-r--r--Source/WebCore/platform/RunLoop.h167
-rw-r--r--Source/WebCore/platform/SchemeRegistry.cpp26
-rw-r--r--Source/WebCore/platform/SchemeRegistry.h4
-rw-r--r--Source/WebCore/platform/ScrollAnimator.h2
-rw-r--r--Source/WebCore/platform/ScrollView.cpp11
-rw-r--r--Source/WebCore/platform/ScrollView.h1
-rw-r--r--Source/WebCore/platform/ScrollableArea.cpp4
-rw-r--r--Source/WebCore/platform/ScrollableArea.h2
-rw-r--r--Source/WebCore/platform/Scrollbar.cpp8
-rw-r--r--Source/WebCore/platform/Scrollbar.h1
-rw-r--r--Source/WebCore/platform/SharedBuffer.h8
-rw-r--r--Source/WebCore/platform/Widget.h9
-rw-r--r--Source/WebCore/platform/animation/AnimationUtilities.h5
-rw-r--r--Source/WebCore/platform/audio/AudioArray.h2
-rw-r--r--Source/WebCore/platform/audio/AudioBus.cpp68
-rw-r--r--Source/WebCore/platform/audio/AudioBus.h25
-rw-r--r--Source/WebCore/platform/audio/AudioChannel.cpp18
-rw-r--r--Source/WebCore/platform/audio/AudioChannel.h4
-rw-r--r--Source/WebCore/platform/audio/AudioDSPKernelProcessor.cpp4
-rw-r--r--Source/WebCore/platform/audio/AudioDSPKernelProcessor.h2
-rw-r--r--Source/WebCore/platform/audio/AudioProcessor.h2
-rw-r--r--Source/WebCore/platform/audio/AudioResampler.cpp2
-rw-r--r--Source/WebCore/platform/audio/AudioUtilities.cpp34
-rw-r--r--Source/WebCore/platform/audio/AudioUtilities.h4
-rw-r--r--Source/WebCore/platform/audio/DynamicsCompressor.cpp10
-rw-r--r--Source/WebCore/platform/audio/DynamicsCompressor.h2
-rw-r--r--Source/WebCore/platform/audio/DynamicsCompressorKernel.cpp4
-rw-r--r--Source/WebCore/platform/audio/DynamicsCompressorKernel.h4
-rw-r--r--Source/WebCore/platform/audio/EqualPowerPanner.cpp14
-rw-r--r--Source/WebCore/platform/audio/EqualPowerPanner.h2
-rw-r--r--Source/WebCore/platform/audio/FFTConvolver.cpp2
-rw-r--r--Source/WebCore/platform/audio/FFTConvolver.h2
-rw-r--r--Source/WebCore/platform/audio/FFTFrame.cpp11
-rw-r--r--Source/WebCore/platform/audio/FFTFrame.h19
-rw-r--r--Source/WebCore/platform/audio/FFTFrameStub.cpp4
-rw-r--r--Source/WebCore/platform/audio/HRTFElevation.cpp2
-rw-r--r--Source/WebCore/platform/audio/HRTFElevation.h2
-rw-r--r--Source/WebCore/platform/audio/HRTFKernel.cpp6
-rw-r--r--Source/WebCore/platform/audio/HRTFPanner.cpp216
-rw-r--r--Source/WebCore/platform/audio/HRTFPanner.h55
-rw-r--r--Source/WebCore/platform/audio/MultiChannelResampler.cpp4
-rw-r--r--Source/WebCore/platform/audio/Panner.h2
-rw-r--r--Source/WebCore/platform/audio/Reverb.cpp41
-rw-r--r--Source/WebCore/platform/audio/Reverb.h2
-rw-r--r--Source/WebCore/platform/audio/ReverbConvolver.cpp8
-rw-r--r--Source/WebCore/platform/audio/ReverbConvolver.h2
-rw-r--r--Source/WebCore/platform/audio/ReverbConvolverStage.cpp13
-rw-r--r--Source/WebCore/platform/audio/ReverbConvolverStage.h4
-rw-r--r--Source/WebCore/platform/audio/ReverbInputBuffer.cpp2
-rw-r--r--Source/WebCore/platform/audio/ReverbInputBuffer.h2
-rw-r--r--Source/WebCore/platform/audio/SincResampler.cpp10
-rw-r--r--Source/WebCore/platform/audio/SincResampler.h4
-rw-r--r--Source/WebCore/platform/audio/VectorMath.cpp100
-rw-r--r--Source/WebCore/platform/audio/VectorMath.h9
-rw-r--r--Source/WebCore/platform/audio/ZeroPole.cpp2
-rw-r--r--Source/WebCore/platform/audio/ZeroPole.h2
-rw-r--r--Source/WebCore/platform/audio/ffmpeg/FFTFrameFFMPEG.cpp2
-rw-r--r--Source/WebCore/platform/audio/gstreamer/AudioFileReaderGStreamer.cpp2
-rw-r--r--Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp2
-rw-r--r--Source/WebCore/platform/audio/mac/AudioBusMac.mm9
-rw-r--r--Source/WebCore/platform/audio/mac/AudioFileReaderMac.cpp4
-rw-r--r--Source/WebCore/platform/audio/mac/FFTFrameMac.cpp2
-rw-r--r--Source/WebCore/platform/audio/mkl/FFTFrameMKL.cpp2
-rw-r--r--Source/WebCore/platform/audio/resources/Composite.wavbin245804 -> 245804 bytes
-rw-r--r--Source/WebCore/platform/blackberry/LocalizedStringsBlackBerry.cpp10
-rw-r--r--Source/WebCore/platform/blackberry/LoggingBlackBerry.cpp38
-rw-r--r--Source/WebCore/platform/blackberry/PlatformKeyboardEventBlackBerry.cpp8
-rw-r--r--Source/WebCore/platform/blackberry/PlatformScreenBlackBerry.cpp5
-rw-r--r--Source/WebCore/platform/cf/KURLCFNet.cpp17
-rw-r--r--Source/WebCore/platform/cf/SchedulePair.h6
-rw-r--r--Source/WebCore/platform/chromium/ChromiumDataObject.cpp6
-rw-r--r--Source/WebCore/platform/chromium/ChromiumDataObject.h7
-rw-r--r--Source/WebCore/platform/chromium/ClipboardChromium.cpp226
-rw-r--r--Source/WebCore/platform/chromium/ClipboardChromium.h22
-rw-r--r--Source/WebCore/platform/chromium/ClipboardChromiumPosix.cpp (renamed from Source/WebCore/platform/chromium/ClipboardChromiumMac.cpp)41
-rw-r--r--Source/WebCore/platform/chromium/ClipboardChromiumWin.cpp23
-rw-r--r--Source/WebCore/platform/chromium/DataTransferItemChromium.cpp54
-rw-r--r--Source/WebCore/platform/chromium/DataTransferItemChromium.h20
-rw-r--r--Source/WebCore/platform/chromium/DataTransferItemListChromium.cpp119
-rw-r--r--Source/WebCore/platform/chromium/DataTransferItemListChromium.h21
-rw-r--r--Source/WebCore/platform/chromium/DragDataChromium.cpp6
-rw-r--r--Source/WebCore/platform/chromium/LanguageChromium.cpp10
-rw-r--r--Source/WebCore/platform/chromium/PlatformScreenChromium.cpp14
-rw-r--r--Source/WebCore/platform/chromium/PlatformSupport.h6
-rw-r--r--Source/WebCore/platform/efl/LanguageEfl.cpp10
-rw-r--r--Source/WebCore/platform/efl/LocalizedStringsEfl.cpp5
-rw-r--r--Source/WebCore/platform/efl/PlatformScreenEfl.cpp11
-rw-r--r--Source/WebCore/platform/graphics/BitmapImage.h6
-rw-r--r--Source/WebCore/platform/graphics/CrossfadeGeneratedImage.h7
-rw-r--r--Source/WebCore/platform/graphics/FloatRect.cpp39
-rw-r--r--Source/WebCore/platform/graphics/FloatRect.h4
-rw-r--r--Source/WebCore/platform/graphics/Font.h14
-rw-r--r--Source/WebCore/platform/graphics/FontDescription.h18
-rw-r--r--Source/WebCore/platform/graphics/FontFastPath.cpp4
-rw-r--r--Source/WebCore/platform/graphics/FontPlatformData.h6
-rw-r--r--Source/WebCore/platform/graphics/GraphicsContext3D.h16
-rw-r--r--Source/WebCore/platform/graphics/GraphicsLayer.cpp48
-rw-r--r--Source/WebCore/platform/graphics/GraphicsLayer.h31
-rw-r--r--Source/WebCore/platform/graphics/GraphicsLayerClient.h4
-rw-r--r--Source/WebCore/platform/graphics/GraphicsTypes.h6
-rw-r--r--Source/WebCore/platform/graphics/Icon.h6
-rw-r--r--Source/WebCore/platform/graphics/Image.h6
-rw-r--r--Source/WebCore/platform/graphics/ImageBuffer.h11
-rw-r--r--Source/WebCore/platform/graphics/MediaPlayer.cpp4
-rw-r--r--Source/WebCore/platform/graphics/MediaPlayer.h13
-rw-r--r--Source/WebCore/platform/graphics/Path.h2
-rw-r--r--Source/WebCore/platform/graphics/SVGGlyph.cpp4
-rw-r--r--Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp1
-rw-r--r--Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h22
-rw-r--r--Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp53
-rw-r--r--Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h5
-rw-r--r--Source/WebCore/platform/graphics/ca/LayerFlushScheduler.h2
-rw-r--r--Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h6
-rw-r--r--Source/WebCore/platform/graphics/ca/PlatformCALayer.h2
-rw-r--r--Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h2
-rw-r--r--Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm43
-rw-r--r--Source/WebCore/platform/graphics/ca/mac/TileCache.h55
-rw-r--r--Source/WebCore/platform/graphics/ca/mac/TileCache.mm271
-rw-r--r--Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.h2
-rw-r--r--Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm40
-rw-r--r--Source/WebCore/platform/graphics/ca/mac/WebTileLayer.h3
-rw-r--r--Source/WebCore/platform/graphics/ca/mac/WebTileLayer.mm5
-rw-r--r--Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp4
-rw-r--r--Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp4
-rw-r--r--Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp2
-rw-r--r--Source/WebCore/platform/graphics/cairo/OpenGLShims.cpp2
-rw-r--r--Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp41
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp33
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h2
-rw-r--r--Source/WebCore/platform/graphics/cg/PathCG.cpp91
-rw-r--r--Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp14
-rw-r--r--Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.h4
-rw-r--r--Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp4
-rw-r--r--Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp23
-rw-r--r--Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h8
-rw-r--r--Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp4
-rw-r--r--Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp39
-rw-r--r--Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h20
-rw-r--r--Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp2
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp17
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp6
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp12
-rw-r--r--Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp70
-rw-r--r--Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp16
-rw-r--r--Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h7
-rw-r--r--Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp12
-rw-r--r--Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h7
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerChromium.cpp65
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerChromium.h40
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp69
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h4
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerTextureUpdater.h8
-rw-r--r--Source/WebCore/platform/graphics/chromium/ManagedTexture.cpp20
-rw-r--r--Source/WebCore/platform/graphics/chromium/ManagedTexture.h5
-rw-r--r--Source/WebCore/platform/graphics/chromium/PlatformCanvas.cpp22
-rw-r--r--Source/WebCore/platform/graphics/chromium/PlatformCanvas.h7
-rw-r--r--Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp8
-rw-r--r--Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h4
-rw-r--r--Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp10
-rw-r--r--Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp12
-rw-r--r--Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.h9
-rw-r--r--Source/WebCore/platform/graphics/chromium/SolidColorLayerChromium.cpp57
-rw-r--r--Source/WebCore/platform/graphics/chromium/SolidColorLayerChromium.h54
-rw-r--r--Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp116
-rw-r--r--Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h9
-rw-r--r--Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp9
-rw-r--r--Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp9
-rw-r--r--Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h5
-rw-r--r--Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp8
-rw-r--r--Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h4
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.cpp98
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.h123
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCAnimationCurve.cpp43
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCAnimationCurve.h71
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCCanvasDrawQuad.cpp45
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCCanvasDrawQuad.h54
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp31
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h4
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCDelayBasedTimeSource.h1
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.cpp38
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.h30
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.cpp15
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.h3
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCInputHandler.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp223
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.h88
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp49
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h6
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp1
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp99
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h14
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp36
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h7
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.cpp (renamed from Source/WebCore/platform/graphics/chromium/cc/CCCustomLayerDrawQuad.cpp)12
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.h (renamed from Source/WebCore/platform/graphics/chromium/cc/CCCustomLayerDrawQuad.h)17
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp6
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCProxy.h4
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp41
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp13
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp12
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h4
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h1
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCSolidColorDrawQuad.cpp4
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.cpp74
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.h58
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp17
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h1
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCTileDrawQuad.cpp7
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCTileDrawQuad.h4
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp22
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCTimeSource.h1
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.cpp44
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.h50
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp17
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h2
-rw-r--r--Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp5
-rw-r--r--Source/WebCore/platform/graphics/efl/IntRectEfl.cpp10
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterNumberParameter.h64
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterOperation.cpp74
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterOperation.h110
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterParameter.h72
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp92
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterProgram.h82
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterProgramClient.h52
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterShader.cpp7
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterShader.h2
-rw-r--r--Source/WebCore/platform/graphics/filters/FEColorMatrix.h3
-rw-r--r--Source/WebCore/platform/graphics/filters/FECustomFilter.cpp62
-rw-r--r--Source/WebCore/platform/graphics/filters/FECustomFilter.h14
-rw-r--r--Source/WebCore/platform/graphics/filters/FETile.cpp2
-rw-r--r--Source/WebCore/platform/graphics/filters/FETurbulence.cpp72
-rw-r--r--Source/WebCore/platform/graphics/filters/FETurbulence.h30
-rw-r--r--Source/WebCore/platform/graphics/glx/GraphicsContext3DPrivate.cpp (renamed from Source/WebCore/platform/graphics/gtk/GraphicsContext3DPrivate.cpp)3
-rw-r--r--Source/WebCore/platform/graphics/glx/GraphicsContext3DPrivate.h (renamed from Source/WebCore/platform/graphics/gtk/GraphicsContext3DPrivate.h)4
-rw-r--r--Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp4
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp152
-rw-r--r--Source/WebCore/platform/graphics/gtk/ImageGtk.cpp50
-rw-r--r--Source/WebCore/platform/graphics/mac/ColorMac.h6
-rw-r--r--Source/WebCore/platform/graphics/mac/ComplexTextController.cpp11
-rw-r--r--Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp3
-rw-r--r--Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm4
-rw-r--r--Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h20
-rw-r--r--Source/WebCore/platform/graphics/mac/MediaPlayerProxy.h6
-rw-r--r--Source/WebCore/platform/graphics/mac/WebLayer.mm2
-rw-r--r--Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp1130
-rw-r--r--Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp1178
-rw-r--r--Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp100
-rw-r--r--Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp95
-rw-r--r--Source/WebCore/platform/graphics/opengl/TextureMapperGL.h2
-rw-r--r--Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp4
-rw-r--r--Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp2
-rw-r--r--Source/WebCore/platform/graphics/qt/TextureMapperQt.cpp3
-rw-r--r--Source/WebCore/platform/graphics/qt/TextureMapperQt.h3
-rw-r--r--Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp67
-rw-r--r--Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp106
-rw-r--r--Source/WebCore/platform/graphics/skia/ImageSkia.cpp1
-rw-r--r--Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.cpp309
-rw-r--r--Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.h70
-rw-r--r--Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp36
-rw-r--r--Source/WebCore/platform/graphics/skia/PlatformContextSkia.h19
-rw-r--r--Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp (renamed from Source/WebCore/platform/graphics/harfbuzz/SimpleFontDataSkia.cpp)0
-rw-r--r--Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp16
-rw-r--r--Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp47
-rw-r--r--Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h2
-rw-r--r--Source/WebCore/platform/graphics/texmap/LayerTransform.cpp116
-rw-r--r--Source/WebCore/platform/graphics/texmap/LayerTransform.h62
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapper.cpp38
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapper.h3
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp255
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.h85
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp619
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperNode.h79
-rw-r--r--Source/WebCore/platform/graphics/transforms/AffineTransform.cpp16
-rw-r--r--Source/WebCore/platform/graphics/transforms/AffineTransform.h4
-rw-r--r--Source/WebCore/platform/graphics/win/FontCacheWin.cpp15
-rw-r--r--Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp4
-rw-r--r--Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp4
-rw-r--r--Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp6
-rw-r--r--Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp24
-rw-r--r--Source/WebCore/platform/graphics/win/UniscribeController.cpp12
-rw-r--r--Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp2
-rw-r--r--Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp2
-rw-r--r--Source/WebCore/platform/gtk/GtkUtilities.cpp5
-rw-r--r--Source/WebCore/platform/gtk/GtkUtilities.h3
-rw-r--r--Source/WebCore/platform/gtk/LanguageGtk.cpp10
-rw-r--r--Source/WebCore/platform/gtk/PlatformScreenGtk.cpp11
-rw-r--r--Source/WebCore/platform/gtk/RenderThemeGtk.h2
-rw-r--r--Source/WebCore/platform/gtk/RunLoopGtk.cpp137
-rw-r--r--Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp33
-rw-r--r--Source/WebCore/platform/gtk/ScrollbarThemeGtk.h2
-rw-r--r--Source/WebCore/platform/gtk/ScrollbarThemeGtk2.cpp2
-rw-r--r--Source/WebCore/platform/gtk/ScrollbarThemeGtk3.cpp2
-rw-r--r--Source/WebCore/platform/image-decoders/ImageDecoder.h17
-rw-r--r--Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp56
-rw-r--r--Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp33
-rw-r--r--Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp4
-rw-r--r--Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h2
-rw-r--r--Source/WebCore/platform/image-encoders/skia/WEBPImageEncoder.cpp4
-rw-r--r--Source/WebCore/platform/image-encoders/skia/WEBPImageEncoder.h3
-rw-r--r--Source/WebCore/platform/mac/ClipboardMac.h9
-rw-r--r--Source/WebCore/platform/mac/ClipboardMac.mm27
-rw-r--r--Source/WebCore/platform/mac/DragDataMac.mm6
-rw-r--r--Source/WebCore/platform/mac/HTMLConverter.mm2
-rw-r--r--Source/WebCore/platform/mac/KURLMac.mm17
-rw-r--r--Source/WebCore/platform/mac/Language.mm38
-rw-r--r--Source/WebCore/platform/mac/LocalCurrentGraphicsContext.h6
-rw-r--r--Source/WebCore/platform/mac/LoggingMac.mm1
-rw-r--r--Source/WebCore/platform/mac/MemoryPressureHandlerMac.mm17
-rw-r--r--Source/WebCore/platform/mac/NSScrollerImpDetails.h1
-rw-r--r--Source/WebCore/platform/mac/PasteboardHelper.h6
-rw-r--r--Source/WebCore/platform/mac/PasteboardMac.mm61
-rw-r--r--Source/WebCore/platform/mac/PlatformEventFactoryMac.h8
-rw-r--r--Source/WebCore/platform/mac/PlatformEventFactoryMac.mm9
-rw-r--r--Source/WebCore/platform/mac/PlatformScreenMac.mm31
-rw-r--r--Source/WebCore/platform/mac/PopupMenuMac.h6
-rw-r--r--Source/WebCore/platform/mac/RunLoopMac.mm193
-rw-r--r--Source/WebCore/platform/mac/ScrollAnimatorMac.h31
-rw-r--r--Source/WebCore/platform/mac/ScrollAnimatorMac.mm508
-rw-r--r--Source/WebCore/platform/mac/ScrollElasticityController.h15
-rw-r--r--Source/WebCore/platform/mac/ScrollElasticityController.mm356
-rw-r--r--Source/WebCore/platform/mac/ScrollbarThemeMac.mm9
-rw-r--r--Source/WebCore/platform/mac/WebCoreSystemInterface.h76
-rw-r--r--Source/WebCore/platform/mac/WebCoreSystemInterface.mm1
-rw-r--r--Source/WebCore/platform/mediastream/MediaStreamCenter.cpp11
-rw-r--r--Source/WebCore/platform/mediastream/MediaStreamCenter.h6
-rw-r--r--Source/WebCore/platform/mediastream/MediaStreamDescriptor.h23
-rw-r--r--Source/WebCore/platform/mock/SpeechInputClientMock.cpp146
-rw-r--r--Source/WebCore/platform/network/HTTPParsers.cpp50
-rw-r--r--Source/WebCore/platform/network/HTTPParsers.h1
-rw-r--r--Source/WebCore/platform/network/ResourceHandle.h15
-rw-r--r--Source/WebCore/platform/network/ResourceHandleClient.h6
-rw-r--r--Source/WebCore/platform/network/ResourceHandleInternal.h9
-rw-r--r--Source/WebCore/platform/network/ResourceRequestBase.cpp6
-rw-r--r--Source/WebCore/platform/network/ResourceRequestBase.h10
-rw-r--r--Source/WebCore/platform/network/blackberry/CredentialBackingStore.cpp197
-rw-r--r--Source/WebCore/platform/network/blackberry/NetworkJob.cpp26
-rw-r--r--Source/WebCore/platform/network/blackberry/NetworkJob.h2
-rw-r--r--Source/WebCore/platform/network/blackberry/NetworkManager.cpp2
-rw-r--r--Source/WebCore/platform/network/blackberry/ResourceRequestBlackBerry.cpp2
-rw-r--r--Source/WebCore/platform/network/cf/AuthenticationChallenge.h9
-rw-r--r--Source/WebCore/platform/network/cf/ResourceError.h6
-rw-r--r--Source/WebCore/platform/network/cf/ResourceRequest.h6
-rw-r--r--Source/WebCore/platform/network/cf/ResourceResponse.h6
-rw-r--r--Source/WebCore/platform/network/soup/ResourceResponse.h1
-rw-r--r--Source/WebCore/platform/qt/DataTransferItemListQt.cpp65
-rw-r--r--Source/WebCore/platform/qt/DataTransferItemListQt.h13
-rw-r--r--Source/WebCore/platform/qt/DataTransferItemQt.cpp51
-rw-r--r--Source/WebCore/platform/qt/DataTransferItemQt.h23
-rw-r--r--Source/WebCore/platform/qt/LanguageQt.cpp10
-rw-r--r--Source/WebCore/platform/qt/PlatformScreenQt.cpp8
-rw-r--r--Source/WebCore/platform/qt/PlatformTouchPointQt.cpp22
-rw-r--r--Source/WebCore/platform/qt/RenderThemeQtMobile.cpp193
-rw-r--r--Source/WebCore/platform/qt/RenderThemeQtMobile.h54
-rw-r--r--Source/WebCore/platform/qt/RunLoopQt.cpp166
-rw-r--r--Source/WebCore/platform/text/DecodeEscapeSequences.h85
-rw-r--r--Source/WebCore/platform/text/LocalizedNumber.h27
-rw-r--r--Source/WebCore/platform/text/LocalizedNumberICU.cpp31
-rw-r--r--Source/WebCore/platform/text/LocalizedNumberNone.cpp8
-rw-r--r--Source/WebCore/platform/text/mac/LocalizedNumberMac.mm32
-rw-r--r--Source/WebCore/platform/win/CursorWin.cpp4
-rw-r--r--Source/WebCore/platform/win/DragImageCGWin.cpp7
-rw-r--r--Source/WebCore/platform/win/DragImageWin.cpp9
-rw-r--r--Source/WebCore/platform/win/HWndDC.h (renamed from Source/WebCore/platform/efl/CookieJarEfl.cpp)89
-rw-r--r--Source/WebCore/platform/win/LanguageWin.cpp10
-rw-r--r--Source/WebCore/platform/win/PasteboardWin.cpp4
-rw-r--r--Source/WebCore/platform/win/PlatformScreenWin.cpp8
-rw-r--r--Source/WebCore/platform/win/PopupMenuWin.cpp10
-rw-r--r--Source/WebCore/platform/win/RunLoopWin.cpp181
-rw-r--r--Source/WebCore/platform/wx/KeyboardEventWx.cpp18
-rw-r--r--Source/WebCore/platform/wx/LanguageWx.cpp (renamed from Source/WebCore/platform/chromium/ClipboardChromiumLinux.cpp)20
-rw-r--r--Source/WebCore/platform/wx/RunLoopWx.cpp57
-rw-r--r--Source/WebCore/platform/wx/ScreenWx.cpp5
407 files changed, 10139 insertions, 4436 deletions
diff --git a/Source/WebCore/platform/AsyncFileSystem.cpp b/Source/WebCore/platform/AsyncFileSystem.cpp
index 404aab673..c3c241224 100644
--- a/Source/WebCore/platform/AsyncFileSystem.cpp
+++ b/Source/WebCore/platform/AsyncFileSystem.cpp
@@ -39,6 +39,11 @@
namespace WebCore {
+const char AsyncFileSystem::persistentPathPrefix[] = "persistent";
+const size_t AsyncFileSystem::persistentPathPrefixLength = sizeof(AsyncFileSystem::persistentPathPrefix) - 1;
+const char AsyncFileSystem::temporaryPathPrefix[] = "temporary";
+const size_t AsyncFileSystem::temporaryPathPrefixLength = sizeof(AsyncFileSystem::temporaryPathPrefix) - 1;
+
#if !PLATFORM(CHROMIUM)
bool AsyncFileSystem::isAvailable()
{
@@ -46,6 +51,11 @@ bool AsyncFileSystem::isAvailable()
return false;
}
+bool AsyncFileSystem::isValidType(Type type)
+{
+ return type == Temporary || type == Persistent;
+}
+
PassOwnPtr<AsyncFileSystem> AsyncFileSystem::create(Type, const String&)
{
notImplemented();
diff --git a/Source/WebCore/platform/AsyncFileSystem.h b/Source/WebCore/platform/AsyncFileSystem.h
index c2c68454f..bbef6a4e3 100644
--- a/Source/WebCore/platform/AsyncFileSystem.h
+++ b/Source/WebCore/platform/AsyncFileSystem.h
@@ -54,14 +54,26 @@ public:
enum Type {
Temporary,
Persistent,
- External,
};
+ // 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[];
+ static const size_t persistentPathPrefixLength;
+ static const char temporaryPathPrefix[];
+ static const size_t temporaryPathPrefixLength;
+
virtual void stop() { }
virtual bool hasPendingActivity() { return false; }
static bool isAvailable();
+ static bool isValidType(Type);
+
+ static bool crackFileSystemURL(const KURL&, Type&, String& filePath);
+
+ virtual String toURL(const String& originString, const String& fullPath) = 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; }
diff --git a/Source/WebCore/platform/AutodrainedPool.h b/Source/WebCore/platform/AutodrainedPool.h
index f03ec812e..207aadcbe 100644
--- a/Source/WebCore/platform/AutodrainedPool.h
+++ b/Source/WebCore/platform/AutodrainedPool.h
@@ -31,11 +31,7 @@
#include <wtf/Noncopyable.h>
-#ifdef __OBJC__
-@class NSAutoreleasePool;
-#else
-class NSAutoreleasePool;
-#endif
+OBJC_CLASS NSAutoreleasePool;
namespace WebCore {
diff --git a/Source/WebCore/platform/CalculationValue.cpp b/Source/WebCore/platform/CalculationValue.cpp
new file mode 100755
index 000000000..b9e38581a
--- /dev/null
+++ b/Source/WebCore/platform/CalculationValue.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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 "CalculationValue.h"
+
+namespace WebCore {
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/mock/SpeechInputClientMock.h b/Source/WebCore/platform/CalculationValue.h
index 4e13242ac..44a52d5ed 100644..100755
--- a/Source/WebCore/platform/mock/SpeechInputClientMock.h
+++ b/Source/WebCore/platform/CalculationValue.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
+ * 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
@@ -28,51 +28,25 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SpeechInputClientMock_h
-#define SpeechInputClientMock_h
+#ifndef CalculationValue_h
+#define CalculationValue_h
-#include "PlatformString.h"
-#include "SpeechInputClient.h"
-#include "SpeechInputResult.h"
-#include "Timer.h"
-#include <wtf/HashMap.h>
-#include <wtf/text/StringHash.h>
-
-#if ENABLE(INPUT_SPEECH)
+#include "Length.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
namespace WebCore {
-class SpeechInputListener;
-
-// Provides a mock object for the speech input embedder API called by WebCore.
-class SpeechInputClientMock : public SpeechInputClient {
-public:
- SpeechInputClientMock();
-
- void addRecognitionResult(const String& result, double confidence, const AtomicString& language);
- void clearResults();
-
- // SpeechInputClient methods.
- void setListener(SpeechInputListener*);
- bool startRecognition(int requestId, const IntRect& elementRect, const AtomicString& language, const String& grammar, SecurityOrigin*);
- void stopRecording(int);
- void cancelRecognition(int);
-
-private:
- void timerFired(Timer<SpeechInputClientMock>*);
-
- bool m_recording;
- Timer<SpeechInputClientMock> m_timer;
- SpeechInputListener* m_listener;
- int m_requestId;
-
- HashMap<String, SpeechInputResultArray> m_recognitionResults;
- AtomicString m_language;
- SpeechInputResultArray m_resultsForEmptyLanguage;
+enum CalcOperator {
+ CalcAdd = '+',
+ CalcSubtract = '-',
+ CalcMultiply = '*',
+ CalcDivide = '/',
+ CalcMod = '%'
};
} // namespace WebCore
-#endif // ENABLE(INPUT_SPEECH)
-
-#endif // SpeechInputClientMock_h
+#endif // CalculationValue_h
diff --git a/Source/WebCore/platform/ContextMenuItem.h b/Source/WebCore/platform/ContextMenuItem.h
index 98d4be245..2520c64e6 100644
--- a/Source/WebCore/platform/ContextMenuItem.h
+++ b/Source/WebCore/platform/ContextMenuItem.h
@@ -33,12 +33,7 @@
#if PLATFORM(MAC)
#include <wtf/RetainPtr.h>
-
-#ifdef __OBJC__
-@class NSMenuItem;
-#else
-class NSMenuItem;
-#endif
+OBJC_CLASS NSMenuItem;
#elif PLATFORM(WIN)
typedef struct tagMENUITEMINFOW MENUITEMINFO;
#elif PLATFORM(GTK)
@@ -64,7 +59,7 @@ namespace WebCore {
ContextMenuItemTagOpenImageInNewWindow,
ContextMenuItemTagDownloadImageToDisk,
ContextMenuItemTagCopyImageToClipboard,
-#if PLATFORM(QT) || PLATFORM(GTK)
+#if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL)
ContextMenuItemTagCopyImageUrlToClipboard,
#endif
ContextMenuItemTagOpenFrameInNewWindow,
diff --git a/Source/WebCore/platform/Cursor.h b/Source/WebCore/platform/Cursor.h
index c324ef00e..bc5184070 100644
--- a/Source/WebCore/platform/Cursor.h
+++ b/Source/WebCore/platform/Cursor.h
@@ -46,11 +46,7 @@ typedef HICON HCURSOR;
#endif
#if PLATFORM(MAC) && !PLATFORM(IOS)
-#ifdef __OBJC__
-@class NSCursor;
-#else
-class NSCursor;
-#endif
+OBJC_CLASS NSCursor;
#endif
#if PLATFORM(WX)
diff --git a/Source/WebCore/platform/DragData.h b/Source/WebCore/platform/DragData.h
index bb242f9e9..17abd44fa 100644
--- a/Source/WebCore/platform/DragData.h
+++ b/Source/WebCore/platform/DragData.h
@@ -36,15 +36,17 @@
#if PLATFORM(MAC)
#include <wtf/RetainPtr.h>
+
#ifdef __OBJC__
#import <Foundation/Foundation.h>
#import <AppKit/NSDragging.h>
typedef id <NSDraggingInfo> DragDataRef;
-@class NSPasteboard;
#else
typedef void* DragDataRef;
-class NSPasteboard;
#endif
+
+OBJC_CLASS NSPasteboard;
+
#elif PLATFORM(QT)
QT_BEGIN_NAMESPACE
class QMimeData;
diff --git a/Source/WebCore/platform/DragImage.h b/Source/WebCore/platform/DragImage.h
index 811fa56d2..a22db6a76 100644
--- a/Source/WebCore/platform/DragImage.h
+++ b/Source/WebCore/platform/DragImage.h
@@ -32,11 +32,7 @@
#if PLATFORM(MAC)
#include <wtf/RetainPtr.h>
-#ifdef __OBJC__
-@class NSImage;
-#else
-class NSImage;
-#endif
+OBJC_CLASS NSImage;
#elif PLATFORM(QT)
QT_BEGIN_NAMESPACE
class QPixmap;
diff --git a/Source/WebCore/platform/KURL.cpp b/Source/WebCore/platform/KURL.cpp
index 2408cc2b4..606280ab4 100644
--- a/Source/WebCore/platform/KURL.cpp
+++ b/Source/WebCore/platform/KURL.cpp
@@ -68,6 +68,18 @@ static inline bool isLetterMatchIgnoringCase(UChar character, char lowercaseLett
#if !USE(GOOGLEURL)
+static const char wsScheme[] = {'w', 's'};
+static const char ftpScheme[] = {'f', 't', 'p'};
+static const char ftpPort[] = {'2', '1'};
+static const char wssScheme[] = {'w', 's', 's'};
+static const char fileScheme[] = {'f', 'i', 'l', 'e'};
+static const char httpScheme[] = {'h', 't', 't', 'p'};
+static const char httpPort[] = {'8', '0'};
+static const char httpsScheme[] = {'h', 't', 't', 'p', 's'};
+static const char httpsPort[] = {'4', '4', '3'};
+static const char gopherScheme[] = {'g', 'o', 'p', 'h', 'e', 'r'};
+static const char gopherPort[] = {'7', '0'};
+
static inline bool isLetterMatchIgnoringCase(char character, char lowercaseLetter)
{
ASSERT(isASCIILower(lowercaseLetter));
@@ -1050,13 +1062,20 @@ void KURL::parse(const String& string)
parse(buffer.data(), &string);
}
-// FIXME: (lenA != lenB) is never true in the way this function is used.
-// FIXME: This is only used for short string, we should replace equal() by a recursive template comparing the strings without loop.
-static inline bool equal(const char* a, size_t lenA, const char* b, size_t lenB)
+template<size_t length>
+static inline bool equal(const char* a, const char (&b)[length])
{
- if (lenA != lenB)
- return false;
- return !strncmp(a, b, lenA);
+ for (size_t i = 0; i < length; ++i) {
+ if (a[i] != b[i])
+ return false;
+ }
+ return true;
+}
+
+template<size_t lengthB>
+static inline bool equal(const char* stringA, size_t lengthA, const char (&stringB)[lengthB])
+{
+ return lengthA == lengthB && equal(stringA, stringB);
}
// List of default schemes is taken from google-url:
@@ -1067,19 +1086,19 @@ static inline bool isDefaultPortForScheme(const char* port, size_t portLength, c
// the code was moved from google-url, but may be removed later.
switch (schemeLength) {
case 2:
- return equal("ws", 2, scheme, schemeLength) && equal("80", 2, port, portLength);
+ return equal(scheme, wsScheme) && equal(port, portLength, httpPort);
case 3:
- if (equal("ftp", 3, scheme, schemeLength))
- return equal("21", 2, port, portLength);
- if (equal("wss", 3, scheme, schemeLength))
- return equal("443", 3, port, portLength);
+ if (equal(scheme, ftpScheme))
+ return equal(port, portLength, ftpPort);
+ if (equal(scheme, wssScheme))
+ return equal(port, portLength, httpsPort);
break;
case 4:
- return equal("http", 4, scheme, schemeLength) && equal("80", 2, port, portLength);
+ return equal(scheme, httpScheme) && equal(port, portLength, httpPort);
case 5:
- return equal("https", 5, scheme, schemeLength) && equal("443", 3, port, portLength);
+ return equal(scheme, httpsScheme) && equal(port, portLength, httpsPort);
case 6:
- return equal("gopher", 6, scheme, schemeLength) && equal("70", 2, port, portLength);
+ return equal(scheme, gopherScheme) && equal(port, portLength, gopherPort);
}
return false;
}
@@ -1093,15 +1112,15 @@ static bool isNonFileHierarchicalScheme(const char* scheme, size_t schemeLength)
{
switch (schemeLength) {
case 2:
- return equal("ws", 2, scheme, schemeLength);
+ return equal(scheme, wsScheme);
case 3:
- return equal("ftp", 3, scheme, schemeLength) || equal("wss", 3, scheme, schemeLength);
+ return equal(scheme, ftpScheme) || equal(scheme, wssScheme);
case 4:
- return equal("http", 4, scheme, schemeLength);
+ return equal(scheme, httpScheme);
case 5:
- return equal("https", 5, scheme, schemeLength);
+ return equal(scheme, httpsScheme);
case 6:
- return equal("gopher", 6, scheme, schemeLength);
+ return equal(scheme, gopherScheme);
}
return false;
}
@@ -1110,15 +1129,15 @@ static bool isCanonicalHostnameLowercaseForScheme(const char* scheme, size_t sch
{
switch (schemeLength) {
case 2:
- return equal("ws", 2, scheme, schemeLength);
+ return equal(scheme, wsScheme);
case 3:
- return equal("ftp", 3, scheme, schemeLength) || equal("wss", 3, scheme, schemeLength);
+ return equal(scheme, ftpScheme) || equal(scheme, wssScheme);
case 4:
- return equal("http", 4, scheme, schemeLength) || equal("file", 4, scheme, schemeLength);
+ return equal(scheme, httpScheme) || equal(scheme, fileScheme);
case 5:
- return equal("https", 5, scheme, schemeLength);
+ return equal(scheme, httpsScheme);
case 6:
- return equal("gopher", 6, scheme, schemeLength);
+ return equal(scheme, gopherScheme);
}
return false;
}
@@ -1324,7 +1343,7 @@ void KURL::parse(const char* url, const String* originalString)
&& isLetterMatchIgnoringCase(url[userStart+8], 't');
// File URLs need a host part unless it is just file:// or file://localhost
- bool degenFilePath = pathStart == pathEnd && (hostStart == hostEnd || hostIsLocalHost);
+ bool degenerateFilePath = pathStart == pathEnd && (hostStart == hostEnd || hostIsLocalHost);
bool haveNonHostAuthorityPart = userStart != userEnd || passwordStart != passwordEnd || portStart != portEnd;
@@ -1332,7 +1351,7 @@ void KURL::parse(const char* url, const String* originalString)
*p++ = ':';
// if we have at least one authority part or a file URL - add "//" and authority
- if (isFile ? !degenFilePath : (haveNonHostAuthorityPart || hostStart != hostEnd)) {
+ if (isFile ? !degenerateFilePath : (haveNonHostAuthorityPart || hostStart != hostEnd)) {
*p++ = '/';
*p++ = '/';
@@ -1385,12 +1404,18 @@ void KURL::parse(const char* url, const String* originalString)
}
}
m_portEnd = p - buffer.data();
- } else
+ } else {
+ if (isFile) {
+ ASSERT(degenerateFilePath);
+ *p++ = '/';
+ *p++ = '/';
+ }
m_userStart = m_userEnd = m_passwordEnd = m_hostEnd = m_portEnd = p - buffer.data();
+ }
// For canonicalization, ensure we have a '/' for no path.
- // Do this only for URL with protocol http or https.
- if (m_protocolIsInHTTPFamily && pathEnd == pathStart)
+ // Do this only for URL with protocol file, http or https.
+ if ((m_protocolIsInHTTPFamily || isFile) && pathEnd == pathStart)
*p++ = '/';
// add path, escaping bad characters
diff --git a/Source/WebCore/platform/KURL.h b/Source/WebCore/platform/KURL.h
index 49cd9514c..9afced50e 100644
--- a/Source/WebCore/platform/KURL.h
+++ b/Source/WebCore/platform/KURL.h
@@ -35,11 +35,7 @@ typedef const struct __CFURL* CFURLRef;
#endif
#if PLATFORM(MAC) || (PLATFORM(QT) && USE(QTKIT))
-#ifdef __OBJC__
-@class NSURL;
-#else
-class NSURL;
-#endif
+OBJC_CLASS NSURL;
#endif
#if PLATFORM(QT)
@@ -222,6 +218,13 @@ public:
const CString& utf8String() const { return m_url.utf8String(); }
#endif
+
+#if USE(GOOGLEURL)
+ const KURL* innerURL() const { return m_url.innerURL(); }
+#else
+ const KURL* innerURL() const { return 0; }
+#endif
+
#ifndef NDEBUG
void print() const;
#endif
diff --git a/Source/WebCore/platform/KURLGoogle.cpp b/Source/WebCore/platform/KURLGoogle.cpp
index 6bf9fccb1..0507a2412 100644
--- a/Source/WebCore/platform/KURLGoogle.cpp
+++ b/Source/WebCore/platform/KURLGoogle.cpp
@@ -174,6 +174,35 @@ KURLGooglePrivate::KURLGooglePrivate(WTF::HashTableDeletedValueType)
{
}
+KURLGooglePrivate::KURLGooglePrivate(const KURLGooglePrivate& o)
+ : m_isValid(o.m_isValid)
+ , m_protocolIsInHTTPFamily(o.m_protocolIsInHTTPFamily)
+ , m_parsed(o.m_parsed)
+ , m_utf8(o.m_utf8)
+ , m_utf8IsASCII(o.m_utf8IsASCII)
+ , m_stringIsValid(o.m_stringIsValid)
+ , m_string(o.m_string)
+{
+ if (o.m_innerURL.get())
+ m_innerURL = adoptPtr(new KURL(o.m_innerURL->copy()));
+}
+
+KURLGooglePrivate& KURLGooglePrivate::operator=(const KURLGooglePrivate& o)
+{
+ m_isValid = o.m_isValid;
+ m_protocolIsInHTTPFamily = o.m_protocolIsInHTTPFamily;
+ m_parsed = o.m_parsed;
+ m_utf8 = o.m_utf8;
+ m_utf8IsASCII = o.m_utf8IsASCII;
+ m_stringIsValid = o.m_stringIsValid;
+ m_string = o.m_string;
+ if (o.m_innerURL.get())
+ m_innerURL = adoptPtr(new KURL(o.m_innerURL->copy()));
+ else
+ m_innerURL.clear();
+ return *this;
+}
+
// Setters for the data. Using the ASCII version when you know the
// data is ASCII will be slightly more efficient. The UTF-8 version
// will always be correct if the caller is unsure.
@@ -197,6 +226,7 @@ void KURLGooglePrivate::setUtf8(const CString& str)
m_utf8 = str;
m_stringIsValid = false;
initProtocolIsInHTTPFamily();
+ initInnerURL();
}
void KURLGooglePrivate::setAscii(const CString& str)
@@ -205,6 +235,7 @@ void KURLGooglePrivate::setAscii(const CString& str)
m_utf8IsASCII = true;
m_stringIsValid = false;
initProtocolIsInHTTPFamily();
+ initInnerURL();
}
void KURLGooglePrivate::init(const KURL& base,
@@ -258,6 +289,21 @@ void KURLGooglePrivate::init(const KURL& base, const CHAR* rel, int relLength,
}
}
+void KURLGooglePrivate::initInnerURL()
+{
+ if (!m_isValid) {
+ m_innerURL.clear();
+ return;
+ }
+ url_parse::Parsed* innerParsed = m_parsed.inner_parsed();
+ if (innerParsed)
+ m_innerURL = adoptPtr(new KURL(
+ ParsedURLString,
+ String(m_utf8.data() + innerParsed->scheme.begin, innerParsed->Length() - innerParsed->scheme.begin)));
+ else
+ m_innerURL.clear();
+}
+
void KURLGooglePrivate::initProtocolIsInHTTPFamily()
{
if (!m_isValid) {
@@ -285,6 +331,10 @@ void KURLGooglePrivate::copyTo(KURLGooglePrivate* dest) const
dest->m_utf8IsASCII = m_utf8IsASCII;
dest->m_stringIsValid = false;
dest->m_string = String(); // Clear the invalid string to avoid cross thread ref counting.
+ if (m_innerURL)
+ dest->m_innerURL = adoptPtr(new KURL(m_innerURL->copy()));
+ else
+ dest->m_innerURL.clear();
}
String KURLGooglePrivate::componentString(const url_parse::Component& comp) const
@@ -827,7 +877,10 @@ String encodeWithURLEscapeSequences(const String& notEncodedString)
buffer.Resize(inputLength * 3);
url_util::EncodeURIComponent(input, inputLength, &buffer);
- return String(buffer.data(), buffer.length());
+ String escaped(buffer.data(), buffer.length());
+ // Unescape '/'; it's safe and much prettier.
+ escaped.replace("%2F", "/");
+ return escaped;
}
bool KURL::isHierarchical() const
diff --git a/Source/WebCore/platform/KURLGooglePrivate.h b/Source/WebCore/platform/KURLGooglePrivate.h
index 31efd64ee..374d0d726 100644
--- a/Source/WebCore/platform/KURLGooglePrivate.h
+++ b/Source/WebCore/platform/KURLGooglePrivate.h
@@ -31,6 +31,7 @@
#ifndef KURLGooglePrivate_h
#define KURLGooglePrivate_h
+#include <wtf/OwnPtr.h>
#include <wtf/text/CString.h>
#include <googleurl/src/url_parse.h>
@@ -49,6 +50,8 @@ namespace WebCore {
KURLGooglePrivate();
KURLGooglePrivate(const url_parse::Parsed&, bool isValid);
KURLGooglePrivate(WTF::HashTableDeletedValueType);
+ KURLGooglePrivate(const KURLGooglePrivate&);
+ KURLGooglePrivate& operator=(const KURLGooglePrivate&);
// Initializes the object. This will call through the backend initializer
// below.
@@ -94,7 +97,10 @@ namespace WebCore {
bool m_protocolIsInHTTPFamily;
url_parse::Parsed m_parsed; // Indexes into the UTF-8 version of the string.
+ KURL* innerURL() const { return m_innerURL.get(); }
+
private:
+ void initInnerURL();
void initProtocolIsInHTTPFamily();
CString m_utf8;
@@ -107,6 +113,8 @@ namespace WebCore {
mutable bool m_stringIsValid;
mutable String m_string;
+
+ OwnPtr<KURL> m_innerURL;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/Language.cpp b/Source/WebCore/platform/Language.cpp
index 6cf259724..47f09f609 100644
--- a/Source/WebCore/platform/Language.cpp
+++ b/Source/WebCore/platform/Language.cpp
@@ -56,24 +56,91 @@ void languageDidChange()
iter->second(iter->first);
}
-static String& languageOverride()
+String defaultLanguage()
+{
+ Vector<String> languages = userPreferredLanguages();
+ if (languages.size())
+ return languages[0];
+
+ return emptyString();
+}
+
+static Vector<String>& preferredLanguagesOverride()
{
- DEFINE_STATIC_LOCAL(String, override, ());
+ DEFINE_STATIC_LOCAL(Vector<String>, override, ());
return override;
}
-String defaultLanguage()
+void overrideUserPreferredLanguages(const Vector<String>& override)
{
- const String& override = languageOverride();
- if (!override.isNull())
+ preferredLanguagesOverride() = override;
+}
+
+Vector<String> userPreferredLanguages()
+{
+ Vector<String>& override = preferredLanguagesOverride();
+ if (!override.isEmpty())
return override;
+
+ return platformUserPreferredLanguages();
+}
+
+static String canonicalLanguageIdentifier(const String& languageCode)
+{
+ String lowercaseLanguageCode = languageCode.lower();
+
+ if (lowercaseLanguageCode.length() >= 3 && lowercaseLanguageCode[2] == '_')
+ lowercaseLanguageCode.replace(2, 1, "-");
- return platformDefaultLanguage();
+ return lowercaseLanguageCode;
}
-void overrideDefaultLanguage(const String& override)
+static String bestMatchingLanguage(const String& language, const Vector<String>& languageList)
{
- languageOverride() = override;
+ bool canMatchLanguageOnly = (language.length() == 2 || (language.length() >= 3 && language[2] == '-'));
+ String languageWithoutLocaleMatch;
+ String languageMatchButNotLocale;
+
+ for (size_t i = 0; i < languageList.size(); ++i) {
+ String canonicalizedLanguageFromList = canonicalLanguageIdentifier(languageList[i]);
+
+ if (language == canonicalizedLanguageFromList)
+ return languageList[i];
+
+ if (canMatchLanguageOnly && canonicalizedLanguageFromList.length() >= 2) {
+ if (language[0] == canonicalizedLanguageFromList[0] && language[1] == canonicalizedLanguageFromList[1]) {
+ if (!languageWithoutLocaleMatch.length() && canonicalizedLanguageFromList.length() == 2)
+ languageWithoutLocaleMatch = languageList[i];
+ if (!languageMatchButNotLocale.length() && canonicalizedLanguageFromList.length() >= 3)
+ languageMatchButNotLocale = languageList[i];
+ }
+ }
+ }
+
+ // If we have both a language-only match and a languge-but-not-locale match, return the
+ // languge-only match as is considered a "better" match. For example, if the list
+ // provided has both "en-GB" and "en" and the user prefers "en-US" we will return "en".
+ if (languageWithoutLocaleMatch.length())
+ return languageWithoutLocaleMatch;
+
+ if (languageMatchButNotLocale.length())
+ return languageMatchButNotLocale;
+
+ return emptyString();
}
+String preferredLanguageFromList(const Vector<String>& languageList)
+{
+ Vector<String> preferredLanguages = userPreferredLanguages();
+
+ for (size_t i = 0; i < preferredLanguages.size(); ++i) {
+ String bestMatch = bestMatchingLanguage(canonicalLanguageIdentifier(preferredLanguages[i]), languageList);
+
+ if (bestMatch.length())
+ return bestMatch;
+ }
+
+ return emptyString();
+}
+
}
diff --git a/Source/WebCore/platform/Language.h b/Source/WebCore/platform/Language.h
index 656caee07..411615c9e 100644
--- a/Source/WebCore/platform/Language.h
+++ b/Source/WebCore/platform/Language.h
@@ -27,18 +27,23 @@
#define Language_h
#include <wtf/Forward.h>
+#include <wtf/Vector.h>
namespace WebCore {
String defaultLanguage();
-void overrideDefaultLanguage(const String&);
+Vector<String> userPreferredLanguages();
+void overrideUserPreferredLanguages(const Vector<String>&);
+String preferredLanguageFromList(const Vector<String>&);
-// The observer function will be called when system language changes (unless it's overridden by overrideDefaultLanguage()).
+// The observer function will be called when system language changes.
typedef void (*LanguageChangeObserverFunction)(void* context);
void addLanguageChangeObserver(void* context, LanguageChangeObserverFunction);
void removeLanguageChangeObserver(void* context);
-String platformDefaultLanguage();
+Vector<String> platformUserPreferredLanguages();
+
+// Called from platform specific code when the user's preferred language(s) change.
void languageDidChange();
}
diff --git a/Source/WebCore/platform/LocalizationStrategy.h b/Source/WebCore/platform/LocalizationStrategy.h
index b00ab13d0..8fab764b8 100644
--- a/Source/WebCore/platform/LocalizationStrategy.h
+++ b/Source/WebCore/platform/LocalizationStrategy.h
@@ -58,7 +58,7 @@ public:
virtual String contextMenuItemTagOpenImageInNewWindow() = 0;
virtual String contextMenuItemTagDownloadImageToDisk() = 0;
virtual String contextMenuItemTagCopyImageToClipboard() = 0;
-#if PLATFORM(QT) || PLATFORM(GTK)
+#if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL)
virtual String contextMenuItemTagCopyImageUrlToClipboard() = 0;
#endif
virtual String contextMenuItemTagOpenFrameInNewWindow() = 0;
diff --git a/Source/WebCore/platform/LocalizedStrings.cpp b/Source/WebCore/platform/LocalizedStrings.cpp
index a6a41ac34..1409bbf31 100644
--- a/Source/WebCore/platform/LocalizedStrings.cpp
+++ b/Source/WebCore/platform/LocalizedStrings.cpp
@@ -127,7 +127,7 @@ String contextMenuItemTagCopyImageToClipboard()
return localizationStrategy()->contextMenuItemTagCopyImageToClipboard();
}
-#if PLATFORM(QT) || PLATFORM(GTK)
+#if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL)
String contextMenuItemTagCopyImageUrlToClipboard()
{
return localizationStrategy()->contextMenuItemTagCopyImageUrlToClipboard();
diff --git a/Source/WebCore/platform/LocalizedStrings.h b/Source/WebCore/platform/LocalizedStrings.h
index edceb6306..a73c991fe 100644
--- a/Source/WebCore/platform/LocalizedStrings.h
+++ b/Source/WebCore/platform/LocalizedStrings.h
@@ -54,7 +54,7 @@ namespace WebCore {
String contextMenuItemTagOpenImageInNewWindow();
String contextMenuItemTagDownloadImageToDisk();
String contextMenuItemTagCopyImageToClipboard();
-#if PLATFORM(QT) || PLATFORM(GTK)
+#if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL)
String contextMenuItemTagCopyImageUrlToClipboard();
#endif
String contextMenuItemTagOpenFrameInNewWindow();
diff --git a/Source/WebCore/platform/Logging.cpp b/Source/WebCore/platform/Logging.cpp
index 8f6428241..bd0196410 100644
--- a/Source/WebCore/platform/Logging.cpp
+++ b/Source/WebCore/platform/Logging.cpp
@@ -61,6 +61,8 @@ WTFLogChannel LogProgress = { 0x08000000, "WebCoreLogLevel", WTFLogChan
WTFLogChannel LogFileAPI = { 0x10000000, "WebCoreLogLevel", WTFLogChannelOff };
+WTFLogChannel LogWebAudio = { 0x20000000, "WebCoreLogLevel", WTFLogChannelOff };
+
WTFLogChannel* getChannelFromName(const String& channelName)
{
if (!(channelName.length() >= 2))
@@ -135,6 +137,9 @@ WTFLogChannel* getChannelFromName(const String& channelName)
if (equalIgnoringCase(channelName, String("FileAPI")))
return &LogFileAPI;
+ if (equalIgnoringCase(channelName, String("WebAudio")))
+ return &LogWebAudio;
+
return 0;
}
diff --git a/Source/WebCore/platform/Logging.h b/Source/WebCore/platform/Logging.h
index 0092699d7..8201f16b3 100644
--- a/Source/WebCore/platform/Logging.h
+++ b/Source/WebCore/platform/Logging.h
@@ -59,6 +59,7 @@ namespace WebCore {
extern WTFLogChannel LogArchives;
extern WTFLogChannel LogProgress;
extern WTFLogChannel LogFileAPI;
+ extern WTFLogChannel LogWebAudio;
void initializeLoggingChannelsIfNecessary();
WTFLogChannel* getChannelFromName(const String& channelName);
diff --git a/Source/WebCore/platform/MIMETypeRegistry.cpp b/Source/WebCore/platform/MIMETypeRegistry.cpp
index d20986159..b5f2d4551 100644
--- a/Source/WebCore/platform/MIMETypeRegistry.cpp
+++ b/Source/WebCore/platform/MIMETypeRegistry.cpp
@@ -261,6 +261,10 @@ static void initializeSupportedImageMIMETypes()
supportedImageMIMETypes->add(types[i]);
supportedImageResourceMIMETypes->add(types[i]);
}
+#if PLATFORM(BLACKBERRY)
+ supportedImageMIMETypes->add("image/pjpeg");
+ supportedImageResourceMIMETypes->add("image/pjpeg");
+#endif
#endif
}
diff --git a/Source/WebCore/platform/MemoryPressureHandler.cpp b/Source/WebCore/platform/MemoryPressureHandler.cpp
index bb0c64c97..982876d05 100644
--- a/Source/WebCore/platform/MemoryPressureHandler.cpp
+++ b/Source/WebCore/platform/MemoryPressureHandler.cpp
@@ -42,7 +42,7 @@ MemoryPressureHandler::MemoryPressureHandler()
{
}
-#if !PLATFORM(MAC) || defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD)
+#if !PLATFORM(MAC) || defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD) || PLATFORM(IOS)
void MemoryPressureHandler::install() { }
void MemoryPressureHandler::uninstall() { }
diff --git a/Source/WebCore/platform/MemoryPressureHandler.h b/Source/WebCore/platform/MemoryPressureHandler.h
index d9d2d90b2..9d6e95f8d 100644
--- a/Source/WebCore/platform/MemoryPressureHandler.h
+++ b/Source/WebCore/platform/MemoryPressureHandler.h
@@ -45,6 +45,7 @@ private:
~MemoryPressureHandler();
void respondToMemoryPressure();
+ void releaseMemory(bool critical);
bool m_installed;
time_t m_lastRespondTime;
diff --git a/Source/WebCore/platform/Pasteboard.h b/Source/WebCore/platform/Pasteboard.h
index 866e7e532..fedfc8abd 100644
--- a/Source/WebCore/platform/Pasteboard.h
+++ b/Source/WebCore/platform/Pasteboard.h
@@ -43,15 +43,9 @@
// knowledge of the frame and editor or moved into the editing directory.
#if PLATFORM(MAC)
-#ifdef __OBJC__
-@class NSFileWrapper;
-@class NSPasteboard;
-@class NSArray;
-#else
-class NSFileWrapper;
-class NSPasteboard;
-class NSArray;
-#endif
+OBJC_CLASS NSFileWrapper;
+OBJC_CLASS NSPasteboard;
+OBJC_CLASS NSArray;
#endif
#if PLATFORM(WIN)
@@ -86,12 +80,10 @@ class Pasteboard {
WTF_MAKE_NONCOPYABLE(Pasteboard); WTF_MAKE_FAST_ALLOCATED;
public:
#if PLATFORM(MAC)
- //Helper functions to allow Clipboard to share code
- static void writeSelection(NSPasteboard*, NSArray* pasteboardTypes, Range* selectedRange, bool canSmartCopyOrDelete, Frame*);
- static void writeURL(NSPasteboard* pasteboard, NSArray* types, const KURL& url, const String& titleStr, Frame* frame);
- static void writePlainText(NSPasteboard* pasteboard, const String& text);
+ void writeSelectionForTypes(NSArray* pasteboardTypes, Range* selectedRange, bool canSmartCopyOrDelete, Frame*);
+ void writeURLForTypes(NSArray* types, const KURL&, const String& titleStr, Frame*);
- Pasteboard(NSPasteboard *);
+ Pasteboard(const String& pasteboardName);
#endif
static Pasteboard* generalPasteboard();
diff --git a/Source/WebCore/platform/PlatformKeyboardEvent.h b/Source/WebCore/platform/PlatformKeyboardEvent.h
index f15496673..5990098db 100644
--- a/Source/WebCore/platform/PlatformKeyboardEvent.h
+++ b/Source/WebCore/platform/PlatformKeyboardEvent.h
@@ -32,11 +32,7 @@
#if PLATFORM(MAC)
#include <wtf/RetainPtr.h>
-#ifdef __OBJC__
-@class NSEvent;
-#else
-class NSEvent;
-#endif
+OBJC_CLASS NSEvent;
#endif
#if PLATFORM(WIN)
diff --git a/Source/WebCore/platform/PlatformMenuDescription.h b/Source/WebCore/platform/PlatformMenuDescription.h
index 08845cb4a..459d0a5ea 100644
--- a/Source/WebCore/platform/PlatformMenuDescription.h
+++ b/Source/WebCore/platform/PlatformMenuDescription.h
@@ -27,11 +27,7 @@
#define PlatformMenuDescription_h
#if PLATFORM(MAC)
-#ifdef __OBJC__
-@class NSMutableArray;
-#else
-class NSMutableArray;
-#endif
+OBJC_CLASS NSMutableArray;
#elif PLATFORM(QT)
#include <qlist.h>
#elif PLATFORM(GTK)
diff --git a/Source/WebCore/platform/PlatformScreen.h b/Source/WebCore/platform/PlatformScreen.h
index a9acb5dd0..827801b44 100644
--- a/Source/WebCore/platform/PlatformScreen.h
+++ b/Source/WebCore/platform/PlatformScreen.h
@@ -31,13 +31,8 @@
#include <wtf/RefPtr.h>
#if PLATFORM(MAC)
-#ifdef __OBJC__
- @class NSScreen;
- @class NSWindow;
-#else
- class NSScreen;
- class NSWindow;
-#endif
+OBJC_CLASS NSScreen;
+OBJC_CLASS NSWindow;
#endif
typedef uint32_t PlatformDisplayID;
@@ -45,6 +40,7 @@ typedef uint32_t PlatformDisplayID;
namespace WebCore {
class FloatRect;
+ class FrameView;
class Widget;
int screenHorizontalDPI(Widget*);
@@ -53,19 +49,14 @@ namespace WebCore {
int screenDepthPerComponent(Widget*);
bool screenIsMonochrome(Widget*);
- FloatRect screenRect(Widget*);
- FloatRect screenAvailableRect(Widget*);
-
-#if PLATFORM(CHROMIUM)
- // Measured in frames per second. 0 if the refresh rate is unknown, or not applicable.
- double screenRefreshRate(Widget*);
-#endif
+ FloatRect screenRect(FrameView*);
+ FloatRect screenAvailableRect(FrameView*);
#if PLATFORM(MAC)
NSScreen *screenForWindow(NSWindow *);
- FloatRect toUserSpace(const NSRect&, NSWindow *destination);
- NSRect toDeviceSpace(const FloatRect&, NSWindow *source);
+ FloatRect toUserSpace(const NSRect&, NSWindow *destination, float deviceScaleFactor);
+ NSRect toDeviceSpace(const FloatRect&, NSWindow *source, float deviceScaleFactor);
NSPoint flipScreenPoint(const NSPoint&, NSScreen *);
#endif
diff --git a/Source/WebCore/platform/PlatformWheelEvent.h b/Source/WebCore/platform/PlatformWheelEvent.h
index 8e99e4762..f76f4c958 100644
--- a/Source/WebCore/platform/PlatformWheelEvent.h
+++ b/Source/WebCore/platform/PlatformWheelEvent.h
@@ -77,11 +77,12 @@ namespace WebCore {
#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN))
enum PlatformWheelEventPhase {
PlatformWheelEventPhaseNone = 0,
- PlatformWheelEventPhaseBegan = 1 << 1,
- PlatformWheelEventPhaseStationary = 1 << 2,
- PlatformWheelEventPhaseChanged = 1 << 3,
- PlatformWheelEventPhaseEnded = 1 << 4,
- PlatformWheelEventPhaseCancelled = 1 << 5,
+ PlatformWheelEventPhaseBegan = 1 << 0,
+ PlatformWheelEventPhaseStationary = 1 << 1,
+ PlatformWheelEventPhaseChanged = 1 << 2,
+ PlatformWheelEventPhaseEnded = 1 << 3,
+ PlatformWheelEventPhaseCancelled = 1 << 4,
+ PlatformWheelEventPhaseMayBegin = 1 << 5,
};
#endif
diff --git a/Source/WebCore/platform/PopupMenuClient.h b/Source/WebCore/platform/PopupMenuClient.h
index 7c2b4a9b4..4abe3379c 100644
--- a/Source/WebCore/platform/PopupMenuClient.h
+++ b/Source/WebCore/platform/PopupMenuClient.h
@@ -64,7 +64,7 @@ public:
virtual void setTextFromItem(unsigned listIndex) = 0;
virtual void listBoxSelectItem(int /*listIndex*/, bool /*allowMultiplySelections*/, bool /*shift*/, bool /*fireOnChangeNow*/ = true) { ASSERT_NOT_REACHED(); }
- virtual bool multiple()
+ virtual bool multiple() const
{
ASSERT_NOT_REACHED();
return false;
diff --git a/Source/WebCore/platform/RunLoop.cpp b/Source/WebCore/platform/RunLoop.cpp
new file mode 100644
index 000000000..cbbca4c61
--- /dev/null
+++ b/Source/WebCore/platform/RunLoop.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 "RunLoop.h"
+
+#include <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+#if !PLATFORM(MAC)
+
+static RunLoop* s_mainRunLoop;
+
+void RunLoop::initializeMainRunLoop()
+{
+ if (s_mainRunLoop)
+ return;
+ s_mainRunLoop = RunLoop::current();
+}
+
+RunLoop* RunLoop::current()
+{
+ DEFINE_STATIC_LOCAL(WTF::ThreadSpecific<RunLoop>, runLoopData, ());
+ return &*runLoopData;
+}
+
+RunLoop* RunLoop::main()
+{
+ ASSERT(s_mainRunLoop);
+ return s_mainRunLoop;
+}
+
+#endif
+
+void RunLoop::performWork()
+{
+ Vector<Function<void()> > functionQueue;
+ {
+ MutexLocker locker(m_functionQueueLock);
+ m_functionQueue.swap(functionQueue);
+ }
+
+ for (size_t i = 0; i < functionQueue.size(); ++i)
+ functionQueue[i]();
+}
+
+void RunLoop::dispatch(const Function<void()>& function)
+{
+ MutexLocker locker(m_functionQueueLock);
+ m_functionQueue.append(function);
+
+ wakeUp();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/RunLoop.h b/Source/WebCore/platform/RunLoop.h
new file mode 100644
index 000000000..1f19c836d
--- /dev/null
+++ b/Source/WebCore/platform/RunLoop.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Portions Copyright (c) 2010 Motorola Mobility, 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 RunLoop_h
+#define RunLoop_h
+
+#include <wtf/Forward.h>
+#include <wtf/Functional.h>
+#include <wtf/HashMap.h>
+#include <wtf/ThreadSpecific.h>
+#include <wtf/Threading.h>
+#include <wtf/Vector.h>
+
+#if PLATFORM(GTK)
+#include <wtf/gobject/GRefPtr.h>
+typedef struct _GSource GSource;
+typedef struct _GMainLoop GMainLoop;
+typedef struct _GMainContext GMainContext;
+typedef int gboolean;
+#endif
+
+namespace WebCore {
+
+class RunLoop {
+public:
+ // Must be called from the main thread (except for the Mac platform, where it
+ // can be called from any thread).
+ static void initializeMainRunLoop();
+
+ static RunLoop* current();
+ static RunLoop* main();
+
+ void dispatch(const Function<void()>&);
+
+ static void run();
+ void stop();
+
+#if PLATFORM(MAC)
+ void runForDuration(double duration);
+#endif
+
+ class TimerBase {
+ friend class RunLoop;
+ public:
+ TimerBase(RunLoop*);
+ virtual ~TimerBase();
+
+ void startRepeating(double repeatInterval) { start(repeatInterval, true); }
+ void startOneShot(double interval) { start(interval, false); }
+
+ void stop();
+ bool isActive() const;
+
+ virtual void fired() = 0;
+
+ private:
+ void start(double nextFireInterval, bool repeat);
+
+ RunLoop* m_runLoop;
+
+#if PLATFORM(WIN)
+ static void timerFired(RunLoop*, uint64_t ID);
+ uint64_t m_ID;
+ bool m_isRepeating;
+#elif PLATFORM(MAC)
+ static void timerFired(CFRunLoopTimerRef, void*);
+ CFRunLoopTimerRef m_timer;
+#elif PLATFORM(QT)
+ static void timerFired(RunLoop*, int ID);
+ int m_ID;
+ bool m_isRepeating;
+#elif PLATFORM(GTK)
+ static gboolean timerFiredCallback(RunLoop::TimerBase*);
+ gboolean isRepeating() const { return m_isRepeating; }
+ void clearTimerSource();
+ GRefPtr<GSource> m_timerSource;
+ gboolean m_isRepeating;
+#endif
+ };
+
+ template <typename TimerFiredClass>
+ class Timer : public TimerBase {
+ public:
+ typedef void (TimerFiredClass::*TimerFiredFunction)();
+
+ Timer(RunLoop* runLoop, TimerFiredClass* o, TimerFiredFunction f)
+ : TimerBase(runLoop)
+ , m_object(o)
+ , m_function(f)
+ {
+ }
+
+ private:
+ virtual void fired() { (m_object->*m_function)(); }
+
+ TimerFiredClass* m_object;
+ TimerFiredFunction m_function;
+ };
+
+private:
+ friend class WTF::ThreadSpecific<RunLoop>;
+
+ RunLoop();
+ ~RunLoop();
+
+ void performWork();
+ void wakeUp();
+
+ Mutex m_functionQueueLock;
+ Vector<Function<void()> > m_functionQueue;
+
+#if PLATFORM(WIN)
+ static bool registerRunLoopMessageWindowClass();
+ static LRESULT CALLBACK RunLoopWndProc(HWND, UINT, WPARAM, LPARAM);
+ LRESULT wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+ HWND m_runLoopMessageWindow;
+
+ typedef HashMap<uint64_t, TimerBase*> TimerMap;
+ TimerMap m_activeTimers;
+#elif PLATFORM(MAC)
+ RunLoop(CFRunLoopRef);
+ static void performWork(void*);
+ CFRunLoopRef m_runLoop;
+ CFRunLoopSourceRef m_runLoopSource;
+ int m_nestingLevel;
+#elif PLATFORM(QT)
+ typedef HashMap<int, TimerBase*> TimerMap;
+ TimerMap m_activeTimers;
+ class TimerObject;
+ TimerObject* m_timerObject;
+#elif PLATFORM(GTK)
+public:
+ static gboolean queueWork(RunLoop*);
+ GMainLoop* mainLoop();
+private:
+ GMainContext* m_runLoopContext;
+ GMainLoop* m_runLoopMain;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // RunLoop_h
diff --git a/Source/WebCore/platform/SchemeRegistry.cpp b/Source/WebCore/platform/SchemeRegistry.cpp
index 5cdeb3375..d5d36f151 100644
--- a/Source/WebCore/platform/SchemeRegistry.cpp
+++ b/Source/WebCore/platform/SchemeRegistry.cpp
@@ -25,6 +25,7 @@
*/
#include "config.h"
#include "SchemeRegistry.h"
+#include <wtf/MainThread.h>
namespace WebCore {
@@ -152,6 +153,19 @@ static URLSchemesMap& schemesAllowingDatabaseAccessInPrivateBrowsing()
return schemesAllowingDatabaseAccessInPrivateBrowsing;
}
+static URLSchemesMap& CORSEnabledSchemes()
+{
+ // FIXME: http://bugs.webkit.org/show_bug.cgi?id=77160
+ DEFINE_STATIC_LOCAL(URLSchemesMap, CORSEnabledSchemes, ());
+
+ if (CORSEnabledSchemes.isEmpty()) {
+ CORSEnabledSchemes.add("http");
+ CORSEnabledSchemes.add("https");
+ }
+
+ return CORSEnabledSchemes;
+}
+
bool SchemeRegistry::shouldTreatURLSchemeAsLocal(const String& scheme)
{
if (scheme.isEmpty())
@@ -273,4 +287,16 @@ bool SchemeRegistry::allowsDatabaseAccessInPrivateBrowsing(const String& scheme)
return schemesAllowingDatabaseAccessInPrivateBrowsing().contains(scheme);
}
+void SchemeRegistry::registerURLSchemeAsCORSEnabled(const String& scheme)
+{
+ CORSEnabledSchemes().add(scheme);
+}
+
+bool SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(const String& scheme)
+{
+ if (scheme.isEmpty())
+ return false;
+ return CORSEnabledSchemes().contains(scheme);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/SchemeRegistry.h b/Source/WebCore/platform/SchemeRegistry.h
index 04f1bf864..9b08e0a41 100644
--- a/Source/WebCore/platform/SchemeRegistry.h
+++ b/Source/WebCore/platform/SchemeRegistry.h
@@ -78,6 +78,10 @@ public:
static bool allowsLocalStorageAccessInPrivateBrowsing(const String& scheme);
static void registerURLSchemeAsAllowingDatabaseAccessInPrivateBrowsing(const String& scheme);
static bool allowsDatabaseAccessInPrivateBrowsing(const String& scheme);
+
+ // Allow non-HTTP schemes to be registered to allow CORS requests.
+ static void registerURLSchemeAsCORSEnabled(const String& scheme);
+ static bool shouldTreatURLSchemeAsCORSEnabled(const String& scheme);
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/ScrollAnimator.h b/Source/WebCore/platform/ScrollAnimator.h
index 576743945..b33c45812 100644
--- a/Source/WebCore/platform/ScrollAnimator.h
+++ b/Source/WebCore/platform/ScrollAnimator.h
@@ -96,6 +96,8 @@ public:
virtual void resetZoom();
virtual void setZoomParametersForTest(float, float, float);
+ virtual bool shouldScrollbarParticipateInHitTesting(Scrollbar*) { return true; }
+
protected:
ScrollAnimator(ScrollableArea*);
diff --git a/Source/WebCore/platform/ScrollView.cpp b/Source/WebCore/platform/ScrollView.cpp
index d76a909e5..f2bb054a3 100644
--- a/Source/WebCore/platform/ScrollView.cpp
+++ b/Source/WebCore/platform/ScrollView.cpp
@@ -219,7 +219,11 @@ void ScrollView::setClipsRepaints(bool clipsRepaints)
void ScrollView::setDelegatesScrolling(bool delegatesScrolling)
{
+ if (m_delegatesScrolling == delegatesScrolling)
+ return;
+
m_delegatesScrolling = delegatesScrolling;
+ delegatesScrollingDidChange();
}
#if !PLATFORM(GTK)
@@ -828,9 +832,9 @@ Scrollbar* ScrollView::scrollbarAtPoint(const IntPoint& windowPoint)
return 0;
IntPoint viewPoint = convertFromContainingWindow(windowPoint);
- if (m_horizontalScrollbar && m_horizontalScrollbar->frameRect().contains(viewPoint))
+ if (m_horizontalScrollbar && m_horizontalScrollbar->shouldParticipateInHitTesting() && m_horizontalScrollbar->frameRect().contains(viewPoint))
return m_horizontalScrollbar.get();
- if (m_verticalScrollbar && m_verticalScrollbar->frameRect().contains(viewPoint))
+ if (m_verticalScrollbar && m_verticalScrollbar->shouldParticipateInHitTesting() && m_verticalScrollbar->frameRect().contains(viewPoint))
return m_verticalScrollbar.get();
return 0;
}
@@ -991,6 +995,7 @@ void ScrollView::scrollbarStyleChanged(int, bool forceUpdate)
contentsResized();
updateScrollbars(scrollOffset());
+ positionScrollbarLayers();
}
void ScrollView::updateScrollCorner()
@@ -1075,7 +1080,7 @@ void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
paintContents(context, documentDirtyRect);
}
-#if USE(ACCELERATED_COMPOSITING) && PLATFORM(CHROMIUM) && ENABLE(RUBBER_BANDING)
+#if USE(ACCELERATED_COMPOSITING) && ENABLE(RUBBER_BANDING)
if (!layerForOverhangAreas())
calculateAndPaintOverhangAreas(context, rect);
#else
diff --git a/Source/WebCore/platform/ScrollView.h b/Source/WebCore/platform/ScrollView.h
index 5d34a9288..ba586a4ab 100644
--- a/Source/WebCore/platform/ScrollView.h
+++ b/Source/WebCore/platform/ScrollView.h
@@ -301,6 +301,7 @@ protected:
virtual void paintOverhangAreas(GraphicsContext*, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect);
virtual void visibleContentsResized() = 0;
+ virtual void delegatesScrollingDidChange() { }
IntRect fixedVisibleContentRect() const { return m_fixedVisibleContentRect; }
diff --git a/Source/WebCore/platform/ScrollableArea.cpp b/Source/WebCore/platform/ScrollableArea.cpp
index 374092eb2..99b9babc3 100644
--- a/Source/WebCore/platform/ScrollableArea.cpp
+++ b/Source/WebCore/platform/ScrollableArea.cpp
@@ -181,7 +181,7 @@ void ScrollableArea::setScrollOffsetFromAnimation(const IntPoint& offset)
// Tell the scrollbars to update their thumb postions.
if (Scrollbar* horizontalScrollbar = this->horizontalScrollbar()) {
horizontalScrollbar->offsetDidChange();
- if (horizontalScrollbar->isOverlayScrollbar()) {
+ if (horizontalScrollbar->isOverlayScrollbar() && !hasLayerForHorizontalScrollbar()) {
if (!verticalScrollbar)
horizontalScrollbar->invalidate();
else {
@@ -195,7 +195,7 @@ void ScrollableArea::setScrollOffsetFromAnimation(const IntPoint& offset)
}
if (verticalScrollbar) {
verticalScrollbar->offsetDidChange();
- if (verticalScrollbar->isOverlayScrollbar())
+ if (verticalScrollbar->isOverlayScrollbar() && !hasLayerForVerticalScrollbar())
verticalScrollbar->invalidate();
}
}
diff --git a/Source/WebCore/platform/ScrollableArea.h b/Source/WebCore/platform/ScrollableArea.h
index 26a8cfe10..0b4583bbe 100644
--- a/Source/WebCore/platform/ScrollableArea.h
+++ b/Source/WebCore/platform/ScrollableArea.h
@@ -184,7 +184,7 @@ protected:
virtual GraphicsLayer* layerForHorizontalScrollbar() const { return 0; }
virtual GraphicsLayer* layerForVerticalScrollbar() const { return 0; }
virtual GraphicsLayer* layerForScrollCorner() const { return 0; }
-#if PLATFORM(CHROMIUM) && ENABLE(RUBBER_BANDING)
+#if ENABLE(RUBBER_BANDING)
virtual GraphicsLayer* layerForOverhangAreas() const { return 0; }
#endif
#endif
diff --git a/Source/WebCore/platform/Scrollbar.cpp b/Source/WebCore/platform/Scrollbar.cpp
index b952d49df..3b9c195cf 100644
--- a/Source/WebCore/platform/Scrollbar.cpp
+++ b/Source/WebCore/platform/Scrollbar.cpp
@@ -487,6 +487,14 @@ bool Scrollbar::isOverlayScrollbar() const
return m_theme->usesOverlayScrollbars();
}
+bool Scrollbar::shouldParticipateInHitTesting()
+{
+ // Non-overlay scrollbars should always participate in hit testing.
+ if (!isOverlayScrollbar())
+ return true;
+ return m_scrollableArea->scrollAnimator()->shouldScrollbarParticipateInHitTesting(this);
+}
+
bool Scrollbar::isWindowActive() const
{
return m_scrollableArea && m_scrollableArea->isActive();
diff --git a/Source/WebCore/platform/Scrollbar.h b/Source/WebCore/platform/Scrollbar.h
index 09b247b54..e4e72465b 100644
--- a/Source/WebCore/platform/Scrollbar.h
+++ b/Source/WebCore/platform/Scrollbar.h
@@ -87,6 +87,7 @@ public:
virtual void setEnabled(bool e);
virtual bool isOverlayScrollbar() const;
+ bool shouldParticipateInHitTesting();
bool isWindowActive() const;
diff --git a/Source/WebCore/platform/SharedBuffer.h b/Source/WebCore/platform/SharedBuffer.h
index d85abba1b..57cfc2949 100644
--- a/Source/WebCore/platform/SharedBuffer.h
+++ b/Source/WebCore/platform/SharedBuffer.h
@@ -23,6 +23,7 @@
* (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 SharedBuffer_h
#define SharedBuffer_h
@@ -37,12 +38,7 @@
#endif
#if PLATFORM(MAC) || (PLATFORM(QT) && USE(QTKIT))
-#ifdef __OBJC__
-@class NSData;
-#else
-class NSData;
-#endif
-
+OBJC_CLASS NSData;
#endif
namespace WebCore {
diff --git a/Source/WebCore/platform/Widget.h b/Source/WebCore/platform/Widget.h
index 9fddf7092..3f19b61e2 100644
--- a/Source/WebCore/platform/Widget.h
+++ b/Source/WebCore/platform/Widget.h
@@ -45,13 +45,8 @@
#endif
#if PLATFORM(MAC)
-#ifdef __OBJC__
-@class NSView;
-@class NSWindow;
-#else
-class NSView;
-class NSWindow;
-#endif
+OBJC_CLASS NSView;
+OBJC_CLASS NSWindow;
typedef NSView *PlatformWidget;
#endif
diff --git a/Source/WebCore/platform/animation/AnimationUtilities.h b/Source/WebCore/platform/animation/AnimationUtilities.h
index 128f2ed0e..aebca46bb 100644
--- a/Source/WebCore/platform/animation/AnimationUtilities.h
+++ b/Source/WebCore/platform/animation/AnimationUtilities.h
@@ -35,6 +35,11 @@ inline int blend(int from, int to, double progress)
return static_cast<int>(lround(static_cast<double>(from) + static_cast<double>(to - from) * progress));
}
+inline unsigned blend(unsigned from, unsigned to, double progress)
+{
+ return static_cast<unsigned>(lround(static_cast<double>(from) + static_cast<double>(to - from) * progress));
+}
+
inline double blend(double from, double to, double progress)
{
return from + (to - from) * progress;
diff --git a/Source/WebCore/platform/audio/AudioArray.h b/Source/WebCore/platform/audio/AudioArray.h
index a14c950dd..7a2251b38 100644
--- a/Source/WebCore/platform/audio/AudioArray.h
+++ b/Source/WebCore/platform/audio/AudioArray.h
@@ -127,7 +127,7 @@ public:
memset(this->data() + start, 0, sizeof(T) * (end - start));
}
- void copyToRange(T* sourceData, unsigned start, unsigned end)
+ void copyToRange(const T* sourceData, unsigned start, unsigned end)
{
bool isSafe = (start <= end) && (end <= this->size());
ASSERT(isSafe);
diff --git a/Source/WebCore/platform/audio/AudioBus.cpp b/Source/WebCore/platform/audio/AudioBus.cpp
index 800197e2d..eea191961 100644
--- a/Source/WebCore/platform/audio/AudioBus.cpp
+++ b/Source/WebCore/platform/audio/AudioBus.cpp
@@ -34,9 +34,7 @@
#include "DenormalDisabler.h"
-#if !PLATFORM(MAC)
#include "SincResampler.h"
-#endif
#include "VectorMath.h"
#include <algorithm>
#include <assert.h>
@@ -132,6 +130,11 @@ AudioChannel* AudioBus::channelByType(unsigned channelType)
return 0;
}
+const AudioChannel* AudioBus::channelByType(unsigned type) const
+{
+ return const_cast<AudioBus*>(this)->channelByType(type);
+}
+
// Returns true if the channel count and frame-size match.
bool AudioBus::topologyMatches(const AudioBus& bus) const
{
@@ -145,7 +148,7 @@ bool AudioBus::topologyMatches(const AudioBus& bus) const
return true;
}
-PassOwnPtr<AudioBus> AudioBus::createBufferFromRange(AudioBus* sourceBuffer, unsigned startFrame, unsigned endFrame)
+PassOwnPtr<AudioBus> AudioBus::createBufferFromRange(const AudioBus* sourceBuffer, unsigned startFrame, unsigned endFrame)
{
size_t numberOfSourceFrames = sourceBuffer->length();
unsigned numberOfChannels = sourceBuffer->numberOfChannels();
@@ -185,7 +188,7 @@ void AudioBus::normalize()
scale(1.0f / max);
}
-void AudioBus::scale(double scale)
+void AudioBus::scale(float scale)
{
for (unsigned i = 0; i < numberOfChannels(); ++i)
channel(i)->scale(scale);
@@ -243,7 +246,8 @@ void AudioBus::sumFrom(const AudioBus &sourceBus)
OP \
GAIN_DEZIPPER \
} \
- gain = totalDesiredGain; \
+ if (!framesToDezipper) \
+ gain = totalDesiredGain; \
OP##_V
#define STEREO_SUM \
@@ -254,10 +258,11 @@ void AudioBus::sumFrom(const AudioBus &sourceBus)
*destinationR++ = sumR; \
}
-// FIXME: this can be optimized with additional VectorMath functions.
#define STEREO_SUM_V \
- for (; k < framesToProcess; ++k) \
- STEREO_SUM
+ { \
+ vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
+ vsma(sourceR, 1, &gain, destinationR, 1, framesToProcess - k); \
+ }
// Mono -> stereo (mix equally into L and R)
// FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
@@ -271,8 +276,10 @@ void AudioBus::sumFrom(const AudioBus &sourceBus)
}
#define MONO2STEREO_SUM_V \
- for (; k < framesToProcess; ++k) \
- MONO2STEREO_SUM
+ { \
+ vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
+ vsma(sourceL, 1, &gain, destinationR, 1, framesToProcess - k); \
+ }
#define MONO_SUM \
{ \
@@ -281,8 +288,9 @@ void AudioBus::sumFrom(const AudioBus &sourceBus)
}
#define MONO_SUM_V \
- for (; k < framesToProcess; ++k) \
- MONO_SUM
+ { \
+ vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
+ }
#define STEREO_NO_SUM \
{ \
@@ -324,12 +332,10 @@ void AudioBus::sumFrom(const AudioBus &sourceBus)
vsmul(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
}
-void AudioBus::processWithGainFromMonoStereo(const AudioBus &sourceBus, double* lastMixGain, double targetGain, bool sumToBus)
+void AudioBus::processWithGainFromMonoStereo(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus)
{
// We don't want to suddenly change the gain from mixing one time slice to the next,
// so we "de-zipper" by slowly changing the gain each sample-frame until we've achieved the target gain.
-
- // FIXME: targetGain and lastMixGain should be changed to floats instead of doubles.
// Take master bus gain into account as well as the targetGain.
float totalDesiredGain = static_cast<float>(m_busGain * targetGain);
@@ -345,8 +351,8 @@ void AudioBus::processWithGainFromMonoStereo(const AudioBus &sourceBus, double*
const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
const float* sourceR = numberOfSourceChannels > 1 ? sourceBusSafe.channelByType(ChannelRight)->data() : 0;
- float* destinationL = channelByType(ChannelLeft)->data();
- float* destinationR = numberOfDestinationChannels > 1 ? channelByType(ChannelRight)->data() : 0;
+ float* destinationL = channelByType(ChannelLeft)->mutableData();
+ float* destinationR = numberOfDestinationChannels > 1 ? channelByType(ChannelRight)->mutableData() : 0;
const float DezipperRate = 0.005f;
int framesToProcess = length();
@@ -392,10 +398,10 @@ void AudioBus::processWithGainFromMonoStereo(const AudioBus &sourceBus, double*
}
// Save the target gain as the starting point for next time around.
- *lastMixGain = static_cast<double>(gain);
+ *lastMixGain = gain;
}
-void AudioBus::processWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain, bool sumToBus)
+void AudioBus::processWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus)
{
// Make sure we're summing from same type of bus.
// We *are* able to sum from mono -> stereo
@@ -437,23 +443,22 @@ void AudioBus::copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, f
for (unsigned channelIndex = 0; channelIndex < numberOfChannels(); ++channelIndex) {
if (sourceBus.numberOfChannels() == numberOfChannels())
source = sourceBus.channel(channelIndex)->data();
- float* destination = channel(channelIndex)->data();
+ float* destination = channel(channelIndex)->mutableData();
vmul(source, 1, gainValues, 1, destination, 1, numberOfGainValues);
}
}
-void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain)
+void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)
{
processWithGainFrom(sourceBus, lastMixGain, targetGain, false);
}
-void AudioBus::sumWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain)
+void AudioBus::sumWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)
{
processWithGainFrom(sourceBus, lastMixGain, targetGain, true);
}
-#if !PLATFORM(MAC)
-PassOwnPtr<AudioBus> AudioBus::createBySampleRateConverting(AudioBus* sourceBus, bool mixToMono, double newSampleRate)
+PassOwnPtr<AudioBus> AudioBus::createBySampleRateConverting(const AudioBus* sourceBus, bool mixToMono, double newSampleRate)
{
// sourceBus's sample-rate must be known.
ASSERT(sourceBus && sourceBus->sampleRate());
@@ -477,7 +482,7 @@ PassOwnPtr<AudioBus> AudioBus::createBySampleRateConverting(AudioBus* sourceBus,
}
// First, mix to mono (if necessary) then sample-rate convert.
- AudioBus* resamplerSourceBus;
+ const AudioBus* resamplerSourceBus;
OwnPtr<AudioBus> mixedMonoBus;
if (mixToMono) {
mixedMonoBus = AudioBus::createByMixingToMono(sourceBus);
@@ -498,8 +503,8 @@ PassOwnPtr<AudioBus> AudioBus::createBySampleRateConverting(AudioBus* sourceBus,
// Sample-rate convert each channel.
for (unsigned i = 0; i < numberOfDestinationChannels; ++i) {
- float* source = resamplerSourceBus->channel(i)->data();
- float* destination = destinationBus->channel(i)->data();
+ const float* source = resamplerSourceBus->channel(i)->data();
+ float* destination = destinationBus->channel(i)->mutableData();
SincResampler resampler(sampleRateRatio);
resampler.process(source, destination, sourceLength);
@@ -508,9 +513,8 @@ PassOwnPtr<AudioBus> AudioBus::createBySampleRateConverting(AudioBus* sourceBus,
destinationBus->setSampleRate(newSampleRate);
return destinationBus.release();
}
-#endif // !PLATFORM(MAC)
-PassOwnPtr<AudioBus> AudioBus::createByMixingToMono(AudioBus* sourceBus)
+PassOwnPtr<AudioBus> AudioBus::createByMixingToMono(const AudioBus* sourceBus)
{
switch (sourceBus->numberOfChannels()) {
case 1:
@@ -521,9 +525,9 @@ PassOwnPtr<AudioBus> AudioBus::createByMixingToMono(AudioBus* sourceBus)
unsigned n = sourceBus->length();
OwnPtr<AudioBus> destinationBus(adoptPtr(new AudioBus(1, n)));
- float* sourceL = sourceBus->channel(0)->data();
- float* sourceR = sourceBus->channel(1)->data();
- float* destination = destinationBus->channel(0)->data();
+ const float* sourceL = sourceBus->channel(0)->data();
+ const float* sourceR = sourceBus->channel(1)->data();
+ float* destination = destinationBus->channel(0)->mutableData();
// Do the mono mixdown.
for (unsigned i = 0; i < n; ++i)
diff --git a/Source/WebCore/platform/audio/AudioBus.h b/Source/WebCore/platform/audio/AudioBus.h
index 53fb4b969..b3da0f451 100644
--- a/Source/WebCore/platform/audio/AudioBus.h
+++ b/Source/WebCore/platform/audio/AudioBus.h
@@ -71,6 +71,7 @@ public:
AudioChannel* channel(unsigned channel) { return m_channels[channel].get(); }
const AudioChannel* channel(unsigned channel) const { return const_cast<AudioBus*>(this)->m_channels[channel].get(); }
AudioChannel* channelByType(unsigned type);
+ const AudioChannel* channelByType(unsigned type) const;
// Number of sample-frames
size_t length() const { return m_length; }
@@ -87,26 +88,24 @@ public:
// Creates a new buffer from a range in the source buffer.
// 0 may be returned if the range does not fit in the sourceBuffer
- static PassOwnPtr<AudioBus> createBufferFromRange(AudioBus* sourceBuffer, unsigned startFrame, unsigned endFrame);
+ static PassOwnPtr<AudioBus> createBufferFromRange(const AudioBus* sourceBuffer, unsigned startFrame, unsigned endFrame);
-#if !PLATFORM(MAC)
// Creates a new AudioBus by sample-rate converting sourceBus to the newSampleRate.
// setSampleRate() must have been previously called on sourceBus.
// Note: sample-rate conversion is already handled in the file-reading code for the mac port, so we don't need this.
- static PassOwnPtr<AudioBus> createBySampleRateConverting(AudioBus* sourceBus, bool mixToMono, double newSampleRate);
-#endif
+ static PassOwnPtr<AudioBus> createBySampleRateConverting(const AudioBus* sourceBus, bool mixToMono, double newSampleRate);
// Creates a new AudioBus by mixing all the channels down to mono.
// If sourceBus is already mono, then the returned AudioBus will simply be a copy.
- static PassOwnPtr<AudioBus> createByMixingToMono(AudioBus* sourceBus);
+ static PassOwnPtr<AudioBus> createByMixingToMono(const AudioBus* sourceBus);
// Scales all samples by the same amount.
- void scale(double scale);
+ void scale(float scale);
// Master gain for this bus - used with sumWithGainFrom() below
- void setGain(double gain) { m_busGain = gain; }
- double gain() { return m_busGain; }
+ void setGain(float gain) { m_busGain = gain; }
+ float gain() const { return m_busGain; }
void reset() { m_isFirstTime = true; } // for de-zippering
@@ -121,8 +120,8 @@ public:
// We scale by targetGain (and our own internal gain m_busGain), performing "de-zippering" to smoothly change from *lastMixGain to (targetGain*m_busGain).
// The caller is responsible for setting up lastMixGain to point to storage which is unique for every "stream" which will be summed to this bus.
// This represents the dezippering memory.
- void copyWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain);
- void sumWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain);
+ void copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain);
+ void sumWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain);
// Copies the sourceBus by scaling with sample-accurate gain values.
void copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, float* gainValues, unsigned numberOfGainValues);
@@ -138,8 +137,8 @@ public:
protected:
AudioBus() { };
- void processWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain, bool sumToBus);
- void processWithGainFromMonoStereo(const AudioBus &sourceBus, double* lastMixGain, double targetGain, bool sumToBus);
+ void processWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus);
+ void processWithGainFromMonoStereo(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus);
size_t m_length;
@@ -147,7 +146,7 @@ protected:
int m_layout;
- double m_busGain;
+ float m_busGain;
bool m_isFirstTime;
float m_sampleRate; // 0.0 if unknown or N/A
};
diff --git a/Source/WebCore/platform/audio/AudioChannel.cpp b/Source/WebCore/platform/audio/AudioChannel.cpp
index a962debd5..3c748e633 100644
--- a/Source/WebCore/platform/audio/AudioChannel.cpp
+++ b/Source/WebCore/platform/audio/AudioChannel.cpp
@@ -41,10 +41,9 @@ namespace WebCore {
using namespace VectorMath;
-void AudioChannel::scale(double scale)
+void AudioChannel::scale(float scale)
{
- float s = static_cast<float>(scale);
- vsmul(data(), 1, &s, data(), 1, length());
+ vsmul(data(), 1, &scale, mutableData(), 1, length());
}
void AudioChannel::copyFrom(const AudioChannel* sourceChannel)
@@ -54,7 +53,7 @@ void AudioChannel::copyFrom(const AudioChannel* sourceChannel)
if (!isSafe)
return;
- memcpy(data(), sourceChannel->data(), sizeof(float) * length());
+ memcpy(mutableData(), sourceChannel->data(), sizeof(float) * length());
}
void AudioChannel::copyFromRange(const AudioChannel* sourceChannel, unsigned startFrame, unsigned endFrame)
@@ -73,7 +72,7 @@ void AudioChannel::copyFromRange(const AudioChannel* sourceChannel, unsigned sta
return;
const float* source = sourceChannel->data();
- float* destination = data();
+ float* destination = mutableData();
memcpy(destination, source + startFrame, sizeof(float) * rangeLength);
}
@@ -84,17 +83,14 @@ void AudioChannel::sumFrom(const AudioChannel* sourceChannel)
if (!isSafe)
return;
- vadd(data(), 1, sourceChannel->data(), 1, data(), 1, length());
+ vadd(data(), 1, sourceChannel->data(), 1, mutableData(), 1, length());
}
float AudioChannel::maxAbsValue() const
{
- const float* p = data();
- int n = length();
-
float max = 0.0f;
- while (n--)
- max = std::max(max, fabsf(*p++));
+
+ vmaxmgv(data(), 1, &max, length());
return max;
}
diff --git a/Source/WebCore/platform/audio/AudioChannel.h b/Source/WebCore/platform/audio/AudioChannel.h
index 7325e9f38..24de3f9e8 100644
--- a/Source/WebCore/platform/audio/AudioChannel.h
+++ b/Source/WebCore/platform/audio/AudioChannel.h
@@ -73,7 +73,7 @@ public:
size_t length() const { return m_length; }
// Direct access to PCM sample data
- float* data() { return m_rawPointer ? m_rawPointer : m_memBuffer->data(); }
+ float* mutableData() { 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.
@@ -86,7 +86,7 @@ public:
}
// Scales all samples by the same amount.
- void scale(double scale);
+ void scale(float scale);
// A simple memcpy() from the source channel
void copyFrom(const AudioChannel* sourceChannel);
diff --git a/Source/WebCore/platform/audio/AudioDSPKernelProcessor.cpp b/Source/WebCore/platform/audio/AudioDSPKernelProcessor.cpp
index cf4d2d351..5f9139f03 100644
--- a/Source/WebCore/platform/audio/AudioDSPKernelProcessor.cpp
+++ b/Source/WebCore/platform/audio/AudioDSPKernelProcessor.cpp
@@ -71,7 +71,7 @@ void AudioDSPKernelProcessor::uninitialize()
m_initialized = false;
}
-void AudioDSPKernelProcessor::process(AudioBus* source, AudioBus* destination, size_t framesToProcess)
+void AudioDSPKernelProcessor::process(const AudioBus* source, AudioBus* destination, size_t framesToProcess)
{
ASSERT(source && destination);
if (!source || !destination)
@@ -88,7 +88,7 @@ void AudioDSPKernelProcessor::process(AudioBus* source, AudioBus* destination, s
return;
for (unsigned i = 0; i < m_kernels.size(); ++i)
- m_kernels[i]->process(source->channel(i)->data(), destination->channel(i)->data(), framesToProcess);
+ m_kernels[i]->process(source->channel(i)->data(), destination->channel(i)->mutableData(), framesToProcess);
}
// Resets filter state
diff --git a/Source/WebCore/platform/audio/AudioDSPKernelProcessor.h b/Source/WebCore/platform/audio/AudioDSPKernelProcessor.h
index 40b5ab8d6..7f8f81d2f 100644
--- a/Source/WebCore/platform/audio/AudioDSPKernelProcessor.h
+++ b/Source/WebCore/platform/audio/AudioDSPKernelProcessor.h
@@ -59,7 +59,7 @@ public:
// AudioProcessor methods
virtual void initialize();
virtual void uninitialize();
- virtual void process(AudioBus* source, AudioBus* destination, size_t framesToProcess);
+ virtual void process(const AudioBus* source, AudioBus* destination, size_t framesToProcess);
virtual void reset();
virtual void setNumberOfChannels(unsigned numberOfChannels);
diff --git a/Source/WebCore/platform/audio/AudioProcessor.h b/Source/WebCore/platform/audio/AudioProcessor.h
index 2d7b60a7c..469f83322 100644
--- a/Source/WebCore/platform/audio/AudioProcessor.h
+++ b/Source/WebCore/platform/audio/AudioProcessor.h
@@ -54,7 +54,7 @@ public:
virtual void uninitialize() = 0;
// Processes the source to destination bus. The number of channels must match in source and destination.
- virtual void process(AudioBus* source, AudioBus* destination, size_t framesToProcess) = 0;
+ virtual void process(const AudioBus* source, AudioBus* destination, size_t framesToProcess) = 0;
// Resets filter state
virtual void reset() = 0;
diff --git a/Source/WebCore/platform/audio/AudioResampler.cpp b/Source/WebCore/platform/audio/AudioResampler.cpp
index ba5b58e64..1a9f81e7a 100644
--- a/Source/WebCore/platform/audio/AudioResampler.cpp
+++ b/Source/WebCore/platform/audio/AudioResampler.cpp
@@ -103,7 +103,7 @@ void AudioResampler::process(AudioSourceProvider* provider, AudioBus* destinatio
// Now that we have the source data, resample each channel into the destination bus.
// FIXME: optimize for the common stereo case where it's faster to process both left/right channels in the same inner loop.
for (unsigned i = 0; i < numberOfChannels; ++i) {
- float* destination = destinationBus->channel(i)->data();
+ float* destination = destinationBus->channel(i)->mutableData();
m_kernels[i]->process(destination, framesToProcess);
}
}
diff --git a/Source/WebCore/platform/audio/AudioUtilities.cpp b/Source/WebCore/platform/audio/AudioUtilities.cpp
index 1a02b7e10..ff19cee69 100644
--- a/Source/WebCore/platform/audio/AudioUtilities.cpp
+++ b/Source/WebCore/platform/audio/AudioUtilities.cpp
@@ -55,7 +55,39 @@ float discreteTimeConstantForSampleRate(float timeConstant, float sampleRate)
// FIXME: replace hardcode 2.718282 with M_E until the correct MathExtras.h solution is determined.
return 1 - powf(1 / 2.718282f, 1 / (sampleRate * timeConstant));
}
-
+
+#if OS(WINDOWS) && COMPILER(MSVC) && !_M_IX86_FP
+// When compiling with MSVC with x87 FPU instructions using 80-bit
+// floats, we want very precise control over the arithmetic so that
+// rounding is done according to the IEEE 754 specification for
+// single- and double-precision floats. We want each operation to be
+// done with specified arithmetic precision and rounding consistent
+// with gcc, not extended to 80 bits automatically.
+//
+// These pragmas are equivalent to /fp:strict flag, but we only need
+// it for the function here. (Using fp:strict everywhere can have
+// severe impact on floating point performance.)
+#pragma float_control(push)
+#pragma float_control(precise, on)
+#pragma fenv_access(on)
+#pragma float_control(except, on)
+#endif
+
+size_t timeToSampleFrame(double time, double sampleRate)
+{
+ // DO NOT CONSOLIDATE THESE ASSIGNMENTS INTO ONE! When compiling
+ // with Visual Studio, these assignments force the rounding of
+ // each operation according to IEEE 754, instead of leaving
+ // intermediate results in 80-bit precision which is not
+ // consistent with IEEE 754 double-precision rounding.
+ double r = time * sampleRate;
+ r += 0.5;
+ return static_cast<size_t>(r);
+}
+#if OS(WINDOWS) && COMPILER(MSVC) && !_M_IX86_FP
+// Restore normal floating-point semantics.
+#pragma float_control(pop)
+#endif
} // AudioUtilites
} // WebCore
diff --git a/Source/WebCore/platform/audio/AudioUtilities.h b/Source/WebCore/platform/audio/AudioUtilities.h
index c98a4c8de..ed2945fb6 100644
--- a/Source/WebCore/platform/audio/AudioUtilities.h
+++ b/Source/WebCore/platform/audio/AudioUtilities.h
@@ -37,7 +37,9 @@ float decibelsToLinear(float);
// to reach the value 1 - 1/e (around 63.2%) given a step input response.
// discreteTimeConstantForSampleRate() will return the discrete time-constant for the specific sampleRate.
float discreteTimeConstantForSampleRate(float timeConstant, float sampleRate);
-
+
+// Convert the time to a sample frame at the given sample rate.
+size_t timeToSampleFrame(double time, double sampleRate);
} // AudioUtilites
} // WebCore
diff --git a/Source/WebCore/platform/audio/DynamicsCompressor.cpp b/Source/WebCore/platform/audio/DynamicsCompressor.cpp
index c4795f4f8..a55205705 100644
--- a/Source/WebCore/platform/audio/DynamicsCompressor.cpp
+++ b/Source/WebCore/platform/audio/DynamicsCompressor.cpp
@@ -115,10 +115,10 @@ void DynamicsCompressor::setEmphasisParameters(float gain, float anchorFreq, flo
setEmphasisStageParameters(3, gain, anchorFreq / (filterStageRatio * filterStageRatio * filterStageRatio));
}
-void DynamicsCompressor::process(AudioBus* sourceBus, AudioBus* destinationBus, unsigned framesToProcess)
+void DynamicsCompressor::process(const AudioBus* sourceBus, AudioBus* destinationBus, unsigned framesToProcess)
{
- float* sourceL = sourceBus->channel(0)->data();
- float* sourceR;
+ const float* sourceL = sourceBus->channel(0)->data();
+ const float* sourceR;
if (sourceBus->numberOfChannels() > 1)
sourceR = sourceBus->channel(1)->data();
@@ -127,8 +127,8 @@ void DynamicsCompressor::process(AudioBus* sourceBus, AudioBus* destinationBus,
ASSERT(destinationBus->numberOfChannels() == 2);
- float* destinationL = destinationBus->channel(0)->data();
- float* destinationR = destinationBus->channel(1)->data();
+ float* destinationL = destinationBus->channel(0)->mutableData();
+ float* destinationR = destinationBus->channel(1)->mutableData();
float filterStageGain = parameterValue(ParamFilterStageGain);
float filterStageRatio = parameterValue(ParamFilterStageRatio);
diff --git a/Source/WebCore/platform/audio/DynamicsCompressor.h b/Source/WebCore/platform/audio/DynamicsCompressor.h
index 21529512d..e0115ee27 100644
--- a/Source/WebCore/platform/audio/DynamicsCompressor.h
+++ b/Source/WebCore/platform/audio/DynamicsCompressor.h
@@ -64,7 +64,7 @@ public:
DynamicsCompressor(bool isStereo, float sampleRate);
- void process(AudioBus* sourceBus, AudioBus* destinationBus, unsigned framesToProcess);
+ void process(const AudioBus* sourceBus, AudioBus* destinationBus, unsigned framesToProcess);
void reset();
float parameterValue(unsigned parameterID);
diff --git a/Source/WebCore/platform/audio/DynamicsCompressorKernel.cpp b/Source/WebCore/platform/audio/DynamicsCompressorKernel.cpp
index e9f496a5b..a7a4c1212 100644
--- a/Source/WebCore/platform/audio/DynamicsCompressorKernel.cpp
+++ b/Source/WebCore/platform/audio/DynamicsCompressorKernel.cpp
@@ -82,9 +82,9 @@ void DynamicsCompressorKernel::setPreDelayTime(float preDelayTime)
}
}
-void DynamicsCompressorKernel::process(float* sourceL,
+void DynamicsCompressorKernel::process(const float* sourceL,
float* destinationL,
- float* sourceR, /* stereo-linked */
+ const float* sourceR, /* stereo-linked */
float* destinationR,
unsigned framesToProcess,
diff --git a/Source/WebCore/platform/audio/DynamicsCompressorKernel.h b/Source/WebCore/platform/audio/DynamicsCompressorKernel.h
index 8e5f7099d..cf319b378 100644
--- a/Source/WebCore/platform/audio/DynamicsCompressorKernel.h
+++ b/Source/WebCore/platform/audio/DynamicsCompressorKernel.h
@@ -38,9 +38,9 @@ public:
DynamicsCompressorKernel(float sampleRate);
// Performs stereo-linked compression.
- void process(float *sourceL,
+ void process(const float *sourceL,
float *destinationL,
- float *sourceR,
+ const float *sourceR,
float *destinationR,
unsigned framesToProcess,
diff --git a/Source/WebCore/platform/audio/EqualPowerPanner.cpp b/Source/WebCore/platform/audio/EqualPowerPanner.cpp
index 13a19d6cd..a2d2dff4c 100644
--- a/Source/WebCore/platform/audio/EqualPowerPanner.cpp
+++ b/Source/WebCore/platform/audio/EqualPowerPanner.cpp
@@ -49,7 +49,7 @@ EqualPowerPanner::EqualPowerPanner(float sampleRate)
m_smoothingConstant = AudioUtilities::discreteTimeConstantForSampleRate(SmoothingTimeConstant, sampleRate);
}
-void EqualPowerPanner::pan(double azimuth, double /*elevation*/, AudioBus* inputBus, AudioBus* outputBus, size_t framesToProcess)
+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();
@@ -62,10 +62,10 @@ void EqualPowerPanner::pan(double azimuth, double /*elevation*/, AudioBus* input
if (!isOutputSafe)
return;
- AudioChannel* channel = inputBus->channel(0);
- float* sourceP = channel->data();
- float* destinationL = outputBus->channelByType(AudioBus::ChannelLeft)->data();
- float* destinationR = outputBus->channelByType(AudioBus::ChannelRight)->data();
+ const AudioChannel* channel = inputBus->channel(0);
+ const float* sourceP = channel->data();
+ float* destinationL = outputBus->channelByType(AudioBus::ChannelLeft)->mutableData();
+ float* destinationR = outputBus->channelByType(AudioBus::ChannelRight)->mutableData();
if (!sourceP || !destinationL || !destinationR)
return;
@@ -84,8 +84,8 @@ void EqualPowerPanner::pan(double azimuth, double /*elevation*/, AudioBus* input
// Pan smoothly from left to right with azimuth going from -90 -> +90 degrees.
double desiredPanPosition = (azimuth + 90) / 180;
- double desiredGainL = 0.5 * cos(piDouble * desiredPanPosition) + 0.5;
- double desiredGainR = sqrt(1.0 - desiredGainL*desiredGainL);
+ double desiredGainL = cos(0.5 * piDouble * desiredPanPosition);
+ double desiredGainR = sin(0.5 * piDouble * desiredPanPosition);
// Don't de-zipper on first render call.
if (m_isFirstRender) {
diff --git a/Source/WebCore/platform/audio/EqualPowerPanner.h b/Source/WebCore/platform/audio/EqualPowerPanner.h
index 4f6001df9..016cd4aa1 100644
--- a/Source/WebCore/platform/audio/EqualPowerPanner.h
+++ b/Source/WebCore/platform/audio/EqualPowerPanner.h
@@ -35,7 +35,7 @@ class EqualPowerPanner : public Panner {
public:
EqualPowerPanner(float sampleRate);
- virtual void pan(double azimuth, double elevation, AudioBus* inputBus, AudioBus* outputBuf, size_t framesToProcess);
+ virtual void pan(double azimuth, double elevation, const AudioBus* inputBus, AudioBus* outputBuf, size_t framesToProcess);
virtual void reset() { m_isFirstRender = true; }
diff --git a/Source/WebCore/platform/audio/FFTConvolver.cpp b/Source/WebCore/platform/audio/FFTConvolver.cpp
index 909343380..2321de0cf 100644
--- a/Source/WebCore/platform/audio/FFTConvolver.cpp
+++ b/Source/WebCore/platform/audio/FFTConvolver.cpp
@@ -47,7 +47,7 @@ FFTConvolver::FFTConvolver(size_t fftSize)
{
}
-void FFTConvolver::process(FFTFrame* fftKernel, float* sourceP, float* destP, size_t framesToProcess)
+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
diff --git a/Source/WebCore/platform/audio/FFTConvolver.h b/Source/WebCore/platform/audio/FFTConvolver.h
index c1b500276..375bf2c65 100644
--- a/Source/WebCore/platform/audio/FFTConvolver.h
+++ b/Source/WebCore/platform/audio/FFTConvolver.h
@@ -46,7 +46,7 @@ public:
// The input to output latency is equal to fftSize / 2
//
// Processing in-place is allowed...
- void process(FFTFrame* fftKernel, float* sourceP, float* destP, size_t framesToProcess);
+ void process(FFTFrame* fftKernel, const float* sourceP, float* destP, size_t framesToProcess);
void reset();
diff --git a/Source/WebCore/platform/audio/FFTFrame.cpp b/Source/WebCore/platform/audio/FFTFrame.cpp
index fbb5dfe24..a1a0a50da 100644
--- a/Source/WebCore/platform/audio/FFTFrame.cpp
+++ b/Source/WebCore/platform/audio/FFTFrame.cpp
@@ -36,13 +36,14 @@
#include <stdio.h>
#endif
+#include "Logging.h"
#include <wtf/Complex.h>
#include <wtf/MathExtras.h>
#include <wtf/OwnPtr.h>
namespace WebCore {
-void FFTFrame::doPaddedFFT(float* data, size_t dataSize)
+void FFTFrame::doPaddedFFT(const float* data, size_t dataSize)
{
// Zero-pad the impulse response
AudioFloatArray paddedResponse(fftSize()); // zero-initialized
@@ -253,8 +254,8 @@ void FFTFrame::print()
FFTFrame& frame = *this;
float* realP = frame.realData();
float* imagP = frame.imagData();
- printf("**** \n");
- printf("DC = %f : nyquist = %f\n", realP[0], imagP[0]);
+ LOG(WebAudio, "**** \n");
+ LOG(WebAudio, "DC = %f : nyquist = %f\n", realP[0], imagP[0]);
int n = m_FFTSize / 2;
@@ -262,9 +263,9 @@ void FFTFrame::print()
double mag = sqrt(realP[i] * realP[i] + imagP[i] * imagP[i]);
double phase = atan2(realP[i], imagP[i]);
- printf("[%d] (%f %f)\n", i, mag, phase);
+ LOG(WebAudio, "[%d] (%f %f)\n", i, mag, phase);
}
- printf("****\n");
+ LOG(WebAudio, "****\n");
}
#endif // NDEBUG
diff --git a/Source/WebCore/platform/audio/FFTFrame.h b/Source/WebCore/platform/audio/FFTFrame.h
index b25d27956..db1d042ee 100644
--- a/Source/WebCore/platform/audio/FFTFrame.h
+++ b/Source/WebCore/platform/audio/FFTFrame.h
@@ -47,6 +47,13 @@
#include "mkl_dfti.h"
#endif // USE(WEBAUDIO_MKL)
+#if USE(WEBAUDIO_GSTREAMER)
+#include <glib.h>
+G_BEGIN_DECLS
+#include <gst/fft/gstfftf32.h>
+G_END_DECLS
+#endif // USE(WEBAUDIO_GSTREAMER)
+
#if USE(WEBAUDIO_FFMPEG)
struct RDFTContext;
#endif // USE(WEBAUDIO_FFMPEG)
@@ -73,7 +80,7 @@ public:
static void initialize();
static void cleanup();
- void doFFT(float* data);
+ void doFFT(const float* data);
void doInverseFFT(float* data);
void multiply(const FFTFrame& frame); // multiplies ourself with frame : effectively operator*=()
@@ -88,7 +95,7 @@ public:
// Interpolates from frame1 -> frame2 as x goes from 0.0 -> 1.0
static PassOwnPtr<FFTFrame> createInterpolatedFrame(const FFTFrame& frame1, const FFTFrame& frame2, double x);
- void doPaddedFFT(float* data, size_t dataSize); // zero-padding with dataSize <= fftSize
+ void doPaddedFFT(const float* data, size_t dataSize); // zero-padding with dataSize <= fftSize
double extractAverageGroupDelay();
void addConstantGroupDelay(double sampleFrameDelay);
@@ -146,6 +153,14 @@ private:
AudioFloatArray m_imagData;
#endif // USE(WEBAUDIO_FFMPEG)
+#if USE(WEBAUDIO_GSTREAMER)
+ GstFFTF32* m_fft;
+ GstFFTF32* m_inverseFft;
+ GstFFTF32Complex* m_complexData;
+ AudioFloatArray m_realData;
+ AudioFloatArray m_imagData;
+#endif // USE(WEBAUDIO_GSTREAMER)
+
#endif // !USE_ACCELERATE_FFT
};
diff --git a/Source/WebCore/platform/audio/FFTFrameStub.cpp b/Source/WebCore/platform/audio/FFTFrameStub.cpp
index dfc52a2ad..aa26ec605 100644
--- a/Source/WebCore/platform/audio/FFTFrameStub.cpp
+++ b/Source/WebCore/platform/audio/FFTFrameStub.cpp
@@ -29,7 +29,7 @@
#if ENABLE(WEB_AUDIO)
-#if !OS(DARWIN) && !USE(WEBAUDIO_MKL) && !USE(WEBAUDIO_FFMPEG)
+#if !OS(DARWIN) && !USE(WEBAUDIO_MKL) && !USE(WEBAUDIO_FFMPEG) && !USE(WEBAUDIO_GSTREAMER)
#include "FFTFrame.h"
@@ -102,6 +102,6 @@ float* FFTFrame::imagData() const
} // namespace WebCore
-#endif // !OS(DARWIN) && !USE(WEBAUDIO_MKL)
+#endif // !OS(DARWIN) && !USE(WEBAUDIO_MKL) && !USE(WEBAUDIO_GSTREAMER)
#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/platform/audio/HRTFElevation.cpp b/Source/WebCore/platform/audio/HRTFElevation.cpp
index e7de83a05..eb07d4ec9 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)
+#if PLATFORM(GTK) || PLATFORM(MAC)
#define USE_CONCATENATED_IMPULSE_RESPONSES
#endif
diff --git a/Source/WebCore/platform/audio/HRTFElevation.h b/Source/WebCore/platform/audio/HRTFElevation.h
index ccff097f8..446e66d0e 100644
--- a/Source/WebCore/platform/audio/HRTFElevation.h
+++ b/Source/WebCore/platform/audio/HRTFElevation.h
@@ -60,7 +60,7 @@ public:
HRTFKernelList* kernelListR() { return m_kernelListR.get(); }
double elevationAngle() const { return m_elevationAngle; }
- unsigned numberOfAzimuths() { return NumberOfTotalAzimuths; }
+ unsigned numberOfAzimuths() const { return NumberOfTotalAzimuths; }
float sampleRate() const { return m_sampleRate; }
// Returns the left and right kernels for the given azimuth index.
diff --git a/Source/WebCore/platform/audio/HRTFKernel.cpp b/Source/WebCore/platform/audio/HRTFKernel.cpp
index c44de932d..391f90402 100644
--- a/Source/WebCore/platform/audio/HRTFKernel.cpp
+++ b/Source/WebCore/platform/audio/HRTFKernel.cpp
@@ -50,7 +50,7 @@ static float extractAverageGroupDelay(AudioChannel* channel, size_t analysisFFTS
{
ASSERT(channel);
- float* impulseP = channel->data();
+ float* impulseP = channel->mutableData();
bool isSizeGood = channel->length() >= analysisFFTSize;
ASSERT(isSizeGood);
@@ -78,7 +78,7 @@ HRTFKernel::HRTFKernel(AudioChannel* channel, size_t fftSize, float sampleRate,
// Determine the leading delay (average group delay) for the response.
m_frameDelay = extractAverageGroupDelay(channel, fftSize / 2);
- float* impulseResponse = channel->data();
+ float* impulseResponse = channel->mutableData();
size_t responseLength = channel->length();
if (bassBoost) {
@@ -114,7 +114,7 @@ PassOwnPtr<AudioChannel> HRTFKernel::createImpulseResponse()
// Add leading delay back in.
fftFrame.addConstantGroupDelay(m_frameDelay);
- fftFrame.doInverseFFT(channel->data());
+ fftFrame.doInverseFFT(channel->mutableData());
return channel.release();
}
diff --git a/Source/WebCore/platform/audio/HRTFPanner.cpp b/Source/WebCore/platform/audio/HRTFPanner.cpp
index 978371cef..4c69932ed 100644
--- a/Source/WebCore/platform/audio/HRTFPanner.cpp
+++ b/Source/WebCore/platform/audio/HRTFPanner.cpp
@@ -37,23 +37,37 @@
#include <wtf/RefPtr.h>
using namespace std;
-
+
namespace WebCore {
// The value of 2 milliseconds is larger than the largest delay which exists in any HRTFKernel from the default HRTFDatabase (0.0136 seconds).
// We ASSERT the delay values used in process() with this value.
const double MaxDelayTimeSeconds = 0.002;
+const int UninitializedAzimuth = -1;
+const unsigned RenderingQuantum = 128;
+
HRTFPanner::HRTFPanner(float sampleRate)
: Panner(PanningModelHRTF)
, m_sampleRate(sampleRate)
- , m_isFirstRender(true)
- , m_azimuthIndex(0)
- , m_convolverL(fftSizeForSampleRate(sampleRate))
- , m_convolverR(fftSizeForSampleRate(sampleRate))
+ , m_crossfadeSelection(CrossfadeSelection1)
+ , m_azimuthIndex1(UninitializedAzimuth)
+ , m_elevation1(0)
+ , m_azimuthIndex2(UninitializedAzimuth)
+ , m_elevation2(0)
+ , m_crossfadeX(0)
+ , m_crossfadeIncr(0)
+ , m_convolverL1(fftSizeForSampleRate(sampleRate))
+ , m_convolverR1(fftSizeForSampleRate(sampleRate))
+ , m_convolverL2(fftSizeForSampleRate(sampleRate))
+ , m_convolverR2(fftSizeForSampleRate(sampleRate))
, m_delayLineL(MaxDelayTimeSeconds, sampleRate)
, m_delayLineR(MaxDelayTimeSeconds, sampleRate)
-{
+ , m_tempL1(RenderingQuantum)
+ , m_tempR1(RenderingQuantum)
+ , m_tempL2(RenderingQuantum)
+ , m_tempR2(RenderingQuantum)
+{
}
HRTFPanner::~HRTFPanner()
@@ -71,31 +85,24 @@ size_t HRTFPanner::fftSizeForSampleRate(float sampleRate)
void HRTFPanner::reset()
{
- m_isFirstRender = true;
- m_convolverL.reset();
- m_convolverR.reset();
+ m_convolverL1.reset();
+ m_convolverR1.reset();
+ m_convolverL2.reset();
+ m_convolverR2.reset();
m_delayLineL.reset();
m_delayLineR.reset();
}
-static bool wrapDistance(int i, int j, int length)
-{
- int directDistance = abs(i - j);
- int indirectDistance = length - directDistance;
-
- return indirectDistance < directDistance;
-}
-
int HRTFPanner::calculateDesiredAzimuthIndexAndBlend(double azimuth, double& azimuthBlend)
{
// Convert the azimuth angle from the range -180 -> +180 into the range 0 -> 360.
// The azimuth index may then be calculated from this positive value.
if (azimuth < 0)
azimuth += 360.0;
-
- HRTFDatabase* database = HRTFDatabaseLoader::defaultHRTFDatabase();
+
+ HRTFDatabase* database = HRTFDatabaseLoader::defaultHRTFDatabase();
ASSERT(database);
-
+
int numberOfAzimuths = database->numberOfAzimuths();
const double angleBetweenAzimuths = 360.0 / numberOfAzimuths;
@@ -103,7 +110,7 @@ int HRTFPanner::calculateDesiredAzimuthIndexAndBlend(double azimuth, double& azi
double desiredAzimuthIndexFloat = azimuth / angleBetweenAzimuths;
int desiredAzimuthIndex = static_cast<int>(desiredAzimuthIndexFloat);
azimuthBlend = desiredAzimuthIndexFloat - static_cast<double>(desiredAzimuthIndex);
-
+
// We don't immediately start using this azimuth index, but instead approach this index from the last index we rendered at.
// This minimizes the clicks and graininess for moving sources which occur otherwise.
desiredAzimuthIndex = max(0, desiredAzimuthIndex);
@@ -111,7 +118,7 @@ int HRTFPanner::calculateDesiredAzimuthIndexAndBlend(double azimuth, double& azi
return desiredAzimuthIndex;
}
-void HRTFPanner::pan(double desiredAzimuth, double elevation, AudioBus* inputBus, AudioBus* outputBus, size_t framesToProcess)
+void HRTFPanner::pan(double desiredAzimuth, double elevation, const AudioBus* inputBus, AudioBus* outputBus, size_t framesToProcess)
{
unsigned numInputChannels = inputBus ? inputBus->numberOfChannels() : 0;
@@ -128,7 +135,7 @@ void HRTFPanner::pan(double desiredAzimuth, double elevation, AudioBus* inputBus
}
// This code only runs as long as the context is alive and after database has been loaded.
- HRTFDatabase* database = HRTFDatabaseLoader::defaultHRTFDatabase();
+ HRTFDatabase* database = HRTFDatabaseLoader::defaultHRTFDatabase();
ASSERT(database);
if (!database) {
outputBus->zero();
@@ -147,68 +154,89 @@ void HRTFPanner::pan(double desiredAzimuth, double elevation, AudioBus* inputBus
// Normally, we'll just be dealing with mono sources.
// If we have a stereo input, implement stereo panning with left source processed by left HRTF, and right source by right HRTF.
- AudioChannel* inputChannelL = inputBus->channelByType(AudioBus::ChannelLeft);
- AudioChannel* inputChannelR = numInputChannels > 1 ? inputBus->channelByType(AudioBus::ChannelRight) : 0;
+ const AudioChannel* inputChannelL = inputBus->channelByType(AudioBus::ChannelLeft);
+ const AudioChannel* inputChannelR = numInputChannels > 1 ? inputBus->channelByType(AudioBus::ChannelRight) : 0;
// Get source and destination pointers.
- float* sourceL = inputChannelL->data();
- float* sourceR = numInputChannels > 1 ? inputChannelR->data() : sourceL;
- float* destinationL = outputBus->channelByType(AudioBus::ChannelLeft)->data();
- float* destinationR = outputBus->channelByType(AudioBus::ChannelRight)->data();
+ const float* sourceL = inputChannelL->data();
+ const float* sourceR = numInputChannels > 1 ? inputChannelR->data() : sourceL;
+ float* destinationL = outputBus->channelByType(AudioBus::ChannelLeft)->mutableData();
+ float* destinationR = outputBus->channelByType(AudioBus::ChannelRight)->mutableData();
double azimuthBlend;
int desiredAzimuthIndex = calculateDesiredAzimuthIndexAndBlend(azimuth, azimuthBlend);
- // This algorithm currently requires that we process in power-of-two size chunks at least 128.
+ // Initially snap azimuth and elevation values to first values encountered.
+ if (m_azimuthIndex1 == UninitializedAzimuth) {
+ m_azimuthIndex1 = desiredAzimuthIndex;
+ m_elevation1 = elevation;
+ }
+ if (m_azimuthIndex2 == UninitializedAzimuth) {
+ m_azimuthIndex2 = desiredAzimuthIndex;
+ m_elevation2 = elevation;
+ }
+
+ // Cross-fade / transition over a period of around 45 milliseconds.
+ // This is an empirical value tuned to be a reasonable trade-off between
+ // smoothness and speed.
+ const double fadeFrames = sampleRate() <= 48000 ? 2048 : 4096;
+
+ // Check for azimuth and elevation changes, initiating a cross-fade if needed.
+ if (!m_crossfadeX && m_crossfadeSelection == CrossfadeSelection1) {
+ if (desiredAzimuthIndex != m_azimuthIndex1 || elevation != m_elevation1) {
+ // Cross-fade from 1 -> 2
+ m_crossfadeIncr = 1 / fadeFrames;
+ m_azimuthIndex2 = desiredAzimuthIndex;
+ m_elevation2 = elevation;
+ }
+ }
+ if (m_crossfadeX == 1 && m_crossfadeSelection == CrossfadeSelection2) {
+ if (desiredAzimuthIndex != m_azimuthIndex2 || elevation != m_elevation2) {
+ // Cross-fade from 2 -> 1
+ m_crossfadeIncr = -1 / fadeFrames;
+ m_azimuthIndex1 = desiredAzimuthIndex;
+ m_elevation1 = elevation;
+ }
+ }
+
+ // This algorithm currently requires that we process in power-of-two size chunks at least RenderingQuantum.
ASSERT(1UL << static_cast<int>(log2(framesToProcess)) == framesToProcess);
- ASSERT(framesToProcess >= 128);
-
- const unsigned framesPerSegment = 128;
+ ASSERT(framesToProcess >= RenderingQuantum);
+
+ const unsigned framesPerSegment = RenderingQuantum;
const unsigned numberOfSegments = framesToProcess / framesPerSegment;
for (unsigned segment = 0; segment < numberOfSegments; ++segment) {
- if (m_isFirstRender) {
- // Snap exactly to desired position (first time and after reset()).
- m_azimuthIndex = desiredAzimuthIndex;
- m_isFirstRender = false;
- } else {
- // Each segment renders with an azimuth index closer by one to the desired azimuth index.
- // Because inter-aural time delay is mostly a factor of azimuth and the delay is where the clicks and graininess come from,
- // we don't bother smoothing the elevations.
- int numberOfAzimuths = database->numberOfAzimuths();
- bool wrap = wrapDistance(m_azimuthIndex, desiredAzimuthIndex, numberOfAzimuths);
- if (wrap) {
- if (m_azimuthIndex < desiredAzimuthIndex)
- m_azimuthIndex = (m_azimuthIndex - 1 + numberOfAzimuths) % numberOfAzimuths;
- else if (m_azimuthIndex > desiredAzimuthIndex)
- m_azimuthIndex = (m_azimuthIndex + 1) % numberOfAzimuths;
- } else {
- if (m_azimuthIndex < desiredAzimuthIndex)
- m_azimuthIndex = (m_azimuthIndex + 1) % numberOfAzimuths;
- else if (m_azimuthIndex > desiredAzimuthIndex)
- m_azimuthIndex = (m_azimuthIndex - 1 + numberOfAzimuths) % numberOfAzimuths;
- }
- }
-
- // Get the HRTFKernels and interpolated delays.
- HRTFKernel* kernelL;
- HRTFKernel* kernelR;
- double frameDelayL;
- double frameDelayR;
- database->getKernelsFromAzimuthElevation(azimuthBlend, m_azimuthIndex, elevation, kernelL, kernelR, frameDelayL, frameDelayR);
-
- ASSERT(kernelL && kernelR);
- if (!kernelL || !kernelR) {
+ // Get the HRTFKernels and interpolated delays.
+ HRTFKernel* kernelL1;
+ HRTFKernel* kernelR1;
+ HRTFKernel* kernelL2;
+ HRTFKernel* kernelR2;
+ double frameDelayL1;
+ double frameDelayR1;
+ double frameDelayL2;
+ double frameDelayR2;
+ database->getKernelsFromAzimuthElevation(azimuthBlend, m_azimuthIndex1, m_elevation1, kernelL1, kernelR1, frameDelayL1, frameDelayR1);
+ database->getKernelsFromAzimuthElevation(azimuthBlend, m_azimuthIndex2, m_elevation2, kernelL2, kernelR2, frameDelayL2, frameDelayR2);
+
+ bool areKernelsGood = kernelL1 && kernelR1 && kernelL2 && kernelR2;
+ ASSERT(areKernelsGood);
+ if (!areKernelsGood) {
outputBus->zero();
return;
}
-
- ASSERT(frameDelayL / sampleRate() < MaxDelayTimeSeconds && frameDelayR / sampleRate() < MaxDelayTimeSeconds);
-
+
+ ASSERT(frameDelayL1 / sampleRate() < MaxDelayTimeSeconds && frameDelayR1 / sampleRate() < MaxDelayTimeSeconds);
+ ASSERT(frameDelayL2 / sampleRate() < MaxDelayTimeSeconds && frameDelayR2 / sampleRate() < MaxDelayTimeSeconds);
+
+ // Crossfade inter-aural delays based on transitions.
+ double frameDelayL = (1 - m_crossfadeX) * frameDelayL1 + m_crossfadeX * frameDelayL2;
+ double frameDelayR = (1 - m_crossfadeX) * frameDelayR1 + m_crossfadeX * frameDelayR2;
+
// Calculate the source and destination pointers for the current segment.
unsigned offset = segment * framesPerSegment;
- float* segmentSourceL = sourceL + offset;
- float* segmentSourceR = sourceR + offset;
+ const float* segmentSourceL = sourceL + offset;
+ const float* segmentSourceR = sourceR + offset;
float* segmentDestinationL = destinationL + offset;
float* segmentDestinationR = destinationR + offset;
@@ -218,9 +246,51 @@ void HRTFPanner::pan(double desiredAzimuth, double elevation, AudioBus* inputBus
m_delayLineL.process(segmentSourceL, segmentDestinationL, framesPerSegment);
m_delayLineR.process(segmentSourceR, segmentDestinationR, framesPerSegment);
- // Now do the convolutions in-place.
- m_convolverL.process(kernelL->fftFrame(), segmentDestinationL, segmentDestinationL, framesPerSegment);
- m_convolverR.process(kernelR->fftFrame(), segmentDestinationR, segmentDestinationR, framesPerSegment);
+ bool needsCrossfading = m_crossfadeIncr;
+
+ // Have the convolvers render directly to the final destination if we're not cross-fading.
+ float* convolutionDestinationL1 = needsCrossfading ? m_tempL1.data() : segmentDestinationL;
+ float* convolutionDestinationR1 = needsCrossfading ? m_tempR1.data() : segmentDestinationR;
+ float* convolutionDestinationL2 = needsCrossfading ? m_tempL2.data() : segmentDestinationL;
+ float* convolutionDestinationR2 = needsCrossfading ? m_tempR2.data() : segmentDestinationR;
+
+ // Now do the convolutions.
+ // Note that we avoid doing convolutions on both sets of convolvers if we're not currently cross-fading.
+
+ if (m_crossfadeSelection == CrossfadeSelection1 || needsCrossfading) {
+ m_convolverL1.process(kernelL1->fftFrame(), segmentDestinationL, convolutionDestinationL1, framesPerSegment);
+ m_convolverR1.process(kernelR1->fftFrame(), segmentDestinationR, convolutionDestinationR1, framesPerSegment);
+ }
+
+ if (m_crossfadeSelection == CrossfadeSelection2 || needsCrossfading) {
+ m_convolverL2.process(kernelL2->fftFrame(), segmentDestinationL, convolutionDestinationL2, framesPerSegment);
+ m_convolverR2.process(kernelR2->fftFrame(), segmentDestinationR, convolutionDestinationR2, framesPerSegment);
+ }
+
+ if (needsCrossfading) {
+ // Apply linear cross-fade.
+ float x = m_crossfadeX;
+ float incr = m_crossfadeIncr;
+ for (unsigned i = 0; i < framesPerSegment; ++i) {
+ segmentDestinationL[i] = (1 - x) * convolutionDestinationL1[i] + x * convolutionDestinationL2[i];
+ segmentDestinationR[i] = (1 - x) * convolutionDestinationR1[i] + x * convolutionDestinationR2[i];
+ x += incr;
+ }
+ // Update cross-fade value from local.
+ m_crossfadeX = x;
+
+ if (m_crossfadeIncr > 0 && fabs(m_crossfadeX - 1) < m_crossfadeIncr) {
+ // We've fully made the crossfade transition from 1 -> 2.
+ m_crossfadeSelection = CrossfadeSelection2;
+ m_crossfadeX = 1;
+ m_crossfadeIncr = 0;
+ } else if (m_crossfadeIncr < 0 && fabs(m_crossfadeX) < -m_crossfadeIncr) {
+ // We've fully made the crossfade transition from 2 -> 1.
+ m_crossfadeSelection = CrossfadeSelection1;
+ m_crossfadeX = 0;
+ m_crossfadeIncr = 0;
+ }
+ }
}
}
diff --git a/Source/WebCore/platform/audio/HRTFPanner.h b/Source/WebCore/platform/audio/HRTFPanner.h
index e771ba28b..f5af1d152 100644
--- a/Source/WebCore/platform/audio/HRTFPanner.h
+++ b/Source/WebCore/platform/audio/HRTFPanner.h
@@ -37,30 +37,65 @@ public:
virtual ~HRTFPanner();
// Panner
- virtual void pan(double azimuth, double elevation, AudioBus* inputBus, AudioBus* outputBus, size_t framesToProcess);
+ 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); }
static size_t fftSizeForSampleRate(float sampleRate);
float sampleRate() const { return m_sampleRate; }
-
+
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.
int calculateDesiredAzimuthIndexAndBlend(double azimuth, double& azimuthBlend);
float m_sampleRate;
-
- // m_isFirstRender and m_azimuthIndex are used to avoid harshly changing from rendering at one azimuth angle to another angle very far away.
- // Changing the azimuth gradually produces a smoother sound.
- bool m_isFirstRender;
- int m_azimuthIndex;
-
- FFTConvolver m_convolverL;
- FFTConvolver m_convolverR;
+
+ // We maintain two sets of convolvers for smooth cross-faded interpolations when
+ // then azimuth and elevation are dynamically changing.
+ // When the azimuth and elevation are not changing, we simply process with one of the two sets.
+ // Initially we use CrossfadeSelection1 corresponding to m_convolverL1 and m_convolverR1.
+ // Whenever the azimuth or elevation changes, a crossfade is initiated to transition
+ // to the new position. So if we're currently processing with CrossfadeSelection1, then
+ // we transition to CrossfadeSelection2 (and vice versa).
+ // If we're in the middle of a transition, then we wait until it is complete before
+ // initiating a new transition.
+
+ // Selects either the convolver set (m_convolverL1, m_convolverR1) or (m_convolverL2, m_convolverR2).
+ enum CrossfadeSelection {
+ CrossfadeSelection1,
+ CrossfadeSelection2
+ };
+
+ CrossfadeSelection m_crossfadeSelection;
+
+ // azimuth/elevation for CrossfadeSelection1.
+ int m_azimuthIndex1;
+ double m_elevation1;
+
+ // azimuth/elevation for CrossfadeSelection2.
+ int m_azimuthIndex2;
+ double m_elevation2;
+
+ // A crossfade value 0 <= m_crossfadeX <= 1.
+ float m_crossfadeX;
+
+ // Per-sample-frame crossfade value increment.
+ float m_crossfadeIncr;
+
+ FFTConvolver m_convolverL1;
+ FFTConvolver m_convolverR1;
+ FFTConvolver m_convolverL2;
+ FFTConvolver m_convolverR2;
+
DelayDSPKernel m_delayLineL;
DelayDSPKernel m_delayLineR;
+
+ AudioFloatArray m_tempL1;
+ AudioFloatArray m_tempR1;
+ AudioFloatArray m_tempL2;
+ AudioFloatArray m_tempR2;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/audio/MultiChannelResampler.cpp b/Source/WebCore/platform/audio/MultiChannelResampler.cpp
index db51e90ed..f6c07e7c1 100644
--- a/Source/WebCore/platform/audio/MultiChannelResampler.cpp
+++ b/Source/WebCore/platform/audio/MultiChannelResampler.cpp
@@ -77,7 +77,7 @@ public:
// Copy the channel data from what we received from m_multiChannelProvider.
ASSERT(m_currentChannel <= m_numberOfChannels);
if (m_currentChannel < m_numberOfChannels) {
- memcpy(bus->channel(0)->data(), m_multiChannelBus->channel(m_currentChannel)->data(), sizeof(float) * framesToProcess);
+ memcpy(bus->channel(0)->mutableData(), m_multiChannelBus->channel(m_currentChannel)->data(), sizeof(float) * framesToProcess);
++m_currentChannel;
}
}
@@ -113,7 +113,7 @@ void MultiChannelResampler::process(AudioSourceProvider* provider, AudioBus* des
// However, if it calls provideInput() for the first channel, then it will call it for the remaining
// channels, since they all buffer in the same way and are processing the same number of frames.
m_kernels[channelIndex]->process(&channelProvider,
- destination->channel(channelIndex)->data(),
+ destination->channel(channelIndex)->mutableData(),
framesToProcess);
}
}
diff --git a/Source/WebCore/platform/audio/Panner.h b/Source/WebCore/platform/audio/Panner.h
index 4b728327d..d8b8dd0f1 100644
--- a/Source/WebCore/platform/audio/Panner.h
+++ b/Source/WebCore/platform/audio/Panner.h
@@ -53,7 +53,7 @@ public:
PanningModel panningModel() const { return m_panningModel; }
- virtual void pan(double azimuth, double elevation, AudioBus* inputBus, AudioBus* outputBus, size_t framesToProcess) = 0;
+ virtual void pan(double azimuth, double elevation, const AudioBus* inputBus, AudioBus* outputBus, size_t framesToProcess) = 0;
virtual void reset() = 0;
diff --git a/Source/WebCore/platform/audio/Reverb.cpp b/Source/WebCore/platform/audio/Reverb.cpp
index 2b787ebf3..122e21b68 100644
--- a/Source/WebCore/platform/audio/Reverb.cpp
+++ b/Source/WebCore/platform/audio/Reverb.cpp
@@ -35,6 +35,7 @@
#include "AudioBus.h"
#include "AudioFileReader.h"
#include "ReverbConvolver.h"
+#include "VectorMath.h"
#include <math.h>
#include <wtf/MathExtras.h>
#include <wtf/OwnPtr.h>
@@ -46,28 +47,26 @@ using namespace std;
namespace WebCore {
+using namespace VectorMath;
+
// Empirical gain calibration tested across many impulse responses to ensure perceived volume is same as dry (unprocessed) signal
-const double GainCalibration = -58.0;
+const float GainCalibration = -58;
// A minimum power value to when normalizing a silent (or very quiet) impulse response
-const double MinPower = 0.000125;
+const float MinPower = 0.000125f;
-static double calculateNormalizationScale(AudioBus* response)
+static float calculateNormalizationScale(AudioBus* response)
{
// Normalize by RMS power
size_t numberOfChannels = response->numberOfChannels();
size_t length = response->length();
- double power = 0.0;
+ float power = 0;
for (size_t i = 0; i < numberOfChannels; ++i) {
- int n = length;
- float* p = response->channel(i)->data();
-
- while (n--) {
- float sample = *p++;
- power += sample * sample;
- }
+ float channelPower = 0;
+ vsvesq(response->channel(i)->data(), 1, &channelPower, length);
+ power += channelPower;
}
power = sqrt(power / (numberOfChannels * length));
@@ -76,20 +75,20 @@ static double calculateNormalizationScale(AudioBus* response)
if (isinf(power) || isnan(power) || power < MinPower)
power = MinPower;
- double scale = 1.0 / power;
+ float scale = 1 / power;
- scale *= pow(10.0, GainCalibration * 0.05); // calibrate to make perceived volume same as unprocessed
+ scale *= powf(10, GainCalibration * 0.05f); // calibrate to make perceived volume same as unprocessed
// True-stereo compensation
if (response->numberOfChannels() == 4)
- scale *= 0.5;
+ scale *= 0.5f;
return scale;
}
Reverb::Reverb(AudioBus* impulseResponse, size_t renderSliceSize, size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads, bool normalize)
{
- double scale = 1;
+ float scale = 1;
if (normalize) {
scale = calculateNormalizationScale(impulseResponse);
@@ -104,7 +103,7 @@ Reverb::Reverb(AudioBus* impulseResponse, size_t renderSliceSize, size_t maxFFTS
// FIXME: What about roundoff? Perhaps consider making a temporary scaled copy
// instead of scaling and unscaling in place.
if (normalize && scale)
- impulseResponse->scale(1.0 / scale);
+ impulseResponse->scale(1 / scale);
}
void Reverb::initialize(AudioBus* impulseResponseBuffer, size_t renderSliceSize, size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads)
@@ -131,7 +130,7 @@ void Reverb::initialize(AudioBus* impulseResponseBuffer, size_t renderSliceSize,
m_tempBuffer = adoptPtr(new AudioBus(2, MaxFrameSize));
}
-void Reverb::process(AudioBus* sourceBus, AudioBus* destinationBus, size_t framesToProcess)
+void Reverb::process(const AudioBus* sourceBus, AudioBus* destinationBus, size_t framesToProcess)
{
// Do a fairly comprehensive sanity check.
// If these conditions are satisfied, all of the source and destination pointers will be valid for the various matrixing cases.
@@ -149,7 +148,7 @@ void Reverb::process(AudioBus* sourceBus, AudioBus* destinationBus, size_t frame
}
AudioChannel* destinationChannelL = destinationBus->channel(0);
- AudioChannel* sourceChannelL = sourceBus->channel(0);
+ const AudioChannel* sourceChannelL = sourceBus->channel(0);
// Handle input -> output matrixing...
size_t numInputChannels = sourceBus->numberOfChannels();
@@ -158,7 +157,7 @@ void Reverb::process(AudioBus* sourceBus, AudioBus* destinationBus, size_t frame
if (numInputChannels == 2 && numReverbChannels == 2 && numOutputChannels == 2) {
// 2 -> 2 -> 2
- AudioChannel* sourceChannelR = sourceBus->channel(1);
+ const AudioChannel* sourceChannelR = sourceBus->channel(1);
AudioChannel* destinationChannelR = destinationBus->channel(1);
m_convolvers[0]->process(sourceChannelL, destinationChannelL, framesToProcess);
m_convolvers[1]->process(sourceChannelR, destinationChannelR, framesToProcess);
@@ -178,13 +177,13 @@ void Reverb::process(AudioBus* sourceBus, AudioBus* destinationBus, size_t frame
ASSERT(isCopySafe);
if (!isCopySafe)
return;
- memcpy(destinationChannelR->data(), destinationChannelL->data(), sizeof(float) * framesToProcess);
+ memcpy(destinationChannelR->mutableData(), destinationChannelL->data(), sizeof(float) * framesToProcess);
} else if (numInputChannels == 1 && numReverbChannels == 1 && numOutputChannels == 1) {
// 1 -> 1 -> 1
m_convolvers[0]->process(sourceChannelL, destinationChannelL, framesToProcess);
} else if (numInputChannels == 2 && numReverbChannels == 4 && numOutputChannels == 2) {
// 2 -> 4 -> 2 ("True" stereo)
- AudioChannel* sourceChannelR = sourceBus->channel(1);
+ const AudioChannel* sourceChannelR = sourceBus->channel(1);
AudioChannel* destinationChannelR = destinationBus->channel(1);
AudioChannel* tempChannelL = m_tempBuffer->channel(0);
diff --git a/Source/WebCore/platform/audio/Reverb.h b/Source/WebCore/platform/audio/Reverb.h
index f162e0b70..779e7bba4 100644
--- a/Source/WebCore/platform/audio/Reverb.h
+++ b/Source/WebCore/platform/audio/Reverb.h
@@ -45,7 +45,7 @@ public:
// renderSliceSize is a rendering hint, so the FFTs can be optimized to not all occur at the same time (very bad when rendering on a real-time thread).
Reverb(AudioBus* impulseResponseBuffer, size_t renderSliceSize, size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads, bool normalize);
- void process(AudioBus* sourceBus, AudioBus* destinationBus, size_t framesToProcess);
+ void process(const AudioBus* sourceBus, AudioBus* destinationBus, size_t framesToProcess);
void reset();
unsigned impulseResponseLength() const { return m_impulseResponseLength; }
diff --git a/Source/WebCore/platform/audio/ReverbConvolver.cpp b/Source/WebCore/platform/audio/ReverbConvolver.cpp
index bbb55087f..c611414cb 100644
--- a/Source/WebCore/platform/audio/ReverbConvolver.cpp
+++ b/Source/WebCore/platform/audio/ReverbConvolver.cpp
@@ -82,7 +82,7 @@ ReverbConvolver::ReverbConvolver(AudioChannel* impulseResponse, size_t renderSli
// Otherwise, assume we're being run from a command-line tool.
bool hasRealtimeConstraint = useBackgroundThreads;
- float* response = impulseResponse->data();
+ 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
@@ -175,15 +175,15 @@ void ReverbConvolver::backgroundThreadEntry()
}
}
-void ReverbConvolver::process(AudioChannel* sourceChannel, AudioChannel* destinationChannel, size_t framesToProcess)
+void ReverbConvolver::process(const AudioChannel* sourceChannel, AudioChannel* destinationChannel, size_t framesToProcess)
{
bool isSafe = sourceChannel && destinationChannel && sourceChannel->length() >= framesToProcess && destinationChannel->length() >= framesToProcess;
ASSERT(isSafe);
if (!isSafe)
return;
- float* source = sourceChannel->data();
- float* destination = destinationChannel->data();
+ const float* source = sourceChannel->data();
+ float* destination = destinationChannel->mutableData();
bool isDataSafe = source && destination;
ASSERT(isDataSafe);
if (!isDataSafe)
diff --git a/Source/WebCore/platform/audio/ReverbConvolver.h b/Source/WebCore/platform/audio/ReverbConvolver.h
index 013b68497..370b87206 100644
--- a/Source/WebCore/platform/audio/ReverbConvolver.h
+++ b/Source/WebCore/platform/audio/ReverbConvolver.h
@@ -52,7 +52,7 @@ public:
ReverbConvolver(AudioChannel* impulseResponse, size_t renderSliceSize, size_t maxFFTSize, size_t convolverRenderPhase, bool useBackgroundThreads);
~ReverbConvolver();
- void process(AudioChannel* sourceChannel, AudioChannel* destinationChannel, size_t framesToProcess);
+ void process(const AudioChannel* sourceChannel, AudioChannel* destinationChannel, size_t framesToProcess);
void reset();
size_t impulseResponseLength() const { return m_impulseResponseLength; }
diff --git a/Source/WebCore/platform/audio/ReverbConvolverStage.cpp b/Source/WebCore/platform/audio/ReverbConvolverStage.cpp
index f207d19de..53bb65008 100644
--- a/Source/WebCore/platform/audio/ReverbConvolverStage.cpp
+++ b/Source/WebCore/platform/audio/ReverbConvolverStage.cpp
@@ -43,7 +43,7 @@ namespace WebCore {
using namespace VectorMath;
-ReverbConvolverStage::ReverbConvolverStage(float* impulseResponse, size_t responseLength, size_t reverbTotalLatency, size_t stageOffset, size_t stageLength,
+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)
@@ -88,7 +88,7 @@ void ReverbConvolverStage::processInBackground(ReverbConvolver* convolver, size_
process(source, framesToProcess);
}
-void ReverbConvolverStage::process(float* source, size_t framesToProcess)
+void ReverbConvolverStage::process(const float* source, size_t framesToProcess)
{
ASSERT(source);
if (!source)
@@ -96,7 +96,8 @@ void ReverbConvolverStage::process(float* source, size_t framesToProcess)
// Deal with pre-delay stream : note special handling of zero delay.
- float* preDelayedSource;
+ const float* preDelayedSource;
+ float* preDelayedDestination;
float* temporaryBuffer;
bool isTemporaryBufferSafe = false;
if (m_preDelayLength > 0) {
@@ -108,10 +109,12 @@ void ReverbConvolverStage::process(float* source, size_t framesToProcess)
isTemporaryBufferSafe = framesToProcess <= m_temporaryBuffer.size();
- preDelayedSource = m_preDelayBuffer.data() + m_preReadWriteIndex;
+ preDelayedDestination = m_preDelayBuffer.data() + m_preReadWriteIndex;
+ preDelayedSource = preDelayedDestination;
temporaryBuffer = m_temporaryBuffer.data();
} else {
// Zero delay
+ preDelayedDestination = 0;
preDelayedSource = source;
temporaryBuffer = m_preDelayBuffer.data();
@@ -138,7 +141,7 @@ void ReverbConvolverStage::process(float* source, size_t framesToProcess)
// Finally copy input to pre-delay.
if (m_preDelayLength > 0) {
- memcpy(preDelayedSource, source, sizeof(float) * framesToProcess);
+ memcpy(preDelayedDestination, source, sizeof(float) * framesToProcess);
m_preReadWriteIndex += framesToProcess;
ASSERT(m_preReadWriteIndex <= m_preDelayLength);
diff --git a/Source/WebCore/platform/audio/ReverbConvolverStage.h b/Source/WebCore/platform/audio/ReverbConvolverStage.h
index fc05a0e08..9811bc603 100644
--- a/Source/WebCore/platform/audio/ReverbConvolverStage.h
+++ b/Source/WebCore/platform/audio/ReverbConvolverStage.h
@@ -45,11 +45,11 @@ 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(float* impulseResponse, size_t responseLength, size_t reverbTotalLatency, size_t stageOffset, size_t stageLength,
+ 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);
// WARNING: framesToProcess must be such that it evenly divides the delay buffer size (stage_offset).
- void process(float* source, size_t framesToProcess);
+ void process(const float* source, size_t framesToProcess);
void processInBackground(ReverbConvolver* convolver, size_t framesToProcess);
diff --git a/Source/WebCore/platform/audio/ReverbInputBuffer.cpp b/Source/WebCore/platform/audio/ReverbInputBuffer.cpp
index f270f6faa..1be9af884 100644
--- a/Source/WebCore/platform/audio/ReverbInputBuffer.cpp
+++ b/Source/WebCore/platform/audio/ReverbInputBuffer.cpp
@@ -40,7 +40,7 @@ ReverbInputBuffer::ReverbInputBuffer(size_t length)
{
}
-void ReverbInputBuffer::write(float* sourceP, size_t numberOfFrames)
+void ReverbInputBuffer::write(const float* sourceP, size_t numberOfFrames)
{
size_t bufferLength = m_buffer.size();
bool isCopySafe = m_writeIndex + numberOfFrames <= bufferLength;
diff --git a/Source/WebCore/platform/audio/ReverbInputBuffer.h b/Source/WebCore/platform/audio/ReverbInputBuffer.h
index 15a281824..5036575b9 100644
--- a/Source/WebCore/platform/audio/ReverbInputBuffer.h
+++ b/Source/WebCore/platform/audio/ReverbInputBuffer.h
@@ -41,7 +41,7 @@ public:
// The realtime audio thread keeps writing samples here.
// The assumption is that the buffer's length is evenly divisible by numberOfFrames (for nearly all cases this will be fine).
// FIXME: remove numberOfFrames restriction...
- void write(float* sourceP, size_t numberOfFrames);
+ void write(const float* sourceP, size_t numberOfFrames);
// Background threads can call this to check if there's anything to read...
size_t writeIndex() const { return m_writeIndex; }
diff --git a/Source/WebCore/platform/audio/SincResampler.cpp b/Source/WebCore/platform/audio/SincResampler.cpp
index 0e4b84985..1ee692c7c 100644
--- a/Source/WebCore/platform/audio/SincResampler.cpp
+++ b/Source/WebCore/platform/audio/SincResampler.cpp
@@ -135,6 +135,8 @@ void SincResampler::consumeSource(float* buffer, unsigned numberOfSourceFrames)
// Wrap the provided buffer by an AudioBus for use by the source provider.
AudioBus bus(1, numberOfSourceFrames, false);
+
+ // FIXME: Find a way to make the following const-correct:
bus.setChannelMemory(0, buffer, numberOfSourceFrames);
m_sourceProvider->provideInput(&bus, numberOfSourceFrames);
@@ -146,7 +148,7 @@ namespace {
class BufferSourceProvider : public AudioSourceProvider {
public:
- BufferSourceProvider(float* source, size_t numberOfSourceFrames)
+ BufferSourceProvider(const float* source, size_t numberOfSourceFrames)
: m_source(source)
, m_sourceFramesAvailable(numberOfSourceFrames)
{
@@ -159,7 +161,7 @@ public:
if (!m_source || !bus)
return;
- float* buffer = bus->channel(0)->data();
+ float* buffer = bus->channel(0)->mutableData();
// Clamp to number of frames available and zero-pad.
size_t framesToCopy = min(m_sourceFramesAvailable, framesToProcess);
@@ -174,13 +176,13 @@ public:
}
private:
- float* m_source;
+ const float* m_source;
size_t m_sourceFramesAvailable;
};
} // namespace
-void SincResampler::process(float* source, float* destination, unsigned numberOfSourceFrames)
+void SincResampler::process(const float* source, float* destination, unsigned numberOfSourceFrames)
{
// Resample an in-memory buffer using an AudioSourceProvider.
BufferSourceProvider sourceProvider(source, numberOfSourceFrames);
diff --git a/Source/WebCore/platform/audio/SincResampler.h b/Source/WebCore/platform/audio/SincResampler.h
index bbe0c558c..04dbf3fa1 100644
--- a/Source/WebCore/platform/audio/SincResampler.h
+++ b/Source/WebCore/platform/audio/SincResampler.h
@@ -44,7 +44,7 @@ public:
SincResampler(double scaleFactor, unsigned kernelSize = 32, unsigned numberOfKernelOffsets = 32);
// Processes numberOfSourceFrames from source to produce numberOfSourceFrames / scaleFactor frames in destination.
- void process(float* source, float* destination, unsigned numberOfSourceFrames);
+ void process(const float* source, float* destination, unsigned numberOfSourceFrames);
// Process with input source callback function for streaming applications.
void process(AudioSourceProvider*, float* destination, size_t framesToProcess);
@@ -71,7 +71,7 @@ protected:
// Source is copied into this buffer for each processing pass.
AudioFloatArray m_inputBuffer;
- float* m_source;
+ const float* m_source;
unsigned m_sourceFramesAvailable;
// m_sourceProvider is used to provide the audio input stream to the resampler.
diff --git a/Source/WebCore/platform/audio/VectorMath.cpp b/Source/WebCore/platform/audio/VectorMath.cpp
index 71e101470..572dbf353 100644
--- a/Source/WebCore/platform/audio/VectorMath.cpp
+++ b/Source/WebCore/platform/audio/VectorMath.cpp
@@ -36,6 +36,9 @@
#include <emmintrin.h>
#endif
+#include <algorithm>
+#include <math.h>
+
namespace WebCore {
namespace VectorMath {
@@ -90,8 +93,77 @@ void zvmul(const float* real1P, const float* imag1P, const float* real2P, const
#endif
}
+void vsma(const float* sourceP, int sourceStride, const float* scale, float* destP, int destStride, size_t framesToProcess)
+{
+ vDSP_vsma(sourceP, sourceStride, scale, destP, destStride, destP, destStride, framesToProcess);
+}
+
+void vmaxmgv(const float* sourceP, int sourceStride, float* maxP, size_t framesToProcess)
+{
+ vDSP_maxmgv(sourceP, sourceStride, maxP, framesToProcess);
+}
+
+void vsvesq(const float* sourceP, int sourceStride, float* sumP, size_t framesToProcess)
+{
+ vDSP_svesq(const_cast<float*>(sourceP), sourceStride, sumP, framesToProcess);
+}
#else
+void vsma(const float* sourceP, int sourceStride, const float* scale, float* destP, int destStride, size_t framesToProcess)
+{
+ int n = framesToProcess;
+
+#ifdef __SSE2__
+ if ((sourceStride == 1) && (destStride == 1)) {
+ float k = *scale;
+
+ // If the sourceP address is not 16-byte aligned, the first several frames (at most three) should be processed seperately.
+ while ((reinterpret_cast<uintptr_t>(sourceP) & 0x0F) && n) {
+ *destP += k * *sourceP;
+ sourceP++;
+ destP++;
+ n--;
+ }
+
+ // Now the sourceP address aligned and start to apply SSE.
+ int tailFrames = n % 4;
+ float* endP = destP + n - tailFrames;
+
+ __m128 pSource;
+ __m128 dest;
+ __m128 temp;
+ __m128 mScale = _mm_set_ps1(k);
+
+ bool destAligned = !(reinterpret_cast<uintptr_t>(destP) & 0x0F);
+
+#define SSE2_MULT_ADD(loadInstr, storeInstr) \
+ while (destP < endP) \
+ { \
+ pSource = _mm_load_ps(sourceP); \
+ temp = _mm_mul_ps(pSource, mScale); \
+ dest = _mm_##loadInstr##_ps(destP); \
+ dest = _mm_add_ps(dest, temp); \
+ _mm_##storeInstr##_ps(destP, dest); \
+ sourceP += 4; \
+ destP += 4; \
+ }
+
+ if (destAligned)
+ SSE2_MULT_ADD(load, store)
+ else
+ SSE2_MULT_ADD(loadu, storeu)
+
+ n = tailFrames;
+ }
+#endif
+ while (n) {
+ *destP += *sourceP * *scale;
+ sourceP += sourceStride;
+ destP += destStride;
+ n--;
+ }
+}
+
void vsmul(const float* sourceP, int sourceStride, const float* scale, float* destP, int destStride, size_t framesToProcess)
{
#ifdef __SSE2__
@@ -351,6 +423,34 @@ void zvmul(const float* real1P, const float* imag1P, const float* real2P, const
}
}
+void vsvesq(const float* sourceP, int sourceStride, float* sumP, size_t framesToProcess)
+{
+ // FIXME: optimize for SSE
+ int n = framesToProcess;
+ float sum = 0;
+ while (n--) {
+ float sample = *sourceP;
+ sum += sample * sample;
+ sourceP += sourceStride;
+ }
+
+ ASSERT(sumP);
+ *sumP = sum;
+}
+
+void vmaxmgv(const float* sourceP, int sourceStride, float* maxP, size_t framesToProcess)
+{
+ // FIXME: optimize for SSE
+ int n = framesToProcess;
+ float max = 0;
+ while (n--) {
+ max = std::max(max, fabsf(*sourceP));
+ sourceP += sourceStride;
+ }
+
+ ASSERT(maxP);
+ *maxP = max;
+}
#endif // OS(DARWIN)
} // namespace VectorMath
diff --git a/Source/WebCore/platform/audio/VectorMath.h b/Source/WebCore/platform/audio/VectorMath.h
index 5ae80dab9..702251920 100644
--- a/Source/WebCore/platform/audio/VectorMath.h
+++ b/Source/WebCore/platform/audio/VectorMath.h
@@ -31,9 +31,18 @@ namespace WebCore {
namespace VectorMath {
+// Vector scalar multiply and then add.
+void vsma(const float* sourceP, int sourceStride, const float* scale, float* destP, int destStride, size_t framesToProcess);
+
void vsmul(const float* sourceP, int sourceStride, const float* scale, float* destP, int destStride, size_t framesToProcess);
void vadd(const float* source1P, int sourceStride1, const float* source2P, int sourceStride2, float* destP, int destStride, size_t framesToProcess);
+// Finds the maximum magnitude of a float vector.
+void vmaxmgv(const float* sourceP, int sourceStride, float* maxP, size_t framesToProcess);
+
+// Sums the squares of a float vector's elements.
+void vsvesq(const float* sourceP, int sourceStride, float* sumP, size_t framesToProcess);
+
// For an element-by-element multiply of two float vectors.
void vmul(const float* source1P, int sourceStride1, const float* source2P, int sourceStride2, float* destP, int destStride, size_t framesToProcess);
diff --git a/Source/WebCore/platform/audio/ZeroPole.cpp b/Source/WebCore/platform/audio/ZeroPole.cpp
index 2fa44003a..9e6f1b635 100644
--- a/Source/WebCore/platform/audio/ZeroPole.cpp
+++ b/Source/WebCore/platform/audio/ZeroPole.cpp
@@ -36,7 +36,7 @@
namespace WebCore {
-void ZeroPole::process(float *source, float *destination, unsigned framesToProcess)
+void ZeroPole::process(const float *source, float *destination, unsigned framesToProcess)
{
float zero = m_zero;
float pole = m_pole;
diff --git a/Source/WebCore/platform/audio/ZeroPole.h b/Source/WebCore/platform/audio/ZeroPole.h
index 93fd0d6f9..4cb1d1745 100644
--- a/Source/WebCore/platform/audio/ZeroPole.h
+++ b/Source/WebCore/platform/audio/ZeroPole.h
@@ -43,7 +43,7 @@ public:
{
}
- void process(float *source, float *destination, unsigned framesToProcess);
+ void process(const float *source, float *destination, unsigned framesToProcess);
// Reset filter state.
void reset() { m_lastX = 0; m_lastY = 0; }
diff --git a/Source/WebCore/platform/audio/ffmpeg/FFTFrameFFMPEG.cpp b/Source/WebCore/platform/audio/ffmpeg/FFTFrameFFMPEG.cpp
index 9f8932445..d4624a70b 100644
--- a/Source/WebCore/platform/audio/ffmpeg/FFTFrameFFMPEG.cpp
+++ b/Source/WebCore/platform/audio/ffmpeg/FFTFrameFFMPEG.cpp
@@ -135,7 +135,7 @@ void FFTFrame::multiply(const FFTFrame& frame)
VectorMath::vsmul(imagP1, 1, &scale, imagP1, 1, halfSize);
}
-void FFTFrame::doFFT(float* data)
+void FFTFrame::doFFT(const float* data)
{
// Copy since processing is in-place.
float* p = m_complexData.data();
diff --git a/Source/WebCore/platform/audio/gstreamer/AudioFileReaderGStreamer.cpp b/Source/WebCore/platform/audio/gstreamer/AudioFileReaderGStreamer.cpp
index 20e81b9c0..093f81fa8 100644
--- a/Source/WebCore/platform/audio/gstreamer/AudioFileReaderGStreamer.cpp
+++ b/Source/WebCore/platform/audio/gstreamer/AudioFileReaderGStreamer.cpp
@@ -80,7 +80,7 @@ static void copyGstreamerBuffersToAudioChannel(GstBufferList* buffers, AudioChan
gst_buffer_list_iterator_next_group(iter);
GstBuffer* buffer = gst_buffer_list_iterator_merge_group(iter);
if (buffer) {
- memcpy(audioChannel->data(), reinterpret_cast<float*>(GST_BUFFER_DATA(buffer)), GST_BUFFER_SIZE(buffer));
+ memcpy(audioChannel->mutableData(), reinterpret_cast<float*>(GST_BUFFER_DATA(buffer)), GST_BUFFER_SIZE(buffer));
gst_buffer_unref(buffer);
}
diff --git a/Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp b/Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp
index 5183e3403..2cae4acab 100644
--- a/Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp
+++ b/Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp
@@ -333,7 +333,7 @@ static void webKitWebAudioSrcLoop(WebKitWebAudioSrc* src)
ASSERT(buffer);
ASSERT(!GST_BUFFER_MALLOCDATA(buffer));
- GST_BUFFER_DATA(buffer) = reinterpret_cast<guint8*>(priv->bus->channel(index)->data());
+ GST_BUFFER_DATA(buffer) = reinterpret_cast<guint8*>(const_cast<float*>(priv->bus->channel(index)->data()));
GST_BUFFER_SIZE(buffer) = bufferSize;
GST_BUFFER_OFFSET(buffer) = priv->currentBufferOffset;
GST_BUFFER_OFFSET_END(buffer) = priv->currentBufferOffset + priv->framesToPull;
diff --git a/Source/WebCore/platform/audio/mac/AudioBusMac.mm b/Source/WebCore/platform/audio/mac/AudioBusMac.mm
index 42a718b21..f2d3676e5 100644
--- a/Source/WebCore/platform/audio/mac/AudioBusMac.mm
+++ b/Source/WebCore/platform/audio/mac/AudioBusMac.mm
@@ -47,8 +47,13 @@ PassOwnPtr<AudioBus> AudioBus::loadPlatformResource(const char* name, float samp
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSBundle *bundle = [NSBundle bundleForClass:[WebCoreAudioBundleClass class]];
- NSString *audioFilePath = [bundle pathForResource:[NSString stringWithUTF8String:name] ofType:@"wav" inDirectory:@"audio"];
- NSData *audioData = [NSData dataWithContentsOfFile:audioFilePath];
+ NSURL *audioFileURL = [bundle URLForResource:[NSString stringWithUTF8String:name] withExtension:@"wav" subdirectory:@"audio"];
+#if defined(BUILDING_ON_SNOW_LEOPARD)
+ NSDataReadingOptions options = NSDataReadingMapped;
+#else
+ NSDataReadingOptions options = NSDataReadingMappedIfSafe;
+#endif
+ NSData *audioData = [NSData dataWithContentsOfURL:audioFileURL options:options error:nil];
if (audioData) {
OwnPtr<AudioBus> bus(createBusFromInMemoryAudioFile([audioData bytes], [audioData length], false, sampleRate));
diff --git a/Source/WebCore/platform/audio/mac/AudioFileReaderMac.cpp b/Source/WebCore/platform/audio/mac/AudioFileReaderMac.cpp
index 95502636b..d0ecf1a31 100644
--- a/Source/WebCore/platform/audio/mac/AudioFileReaderMac.cpp
+++ b/Source/WebCore/platform/audio/mac/AudioFileReaderMac.cpp
@@ -212,7 +212,7 @@ PassOwnPtr<AudioBus> AudioFileReader::createBus(float sampleRate, bool mixToMono
for (size_t i = 0; i < numberOfChannels; ++i) {
bufferList->mBuffers[i].mNumberChannels = 1;
bufferList->mBuffers[i].mDataByteSize = numberOfFrames * sizeof(float);
- bufferList->mBuffers[i].mData = audioBus->channel(i)->data();
+ bufferList->mBuffers[i].mData = audioBus->channel(i)->mutableData();
}
}
@@ -224,7 +224,7 @@ PassOwnPtr<AudioBus> AudioFileReader::createBus(float sampleRate, bool mixToMono
if (mixToMono && numberOfChannels == 2) {
// Mix stereo down to mono
- float* destL = audioBus->channel(0)->data();
+ float* destL = audioBus->channel(0)->mutableData();
for (size_t i = 0; i < numberOfFrames; i++)
destL[i] = 0.5f * (bufferL[i] + bufferR[i]);
}
diff --git a/Source/WebCore/platform/audio/mac/FFTFrameMac.cpp b/Source/WebCore/platform/audio/mac/FFTFrameMac.cpp
index 6dfbbeccb..8cef928d4 100644
--- a/Source/WebCore/platform/audio/mac/FFTFrameMac.cpp
+++ b/Source/WebCore/platform/audio/mac/FFTFrameMac.cpp
@@ -127,7 +127,7 @@ void FFTFrame::multiply(const FFTFrame& frame)
VectorMath::vsmul(imagP1, 1, &scale, imagP1, 1, halfSize);
}
-void FFTFrame::doFFT(float* data)
+void FFTFrame::doFFT(const float* data)
{
vDSP_ctoz((DSPComplex*)data, 2, &m_frame, 1, m_FFTSize / 2);
vDSP_fft_zrip(m_FFTSetup, &m_frame, 1, m_log2FFTSize, FFT_FORWARD);
diff --git a/Source/WebCore/platform/audio/mkl/FFTFrameMKL.cpp b/Source/WebCore/platform/audio/mkl/FFTFrameMKL.cpp
index 6bf2c1e20..0f3a2827f 100644
--- a/Source/WebCore/platform/audio/mkl/FFTFrameMKL.cpp
+++ b/Source/WebCore/platform/audio/mkl/FFTFrameMKL.cpp
@@ -170,7 +170,7 @@ void FFTFrame::multiply(const FFTFrame& frame)
}
}
-void FFTFrame::doFFT(float* data)
+void FFTFrame::doFFT(const float* data)
{
// Compute Forward transform.
MKL_LONG status = DftiComputeForward(m_handle, data, m_complexData.data());
diff --git a/Source/WebCore/platform/audio/resources/Composite.wav b/Source/WebCore/platform/audio/resources/Composite.wav
index 617dd2ae2..25fc82314 100644
--- a/Source/WebCore/platform/audio/resources/Composite.wav
+++ b/Source/WebCore/platform/audio/resources/Composite.wav
Binary files differ
diff --git a/Source/WebCore/platform/blackberry/LocalizedStringsBlackBerry.cpp b/Source/WebCore/platform/blackberry/LocalizedStringsBlackBerry.cpp
index b7f369ba4..a93e38109 100644
--- a/Source/WebCore/platform/blackberry/LocalizedStringsBlackBerry.cpp
+++ b/Source/WebCore/platform/blackberry/LocalizedStringsBlackBerry.cpp
@@ -23,6 +23,7 @@
#include "NotImplemented.h"
#include <BlackBerryPlatformClient.h>
#include <LocalizeResource.h>
+#include <wtf/Vector.h>
namespace WebCore {
@@ -59,7 +60,7 @@ String inputElementAltText()
return String();
}
-String platformDefaultLanguage()
+static String platformLanguage()
{
String lang = BlackBerry::Platform::Client::get()->getLocale().c_str();
// getLocale() returns a POSIX locale which uses '_' to separate language and country.
@@ -71,6 +72,13 @@ String platformDefaultLanguage()
return lang;
}
+Vector<String> platformUserPreferredLanguages()
+{
+ Vector<String> userPreferredLanguages;
+ userPreferredLanguages.append(platformLanguage());
+ return userPreferredLanguages;
+}
+
#if ENABLE(CONTEXT_MENUS)
String contextMenuItemTagBold()
{
diff --git a/Source/WebCore/platform/blackberry/LoggingBlackBerry.cpp b/Source/WebCore/platform/blackberry/LoggingBlackBerry.cpp
index ea535f897..994d78ec9 100644
--- a/Source/WebCore/platform/blackberry/LoggingBlackBerry.cpp
+++ b/Source/WebCore/platform/blackberry/LoggingBlackBerry.cpp
@@ -19,6 +19,8 @@
#include "config.h"
#include "Logging.h"
+#include <wtf/text/WTFString.h>
+
namespace WebCore {
static inline void initializeWithUserDefault(WTFLogChannel& channel, bool enabled)
@@ -36,30 +38,18 @@ void initializeLoggingChannelsIfNecessary()
return;
haveInitializedLoggingChannels = true;
- initializeWithUserDefault(LogNotYetImplemented, true);
- initializeWithUserDefault(LogFrames, true);
- initializeWithUserDefault(LogLoading, true);
- initializeWithUserDefault(LogPopupBlocking, true);
- initializeWithUserDefault(LogEvents, true);
- initializeWithUserDefault(LogEditing, true);
- initializeWithUserDefault(LogLiveConnect, true);
- initializeWithUserDefault(LogIconDatabase, false);
- initializeWithUserDefault(LogSQLDatabase, false);
- initializeWithUserDefault(LogSpellingAndGrammar, true);
- initializeWithUserDefault(LogBackForward, true);
- initializeWithUserDefault(LogHistory, true);
- initializeWithUserDefault(LogPageCache, true);
- initializeWithUserDefault(LogPlatformLeaks, true);
- initializeWithUserDefault(LogNetwork, true);
- initializeWithUserDefault(LogFTP, true);
- initializeWithUserDefault(LogThreading, true);
- initializeWithUserDefault(LogStorageAPI, true);
- initializeWithUserDefault(LogMedia, true);
- initializeWithUserDefault(LogPlugins, true);
- initializeWithUserDefault(LogArchives, true);
- initializeWithUserDefault(LogProgress, false);
- initializeWithUserDefault(LogResourceLoading, false);
- initializeWithUserDefault(LogFileAPI, true);
+ String logEnv = getenv("WEBKIT_DEBUG");
+ if (logEnv.isEmpty())
+ return;
+
+ Vector<String> logv;
+ logEnv.split(" ", logv);
+
+ Vector<String>::const_iterator it = logv.begin();
+ for (; it != logv.end(); ++it) {
+ if (WTFLogChannel* channel = getChannelFromName(*it))
+ channel->state = WTFLogChannelOn;
+ }
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/blackberry/PlatformKeyboardEventBlackBerry.cpp b/Source/WebCore/platform/blackberry/PlatformKeyboardEventBlackBerry.cpp
index b8fc1ee65..607126b7d 100644
--- a/Source/WebCore/platform/blackberry/PlatformKeyboardEventBlackBerry.cpp
+++ b/Source/WebCore/platform/blackberry/PlatformKeyboardEventBlackBerry.cpp
@@ -73,10 +73,10 @@ static String keyIdentifierForBlackBerryCharacter(unsigned short character)
return "Insert";
case KEYCODE_PG_UP:
case KEYCODE_KP_PG_UP:
- return "PageDown";
+ return "PageUp";
case KEYCODE_PG_DOWN:
case KEYCODE_KP_PG_DOWN:
- return "PageUp";
+ return "PageDown";
case KEYCODE_END:
case KEYCODE_KP_END:
return "End";
@@ -299,10 +299,10 @@ static int windowsKeyCodeForBlackBerryCharacter(unsigned short character)
return VK_INSERT;
case KEYCODE_PG_UP:
case KEYCODE_KP_PG_UP:
- return VK_NEXT;
+ return VK_PRIOR;
case KEYCODE_PG_DOWN:
case KEYCODE_KP_PG_DOWN:
- return VK_PRIOR;
+ return VK_NEXT;
case KEYCODE_END:
case KEYCODE_KP_END:
return VK_END;
diff --git a/Source/WebCore/platform/blackberry/PlatformScreenBlackBerry.cpp b/Source/WebCore/platform/blackberry/PlatformScreenBlackBerry.cpp
index d26e55664..b2829c4e9 100644
--- a/Source/WebCore/platform/blackberry/PlatformScreenBlackBerry.cpp
+++ b/Source/WebCore/platform/blackberry/PlatformScreenBlackBerry.cpp
@@ -20,6 +20,7 @@
#include "PlatformScreen.h"
#include "FloatRect.h"
+#include "FrameView.h"
#include "Widget.h"
#include <BlackBerryPlatformScreen.h>
@@ -41,12 +42,12 @@ int screenDepth(Widget*)
return 24;
}
-FloatRect screenAvailableRect(Widget* widget)
+FloatRect screenAvailableRect(FrameView* frameView)
{
return FloatRect(FloatPoint(), FloatSize(IntSize(BlackBerry::Platform::Graphics::Screen::size())));
}
-FloatRect screenRect(Widget* widget)
+FloatRect screenRect(FrameView* frameView)
{
return FloatRect(FloatPoint(), FloatSize(IntSize(BlackBerry::Platform::Graphics::Screen::size())));
}
diff --git a/Source/WebCore/platform/cf/KURLCFNet.cpp b/Source/WebCore/platform/cf/KURLCFNet.cpp
index d79123720..b3a58652b 100644
--- a/Source/WebCore/platform/cf/KURLCFNet.cpp
+++ b/Source/WebCore/platform/cf/KURLCFNet.cpp
@@ -45,22 +45,11 @@ KURL::KURL(CFURLRef url)
}
CFIndex bytesLength = CFURLGetBytes(url, 0, 0);
- Vector<char, 512> buffer(bytesLength + 6); // 5 for "file:", 1 for null character to end C string
- char* bytes = &buffer[5];
+ Vector<char, 512> buffer(bytesLength + 1);
+ char* bytes = &buffer[0];
CFURLGetBytes(url, reinterpret_cast<UInt8*>(bytes), bytesLength);
bytes[bytesLength] = '\0';
- if (bytes[0] != '/') {
- parse(bytes);
- return;
- }
-
- buffer[0] = 'f';
- buffer[1] = 'i';
- buffer[2] = 'l';
- buffer[3] = 'e';
- buffer[4] = ':';
-
- parse(buffer.data());
+ parse(bytes);
}
CFURLRef createCFURLFromBuffer(const CharBuffer& buffer)
diff --git a/Source/WebCore/platform/cf/SchedulePair.h b/Source/WebCore/platform/cf/SchedulePair.h
index 517243688..764c29fc4 100644
--- a/Source/WebCore/platform/cf/SchedulePair.h
+++ b/Source/WebCore/platform/cf/SchedulePair.h
@@ -35,11 +35,7 @@
#include <wtf/RetainPtr.h>
#if PLATFORM(MAC)
-#ifdef __OBJC__
-@class NSRunLoop;
-#else
-class NSRunLoop;
-#endif
+OBJC_CLASS NSRunLoop;
#endif
namespace WebCore {
diff --git a/Source/WebCore/platform/chromium/ChromiumDataObject.cpp b/Source/WebCore/platform/chromium/ChromiumDataObject.cpp
index 05c5e130c..6ad10c7da 100644
--- a/Source/WebCore/platform/chromium/ChromiumDataObject.cpp
+++ b/Source/WebCore/platform/chromium/ChromiumDataObject.cpp
@@ -33,6 +33,7 @@
#include "ClipboardMimeTypes.h"
#include "ClipboardUtilitiesChromium.h"
+#include "DataTransferItemListChromium.h"
#include "Pasteboard.h"
#include "PlatformSupport.h"
@@ -115,9 +116,6 @@ HashSet<String> ChromiumDataObject::types() const
results.add(mimeTypeTextPlain);
}
- if (m_url.isValid())
- results.add(mimeTypeURL);
-
if (!m_uriList.isEmpty())
results.add(mimeTypeTextURIList);
@@ -145,7 +143,7 @@ String ChromiumDataObject::getData(const String& type, bool& success) const
}
if (type == mimeTypeURL) {
- success = !m_url.isEmpty();
+ success = !m_uriList.isEmpty();
return m_url.string();
}
diff --git a/Source/WebCore/platform/chromium/ChromiumDataObject.h b/Source/WebCore/platform/chromium/ChromiumDataObject.h
index 9ddfb0b93..7e675bf93 100644
--- a/Source/WebCore/platform/chromium/ChromiumDataObject.h
+++ b/Source/WebCore/platform/chromium/ChromiumDataObject.h
@@ -85,11 +85,14 @@ public:
KURL htmlBaseUrl() const { return m_htmlBaseUrl; }
void setHtmlBaseUrl(const KURL& url) { m_htmlBaseUrl = url; }
- // Used to handle files being dragged in.
+ // Used to handle files being dragged in and out.
bool containsFilenames() const;
- Vector<String> filenames() const { return m_filenames; }
+ 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); }
+
// Used to handle files (images) being dragged out.
String fileExtension() const { return m_fileExtension; }
void setFileExtension(const String& fileExtension) { m_fileExtension = fileExtension; }
diff --git a/Source/WebCore/platform/chromium/ClipboardChromium.cpp b/Source/WebCore/platform/chromium/ClipboardChromium.cpp
index cd0bf78cf..75f8f630c 100644
--- a/Source/WebCore/platform/chromium/ClipboardChromium.cpp
+++ b/Source/WebCore/platform/chromium/ClipboardChromium.cpp
@@ -31,10 +31,13 @@
#include "ChromiumDataObject.h"
#include "ClipboardMimeTypes.h"
#include "ClipboardUtilitiesChromium.h"
+#include "DataTransferItemChromium.h"
#include "DataTransferItemListChromium.h"
#include "Document.h"
#include "DragData.h"
#include "Element.h"
+#include "ExceptionCode.h"
+#include "File.h"
#include "FileList.h"
#include "Frame.h"
#include "HTMLNames.h"
@@ -45,14 +48,160 @@
#include "PlatformSupport.h"
#include "Range.h"
#include "RenderImage.h"
-#include "ScriptExecutionContext.h"
+#include "StringCallback.h"
#include "markup.h"
-#include <wtf/text/StringBuilder.h>
#include <wtf/text/WTFString.h>
namespace WebCore {
+namespace {
+
+// These wrapper classes invalidate a DataTransferItem/DataTransferItemList when the associated
+// Clipboard object goes out of scope.
+class DataTransferItemListPolicyWrapper : public DataTransferItemList {
+public:
+ static PassRefPtr<DataTransferItemListPolicyWrapper> create(
+ PassRefPtr<ClipboardChromium>, PassRefPtr<DataTransferItemListChromium>);
+
+ 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>);
+
+private:
+ DataTransferItemListPolicyWrapper(PassRefPtr<ClipboardChromium>, PassRefPtr<DataTransferItemListChromium>);
+
+ RefPtr<ClipboardChromium> m_clipboard;
+ RefPtr<DataTransferItemListChromium> m_list;
+};
+
+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)
+{
+ return adoptRef(new DataTransferItemListPolicyWrapper(clipboard, list));
+}
+
+size_t DataTransferItemListPolicyWrapper::length() const
+{
+ if (m_clipboard->policy() == ClipboardNumb)
+ return 0;
+ return m_list->length();
+}
+
+PassRefPtr<DataTransferItem> DataTransferItemListPolicyWrapper::item(unsigned long index)
+{
+ if (m_clipboard->policy() == ClipboardNumb)
+ return 0;
+ RefPtr<DataTransferItem> item = m_list->item(index);
+ if (!item)
+ return 0;
+ return DataTransferItemPolicyWrapper::create(m_clipboard, item);
+}
+
+void DataTransferItemListPolicyWrapper::deleteItem(unsigned long index, ExceptionCode& ec)
+{
+ if (m_clipboard->policy() != ClipboardWritable) {
+ 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);
+}
+
+void DataTransferItemListPolicyWrapper::clear()
+{
+ if (m_clipboard->policy() != ClipboardWritable)
+ return;
+ m_list->clear();
+}
+
+void DataTransferItemListPolicyWrapper::add(const String& data, const String& type, ExceptionCode& ec)
+{
+ if (m_clipboard->policy() != ClipboardWritable)
+ return;
+ m_list->add(data, type, ec);
+}
+
+void DataTransferItemListPolicyWrapper::add(PassRefPtr<File> file)
+{
+ if (m_clipboard->policy() != ClipboardWritable)
+ return;
+ m_list->add(file);
+}
+
+DataTransferItemListPolicyWrapper::DataTransferItemListPolicyWrapper(
+ PassRefPtr<ClipboardChromium> clipboard, PassRefPtr<DataTransferItemListChromium> list)
+ : m_clipboard(clipboard)
+ , m_list(list)
+{
+}
+
+PassRefPtr<DataTransferItemPolicyWrapper> DataTransferItemPolicyWrapper::create(
+ PassRefPtr<ClipboardChromium> clipboard, PassRefPtr<DataTransferItem> item)
+{
+ return adoptRef(new DataTransferItemPolicyWrapper(clipboard, item));
+}
+
+String DataTransferItemPolicyWrapper::kind() const
+{
+ if (m_clipboard->policy() == ClipboardNumb)
+ return String();
+ return m_item->kind();
+}
+
+String DataTransferItemPolicyWrapper::type() const
+{
+ if (m_clipboard->policy() == ClipboardNumb)
+ return String();
+ return m_item->type();
+}
+
+void DataTransferItemPolicyWrapper::getAsString(PassRefPtr<StringCallback> callback) const
+{
+ if (m_clipboard->policy() != ClipboardReadable && m_clipboard->policy() != ClipboardWritable)
+ return;
+
+ m_item->getAsString(callback);
+}
+
+PassRefPtr<Blob> DataTransferItemPolicyWrapper::getAsFile() const
+{
+ if (m_clipboard->policy() != ClipboardReadable && m_clipboard->policy() != ClipboardWritable)
+ return 0;
+
+ return m_item->getAsFile();
+}
+
+DataTransferItemPolicyWrapper::DataTransferItemPolicyWrapper(
+ PassRefPtr<ClipboardChromium> clipboard, PassRefPtr<DataTransferItem> 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
@@ -79,6 +228,11 @@ ClipboardChromium::ClipboardChromium(ClipboardType clipboardType,
, m_dataObject(dataObject)
, m_frame(frame)
, m_originalSequenceNumber(PlatformSupport::clipboardSequenceNumber(currentPasteboardBuffer()))
+ , m_dragStorageUpdated(true)
+{
+}
+
+ClipboardChromium::~ClipboardChromium()
{
}
@@ -93,6 +247,7 @@ void ClipboardChromium::clearData(const String& type)
if (policy() != ClipboardWritable || !m_dataObject)
return;
+ m_dragStorageUpdated = true;
m_dataObject->clearData(normalizeType(type));
ASSERT_NOT_REACHED();
@@ -103,6 +258,7 @@ void ClipboardChromium::clearAllData()
if (policy() != ClipboardWritable)
return;
+ m_dragStorageUpdated = true;
m_dataObject->clearAll();
}
@@ -123,6 +279,7 @@ bool ClipboardChromium::setData(const String& type, const String& data)
if (policy() != ClipboardWritable)
return false;
+ m_dragStorageUpdated = true;
return m_dataObject->setData(normalizeType(type), data);
}
@@ -246,13 +403,15 @@ static void writeImageToDataObject(ChromiumDataObject* dataObject, Element* elem
if (extensionIndex != -1)
filename.truncate(extensionIndex);
}
- filename = ClipboardChromium::validateFileName(filename, dataObject);
String extension = MIMETypeRegistry::getPreferredExtensionForMIMEType(
cachedImage->response().mimeType());
- dataObject->setFileExtension(extension.isEmpty() ? emptyString() : "." + extension);
+ extension = extension.isEmpty() ? emptyString() : "." + extension;
+
+ ClipboardChromium::validateFilename(filename, extension);
- dataObject->setFileContentFilename(filename + dataObject->fileExtension());
+ dataObject->setFileContentFilename(filename + extension);
+ dataObject->setFileExtension(extension);
}
void ClipboardChromium::declareAndWriteDragImage(Element* element, const KURL& url, const String& title, Frame* frame)
@@ -260,6 +419,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);
@@ -275,6 +435,8 @@ void ClipboardChromium::writeURL(const KURL& url, const String& title, Frame*)
if (!m_dataObject)
return;
ASSERT(!url.isEmpty());
+
+ m_dragStorageUpdated = true;
m_dataObject->setData(mimeTypeURL, url);
m_dataObject->setUrlTitle(title);
@@ -292,6 +454,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());
@@ -313,6 +476,8 @@ void ClipboardChromium::writePlainText(const String& text)
replaceNewlinesWithWindowsStyleNewlines(str);
#endif
replaceNBSPWithSpace(str);
+
+ m_dragStorageUpdated = true;
m_dataObject->setData(mimeTypeTextPlain, str);
}
@@ -328,19 +493,60 @@ bool ClipboardChromium::hasData()
#if ENABLE(DATA_TRANSFER_ITEMS)
PassRefPtr<DataTransferItemList> ClipboardChromium::items()
{
- RefPtr<DataTransferItemListChromium> items = DataTransferItemListChromium::create(this, m_frame->document()->scriptExecutionContext());
-
if (!m_dataObject)
- return items;
+ // 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->addPasteboardItem(*it);
+ items.append(DataTransferItemChromium::createFromPasteboard(this, scriptExecutionContext, *it));
+ return;
}
- return items;
+
+ 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;
}
+
+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 8b174527a..924226df3 100644
--- a/Source/WebCore/platform/chromium/ClipboardChromium.h
+++ b/Source/WebCore/platform/chromium/ClipboardChromium.h
@@ -38,22 +38,23 @@ namespace WebCore {
class CachedImage;
class ChromiumDataObject;
+ class DataTransferItem;
+ class DataTransferItemListChromium;
class Frame;
class IntPoint;
class ClipboardChromium : public Clipboard, public CachedImageClient {
WTF_MAKE_FAST_ALLOCATED;
public:
- ~ClipboardChromium() {}
+ ~ClipboardChromium();
static PassRefPtr<ClipboardChromium> create(
ClipboardType, PassRefPtr<ChromiumDataObject>, ClipboardAccessPolicy, Frame*);
- // Returns the file name (not including the extension). This removes any
- // invalid file system characters as well as making sure the
- // path + extension is not bigger than allowed by the file system.
- // This may change the file extension in dataObject.
- static String validateFileName(const String& title, ChromiumDataObject* dataObject);
+ // Validates a filename (without the extension) and the extension. This removes any invalid
+ // file system characters as well as making sure the path + extension is not bigger than
+ // allowed by the file system.
+ static void validateFilename(String& name, String& extension);
virtual void clearData(const String& type);
void clearAllData();
@@ -83,6 +84,10 @@ 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
private:
@@ -93,7 +98,12 @@ namespace WebCore {
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/ClipboardChromiumMac.cpp b/Source/WebCore/platform/chromium/ClipboardChromiumPosix.cpp
index 38021402e..54cb99458 100644
--- a/Source/WebCore/platform/chromium/ClipboardChromiumMac.cpp
+++ b/Source/WebCore/platform/chromium/ClipboardChromiumPosix.cpp
@@ -27,43 +27,32 @@
#include "config.h"
#include "ClipboardChromium.h"
-#include "ChromiumDataObject.h"
-
namespace WebCore {
-
-
-// Filename length and character-set limits vary by filesystem, and there's no
-// real way to tell what filesystem is in use. Since HFS+ is by far the most
-// common, we'll abide by its limits, which are 255 Unicode characters (slightly
-// simplified; really it uses Normalization Form D, but the differences aren't
-// really worth dealing with here.)
-static const unsigned MaxHFSFilenameLength = 255;
+// On POSIX systems, the typical filename length limit is 255 character units. HFS+'s limit is
+// actually 255 Unicode characters using Apple's modification of Normzliation Form D, but the
+// differences aren't really worth dealing with here.
+static const unsigned maxFilenameLength = 255;
static bool isInvalidFileCharacter(UChar c)
{
- // HFS+ basically allows anything but '/'. For sanity's sake we'll disallow
- // control characters.
+ // HFS+ disallows '/' and Linux systems also disallow null. For sanity's sake we'll also
+ // disallow control characters.
return c < ' ' || c == 0x7F || c == '/';
}
-String ClipboardChromium::validateFileName(const String& title, ChromiumDataObject* dataObject)
+void ClipboardChromium::validateFilename(String& name, String& extension)
{
// Remove any invalid file system characters, especially "/".
- String result = title.removeCharacters(isInvalidFileCharacter);
- String extension = dataObject->fileExtension().removeCharacters(&isInvalidFileCharacter);
+ name = name.removeCharacters(&isInvalidFileCharacter);
+ extension = extension.removeCharacters(&isInvalidFileCharacter);
// Remove a ridiculously-long extension.
- if (extension.length() >= MaxHFSFilenameLength)
- extension = "";
-
- // Truncate an overly-long filename.
- int overflow = result.length() + extension.length() - MaxHFSFilenameLength;
- if (overflow > 0)
- result.remove(result.length() - overflow, overflow);
-
- dataObject->setFileExtension(extension);
- return result;
+ if (extension.length() >= maxFilenameLength)
+ extension = String();
+
+ // Truncate an overly-long filename, reserving one character for a dot.
+ name.truncate(maxFilenameLength - extension.length() - 1);
}
-} // namespace WebCore
+} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/ClipboardChromiumWin.cpp b/Source/WebCore/platform/chromium/ClipboardChromiumWin.cpp
index d9bbeb5dd..39b5806cd 100644
--- a/Source/WebCore/platform/chromium/ClipboardChromiumWin.cpp
+++ b/Source/WebCore/platform/chromium/ClipboardChromiumWin.cpp
@@ -27,12 +27,13 @@
#include "config.h"
#include "ClipboardChromium.h"
-#include "ChromiumDataObject.h"
-
#include <shlwapi.h>
namespace WebCore {
+// FAT32 and NTFS both limit filenames to a maximum of 255 characters.
+static const unsigned maxFilenameLength = 255;
+
// Returns true if the specified character is not valid in a file name. This
// is intended for use with removeCharacters.
static bool isInvalidFileCharacter(UChar c)
@@ -40,17 +41,17 @@ static bool isInvalidFileCharacter(UChar c)
return (PathGetCharType(c) & (GCT_LFNCHAR | GCT_SHORTCHAR)) == 0;
}
-String ClipboardChromium::validateFileName(const String& title, ChromiumDataObject* dataObject)
+void ClipboardChromium::validateFilename(String& name, String& extension)
{
// Remove any invalid file system characters.
- String result = title.removeCharacters(&isInvalidFileCharacter);
- if (result.length() + dataObject->fileExtension().length() + 1 >= MAX_PATH) {
- if (dataObject->fileExtension().length() + 1 >= MAX_PATH)
- dataObject->setFileExtension("");
- if (result.length() + dataObject->fileExtension().length() + 1 >= MAX_PATH)
- result = result.substring(0, MAX_PATH - dataObject->fileExtension().length() - 1);
- }
- return result;
+ name = name.removeCharacters(&isInvalidFileCharacter);
+ extension = extension.removeCharacters(&isInvalidFileCharacter);
+
+ if (extension.length() >= maxFilenameLength)
+ extension = String();
+
+ // Truncate overly-long filenames, reserving one character for a dot.
+ name.truncate(maxFilenameLength - extension.length() - 1);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/DataTransferItemChromium.cpp b/Source/WebCore/platform/chromium/DataTransferItemChromium.cpp
index a79ae85eb..696ee653e 100644
--- a/Source/WebCore/platform/chromium/DataTransferItemChromium.cpp
+++ b/Source/WebCore/platform/chromium/DataTransferItemChromium.cpp
@@ -38,6 +38,8 @@
#include "ClipboardChromium.h"
#include "ClipboardMimeTypes.h"
#include "ClipboardUtilitiesChromium.h"
+#include "DataTransferItemListChromium.h"
+#include "File.h"
#include "PlatformSupport.h"
#include "SharedBuffer.h"
#include "StringCallback.h"
@@ -47,7 +49,7 @@ 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, ""));
+ return adoptRef(new DataTransferItemChromium(owner, context, PasteboardSource, DataTransferItem::kindString, type, String()));
return adoptRef(new DataTransferItemChromium(owner, context, PasteboardSource, DataTransferItem::kindFile, type, ""));
}
@@ -56,29 +58,42 @@ PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::create(PassRefPtr
const String& data,
const String& type)
{
- return adoptRef(new DataTransferItemChromium(owner, context, InternalSource, DataTransferItem::kindString, type, data));
+ return adoptRef(new DataTransferItemChromium(owner, context, DataTransferItemChromium::InternalSource, kindString, type, data));
}
-PassRefPtr<DataTransferItem> DataTransferItem::create(PassRefPtr<Clipboard> owner,
- ScriptExecutionContext* context,
- const String& data,
- const String& type)
+PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::create(PassRefPtr<Clipboard> owner,
+ ScriptExecutionContext* context,
+ PassRefPtr<File> file)
{
- return DataTransferItemChromium::create(owner, context, data, type);
+ 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)
- : DataTransferItem(owner, kind, type)
- , m_context(context)
+ : m_context(context)
+ , m_owner(owner)
+ , m_kind(kind)
+ , m_type(type)
, m_source(source)
, m_data(data)
{
}
-void DataTransferItemChromium::getAsString(PassRefPtr<StringCallback> callback)
+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 ((owner()->policy() != ClipboardReadable && owner()->policy() != ClipboardWritable)
- || kind() != kindString)
+ if (kind() != kindString)
+ return;
+
+ if (clipboardChromium()->storageHasUpdated())
return;
if (m_source == InternalSource) {
@@ -87,8 +102,6 @@ void DataTransferItemChromium::getAsString(PassRefPtr<StringCallback> callback)
}
ASSERT(m_source == PasteboardSource);
- if (static_cast<ClipboardChromium*>(owner())->platformClipboardChanged())
- return;
// This is ugly but there's no real alternative.
if (type() == mimeTypeTextPlain) {
@@ -106,13 +119,13 @@ void DataTransferItemChromium::getAsString(PassRefPtr<StringCallback> callback)
ASSERT_NOT_REACHED();
}
-PassRefPtr<Blob> DataTransferItemChromium::getAsFile()
+PassRefPtr<Blob> DataTransferItemChromium::getAsFile() const
{
- if (m_source == InternalSource)
+ if (kind() != kindFile || clipboardChromium()->storageHasUpdated())
return 0;
- if (static_cast<ClipboardChromium*>(owner())->platformClipboardChanged())
- return 0;
+ if (m_source == InternalSource)
+ return m_file;
ASSERT(m_source == PasteboardSource);
if (type() == mimeTypeImagePng) {
@@ -136,6 +149,11 @@ PassRefPtr<Blob> DataTransferItemChromium::getAsFile()
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
index 144e40f7c..2a919006b 100644
--- a/Source/WebCore/platform/chromium/DataTransferItemChromium.h
+++ b/Source/WebCore/platform/chromium/DataTransferItemChromium.h
@@ -40,27 +40,41 @@
namespace WebCore {
class Clipboard;
+class ClipboardChromium;
+class File;
class ScriptExecutionContext;
class DataTransferItemChromium : public DataTransferItem {
public:
- static PassRefPtr<DataTransferItemChromium> createFromPasteboard(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, const String& type);
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 void getAsString(PassRefPtr<StringCallback>);
- virtual PassRefPtr<Blob> getAsFile();
+ 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
diff --git a/Source/WebCore/platform/chromium/DataTransferItemListChromium.cpp b/Source/WebCore/platform/chromium/DataTransferItemListChromium.cpp
index 320e74914..3a280fe3b 100644
--- a/Source/WebCore/platform/chromium/DataTransferItemListChromium.cpp
+++ b/Source/WebCore/platform/chromium/DataTransferItemListChromium.cpp
@@ -33,9 +33,17 @@
#if ENABLE(DATA_TRANSFER_ITEMS)
-#include "Clipboard.h"
+#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 {
@@ -45,13 +53,116 @@ PassRefPtr<DataTransferItemListChromium> DataTransferItemListChromium::create(Pa
}
DataTransferItemListChromium::DataTransferItemListChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context)
- : DataTransferItemList(owner, context)
+ : m_owner(owner)
+ , m_context(context)
{
}
-void DataTransferItemListChromium::addPasteboardItem(const String& type)
+size_t DataTransferItemListChromium::length() const
{
- m_items.append(DataTransferItemChromium::createFromPasteboard(m_owner, m_context, type));
+ 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
diff --git a/Source/WebCore/platform/chromium/DataTransferItemListChromium.h b/Source/WebCore/platform/chromium/DataTransferItemListChromium.h
index a3321b5ad..61bd167c7 100644
--- a/Source/WebCore/platform/chromium/DataTransferItemListChromium.h
+++ b/Source/WebCore/platform/chromium/DataTransferItemListChromium.h
@@ -40,7 +40,8 @@
namespace WebCore {
class Clipboard;
-class DataTransferItemChromium;
+class ClipboardChromium;
+class File;
class ScriptExecutionContext;
typedef int ExceptionCode;
@@ -49,12 +50,23 @@ class DataTransferItemListChromium : public DataTransferItemList {
public:
static PassRefPtr<DataTransferItemListChromium> create(PassRefPtr<Clipboard>, ScriptExecutionContext*);
-private:
- friend class ClipboardChromium;
+ 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>);
+private:
DataTransferItemListChromium(PassRefPtr<Clipboard>, ScriptExecutionContext*);
+ ClipboardChromium* clipboardChromium() const;
- virtual void addPasteboardItem(const String& 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;
};
} // namespace WebCore
@@ -62,4 +74,3 @@ private:
#endif // ENABLE(DATA_TRANSFER_ITEMS)
#endif // DataTransferItemListChromium_h
-
diff --git a/Source/WebCore/platform/chromium/DragDataChromium.cpp b/Source/WebCore/platform/chromium/DragDataChromium.cpp
index 9c3838602..3d94a19b2 100644
--- a/Source/WebCore/platform/chromium/DragDataChromium.cpp
+++ b/Source/WebCore/platform/chromium/DragDataChromium.cpp
@@ -50,14 +50,14 @@ static bool containsHTML(const ChromiumDataObject* dropData)
bool DragData::containsURL(Frame*, FilenameConversionPolicy filenamePolicy) const
{
- return m_platformDragData->types().contains(mimeTypeURL)
+ return m_platformDragData->types().contains(mimeTypeTextURIList)
|| (filenamePolicy == ConvertFilenames && m_platformDragData->containsFilenames());
}
String DragData::asURL(Frame*, FilenameConversionPolicy filenamePolicy, String* title) const
{
String url;
- if (m_platformDragData->types().contains(mimeTypeURL)) {
+ if (m_platformDragData->types().contains(mimeTypeTextURIList)) {
bool ignoredSuccess;
url = m_platformDragData->getData(mimeTypeURL, ignoredSuccess);
if (title)
@@ -109,7 +109,7 @@ bool DragData::canSmartReplace() const
// ClipboardWin::writeRange is called). For example, dragging a link
// should not result in a space being added.
return m_platformDragData->types().contains(mimeTypeTextPlain)
- && !m_platformDragData->types().contains(mimeTypeURL);
+ && !m_platformDragData->types().contains(mimeTypeTextURIList);
}
bool DragData::containsCompatibleContent() const
diff --git a/Source/WebCore/platform/chromium/LanguageChromium.cpp b/Source/WebCore/platform/chromium/LanguageChromium.cpp
index 93af1a946..d23f19cf1 100644
--- a/Source/WebCore/platform/chromium/LanguageChromium.cpp
+++ b/Source/WebCore/platform/chromium/LanguageChromium.cpp
@@ -33,10 +33,11 @@
#include "PlatformString.h"
#include "PlatformSupport.h"
+#include <wtf/Vector.h>
namespace WebCore {
-String platformDefaultLanguage()
+static String platformLanguage()
{
DEFINE_STATIC_LOCAL(String, computedDefaultLanguage, ());
if (computedDefaultLanguage.isEmpty())
@@ -44,4 +45,11 @@ String platformDefaultLanguage()
return computedDefaultLanguage;
}
+Vector<String> platformUserPreferredLanguages()
+{
+ Vector<String> userPreferredLanguages;
+ userPreferredLanguages.append(platformLanguage());
+ return userPreferredLanguages;
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/PlatformScreenChromium.cpp b/Source/WebCore/platform/chromium/PlatformScreenChromium.cpp
index 44df3213f..e0553b930 100644
--- a/Source/WebCore/platform/chromium/PlatformScreenChromium.cpp
+++ b/Source/WebCore/platform/chromium/PlatformScreenChromium.cpp
@@ -31,6 +31,7 @@
#include "config.h"
#include "PlatformScreen.h"
+#include "FrameView.h"
#include "IntRect.h"
#include "PlatformSupport.h"
@@ -61,19 +62,14 @@ bool screenIsMonochrome(Widget* widget)
return PlatformSupport::screenIsMonochrome(widget);
}
-FloatRect screenRect(Widget* widget)
+FloatRect screenRect(FrameView* frameView)
{
- return PlatformSupport::screenRect(widget);
+ return PlatformSupport::screenRect(frameView);
}
-FloatRect screenAvailableRect(Widget* widget)
+FloatRect screenAvailableRect(FrameView* frameView)
{
- return PlatformSupport::screenAvailableRect(widget);
-}
-
-double screenRefreshRate(Widget* widget)
-{
- return PlatformSupport::screenRefreshRate(widget);
+ return PlatformSupport::screenAvailableRect(frameView);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/PlatformSupport.h b/Source/WebCore/platform/chromium/PlatformSupport.h
index c8ded6e26..1f396c5d3 100644
--- a/Source/WebCore/platform/chromium/PlatformSupport.h
+++ b/Source/WebCore/platform/chromium/PlatformSupport.h
@@ -71,6 +71,7 @@ class Color;
class Cursor;
class Document;
class Frame;
+class FrameView;
class GamepadList;
class GeolocationServiceBridge;
class GeolocationServiceChromium;
@@ -245,9 +246,8 @@ public:
static int screenDepth(Widget*);
static int screenDepthPerComponent(Widget*);
static bool screenIsMonochrome(Widget*);
- static IntRect screenRect(Widget*);
- static IntRect screenAvailableRect(Widget*);
- static double screenRefreshRate(Widget*);
+ static IntRect screenRect(FrameView*);
+ static IntRect screenAvailableRect(FrameView*);
// SharedTimers -------------------------------------------------------
static void setSharedTimerFiredFunction(void (*func)());
diff --git a/Source/WebCore/platform/efl/LanguageEfl.cpp b/Source/WebCore/platform/efl/LanguageEfl.cpp
index efed862fb..e6c1a7259 100644
--- a/Source/WebCore/platform/efl/LanguageEfl.cpp
+++ b/Source/WebCore/platform/efl/LanguageEfl.cpp
@@ -32,10 +32,11 @@
#include "PlatformString.h"
#include <locale.h>
+#include <wtf/Vector.h>
namespace WebCore {
-String platformDefaultLanguage()
+static String platformLanguage()
{
char* localeDefault = setlocale(LC_CTYPE, 0);
@@ -50,4 +51,11 @@ String platformDefaultLanguage()
return String(localeDefault);
}
+Vector<String> platformUserPreferredLanguages()
+{
+ Vector<String> userPreferredLanguages;
+ userPreferredLanguages.append(platformLanguage());
+ return userPreferredLanguages;
+}
+
}
diff --git a/Source/WebCore/platform/efl/LocalizedStringsEfl.cpp b/Source/WebCore/platform/efl/LocalizedStringsEfl.cpp
index ae530c1d9..27240e82b 100644
--- a/Source/WebCore/platform/efl/LocalizedStringsEfl.cpp
+++ b/Source/WebCore/platform/efl/LocalizedStringsEfl.cpp
@@ -113,6 +113,11 @@ String contextMenuItemTagCopyImageToClipboard()
return String::fromUTF8("Copy Image");
}
+String contextMenuItemTagCopyImageUrlToClipboard()
+{
+ return String::fromUTF8("Copy Image Address");
+}
+
String contextMenuItemTagOpenVideoInNewWindow()
{
return String::fromUTF8("Open Video in New Window");
diff --git a/Source/WebCore/platform/efl/PlatformScreenEfl.cpp b/Source/WebCore/platform/efl/PlatformScreenEfl.cpp
index fac959723..f30d23da7 100644
--- a/Source/WebCore/platform/efl/PlatformScreenEfl.cpp
+++ b/Source/WebCore/platform/efl/PlatformScreenEfl.cpp
@@ -34,6 +34,7 @@
#include "config.h"
#include "PlatformScreen.h"
+#include "FrameView.h"
#include "NotImplemented.h"
#include "PlatformString.h"
#include "Widget.h"
@@ -73,23 +74,23 @@ bool screenIsMonochrome(Widget*)
return false;
}
-FloatRect screenRect(Widget* widget)
+FloatRect screenRect(FrameView* frameView)
{
- if (!widget)
+ if (!frameView)
return FloatRect();
int x, y, w, h;
- Evas* e = widget->evas();
+ Evas* e = frameView->evas();
ecore_evas_screen_geometry_get(ecore_evas_ecore_evas_get(e), &x, &y, &w, &h);
return FloatRect(x, y, w, h);
}
-FloatRect screenAvailableRect(Widget* widget)
+FloatRect screenAvailableRect(FrameView* frameView)
{
notImplemented();
- return screenRect(widget);
+ return screenRect(frameView);
}
}
diff --git a/Source/WebCore/platform/graphics/BitmapImage.h b/Source/WebCore/platform/graphics/BitmapImage.h
index f4d50ce75..00802f69f 100644
--- a/Source/WebCore/platform/graphics/BitmapImage.h
+++ b/Source/WebCore/platform/graphics/BitmapImage.h
@@ -34,11 +34,7 @@
#if PLATFORM(MAC)
#include <wtf/RetainPtr.h>
-#ifdef __OBJC__
-@class NSImage;
-#else
-class NSImage;
-#endif
+OBJC_CLASS NSImage;
#endif
#if PLATFORM(WIN)
diff --git a/Source/WebCore/platform/graphics/CrossfadeGeneratedImage.h b/Source/WebCore/platform/graphics/CrossfadeGeneratedImage.h
index ade2e5bd7..eb06b6d8b 100644
--- a/Source/WebCore/platform/graphics/CrossfadeGeneratedImage.h
+++ b/Source/WebCore/platform/graphics/CrossfadeGeneratedImage.h
@@ -43,6 +43,13 @@ public:
return adoptRef(new CrossfadeGeneratedImage(fromImage, toImage, percentage, crossfadeSize, size));
}
+ virtual void setContainerSize(const IntSize&) { }
+ virtual bool usesContainerSize() const { return false; }
+ virtual bool hasRelativeWidth() const { return false; }
+ virtual bool hasRelativeHeight() const { return false; }
+
+ virtual IntSize size() const { return m_crossfadeSize; }
+
protected:
virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator);
virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& dstRect);
diff --git a/Source/WebCore/platform/graphics/FloatRect.cpp b/Source/WebCore/platform/graphics/FloatRect.cpp
index fa9045c0b..595af2a32 100644
--- a/Source/WebCore/platform/graphics/FloatRect.cpp
+++ b/Source/WebCore/platform/graphics/FloatRect.cpp
@@ -103,30 +103,30 @@ void FloatRect::unite(const FloatRect& other)
return;
}
- float l = min(x(), other.x());
- float t = min(y(), other.y());
- float r = max(maxX(), other.maxX());
- float b = max(maxY(), other.maxY());
+ uniteEvenIfEmpty(other);
+}
- setLocationAndSizeFromEdges(l, t, r, b);
+void FloatRect::uniteEvenIfEmpty(const FloatRect& other)
+{
+ float minX = min(x(), other.x());
+ float minY = min(y(), other.y());
+ float maxX = max(this->maxX(), other.maxX());
+ float maxY = max(this->maxY(), other.maxY());
+
+ setLocationAndSizeFromEdges(minX, minY, maxX, maxY);
}
void FloatRect::uniteIfNonZero(const FloatRect& other)
{
// Handle empty special cases first.
- if (!other.width() && !other.height())
+ if (other.isZero())
return;
- if (!width() && !height()) {
+ if (isZero()) {
*this = other;
return;
}
- float left = min(x(), other.x());
- float top = min(y(), other.y());
- float right = max(maxX(), other.maxX());
- float bottom = max(maxY(), other.maxY());
-
- setLocationAndSizeFromEdges(left, top, right, bottom);
+ uniteEvenIfEmpty(other);
}
void FloatRect::scale(float sx, float sy)
@@ -218,6 +218,19 @@ IntRect enclosingIntRect(const FloatRect& rect)
clampToInteger(width), clampToInteger(height));
}
+IntRect enclosedIntRect(const FloatRect& rect)
+{
+ int x = clampToInteger(ceilf(rect.x()));
+ int y = clampToInteger(ceilf(rect.y()));
+ float maxX = clampToInteger(floorf(rect.maxX()));
+ float maxY = clampToInteger(floorf(rect.maxY()));
+ // A rect of width 0 should not become a rect of width -1 due to ceil/floor.
+ int width = max(clampToInteger(maxX - x), 0);
+ int height = max(clampToInteger(maxY - y), 0);
+
+ return IntRect(x, y, width, height);
+}
+
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 ae6c23a7d..22c171c5a 100644
--- a/Source/WebCore/platform/graphics/FloatRect.h
+++ b/Source/WebCore/platform/graphics/FloatRect.h
@@ -152,6 +152,7 @@ public:
void intersect(const FloatRect&);
void unite(const FloatRect&);
+ void uniteEvenIfEmpty(const FloatRect&);
void uniteIfNonZero(const FloatRect&);
// Note, this doesn't match what IntRect::contains(IntPoint&) does; the int version
@@ -269,6 +270,9 @@ inline bool operator!=(const FloatRect& a, const FloatRect& b)
IntRect enclosingIntRect(const FloatRect&);
+// Returns a valid IntRect contained within the given FloatRect.
+IntRect enclosedIntRect(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/Font.h b/Source/WebCore/platform/graphics/Font.h
index 9a7a86213..d15a77f3c 100644
--- a/Source/WebCore/platform/graphics/Font.h
+++ b/Source/WebCore/platform/graphics/Font.h
@@ -129,6 +129,17 @@ public:
break;
}
+ switch (m_fontDescription.commonLigaturesState()) {
+ case FontDescription::DisabledLigaturesState:
+ features &= ~Ligatures;
+ break;
+ case FontDescription::EnabledLigaturesState:
+ features |= Ligatures;
+ break;
+ case FontDescription::NormalLigaturesState:
+ break;
+ }
+
return features;
}
@@ -171,6 +182,7 @@ public:
static bool shouldUseSmoothing();
enum CodePath { Auto, Simple, Complex, SimpleWithGlyphOverflow };
+ CodePath codePath(const TextRun&) const;
private:
enum ForTextEmphasisOrNot { NotForTextEmphasis, ForTextEmphasis };
@@ -191,8 +203,6 @@ private:
static bool canReturnFallbackFontsForComplexText();
static bool canExpandAroundIdeographsInComplexText();
- CodePath codePath(const TextRun&) const;
-
// Returns the initial in-stream advance.
float getGlyphsAndAdvancesForComplexText(const TextRun&, int from, int to, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const;
void drawComplexText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
diff --git a/Source/WebCore/platform/graphics/FontDescription.h b/Source/WebCore/platform/graphics/FontDescription.h
index 51a257b41..e8329763d 100644
--- a/Source/WebCore/platform/graphics/FontDescription.h
+++ b/Source/WebCore/platform/graphics/FontDescription.h
@@ -74,6 +74,8 @@ public:
enum Kerning { AutoKerning, NormalKerning, NoneKerning };
+ enum LigaturesState { NormalLigaturesState, DisabledLigaturesState, EnabledLigaturesState };
+
FontDescription()
: m_specifiedSize(0)
, m_computedSize(0)
@@ -88,6 +90,9 @@ public:
, m_usePrinterFont(false)
, m_renderingMode(NormalRenderingMode)
, m_kerning(AutoKerning)
+ , m_commonLigaturesState(NormalLigaturesState)
+ , m_discretionaryLigaturesState(NormalLigaturesState)
+ , m_historicalLigaturesState(NormalLigaturesState)
, m_keywordSize(0)
, m_fontSmoothing(AutoSmoothing)
, m_textRendering(AutoTextRendering)
@@ -116,6 +121,9 @@ public:
bool useFixedDefaultSize() const { return genericFamily() == MonospaceFamily && !family().next() && family().family() == monospaceFamily; }
FontRenderingMode renderingMode() const { return static_cast<FontRenderingMode>(m_renderingMode); }
Kerning kerning() const { return static_cast<Kerning>(m_kerning); }
+ LigaturesState commonLigaturesState() const { return static_cast<LigaturesState>(m_commonLigaturesState); }
+ LigaturesState discretionaryLigaturesState() const { return static_cast<LigaturesState>(m_discretionaryLigaturesState); }
+ LigaturesState historicalLigaturesState() const { return static_cast<LigaturesState>(m_historicalLigaturesState); }
unsigned keywordSize() const { return m_keywordSize; }
FontSmoothingMode fontSmoothing() const { return static_cast<FontSmoothingMode>(m_fontSmoothing); }
TextRenderingMode textRenderingMode() const { return static_cast<TextRenderingMode>(m_textRendering); }
@@ -146,6 +154,9 @@ public:
#endif
void setRenderingMode(FontRenderingMode mode) { m_renderingMode = mode; }
void setKerning(Kerning kerning) { m_kerning = kerning; }
+ void setCommonLigaturesState(LigaturesState commonLigaturesState) { m_commonLigaturesState = commonLigaturesState; }
+ void setDiscretionaryLigaturesState(LigaturesState discretionaryLigaturesState) { m_discretionaryLigaturesState = discretionaryLigaturesState; }
+ void setHistoricalLigaturesState(LigaturesState historicalLigaturesState) { m_historicalLigaturesState = historicalLigaturesState; }
void setKeywordSize(unsigned s) { m_keywordSize = s; }
void setFontSmoothing(FontSmoothingMode smoothing) { m_fontSmoothing = smoothing; }
void setTextRenderingMode(TextRenderingMode rendering) { m_textRendering = rendering; }
@@ -180,6 +191,10 @@ private:
unsigned m_renderingMode : 1; // Used to switch between CG and GDI text on Windows.
unsigned m_kerning : 2; // Kerning
+ unsigned m_commonLigaturesState : 2;
+ unsigned m_discretionaryLigaturesState : 2;
+ unsigned m_historicalLigaturesState : 2;
+
unsigned m_keywordSize : 4; // We cache whether or not a font is currently represented by a CSS keyword (e.g., medium). If so,
// then we can accurately translate across different generic families to adjust for different preference settings
// (e.g., 13px monospace vs. 16px everything else). Sizes are 1-8 (like the HTML size values for <font>).
@@ -203,6 +218,9 @@ inline bool FontDescription::operator==(const FontDescription& other) const
&& m_usePrinterFont == other.m_usePrinterFont
&& m_renderingMode == other.m_renderingMode
&& m_kerning == other.m_kerning
+ && m_commonLigaturesState == other.m_commonLigaturesState
+ && m_discretionaryLigaturesState == other.m_discretionaryLigaturesState
+ && m_historicalLigaturesState == other.m_historicalLigaturesState
&& m_keywordSize == other.m_keywordSize
&& m_fontSmoothing == other.m_fontSmoothing
&& m_textRendering == other.m_textRendering
diff --git a/Source/WebCore/platform/graphics/FontFastPath.cpp b/Source/WebCore/platform/graphics/FontFastPath.cpp
index 02b695b1c..3ae0ad581 100644
--- a/Source/WebCore/platform/graphics/FontFastPath.cpp
+++ b/Source/WebCore/platform/graphics/FontFastPath.cpp
@@ -379,6 +379,10 @@ void Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRu
void Font::drawGlyphBuffer(GraphicsContext* context, const TextRun& run, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const
{
+#if !ENABLE(SVG_FONTS)
+ UNUSED_PARAM(run);
+#endif
+
// Draw each contiguous run of glyphs that use the same font data.
const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
FloatSize offset = glyphBuffer.offsetAt(0);
diff --git a/Source/WebCore/platform/graphics/FontPlatformData.h b/Source/WebCore/platform/graphics/FontPlatformData.h
index 1fcba312f..705c58897 100644
--- a/Source/WebCore/platform/graphics/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/FontPlatformData.h
@@ -55,11 +55,7 @@
#endif
#if OS(DARWIN)
-#ifdef __OBJC__
-@class NSFont;
-#else
-class NSFont;
-#endif
+OBJC_CLASS NSFont;
typedef struct CGFont* CGFontRef;
typedef const struct __CTFont* CTFontRef;
diff --git a/Source/WebCore/platform/graphics/GraphicsContext3D.h b/Source/WebCore/platform/graphics/GraphicsContext3D.h
index e4f69d8aa..34c549ab4 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext3D.h
+++ b/Source/WebCore/platform/graphics/GraphicsContext3D.h
@@ -50,13 +50,8 @@
#if PLATFORM(MAC)
#include <OpenGL/OpenGL.h>
#include <wtf/RetainPtr.h>
-#ifdef __OBJC__
-@class CALayer;
-@class WebGLLayer;
-#else
-class CALayer;
-class WebGLLayer;
-#endif
+OBJC_CLASS CALayer;
+OBJC_CLASS WebGLLayer;
#elif PLATFORM(QT)
QT_BEGIN_NAMESPACE
class QPainter;
@@ -459,7 +454,14 @@ public:
virtual ~ContextLostCallback() {}
};
+ class ErrorMessageCallback {
+ public:
+ virtual void onErrorMessage(const String& message, GC3Dint id) = 0;
+ virtual ~ErrorMessageCallback() { }
+ };
+
void setContextLostCallback(PassOwnPtr<ContextLostCallback>);
+ void setErrorMessageCallback(PassOwnPtr<ErrorMessageCallback>);
static PassRefPtr<GraphicsContext3D> create(Attributes, HostWindow*, RenderStyle = RenderOffscreen);
~GraphicsContext3D();
diff --git a/Source/WebCore/platform/graphics/GraphicsLayer.cpp b/Source/WebCore/platform/graphics/GraphicsLayer.cpp
index 3b884f546..c7a22755b 100644
--- a/Source/WebCore/platform/graphics/GraphicsLayer.cpp
+++ b/Source/WebCore/platform/graphics/GraphicsLayer.cpp
@@ -30,6 +30,8 @@
#include "GraphicsLayer.h"
#include "FloatPoint.h"
+#include "GraphicsContext.h"
+#include "LayoutTypes.h"
#include "RotateTransformOperation.h"
#include "TextStream.h"
#include <wtf/text/CString.h>
@@ -261,6 +263,17 @@ void GraphicsLayer::setReplicatedByLayer(GraphicsLayer* layer)
m_replicaLayer = layer;
}
+void GraphicsLayer::setOffsetFromRenderer(const IntSize& offset)
+{
+ if (offset == m_offsetFromRenderer)
+ return;
+
+ m_offsetFromRenderer = offset;
+
+ // If the compositing layer offset changes, we need to repaint.
+ setNeedsDisplay();
+}
+
void GraphicsLayer::setBackgroundColor(const Color& color)
{
m_backgroundColor = color;
@@ -278,8 +291,15 @@ void GraphicsLayer::paintGraphicsLayerContents(GraphicsContext& context, const I
#ifndef NDEBUG
s_inPaintContents = true;
#endif
- if (m_client)
- m_client->paintContents(this, context, m_paintingPhase, clip);
+ if (m_client) {
+ LayoutSize offset = offsetFromRenderer();
+ context.translate(-offset);
+
+ LayoutRect clipRect(clip);
+ clipRect.move(offset);
+
+ m_client->paintContents(this, context, m_paintingPhase, clipRect);
+ }
#ifndef NDEBUG
s_inPaintContents = false;
#endif
@@ -306,7 +326,11 @@ void GraphicsLayer::updateDebugIndicators()
{
if (GraphicsLayer::showDebugBorders()) {
if (drawsContent()) {
- if (m_usingTiledLayer)
+ // FIXME: It's weird to ask the client if this layer is a tile cache layer.
+ // Maybe we should just cache that information inside GraphicsLayer?
+ if (m_client->shouldUseTileCache(this)) // tile cache layer: dark blue
+ setDebugBorder(Color(0, 0, 128, 128), 0.5);
+ else if (m_usingTiledLayer)
setDebugBorder(Color(255, 128, 0, 128), 2); // tiled layer: orange
else
setDebugBorder(Color(0, 128, 32, 128), 2); // normal layer: green
@@ -365,16 +389,14 @@ static inline const TransformOperations* operationsAt(const KeyframeValueList& v
return static_cast<const TransformAnimationValue*>(valueList.at(index))->value();
}
-void GraphicsLayer::fetchTransformOperationList(const KeyframeValueList& valueList, TransformOperationList& list, bool& isValid, bool& hasBigRotation)
+int GraphicsLayer::validateTransformOperations(const KeyframeValueList& valueList, bool& hasBigRotation)
{
ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
- list.clear();
- isValid = false;
hasBigRotation = false;
if (valueList.size() < 2)
- return;
+ return -1;
// Empty transforms match anything, so find the first non-empty entry as the reference.
size_t firstIndex = 0;
@@ -384,7 +406,7 @@ void GraphicsLayer::fetchTransformOperationList(const KeyframeValueList& valueLi
}
if (firstIndex >= valueList.size())
- return;
+ return -1;
const TransformOperations* firstVal = operationsAt(valueList, firstIndex);
@@ -397,19 +419,15 @@ void GraphicsLayer::fetchTransformOperationList(const KeyframeValueList& valueLi
continue;
if (!firstVal->operationsMatch(*val))
- return;
+ return -1;
}
- // Keyframes are valid, fill in the list.
- isValid = true;
-
+ // Keyframes are valid, check for big rotations.
double lastRotAngle = 0.0;
double maxRotAngle = -1.0;
- list.resize(firstVal->operations().size());
for (size_t j = 0; j < firstVal->operations().size(); ++j) {
TransformOperation::OperationType type = firstVal->operations().at(j)->getOperationType();
- list[j] = type;
// if this is a rotation entry, we need to see if any angle differences are >= 180 deg
if (type == TransformOperation::ROTATE_X ||
@@ -433,6 +451,8 @@ void GraphicsLayer::fetchTransformOperationList(const KeyframeValueList& valueLi
}
hasBigRotation = maxRotAngle >= 180.0;
+
+ return firstIndex;
}
diff --git a/Source/WebCore/platform/graphics/GraphicsLayer.h b/Source/WebCore/platform/graphics/GraphicsLayer.h
index 0b60be108..9f75624ff 100644
--- a/Source/WebCore/platform/graphics/GraphicsLayer.h
+++ b/Source/WebCore/platform/graphics/GraphicsLayer.h
@@ -44,11 +44,7 @@
#include <wtf/PassOwnPtr.h>
#if PLATFORM(MAC)
-#ifdef __OBJC__
-@class CALayer;
-#else
-class CALayer;
-#endif
+OBJC_CLASS CALayer;
typedef CALayer PlatformLayer;
#elif PLATFORM(WIN)
typedef struct _CACFLayer PlatformLayer;
@@ -258,7 +254,7 @@ public:
// Offset is origin of the renderer minus origin of the graphics layer (so either zero or negative).
IntSize offsetFromRenderer() const { return m_offsetFromRenderer; }
- void setOffsetFromRenderer(const IntSize& offset) { m_offsetFromRenderer = offset; }
+ void setOffsetFromRenderer(const IntSize&);
// The position of the layer (the location of its top-left corner in its parent)
const FloatPoint& position() const { return m_position; }
@@ -374,8 +370,8 @@ public:
virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation) { m_contentsOrientation = orientation; }
CompositingCoordinatesOrientation contentsOrientation() const { return m_contentsOrientation; }
- bool showDebugBorders() const { return m_client ? m_client->showDebugBorders() : false; }
- bool showRepaintCounter() const { return m_client ? m_client->showRepaintCounter() : false; }
+ bool showDebugBorders() const { return m_client ? m_client->showDebugBorders(this) : false; }
+ bool showRepaintCounter() const { return m_client ? m_client->showRepaintCounter(this) : false; }
void updateDebugIndicators();
@@ -412,6 +408,9 @@ public:
bool usingTiledLayer() const { return m_usingTiledLayer; }
+ // Called whenever the visible rect of the given GraphicsLayer changed.
+ virtual void visibleRectChanged() { }
+
#if PLATFORM(QT) || PLATFORM(GTK)
// This allows several alternative GraphicsLayer implementations in the same port,
// e.g. if a different GraphicsLayer implementation is needed in WebKit1 vs. WebKit2.
@@ -420,11 +419,19 @@ public:
#endif
protected:
+#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
+ // needs to notifiy the change to the platform layer as needed.
+ void clearFilters() { m_filters.clear(); }
+#endif
- typedef Vector<TransformOperation::OperationType> TransformOperationList;
- // Given a list of TransformAnimationValues, return an array of transform operations.
- // On return, if hasBigRotation is true, functions contain rotations of >= 180 degrees
- static void fetchTransformOperationList(const KeyframeValueList&, TransformOperationList&, bool& isValid, bool& hasBigRotation);
+ // Given a list of TransformAnimationValues, see if all the operations for each keyframe match. If so
+ // return the index of the KeyframeValueList entry that has that list of operations (it may not be
+ // the first entry because some keyframes might have an empty transform and those match any list).
+ // If the lists don't match return -1. On return, if hasBigRotation is true, functions contain
+ // rotations of >= 180 degrees
+ static int validateTransformOperations(const KeyframeValueList&, bool& hasBigRotation);
virtual void setOpacityInternal(float) { }
diff --git a/Source/WebCore/platform/graphics/GraphicsLayerClient.h b/Source/WebCore/platform/graphics/GraphicsLayerClient.h
index d9338265c..81272ddbe 100644
--- a/Source/WebCore/platform/graphics/GraphicsLayerClient.h
+++ b/Source/WebCore/platform/graphics/GraphicsLayerClient.h
@@ -71,8 +71,8 @@ public:
// Page scale factor.
virtual float pageScaleFactor() const { return 1; }
- virtual bool showDebugBorders() const = 0;
- virtual bool showRepaintCounter() const = 0;
+ virtual bool showDebugBorders(const GraphicsLayer*) const = 0;
+ virtual bool showRepaintCounter(const GraphicsLayer*) const = 0;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/GraphicsTypes.h b/Source/WebCore/platform/graphics/GraphicsTypes.h
index 1a07f0083..e6596d95c 100644
--- a/Source/WebCore/platform/graphics/GraphicsTypes.h
+++ b/Source/WebCore/platform/graphics/GraphicsTypes.h
@@ -30,9 +30,6 @@
namespace WebCore {
- // Note: These constants exactly match the NSCompositeOperator constants of
- // AppKit on Mac OS X Tiger. If these ever change, we'll need to change the
- // Mac OS X Tiger platform code to map one to the other.
enum CompositeOperator {
CompositeClear,
CompositeCopy,
@@ -46,7 +43,8 @@ namespace WebCore {
CompositeDestinationAtop,
CompositeXOR,
CompositePlusDarker,
- CompositePlusLighter
+ CompositePlusLighter,
+ CompositeDifference
};
enum GradientSpreadMethod {
diff --git a/Source/WebCore/platform/graphics/Icon.h b/Source/WebCore/platform/graphics/Icon.h
index 279713331..781a08cb2 100644
--- a/Source/WebCore/platform/graphics/Icon.h
+++ b/Source/WebCore/platform/graphics/Icon.h
@@ -28,11 +28,7 @@
#if PLATFORM(MAC)
#include <wtf/RetainPtr.h>
-#ifdef __OBJC__
-@class NSImage;
-#else
-class NSImage;
-#endif
+OBJC_CLASS NSImage;
#elif PLATFORM(WIN)
typedef struct HICON__* HICON;
#elif PLATFORM(QT)
diff --git a/Source/WebCore/platform/graphics/Image.h b/Source/WebCore/platform/graphics/Image.h
index 21b37d357..b78fc7d81 100644
--- a/Source/WebCore/platform/graphics/Image.h
+++ b/Source/WebCore/platform/graphics/Image.h
@@ -39,11 +39,7 @@
#include <wtf/text/WTFString.h>
#if PLATFORM(MAC)
-#ifdef __OBJC__
-@class NSImage;
-#else
-class NSImage;
-#endif
+OBJC_CLASS NSImage;
#endif
#if USE(CG)
diff --git a/Source/WebCore/platform/graphics/ImageBuffer.h b/Source/WebCore/platform/graphics/ImageBuffer.h
index 13070004c..ebc5bfa52 100644
--- a/Source/WebCore/platform/graphics/ImageBuffer.h
+++ b/Source/WebCore/platform/graphics/ImageBuffer.h
@@ -68,14 +68,19 @@ namespace WebCore {
DontCopyBackingStore // Subsequent draws may affect the copy.
};
+ enum DeferralMode {
+ NonDeferred,
+ Deferred
+ };
+
class ImageBuffer {
WTF_MAKE_NONCOPYABLE(ImageBuffer); WTF_MAKE_FAST_ALLOCATED;
public:
// Will return a null pointer on allocation failure.
- static PassOwnPtr<ImageBuffer> create(const IntSize& size, ColorSpace colorSpace = ColorSpaceDeviceRGB, RenderingMode renderingMode = Unaccelerated)
+ static PassOwnPtr<ImageBuffer> create(const IntSize& size, ColorSpace colorSpace = ColorSpaceDeviceRGB, RenderingMode renderingMode = Unaccelerated, DeferralMode deferralMode = NonDeferred)
{
bool success = false;
- OwnPtr<ImageBuffer> buf = adoptPtr(new ImageBuffer(size, colorSpace, renderingMode, success));
+ OwnPtr<ImageBuffer> buf = adoptPtr(new ImageBuffer(size, colorSpace, renderingMode, deferralMode, success));
if (success)
return buf.release();
return nullptr;
@@ -143,7 +148,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, bool& success);
+ ImageBuffer(const IntSize&, ColorSpace, RenderingMode, DeferralMode, bool& success);
};
#if USE(CG) || USE(SKIA)
diff --git a/Source/WebCore/platform/graphics/MediaPlayer.cpp b/Source/WebCore/platform/graphics/MediaPlayer.cpp
index 95ce0c553..54d7d7527 100644
--- a/Source/WebCore/platform/graphics/MediaPlayer.cpp
+++ b/Source/WebCore/platform/graphics/MediaPlayer.cpp
@@ -394,8 +394,10 @@ void MediaPlayer::loadWithNextMediaEngine(MediaPlayerFactory* current)
m_private->load(m_url);
else {
m_private = createNullMediaPlayer(this);
- if (m_mediaPlayerClient)
+ if (m_mediaPlayerClient) {
m_mediaPlayerClient->mediaPlayerEngineUpdated(this);
+ m_mediaPlayerClient->mediaPlayerResourceNotSupported(this);
+ }
}
}
diff --git a/Source/WebCore/platform/graphics/MediaPlayer.h b/Source/WebCore/platform/graphics/MediaPlayer.h
index da53de152..26ca3aada 100644
--- a/Source/WebCore/platform/graphics/MediaPlayer.h
+++ b/Source/WebCore/platform/graphics/MediaPlayer.h
@@ -46,13 +46,9 @@
#include "GraphicsLayer.h"
#endif
-#ifdef __OBJC__
-@class AVPlayer;
-@class QTMovie;
-#else
-class AVPlayer;
-class QTMovie;
-#endif
+OBJC_CLASS AVPlayer;
+OBJC_CLASS QTMovie;
+
class AVCFPlayer;
class QTMovieGWorld;
class QTMovieVisualContext;
@@ -139,6 +135,9 @@ public:
// element to an <embed> in standalone documents
virtual void mediaPlayerSawUnsupportedTracks(MediaPlayer*) { }
+ // The MediaPlayer could not discover an engine which supports the requested resource.
+ virtual void mediaPlayerResourceNotSupported(MediaPlayer*) { }
+
// Presentation-related methods
// a new frame of video is available
virtual void mediaPlayerRepaint(MediaPlayer*) { }
diff --git a/Source/WebCore/platform/graphics/Path.h b/Source/WebCore/platform/graphics/Path.h
index d14d90879..69ba93ef6 100644
--- a/Source/WebCore/platform/graphics/Path.h
+++ b/Source/WebCore/platform/graphics/Path.h
@@ -146,9 +146,9 @@ namespace WebCore {
void apply(void* info, PathApplierFunction) const;
void transform(const AffineTransform&);
- private:
void addBeziersForRoundedRect(const FloatRect&, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius);
+ private:
PlatformPathPtr m_path;
};
diff --git a/Source/WebCore/platform/graphics/SVGGlyph.cpp b/Source/WebCore/platform/graphics/SVGGlyph.cpp
index d5b7b9875..668134409 100644
--- a/Source/WebCore/platform/graphics/SVGGlyph.cpp
+++ b/Source/WebCore/platform/graphics/SVGGlyph.cpp
@@ -80,7 +80,7 @@ static inline SVGGlyph::ArabicForm processArabicFormDetection(const UChar& curCh
return curForm;
}
-Vector<SVGGlyph::ArabicForm> charactersWithArabicForm(const String& input, bool mirror)
+Vector<SVGGlyph::ArabicForm> charactersWithArabicForm(const String& input, bool rtl)
{
Vector<SVGGlyph::ArabicForm> forms;
unsigned length = input.length();
@@ -99,7 +99,7 @@ Vector<SVGGlyph::ArabicForm> charactersWithArabicForm(const String& input, bool
bool lastCharShapesRight = false;
// Start identifying arabic forms
- if (mirror) {
+ if (rtl) {
for (int i = length - 1; i >= 0; --i)
forms.prepend(processArabicFormDetection(input[i], lastCharShapesRight, forms.isEmpty() ? 0 : &forms.first()));
} else {
diff --git a/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp b/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp
index 29ebbeeac..32c85cd8f 100644
--- a/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp
+++ b/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp
@@ -160,6 +160,7 @@ private:
virtual bool platformCALayerContentsOpaque() const { return false; }
virtual bool platformCALayerDrawsContent() const { return false; }
virtual void platformCALayerLayerDidDisplay(PlatformLayer*) { }
+ virtual void platformCALayerDidCreateTiles() { }
AVFWrapper* m_parent;
};
diff --git a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h
index 7fd2465dc..dcc046d07 100644
--- a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h
+++ b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h
@@ -30,20 +30,14 @@
#include "MediaPlayerPrivateAVFoundation.h"
-#ifdef __OBJC__
-@class AVAsset;
-@class AVPlayer;
-@class AVPlayerItem;
-@class AVPlayerLayer;
-@class AVAssetImageGenerator;
-@class WebCoreAVFMovieObserver;
-#else
-class AVAsset;
-class AVPlayer;
-class AVPlayerItem;
-class AVPlayerLayer;
-class AVAssetImageGenerator;
-class WebCoreAVFMovieObserver;
+OBJC_CLASS AVAsset;
+OBJC_CLASS AVPlayer;
+OBJC_CLASS AVPlayerItem;
+OBJC_CLASS AVPlayerLayer;
+OBJC_CLASS AVAssetImageGenerator;
+OBJC_CLASS WebCoreAVFMovieObserver;
+
+#ifndef __OBJC__
typedef struct objc_object *id;
#endif
diff --git a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
index e73272ded..ad3ac04a2 100644
--- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
+++ b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
@@ -569,12 +569,19 @@ void GraphicsLayerCA::setOpacity(float opacity)
}
#if ENABLE(CSS_FILTERS)
-bool GraphicsLayerCA::setFilters(const FilterOperations& filters)
+bool GraphicsLayerCA::setFilters(const FilterOperations& filterOperations)
{
- GraphicsLayer::setFilters(filters);
- noteLayerPropertyChanged(FiltersChanged);
-
- return PlatformCALayer::filtersCanBeComposited(filters);
+ bool canCompositeFilters = PlatformCALayer::filtersCanBeComposited(filterOperations);
+ if (canCompositeFilters) {
+ GraphicsLayer::setFilters(filterOperations);
+ noteLayerPropertyChanged(FiltersChanged);
+ } else if (filters().size()) {
+ // In this case filters are rendered in software, so we need to remove any
+ // previously attached hardware filters.
+ clearFilters();
+ noteLayerPropertyChanged(FiltersChanged);
+ }
+ return canCompositeFilters;
}
#endif
@@ -836,6 +843,11 @@ void GraphicsLayerCA::syncCompositingStateForThisLayerOnly()
commitLayerChangesAfterSublayers();
}
+void GraphicsLayerCA::visibleRectChanged()
+{
+ m_layer->visibleRectChanged();
+}
+
void GraphicsLayerCA::recursiveCommitChanges(const TransformState& state, float pageScaleFactor, const FloatPoint& positionRelativeToBase, bool affectedByPageScale)
{
// Save the state before sending down to kids and restore it after
@@ -921,6 +933,15 @@ void GraphicsLayerCA::platformCALayerPaintContents(GraphicsContext& context, con
paintGraphicsLayerContents(context, clip);
}
+void GraphicsLayerCA::platformCALayerDidCreateTiles()
+{
+ ASSERT(m_layer->layerType() == PlatformCALayer::LayerTypeTileCacheLayer);
+
+ // 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);
+}
+
void GraphicsLayerCA::commitLayerChangesBeforeSublayers(float pageScaleFactor, const FloatPoint& positionRelativeToBase)
{
if (!m_uncommittedChanges)
@@ -1749,9 +1770,9 @@ bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valu
return true;
}
-bool GraphicsLayerCA::appendToUncommittedAnimations(const KeyframeValueList& valueList, const TransformOperationList& functionList, const Animation* animation, const String& animationName, const IntSize& boxSize, int animationIndex, double timeOffset, bool isMatrixAnimation)
+bool GraphicsLayerCA::appendToUncommittedAnimations(const KeyframeValueList& valueList, const TransformOperations* operations, const Animation* animation, const String& animationName, const IntSize& boxSize, int animationIndex, double timeOffset, bool isMatrixAnimation)
{
- TransformOperation::OperationType transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : functionList[animationIndex];
+ TransformOperation::OperationType transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : operations->operations().at(animationIndex)->getOperationType();
bool additive = animationIndex > 0;
bool isKeyframe = valueList.size() > 2;
@@ -1776,23 +1797,23 @@ bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValue
{
ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
- TransformOperationList functionList;
- bool listsMatch, hasBigRotation;
- fetchTransformOperationList(valueList, functionList, listsMatch, hasBigRotation);
+ bool hasBigRotation;
+ int listIndex = validateTransformOperations(valueList, hasBigRotation);
+ const TransformOperations* operations = (listIndex >= 0) ? static_cast<const TransformAnimationValue*>(valueList.at(listIndex))->value() : 0;
// We need to fall back to software animation if we don't have setValueFunction:, and
// we would need to animate each incoming transform function separately. This is the
// case if we have a rotation >= 180 or we have more than one transform function.
- if ((hasBigRotation || functionList.size() > 1) && !PlatformCAAnimation::supportsValueFunction())
+ if ((hasBigRotation || (operations && operations->size() > 1)) && !PlatformCAAnimation::supportsValueFunction())
return false;
bool validMatrices = true;
- // If functionLists don't match we do a matrix animation, otherwise we do a component hardware animation.
+ // If function lists don't match we do a matrix animation, otherwise we do a component hardware animation.
// Also, we can't do component animation unless we have valueFunction, so we need to do matrix animation
// if that's not true as well.
- bool isMatrixAnimation = !listsMatch || !PlatformCAAnimation::supportsValueFunction();
- int numAnimations = isMatrixAnimation ? 1 : functionList.size();
+ bool isMatrixAnimation = listIndex < 0 || !PlatformCAAnimation::supportsValueFunction();
+ int numAnimations = isMatrixAnimation ? 1 : operations->size();
bool reverseAnimationList = true;
#if !defined(BUILDING_ON_SNOW_LEOPARD) && !PLATFORM(WIN)
@@ -1807,14 +1828,14 @@ bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValue
#endif
if (reverseAnimationList) {
for (int animationIndex = numAnimations - 1; animationIndex >= 0; --animationIndex) {
- if (!appendToUncommittedAnimations(valueList, functionList, animation, animationName, boxSize, animationIndex, timeOffset, isMatrixAnimation)) {
+ if (!appendToUncommittedAnimations(valueList, operations, animation, animationName, boxSize, animationIndex, timeOffset, isMatrixAnimation)) {
validMatrices = false;
break;
}
}
} else {
for (int animationIndex = 0; animationIndex < numAnimations; ++animationIndex) {
- if (!appendToUncommittedAnimations(valueList, functionList, animation, animationName, boxSize, animationIndex, timeOffset, isMatrixAnimation)) {
+ if (!appendToUncommittedAnimations(valueList, operations, animation, animationName, boxSize, animationIndex, timeOffset, isMatrixAnimation)) {
validMatrices = false;
break;
}
diff --git a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h
index 93e0e64cd..80b237641 100644
--- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h
+++ b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h
@@ -134,6 +134,8 @@ public:
virtual void syncCompositingState(const FloatRect&);
virtual void syncCompositingStateForThisLayerOnly();
+ virtual void visibleRectChanged() OVERRIDE;
+
bool allowTiledLayer() const { return m_allowTiledLayer; }
virtual void setAllowTiledLayer(bool b);
@@ -155,6 +157,7 @@ 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;
void updateOpacityOnLayer();
@@ -321,7 +324,7 @@ private:
static void moveOrCopyLayerAnimation(MoveOrCopy, const String& animationIdentifier, PlatformCALayer *fromLayer, PlatformCALayer *toLayer);
void moveOrCopyAnimationsForProperty(MoveOrCopy, AnimatedPropertyID, PlatformCALayer * fromLayer, PlatformCALayer * toLayer);
- bool appendToUncommittedAnimations(const KeyframeValueList&, const TransformOperationList&, const Animation*, const String& animationName, const IntSize& boxSize, int animationIndex, double timeOffset, bool isMatrixAnimation);
+ bool appendToUncommittedAnimations(const KeyframeValueList&, const TransformOperations*, const Animation*, const String& animationName, const IntSize& boxSize, int animationIndex, double timeOffset, bool isMatrixAnimation);
enum LayerChange {
NoChange = 0,
diff --git a/Source/WebCore/platform/graphics/ca/LayerFlushScheduler.h b/Source/WebCore/platform/graphics/ca/LayerFlushScheduler.h
index f59071e5d..36b60418f 100644
--- a/Source/WebCore/platform/graphics/ca/LayerFlushScheduler.h
+++ b/Source/WebCore/platform/graphics/ca/LayerFlushScheduler.h
@@ -46,6 +46,8 @@ public:
void suspend();
void resume();
+ bool isSuspended() const { return m_isSuspended; }
+
private:
bool m_isSuspended;
LayerFlushSchedulerClient* m_client;
diff --git a/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h b/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h
index bfd76c82a..b2d325956 100644
--- a/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h
+++ b/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h
@@ -36,11 +36,7 @@
#include <wtf/Vector.h>
#if PLATFORM(MAC)
-#ifdef __OBJC__
-@class CAPropertyAnimation;
-#else
-class CAPropertyAnimation;
-#endif
+OBJC_CLASS CAPropertyAnimation;
typedef CAPropertyAnimation* PlatformAnimationRef;
#elif PLATFORM(WIN)
typedef struct _CACFAnimation* CACFAnimationRef;
diff --git a/Source/WebCore/platform/graphics/ca/PlatformCALayer.h b/Source/WebCore/platform/graphics/ca/PlatformCALayer.h
index 73661321a..582a0f74a 100644
--- a/Source/WebCore/platform/graphics/ca/PlatformCALayer.h
+++ b/Source/WebCore/platform/graphics/ca/PlatformCALayer.h
@@ -203,6 +203,8 @@ public:
float contentsScale() const;
void setContentsScale(float);
+ void visibleRectChanged();
+
#if PLATFORM(WIN)
HashMap<String, RefPtr<PlatformCAAnimation> >& animations() { return m_animations; }
#endif
diff --git a/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h b/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h
index ae1815c0b..be8e459d8 100644
--- a/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h
+++ b/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h
@@ -59,6 +59,8 @@ public:
virtual bool platformCALayerDrawsContent() const = 0;
virtual void platformCALayerLayerDidDisplay(PlatformLayer*) = 0;
+ virtual void platformCALayerDidCreateTiles() = 0;
+
protected:
virtual ~PlatformCALayerClient() {}
};
diff --git a/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm b/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm
index 34c9710d9..c52f20dd9 100644
--- a/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm
+++ b/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm
@@ -720,6 +720,8 @@ void PlatformCALayer::setFilters(const FilterOperations& filters)
RetainPtr<NSMutableArray> array(AdoptNS, [[NSMutableArray alloc] init]);
for (unsigned i = 0; i < filters.size(); ++i) {
+ String filterName = String::format("filter_%d", i);
+
const FilterOperation* filterOperation = filters.at(i);
switch(filterOperation->getOperationType()) {
case FilterOperation::DROP_SHADOW: {
@@ -744,7 +746,7 @@ void PlatformCALayer::setFilters(const FilterOperations& filters)
[caFilter setDefaults];
[caFilter setValue:[NSNumber numberWithFloat:op->amount()] forKey:@"inputIntensity"];
[caFilter setValue:[CIColor colorWithRed:1 green:1 blue:1] forKey:@"inputColor"];
- [caFilter setName:@"grayscaleFilter"];
+ [caFilter setName:filterName];
[array.get() addObject:caFilter];
break;
}
@@ -762,7 +764,7 @@ void PlatformCALayer::setFilters(const FilterOperations& filters)
[caFilter setValue:[CIVector vectorWithX:WebCore::blend(0.0, 0.272, t) Y:WebCore::blend(0.0, 0.534, t) Z:WebCore::blend(1.0, 0.131, t) W:0] forKey:@"inputBVector"];
[caFilter setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:1] forKey:@"inputAVector"];
[caFilter setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:0] forKey:@"inputBiasVector"];
- [caFilter setName:@"sepiaFilter"];
+ [caFilter setName:filterName];
[array.get() addObject:caFilter];
break;
}
@@ -771,7 +773,7 @@ void PlatformCALayer::setFilters(const FilterOperations& filters)
CIFilter* caFilter = [CIFilter filterWithName:@"CIColorControls"];
[caFilter setDefaults];
[caFilter setValue:[NSNumber numberWithFloat:op->amount()] forKey:@"inputSaturation"];
- [caFilter setName:@"saturateFilter"];
+ [caFilter setName:filterName];
[array.get() addObject:caFilter];
break;
}
@@ -782,7 +784,7 @@ void PlatformCALayer::setFilters(const FilterOperations& filters)
// The CIHueAdjust value is in radians
[caFilter setValue:[NSNumber numberWithFloat:op->amount() * M_PI * 2 / 360] forKey:@"inputAngle"];
- [caFilter setName:@"hueRotateFilter"];
+ [caFilter setName:filterName];
[array.get() addObject:caFilter];
break;
}
@@ -798,7 +800,7 @@ void PlatformCALayer::setFilters(const FilterOperations& filters)
[caFilter setValue:[CIVector vectorWithX:0 Y:0 Z:multiplier W:0] forKey:@"inputBVector"];
[caFilter setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:1] forKey:@"inputAVector"];
[caFilter setValue:[CIVector vectorWithX:op->amount() Y:op->amount() Z:op->amount() W:0] forKey:@"inputBiasVector"];
- [caFilter setName:@"invertFilter"];
+ [caFilter setName:filterName];
[array.get() addObject:caFilter];
break;
}
@@ -812,7 +814,7 @@ void PlatformCALayer::setFilters(const FilterOperations& filters)
[caFilter setValue:[CIVector vectorWithX:0 Y:0 Z:1 W:0] forKey:@"inputBVector"];
[caFilter setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:op->amount()] forKey:@"inputAVector"];
[caFilter setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:0] forKey:@"inputBiasVector"];
- [caFilter setName:@"opacityFilter"];
+ [caFilter setName:filterName];
[array.get() addObject:caFilter];
break;
}
@@ -822,7 +824,25 @@ void PlatformCALayer::setFilters(const FilterOperations& filters)
CIFilter* caFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
[caFilter setDefaults];
[caFilter setValue:[NSNumber numberWithFloat:op->stdDeviation().calcFloatValue(0)] forKey:@"inputRadius"];
- [caFilter setName:@"blurFilter"];
+ [caFilter setName:filterName];
+ [array.get() addObject:caFilter];
+ break;
+ }
+ case FilterOperation::CONTRAST: {
+ const BasicComponentTransferFilterOperation* op = static_cast<const BasicComponentTransferFilterOperation*>(filterOperation);
+ CIFilter* caFilter = [CIFilter filterWithName:@"CIColorControls"];
+ [caFilter setDefaults];
+ [caFilter setValue:[NSNumber numberWithFloat:op->amount()] forKey:@"inputContrast"];
+ [caFilter setName:filterName];
+ [array.get() addObject:caFilter];
+ break;
+ }
+ case FilterOperation::BRIGHTNESS: {
+ const BasicComponentTransferFilterOperation* op = static_cast<const BasicComponentTransferFilterOperation*>(filterOperation);
+ CIFilter* caFilter = [CIFilter filterWithName:@"CIColorControls"];
+ [caFilter setDefaults];
+ [caFilter setValue:[NSNumber numberWithFloat:op->amount()] forKey:@"inputBrightness"];
+ [caFilter setName:filterName];
[array.get() addObject:caFilter];
break;
}
@@ -936,6 +956,15 @@ void PlatformCALayer::setContentsScale(float value)
#endif
}
+void PlatformCALayer::visibleRectChanged()
+{
+ if (m_layerType != LayerTypeTileCacheLayer)
+ return;
+
+ WebTileCacheLayer *tileCacheLayer = static_cast<WebTileCacheLayer *>(m_layer.get());
+ [tileCacheLayer visibleRectChanged];
+}
+
#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
void PlatformCALayer::synchronouslyDisplayTilesInRect(const FloatRect& rect)
{
diff --git a/Source/WebCore/platform/graphics/ca/mac/TileCache.h b/Source/WebCore/platform/graphics/ca/mac/TileCache.h
index 5c788f9fb..2c290e500 100644
--- a/Source/WebCore/platform/graphics/ca/mac/TileCache.h
+++ b/Source/WebCore/platform/graphics/ca/mac/TileCache.h
@@ -26,23 +26,21 @@
#ifndef TileCache_h
#define TileCache_h
+#include "IntPointHash.h"
#include "IntSize.h"
+#include "Timer.h"
+#include <wtf/HashMap.h>
#include <wtf/Noncopyable.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/RetainPtr.h>
-#ifdef __OBJC__
-@class CALayer;
-@class WebTileCacheLayer;
-@class WebTileLayer;
-#else
-class CALayer;
-class WebTileCacheLayer;
-class WebTileLayer;
-#endif
+OBJC_CLASS CALayer;
+OBJC_CLASS WebTileCacheLayer;
+OBJC_CLASS WebTileLayer;
namespace WebCore {
+class FloatRect;
class IntPoint;
class IntRect;
@@ -53,30 +51,55 @@ public:
static PassOwnPtr<TileCache> create(WebTileCacheLayer*, const IntSize& tileSize);
void tileCacheLayerBoundsChanged();
+
+ void setNeedsDisplay();
void setNeedsDisplayInRect(const IntRect&);
void drawLayer(WebTileLayer*, CGContextRef);
+ bool acceleratesDrawing() const { return m_acceleratesDrawing; }
+ void setAcceleratesDrawing(bool);
+
CALayer *tileContainerLayer() const { return m_tileContainerLayer.get(); }
+ void visibleRectChanged();
+
+ 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);
+ FloatRect visibleRect() const;
IntRect bounds() const;
- void getTileRangeForRect(const IntRect&, IntPoint& topLeft, IntPoint& bottomRight);
- IntSize numTilesForGridSize(const IntSize&) const;
- void resizeTileGrid(const IntSize& numTiles);
+ IntRect rectForTileIndex(const TileIndex&) const;
+ void getTileIndexRangeForRect(const IntRect&, TileIndex& topLeft, TileIndex& bottomRight);
- WebTileLayer* tileLayerAtPosition(const IntPoint&) const;
+ void scheduleTileRevalidation();
+ void tileRevalidationTimerFired(Timer<TileCache>*);
+ void revalidateTiles();
+
+ WebTileLayer* tileLayerAtIndex(const TileIndex&) const;
RetainPtr<WebTileLayer> createTileLayer();
+ bool shouldShowRepaintCounters() const;
+
WebTileCacheLayer* m_tileCacheLayer;
+ RetainPtr<CALayer> m_tileContainerLayer;
const IntSize m_tileSize;
- RetainPtr<CALayer> m_tileContainerLayer;
+ typedef HashMap<TileIndex, RetainPtr<WebTileLayer> > TileMap;
+ TileMap m_tiles;
+ Timer<TileCache> m_tileRevalidationTimer;
+
+ bool m_acceleratesDrawing;
- // Number of tiles in each dimension.
- IntSize m_numTilesInGrid;
+ RetainPtr<CGColorRef> m_tileDebugBorderColor;
+ float m_tileDebugBorderWidth;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/ca/mac/TileCache.mm b/Source/WebCore/platform/graphics/ca/mac/TileCache.mm
index dc791f836..2550b3dd6 100644
--- a/Source/WebCore/platform/graphics/ca/mac/TileCache.mm
+++ b/Source/WebCore/platform/graphics/ca/mac/TileCache.mm
@@ -35,6 +35,12 @@
using namespace std;
+#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+@interface CALayer (WebCALayerDetails)
+- (void)setAcceleratesDrawing:(BOOL)flag;
+@end
+#endif
+
namespace WebCore {
PassOwnPtr<TileCache> TileCache::create(WebTileCacheLayer* tileCacheLayer, const IntSize& tileSize)
@@ -44,8 +50,11 @@ PassOwnPtr<TileCache> TileCache::create(WebTileCacheLayer* tileCacheLayer, const
TileCache::TileCache(WebTileCacheLayer* tileCacheLayer, const IntSize& tileSize)
: m_tileCacheLayer(tileCacheLayer)
- , m_tileSize(tileSize)
, m_tileContainerLayer(adoptCF([[CALayer alloc] init]))
+ , m_tileSize(tileSize)
+ , m_tileRevalidationTimer(this, &TileCache::tileRevalidationTimerFired)
+ , m_acceleratesDrawing(false)
+ , m_tileDebugBorderWidth(0)
{
[CATransaction begin];
[CATransaction setDisableActions:YES];
@@ -55,31 +64,48 @@ TileCache::TileCache(WebTileCacheLayer* tileCacheLayer, const IntSize& tileSize)
void TileCache::tileCacheLayerBoundsChanged()
{
- IntSize numTilesInGrid = numTilesForGridSize(bounds().size());
- if (numTilesInGrid == m_numTilesInGrid)
+ if (m_tiles.isEmpty()) {
+ // We must revalidate immediately instead of using a timer when there are
+ // no tiles to avoid a flash when transitioning from one page to another.
+ revalidateTiles();
return;
+ }
- resizeTileGrid(numTilesInGrid);
+ scheduleTileRevalidation();
+}
+
+void TileCache::setNeedsDisplay()
+{
+ setNeedsDisplayInRect(IntRect(0, 0, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()));
}
void TileCache::setNeedsDisplayInRect(const IntRect& rect)
{
- if (m_numTilesInGrid.isZero())
+ if (m_tiles.isEmpty())
return;
// Find the tiles that need to be invalidated.
- IntPoint topLeft;
- IntPoint bottomRight;
- getTileRangeForRect(rect, topLeft, bottomRight);
+ TileIndex topLeft;
+ TileIndex bottomRight;
+ getTileIndexRangeForRect(rect, topLeft, bottomRight);
for (int y = topLeft.y(); y <= bottomRight.y(); ++y) {
for (int x = topLeft.x(); x <= bottomRight.x(); ++x) {
- WebTileLayer* tileLayer = tileLayerAtPosition(IntPoint(x, y));
+ WebTileLayer* tileLayer = tileLayerAtIndex(TileIndex(x, y));
+ if (!tileLayer)
+ continue;
CGRect tileRect = [m_tileCacheLayer convertRect:rect toLayer:tileLayer];
+ if (CGRectIsEmpty(tileRect))
+ continue;
+
+ [tileLayer setNeedsDisplayInRect:tileRect];
- if (!CGRectIsEmpty(tileRect))
- [tileLayer setNeedsDisplayInRect:tileRect];
+ if (shouldShowRepaintCounters()) {
+ CGRect bounds = [tileLayer bounds];
+ CGRect indicatorRect = CGRectMake(bounds.origin.x, bounds.origin.y, 52, 27);
+ [tileLayer setNeedsDisplayInRect:indicatorRect];
+ }
}
}
}
@@ -97,6 +123,99 @@ void TileCache::drawLayer(WebTileLayer* layer, CGContextRef context)
drawLayerContents(context, layer, platformLayer);
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);
+}
+
+void TileCache::setAcceleratesDrawing(bool acceleratesDrawing)
+{
+#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+ if (m_acceleratesDrawing == acceleratesDrawing)
+ return;
+
+ m_acceleratesDrawing = acceleratesDrawing;
+
+ for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it)
+ [it->second.get() setAcceleratesDrawing:m_acceleratesDrawing];
+#else
+ UNUSED_PARAM(acceleratesDrawing);
+#endif
+}
+
+void TileCache::visibleRectChanged()
+{
+ scheduleTileRevalidation();
+}
+
+void TileCache::setTileDebugBorderWidth(float borderWidth)
+{
+ if (m_tileDebugBorderWidth == borderWidth)
+ return;
+
+ m_tileDebugBorderWidth = borderWidth;
+ for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it)
+ [it->second.get() setBorderWidth:m_tileDebugBorderWidth];
+}
+
+void TileCache::setTileDebugBorderColor(CGColorRef borderColor)
+{
+ if (m_tileDebugBorderColor == borderColor)
+ return;
+
+ m_tileDebugBorderColor = borderColor;
+ for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it)
+ [it->second.get() setBorderColor:m_tileDebugBorderColor.get()];
+}
+
+FloatRect TileCache::visibleRect() const
+{
+ CGRect rect = [m_tileCacheLayer bounds];
+
+ CALayer *layer = m_tileCacheLayer;
+ CALayer *superlayer = [layer superlayer];
+
+ while (superlayer) {
+ CGRect rectInSuperlayerCoordinates = [superlayer convertRect:rect fromLayer:layer];
+
+ if ([superlayer masksToBounds])
+ rect = CGRectIntersection([superlayer bounds], rectInSuperlayerCoordinates);
+ else
+ rect = rectInSuperlayerCoordinates;
+
+ layer = superlayer;
+ superlayer = [layer superlayer];
+ }
+
+ return [m_tileCacheLayer convertRect:rect fromLayer:layer];
}
IntRect TileCache::bounds() const
@@ -104,60 +223,104 @@ IntRect TileCache::bounds() const
return IntRect(IntPoint(), IntSize([m_tileCacheLayer bounds].size));
}
-void TileCache::getTileRangeForRect(const IntRect& rect, IntPoint& topLeft, IntPoint& bottomRight)
+IntRect TileCache::rectForTileIndex(const TileIndex& tileIndex) const
{
- topLeft.setX(max(rect.x() / m_tileSize.width(), 0));
- topLeft.setY(max(rect.y() / m_tileSize.height(), 0));
- bottomRight.setX(min(rect.maxX() / m_tileSize.width(), m_numTilesInGrid.width() - 1));
- bottomRight.setY(min(rect.maxY() / m_tileSize.height(), m_numTilesInGrid.height() - 1));
+ return IntRect(IntPoint(tileIndex.x() * m_tileSize.width(), tileIndex.y() * m_tileSize.height()), m_tileSize);
}
-IntSize TileCache::numTilesForGridSize(const IntSize& gridSize) const
+void TileCache::getTileIndexRangeForRect(const IntRect& rect, TileIndex& topLeft, TileIndex& bottomRight)
{
- int numXTiles = ceil(static_cast<double>(gridSize.width()) / m_tileSize.width());
- int numYTiles = ceil(static_cast<double>(gridSize.height()) / m_tileSize.height());
+ IntRect clampedRect = intersection(rect, bounds());
- return IntSize(numXTiles, numYTiles);
+ topLeft.setX(max(clampedRect.x() / m_tileSize.width(), 0));
+ topLeft.setY(max(clampedRect.y() / m_tileSize.height(), 0));
+ bottomRight.setX(max(clampedRect.maxX() / m_tileSize.width(), 0));
+ bottomRight.setY(max(clampedRect.maxY() / m_tileSize.height(), 0));
}
-void TileCache::resizeTileGrid(const IntSize& numTilesInGrid)
+void TileCache::scheduleTileRevalidation()
{
- [CATransaction begin];
- [CATransaction setDisableActions:YES];
+ if (m_tileRevalidationTimer.isActive())
+ return;
+
+ m_tileRevalidationTimer.startOneShot(0);
+}
+
+void TileCache::tileRevalidationTimerFired(Timer<TileCache>*)
+{
+ revalidateTiles();
+}
+
+void TileCache::revalidateTiles()
+{
+ IntRect tileCoverageRect = enclosingIntRect(visibleRect());
+ if (tileCoverageRect.isEmpty())
+ return;
+
+ // 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());
+
+ Vector<TileIndex> tilesToRemove;
+
+ for (TileMap::iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) {
+ const TileIndex& tileIndex = it->first;
+
+ WebTileLayer* tileLayer = it->second.get();
+
+ if (!rectForTileIndex(tileIndex).intersects(tileCoverageRect)) {
+ // Remove this layer.
+ [tileLayer removeFromSuperlayer];
+ [tileLayer setTileCache:0];
- RetainPtr<NSMutableArray> newSublayers = adoptNS([[NSMutableArray alloc] initWithCapacity:numTilesInGrid.width() * numTilesInGrid.height()]);
+ tilesToRemove.append(tileIndex);
+ }
+ }
+
+ // FIXME: Be more clever about which tiles to remove. We might not want to remove all
+ // the tiles that are outside the coverage rect. When we know that we're going to be scrolling up,
+ // we might want to remove the ones below the coverage rect but keep the ones above.
+ for (size_t i = 0; i < tilesToRemove.size(); ++i)
+ m_tiles.remove(tilesToRemove[i]);
- for (int y = 0; y < numTilesInGrid.height(); ++y) {
- for (int x = 0; x < numTilesInGrid.width(); ++x) {
- RetainPtr<WebTileLayer> tileLayer;
+ TileIndex topLeft;
+ TileIndex bottomRight;
+ getTileIndexRangeForRect(tileCoverageRect, topLeft, bottomRight);
- if (x < m_numTilesInGrid.width() && y < m_numTilesInGrid.height()) {
- // We can reuse the tile layer at this position.
- tileLayer = tileLayerAtPosition(IntPoint(x, y));
- } else {
- tileLayer = createTileLayer();
+ bool didCreateNewTiles = false;
+
+ 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;
}
+ didCreateNewTiles = true;
+
+ tileLayer = createTileLayer();
+
+ [tileLayer.get() setNeedsDisplay];
[tileLayer.get() setPosition:CGPointMake(x * m_tileSize.width(), y * m_tileSize.height())];
- [newSublayers.get() addObject:tileLayer.get()];
+ [m_tileContainerLayer.get() addSublayer:tileLayer.get()];
}
}
- // FIXME: Make sure to call setTileCache:0 on the layers that get thrown away here.
- [m_tileContainerLayer.get() setSublayers:newSublayers.get()];
- m_numTilesInGrid = numTilesInGrid;
+ if (!didCreateNewTiles)
+ return;
- [CATransaction commit];
+ PlatformCALayer* platformLayer = PlatformCALayer::platformCALayer(m_tileCacheLayer);
+ platformLayer->owner()->platformCALayerDidCreateTiles();
}
-WebTileLayer* TileCache::tileLayerAtPosition(const IntPoint& point) const
+WebTileLayer* TileCache::tileLayerAtIndex(const TileIndex& index) const
{
- ASSERT(point.x() >= 0);
- ASSERT(point.x() <= m_numTilesInGrid.width());
- ASSERT(point.y() >= 0);
- ASSERT(point.y() <= m_numTilesInGrid.height());
-
- return [[m_tileContainerLayer.get() sublayers] objectAtIndex:point.y() * m_numTilesInGrid.width() + point.x()];
+ return m_tiles.get(index).get();
}
RetainPtr<WebTileLayer> TileCache::createTileLayer()
@@ -166,8 +329,28 @@ RetainPtr<WebTileLayer> TileCache::createTileLayer()
[layer.get() setBounds:CGRectMake(0, 0, m_tileSize.width(), m_tileSize.height())];
[layer.get() setAnchorPoint:CGPointZero];
[layer.get() setTileCache:this];
+ [layer.get() setBorderColor:m_tileDebugBorderColor.get()];
+ [layer.get() setBorderWidth:m_tileDebugBorderWidth];
+
+#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+ [layer.get() setAcceleratesDrawing:m_acceleratesDrawing];
+#endif
return layer;
}
+bool TileCache::shouldShowRepaintCounters() const
+{
+ PlatformCALayer* platformLayer = PlatformCALayer::platformCALayer(m_tileCacheLayer);
+ if (!platformLayer)
+ return false;
+
+ WebCore::PlatformCALayerClient* layerContents = platformLayer->owner();
+ ASSERT(layerContents);
+ if (!layerContents)
+ return false;
+
+ return layerContents->platformCALayerShowRepaintCounter();
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.h b/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.h
index 77126c0aa..5dc64983e 100644
--- a/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.h
+++ b/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.h
@@ -35,4 +35,6 @@ namespace WebCore {
}
- (CALayer *)tileContainerLayer;
+- (void)visibleRectChanged;
+
@end
diff --git a/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm b/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm
index 3e292e9cf..059f1777c 100644
--- a/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm
+++ b/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm
@@ -52,14 +52,54 @@ using namespace WebCore;
_tileCache->tileCacheLayerBoundsChanged();
}
+- (void)setNeedsDisplay
+{
+ _tileCache->setNeedsDisplay();
+}
+
- (void)setNeedsDisplayInRect:(CGRect)rect
{
_tileCache->setNeedsDisplayInRect(enclosingIntRect(rect));
}
+- (void)setAcceleratesDrawing:(BOOL)acceleratesDrawing
+{
+ _tileCache->setAcceleratesDrawing(acceleratesDrawing);
+}
+
+- (BOOL)acceleratesDrawing
+{
+ return _tileCache->acceleratesDrawing();
+}
+
- (CALayer *)tileContainerLayer
{
return _tileCache->tileContainerLayer();
}
+- (void)visibleRectChanged
+{
+ _tileCache->visibleRectChanged();
+}
+
+- (CGColorRef)borderColor
+{
+ return _tileCache->tileDebugBorderColor();
+}
+
+- (void)setBorderColor:(CGColorRef)borderColor
+{
+ _tileCache->setTileDebugBorderColor(borderColor);
+}
+
+- (CGFloat)borderWidth
+{
+ return _tileCache->tileDebugBorderWidth();
+}
+
+- (void)setBorderWidth:(CGFloat)borderWidth
+{
+ _tileCache->setTileDebugBorderWidth(borderWidth);
+}
+
@end
diff --git a/Source/WebCore/platform/graphics/ca/mac/WebTileLayer.h b/Source/WebCore/platform/graphics/ca/mac/WebTileLayer.h
index cb52c1cbd..577e34a39 100644
--- a/Source/WebCore/platform/graphics/ca/mac/WebTileLayer.h
+++ b/Source/WebCore/platform/graphics/ca/mac/WebTileLayer.h
@@ -32,8 +32,11 @@ namespace WebCore {
@interface WebTileLayer : CALayer {
WebCore::TileCache* _tileCache;
+ unsigned _repaintCount;
}
+
- (void)setTileCache:(WebCore::TileCache*)tileCache;
+- (unsigned)incrementRepaintCount;
@end
diff --git a/Source/WebCore/platform/graphics/ca/mac/WebTileLayer.mm b/Source/WebCore/platform/graphics/ca/mac/WebTileLayer.mm
index ef42d7c67..6f7c85c08 100644
--- a/Source/WebCore/platform/graphics/ca/mac/WebTileLayer.mm
+++ b/Source/WebCore/platform/graphics/ca/mac/WebTileLayer.mm
@@ -52,5 +52,10 @@ using namespace WebCore;
_tileCache = tileCache;
}
+- (unsigned)incrementRepaintCount
+{
+ return ++_repaintCount;
+}
+
@end
diff --git a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp
index 060f2490d..4a9a33599 100644
--- a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp
+++ b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp
@@ -620,6 +620,10 @@ void PlatformCALayer::setContentsScale(float)
{
}
+void PlatformCALayer::visibleRectChanged()
+{
+}
+
#ifndef NDEBUG
static void printIndent(int indent)
{
diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp
index b5e1231d2..c85aab416 100644
--- a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp
@@ -115,6 +115,10 @@ void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>)
{
}
+void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<ErrorMessageCallback>)
+{
+}
+
#if USE(ACCELERATED_COMPOSITING)
PlatformLayer* GraphicsContext3D::platformLayer() const
{
diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
index 81c5ae47c..f4d2ea22c 100644
--- a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
@@ -54,7 +54,7 @@ ImageBufferData::ImageBufferData(const IntSize& size)
{
}
-ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode, DeferralMode, bool& success)
: m_data(size)
, m_size(size)
{
diff --git a/Source/WebCore/platform/graphics/cairo/OpenGLShims.cpp b/Source/WebCore/platform/graphics/cairo/OpenGLShims.cpp
index 28316e0e4..2994cd2c9 100644
--- a/Source/WebCore/platform/graphics/cairo/OpenGLShims.cpp
+++ b/Source/WebCore/platform/graphics/cairo/OpenGLShims.cpp
@@ -42,7 +42,7 @@ OpenGLFunctionTable* openGLFunctionTable()
#if PLATFORM(QT)
static void* getProcAddress(const char* procName)
{
- return QGLContext::currentContext()->getProcAddress(QString::fromLatin1(procName));
+ return reinterpret_cast<void*>(QGLContext::currentContext()->getProcAddress(QString::fromLatin1(procName)));
}
#else
typedef void* (*glGetProcAddressType) (const char* procName);
diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index 20ffba646..4b6192f16 100644
--- a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -630,9 +630,12 @@ void GraphicsContext::fillPath(const Path& path)
if (m_state.fillGradient) {
if (hasShadow()) {
FloatRect rect = path.fastBoundingRect();
- CGLayerRef layer = CGLayerCreateWithContext(context, CGSizeMake(rect.width(), rect.height()), 0);
+ FloatSize layerSize = getCTM().mapSize(rect.size());
+
+ CGLayerRef layer = CGLayerCreateWithContext(context, layerSize, 0);
CGContextRef layerContext = CGLayerGetContext(layer);
+ CGContextScaleCTM(layerContext, layerSize.width() / rect.width(), layerSize.height() / rect.height());
CGContextTranslateCTM(layerContext, -rect.x(), -rect.y());
CGContextBeginPath(layerContext);
CGContextAddPath(layerContext, path.platformPath());
@@ -644,7 +647,7 @@ void GraphicsContext::fillPath(const Path& path)
CGContextClip(layerContext);
m_state.fillGradient->paint(layerContext);
- CGContextDrawLayerAtPoint(context, CGPointMake(rect.x(), rect.y()), layer);
+ CGContextDrawLayerInRect(context, rect, layer);
CGLayerRelease(layer);
} else {
CGContextBeginPath(context);
@@ -687,10 +690,12 @@ void GraphicsContext::strokePath(const Path& path)
FloatRect rect = path.fastBoundingRect();
float lineWidth = strokeThickness();
float doubleLineWidth = lineWidth * 2;
- float layerWidth = ceilf(rect.width() + doubleLineWidth);
- float layerHeight = ceilf(rect.height() + doubleLineWidth);
+ float adjustedWidth = ceilf(rect.width() + doubleLineWidth);
+ float adjustedHeight = ceilf(rect.height() + doubleLineWidth);
+
+ FloatSize layerSize = getCTM().mapSize(FloatSize(adjustedWidth, adjustedHeight));
- CGLayerRef layer = CGLayerCreateWithContext(context, CGSizeMake(layerWidth, layerHeight), 0);
+ CGLayerRef layer = CGLayerCreateWithContext(context, layerSize, 0);
CGContextRef layerContext = CGLayerGetContext(layer);
CGContextSetLineWidth(layerContext, lineWidth);
@@ -699,6 +704,7 @@ void GraphicsContext::strokePath(const Path& path)
// the layer on the left and top sides.
float translationX = lineWidth - rect.x();
float translationY = lineWidth - rect.y();
+ CGContextScaleCTM(layerContext, layerSize.width() / adjustedWidth, layerSize.height() / adjustedHeight);
CGContextTranslateCTM(layerContext, translationX, translationY);
CGContextAddPath(layerContext, path.platformPath());
@@ -709,7 +715,7 @@ void GraphicsContext::strokePath(const Path& path)
float destinationX = roundf(rect.x() - lineWidth);
float destinationY = roundf(rect.y() - lineWidth);
- CGContextDrawLayerAtPoint(context, CGPointMake(destinationX, destinationY), layer);
+ CGContextDrawLayerInRect(context, CGRectMake(destinationX, destinationY, adjustedWidth, adjustedHeight), layer);
CGLayerRelease(layer);
} else {
CGContextSaveGState(context);
@@ -747,16 +753,19 @@ void GraphicsContext::fillRect(const FloatRect& rect)
if (m_state.fillGradient) {
CGContextSaveGState(context);
if (hasShadow()) {
- CGLayerRef layer = CGLayerCreateWithContext(context, CGSizeMake(rect.width(), rect.height()), 0);
+ FloatSize layerSize = getCTM().mapSize(rect.size());
+
+ CGLayerRef layer = CGLayerCreateWithContext(context, layerSize, 0);
CGContextRef layerContext = CGLayerGetContext(layer);
+ CGContextScaleCTM(layerContext, layerSize.width() / rect.width(), layerSize.height() / rect.height());
CGContextTranslateCTM(layerContext, -rect.x(), -rect.y());
CGContextAddRect(layerContext, rect);
CGContextClip(layerContext);
CGContextConcatCTM(layerContext, m_state.fillGradient->gradientSpaceTransform());
m_state.fillGradient->paint(layerContext);
- CGContextDrawLayerAtPoint(context, CGPointMake(rect.x(), rect.y()), layer);
+ CGContextDrawLayerInRect(context, rect, layer);
CGLayerRelease(layer);
} else {
CGContextClipToRect(context, rect);
@@ -1027,6 +1036,7 @@ void GraphicsContext::setPlatformShadow(const FloatSize& offset, float blur, con
blurRadius = min(blurRadius, narrowPrecisionToCGFloat(1000.0));
+#if defined(BUILDING_ON_SNOW_LEOPARD) || defined(BUILDING_ON_LION)
if (!isAcceleratedContext()) {
// Work around <rdar://problem/5539388> by ensuring that the offsets will get truncated
// to the desired integer. Also see: <rdar://problem/10056277>
@@ -1041,6 +1051,7 @@ void GraphicsContext::setPlatformShadow(const FloatSize& offset, float blur, con
else if (yOffset < 0)
yOffset -= extraShadowOffset;
}
+#endif
// Check for an invalid color, as this means that the color was not set for the shadow
// and we should therefore just use the default shadow color.
@@ -1088,9 +1099,11 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
if (m_state.strokeGradient) {
if (hasShadow()) {
const float doubleLineWidth = lineWidth * 2;
- const float layerWidth = ceilf(rect.width() + doubleLineWidth);
- const float layerHeight = ceilf(rect.height() + doubleLineWidth);
- CGLayerRef layer = CGLayerCreateWithContext(context, CGSizeMake(layerWidth, layerHeight), 0);
+ float adjustedWidth = ceilf(rect.width() + doubleLineWidth);
+ float adjustedHeight = ceilf(rect.height() + doubleLineWidth);
+ FloatSize layerSize = getCTM().mapSize(FloatSize(adjustedWidth, adjustedHeight));
+
+ CGLayerRef layer = CGLayerCreateWithContext(context, layerSize, 0);
CGContextRef layerContext = CGLayerGetContext(layer);
m_state.strokeThickness = lineWidth;
@@ -1101,6 +1114,7 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
// the layer on the left and top sides.
const float translationX = lineWidth - rect.x();
const float translationY = lineWidth - rect.y();
+ CGContextScaleCTM(layerContext, layerSize.width() / adjustedWidth, layerSize.height() / adjustedHeight);
CGContextTranslateCTM(layerContext, translationX, translationY);
CGContextAddRect(layerContext, rect);
@@ -1111,7 +1125,7 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
const float destinationX = roundf(rect.x() - lineWidth);
const float destinationY = roundf(rect.y() - lineWidth);
- CGContextDrawLayerAtPoint(context, CGPointMake(destinationX, destinationY), layer);
+ CGContextDrawLayerInRect(context, CGRectMake(destinationX, destinationY, adjustedWidth, adjustedHeight), layer);
CGLayerRelease(layer);
} else {
CGContextSaveGState(context);
@@ -1589,6 +1603,9 @@ void GraphicsContext::setPlatformCompositeOperation(CompositeOperator mode)
case CompositePlusLighter:
target = kCGBlendModePlusLighter;
break;
+ case CompositeDifference:
+ target = kCGBlendModeDifference;
+ break;
}
CGContextSetBlendMode(platformContext(), target);
}
diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
index 355f475e2..02ba8cffd 100644
--- a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -38,7 +38,6 @@
#include <math.h>
#include <wtf/Assertions.h>
#include <wtf/CheckedArithmetic.h>
-#include <wtf/CurrentTime.h>
#include <wtf/MainThread.h>
#include <wtf/OwnArrayPtr.h>
#include <wtf/RetainPtr.h>
@@ -53,6 +52,10 @@
#include <IOSurface/IOSurface.h>
#endif
+#if defined(BUILDING_ON_LION)
+#include <wtf/CurrentTime.h>
+#endif
+
using namespace std;
namespace WebCore {
@@ -104,7 +107,7 @@ static void releaseImageData(void*, const void* data, size_t)
fastFree(const_cast<void*>(data));
}
-ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, RenderingMode renderingMode, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, RenderingMode renderingMode, DeferralMode, bool& success)
: m_data(size)
, m_size(size)
{
@@ -169,7 +172,9 @@ ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, Render
m_context->scale(FloatSize(1, -1));
m_context->translate(0, -height.unsafeGet());
m_context->setIsAcceleratedContext(accelerateRendering);
+#if defined(BUILDING_ON_LION)
m_data.m_lastFlushTime = currentTimeMS();
+#endif
success = true;
}
@@ -184,6 +189,7 @@ size_t ImageBuffer::dataSize() const
GraphicsContext* ImageBuffer::context() const
{
+#if defined(BUILDING_ON_LION)
// Force a flush if last flush was more than 20ms ago
if (m_context->isAcceleratedContext()) {
double elapsedTime = currentTimeMS() - m_data.m_lastFlushTime;
@@ -195,6 +201,7 @@ GraphicsContext* ImageBuffer::context() const
m_data.m_lastFlushTime = currentTimeMS();
}
}
+#endif
return m_context.get();
}
@@ -228,7 +235,9 @@ NativeImagePtr ImageBuffer::copyNativeImage(BackingStoreCopy copyBehavior) const
#if USE(IOSURFACE_CANVAS_BACKING_STORE)
else {
image = wkIOSurfaceContextCreateImage(context()->platformContext());
+#if defined(BUILDING_ON_LION)
m_data.m_lastFlushTime = currentTimeMS();
+#endif
}
#endif
@@ -241,7 +250,7 @@ void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace,
ColorSpace colorSpace = (destContext == m_context) ? ColorSpaceDeviceRGB : styleColorSpace;
RetainPtr<CGImageRef> image;
- if (destContext == m_context)
+ if (destContext == m_context || destContext->isAcceleratedContext())
image.adoptCF(copyNativeImage(CopyBackingStore)); // Drawing into our own buffer, need to deep copy.
else
image.adoptCF(copyNativeImage(DontCopyBackingStore));
@@ -249,19 +258,19 @@ void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace,
destContext->drawNativeImage(image.get(), m_size, colorSpace, destRect, srcRect, op);
}
-void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
+void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
{
if (!m_context->isAcceleratedContext()) {
- if (context == m_context) {
+ if (destContext == m_context || destContext->isAcceleratedContext()) {
RefPtr<Image> copy = copyImage(CopyBackingStore); // Drawing into our own buffer, need to deep copy.
- copy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
+ copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
} else {
RefPtr<Image> imageForRendering = copyImage(DontCopyBackingStore);
- imageForRendering->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
+ imageForRendering->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
}
} else {
RefPtr<Image> copy = copyImage(CopyBackingStore);
- copy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
+ copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
}
}
@@ -280,7 +289,9 @@ PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect)
{
if (m_context->isAcceleratedContext()) {
CGContextFlush(context()->platformContext());
+#if defined(BUILDING_ON_LION)
m_data.m_lastFlushTime = currentTimeMS();
+#endif
}
return m_data.getData(rect, m_size, m_context->isAcceleratedContext(), true);
}
@@ -289,7 +300,9 @@ PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect
{
if (m_context->isAcceleratedContext()) {
CGContextFlush(context()->platformContext());
+#if defined(BUILDING_ON_LION)
m_data.m_lastFlushTime = currentTimeMS();
+#endif
}
return m_data.getData(rect, m_size, m_context->isAcceleratedContext(), false);
}
@@ -298,7 +311,9 @@ void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sou
{
if (m_context->isAcceleratedContext()) {
CGContextFlush(context()->platformContext());
+#if defined(BUILDING_ON_LION)
m_data.m_lastFlushTime = currentTimeMS();
+#endif
}
m_data.putData(source, sourceSize, sourceRect, destPoint, m_size, m_context->isAcceleratedContext(), true);
}
@@ -307,7 +322,9 @@ void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& so
{
if (m_context->isAcceleratedContext()) {
CGContextFlush(context()->platformContext());
+#if defined(BUILDING_ON_LION)
m_data.m_lastFlushTime = currentTimeMS();
+#endif
}
m_data.putData(source, sourceSize, sourceRect, destPoint, m_size, m_context->isAcceleratedContext(), false);
}
diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h b/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h
index 61d92ad0f..a148de6c2 100644
--- a/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h
+++ b/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h
@@ -54,7 +54,9 @@ public:
Checked<unsigned, RecordOverflow> m_bytesPerRow;
CGColorSpaceRef m_colorSpace;
RetainPtr<IOSurfaceRef> m_surface;
+#if defined(BUILDING_ON_LION)
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);
diff --git a/Source/WebCore/platform/graphics/cg/PathCG.cpp b/Source/WebCore/platform/graphics/cg/PathCG.cpp
index 93faf80f2..01f7ffe41 100644
--- a/Source/WebCore/platform/graphics/cg/PathCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/PathCG.cpp
@@ -41,59 +41,6 @@
namespace WebCore {
-// A class to provide an isEmpty test that considers a one-element path with only a MoveTo element
-// to be empty. This behavior is consistent with other platforms in WebKit, and is needed to prevent
-// incorrect (according to the spec) linecap stroking for zero length paths in SVG.
-class PathIsEmptyOrSingleMoveTester {
-public:
- PathIsEmptyOrSingleMoveTester() : m_moveCount(0) { }
-
- bool isEmpty() const
- {
- return m_moveCount <= 1;
- }
-
- static void testPathElement(void* info, const CGPathElement* element)
- {
- PathIsEmptyOrSingleMoveTester* tester = static_cast<PathIsEmptyOrSingleMoveTester*>(info);
- if (element->type == kCGPathElementMoveToPoint)
- ++tester->m_moveCount;
- else {
- // Any non move element implies a non-empty path; set the count to 2 to force
- // isEmpty to return false.
- tester->m_moveCount = 2;
- }
- }
-
-private:
- // Any non-move-to element, or more than one move-to element, will make the count >= 2.
- unsigned m_moveCount;
-};
-
-// Paths with only move-to elements do not draw under any circumstances, so their bound should
-// be empty. Currently, CoreGraphics returns non-empty bounds for such paths. Radar 10450621
-// tracks this. This class reports paths that have only move-to elements, allowing the
-// bounding box code to work around the CoreGraphics problem.
-class PathHasOnlyMoveToTester {
-public:
- PathHasOnlyMoveToTester() : m_hasSeenOnlyMoveTo(true) { }
-
- bool hasOnlyMoveTo() const
- {
- return m_hasSeenOnlyMoveTo;
- }
-
- static void testPathElement(void* info, const CGPathElement* element)
- {
- PathHasOnlyMoveToTester* tester = static_cast<PathHasOnlyMoveToTester*>(info);
- if (tester->m_hasSeenOnlyMoveTo && element->type != kCGPathElementMoveToPoint)
- tester->m_hasSeenOnlyMoveTo = false;
- }
-
-private:
- bool m_hasSeenOnlyMoveTo;
-};
-
static size_t putBytesNowhere(void*, const void*, size_t count)
{
return count;
@@ -218,32 +165,20 @@ FloatRect Path::boundingRect() const
{
// CGPathGetBoundingBox includes the path's control points, CGPathGetPathBoundingBox
// does not, but only exists on 10.6 and above.
- // A bug in CoreGraphics leads to an incorrect bound on paths containing only move-to elements
- // with a linecap style that is non-butt. All paths with only move-to elements (regardless of
- // linecap) are effectively empty for bounding purposes and here we make it so.
- PathHasOnlyMoveToTester tester;
- CGPathApply(m_path, &tester, PathHasOnlyMoveToTester::testPathElement);
- if (tester.hasOnlyMoveTo())
- return FloatRect(0, 0, 0, 0);
+ CGRect bound = CGRectZero;
#if !defined(BUILDING_ON_LEOPARD)
- return CGPathGetPathBoundingBox(m_path);
+ bound = CGPathGetPathBoundingBox(m_path);
#else
- return CGPathGetBoundingBox(m_path);
+ bound = CGPathGetBoundingBox(m_path);
#endif
+ return CGRectIsNull(bound) ? CGRectZero : bound;
}
FloatRect Path::fastBoundingRect() const
{
- // A bug in CoreGraphics leads to an incorrect bound on paths containing only move-to elements
- // with a linecap style that is non-butt. All paths with only move-to elements (regardless of
- // linecap) are effectively empty for bounding purposes and here we make it so.
- PathHasOnlyMoveToTester tester;
- CGPathApply(m_path, &tester, PathHasOnlyMoveToTester::testPathElement);
- if (tester.hasOnlyMoveTo())
- return FloatRect(0, 0, 0, 0);
-
- return CGPathGetBoundingBox(m_path);
+ CGRect bound = CGPathGetBoundingBox(m_path);
+ return CGRectIsNull(bound) ? CGRectZero : bound;
}
FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const
@@ -263,7 +198,7 @@ FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const
CGRect box = CGContextIsPathEmpty(context) ? CGRectZero : CGContextGetPathBoundingBox(context);
CGContextRestoreGState(context);
- return box;
+ return CGRectIsNull(box) ? CGRectZero : box;
}
void Path::moveTo(const FloatPoint& point)
@@ -321,18 +256,12 @@ void Path::clear()
bool Path::isEmpty() const
{
- // The SVG rendering code that uses this method relies on paths with a single move-to
- // element, and nothing else, as being empty. Until that code is refactored to avoid
- // the dependence on isEmpty, we match the behavior of other platforms.
- // When the SVG code is refactored, we could use CGPathIsEmpty(m_path);
- PathIsEmptyOrSingleMoveTester tester;
- CGPathApply(m_path, &tester, PathIsEmptyOrSingleMoveTester::testPathElement);
- return tester.isEmpty();
+ return CGPathIsEmpty(m_path);
}
bool Path::hasCurrentPoint() const
{
- return !CGPathIsEmpty(m_path);
+ return !isEmpty();
}
FloatPoint Path::currentPoint() const
@@ -386,7 +315,7 @@ void Path::apply(void* info, PathApplierFunction function) const
void Path::transform(const AffineTransform& transform)
{
- if (transform.isIdentity() || CGPathIsEmpty(m_path))
+ if (transform.isIdentity() || isEmpty())
return;
CGMutablePathRef path = CGPathCreateMutable();
diff --git a/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp
index dd931913f..0d97e52ae 100644
--- a/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp
+++ b/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp
@@ -32,6 +32,7 @@
#include "LayerPainterChromium.h"
#include "PlatformColor.h"
+#include "PlatformContextSkia.h"
namespace WebCore {
@@ -77,10 +78,12 @@ LayerTextureUpdater::SampledTexelFormat BitmapCanvasLayerTextureUpdater::sampled
LayerTextureUpdater::SampledTexelFormatRGBA : LayerTextureUpdater::SampledTexelFormatBGRA;
}
-void BitmapCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, int borderTexels, float contentsScale)
+void BitmapCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, int borderTexels, float contentsScale, IntRect* resultingOpaqueRect)
{
m_texSubImage.setSubImageSize(tileSize);
+ bool layerIsOpaque = m_canvas.opaque();
+
m_canvas.resize(contentRect.size());
// Assumption: if a tiler is using border texels, then it is because the
// layer is likely to be filtered or transformed. Because of it might be
@@ -88,7 +91,11 @@ void BitmapCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect
PlatformCanvas::Painter::TextOption textOption =
borderTexels ? PlatformCanvas::Painter::GrayscaleText : PlatformCanvas::Painter::SubpixelText;
PlatformCanvas::Painter canvasPainter(&m_canvas, textOption);
+ canvasPainter.skiaContext()->setTrackOpaqueRegion(!layerIsOpaque);
paintContents(*canvasPainter.context(), contentRect, contentsScale);
+
+ if (!layerIsOpaque)
+ *resultingOpaqueRect = canvasPainter.skiaContext()->opaqueRegion().asRect();
}
void BitmapCanvasLayerTextureUpdater::updateTextureRect(GraphicsContext3D* context, TextureAllocator* allocator, ManagedTexture* texture, const IntRect& sourceRect, const IntRect& destRect)
@@ -99,5 +106,10 @@ void BitmapCanvasLayerTextureUpdater::updateTextureRect(GraphicsContext3D* conte
m_texSubImage.upload(locker.pixels(), contentRect(), sourceRect, destRect, texture->format(), context);
}
+void BitmapCanvasLayerTextureUpdater::setOpaque(bool opaque)
+{
+ m_canvas.setOpaque(opaque);
+}
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.h
index 153dd2c3c..4e162295b 100644
--- a/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.h
+++ b/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.h
@@ -60,9 +60,11 @@ 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);
+ 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);
+
private:
BitmapCanvasLayerTextureUpdater(PassOwnPtr<LayerPainterChromium>, bool useMapTexSubImage);
diff --git a/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp
index 8221dd2e5..e2ab79838 100644
--- a/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp
+++ b/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp
@@ -86,10 +86,10 @@ LayerTextureUpdater::SampledTexelFormat BitmapSkPictureCanvasLayerTextureUpdater
LayerTextureUpdater::SampledTexelFormatRGBA : LayerTextureUpdater::SampledTexelFormatBGRA;
}
-void BitmapSkPictureCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, int borderTexels, float contentsScale)
+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);
+ SkPictureCanvasLayerTextureUpdater::prepareToUpdate(contentRect, tileSize, borderTexels, contentsScale, resultingOpaqueRect);
}
void BitmapSkPictureCanvasLayerTextureUpdater::paintContentsRect(SkCanvas* canvas, const IntRect& sourceRect)
diff --git a/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h
index 6f2f10d9b..1c564cdc1 100644
--- a/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h
+++ b/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h
@@ -59,7 +59,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);
+ 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 3408aa56b..6c778bf74 100644
--- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
@@ -41,9 +41,9 @@
#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h" // For the GLC() macro
-#if USE(SKIA)
#include "GrContext.h"
-#endif
+#include "SkCanvas.h"
+#include "SkDevice.h"
namespace WebCore {
@@ -53,12 +53,13 @@ PassRefPtr<Canvas2DLayerChromium> Canvas2DLayerChromium::create(GraphicsContext3
}
Canvas2DLayerChromium::Canvas2DLayerChromium(GraphicsContext3D* context, const IntSize& size)
- : CanvasLayerChromium(0)
+ : CanvasLayerChromium()
, m_context(context)
, m_size(size)
, m_backTextureId(0)
, m_fbo(0)
, m_useDoubleBuffering(CCProxy::hasImplThread())
+ , m_canvas(0)
{
if (m_useDoubleBuffering)
GLC(m_context, m_fbo = m_context->createFramebuffer());
@@ -81,6 +82,7 @@ void Canvas2DLayerChromium::contentChanged()
if (layerTreeHost())
layerTreeHost()->startRateLimiter(m_context);
+ m_updateRect = FloatRect(FloatPoint(), contentBounds());
setNeedsDisplay();
}
@@ -90,7 +92,12 @@ bool Canvas2DLayerChromium::drawsContent() const
&& m_context && (m_context->getExtensions()->getGraphicsResetStatusARB() == GraphicsContext3D::NO_ERROR);
}
-void Canvas2DLayerChromium::paintContentsIfDirty()
+void Canvas2DLayerChromium::setCanvas(SkCanvas* canvas)
+{
+ m_canvas = canvas;
+}
+
+void Canvas2DLayerChromium::paintContentsIfDirty(const Region& /* occludedScreenSpace */)
{
if (!drawsContent())
return;
@@ -106,11 +113,15 @@ void Canvas2DLayerChromium::paintContentsIfDirty()
bool success = m_context->makeContextCurrent();
ASSERT_UNUSED(success, success);
-#if USE(SKIA)
+ // FIXME: Replace this block of skia code with m_canvas->flush, when that
+ // API becomes available.
+ // https://bugs.webkit.org/show_bug.cgi?id=77463
+ if (m_canvas)
+ m_canvas->getDevice()->accessRenderTarget(); // Triggers execution of pending draw operations.
+
GrContext* grContext = m_context->grContext();
if (grContext)
grContext->flush();
-#endif
m_context->flush();
}
diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
index 83615a1f2..877224f41 100644
--- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
@@ -37,9 +37,12 @@
#include "CanvasLayerChromium.h"
#include "ManagedTexture.h"
+class SkCanvas;
+
namespace WebCore {
class GraphicsContext3D;
+class Region;
// A layer containing an accelerated 2d canvas
class Canvas2DLayerChromium : public CanvasLayerChromium {
@@ -52,7 +55,7 @@ public:
virtual void contentChanged();
virtual bool drawsContent() const;
- virtual void paintContentsIfDirty();
+ virtual void paintContentsIfDirty(const Region& occludedScreenSpace);
virtual void setLayerTreeHost(CCLayerTreeHost*);
virtual void updateCompositorResources(GraphicsContext3D*, CCTextureUpdater&);
@@ -60,6 +63,8 @@ public:
virtual void unreserveContentsTexture();
virtual void cleanupResources();
+ void setCanvas(SkCanvas*);
+
private:
Canvas2DLayerChromium(GraphicsContext3D*, const IntSize&);
@@ -76,6 +81,7 @@ private:
// synchronize its draws with the canvas updates.
bool m_useDoubleBuffering;
OwnPtr<ManagedTexture> m_frontTexture;
+ SkCanvas* m_canvas;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp
index c51008cb4..181ba4e58 100644
--- a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp
@@ -40,8 +40,8 @@
namespace WebCore {
-CanvasLayerChromium::CanvasLayerChromium(CCLayerDelegate* delegate)
- : LayerChromium(delegate)
+CanvasLayerChromium::CanvasLayerChromium()
+ : LayerChromium()
{
}
diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h
index f4072f5d0..9e8ce7d8c 100644
--- a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h
@@ -44,7 +44,7 @@ public:
virtual PassRefPtr<CCLayerImpl> createCCLayerImpl();
protected:
- explicit CanvasLayerChromium(CCLayerDelegate*);
+ CanvasLayerChromium();
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
index ef105b53f..34303110f 100644
--- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
@@ -48,7 +48,7 @@ namespace WebCore {
class ContentLayerPainter : public LayerPainterChromium {
WTF_MAKE_NONCOPYABLE(ContentLayerPainter);
public:
- static PassOwnPtr<ContentLayerPainter> create(CCLayerDelegate* delegate)
+ static PassOwnPtr<ContentLayerPainter> create(ContentLayerDelegate* delegate)
{
return adoptPtr(new ContentLayerPainter(delegate));
}
@@ -65,21 +65,22 @@ public:
PlatformSupport::histogramCustomCounts("Renderer4.AccelContentPaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30);
}
private:
- explicit ContentLayerPainter(CCLayerDelegate* delegate)
+ explicit ContentLayerPainter(ContentLayerDelegate* delegate)
: m_delegate(delegate)
{
}
- CCLayerDelegate* m_delegate;
+ ContentLayerDelegate* m_delegate;
};
-PassRefPtr<ContentLayerChromium> ContentLayerChromium::create(CCLayerDelegate* delegate)
+PassRefPtr<ContentLayerChromium> ContentLayerChromium::create(ContentLayerDelegate* delegate)
{
return adoptRef(new ContentLayerChromium(delegate));
}
-ContentLayerChromium::ContentLayerChromium(CCLayerDelegate* delegate)
- : TiledLayerChromium(delegate)
+ContentLayerChromium::ContentLayerChromium(ContentLayerDelegate* delegate)
+ : TiledLayerChromium()
+ , m_delegate(delegate)
{
}
@@ -87,7 +88,12 @@ ContentLayerChromium::~ContentLayerChromium()
{
}
-void ContentLayerChromium::paintContentsIfDirty()
+bool ContentLayerChromium::drawsContent() const
+{
+ return TiledLayerChromium::drawsContent() && m_delegate;
+}
+
+void ContentLayerChromium::paintContentsIfDirty(const Region& /* occludedScreenSpace */)
{
updateTileSizeAndTilingOption();
@@ -119,18 +125,21 @@ void ContentLayerChromium::idlePaintContentsIfDirty()
void ContentLayerChromium::createTextureUpdater(const CCLayerTreeHost* host)
{
#if USE(SKIA)
- if (host->settings().acceleratePainting) {
+ if (host->settings().acceleratePainting)
m_textureUpdater = FrameBufferSkPictureCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_delegate));
- return;
- }
-
- if (host->settings().perTilePainting) {
+ else if (host->settings().perTilePainting)
m_textureUpdater = BitmapSkPictureCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_delegate), host->layerRendererCapabilities().usingMapSub);
- return;
- }
+ else
#endif // USE(SKIA)
+ m_textureUpdater = BitmapCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_delegate), host->layerRendererCapabilities().usingMapSub);
+ m_textureUpdater->setOpaque(opaque());
+}
- m_textureUpdater = BitmapCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_delegate), host->layerRendererCapabilities().usingMapSub);
+void ContentLayerChromium::setOpaque(bool opaque)
+{
+ LayerChromium::setOpaque(opaque);
+ if (m_textureUpdater)
+ m_textureUpdater->setOpaque(opaque);
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h
index c3df1c20c..5eff6a3d6 100644
--- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h
@@ -41,24 +41,38 @@ namespace WebCore {
class LayerTilerChromium;
class LayerTextureUpdater;
+class Region;
+
+class ContentLayerDelegate {
+public:
+ virtual ~ContentLayerDelegate() { }
+ virtual void paintContents(GraphicsContext&, const IntRect& clip) = 0;
+};
// A Layer that requires a GraphicsContext to render its contents.
class ContentLayerChromium : public TiledLayerChromium {
public:
- static PassRefPtr<ContentLayerChromium> create(CCLayerDelegate*);
+ static PassRefPtr<ContentLayerChromium> create(ContentLayerDelegate*);
virtual ~ContentLayerChromium();
- virtual void paintContentsIfDirty();
+ void clearDelegate() { m_delegate = 0; }
+
+ virtual bool drawsContent() const;
+ virtual void paintContentsIfDirty(const Region& occludedScreenSpace);
virtual void idlePaintContentsIfDirty();
+ virtual void setOpaque(bool);
+
protected:
- explicit ContentLayerChromium(CCLayerDelegate*);
+ explicit ContentLayerChromium(ContentLayerDelegate*);
+
private:
virtual void createTextureUpdater(const CCLayerTreeHost*);
virtual LayerTextureUpdater* textureUpdater() const { return m_textureUpdater.get(); }
+ ContentLayerDelegate* m_delegate;
RefPtr<LayerTextureUpdater> m_textureUpdater;
};
diff --git a/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
index ead6aa3a2..551adf769 100644
--- a/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
@@ -143,7 +143,7 @@ void DrawingBuffer::publishToPlatformLayer()
PlatformLayer* DrawingBuffer::platformLayer()
{
if (!m_platformLayer) {
- m_platformLayer = WebGLLayerChromium::create(0);
+ m_platformLayer = WebGLLayerChromium::create();
m_platformLayer->setDrawingBuffer(this);
m_platformLayer->setOpaque(!m_context->getContextAttributes().alpha);
}
diff --git a/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
index 9f5bd4919..a50e6abc4 100644
--- a/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006, 2007 Apple Computer, Inc.
- * Copyright (c) 2006, 2007, 2008, 2009 Google Inc. All rights reserved.
+ * Copyright (c) 2006, 2007, 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
@@ -36,6 +36,7 @@
#include "FontUtilsChromiumWin.h"
#include "HashMap.h"
#include "HashSet.h"
+#include "HWndDC.h"
#include "PlatformSupport.h"
#include "SimpleFontData.h"
#include <unicode/uniset.h>
@@ -241,7 +242,7 @@ static HFONT createFontIndirectAndGetWinName(const String& family, LOGFONT* winf
if (!hfont)
return 0;
- HDC dc = GetDC(0);
+ HWndDC dc(0);
HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(dc, hfont));
WCHAR name[LF_FACESIZE];
unsigned resultLength = GetTextFace(dc, LF_FACESIZE, name);
@@ -249,7 +250,6 @@ static HFONT createFontIndirectAndGetWinName(const String& family, LOGFONT* winf
resultLength--; // ignore the null terminator
SelectObject(dc, oldFont);
- ReleaseDC(0, dc);
*winName = String(name, resultLength);
return hfont;
}
@@ -279,7 +279,7 @@ static bool fontContainsCharacter(const FontPlatformData* fontData,
return it->second->contains(character);
HFONT hfont = fontData->hfont();
- HDC hdc = GetDC(0);
+ HWndDC hdc(0);
HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(hdc, hfont));
int count = GetFontUnicodeRanges(hdc, 0);
if (!count && PlatformSupport::ensureFontLoaded(hfont))
@@ -287,7 +287,6 @@ static bool fontContainsCharacter(const FontPlatformData* fontData,
if (!count) {
LOG_ERROR("Unable to get the font unicode range after second attempt");
SelectObject(hdc, oldFont);
- ReleaseDC(0, hdc);
return true;
}
@@ -299,7 +298,6 @@ static bool fontContainsCharacter(const FontPlatformData* fontData,
count = GetFontUnicodeRanges(hdc, glyphset);
ASSERT(count > 0);
SelectObject(hdc, oldFont);
- ReleaseDC(0, hdc);
// FIXME: consider doing either of the following two:
// 1) port back ICU 4.0's faster look-up code for UnicodeSet
@@ -571,11 +569,10 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& desc
// both GetTextFace() and EnumFontFamilies() return the localized name. So,
// FontCache::createFontPlatformData() does not filter out the fonts
// returned by this EnumFontFamilies() call.
- HDC dc = GetDC(0);
+ HWndDC dc(0);
if (dc) {
GetLastResortFallbackFontProcData procData(this, &description, shouldRetain, fallbackFontName);
EnumFontFamilies(dc, 0, getLastResortFallbackFontProc, reinterpret_cast<LPARAM>(&procData));
- ReleaseDC(0, dc);
if (procData.m_fontData)
return procData.m_fontData;
@@ -587,7 +584,7 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& desc
void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks)
{
- HDC hdc = GetDC(0);
+ HWndDC hdc(0);
LOGFONT logFont;
logFont.lfCharSet = DEFAULT_CHARSET;
@@ -599,8 +596,6 @@ void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigne
TraitsInFamilyProcData procData(familyName);
EnumFontFamiliesEx(hdc, &logFont, traitsInFamilyEnumProc, reinterpret_cast<LPARAM>(&procData), 0);
copyToVector(procData.m_traitsMasks, traitsMasks);
-
- ReleaseDC(0, hdc);
}
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp
index 46f9ecdad..a89a18232 100644
--- a/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006, 2007 Apple Computer, Inc.
- * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
+ * Copyright (c) 2006, 2007, 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
@@ -36,6 +36,7 @@
#include <objidl.h>
#include <mlang.h>
+#include "HWndDC.h"
#include "PlatformSupport.h"
#include "SkTypeface_win.h"
#include "SkiaFontWin.h"
@@ -161,7 +162,7 @@ SCRIPT_FONTPROPERTIES* FontPlatformData::scriptFontProperties() const
HRESULT result = ScriptGetFontProperties(0, scriptCache(),
m_scriptFontProperties);
if (result == E_PENDING) {
- HDC dc = GetDC(0);
+ HWndDC dc(0);
HGDIOBJ oldFont = SelectObject(dc, hfont());
HRESULT hr = ScriptGetFontProperties(dc, scriptCache(),
m_scriptFontProperties);
@@ -177,7 +178,6 @@ SCRIPT_FONTPROPERTIES* FontPlatformData::scriptFontProperties() const
}
SelectObject(dc, oldFont);
- ReleaseDC(0, dc);
}
}
return m_scriptFontProperties;
diff --git a/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
index a4798ddd5..711b896ac 100644
--- a/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2007, 2008, 2009, 2010, Google Inc. All rights reserved.
+ * Copyright (c) 2006, 2007, 2008, 2009, 2010, 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,6 +33,7 @@
#include <limits>
+#include "HWndDC.h"
#include "PlatformString.h"
#include "UniscribeHelper.h"
#include <unicode/locid.h>
@@ -50,14 +51,13 @@ bool isFontPresent(const UChar* fontName)
fontName);
if (!hfont)
return false;
- HDC dc = GetDC(0);
+ HWndDC dc(0);
HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(dc, hfont));
WCHAR actualFontName[LF_FACESIZE];
GetTextFace(dc, LF_FACESIZE, actualFontName);
actualFontName[LF_FACESIZE - 1] = 0;
SelectObject(dc, oldFont);
DeleteObject(hfont);
- ReleaseDC(0, dc);
// We don't have to worry about East Asian fonts with locale-dependent
// names here for now.
return !wcscmp(fontName, actualFontName);
@@ -241,24 +241,22 @@ const int kUndefinedAscent = std::numeric_limits<int>::min();
// kUndefinedAscent is returned, instead.
int getAscent(HFONT hfont)
{
- HDC dc = GetDC(0);
+ HWndDC dc(0);
HGDIOBJ oldFont = SelectObject(dc, hfont);
TEXTMETRIC tm;
BOOL gotMetrics = GetTextMetrics(dc, &tm);
SelectObject(dc, oldFont);
- ReleaseDC(0, dc);
return gotMetrics ? tm.tmAscent : kUndefinedAscent;
}
WORD getSpaceGlyph(HFONT hfont)
{
- HDC dc = GetDC(0);
+ HWndDC dc(0);
HGDIOBJ oldFont = SelectObject(dc, hfont);
WCHAR space = L' ';
WORD spaceGlyph = 0;
GetGlyphIndices(dc, &space, 1, &spaceGlyph, 0);
SelectObject(dc, oldFont);
- ReleaseDC(0, dc);
return spaceGlyph;
}
diff --git a/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp
index f5ab22156..f5425b9df 100644
--- a/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.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
@@ -34,6 +34,7 @@
#include "Font.h"
#include "GlyphPageTreeNode.h"
+#include "HWndDC.h"
#include "PlatformSupport.h"
#include "SimpleFontData.h"
#include "SystemInfo.h"
@@ -49,15 +50,27 @@ static void fillEmptyGlyphs(GlyphPage* page)
page->setGlyphDataForIndex(i, 0, 0);
}
-// Lazily initializes space glyph
-static Glyph initSpaceGlyph(HDC dc, Glyph* spaceGlyph)
+// Convert characters to glyph ids by GetGlyphIndices(), during which, we
+// ensure the font is loaded in memory to make it work in a sandboxed process.
+static bool getGlyphIndices(HFONT font, HDC dc, const UChar* characters, unsigned charactersLength, WORD* glyphBuffer, DWORD flag)
{
- if (*spaceGlyph)
- return *spaceGlyph;
+ if (GetGlyphIndices(dc, characters, charactersLength, glyphBuffer, flag) != GDI_ERROR)
+ return true;
+ if (PlatformSupport::ensureFontLoaded(font)) {
+ if (GetGlyphIndices(dc, characters, charactersLength, glyphBuffer, flag) != GDI_ERROR)
+ return true;
+ // FIXME: Handle gracefully the error if this call also fails.
+ // See http://crbug.com/6401
+ LOG_ERROR("Unable to get the glyph indices after second attempt");
+ }
+ return false;
+}
+// Initializes space glyph
+static bool initSpaceGlyph(HFONT font, HDC dc, Glyph* spaceGlyph)
+{
static wchar_t space = ' ';
- GetGlyphIndices(dc, &space, 1, spaceGlyph, 0);
- return *spaceGlyph;
+ return getGlyphIndices(font, dc, &space, 1, spaceGlyph, 0);
}
// Fills |length| glyphs starting at |offset| in a |page| in the Basic
@@ -68,27 +81,25 @@ static bool fillBMPGlyphs(unsigned offset,
unsigned length,
UChar* buffer,
GlyphPage* page,
- const SimpleFontData* fontData,
- bool recurse)
+ const SimpleFontData* fontData)
{
- HDC dc = GetDC((HWND)0);
+ HWndDC dc(0);
HGDIOBJ oldFont = SelectObject(dc, fontData->platformData().hfont());
TEXTMETRIC tm = {0};
if (!GetTextMetrics(dc, &tm)) {
- SelectObject(dc, oldFont);
- ReleaseDC(0, dc);
+ if (PlatformSupport::ensureFontLoaded(fontData->platformData().hfont())) {
+ if (!GetTextMetrics(dc, &tm)) {
+ // FIXME: Handle gracefully the error if this call also fails.
+ // See http://crbug.com/6401
+ LOG_ERROR("Unable to get the text metrics after second attempt");
- if (recurse) {
- if (PlatformSupport::ensureFontLoaded(fontData->platformData().hfont()))
- return fillBMPGlyphs(offset, length, buffer, page, fontData, false);
-
- fillEmptyGlyphs(page);
- return false;
+ SelectObject(dc, oldFont);
+ fillEmptyGlyphs(page);
+ return false;
+ }
} else {
- // FIXME: Handle gracefully the error if this call also fails.
- // See http://crbug.com/6401
- LOG_ERROR("Unable to get the text metrics after second attempt");
+ SelectObject(dc, oldFont);
fillEmptyGlyphs(page);
return false;
}
@@ -128,7 +139,11 @@ static bool fillBMPGlyphs(unsigned offset,
// Also according to Jungshik and Hironori's suggestion and modification
// we treat turetype and raster Font as different way when windows version
// is less than Vista.
- GetGlyphIndices(dc, buffer, length, localGlyphBuffer, GGI_MARK_NONEXISTING_GLYPHS);
+ if (!getGlyphIndices(fontData->platformData().hfont(), dc, buffer, length, localGlyphBuffer, GGI_MARK_NONEXISTING_GLYPHS)) {
+ SelectObject(dc, oldFont);
+ fillEmptyGlyphs(page);
+ return false;
+ }
// Copy the output to the GlyphPage
bool haveGlyphs = false;
@@ -138,6 +153,7 @@ static bool fillBMPGlyphs(unsigned offset,
invalidGlyph = 0x1F;
Glyph spaceGlyph = 0; // Glyph for a space. Lazily filled.
+ bool spaceGlyphInitialized = false;
for (unsigned i = 0; i < length; i++) {
UChar c = buffer[i];
@@ -149,7 +165,12 @@ static bool fillBMPGlyphs(unsigned offset,
if (Font::treatAsSpace(c)) {
// Hard code the glyph indices for characters that should be
// treated like spaces.
- glyph = initSpaceGlyph(dc, &spaceGlyph);
+ if (!spaceGlyphInitialized) {
+ // If initSpaceGlyph fails, spaceGlyph stays 0 (= glyph is not present).
+ initSpaceGlyph(fontData->platformData().hfont(), dc, &spaceGlyph);
+ spaceGlyphInitialized = true;
+ }
+ glyph = spaceGlyph;
} else if (glyph == invalidGlyph) {
// WebKit expects both the glyph index and FontData
// pointer to be 0 if the glyph is not present
@@ -161,7 +182,6 @@ static bool fillBMPGlyphs(unsigned offset,
}
SelectObject(dc, oldFont);
- ReleaseDC(0, dc);
return haveGlyphs;
}
@@ -222,7 +242,7 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* characterBuffer,
// FIXME: Add assertions to make sure that buffer is entirely in BMP
// or entirely in non-BMP.
if (bufferLength == length)
- return fillBMPGlyphs(offset, length, characterBuffer, this, fontData, true);
+ return fillBMPGlyphs(offset, length, characterBuffer, this, fontData);
if (bufferLength == 2 * length) {
// A non-BMP input buffer will be twice as long as output glyph buffer
diff --git a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
index 67e05f8dc..31a5118ff 100644
--- a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
@@ -82,17 +82,13 @@ GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client)
GraphicsLayerChromium::~GraphicsLayerChromium()
{
if (m_layer) {
- m_layer->setDelegate(0);
+ m_layer->clearDelegate();
m_layer->clearRenderSurface();
}
- if (m_contentsLayer) {
- m_contentsLayer->setDelegate(0);
+ if (m_contentsLayer)
m_contentsLayer->clearRenderSurface();
- }
- if (m_transformLayer) {
- m_transformLayer->setDelegate(0);
+ if (m_transformLayer)
m_transformLayer->clearRenderSurface();
- }
}
void GraphicsLayerChromium::setName(const String& inName)
@@ -327,7 +323,7 @@ void GraphicsLayerChromium::setContentsToImage(Image* image)
bool childrenChanged = false;
if (image) {
if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForImage) {
- RefPtr<ImageLayerChromium> imageLayer = ImageLayerChromium::create(this);
+ RefPtr<ImageLayerChromium> imageLayer = ImageLayerChromium::create();
setupContentsLayer(imageLayer.get());
m_contentsLayerPurpose = ContentsLayerForImage;
childrenChanged = true;
@@ -353,7 +349,6 @@ void GraphicsLayerChromium::setContentsToCanvas(PlatformLayer* platformLayer)
{
bool childrenChanged = false;
if (platformLayer) {
- platformLayer->setDelegate(this);
if (m_contentsLayer.get() != platformLayer) {
setupContentsLayer(platformLayer);
m_contentsLayerPurpose = ContentsLayerForCanvas;
@@ -383,7 +378,6 @@ void GraphicsLayerChromium::setContentsToMedia(PlatformLayer* layer)
m_contentsLayerPurpose = ContentsLayerForVideo;
childrenChanged = true;
}
- layer->setDelegate(this);
layer->setNeedsDisplay();
updateContentsRect();
} else {
@@ -528,7 +522,7 @@ void GraphicsLayerChromium::updateLayerPreserves3D()
{
if (m_preserves3D && !m_transformLayer) {
// Create the transform layer.
- m_transformLayer = LayerChromium::create(this);
+ m_transformLayer = LayerChromium::create();
m_transformLayer->setPreserves3D(true);
// Copy the position from this layer.
diff --git a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
index dfa109d3e..39b367b9d 100644
--- a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
@@ -33,6 +33,7 @@
#if USE(ACCELERATED_COMPOSITING)
+#include "ContentLayerChromium.h"
#include "LayerChromium.h"
#include "GraphicsContext.h"
#include "GraphicsLayer.h"
@@ -41,7 +42,7 @@ namespace WebCore {
class LayerChromium;
-class GraphicsLayerChromium : public GraphicsLayer, public CCLayerDelegate {
+class GraphicsLayerChromium : public GraphicsLayer, public ContentLayerDelegate {
public:
GraphicsLayerChromium(GraphicsLayerClient*);
virtual ~GraphicsLayerChromium();
@@ -97,7 +98,7 @@ public:
virtual void setDebugBorder(const Color&, float borderWidth);
virtual void deviceOrPageScaleFactorChanged();
- // The following functions implement the CCLayerDelegate interface.
+ // ContentLayerDelegate implementation.
virtual void paintContents(GraphicsContext&, const IntRect& clip);
// Exposed for tests.
@@ -130,7 +131,7 @@ private:
String m_nameBase;
- RefPtr<LayerChromium> m_layer;
+ RefPtr<ContentLayerChromium> m_layer;
RefPtr<LayerChromium> m_transformLayer;
RefPtr<LayerChromium> m_contentsLayer;
diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
index a0fb35f02..831cbe809 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 */)
+ virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, int /* borderTexels */, float /* contentsScale */, IntRect* /* resultingOpaqueRect */)
{
m_texSubImage.setSubImageSize(tileSize);
}
@@ -129,13 +129,13 @@ private:
LayerTextureSubImage m_texSubImage;
};
-PassRefPtr<ImageLayerChromium> ImageLayerChromium::create(CCLayerDelegate* delegate)
+PassRefPtr<ImageLayerChromium> ImageLayerChromium::create()
{
- return adoptRef(new ImageLayerChromium(delegate));
+ return adoptRef(new ImageLayerChromium());
}
-ImageLayerChromium::ImageLayerChromium(CCLayerDelegate* delegate)
- : TiledLayerChromium(delegate)
+ImageLayerChromium::ImageLayerChromium()
+ : TiledLayerChromium()
, m_imageForCurrentFrame(0)
{
}
@@ -158,7 +158,7 @@ void ImageLayerChromium::setContents(Image* contents)
setNeedsDisplay();
}
-void ImageLayerChromium::paintContentsIfDirty()
+void ImageLayerChromium::paintContentsIfDirty(const Region& /* occludedScreenSpace */)
{
if (m_needsDisplay) {
m_textureUpdater->updateFromImage(m_contents->nativeImageForCurrentFrame());
diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h
index 1259a663c..ab5c1b27b 100644
--- a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h
@@ -45,21 +45,22 @@ namespace WebCore {
class Image;
class ImageLayerTextureUpdater;
+class Region;
// A Layer that contains only an Image element.
class ImageLayerChromium : public TiledLayerChromium {
public:
- static PassRefPtr<ImageLayerChromium> create(CCLayerDelegate*);
+ static PassRefPtr<ImageLayerChromium> create();
virtual ~ImageLayerChromium();
virtual bool drawsContent() const;
- virtual void paintContentsIfDirty();
+ virtual void paintContentsIfDirty(const Region& occludedScreenSpace);
virtual bool needsContentsScale() const;
void setContents(Image* image);
private:
- explicit ImageLayerChromium(CCLayerDelegate*);
+ ImageLayerChromium();
virtual void createTextureUpdater(const CCLayerTreeHost*);
void setTilingOption(TilingOption);
diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
index 2df05b59c..b2f70141b 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
@@ -39,6 +39,7 @@
#include "NativeImageSkia.h"
#include "PlatformContextSkia.h"
#endif
+#include "Region.h"
#include "RenderLayerBacking.h"
#include "TextStream.h"
#include "skia/ext/platform_canvas.h"
@@ -49,19 +50,19 @@ using namespace std;
static int s_nextLayerId = 1;
-PassRefPtr<LayerChromium> LayerChromium::create(CCLayerDelegate* delegate)
+PassRefPtr<LayerChromium> LayerChromium::create()
{
- return adoptRef(new LayerChromium(delegate));
+ return adoptRef(new LayerChromium());
}
-LayerChromium::LayerChromium(CCLayerDelegate* delegate)
- : m_delegate(delegate)
- , m_needsDisplay(false)
+LayerChromium::LayerChromium()
+ : m_needsDisplay(false)
, m_layerId(s_nextLayerId++)
, m_parent(0)
, m_scrollable(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)
@@ -72,6 +73,7 @@ LayerChromium::LayerChromium(CCLayerDelegate* delegate)
, m_usesLayerClipping(false)
, m_isNonCompositedContent(false)
, m_preserves3D(false)
+ , m_alwaysReserveTextures(false)
, m_replicaLayer(0)
, m_drawOpacity(0)
, m_targetRenderSurface(0)
@@ -94,19 +96,6 @@ void LayerChromium::cleanupResources()
{
}
-void LayerChromium::cleanupResourcesRecursive()
-{
- for (size_t i = 0; i < children().size(); ++i)
- children()[i]->cleanupResourcesRecursive();
-
- if (maskLayer())
- maskLayer()->cleanupResourcesRecursive();
- if (replicaLayer())
- replicaLayer()->cleanupResourcesRecursive();
-
- cleanupResources();
-}
-
void LayerChromium::setIsNonCompositedContent(bool isNonCompositedContent)
{
m_isNonCompositedContent = isNonCompositedContent;
@@ -285,6 +274,14 @@ 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)
@@ -330,7 +327,7 @@ void LayerChromium::setOpaque(bool opaque)
if (m_opaque == opaque)
return;
m_opaque = opaque;
- setNeedsCommit();
+ setNeedsDisplay();
}
void LayerChromium::setPosition(const FloatPoint& position)
@@ -416,6 +413,7 @@ 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);
@@ -472,6 +470,35 @@ void LayerChromium::setContentsScale(float contentsScale)
setNeedsDisplay();
}
+TransformationMatrix LayerChromium::contentToScreenSpaceTransform() const
+{
+ IntSize boundsInLayerSpace = bounds();
+ IntSize boundsInContentSpace = contentBounds();
+
+ TransformationMatrix transform = screenSpaceTransform();
+
+ // 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;
+}
+
+void LayerChromium::addSelfToOccludedScreenSpace(Region& occludedScreenSpace)
+{
+ if (!opaque() || drawOpacity() != 1 || !isPaintedAxisAlignedInScreen())
+ return;
+
+ FloatRect targetRect = contentToScreenSpaceTransform().mapRect(FloatRect(visibleLayerRect()));
+ occludedScreenSpace.unite(enclosedIntRect(targetRect));
+}
+
+bool LayerChromium::isPaintedAxisAlignedInScreen() const
+{
+ FloatQuad quad = contentToScreenSpaceTransform().mapQuad(FloatQuad(visibleLayerRect()));
+ return quad.isRectilinear();
+}
+
void LayerChromium::createRenderSurface()
{
ASSERT(!m_renderSurface);
diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerChromium.h
index 87f5056f3..764f73015 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.h
@@ -55,19 +55,14 @@ class CCLayerImpl;
class CCLayerTreeHost;
class CCTextureUpdater;
class GraphicsContext3D;
-
-class CCLayerDelegate {
-public:
- virtual ~CCLayerDelegate() { }
- virtual void paintContents(GraphicsContext&, const IntRect& clip) = 0;
-};
+class Region;
// Base class for composited layers. Special layer types are derived from
// this class.
class LayerChromium : public RefCounted<LayerChromium> {
friend class LayerTilerChromium;
public:
- static PassRefPtr<LayerChromium> create(CCLayerDelegate*);
+ static PassRefPtr<LayerChromium> create();
virtual ~LayerChromium();
@@ -90,6 +85,9 @@ 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(); }
@@ -110,7 +108,7 @@ public:
void setOpacity(float);
float opacity() const { return m_opacity; }
- void setOpaque(bool);
+ virtual void setOpaque(bool);
bool opaque() const { return m_opaque; }
void setPosition(const FloatPoint&);
@@ -149,8 +147,6 @@ public:
virtual void setLayerTreeHost(CCLayerTreeHost*);
- void setDelegate(CCLayerDelegate* delegate) { m_delegate = delegate; }
-
void setIsDrawable(bool);
void setReplicaLayer(LayerChromium*);
@@ -158,7 +154,7 @@ public:
// These methods typically need to be overwritten by derived classes.
virtual bool drawsContent() const { return m_isDrawable; }
- virtual void paintContentsIfDirty() { }
+ virtual void paintContentsIfDirty(const Region& /* occludedScreenSpace */) { }
virtual void idlePaintContentsIfDirty() { }
virtual void updateCompositorResources(GraphicsContext3D*, CCTextureUpdater&) { }
virtual void setIsMask(bool) { }
@@ -187,8 +183,10 @@ public:
void setClipRect(const IntRect& clipRect) { m_clipRect = clipRect; }
RenderSurfaceChromium* targetRenderSurface() const { return m_targetRenderSurface; }
void setTargetRenderSurface(RenderSurfaceChromium* surface) { m_targetRenderSurface = surface; }
+ // 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; }
+ // This moves from layer space, with origin the top left to screen space with origin in the top left
const TransformationMatrix& screenSpaceTransform() const { return m_screenSpaceTransform; }
void setScreenSpaceTransform(const TransformationMatrix& matrix) { m_screenSpaceTransform = matrix; }
const IntRect& drawableContentRect() const { return m_drawableContentRect; }
@@ -196,22 +194,33 @@ public:
float contentsScale() const { return m_contentsScale; }
void setContentsScale(float);
+ TransformationMatrix contentToScreenSpaceTransform() const;
+
+ // Adds any opaque visible pixels to the occluded region.
+ virtual void addSelfToOccludedScreenSpace(Region& occludedScreenSpace);
+
// Returns true if any of the layer's descendants has content to draw.
bool descendantDrawsContent();
virtual void contentChanged() { }
CCLayerTreeHost* layerTreeHost() const { return m_layerTreeHost.get(); }
- void cleanupResourcesRecursive();
+
+ // Reserve any textures needed for this layer.
+ virtual void reserveTextures() { }
+
+ void setAlwaysReserveTextures(bool alwaysReserveTextures) { m_alwaysReserveTextures = alwaysReserveTextures; }
+ bool alwaysReserveTextures() const { return m_alwaysReserveTextures; }
protected:
- CCLayerDelegate* m_delegate;
- explicit LayerChromium(CCLayerDelegate*);
+ LayerChromium();
// This is called to clean up resources being held in the same context as
// layerRendererContext(). Subclasses should override this method if they
// hold context-dependent resources such as textures.
virtual void cleanupResources();
+ bool isPaintedAxisAlignedInScreen() const;
+
void setNeedsCommit();
// This flag is set when layer need repainting/updating.
@@ -220,6 +229,7 @@ protected:
// 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.
+ // Note this rect is in layer space (not content space).
FloatRect m_updateRect;
RefPtr<LayerChromium> m_maskLayer;
@@ -258,6 +268,7 @@ private:
FloatPoint m_position;
FloatPoint m_anchorPoint;
Color m_backgroundColor;
+ bool m_backgroundCoversViewport;
Color m_debugBorderColor;
float m_debugBorderWidth;
float m_opacity;
@@ -269,6 +280,7 @@ private:
bool m_usesLayerClipping;
bool m_isNonCompositedContent;
bool m_preserves3D;
+ bool m_alwaysReserveTextures;
TransformationMatrix m_transform;
TransformationMatrix m_sublayerTransform;
diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
index 933e78253..4f76dd9a9 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
@@ -52,16 +52,18 @@
#include "TrackingTextureAllocator.h"
#include "TreeSynchronizer.h"
#include "WebGLLayerChromium.h"
-#include "cc/CCCustomLayerDrawQuad.h"
+#include "cc/CCCanvasDrawQuad.h"
#include "cc/CCDamageTracker.h"
#include "cc/CCDebugBorderDrawQuad.h"
#include "cc/CCLayerImpl.h"
#include "cc/CCLayerTreeHostCommon.h"
+#include "cc/CCPluginDrawQuad.h"
#include "cc/CCProxy.h"
#include "cc/CCRenderPass.h"
#include "cc/CCRenderSurfaceDrawQuad.h"
#include "cc/CCSolidColorDrawQuad.h"
#include "cc/CCTileDrawQuad.h"
+#include "cc/CCVideoDrawQuad.h"
#if USE(SKIA)
#include "Extensions3D.h"
#include "GrContext.h"
@@ -161,10 +163,6 @@ private:
PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create(CCLayerTreeHostImpl* owner, PassRefPtr<GraphicsContext3D> context)
{
-#if USE(SKIA)
- if (owner->settings().acceleratePainting && !contextSupportsAcceleratedPainting(context.get()))
- return nullptr;
-#endif
OwnPtr<LayerRendererChromium> layerRenderer(adoptPtr(new LayerRendererChromium(owner, context)));
if (!layerRenderer->initialize())
return nullptr;
@@ -189,8 +187,10 @@ bool LayerRendererChromium::initialize()
if (!m_context->makeContextCurrent())
return false;
- if (settings().acceleratePainting)
+#if USE(SKIA)
+ if (settings().acceleratePainting && contextSupportsAcceleratedPainting(m_context.get()))
m_capabilities.usingAcceleratedPainting = true;
+#endif
WebCore::Extensions3D* extensions = m_context->getExtensions();
m_capabilities.contextHasCachedFrontBuffer = extensions->supports("GL_CHROMIUM_front_buffer_cached");
@@ -422,8 +422,14 @@ void LayerRendererChromium::drawQuad(const CCDrawQuad* quad, const FloatRect& su
case CCDrawQuad::TiledContent:
drawTileQuad(quad->toTileDrawQuad());
break;
- case CCDrawQuad::CustomLayer:
- drawCustomLayerQuad(quad->toCustomLayerDrawQuad());
+ case CCDrawQuad::CanvasContent:
+ drawCanvasQuad(quad->toCanvasDrawQuad());
+ break;
+ case CCDrawQuad::VideoContent:
+ drawVideoQuad(quad->toVideoDrawQuad());
+ break;
+ case CCDrawQuad::PluginContent:
+ drawPluginQuad(quad->toPluginDrawQuad());
break;
}
}
@@ -536,7 +542,7 @@ static void findTileProgramUniforms(LayerRendererChromium* layerRenderer, const
void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad)
{
- const IntRect& tileRect = quad->quadRect();
+ const IntRect& tileRect = quad->quadVisibleRect();
FloatRect clampRect(tileRect);
// Clamp texture coordinates to avoid sampling outside the layer
@@ -552,7 +558,8 @@ void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad)
clampRect.inflateY(-clampY);
FloatSize clampOffset = clampRect.minXMinYCorner() - FloatRect(tileRect).minXMinYCorner();
- FloatPoint textureOffset = quad->textureOffset() + clampOffset;
+ FloatPoint textureOffset = quad->textureOffset() + clampOffset +
+ IntPoint(quad->quadVisibleRect().location() - quad->quadRect().location());
// Map clamping rectangle to unit square.
float vertexTexTranslateX = -clampRect.x() / clampRect.width();
@@ -615,13 +622,14 @@ void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad)
CCLayerQuad::Edge topEdge(topLeft, topRight);
CCLayerQuad::Edge rightEdge(topRight, bottomRight);
- if (quad->topEdgeAA())
+ // Only apply anti-aliasing to edges not clipped during culling.
+ if (quad->topEdgeAA() && quad->quadVisibleRect().y() == quad->quadRect().y())
topEdge = deviceLayerEdges.top();
- if (quad->leftEdgeAA())
+ if (quad->leftEdgeAA() && quad->quadVisibleRect().x() == quad->quadRect().x())
leftEdge = deviceLayerEdges.left();
- if (quad->rightEdgeAA())
+ if (quad->rightEdgeAA() && quad->quadVisibleRect().maxX() == quad->quadRect().maxX())
rightEdge = deviceLayerEdges.right();
- if (quad->bottomEdgeAA())
+ if (quad->bottomEdgeAA() && quad->quadVisibleRect().maxY() == quad->quadRect().maxY())
bottomEdge = deviceLayerEdges.bottom();
float sign = FloatQuad(tileRect).isCounterclockwise() ? -1 : 1;
@@ -659,7 +667,38 @@ void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad)
drawTexturedQuad(quad->quadTransform(), tileRect.width(), tileRect.height(), quad->opacity(), localQuad, uniforms.matrixLocation, uniforms.alphaLocation, uniforms.pointLocation);
}
-void LayerRendererChromium::drawCustomLayerQuad(const CCCustomLayerDrawQuad* quad)
+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::drawVideoQuad(const CCVideoDrawQuad* quad)
+{
+ CCLayerImpl* layer = quad->layer();
+ layer->draw(this);
+}
+
+void LayerRendererChromium::drawPluginQuad(const CCPluginDrawQuad* quad)
{
CCLayerImpl* layer = quad->layer();
layer->draw(this);
diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h
index 2bb0146ad..c896b1df2 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h
@@ -167,7 +167,9 @@ private:
void drawRenderSurfaceQuad(const CCRenderSurfaceDrawQuad*);
void drawSolidColorQuad(const CCSolidColorDrawQuad*);
void drawTileQuad(const CCTileDrawQuad*);
- void drawCustomLayerQuad(const CCCustomLayerDrawQuad*);
+ void drawCanvasQuad(const CCCanvasDrawQuad*);
+ void drawVideoQuad(const CCVideoDrawQuad*);
+ void drawPluginQuad(const CCPluginDrawQuad*);
ManagedTexture* getOffscreenLayerTexture();
void copyOffscreenTextureToDisplay();
diff --git a/Source/WebCore/platform/graphics/chromium/LayerTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/LayerTextureUpdater.h
index 34db72aa4..179fea6e1 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerTextureUpdater.h
+++ b/Source/WebCore/platform/graphics/chromium/LayerTextureUpdater.h
@@ -71,7 +71,13 @@ public:
// This format specifies the component order in the sampled texel.
// If the format is TexelFormatBGRA, vec4.x is blue and vec4.z is red.
virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat) = 0;
- virtual void prepareToUpdate(const IntRect& /* contentRect */, const IntSize& /* tileSize */, int /* borderTexels */, float /* contentsScale */) { }
+ // 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 */) { }
+
+ // Set true by the layer when it is known that the entire output is going to be opaque.
+ virtual void setOpaque(bool) { }
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/ManagedTexture.cpp b/Source/WebCore/platform/graphics/chromium/ManagedTexture.cpp
index 0c1e4b70d..5bb19fa87 100644
--- a/Source/WebCore/platform/graphics/chromium/ManagedTexture.cpp
+++ b/Source/WebCore/platform/graphics/chromium/ManagedTexture.cpp
@@ -41,6 +41,15 @@ ManagedTexture::ManagedTexture(TextureManager* manager)
{
}
+ManagedTexture::ManagedTexture(TextureManager* manager, TextureToken token, IntSize size, unsigned format, unsigned textureId)
+ : m_textureManager(manager)
+ , m_token(token)
+ , m_size(size)
+ , m_format(format)
+ , m_textureId(textureId)
+{
+}
+
ManagedTexture::~ManagedTexture()
{
if (m_token)
@@ -99,6 +108,17 @@ void ManagedTexture::framebufferTexture2D(GraphicsContext3D* context, TextureAll
context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_textureId, 0);
}
+PassOwnPtr<ManagedTexture> ManagedTexture::steal()
+{
+ OwnPtr<ManagedTexture> texture = adoptPtr(new ManagedTexture(m_textureManager, m_token, m_size, m_format, m_textureId));
+ m_token = 0;
+ m_size = IntSize();
+ m_format = 0;
+ m_textureId = 0;
+ return texture.release();
+}
+
+
}
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/ManagedTexture.h b/Source/WebCore/platform/graphics/chromium/ManagedTexture.h
index 1cc8bfa9a..76d62a8bb 100644
--- a/Source/WebCore/platform/graphics/chromium/ManagedTexture.h
+++ b/Source/WebCore/platform/graphics/chromium/ManagedTexture.h
@@ -63,8 +63,13 @@ public:
unsigned format() const { return m_format; }
unsigned textureId() const { return m_textureId; }
+ // Steal token and textureId by instantiates a new texture using existing
+ // member variables.
+ PassOwnPtr<ManagedTexture> steal();
+
private:
explicit ManagedTexture(TextureManager*);
+ ManagedTexture(TextureManager*, TextureToken, IntSize, unsigned format, unsigned textureId);
TextureManager* m_textureManager;
TextureToken m_token;
diff --git a/Source/WebCore/platform/graphics/chromium/PlatformCanvas.cpp b/Source/WebCore/platform/graphics/chromium/PlatformCanvas.cpp
index 1c3a20f57..a6b25c534 100644
--- a/Source/WebCore/platform/graphics/chromium/PlatformCanvas.cpp
+++ b/Source/WebCore/platform/graphics/chromium/PlatformCanvas.cpp
@@ -41,6 +41,7 @@
namespace WebCore {
PlatformCanvas::PlatformCanvas()
+ : m_opaque(false)
{
}
@@ -53,10 +54,27 @@ void PlatformCanvas::resize(const IntSize& size)
if (m_size == size)
return;
m_size = size;
+ createBackingCanvas();
+}
+
+void PlatformCanvas::setOpaque(bool opaque)
+{
+ if (opaque == m_opaque)
+ return;
+
+ m_opaque = opaque;
+ createBackingCanvas();
+}
+
+void PlatformCanvas::createBackingCanvas()
+{
+ if (m_size.isEmpty())
+ return;
+
#if USE(SKIA)
- m_skiaCanvas = adoptPtr(skia::CreateBitmapCanvas(size.width(), size.height(), false));
+ m_skiaCanvas = adoptPtr(skia::CreateBitmapCanvas(m_size.width(), m_size.height(), m_opaque));
#elif USE(CG)
- size_t bufferSize = size.width() * size.height() * 4;
+ size_t bufferSize = m_size.width() * m_size.height() * 4;
m_pixelData = adoptArrayPtr(new uint8_t[bufferSize]);
memset(m_pixelData.get(), 0, bufferSize);
#endif
diff --git a/Source/WebCore/platform/graphics/chromium/PlatformCanvas.h b/Source/WebCore/platform/graphics/chromium/PlatformCanvas.h
index 14fe68798..fdee71b9f 100644
--- a/Source/WebCore/platform/graphics/chromium/PlatformCanvas.h
+++ b/Source/WebCore/platform/graphics/chromium/PlatformCanvas.h
@@ -85,6 +85,7 @@ public:
~Painter();
GraphicsContext* context() const { return m_context.get(); }
+ PlatformContextSkia* skiaContext() const { return m_skiaContext.get(); }
private:
OwnPtr<GraphicsContext> m_context;
#if USE(SKIA)
@@ -98,13 +99,19 @@ public:
void resize(const IntSize&);
IntSize size() const { return m_size; }
+ void setOpaque(bool);
+ bool opaque() const { return m_opaque; }
+
private:
+ void createBackingCanvas();
+
#if USE(SKIA)
OwnPtr<SkCanvas> m_skiaCanvas;
#elif USE(CG)
OwnArrayPtr<uint8_t> m_pixelData;
#endif
IntSize m_size;
+ bool m_opaque;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp
index e3c5c48f7..079ad2ede 100644
--- a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp
@@ -36,13 +36,13 @@
namespace WebCore {
-PassRefPtr<PluginLayerChromium> PluginLayerChromium::create(CCLayerDelegate* delegate)
+PassRefPtr<PluginLayerChromium> PluginLayerChromium::create()
{
- return adoptRef(new PluginLayerChromium(delegate));
+ return adoptRef(new PluginLayerChromium);
}
-PluginLayerChromium::PluginLayerChromium(CCLayerDelegate* delegate)
- : LayerChromium(delegate)
+PluginLayerChromium::PluginLayerChromium()
+ : LayerChromium()
, m_textureId(0)
, m_flipped(true)
, m_uvRect(0, 0, 1, 1)
diff --git a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h
index 0f2f4be7f..84365695b 100644
--- a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h
@@ -36,7 +36,7 @@ namespace WebCore {
// A Layer containing a the rendered output of a plugin instance.
class PluginLayerChromium : public LayerChromium {
public:
- static PassRefPtr<PluginLayerChromium> create(CCLayerDelegate* = 0);
+ static PassRefPtr<PluginLayerChromium> create();
virtual void updateCompositorResources(GraphicsContext3D*, CCTextureUpdater&);
virtual PassRefPtr<CCLayerImpl> createCCLayerImpl();
@@ -58,7 +58,7 @@ public:
void invalidateRect(const FloatRect& dirtyRect);
protected:
- explicit PluginLayerChromium(CCLayerDelegate*);
+ PluginLayerChromium();
private:
unsigned m_textureId;
diff --git a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
index 4e1822b31..bf4988c25 100644
--- a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
@@ -63,6 +63,8 @@ public:
float drawOpacity() const { return m_drawOpacity; }
void setDrawOpacity(float drawOpacity) { m_drawOpacity = drawOpacity; }
+ // 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; }
void setDrawTransform(const TransformationMatrix& drawTransform) { m_drawTransform = drawTransform; }
diff --git a/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
index 78ad56af9..a3dbd770a 100644
--- a/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
@@ -36,6 +36,7 @@
#include "Font.h"
#include "FontCache.h"
#include "FontDescription.h"
+#include "HWndDC.h"
#include "PlatformSupport.h"
#include <wtf/MathExtras.h>
@@ -55,7 +56,7 @@ void SimpleFontData::platformInit()
return;
}
- HDC dc = GetDC(0);
+ HWndDC dc(0);
HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
TEXTMETRIC textMetric = {0};
@@ -95,7 +96,6 @@ void SimpleFontData::platformInit()
m_fontMetrics.setLineSpacing(ascent + descent + lineGap);
SelectObject(dc, oldFont);
- ReleaseDC(0, dc);
}
void SimpleFontData::platformCharWidthInit()
@@ -147,7 +147,7 @@ bool SimpleFontData::containsCharacters(const UChar* characters, int length) con
void SimpleFontData::determinePitch()
{
// TEXTMETRICS have this. Set m_treatAsFixedPitch based off that.
- HDC dc = GetDC(0);
+ HWndDC dc(0);
HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
// Yes, this looks backwards, but the fixed pitch bit is actually set if the font
@@ -166,7 +166,6 @@ void SimpleFontData::determinePitch()
m_treatAsFixedPitch = ((textMetric.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0);
SelectObject(dc, oldFont);
- ReleaseDC(0, dc);
}
FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const
@@ -179,7 +178,7 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
if (!m_platformData.size())
return 0;
- HDC dc = GetDC(0);
+ HWndDC dc(0);
HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
int width = 0;
@@ -194,7 +193,6 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
}
SelectObject(dc, oldFont);
- ReleaseDC(0, dc);
return static_cast<float>(width);
}
diff --git a/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp
index 537e137e8..0d974fa63 100644
--- a/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp
+++ b/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp
@@ -41,6 +41,7 @@ namespace WebCore {
SkPictureCanvasLayerTextureUpdater::SkPictureCanvasLayerTextureUpdater(PassOwnPtr<LayerPainterChromium> painter)
: CanvasLayerTextureUpdater(painter)
+ , m_layerIsOpaque(false)
{
}
@@ -48,14 +49,18 @@ SkPictureCanvasLayerTextureUpdater::~SkPictureCanvasLayerTextureUpdater()
{
}
-void SkPictureCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& /* tileSize */, int /* borderTexels */, float contentsScale)
+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);
GraphicsContext graphicsContext(&platformContext);
paintContents(graphicsContext, contentRect, contentsScale);
m_picture.endRecording();
+
+ if (!m_layerIsOpaque)
+ *resultingOpaqueRect = platformContext.opaqueRegion().asRect();
}
void SkPictureCanvasLayerTextureUpdater::drawPicture(SkCanvas* canvas)
@@ -64,6 +69,11 @@ void SkPictureCanvasLayerTextureUpdater::drawPicture(SkCanvas* canvas)
canvas->drawPicture(m_picture);
}
+void SkPictureCanvasLayerTextureUpdater::setOpaque(bool opaque)
+{
+ m_layerIsOpaque = opaque;
+}
+
} // namespace WebCore
#endif // USE(SKIA)
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.h
index 95b78c3b9..7fcc6059f 100644
--- a/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.h
+++ b/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.h
@@ -51,11 +51,16 @@ public:
protected:
explicit SkPictureCanvasLayerTextureUpdater(PassOwnPtr<LayerPainterChromium>);
- virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, int borderTexels, float contentsScale);
+ virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, int borderTexels, float contentsScale, IntRect* resultingOpaqueRect);
void drawPicture(SkCanvas*);
+ virtual void setOpaque(bool);
+
private:
- SkPicture m_picture; // Recording canvas.
+ // Recording canvas.
+ SkPicture m_picture;
+ // True when it is known that all output pixels will be opaque.
+ bool m_layerIsOpaque;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/SolidColorLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/SolidColorLayerChromium.cpp
new file mode 100644
index 000000000..ed13546ba
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/SolidColorLayerChromium.cpp
@@ -0,0 +1,57 @@
+/*
+ * 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 "SolidColorLayerChromium.h"
+
+#include "cc/CCSolidColorLayerImpl.h"
+
+namespace WebCore {
+
+PassRefPtr<CCLayerImpl> SolidColorLayerChromium::createCCLayerImpl()
+{
+ return CCSolidColorLayerImpl::create(id());
+}
+
+PassRefPtr<SolidColorLayerChromium> SolidColorLayerChromium::create()
+{
+ return adoptRef(new SolidColorLayerChromium());
+}
+
+SolidColorLayerChromium::SolidColorLayerChromium()
+ : LayerChromium()
+{
+}
+
+SolidColorLayerChromium::~SolidColorLayerChromium()
+{
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/SolidColorLayerChromium.h b/Source/WebCore/platform/graphics/chromium/SolidColorLayerChromium.h
new file mode 100644
index 000000000..1d14890bd
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/SolidColorLayerChromium.h
@@ -0,0 +1,54 @@
+/*
+ * 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 SolidColorLayerChromium_h
+#define SolidColorLayerChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerChromium.h"
+
+namespace WebCore {
+
+class LayerTilerChromium;
+
+// A Layer that renders a solid color. The color is specified by using
+// setBackgroundColor() on the base class.
+class SolidColorLayerChromium : public LayerChromium {
+public:
+ virtual PassRefPtr<CCLayerImpl> createCCLayerImpl();
+ static PassRefPtr<SolidColorLayerChromium> create();
+
+ virtual ~SolidColorLayerChromium();
+
+protected:
+ SolidColorLayerChromium();
+};
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
+
diff --git a/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp
index ad2cb13fc..283aa8dd0 100644
--- a/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp
@@ -59,16 +59,21 @@ public:
ManagedTexture* managedTexture() { return m_texture->texture(); }
bool isDirty() const { return !m_dirtyRect.isEmpty(); }
- void clearDirty() { m_dirtyRect = IntRect(); }
+ void copyAndClearDirty()
+ {
+ m_updateRect = m_dirtyRect;
+ m_dirtyRect = IntRect();
+ }
IntRect m_dirtyRect;
IntRect m_updateRect;
+ IntRect m_opaqueRect;
private:
OwnPtr<LayerTextureUpdater::Texture> m_texture;
};
-TiledLayerChromium::TiledLayerChromium(CCLayerDelegate* delegate)
- : LayerChromium(delegate)
+TiledLayerChromium::TiledLayerChromium()
+ : LayerChromium()
, m_textureFormat(GraphicsContext3D::INVALID_ENUM)
, m_skipsDraw(false)
, m_skipsIdlePaint(false)
@@ -150,13 +155,13 @@ void TiledLayerChromium::setBorderTexelOption(CCLayerTilingData::BorderTexelOpti
bool TiledLayerChromium::drawsContent() const
{
- if (!LayerChromium::drawsContent() || !m_delegate)
+ if (!LayerChromium::drawsContent())
return false;
if (m_tilingOption == NeverTile && m_tiler->numTiles() > 1)
return false;
- return !m_skipsDraw;
+ return true;
}
bool TiledLayerChromium::needsContentsScale() const
@@ -174,9 +179,6 @@ void TiledLayerChromium::setLayerTreeHost(CCLayerTreeHost* host)
if (host == layerTreeHost())
return;
- if (layerTreeHost())
- cleanupResources();
-
LayerChromium::setLayerTreeHost(host);
if (!host)
@@ -236,7 +238,11 @@ void TiledLayerChromium::updateCompositorResources(GraphicsContext3D*, CCTexture
}
}
+ // 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)
@@ -268,7 +274,7 @@ void TiledLayerChromium::pushPropertiesTo(CCLayerImpl* layer)
if (tile->isDirty())
continue;
- tiledLayer->syncTextureId(i, j, tile->managedTexture()->textureId());
+ tiledLayer->pushTileProperties(i, j, tile->managedTexture()->textureId(), tile->m_opaqueRect);
}
}
@@ -366,7 +372,9 @@ void TiledLayerChromium::prepareToUpdateTiles(bool idle, int left, int top, int
}
// Create tiles as needed, expanding a dirty rect to contain all
- // the dirty regions currently being drawn.
+ // 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;
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
@@ -374,19 +382,28 @@ void TiledLayerChromium::prepareToUpdateTiles(bool idle, int left, int top, int
if (!tile)
tile = createTile(i, j);
+ // Do post commit deletion of current texture when partial texture
+ // updates are not used.
+ if (tile->isDirty() && layerTreeHost() && !layerTreeHost()->settings().partialTextureUpdates)
+ layerTreeHost()->deleteTextureAfterCommit(tile->managedTexture()->steal());
+
if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat))
tile->m_dirtyRect = m_tiler->tileRect(tile);
if (!tile->managedTexture()->reserve(m_tiler->tileSize(), m_textureFormat)) {
m_skipsIdlePaint = true;
if (!idle) {
- m_skipsDraw = true;
+ // If the background covers the viewport, always draw this
+ // layer so that checkerboarded tiles will still draw.
+ if (!backgroundCoversViewport())
+ m_skipsDraw = true;
cleanupResources();
}
return;
}
dirtyLayerRect.unite(tile->m_dirtyRect);
+ tile->copyAndClearDirty();
}
}
@@ -405,7 +422,8 @@ void TiledLayerChromium::prepareToUpdateTiles(bool idle, int left, int top, int
// However, we can't free the memory backing the GraphicsContext until the paint finishes,
// so we grab a local reference here to hold the updater alive until the paint completes.
RefPtr<LayerTextureUpdater> protector(textureUpdater());
- textureUpdater()->prepareToUpdate(m_paintRect, m_tiler->tileSize(), m_tiler->hasBorderTexels(), contentsScale());
+ IntRect paintedOpaqueRect;
+ textureUpdater()->prepareToUpdate(m_paintRect, m_tiler->tileSize(), m_tiler->hasBorderTexels(), contentsScale(), &paintedOpaqueRect);
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
UpdatableTile* tile = tileAt(i, j);
@@ -414,19 +432,27 @@ void TiledLayerChromium::prepareToUpdateTiles(bool idle, int left, int top, int
if (!tile)
CRASH();
- if (!tile->isDirty())
+ IntRect tileRect = m_tiler->tileBounds(i, j);
+
+ // Save what was painted opaque in the tile. If everything painted in the tile was opaque, and the area is a subset of an
+ // already opaque area, keep the old area.
+ IntRect tilePaintedRect = intersection(tileRect, m_paintRect);
+ IntRect tilePaintedOpaqueRect = intersection(tileRect, paintedOpaqueRect);
+ if (tilePaintedOpaqueRect != tilePaintedRect || !tile->m_opaqueRect.contains(tilePaintedOpaqueRect))
+ tile->m_opaqueRect = tilePaintedOpaqueRect;
+
+ // Use m_updateRect as copyAndClearDirty above moved the existing dirty rect to m_updateRect.
+ const IntRect& dirtyRect = tile->m_updateRect;
+ if (dirtyRect.isEmpty())
continue;
+ // sourceRect starts as a full-sized tile with border texels included.
IntRect sourceRect = m_tiler->tileRect(tile);
- sourceRect.intersect(tile->m_dirtyRect);
+ 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);
- // updateCompositorResources() uses m_updateRect to determine
- // the tiles to update so we can clear the dirty rectangle here.
- tile->clearDirty();
-
tile->m_updateRect = sourceRect;
if (sourceRect.isEmpty())
continue;
@@ -436,6 +462,60 @@ void TiledLayerChromium::prepareToUpdateTiles(bool idle, int left, int top, int
}
}
+void TiledLayerChromium::reserveTextures()
+{
+ updateBounds();
+
+ const IntRect& layerRect = visibleLayerRect();
+ if (layerRect.isEmpty() || !m_tiler->numTiles())
+ 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) {
+ UpdatableTile* tile = tileAt(i, j);
+ if (!tile)
+ tile = createTile(i, j);
+
+ if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat))
+ tile->m_dirtyRect = m_tiler->tileRect(tile);
+
+ if (!tile->managedTexture()->reserve(m_tiler->tileSize(), m_textureFormat))
+ return;
+ }
+ }
+}
+
+void TiledLayerChromium::addSelfToOccludedScreenSpace(Region& occludedScreenSpace)
+{
+ if (m_skipsDraw || drawOpacity() != 1 || !isPaintedAxisAlignedInScreen())
+ return;
+
+ if (opaque()) {
+ LayerChromium::addSelfToOccludedScreenSpace(occludedScreenSpace);
+ return;
+ }
+
+ IntRect visibleRect = visibleLayerRect();
+ TransformationMatrix contentTransform = contentToScreenSpaceTransform();
+
+ // FIXME: Create/Use a FloatRegion for the occludedScreenSpace, instead of a Region based on ints, to avoid this step and get better accuracy between layers in target space.
+ Region tileRegion;
+ int left, top, right, bottom;
+ m_tiler->layerRectToTileIndices(visibleLayerRect(), left, top, right, bottom);
+ for (int j = top; j <= bottom; ++j) {
+ for (int i = left; i <= right; ++i) {
+ UpdatableTile* tile = tileAt(i, j);
+ if (tile) {
+ IntRect visibleTileOpaqueRect = intersection(visibleRect, tile->m_opaqueRect);
+ FloatRect screenRect = contentTransform.mapRect(FloatRect(visibleTileOpaqueRect));
+ occludedScreenSpace.unite(enclosedIntRect(screenRect));
+ }
+ }
+ }
+}
void TiledLayerChromium::prepareToUpdate(const IntRect& layerRect)
{
diff --git a/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h b/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h
index f0ab057ef..3cbbbcbd7 100644
--- a/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h
@@ -35,6 +35,7 @@
namespace WebCore {
class LayerTextureUpdater;
+class Region;
class UpdatableTile;
class TiledLayerChromium : public LayerChromium {
@@ -61,8 +62,12 @@ public:
// recycled by the texture manager.
void protectTileTextures(const IntRect& layerRect);
+ virtual void reserveTextures();
+
+ virtual void addSelfToOccludedScreenSpace(Region& occludedScreenSpace);
+
protected:
- explicit TiledLayerChromium(CCLayerDelegate*);
+ TiledLayerChromium();
virtual void cleanupResources();
void updateTileSizeAndTilingOption();
@@ -88,6 +93,8 @@ protected:
// After preparing an update, returns true if more pre-painting is needed.
bool needsIdlePaint(const IntRect& layerRect);
+ bool skipsDraw() const { return m_skipsDraw; }
+
virtual void protectVisibleTileTextures();
virtual TextureManager* textureManager() const;
diff --git a/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp b/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
index efca3d976..51b0c695f 100644
--- a/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
+++ b/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
+ * Copyright (c) 2006, 2007, 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,6 +33,7 @@
#include "Font.h"
#include "FontUtilsChromiumWin.h"
+#include "HWndDC.h"
#include "PlatformContextSkia.h"
#include "SkiaFontWin.h"
#include "SkPoint.h"
@@ -786,13 +787,11 @@ void UniscribeHelper::EnsureCachedDCCreated()
// Allocate a memory DC that is compatible with the Desktop DC since we don't have any window,
// and we don't want to use the Desktop DC directly since it can have nasty side effects
// as identified in Chrome Issue http://crbug.com/59315.
- HDC screenDC = ::GetDC(0);
+ HWndDC screenDC(0);
m_cachedDC = ::CreateCompatibleDC(screenDC);
ASSERT(m_cachedDC);
-
- int result = ::ReleaseDC(0, screenDC);
- ASSERT(result == 1);
}
+
void UniscribeHelper::fillShapes()
{
m_shapes.resize(m_runs.size());
diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
index 0e0fcb665..ae2ae8c80 100644
--- a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
@@ -36,14 +36,13 @@
namespace WebCore {
-PassRefPtr<VideoLayerChromium> VideoLayerChromium::create(CCLayerDelegate* delegate,
- VideoFrameProvider* provider)
+PassRefPtr<VideoLayerChromium> VideoLayerChromium::create(VideoFrameProvider* provider)
{
- return adoptRef(new VideoLayerChromium(delegate, provider));
+ return adoptRef(new VideoLayerChromium(provider));
}
-VideoLayerChromium::VideoLayerChromium(CCLayerDelegate* delegate, VideoFrameProvider* provider)
- : LayerChromium(delegate)
+VideoLayerChromium::VideoLayerChromium(VideoFrameProvider* provider)
+ : LayerChromium()
, m_provider(provider)
{
ASSERT(m_provider);
diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h
index d3bed2b10..878806e26 100644
--- a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h
@@ -45,14 +45,13 @@ class VideoFrameProvider;
class VideoLayerChromium : public LayerChromium {
public:
- static PassRefPtr<VideoLayerChromium> create(CCLayerDelegate* = 0,
- VideoFrameProvider* = 0);
+ static PassRefPtr<VideoLayerChromium> create(VideoFrameProvider* = 0);
virtual ~VideoLayerChromium();
virtual PassRefPtr<CCLayerImpl> createCCLayerImpl();
private:
- VideoLayerChromium(CCLayerDelegate*, VideoFrameProvider*);
+ explicit VideoLayerChromium(VideoFrameProvider*);
// This pointer is only for passing to CCVideoLayerImpl's constructor. It should never be dereferenced by this class.
VideoFrameProvider* m_provider;
diff --git a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
index 7084d66ff..74db7f13e 100644
--- a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
@@ -42,13 +42,13 @@
namespace WebCore {
-PassRefPtr<WebGLLayerChromium> WebGLLayerChromium::create(CCLayerDelegate* delegate)
+PassRefPtr<WebGLLayerChromium> WebGLLayerChromium::create()
{
- return adoptRef(new WebGLLayerChromium(delegate));
+ return adoptRef(new WebGLLayerChromium());
}
-WebGLLayerChromium::WebGLLayerChromium(CCLayerDelegate* delegate)
- : CanvasLayerChromium(delegate)
+WebGLLayerChromium::WebGLLayerChromium()
+ : CanvasLayerChromium()
, m_hasAlpha(true)
, m_premultipliedAlpha(true)
, m_textureId(0)
diff --git a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
index eb5146eb7..4dc68a330 100644
--- a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
@@ -45,7 +45,7 @@ class WebGLLayerChromiumRateLimitTask;
// A Layer containing a WebGL canvas
class WebGLLayerChromium : public CanvasLayerChromium {
public:
- static PassRefPtr<WebGLLayerChromium> create(CCLayerDelegate* = 0);
+ static PassRefPtr<WebGLLayerChromium> create();
virtual ~WebGLLayerChromium();
@@ -63,7 +63,7 @@ public:
void setDrawingBuffer(DrawingBuffer*);
DrawingBuffer* drawingBuffer() const { return m_drawingBuffer; }
private:
- explicit WebGLLayerChromium(CCLayerDelegate*);
+ WebGLLayerChromium();
friend class WebGLLayerChromiumRateLimitTask;
GraphicsContext3D* layerRendererContext();
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.cpp
new file mode 100644
index 000000000..21e6cc7a9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.cpp
@@ -0,0 +1,98 @@
+/*
+ * 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/CCActiveAnimation.h"
+
+#include "cc/CCAnimationCurve.h"
+
+#include <cmath>
+
+namespace WebCore {
+
+CCActiveAnimation::CCActiveAnimation(PassOwnPtr<CCAnimationCurve> curve, GroupID group, TargetProperty targetProperty)
+ : m_animationCurve(curve)
+ , m_group(group)
+ , m_targetProperty(targetProperty)
+ , m_runState(WaitingForTargetAvailability)
+ , m_iterations(1)
+ , m_startTime(0)
+ , m_pauseTime(0)
+ , m_totalPausedTime(0)
+{
+}
+
+void CCActiveAnimation::setRunState(RunState runState, double now)
+{
+ if (runState == Running && m_runState == Paused)
+ m_totalPausedTime += now - m_pauseTime;
+ else if (runState == Paused)
+ m_pauseTime = now;
+ m_runState = runState;
+}
+
+bool CCActiveAnimation::isFinishedAt(double time) const
+{
+ if (m_runState == Finished || m_runState == Aborted)
+ return true;
+
+ return m_runState == Running
+ && m_iterations >= 0
+ && m_iterations * m_animationCurve->duration() <= time - startTime() - m_totalPausedTime;
+}
+
+double CCActiveAnimation::trimTimeToCurrentIteration(double now) const
+{
+ double trimmed = now;
+
+ // If we're paused, time is 'stuck' at the pause time.
+ if (m_runState == Paused && trimmed > m_pauseTime)
+ trimmed = m_pauseTime;
+
+ // Returned time should always be relative to the start time and should subtract
+ // all time spent paused.
+ trimmed -= m_startTime + m_totalPausedTime;
+
+ // Zero is always the start of the animation.
+ if (trimmed <= 0)
+ return 0;
+
+ // Always return zero if we have no iterations.
+ if (!m_iterations)
+ return 0;
+
+ // If less than an iteration duration, just return trimmed.
+ if (trimmed < m_animationCurve->duration())
+ return trimmed;
+
+ // If greater than or equal to the total duration, return iteration duration.
+ if (m_iterations >= 0 && trimmed >= m_animationCurve->duration() * m_iterations)
+ return m_animationCurve->duration();
+
+ // Finally, return x where trimmed = x + n * m_animation->duration() for some positive integer n.
+ return fmod(trimmed, m_animationCurve->duration());
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.h b/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.h
new file mode 100644
index 000000000..c22227941
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.h
@@ -0,0 +1,123 @@
+/*
+ * 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 CCActiveAnimation_h
+#define CCActiveAnimation_h
+
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class CCAnimationCurve;
+
+// A CCActiveAnimation, contains all the state required to play a CCAnimationCurve.
+// Specifically, the affected property, the run state (paused, finished, etc.),
+// loop count, last pause time, and the total time spent paused.
+class CCActiveAnimation {
+public:
+ // Animations that must be run together are called 'grouped' and have the same GroupID
+ // Grouped animations are guaranteed to start at the same time and no other animations
+ // may animate any of the group's target properties until all animations in the
+ // group have finished animating. Note: an active animation's group id and target
+ // property uniquely identify that animation.
+ typedef int GroupID;
+
+ // Animations begin in one of the 'waiting' states. Animations waiting for the next tick
+ // will start the next time the controller animates. Animations waiting for target
+ // availibility will run as soon as their target property is free (and all the animations
+ // animating with it are also able to run). Animations waiting for their start time to
+ // come have be scheduled to run at a particular point in time. When this time arrives,
+ // the controller will move the animations into the Running state. Running animations
+ // may toggle between Running and Paused, and may be stopped by moving into either the
+ // Aborted or Finished states. A Finished animation was allowed to run to completion, but
+ // an Aborted animation was not.
+ enum RunState {
+ WaitingForNextTick = 1,
+ WaitingForTargetAvailability,
+ WaitingForStartTime,
+ Running,
+ Paused,
+ Finished,
+ Aborted
+ };
+
+ enum TargetProperty {
+ Transform = 1,
+ Opacity
+ };
+
+ static PassOwnPtr<CCActiveAnimation> create(PassOwnPtr<CCAnimationCurve> curve, GroupID group, TargetProperty targetProperty)
+ {
+ return adoptPtr(new CCActiveAnimation(curve, group, targetProperty));
+ }
+
+ virtual ~CCActiveAnimation() { }
+
+ GroupID group() const { return m_group; }
+ TargetProperty targetProperty() const { return m_targetProperty; }
+
+ RunState runState() const { return m_runState; }
+ void setRunState(RunState, double now);
+
+ // 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
+ // the animation will loop indefinitely.
+ int iterations() const { return m_iterations; }
+ void setIterations(int n) { m_iterations = n; }
+
+ double startTime() const { return m_startTime; }
+ void setStartTime(double startTime) { m_startTime = startTime; }
+
+ bool isFinishedAt(double time) const;
+ bool isFinished() const { return m_runState == Finished || m_runState == Aborted; }
+
+ CCAnimationCurve* animationCurve() { return m_animationCurve.get(); }
+ const CCAnimationCurve* animationCurve() const { return m_animationCurve.get(); }
+
+ // 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;
+
+private:
+ CCActiveAnimation(PassOwnPtr<CCAnimationCurve>, GroupID, TargetProperty);
+
+ OwnPtr<CCAnimationCurve> m_animationCurve;
+ GroupID m_group;
+ TargetProperty m_targetProperty;
+ RunState m_runState;
+ int m_iterations;
+ double m_startTime;
+
+ // 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
+ // about these values.
+ double m_pauseTime;
+ double m_totalPausedTime;
+};
+
+} // namespace WebCore
+
+#endif // CCActiveAnimation_h
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCAnimationCurve.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCAnimationCurve.cpp
new file mode 100644
index 000000000..58cdc6ad6
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCAnimationCurve.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:
+ * 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/CCAnimationCurve.h"
+
+namespace WebCore {
+
+const CCFloatAnimationCurve* CCAnimationCurve::toFloatAnimationCurve() const
+{
+ ASSERT(type() == CCAnimationCurve::Float);
+ return static_cast<const CCFloatAnimationCurve*>(this);
+}
+
+const CCTransformAnimationCurve* CCAnimationCurve::toTransformAnimationCurve() const
+{
+ ASSERT(type() == CCAnimationCurve::Transform);
+ return static_cast<const CCTransformAnimationCurve*>(this);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCAnimationCurve.h b/Source/WebCore/platform/graphics/chromium/cc/CCAnimationCurve.h
new file mode 100644
index 000000000..de97e38c0
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCAnimationCurve.h
@@ -0,0 +1,71 @@
+/*
+ * 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 CCAnimationCurve_h
+#define CCAnimationCurve_h
+
+namespace WebCore {
+
+class CCFloatAnimationCurve;
+class CCTransformAnimationCurve;
+class TransformOperations;
+
+// An animation curve is a function that returns a value given a time.
+// There are currently only two types of curve, float and transform.
+class CCAnimationCurve {
+public:
+ enum Type { Float, Transform };
+
+ virtual ~CCAnimationCurve() { }
+
+ virtual double duration() const = 0;
+ virtual Type type() const = 0;
+
+ const CCFloatAnimationCurve* toFloatAnimationCurve() const;
+ const CCTransformAnimationCurve* toTransformAnimationCurve() const;
+};
+
+class CCFloatAnimationCurve : public CCAnimationCurve {
+public:
+ virtual ~CCFloatAnimationCurve() { }
+
+ virtual float getValue(double t) const = 0;
+
+ // Partial CCAnimation implementation.
+ virtual Type type() const { return Float; }
+};
+
+class CCTransformAnimationCurve : public CCAnimationCurve {
+public:
+ virtual ~CCTransformAnimationCurve() { }
+
+ virtual TransformOperations getValue(double t) const = 0;
+
+ // Partial CCAnimation implementation.
+ virtual Type type() const { return Transform; }
+};
+
+} // namespace WebCore
+
+#endif // CCAnimation_h
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasDrawQuad.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasDrawQuad.cpp
new file mode 100644
index 000000000..56f5083a5
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasDrawQuad.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 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/CCCanvasDrawQuad.h"
+
+namespace WebCore {
+
+PassOwnPtr<CCCanvasDrawQuad> CCCanvasDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, unsigned textureId, bool hasAlpha, bool premultipliedAlpha)
+{
+ return adoptPtr(new CCCanvasDrawQuad(sharedQuadState, quadRect, textureId, hasAlpha, premultipliedAlpha));
+}
+
+CCCanvasDrawQuad::CCCanvasDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, unsigned textureId, bool hasAlpha, bool premultipliedAlpha)
+ : CCDrawQuad(sharedQuadState, CCDrawQuad::CanvasContent, quadRect)
+ , m_textureId(textureId)
+ , m_hasAlpha(hasAlpha)
+ , m_premultipliedAlpha(premultipliedAlpha)
+{
+}
+
+}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasDrawQuad.h b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasDrawQuad.h
new file mode 100644
index 000000000..aa85dbd13
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasDrawQuad.h
@@ -0,0 +1,54 @@
+/*
+ * 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 CCCanvasDrawQuad_h
+#define CCCanvasDrawQuad_h
+
+#include "cc/CCDrawQuad.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class CCLayerImpl;
+class CCCanvasDrawQuad : public CCDrawQuad {
+ WTF_MAKE_NONCOPYABLE(CCCanvasDrawQuad);
+public:
+ static PassOwnPtr<CCCanvasDrawQuad> create(const CCSharedQuadState*, const IntRect&, unsigned texture_id, bool hasAlpha, bool premultipliedAlpha);
+
+ unsigned textureId() const { return m_textureId; }
+ bool hasAlpha() const { return m_hasAlpha; }
+ bool premultipliedAlpha() const { return m_premultipliedAlpha; }
+
+private:
+ CCCanvasDrawQuad(const CCSharedQuadState*, const IntRect&, unsigned texture_id, bool hasAlpha, bool premultipliedAlpha);
+
+ unsigned m_textureId;
+ bool m_hasAlpha;
+ bool m_premultipliedAlpha;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp
index 6ecdd90f2..2bb3eff22 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp
@@ -31,6 +31,7 @@
#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h"
+#include "cc/CCCanvasDrawQuad.h"
#include "cc/CCProxy.h"
#include <wtf/text/WTFString.h>
@@ -48,36 +49,12 @@ CCCanvasLayerImpl::~CCCanvasLayerImpl()
{
}
-void CCCanvasLayerImpl::draw(LayerRendererChromium* layerRenderer)
+void CCCanvasLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState)
{
- ASSERT(CCProxy::isImplThread());
- const CCCanvasLayerImpl::Program* program = layerRenderer->canvasLayerProgram();
- ASSERT(program && program->initialized());
- GraphicsContext3D* context = layerRenderer->context();
- GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
- GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId));
- 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 (!m_hasAlpha) {
- // Even though the WebGL layer's texture was likely allocated
- // as GL_RGB, disable blending anyway for better robustness.
- context->disable(GraphicsContext3D::BLEND);
- } else {
- GC3Denum sfactor = m_premultipliedAlpha ? GraphicsContext3D::ONE : GraphicsContext3D::SRC_ALPHA;
- GLC(context, context->blendFunc(sfactor, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
- }
- GLC(context, context->useProgram(program->program()));
- GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
- layerRenderer->drawTexturedQuad(drawTransform(), bounds().width(), bounds().height(), drawOpacity(), layerRenderer->sharedGeometryQuad(),
- program->vertexShader().matrixLocation(),
- program->fragmentShader().alphaLocation(),
- -1);
- if (!m_hasAlpha)
- context->enable(GraphicsContext3D::BLEND);
+ IntRect quadRect(IntPoint(), bounds());
+ quadList.append(CCCanvasDrawQuad::create(sharedQuadState, quadRect, m_textureId, m_hasAlpha, m_premultipliedAlpha));
}
-
void CCCanvasLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
{
writeIndent(ts, indent);
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h
index 275bf7ca8..9126a7d44 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h
@@ -40,9 +40,9 @@ public:
}
virtual ~CCCanvasLayerImpl();
- typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program;
+ virtual void appendQuads(CCQuadList&, const CCSharedQuadState*);
- virtual void draw(LayerRendererChromium*);
+ typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program;
virtual void dumpLayerProperties(TextStream&, int indent) const;
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDelayBasedTimeSource.h b/Source/WebCore/platform/graphics/chromium/cc/CCDelayBasedTimeSource.h
index 6336b8849..a41aad4d8 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCDelayBasedTimeSource.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCDelayBasedTimeSource.h
@@ -45,6 +45,7 @@ public:
virtual void setClient(CCTimeSourceClient* client) { m_client = client; }
virtual void setActive(bool);
+ virtual bool active() const { return m_state != STATE_INACTIVE; }
// CCTimerClient implementation.
virtual void onTimerFired();
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.cpp
index 8fcf449f0..708500267 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.cpp
@@ -27,12 +27,14 @@
#include "cc/CCDrawQuad.h"
-#include "cc/CCCustomLayerDrawQuad.h"
+#include "cc/CCCanvasDrawQuad.h"
#include "cc/CCDebugBorderDrawQuad.h"
#include "cc/CCLayerImpl.h"
+#include "cc/CCPluginDrawQuad.h"
#include "cc/CCRenderSurfaceDrawQuad.h"
#include "cc/CCSolidColorDrawQuad.h"
#include "cc/CCTileDrawQuad.h"
+#include "cc/CCVideoDrawQuad.h"
namespace WebCore {
@@ -40,6 +42,7 @@ CCDrawQuad::CCDrawQuad(const CCSharedQuadState* sharedQuadState, Material materi
: m_sharedQuadState(sharedQuadState)
, m_material(material)
, m_quadRect(quadRect)
+ , m_quadVisibleRect(quadRect)
, m_quadOpaque(true)
, m_needsBlending(false)
{
@@ -47,6 +50,21 @@ CCDrawQuad::CCDrawQuad(const CCSharedQuadState* sharedQuadState, Material materi
ASSERT(m_material != Invalid);
}
+IntRect CCDrawQuad::opaqueRect() const
+{
+ if (opacity() != 1)
+ return IntRect();
+ if (m_sharedQuadState->isOpaque() && m_quadOpaque)
+ return m_quadRect;
+ return m_opaqueRect;
+}
+
+void CCDrawQuad::setQuadVisibleRect(const IntRect& quadVisibleRect)
+{
+ m_quadVisibleRect = quadVisibleRect;
+ m_quadVisibleRect.intersect(m_quadRect);
+}
+
const CCDebugBorderDrawQuad* CCDrawQuad::toDebugBorderDrawQuad() const
{
ASSERT(m_material == DebugBorder);
@@ -71,10 +89,22 @@ const CCTileDrawQuad* CCDrawQuad::toTileDrawQuad() const
return static_cast<const CCTileDrawQuad*>(this);
}
-const CCCustomLayerDrawQuad* CCDrawQuad::toCustomLayerDrawQuad() const
+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 == CustomLayer);
- return static_cast<const CCCustomLayerDrawQuad*>(this);
+ 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 b56913b3c..1738b4b0e 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.h
@@ -34,7 +34,9 @@ class CCDebugBorderDrawQuad;
class CCRenderSurfaceDrawQuad;
class CCSolidColorDrawQuad;
class CCTileDrawQuad;
-class CCCustomLayerDrawQuad;
+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
@@ -49,20 +51,25 @@ 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, are the contents of this quad opaque?
- bool drawsOpaque() const { return m_sharedQuadState->isOpaque() && m_quadOpaque && opacity() == 1; }
- bool needsBlending() const { return !m_sharedQuadState->isOpaque() || m_needsBlending || opacity() != 1; }
+ // For the purposes of culling, what part of the contents of this quad are opaque?
+ IntRect opaqueRect() const;
+ bool needsBlending() const { return m_needsBlending || opaqueRect() != m_quadRect; }
bool isLayerAxisAlignedIntRect() const { return m_sharedQuadState->isLayerAxisAlignedIntRect(); }
+ // Allows changing the rect that gets drawn to make it smaller. Parameter passed
+ // in will be clipped to quadRect().
+ void setQuadVisibleRect(const IntRect&);
+ const IntRect& quadVisibleRect() const { return m_quadVisibleRect; }
+
enum Material {
Invalid,
DebugBorder,
RenderSurface,
SolidColor,
TiledContent,
-
- // FIXME: remove this and add proper material types for all layer types
- CustomLayer,
+ CanvasContent,
+ VideoContent,
+ PluginContent,
};
Material material() const { return m_material; }
@@ -71,7 +78,9 @@ public:
const CCRenderSurfaceDrawQuad* toRenderSurfaceDrawQuad() const;
const CCSolidColorDrawQuad* toSolidColorDrawQuad() const;
const CCTileDrawQuad* toTileDrawQuad() const;
- const CCCustomLayerDrawQuad* toCustomLayerDrawQuad() const;
+ const CCCanvasDrawQuad* toCanvasDrawQuad() const;
+ const CCVideoDrawQuad* toVideoDrawQuad() const;
+ const CCPluginDrawQuad* toPluginDrawQuad() const;
protected:
CCDrawQuad(const CCSharedQuadState*, Material, const IntRect&);
@@ -80,12 +89,17 @@ protected:
Material m_material;
IntRect m_quadRect;
+ IntRect m_quadVisibleRect;
// By default, the shared quad state determines whether or not this quad is
// opaque or needs blending. Derived classes can override with these
// variables.
bool m_quadOpaque;
bool m_needsBlending;
+
+ // Be default, this rect is empty. It is used when the shared quad state and above
+ // variables determine that the quad is not fully opaque but may be partially opaque.
+ IntRect m_opaqueRect;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.cpp
index 5ac918658..55447ca59 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.cpp
@@ -26,6 +26,7 @@
#include "cc/CCFrameRateController.h"
+#include "TraceEvent.h"
#include "cc/CCThread.h"
#include "cc/CCThreadTask.h"
@@ -62,6 +63,14 @@ CCFrameRateController::~CCFrameRateController()
m_timeSource->setActive(false);
}
+void CCFrameRateController::setActive(bool active)
+{
+ if (m_timeSource->active() == active)
+ return;
+ TRACE_EVENT("CCFrameRateController::setActive", 0, (active ? "active" : "inactive"));
+ m_timeSource->setActive(active);
+}
+
void CCFrameRateController::setMaxFramesPending(int maxFramesPending)
{
m_maxFramesPending = maxFramesPending;
@@ -69,9 +78,13 @@ void CCFrameRateController::setMaxFramesPending(int maxFramesPending)
void CCFrameRateController::onTimerTick()
{
+ ASSERT(m_timeSource->active());
+
// Don't forward the tick if we have too many frames in flight.
- if (m_maxFramesPending && m_numFramesPending >= m_maxFramesPending)
+ if (m_maxFramesPending && m_numFramesPending >= m_maxFramesPending) {
+ TRACE_EVENT("CCFrameRateController::onTimerTickButMaxFramesPending", 0, 0);
return;
+ }
if (m_client)
m_client->beginFrame();
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.h b/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.h
index b2281213d..a3eefe846 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.h
@@ -50,9 +50,10 @@ public:
void setClient(CCFrameRateControllerClient* client) { m_client = client; }
- void setActive(bool active) { m_timeSource->setActive(active); }
+ void setActive(bool);
void setMaxPendingFrames(int);
+
// Use the following methods to adjust target frame rate.
//
// Multiple frames can be in-progress, but for every didBeginFrame, a
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCInputHandler.h b/Source/WebCore/platform/graphics/chromium/cc/CCInputHandler.h
index 1c25fb194..057d79b1a 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCInputHandler.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCInputHandler.h
@@ -43,7 +43,6 @@ class IntSize;
class CCInputHandlerClient {
WTF_MAKE_NONCOPYABLE(CCInputHandlerClient);
public:
- virtual double currentTimeMs() const = 0;
virtual void setNeedsRedraw() = 0;
enum ScrollStatus { ScrollFailed, ScrollStarted, ScrollIgnored };
@@ -73,6 +72,7 @@ public:
virtual void startPageScaleAnimation(const IntSize& targetPosition,
bool anchorPoint,
float pageScale,
+ double startTimeMs,
double durationMs) = 0;
protected:
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp
new file mode 100644
index 000000000..bbca9cbd9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp
@@ -0,0 +1,223 @@
+/*
+ * 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 "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)
+{
+}
+
+void CCLayerAnimationControllerImpl::animate(double frameBeginTimeSecs)
+{
+ startAnimationsWaitingForNextTick(frameBeginTimeSecs);
+ startAnimationsWaitingForStartTime(frameBeginTimeSecs);
+ startAnimationsWaitingForTargetAvailability(frameBeginTimeSecs);
+ resolveConflicts(frameBeginTimeSecs);
+ tickAnimations(frameBeginTimeSecs);
+ purgeFinishedAnimations();
+ startAnimationsWaitingForTargetAvailability(frameBeginTimeSecs);
+}
+
+void CCLayerAnimationControllerImpl::add(PassOwnPtr<CCActiveAnimation> anim)
+{
+ m_activeAnimations.append(anim);
+ if (m_client)
+ m_client->animationControllerImplDidActivate(this);
+}
+
+CCActiveAnimation* CCLayerAnimationControllerImpl::getActiveAnimation(CCActiveAnimation::GroupID group, CCActiveAnimation::TargetProperty property)
+{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->group() == group && 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 now)
+{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForNextTick) {
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, now);
+ m_activeAnimations[i]->setStartTime(now);
+ }
+ }
+}
+
+void CCLayerAnimationControllerImpl::startAnimationsWaitingForStartTime(double now)
+{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForStartTime && m_activeAnimations[i]->startTime() <= now)
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, now);
+ }
+}
+
+void CCLayerAnimationControllerImpl::startAnimationsWaitingForTargetAvailability(double now)
+{
+ // 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, now);
+ m_activeAnimations[i]->setStartTime(now);
+ 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, now);
+ m_activeAnimations[j]->setStartTime(now);
+ }
+ }
+ }
+ }
+ }
+}
+
+void CCLayerAnimationControllerImpl::resolveConflicts(double now)
+{
+ // 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, now);
+ else
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Aborted, now);
+ }
+ }
+ }
+ }
+}
+
+void CCLayerAnimationControllerImpl::purgeFinishedAnimations()
+{
+ // 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)
+ m_activeAnimations.remove(i);
+ else
+ i++;
+ }
+}
+
+void CCLayerAnimationControllerImpl::tickAnimations(double now)
+{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running) {
+ double trimmed = m_activeAnimations[i]->trimTimeToCurrentIteration(now);
+ switch (m_activeAnimations[i]->targetProperty()) {
+
+ case CCActiveAnimation::Transform: {
+ const CCTransformAnimationCurve* transformAnimationCurve = m_activeAnimations[i]->animationCurve()->toTransformAnimationCurve();
+ const TransformOperations operations = transformAnimationCurve->getValue(trimmed);
+ if (m_activeAnimations[i]->isFinishedAt(now))
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, now);
+
+ // Decide here if absolute or relative. Absolute for now.
+ TransformationMatrix toApply;
+ operations.apply(FloatSize(), toApply);
+ m_client->setTransform(toApply);
+ break;
+ }
+
+ case CCActiveAnimation::Opacity: {
+ const CCFloatAnimationCurve* floatAnimationCurve = m_activeAnimations[i]->animationCurve()->toFloatAnimationCurve();
+ const float opacity = floatAnimationCurve->getValue(trimmed);
+ if (m_activeAnimations[i]->isFinishedAt(now))
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, now);
+
+ 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
new file mode 100644
index 000000000..1ad223dba
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.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:
+ * 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 <wtf/HashSet.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 float opacity() const = 0;
+ virtual void setOpacity(float) = 0;
+ virtual const TransformationMatrix& transform() const = 0;
+ virtual void setTransform(const TransformationMatrix&) = 0;
+ virtual void animationControllerImplDidActivate(CCLayerAnimationControllerImpl*) = 0;
+};
+
+class CCLayerAnimationControllerImpl {
+public:
+ static PassOwnPtr<CCLayerAnimationControllerImpl> create(CCLayerAnimationControllerImplClient*);
+
+ void animate(double frameBeginTimeSecs);
+
+ void add(PassOwnPtr<CCActiveAnimation>);
+
+ // Returns the active animation in the given group, animating the given property if such an
+ // animation exists.
+ CCActiveAnimation* getActiveAnimation(CCActiveAnimation::GroupID, CCActiveAnimation::TargetProperty);
+
+ // Returns true if there are any animations that are neither finished nor aborted.
+ bool hasActiveAnimation() const;
+
+private:
+ // The animator is owned by the layer.
+ explicit CCLayerAnimationControllerImpl(CCLayerAnimationControllerImplClient*);
+
+ void startAnimationsWaitingForNextTick(double now);
+ void startAnimationsWaitingForStartTime(double now);
+ void startAnimationsWaitingForTargetAvailability(double now);
+ void resolveConflicts(double now);
+ void purgeFinishedAnimations();
+
+ void tickAnimations(double now);
+
+ CCLayerAnimationControllerImplClient* m_client;
+ Vector<OwnPtr<CCActiveAnimation> > m_activeAnimations;
+};
+
+} // namespace WebCore
+
+#endif // CCLayerAnimationControllerImpl_h
+
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp
index 6837f0a5c..81f9712e0 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp
@@ -32,9 +32,9 @@
#include "GraphicsContext3D.h"
#include "LayerChromium.h"
#include "LayerRendererChromium.h"
-#include "cc/CCCustomLayerDrawQuad.h"
#include "cc/CCDebugBorderDrawQuad.h"
#include "cc/CCLayerSorter.h"
+#include "cc/CCSolidColorDrawQuad.h"
#include <wtf/text/WTFString.h>
namespace WebCore {
@@ -45,6 +45,7 @@ CCLayerImpl::CCLayerImpl(int id)
, m_anchorPoint(0.5, 0.5)
, m_anchorPointZ(0)
, m_scrollable(false)
+ , m_backgroundCoversViewport(false)
, m_doubleSided(true)
, m_layerPropertyChanged(false)
, m_masksToBounds(false)
@@ -129,8 +130,39 @@ PassOwnPtr<CCSharedQuadState> CCLayerImpl::createSharedQuadState() const
void CCLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState)
{
- IntRect quadRect(IntPoint(), bounds());
- quadList.append(CCCustomLayerDrawQuad::create(sharedQuadState, quadRect, this));
+ appendGutterQuads(quadList, sharedQuadState);
+}
+
+void CCLayerImpl::appendGutterQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState)
+{
+ 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()));
+ }
}
void CCLayerImpl::appendDebugBorderQuad(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState) const
@@ -138,7 +170,7 @@ void CCLayerImpl::appendDebugBorderQuad(CCQuadList& quadList, const CCSharedQuad
if (!hasDebugBorders())
return;
- IntRect layerRect(IntPoint(), bounds());
+ IntRect layerRect(IntPoint(), contentBounds());
quadList.append(CCDebugBorderDrawQuad::create(sharedQuadState, layerRect, debugBorderColor(), debugBorderWidth()));
}
@@ -342,6 +374,15 @@ void CCLayerImpl::setBackgroundColor(const Color& backgroundColor)
m_layerPropertyChanged = true;
}
+void CCLayerImpl::setBackgroundCoversViewport(bool backgroundCoversViewport)
+{
+ if (m_backgroundCoversViewport == backgroundCoversViewport)
+ return;
+
+ m_backgroundCoversViewport = backgroundCoversViewport;
+ m_layerPropertyChanged = true;
+}
+
void CCLayerImpl::setMasksToBounds(bool masksToBounds)
{
if (m_masksToBounds == masksToBounds)
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h
index 0136b01f8..00e0adf8a 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h
@@ -97,6 +97,9 @@ public:
void setBackgroundColor(const Color&);
Color backgroundColor() const { return m_backgroundColor; }
+ void setBackgroundCoversViewport(bool);
+ bool backgroundCoversViewport() const { return m_backgroundCoversViewport; }
+
void setMasksToBounds(bool);
bool masksToBounds() const { return m_masksToBounds; }
@@ -204,6 +207,8 @@ 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;
@@ -233,6 +238,7 @@ private:
IntPoint m_scrollPosition;
bool m_scrollable;
Color m_backgroundColor;
+ bool m_backgroundCoversViewport;
// Whether the "back" of this layer should draw.
bool m_doubleSided;
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp
index 8b8622b78..92637fc83 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp
@@ -96,7 +96,6 @@ CCLayerTilingData::Tile* CCLayerTilingData::tileAt(int i, int j) const
void CCLayerTilingData::reset()
{
m_tiles.clear();
- m_tilingData.setTotalSize(0, 0);
}
void CCLayerTilingData::layerRectToTileIndices(const IntRect& layerRect, int& left, int& top, int& right, int& bottom) const
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp
index 8663ec0ac..4ff8434b2 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp
@@ -29,6 +29,7 @@
#include "LayerChromium.h"
#include "LayerPainterChromium.h"
#include "LayerRendererChromium.h"
+#include "Region.h"
#include "TraceEvent.h"
#include "TreeSynchronizer.h"
#include "cc/CCLayerIterator.h"
@@ -95,6 +96,9 @@ bool CCLayerTreeHost::initialize()
// Update m_settings based on capabilities that we got back from the renderer.
m_settings.acceleratePainting = m_proxy->layerRendererCapabilities().usingAcceleratedPainting;
+ // Update m_settings based on partial update capability.
+ m_settings.partialTextureUpdates = m_settings.partialTextureUpdates && m_proxy->partialTextureUpdateCapability();
+
m_contentsTextureManager = TextureManager::create(TextureManager::highLimitBytes(viewportSize()),
TextureManager::reclaimLimitBytes(viewportSize()),
m_proxy->layerRendererCapabilities().maxTextureSize);
@@ -165,6 +169,7 @@ void CCLayerTreeHost::finishCommitOnImplThread(CCLayerTreeHostImpl* hostImpl)
void CCLayerTreeHost::commitComplete()
{
+ m_deleteTextureAfterCommitList.clear();
clearPendingUpdate();
m_contentsTextureManager->unprotectAllTextures();
}
@@ -181,10 +186,6 @@ PassOwnPtr<CCLayerTreeHostImpl> CCLayerTreeHost::createLayerTreeHostImpl(CCLayer
void CCLayerTreeHost::didRecreateGraphicsContext(bool success)
{
- if (m_rootLayer) {
- m_rootLayer->setLayerTreeHost(0);
- m_rootLayer->setLayerTreeHost(this);
- }
m_client->didRecreateGraphicsContext(success);
}
@@ -379,6 +380,8 @@ void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer)
CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootLayer, rootLayer, identityMatrix, identityMatrix, m_updateList, rootRenderSurface->layerList(), layerRendererCapabilities().maxTextureSize);
}
+ reserveTextures();
+
paintLayerContents(m_updateList, PaintVisible);
if (!m_triggerIdlePaints)
return;
@@ -397,13 +400,26 @@ void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer)
m_contentsTextureManager->setMaxMemoryLimitBytes(maxLimitBytes);
}
+void CCLayerTreeHost::reserveTextures()
+{
+ // Use BackToFront since it's cheap and this isn't order-dependent.
+ typedef CCLayerIterator<LayerChromium, RenderSurfaceChromium, CCLayerIteratorActions::BackToFront> CCLayerIteratorType;
+
+ CCLayerIteratorType end = CCLayerIteratorType::end(&m_updateList);
+ for (CCLayerIteratorType it = CCLayerIteratorType::begin(&m_updateList); it != end; ++it) {
+ if (it.representsTargetRenderSurface() || !it->alwaysReserveTextures())
+ continue;
+ it->reserveTextures();
+ }
+}
+
// static
-void CCLayerTreeHost::paintContentsIfDirty(LayerChromium* layer, PaintType paintType)
+void CCLayerTreeHost::paintContentsIfDirty(LayerChromium* layer, PaintType paintType, const Region& occludedScreenSpace)
{
ASSERT(layer);
ASSERT(PaintVisible == paintType || PaintIdle == paintType);
if (PaintVisible == paintType)
- layer->paintContentsIfDirty();
+ layer->paintContentsIfDirty(occludedScreenSpace);
else
layer->idlePaintContentsIfDirty();
}
@@ -414,35 +430,93 @@ void CCLayerTreeHost::paintMaskAndReplicaForRenderSurface(LayerChromium* renderS
// 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);
+ paintContentsIfDirty(renderSurfaceLayer->maskLayer(), paintType, noOcclusion);
}
LayerChromium* replicaLayer = renderSurfaceLayer->replicaLayer();
if (replicaLayer) {
- paintContentsIfDirty(replicaLayer, paintType);
+ paintContentsIfDirty(replicaLayer, paintType, noOcclusion);
if (replicaLayer->maskLayer()) {
replicaLayer->maskLayer()->setVisibleLayerRect(IntRect(IntPoint(), replicaLayer->maskLayer()->contentBounds()));
- paintContentsIfDirty(replicaLayer->maskLayer(), paintType);
+ paintContentsIfDirty(replicaLayer->maskLayer(), paintType, noOcclusion);
}
}
}
+struct RenderSurfaceRegion {
+ RenderSurfaceChromium* surface;
+ Region occludedInScreen;
+};
+
+// Add the surface to the top of the stack and copy the occlusion from the old top of the stack to the new.
+static void enterTargetRenderSurface(Vector<RenderSurfaceRegion>& stack, RenderSurfaceChromium* newTarget)
+{
+ if (stack.isEmpty()) {
+ stack.append(RenderSurfaceRegion());
+ stack.last().surface = newTarget;
+ } else if (stack.last().surface != newTarget) {
+ const RenderSurfaceRegion& previous = stack.last();
+ stack.append(RenderSurfaceRegion());
+ stack.last().surface = newTarget;
+ stack.last().occludedInScreen = previous.occludedInScreen;
+ }
+}
+
+// Pop the top of the stack off, push on the new surface, and merge the old top's occlusion into the new top surface.
+static void leaveTargetRenderSurface(Vector<RenderSurfaceRegion>& stack, RenderSurfaceChromium* newTarget)
+{
+ int lastIndex = stack.size() - 1;
+ bool surfaceWillBeAtTopAfterPop = stack.size() > 1 && stack[lastIndex - 1].surface == newTarget;
+
+ if (surfaceWillBeAtTopAfterPop) {
+ // Merge the top of the stack down.
+ stack[lastIndex - 1].occludedInScreen.unite(stack[lastIndex].occludedInScreen);
+ stack.removeLast();
+ } else {
+ // Replace the top of the stack with the new pushed surface. Copy the occluded region to the top.
+ stack.last().surface = newTarget;
+ }
+}
+
void CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList, PaintType paintType)
{
// Use FrontToBack to allow for testing occlusion and performing culling during the tree walk.
typedef CCLayerIterator<LayerChromium, RenderSurfaceChromium, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
+ // The stack holds occluded regions for subtrees in the RenderSurface-Layer tree, so that when we leave a subtree we may
+ // apply a mask to it, but not to the parts outside the subtree.
+ // - The first time we see a new subtree under a target, we add that target to the top of the stack. This can happen as a layer representing itself, or as a target surface.
+ // - When we visit a target surface, we apply its mask to its subtree, which is at the top of the stack.
+ // - When we visit a layer representing itself, we add its occlusion to the current subtree, which is at the top of the stack.
+ // - When we visit a layer representing a contributing surface, the current target will never be the top of the stack since we just came from the contributing surface.
+ // We merge the occlusion at the top of the stack with the new current subtree. This new target is pushed onto the stack if not already there.
+ Vector<RenderSurfaceRegion> targetSurfaceStack;
+
CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
if (it.representsTargetRenderSurface()) {
ASSERT(it->renderSurface()->drawOpacity());
+
+ enterTargetRenderSurface(targetSurfaceStack, it->renderSurface());
paintMaskAndReplicaForRenderSurface(*it, paintType);
+ // FIXME: add the replica layer to the current occlusion
+
+ if (it->maskLayer() || it->renderSurface()->drawOpacity() < 1)
+ targetSurfaceStack.last().occludedInScreen = Region();
} else if (it.representsItself()) {
ASSERT(!it->bounds().isEmpty());
- paintContentsIfDirty(*it, paintType);
+
+ enterTargetRenderSurface(targetSurfaceStack, it->targetRenderSurface());
+ paintContentsIfDirty(*it, paintType, targetSurfaceStack.last().occludedInScreen);
+ it->addSelfToOccludedScreenSpace(targetSurfaceStack.last().occludedInScreen);
+ } else {
+ leaveTargetRenderSurface(targetSurfaceStack, it.targetRenderSurfaceLayer()->renderSurface());
}
}
}
@@ -514,4 +588,9 @@ void CCLayerTreeHost::stopRateLimiter(GraphicsContext3D* context)
}
}
+void CCLayerTreeHost::deleteTextureAfterCommit(PassOwnPtr<ManagedTexture> texture)
+{
+ m_deleteTextureAfterCommitList.append(texture);
+}
+
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h
index 2f989bcf6..f58203d15 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h
@@ -48,6 +48,7 @@ class CCLayerTreeHostImpl;
class CCTextureUpdater;
class GraphicsContext3D;
class LayerPainterChromium;
+class Region;
class TextureAllocator;
class TextureManager;
@@ -76,7 +77,8 @@ struct CCSettings {
, showPlatformLayerTree(false)
, refreshRate(0)
, perTilePainting(false)
- , partialSwapEnabled(false) { }
+ , partialSwapEnabled(false)
+ , partialTextureUpdates(true) { }
bool acceleratePainting;
bool compositeOffscreen;
@@ -85,6 +87,7 @@ struct CCSettings {
double refreshRate;
bool perTilePainting;
bool partialSwapEnabled;
+ bool partialTextureUpdates;
};
// Provides information on an Impl's rendering capabilities back to the CCLayerTreeHost
@@ -192,19 +195,24 @@ public:
void startRateLimiter(GraphicsContext3D*);
void stopRateLimiter(GraphicsContext3D*);
+ void deleteTextureAfterCommit(PassOwnPtr<ManagedTexture>);
+
protected:
CCLayerTreeHost(CCLayerTreeHostClient*, const CCSettings&);
bool initialize();
private:
typedef Vector<RefPtr<LayerChromium> > LayerList;
+ typedef Vector<OwnPtr<ManagedTexture> > TextureList;
enum PaintType { PaintVisible, PaintIdle };
- static void paintContentsIfDirty(LayerChromium*, PaintType);
+ static void paintContentsIfDirty(LayerChromium*, PaintType, const Region& occludedScreenSpace);
void paintLayerContents(const LayerList&, PaintType);
void paintMaskAndReplicaForRenderSurface(LayerChromium*, PaintType);
void updateLayers(LayerChromium*);
+ // Pre-reserve textures for any layer marked "always reserve textures"
+ void reserveTextures();
void clearPendingUpdate();
int m_compositorIdentifier;
@@ -233,6 +241,8 @@ private:
float m_pageScale;
float m_minPageScale, m_maxPageScale;
bool m_triggerIdlePaints;
+
+ TextureList m_deleteTextureAfterCommitList;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp
index 02186caaf..1846d6c2e 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp
@@ -114,7 +114,7 @@ void CCLayerTreeHostImpl::animate(double frameBeginTimeMs)
}
}
-void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double durationMs)
+void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTimeMs, double durationMs)
{
if (!m_scrollLayerImpl)
return;
@@ -122,10 +122,10 @@ void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition,
IntSize scrollTotal = toSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
scrollTotal.scale(m_pageScaleDelta);
float scaleTotal = m_pageScale * m_pageScaleDelta;
- IntSize scaledContentSize = m_scrollLayerImpl->children()[0]->contentBounds();
+ IntSize scaledContentSize = contentSize();
scaledContentSize.scale(m_pageScaleDelta);
- m_pageScaleAnimation = CCPageScaleAnimation::create(scrollTotal, scaleTotal, m_viewportSize, scaledContentSize, currentTimeMs());
+ m_pageScaleAnimation = CCPageScaleAnimation::create(scrollTotal, scaleTotal, m_viewportSize, scaledContentSize, startTimeMs);
if (anchorPoint) {
IntSize windowAnchor(targetPosition);
@@ -244,6 +244,15 @@ void CCLayerTreeHostImpl::optimizeRenderPasses(CCRenderPassList& passes)
passes[i]->optimizeQuads();
}
+IntSize CCLayerTreeHostImpl::contentSize() const
+{
+ // TODO(aelias): Hardcoding the first child here is weird. Think of
+ // a cleaner way to get the contentBounds on the Impl side.
+ if (!m_scrollLayerImpl || m_scrollLayerImpl->children().isEmpty())
+ return IntSize();
+ return m_scrollLayerImpl->children()[0]->contentBounds();
+}
+
void CCLayerTreeHostImpl::drawLayers()
{
TRACE_EVENT("CCLayerTreeHostImpl::drawLayers", this, 0);
@@ -346,14 +355,6 @@ bool CCLayerTreeHostImpl::initializeLayerRenderer(PassRefPtr<GraphicsContext3D>
OwnPtr<LayerRendererChromium> layerRenderer;
layerRenderer = LayerRendererChromium::create(this, context);
- // If creation failed, and we had asked for accelerated painting, disable accelerated painting
- // and try creating the renderer again.
- if (!layerRenderer && m_settings.acceleratePainting) {
- m_settings.acceleratePainting = false;
-
- layerRenderer = LayerRendererChromium::create(this, context);
- }
-
if (m_layerRenderer)
m_layerRenderer->close();
@@ -368,7 +369,9 @@ void CCLayerTreeHostImpl::setViewportSize(const IntSize& viewportSize)
m_viewportSize = viewportSize;
updateMaxScrollPosition();
- m_layerRenderer->viewportChanged();
+
+ if (m_layerRenderer)
+ m_layerRenderer->viewportChanged();
}
void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScale, float minPageScale, float maxPageScale)
@@ -438,9 +441,7 @@ void CCLayerTreeHostImpl::updateMaxScrollPosition()
FloatSize viewBounds = m_viewportSize;
viewBounds.scale(1 / m_pageScaleDelta);
- // TODO(aelias): Hardcoding the first child here is weird. Think of
- // a cleaner way to get the contentBounds on the Impl side.
- IntSize maxScroll = m_scrollLayerImpl->children()[0]->contentBounds() - expandedIntSize(viewBounds);
+ IntSize maxScroll = contentSize() - expandedIntSize(viewBounds);
// The viewport may be larger than the contents in some cases, such as
// having a vertical scrollbar but no horizontal overflow.
maxScroll.clampNegativeToZero();
@@ -450,11 +451,6 @@ void CCLayerTreeHostImpl::updateMaxScrollPosition()
// TODO(aelias): Also update sublayers.
}
-double CCLayerTreeHostImpl::currentTimeMs() const
-{
- return monotonicallyIncreasingTime() * 1000.0;
-}
-
void CCLayerTreeHostImpl::setNeedsRedraw()
{
m_client->setNeedsRedrawOnImplThread();
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h
index e4d006d4f..a71adae67 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h
@@ -61,8 +61,7 @@ public:
static PassOwnPtr<CCLayerTreeHostImpl> create(const CCSettings&, CCLayerTreeHostImplClient*);
virtual ~CCLayerTreeHostImpl();
- // CCInputHandlerTarget implementation
- virtual double currentTimeMs() const;
+ // CCInputHandlerClient implementation
virtual void setNeedsRedraw();
virtual CCInputHandlerClient::ScrollStatus scrollBegin(const IntPoint&);
virtual void scrollBy(const IntSize&);
@@ -71,6 +70,7 @@ public:
virtual void pinchGestureBegin();
virtual void pinchGestureUpdate(float, const IntPoint&);
virtual void pinchGestureEnd();
+ virtual void startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTimeMs, double durationMs);
// Virtual for testing
virtual void beginCommit();
@@ -113,8 +113,6 @@ public:
void setPageScaleFactorAndLimits(float pageScale, float minPageScale, float maxPageScale);
float pageScale() const { return m_pageScale; }
- void startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double durationMs);
-
const CCSettings& settings() const { return m_settings; }
PassOwnPtr<CCScrollAndScaleSet> processScrollDeltas();
@@ -135,6 +133,7 @@ private:
void trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList);
void calculateRenderPasses(CCRenderPassList&);
void optimizeRenderPasses(CCRenderPassList&);
+ IntSize contentSize() const;
OwnPtr<LayerRendererChromium> m_layerRenderer;
RefPtr<CCLayerImpl> m_rootLayerImpl;
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCustomLayerDrawQuad.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.cpp
index 8580b10ed..fd2ae4b86 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCCustomLayerDrawQuad.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.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
@@ -25,17 +25,17 @@
#include "config.h"
-#include "cc/CCCustomLayerDrawQuad.h"
+#include "cc/CCPluginDrawQuad.h"
namespace WebCore {
-PassOwnPtr<CCCustomLayerDrawQuad> CCCustomLayerDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCLayerImpl* layer)
+PassOwnPtr<CCPluginDrawQuad> CCPluginDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCLayerImpl* layer)
{
- return adoptPtr(new CCCustomLayerDrawQuad(sharedQuadState, quadRect, layer));
+ return adoptPtr(new CCPluginDrawQuad(sharedQuadState, quadRect, layer));
}
-CCCustomLayerDrawQuad::CCCustomLayerDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCLayerImpl* layer)
- : CCDrawQuad(sharedQuadState, CCDrawQuad::CustomLayer, quadRect)
+CCPluginDrawQuad::CCPluginDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCLayerImpl* layer)
+ : CCDrawQuad(sharedQuadState, CCDrawQuad::PluginContent, quadRect)
, m_layer(layer)
{
ASSERT(m_layer);
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCustomLayerDrawQuad.h b/Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.h
index a9bd46232..ca52abef4 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCCustomLayerDrawQuad.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.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,8 +23,8 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef CCCustomLayerDrawQuad_h
-#define CCCustomLayerDrawQuad_h
+#ifndef CCPluginDrawQuad_h
+#define CCPluginDrawQuad_h
#include "cc/CCDrawQuad.h"
#include <wtf/PassOwnPtr.h>
@@ -33,18 +33,15 @@ namespace WebCore {
class CCLayerImpl;
-// FIXME: This class is a temporary way to access CCLayerImpl::draw. This class
-// should be converted to a set of draw quads for each layer material type and
-// then removed.
-class CCCustomLayerDrawQuad : public CCDrawQuad {
- WTF_MAKE_NONCOPYABLE(CCCustomLayerDrawQuad);
+class CCPluginDrawQuad : public CCDrawQuad {
+ WTF_MAKE_NONCOPYABLE(CCPluginDrawQuad);
public:
- static PassOwnPtr<CCCustomLayerDrawQuad> create(const CCSharedQuadState*, const IntRect&, CCLayerImpl*);
+ static PassOwnPtr<CCPluginDrawQuad> create(const CCSharedQuadState*, const IntRect&, CCLayerImpl*);
CCLayerImpl* layer() const { return m_layer; }
private:
- CCCustomLayerDrawQuad(const CCSharedQuadState*, const IntRect&, CCLayerImpl*);
+ CCPluginDrawQuad(const CCSharedQuadState*, const IntRect&, CCLayerImpl*);
CCLayerImpl* m_layer;
};
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp
index bc105bb4b..b20a2f518 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp
@@ -32,6 +32,7 @@
#include "Extensions3DChromium.h"
#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h"
+#include "cc/CCPluginDrawQuad.h"
#include "cc/CCProxy.h"
#include <wtf/text/WTFString.h>
@@ -176,6 +177,11 @@ void CCPluginLayerImpl::draw(LayerRendererChromium* layerRenderer)
}
}
+void CCPluginLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState)
+{
+ IntRect quadRect(IntPoint(), bounds());
+ quadList.append(CCPluginDrawQuad::create(sharedQuadState, quadRect, this));
+}
void CCPluginLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
{
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h
index e09826a34..9b4d5a4d3 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h
@@ -41,6 +41,8 @@ public:
}
virtual ~CCPluginLayerImpl();
+ virtual void appendQuads(CCQuadList&, const CCSharedQuadState*);
+
typedef ProgramBinding<VertexShaderPosTexStretch, FragmentShaderRGBATexAlpha> Program;
typedef ProgramBinding<VertexShaderPosTexStretch, FragmentShaderRGBATexFlipAlpha> ProgramFlip;
typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexRectAlpha> TexRectProgram;
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCProxy.h b/Source/WebCore/platform/graphics/chromium/cc/CCProxy.h
index bb3780147..937c154ff 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCProxy.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCProxy.h
@@ -79,6 +79,10 @@ public:
virtual void start() = 0; // Must be called before using the proxy.
virtual void stop() = 0; // Must be called before deleting the proxy.
+ // Whether sub-regions of textures can be updated or if complete texture
+ // updates are required.
+ virtual bool partialTextureUpdateCapability() const = 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 4a8b85130..c8bd9b0f3 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp
@@ -31,11 +31,12 @@
#include "Region.h"
#include "TransformationMatrix.h"
-#include "cc/CCCustomLayerDrawQuad.h"
#include "cc/CCLayerImpl.h"
#include "cc/CCRenderPass.h"
#include "cc/CCRenderSurfaceDrawQuad.h"
+using namespace std;
+
namespace std {
// Specialize for OwnPtr<CCDrawQuad> since Vector doesn't know how to reverse a Vector of OwnPtr<T> in general.
@@ -49,16 +50,29 @@ void swap(OwnPtr<WebCore::CCDrawQuad>& a, OwnPtr<WebCore::CCDrawQuad>& b)
namespace WebCore {
-static bool regionContainsRect(const Region& region, const IntRect& rect)
+// 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)
{
Region rectRegion(rect);
Region intersectRegion(intersect(region, rectRegion));
if (intersectRegion.isEmpty())
- return false;
+ return rect;
+ // Test if intersectRegion = rectRegion, if so return empty rect.
rectRegion.subtract(intersectRegion);
- return rectRegion.isEmpty();
+ 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;
}
void CCQuadCuller::cullOccludedQuads(CCQuadList& quadList)
@@ -74,12 +88,23 @@ void CCQuadCuller::cullOccludedQuads(CCQuadList& quadList)
for (int i = quadList.size() - 1; i >= 0; --i) {
CCDrawQuad* drawQuad = quadList[i].get();
- IntRect quadRect(drawQuad->quadTransform().mapRect(drawQuad->quadRect()));
+ FloatRect floatTransformedRect = drawQuad->quadTransform().mapRect(FloatRect(drawQuad->quadRect()));
+ // Inflate rect to be tested to stay conservative.
+ IntRect transformedQuadRect(enclosingIntRect(floatTransformedRect));
+
+ IntRect transformedVisibleQuadRect = rectSubtractRegion(opaqueCoverageThusFar, transformedQuadRect);
+ bool keepQuad = !transformedVisibleQuadRect.isEmpty();
- bool keepQuad = !regionContainsRect(opaqueCoverageThusFar, quadRect);
+ // 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.
+ if (keepQuad && transformedVisibleQuadRect != transformedQuadRect && drawQuad->isLayerAxisAlignedIntRect())
+ drawQuad->setQuadVisibleRect(drawQuad->quadTransform().inverse().mapRect(transformedVisibleQuadRect));
- if (keepQuad && drawQuad->drawsOpaque() && drawQuad->isLayerAxisAlignedIntRect())
- opaqueCoverageThusFar.unite(Region(quadRect));
+ // When adding rect to opaque region, deflate it to stay conservative.
+ if (keepQuad && drawQuad->isLayerAxisAlignedIntRect()) {
+ FloatRect floatOpaqueRect = drawQuad->quadTransform().mapRect(FloatRect(drawQuad->opaqueRect()));
+ opaqueCoverageThusFar.unite(Region(enclosedIntRect(floatOpaqueRect)));
+ }
if (keepQuad)
culledList.append(quadList[i].release());
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp
index 812a0c708..8580467f0 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp
@@ -36,9 +36,7 @@ CCScheduler::CCScheduler(CCSchedulerClient* client, PassOwnPtr<CCFrameRateContro
{
ASSERT(m_client);
m_frameRateController->setClient(this);
-
- // FIXME: make the CCSchedulerStateMachine turn off FrameRateController it isn't needed.
- m_frameRateController->setActive(true);
+ m_frameRateController->setActive(m_stateMachine.vsyncCallbackNeeded());
}
CCScheduler::~CCScheduler()
@@ -49,7 +47,9 @@ CCScheduler::~CCScheduler()
void CCScheduler::setVisible(bool visible)
{
m_stateMachine.setVisible(visible);
+ processScheduledActions();
}
+
void CCScheduler::setNeedsCommit()
{
m_stateMachine.setNeedsCommit();
@@ -114,8 +114,10 @@ CCSchedulerStateMachine::Action CCScheduler::nextAction()
void CCScheduler::processScheduledActions()
{
// Early out so we don't spam TRACE_EVENTS with useless processScheduledActions.
- if (nextAction() == CCSchedulerStateMachine::ACTION_NONE)
+ if (nextAction() == CCSchedulerStateMachine::ACTION_NONE) {
+ m_frameRateController->setActive(m_stateMachine.vsyncCallbackNeeded());
return;
+ }
// This function can re-enter itself. For example, draw may call
// setNeedsCommit. Proceeed with caution.
@@ -151,6 +153,9 @@ void CCScheduler::processScheduledActions()
break;
}
} while (action != CCSchedulerStateMachine::ACTION_NONE);
+
+ // Activate or deactivate the frame rate controller.
+ m_frameRateController->setActive(m_stateMachine.vsyncCallbackNeeded());
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp
index 05b4f6cb6..d1aa5ccdc 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp
@@ -118,6 +118,18 @@ void CCSchedulerStateMachine::updateState(Action action)
}
}
+bool CCSchedulerStateMachine::vsyncCallbackNeeded() const
+{
+ if (!m_visible) {
+ if (m_needsForcedRedraw)
+ return true;
+
+ return false;
+ }
+
+ return m_needsRedraw || m_needsForcedRedraw || m_updateMoreResourcesPending;
+}
+
void CCSchedulerStateMachine::didEnterVSync()
{
m_insideVSync = true;
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h b/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h
index 2d7da7ee3..7de718846 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h
@@ -68,6 +68,10 @@ public:
Action nextAction() const;
void updateState(Action);
+ // Indicates whether the scheduler needs a vsync callback in order to make
+ // progress.
+ bool vsyncCallbackNeeded() const;
+
// Indicates that the system has entered and left a vsync callback.
// The scheduler will not draw more than once in a given vsync callback.
void didEnterVSync();
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h
index 0d5a4a2d8..4faa22999 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h
@@ -54,6 +54,7 @@ public:
virtual void setVisible(bool);
virtual void start();
virtual void stop();
+ virtual bool partialTextureUpdateCapability() const { return true; }
// CCLayerTreeHostImplClient implementation
virtual void onSwapBuffersCompleteOnImplThread() { ASSERT_NOT_REACHED(); }
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorDrawQuad.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorDrawQuad.cpp
index d1c729a41..7f6f98113 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorDrawQuad.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorDrawQuad.cpp
@@ -38,8 +38,10 @@ CCSolidColorDrawQuad::CCSolidColorDrawQuad(const CCSharedQuadState* sharedQuadSt
: CCDrawQuad(sharedQuadState, CCDrawQuad::SolidColor, quadRect)
, m_color(color)
{
- if (m_color.alpha() != 1)
+ if (m_color.hasAlpha())
m_quadOpaque = false;
+ else
+ m_opaqueRect = quadRect;
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.cpp
new file mode 100644
index 000000000..864aff30a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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 "cc/CCSolidColorLayerImpl.h"
+
+#include "LayerRendererChromium.h"
+#include "cc/CCSolidColorDrawQuad.h"
+#include <wtf/MathExtras.h>
+#include <wtf/text/WTFString.h>
+
+using namespace std;
+
+namespace WebCore {
+
+CCSolidColorLayerImpl::CCSolidColorLayerImpl(int id)
+ : CCLayerImpl(id)
+ , m_tileSize(256)
+{
+}
+
+CCSolidColorLayerImpl::~CCSolidColorLayerImpl()
+{
+}
+
+TransformationMatrix CCSolidColorLayerImpl::quadTransform() const
+{
+ TransformationMatrix solidColorTransform = drawTransform();
+ solidColorTransform.translate(-bounds().width() / 2.0, -bounds().height() / 2.0);
+
+ return solidColorTransform;
+}
+
+void CCSolidColorLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState)
+{
+ // We create a series of smaller quads instead of just one large one so that the
+ // culler can reduce the total pixels drawn.
+ int width = bounds().width();
+ int height = bounds().height();
+ for (int x = 0; x < width; x += m_tileSize) {
+ for (int y = 0; y < height; y += m_tileSize) {
+ IntRect solidTileRect(x, y, min(width - x, m_tileSize), min(height - y, m_tileSize));
+ quadList.append(CCSolidColorDrawQuad::create(sharedQuadState, solidTileRect, backgroundColor()));
+ }
+ }
+}
+
+} // namespace WebCore
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.h
new file mode 100644
index 000000000..c7edc18b2
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.h
@@ -0,0 +1,58 @@
+/*
+ * 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 CCSolidColorLayerImpl_h
+#define CCSolidColorLayerImpl_h
+
+#include "TransformationMatrix.h"
+#include "cc/CCLayerImpl.h"
+
+namespace WebCore {
+
+class LayerRendererChromium;
+
+class CCSolidColorLayerImpl : public CCLayerImpl {
+public:
+ static PassRefPtr<CCSolidColorLayerImpl> create(int id)
+ {
+ return adoptRef(new CCSolidColorLayerImpl(id));
+ }
+ virtual ~CCSolidColorLayerImpl();
+
+ virtual TransformationMatrix quadTransform() const;
+ virtual void appendQuads(CCQuadList&, const CCSharedQuadState*);
+
+protected:
+ explicit CCSolidColorLayerImpl(int id);
+
+private:
+ virtual const char* layerTypeAsString() const { return "SolidColorLayer"; }
+
+ const int m_tileSize;
+};
+
+}
+
+#endif // CCSolidColorLayerImpl_h
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp
index 903313513..5e6a8f862 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp
@@ -41,6 +41,12 @@
using namespace WTF;
+namespace {
+
+static const size_t textureUpdatesPerFrame = 0;
+
+} // anonymous namespace
+
namespace WebCore {
PassOwnPtr<CCProxy> CCThreadProxy::create(CCLayerTreeHost* layerTreeHost)
@@ -438,8 +444,7 @@ void CCThreadProxy::scheduledActionUpdateMoreResources()
{
TRACE_EVENT("CCThreadProxy::scheduledActionUpdateMoreResources", this, 0);
ASSERT(m_currentTextureUpdaterOnImplThread);
- static const int UpdatesPerFrame = 99999;
- m_currentTextureUpdaterOnImplThread->update(m_layerTreeHostImpl->context(), UpdatesPerFrame);
+ m_currentTextureUpdaterOnImplThread->update(m_layerTreeHostImpl->context(), textureUpdatesPerFrame > 0 ? textureUpdatesPerFrame : 99999);
}
void CCThreadProxy::scheduledActionCommit()
@@ -528,8 +533,7 @@ void CCThreadProxy::initializeImplOnImplThread(CCCompletionEvent* completion)
TRACE_EVENT("CCThreadProxy::initializeImplOnImplThread", this, 0);
ASSERT(isImplThread());
m_layerTreeHostImpl = m_layerTreeHost->createLayerTreeHostImpl(this);
- ASSERT(m_layerTreeHostImpl->settings().refreshRate > 0);
- const double displayRefreshIntervalMs = 1000.0 / m_layerTreeHostImpl->settings().refreshRate;
+ const double displayRefreshIntervalMs = 1000.0 / 60.0;
OwnPtr<CCFrameRateController> frameRateController = adoptPtr(new CCFrameRateController(CCDelayBasedTimeSource::create(displayRefreshIntervalMs, CCProxy::implThread())));
m_schedulerOnImplThread = CCScheduler::create(this, frameRateController.release());
m_schedulerOnImplThread->setVisible(m_layerTreeHostImpl->visible());
@@ -565,4 +569,9 @@ void CCThreadProxy::layerTreeHostClosedOnImplThread(CCCompletionEvent* completio
completion->signal();
}
+bool CCThreadProxy::partialTextureUpdateCapability() const
+{
+ return !textureUpdatesPerFrame;
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h
index a41c0d564..a11b52785 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h
@@ -62,6 +62,7 @@ public:
virtual void setVisible(bool);
virtual void start();
virtual void stop();
+ virtual bool partialTextureUpdateCapability() const;
// CCLayerTreeHostImplClient implementation
virtual void onSwapBuffersCompleteOnImplThread();
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTileDrawQuad.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCTileDrawQuad.cpp
index df830508a..b35b6f69f 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCTileDrawQuad.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCTileDrawQuad.cpp
@@ -29,12 +29,12 @@
namespace WebCore {
-PassOwnPtr<CCTileDrawQuad> CCTileDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, Platform3DObject textureId, const IntPoint& textureOffset, const IntSize& textureSize, GC3Dint textureFilter, bool swizzleContents, bool leftEdgeAA, bool topEdgeAA, bool rightEdgeAA, bool bottomEdgeAA)
+PassOwnPtr<CCTileDrawQuad> CCTileDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const IntRect& opaqueRect, Platform3DObject textureId, const IntPoint& textureOffset, const IntSize& textureSize, GC3Dint textureFilter, bool swizzleContents, bool leftEdgeAA, bool topEdgeAA, bool rightEdgeAA, bool bottomEdgeAA)
{
- return adoptPtr(new CCTileDrawQuad(sharedQuadState, quadRect, textureId, textureOffset, textureSize, textureFilter, swizzleContents, leftEdgeAA, topEdgeAA, rightEdgeAA, bottomEdgeAA));
+ return adoptPtr(new CCTileDrawQuad(sharedQuadState, quadRect, opaqueRect, textureId, textureOffset, textureSize, textureFilter, swizzleContents, leftEdgeAA, topEdgeAA, rightEdgeAA, bottomEdgeAA));
}
-CCTileDrawQuad::CCTileDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, Platform3DObject textureId, const IntPoint& textureOffset, const IntSize& textureSize, GC3Dint textureFilter, bool swizzleContents, bool leftEdgeAA, bool topEdgeAA, bool rightEdgeAA, bool bottomEdgeAA)
+CCTileDrawQuad::CCTileDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const IntRect& opaqueRect, Platform3DObject textureId, const IntPoint& textureOffset, const IntSize& textureSize, GC3Dint textureFilter, bool swizzleContents, bool leftEdgeAA, bool topEdgeAA, bool rightEdgeAA, bool bottomEdgeAA)
: CCDrawQuad(sharedQuadState, CCDrawQuad::TiledContent, quadRect)
, m_textureId(textureId)
, m_textureOffset(textureOffset)
@@ -48,6 +48,7 @@ CCTileDrawQuad::CCTileDrawQuad(const CCSharedQuadState* sharedQuadState, const I
{
if (isAntialiased())
m_needsBlending = true;
+ m_opaqueRect = opaqueRect;
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTileDrawQuad.h b/Source/WebCore/platform/graphics/chromium/cc/CCTileDrawQuad.h
index 12e53dbd2..33501a806 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCTileDrawQuad.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCTileDrawQuad.h
@@ -35,7 +35,7 @@ namespace WebCore {
class CCTileDrawQuad : public CCDrawQuad {
WTF_MAKE_NONCOPYABLE(CCTileDrawQuad);
public:
- static PassOwnPtr<CCTileDrawQuad> create(const CCSharedQuadState*, const IntRect& quadRect, Platform3DObject textureId, const IntPoint& textureOffset, const IntSize& textureSize, GC3Dint textureFilter, bool swizzleContents, bool leftEdgeAA, bool topEdgeAA, bool rightEdgeAA, bool bottomEdgeAA);
+ static PassOwnPtr<CCTileDrawQuad> create(const CCSharedQuadState*, const IntRect& quadRect, const IntRect& opaqueRect, Platform3DObject textureId, const IntPoint& textureOffset, const IntSize& textureSize, GC3Dint textureFilter, bool swizzleContents, bool leftEdgeAA, bool topEdgeAA, bool rightEdgeAA, bool bottomEdgeAA);
Platform3DObject textureId() const { return m_textureId; }
IntPoint textureOffset() const { return m_textureOffset; }
@@ -51,7 +51,7 @@ public:
bool isAntialiased() const { return leftEdgeAA() || topEdgeAA() || rightEdgeAA() || bottomEdgeAA(); }
private:
- CCTileDrawQuad(const CCSharedQuadState*, const IntRect& quadRect, Platform3DObject textureId, const IntPoint& textureOffset, const IntSize& textureSize, GC3Dint textureFilter, bool swizzleContents, bool leftEdgeAA, bool topEdgeAA, bool rightEdgeAA, bool bottomEdgeAA);
+ CCTileDrawQuad(const CCSharedQuadState*, const IntRect& quadRect, const IntRect& opaqueRect, Platform3DObject textureId, const IntPoint& textureOffset, const IntSize& textureSize, GC3Dint textureFilter, bool swizzleContents, bool leftEdgeAA, bool topEdgeAA, bool rightEdgeAA, bool bottomEdgeAA);
Platform3DObject m_textureId;
IntPoint m_textureOffset;
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp
index 5849ef1eb..80a0435fd 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp
@@ -51,8 +51,13 @@ public:
Platform3DObject textureId() const { return m_textureId; }
void setTextureId(Platform3DObject textureId) { m_textureId = textureId; }
+
+ const IntRect& opaqueRect() const { return m_opaqueRect; }
+ void setOpaqueRect(const IntRect& opaqueRect) { m_opaqueRect = opaqueRect; }
+
private:
Platform3DObject m_textureId;
+ IntRect m_opaqueRect;
};
CCTiledLayerImpl::CCTiledLayerImpl(int id)
@@ -122,7 +127,12 @@ void CCTiledLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState
{
const IntRect& layerRect = visibleLayerRect();
- if (m_skipsDraw || !m_tiler || m_tiler->isEmpty() || layerRect.isEmpty())
+ if (m_skipsDraw)
+ return;
+
+ appendGutterQuads(quadList, sharedQuadState);
+
+ if (!m_tiler || !m_tiler->numTiles() || layerRect.isEmpty())
return;
int left, top, right, bottom;
@@ -143,6 +153,9 @@ void CCTiledLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState
continue;
}
+ IntRect tileOpaqueRect = tile->opaqueRect();
+ tileOpaqueRect.intersect(layerRect);
+
// Keep track of how the top left has moved, so the texture can be
// offset the same amount.
IntSize displayOffset = tileRect.minXMinYCorner() - displayRect.minXMinYCorner();
@@ -159,7 +172,7 @@ void CCTiledLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState
bool bottomEdgeAA = j == m_tiler->numTilesY() - 1 && useAA;
const GC3Dint textureFilter = m_tiler->hasBorderTexels() ? GraphicsContext3D::LINEAR : GraphicsContext3D::NEAREST;
- quadList.append(CCTileDrawQuad::create(sharedQuadState, tileRect, tile->textureId(), textureOffset, textureSize, textureFilter, contentsSwizzled(), leftEdgeAA, topEdgeAA, rightEdgeAA, bottomEdgeAA));
+ 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);
@@ -178,14 +191,15 @@ void CCTiledLayerImpl::setTilingData(const CCLayerTilingData& tiler)
*m_tiler = tiler;
}
-void CCTiledLayerImpl::syncTextureId(int i, int j, Platform3DObject textureId)
+void CCTiledLayerImpl::pushTileProperties(int i, int j, Platform3DObject textureId, const IntRect& opaqueRect)
{
DrawableTile* tile = tileAt(i, j);
if (!tile)
tile = createTile(i, j);
tile->setTextureId(textureId);
+ tile->setOpaqueRect(opaqueRect);
}
-}
+} // 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 478b03402..7ad71599b 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.h
@@ -51,7 +51,7 @@ public:
void setSkipsDraw(bool skipsDraw) { m_skipsDraw = skipsDraw; }
void setTilingData(const CCLayerTilingData& tiler);
- void syncTextureId(int, int, Platform3DObject textureId);
+ void pushTileProperties(int, int, Platform3DObject textureId, const IntRect& opaqueRect);
void setContentsSwizzled(bool contentsSwizzled) { m_contentsSwizzled = contentsSwizzled; }
bool contentsSwizzled() const { return m_contentsSwizzled; }
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTimeSource.h b/Source/WebCore/platform/graphics/chromium/cc/CCTimeSource.h
index ddb21f7b1..dccb470a6 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCTimeSource.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCTimeSource.h
@@ -49,6 +49,7 @@ public:
virtual ~CCTimeSource() { }
virtual void setClient(CCTimeSourceClient*) = 0;
virtual void setActive(bool) = 0;
+ virtual bool active() const = 0;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.cpp
new file mode 100644
index 000000000..3de38e90f
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.cpp
@@ -0,0 +1,44 @@
+/*
+ * 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/CCVideoDrawQuad.h"
+
+namespace WebCore {
+
+PassOwnPtr<CCVideoDrawQuad> CCVideoDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCLayerImpl* layer)
+{
+ return adoptPtr(new CCVideoDrawQuad(sharedQuadState, quadRect, layer));
+}
+
+CCVideoDrawQuad::CCVideoDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCLayerImpl* layer)
+ : CCDrawQuad(sharedQuadState, CCDrawQuad::VideoContent, quadRect)
+ , m_layer(layer)
+{
+ ASSERT(m_layer);
+}
+
+}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.h b/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.h
new file mode 100644
index 000000000..b18bc5541
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 CCVideoDrawQuad_h
+#define CCVideoDrawQuad_h
+
+#include "cc/CCDrawQuad.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class CCLayerImpl;
+class CCVideoDrawQuad : public CCDrawQuad {
+ WTF_MAKE_NONCOPYABLE(CCVideoDrawQuad);
+public:
+ static PassOwnPtr<CCVideoDrawQuad> create(const CCSharedQuadState*, const IntRect&, CCLayerImpl*);
+
+ CCLayerImpl* layer() const { return m_layer; }
+
+private:
+ CCVideoDrawQuad(const CCSharedQuadState*, const IntRect&, CCLayerImpl*);
+
+ CCLayerImpl* m_layer;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp
index 99e7e1174..09afb08d3 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp
@@ -32,9 +32,10 @@
#include "Extensions3DChromium.h"
#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h"
-#include "ProgramBinding.h"
#include "NotImplemented.h"
+#include "ProgramBinding.h"
#include "cc/CCProxy.h"
+#include "cc/CCVideoDrawQuad.h"
#include <wtf/text/WTFString.h>
namespace WebCore {
@@ -125,11 +126,15 @@ void CCVideoLayerImpl::draw(LayerRendererChromium* layerRenderer)
return;
GC3Denum format = convertVFCFormatToGC3DFormat(frame->format());
- if (format == GraphicsContext3D::INVALID_VALUE)
+ if (format == GraphicsContext3D::INVALID_VALUE) {
+ m_provider->putCurrentFrame(frame);
return;
+ }
- if (!copyFrameToTextures(frame, format, layerRenderer))
+ if (!copyFrameToTextures(frame, format, layerRenderer)) {
+ m_provider->putCurrentFrame(frame);
return;
+ }
switch (format) {
case GraphicsContext3D::LUMINANCE:
@@ -150,6 +155,12 @@ void CCVideoLayerImpl::draw(LayerRendererChromium* layerRenderer)
m_provider->putCurrentFrame(frame);
}
+void CCVideoLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState)
+{
+ IntRect quadRect(IntPoint(), bounds());
+ quadList.append(CCVideoDrawQuad::create(sharedQuadState, quadRect, this));
+}
+
bool CCVideoLayerImpl::copyFrameToTextures(const VideoFrameChromium* frame, GC3Denum format, LayerRendererChromium* layerRenderer)
{
if (frame->format() == VideoFrameChromium::NativeTexture) {
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h
index cc4cc8232..182f7b582 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h
@@ -46,6 +46,8 @@ public:
}
virtual ~CCVideoLayerImpl();
+ virtual void appendQuads(CCQuadList&, const CCSharedQuadState*);
+
typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexFlipAlpha> RGBAProgram;
typedef ProgramBinding<VertexShaderPosTexYUVStretch, FragmentShaderYUVVideo> YUVProgram;
typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexFlipAlpha> NativeTextureProgram;
diff --git a/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp b/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp
index d45235e14..e3e82f998 100644
--- a/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp
+++ b/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp
@@ -836,6 +836,11 @@ void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>)
notImplemented();
}
+void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<ErrorMessageCallback>)
+{
+ notImplemented();
+}
+
bool GraphicsContext3D::getImageData(Image* image, GC3Denum format, GC3Denum type, bool premultiplyAlpha,
bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector)
{
diff --git a/Source/WebCore/platform/graphics/efl/IntRectEfl.cpp b/Source/WebCore/platform/graphics/efl/IntRectEfl.cpp
index 0c92f63b6..cfdfe221f 100644
--- a/Source/WebCore/platform/graphics/efl/IntRectEfl.cpp
+++ b/Source/WebCore/platform/graphics/efl/IntRectEfl.cpp
@@ -25,16 +25,16 @@
namespace WebCore {
-IntRect::IntRect(const Eina_Rectangle& r)
- : m_location(IntPoint(r.x, r.y))
- , m_size(r.w, r.h)
+IntRect::IntRect(const Eina_Rectangle& rect)
+ : m_location(IntPoint(rect.x, rect.y))
+ , m_size(rect.w, rect.h)
{
}
IntRect::operator Eina_Rectangle() const
{
- Eina_Rectangle r = {x(), y(), width(), height()};
- return r;
+ Eina_Rectangle rect = {x(), y(), width(), height()};
+ return rect;
}
}
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterNumberParameter.h b/Source/WebCore/platform/graphics/filters/CustomFilterNumberParameter.h
new file mode 100644
index 000000000..36568d59a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterNumberParameter.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012 Adobe Systems Incorporated. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef CustomFilterNumberParameter_h
+#define CustomFilterNumberParameter_h
+
+#if ENABLE(CSS_SHADERS)
+#include "CustomFilterParameter.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class CustomFilterNumberParameter : public CustomFilterParameter {
+public:
+ static PassRefPtr<CustomFilterNumberParameter> create(const String& name)
+ {
+ return adoptRef(new CustomFilterNumberParameter(name));
+ }
+
+ unsigned size() const { return m_data.size(); }
+ double valueAt(unsigned index) const { return m_data.at(index); }
+
+ void addValue(double value) { m_data.append(value); }
+
+private:
+ CustomFilterNumberParameter(const String& name)
+ : CustomFilterParameter(NUMBER, name)
+ {
+ }
+
+ Vector<double, 4> m_data;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_SHADERS)
+
+#endif // CustomFilterNumberParameter_h
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterOperation.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterOperation.cpp
new file mode 100644
index 000000000..93af2b73a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterOperation.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012 Adobe Systems Incorporated. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(CSS_SHADERS)
+#include "CustomFilterOperation.h"
+
+#include "CustomFilterParameter.h"
+#include "CustomFilterProgram.h"
+#include "FilterOperation.h"
+
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+CustomFilterOperation::CustomFilterOperation(PassRefPtr<CustomFilterProgram> program, const CustomFilterParameterList& sortedParameters, unsigned meshRows, unsigned meshColumns, MeshBoxType meshBoxType, MeshType meshType)
+ : FilterOperation(CUSTOM)
+ , m_program(program)
+ , m_parameters(sortedParameters)
+ , m_meshRows(meshRows)
+ , m_meshColumns(meshColumns)
+ , m_meshBoxType(meshBoxType)
+ , m_meshType(meshType)
+{
+ // Make sure that the parameters are alwyas sorted by name. We use that to merge two CustomFilterOperations in animations.
+ ASSERT(hasSortedParameterList());
+}
+
+CustomFilterOperation::~CustomFilterOperation()
+{
+}
+
+#ifndef NDEBUG
+bool CustomFilterOperation::hasSortedParameterList()
+{
+ 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;
+}
+#endif
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_SHADERS)
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterOperation.h b/Source/WebCore/platform/graphics/filters/CustomFilterOperation.h
new file mode 100644
index 000000000..66eb2c8b1
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterOperation.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2011 Adobe Systems Incorporated. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef CustomFilterOperation_h
+#define CustomFilterOperation_h
+
+#if ENABLE(CSS_SHADERS)
+#include "CustomFilterProgram.h"
+#include "FilterOperation.h"
+
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+// CSS Shaders
+
+class CustomFilterParameter;
+typedef Vector<RefPtr<CustomFilterParameter> > CustomFilterParameterList;
+
+class CustomFilterOperation : public FilterOperation {
+public:
+ enum MeshBoxType {
+ FILTER_BOX,
+ BORDER_BOX,
+ PADDING_BOX,
+ CONTENT_BOX
+ };
+
+ enum MeshType {
+ ATTACHED,
+ DETACHED
+ };
+
+ static PassRefPtr<CustomFilterOperation> create(PassRefPtr<CustomFilterProgram> program, const CustomFilterParameterList& sortedParameters, unsigned meshRows, unsigned meshColumns, MeshBoxType meshBoxType, MeshType meshType)
+ {
+ return adoptRef(new CustomFilterOperation(program, sortedParameters, meshRows, meshColumns, meshBoxType, meshType));
+ }
+
+ CustomFilterProgram* program() const { return m_program.get(); }
+
+ const CustomFilterParameterList& parameters() { return m_parameters; }
+
+ unsigned meshRows() const { return m_meshRows; }
+ unsigned meshColumns() const { return m_meshColumns; }
+
+ MeshBoxType meshBoxType() const { return m_meshBoxType; }
+ MeshType meshType() const { return m_meshType; }
+
+ virtual ~CustomFilterOperation();
+
+private:
+ virtual bool operator==(const FilterOperation& o) const
+ {
+ if (!isSameType(o))
+ return false;
+
+ const CustomFilterOperation* other = static_cast<const CustomFilterOperation*>(&o);
+ 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;
+ }
+
+ CustomFilterOperation(PassRefPtr<CustomFilterProgram>, const CustomFilterParameterList&, unsigned meshRows, unsigned meshColumns, MeshBoxType, MeshType);
+
+#ifndef NDEBUG
+ bool hasSortedParameterList();
+#endif
+
+ RefPtr<CustomFilterProgram> m_program;
+ CustomFilterParameterList m_parameters;
+
+ unsigned m_meshRows;
+ unsigned m_meshColumns;
+ MeshBoxType m_meshBoxType;
+ MeshType m_meshType;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_SHADERS)
+
+#endif // CustomFilterOperation_h
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterParameter.h b/Source/WebCore/platform/graphics/filters/CustomFilterParameter.h
new file mode 100644
index 000000000..cd8cb8805
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterParameter.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012 Adobe Systems Incorporated. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef CustomFilterParameter_h
+#define CustomFilterParameter_h
+
+#if ENABLE(CSS_SHADERS)
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class CustomFilterParameter : public RefCounted<CustomFilterParameter> {
+public:
+ // FIXME: Implement other parameters types:
+ // booleans: https://bugs.webkit.org/show_bug.cgi?id=76438
+ // textures: https://bugs.webkit.org/show_bug.cgi?id=71442
+ // 3d-transforms: https://bugs.webkit.org/show_bug.cgi?id=71443
+ // mat2, mat3, mat4: https://bugs.webkit.org/show_bug.cgi?id=71444
+ enum ParameterType {
+ NUMBER
+ };
+
+ virtual ~CustomFilterParameter() { }
+
+ ParameterType parameterType() const { return m_type; }
+ const String& name() const { return m_name; }
+
+protected:
+ CustomFilterParameter(ParameterType type, const String& name)
+ : m_name(name)
+ , m_type(type)
+ {
+ }
+
+private:
+ String m_name;
+ ParameterType m_type;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_SHADERS)
+
+#endif // CustomFilterParameter_h
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp
new file mode 100644
index 000000000..d257f3f83
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2012 Adobe Systems Incorporated. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(CSS_SHADERS)
+#include "CustomFilterProgram.h"
+
+#include "CustomFilterProgramClient.h"
+#include "CustomFilterShader.h"
+
+#if ENABLE(WEBGL)
+#include "GraphicsContext3D.h"
+#endif
+
+namespace WebCore {
+
+CustomFilterProgram::CustomFilterProgram()
+{
+ // Keep the constructor protected to prevent creating this object directly.
+}
+
+CustomFilterProgram::~CustomFilterProgram()
+{
+ // All the clients should keep a reference to this object.
+ ASSERT(m_clients.isEmpty());
+}
+
+void CustomFilterProgram::addClient(CustomFilterProgramClient* client)
+{
+ if (m_clients.isEmpty()) {
+ // Notify the StyleCustomFilterProgram that we now have at least a client
+ // and the loading can begin.
+ // Note: If the shader is already cached the first client will be notified,
+ // even if the filter was already built. Add the client only after notifying
+ // the cache about them, so that we avoid a useless recreation of the filters chain.
+ willHaveClients();
+ }
+ m_clients.add(client);
+}
+
+void CustomFilterProgram::removeClient(CustomFilterProgramClient* client)
+{
+ m_clients.remove(client);
+ if (m_clients.isEmpty()) {
+ // We have no clients anymore, the cached resources can be purged from memory.
+ didRemoveLastClient();
+ }
+}
+
+void CustomFilterProgram::notifyClients()
+{
+ for (CustomFilterProgramClientList::iterator iter = m_clients.begin(), end = m_clients.end(); iter != end; ++iter)
+ iter->first->notifyCustomFilterProgramLoaded(this);
+}
+
+#if ENABLE(WEBGL)
+PassRefPtr<CustomFilterShader> CustomFilterProgram::createShaderWithContext(GraphicsContext3D* context)
+{
+ ASSERT(isLoaded());
+ return CustomFilterShader::create(context, vertexShaderString(), fragmentShaderString());
+}
+#endif
+
+} // namespace WebCore
+#endif // ENABLE(CSS_SHADERS)
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h
new file mode 100644
index 000000000..8c9056d39
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012 Adobe Systems Incorporated. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef CustomFilterProgram_h
+#define CustomFilterProgram_h
+
+#if ENABLE(CSS_SHADERS)
+
+#include <wtf/HashCountedSet.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class GraphicsContext3D;
+class CustomFilterShader;
+class CustomFilterProgramClient;
+
+// This is the base class for the StyleCustomFilterProgram class which knows how to keep
+// references to the cached shaders.
+class CustomFilterProgram: public RefCounted<CustomFilterProgram> {
+public:
+ virtual ~CustomFilterProgram();
+
+ virtual bool isLoaded() const = 0;
+
+ void addClient(CustomFilterProgramClient*);
+ void removeClient(CustomFilterProgramClient*);
+
+#if ENABLE(WEBGL)
+ PassRefPtr<CustomFilterShader> createShaderWithContext(GraphicsContext3D*);
+#endif
+protected:
+ // StyleCustomFilterProgram can notify the clients that the cached resources are
+ // loaded and it is ready to create CustomFilterShader objects.
+ void notifyClients();
+
+ virtual String vertexShaderString() const = 0;
+ virtual String fragmentShaderString() const = 0;
+
+ virtual void willHaveClients() = 0;
+ virtual void didRemoveLastClient() = 0;
+
+ // Keep the constructor protected to prevent creating this object directly.
+ CustomFilterProgram();
+
+private:
+ typedef HashCountedSet<CustomFilterProgramClient*> CustomFilterProgramClientList;
+ CustomFilterProgramClientList m_clients;
+};
+
+}
+
+#endif // ENABLE(CSS_SHADERS)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgramClient.h b/Source/WebCore/platform/graphics/filters/CustomFilterProgramClient.h
new file mode 100644
index 000000000..488247d9f
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgramClient.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012 Adobe Systems Incorporated. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef CustomFilterProgramClient_h
+#define CustomFilterProgramClient_h
+
+#if ENABLE(CSS_SHADERS)
+
+namespace WebCore {
+
+class CustomFilterProgram;
+
+class CustomFilterProgramClient {
+public:
+ virtual ~CustomFilterProgramClient()
+ {
+ }
+
+ virtual void notifyCustomFilterProgramLoaded(CustomFilterProgram*) = 0;
+};
+
+}
+
+#endif // ENABLE(CSS_SHADERS)
+
+#endif // CustomFilterProgramClient_h
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterShader.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterShader.cpp
index 6df78de97..cacfeb615 100644
--- a/Source/WebCore/platform/graphics/filters/CustomFilterShader.cpp
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterShader.cpp
@@ -160,6 +160,13 @@ void CustomFilterShader::initializeParameterLocations()
m_samplerSizeLocation = m_context->getUniformLocation(m_program, "s_textureSize");
m_contentSamplerLocation = m_context->getUniformLocation(m_program, "s_contentTexture");
}
+
+int CustomFilterShader::uniformLocationByName(const String& name)
+{
+ ASSERT(m_isInitialized);
+ // FIXME: Improve this by caching the uniform locations.
+ return m_context->getUniformLocation(m_program, name);
+}
CustomFilterShader::~CustomFilterShader()
{
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterShader.h b/Source/WebCore/platform/graphics/filters/CustomFilterShader.h
index 90602cb1e..6141c18c7 100644
--- a/Source/WebCore/platform/graphics/filters/CustomFilterShader.h
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterShader.h
@@ -63,6 +63,8 @@ public:
int samplerLocation() const { return m_samplerLocation; }
int contentSamplerLocation() const { return m_contentSamplerLocation; }
int samplerSizeLocation() const { return m_samplerSizeLocation; }
+
+ int uniformLocationByName(const String&);
bool isInitialized() const { return m_isInitialized; }
diff --git a/Source/WebCore/platform/graphics/filters/FEColorMatrix.h b/Source/WebCore/platform/graphics/filters/FEColorMatrix.h
index d03b6d376..27a4ac843 100644
--- a/Source/WebCore/platform/graphics/filters/FEColorMatrix.h
+++ b/Source/WebCore/platform/graphics/filters/FEColorMatrix.h
@@ -49,6 +49,9 @@ public:
bool setValues(const Vector<float>&);
virtual void platformApplySoftware();
+#if USE(SKIA)
+ virtual bool platformApplySkia();
+#endif
virtual void dump();
virtual TextStream& externalRepresentation(TextStream&, int indention) const;
diff --git a/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp b/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp
index fb4270e47..95f51fc9b 100644
--- a/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp
+++ b/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp
@@ -34,6 +34,9 @@
#include "CachedShader.h"
#include "CustomFilterMesh.h"
+#include "CustomFilterNumberParameter.h"
+#include "CustomFilterParameter.h"
+#include "CustomFilterProgram.h"
#include "CustomFilterShader.h"
#include "Document.h"
#include "DrawingBuffer.h"
@@ -73,13 +76,13 @@ static void orthogonalProjectionMatrix(TransformationMatrix& matrix, float left,
matrix.setM44(1.0f);
}
-FECustomFilter::FECustomFilter(Filter* filter, Document* document, const String& vertexShader, const String& fragmentShader,
+FECustomFilter::FECustomFilter(Filter* filter, Document* document, PassRefPtr<CustomFilterProgram> program, const CustomFilterParameterList& parameters,
unsigned meshRows, unsigned meshColumns, CustomFilterOperation::MeshBoxType meshBoxType,
CustomFilterOperation::MeshType meshType)
: FilterEffect(filter)
, m_document(document)
- , m_vertexShader(vertexShader)
- , m_fragmentShader(fragmentShader)
+ , m_program(program)
+ , m_parameters(parameters)
, m_meshRows(meshRows)
, m_meshColumns(meshColumns)
, m_meshBoxType(meshBoxType)
@@ -87,11 +90,11 @@ FECustomFilter::FECustomFilter(Filter* filter, Document* document, const String&
{
}
-PassRefPtr<FECustomFilter> FECustomFilter::create(Filter* filter, Document* document, const String& vertexShader, const String& fragmentShader,
+PassRefPtr<FECustomFilter> FECustomFilter::create(Filter* filter, Document* document, PassRefPtr<CustomFilterProgram> program, const CustomFilterParameterList& parameters,
unsigned meshRows, unsigned meshColumns, CustomFilterOperation::MeshBoxType meshBoxType,
CustomFilterOperation::MeshType meshType)
{
- return adoptRef(new FECustomFilter(filter, document, vertexShader, fragmentShader, meshRows, meshColumns, meshBoxType, meshType));
+ return adoptRef(new FECustomFilter(filter, document, program, parameters, meshRows, meshColumns, meshBoxType, meshType));
}
void FECustomFilter::platformApplySoftware()
@@ -116,6 +119,10 @@ void FECustomFilter::platformApplySoftware()
if (m_inputTexture->tiles().numTiles() != 1)
return;
+ // The shader had compiler errors. We cannot draw anything.
+ if (!m_shader->isInitialized())
+ return;
+
m_context->clearColor(0, 0, 0, 0);
m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT);
@@ -137,10 +144,11 @@ void FECustomFilter::initializeContext(const IntSize& contextSize)
attributes.preserveDrawingBuffer = true;
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_shader = CustomFilterShader::create(m_context.get(), m_vertexShader, m_fragmentShader);
+ m_shader = m_program->createShaderWithContext(m_context.get());
m_mesh = CustomFilterMesh::create(m_context.get(), m_meshColumns, m_meshRows,
FloatRect(0, 0, 1, 1),
m_meshType);
@@ -165,6 +173,46 @@ void FECustomFilter::bindVertexAttribute(int attributeLocation, unsigned size, u
offset += size * sizeof(float);
}
+void FECustomFilter::bindProgramNumberParameters(int uniformLocation, CustomFilterNumberParameter* numberParameter)
+{
+ switch (numberParameter->size()) {
+ case 1:
+ m_context->uniform1f(uniformLocation, numberParameter->valueAt(0));
+ break;
+ case 2:
+ m_context->uniform2f(uniformLocation, numberParameter->valueAt(0), numberParameter->valueAt(1));
+ break;
+ case 3:
+ m_context->uniform3f(uniformLocation, numberParameter->valueAt(0), numberParameter->valueAt(1), numberParameter->valueAt(2));
+ break;
+ case 4:
+ m_context->uniform4f(uniformLocation, numberParameter->valueAt(0), numberParameter->valueAt(1), numberParameter->valueAt(2), numberParameter->valueAt(3));
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+
+void FECustomFilter::bindProgramParameters()
+{
+ // FIXME: Find a way to reset uniforms that are not specified in CSS. This is needed to avoid using values
+ // set by other previous rendered filters.
+ // https://bugs.webkit.org/show_bug.cgi?id=76440
+
+ size_t parametersSize = m_parameters.size();
+ for (size_t i = 0; i < parametersSize; ++i) {
+ CustomFilterParameter* parameter = m_parameters.at(i).get();
+ int uniformLocation = m_shader->uniformLocationByName(parameter->name());
+ if (uniformLocation == -1)
+ continue;
+ switch (parameter->parameterType()) {
+ case CustomFilterParameter::NUMBER:
+ bindProgramNumberParameters(uniformLocation, static_cast<CustomFilterNumberParameter*>(parameter));
+ break;
+ }
+ }
+}
+
void FECustomFilter::bindProgramAndBuffers(ByteArray* srcPixelArray)
{
m_context->useProgram(m_shader->program());
@@ -193,6 +241,8 @@ void FECustomFilter::bindProgramAndBuffers(ByteArray* srcPixelArray)
bindVertexAttribute(m_shader->meshAttribLocation(), 2, offset);
if (m_meshType == CustomFilterOperation::DETACHED)
bindVertexAttribute(m_shader->triangleAttribLocation(), 3, offset);
+
+ bindProgramParameters();
}
void FECustomFilter::dump()
diff --git a/Source/WebCore/platform/graphics/filters/FECustomFilter.h b/Source/WebCore/platform/graphics/filters/FECustomFilter.h
index 2aaabf6ba..1fa2d292a 100644
--- a/Source/WebCore/platform/graphics/filters/FECustomFilter.h
+++ b/Source/WebCore/platform/graphics/filters/FECustomFilter.h
@@ -45,6 +45,8 @@ namespace WebCore {
class CachedShader;
class CustomFilterMesh;
+class CustomFilterNumberParameter;
+class CustomFilterProgram;
class CustomFilterShader;
class Document;
class DrawingBuffer;
@@ -54,7 +56,7 @@ class Texture;
class FECustomFilter : public FilterEffect {
public:
- static PassRefPtr<FECustomFilter> create(Filter*, Document*, const String& vertexShader, const String& fragmentShader,
+ static PassRefPtr<FECustomFilter> create(Filter*, Document*, PassRefPtr<CustomFilterProgram>, const CustomFilterParameterList&,
unsigned meshRows, unsigned meshColumns, CustomFilterOperation::MeshBoxType,
CustomFilterOperation::MeshType);
@@ -64,13 +66,15 @@ public:
virtual TextStream& externalRepresentation(TextStream&, int indention) const;
private:
- FECustomFilter(Filter*, Document*, const String& vertexShader, const String& fragmentShader,
+ FECustomFilter(Filter*, Document*, PassRefPtr<CustomFilterProgram>, const CustomFilterParameterList&,
unsigned meshRows, unsigned meshColumns, CustomFilterOperation::MeshBoxType,
CustomFilterOperation::MeshType);
void initializeContext(const IntSize& contextSize);
void resizeContext(const IntSize& newContextSize);
void bindVertexAttribute(int attributeLocation, unsigned size, unsigned& offset);
+ void bindProgramNumberParameters(int uniformLocation, CustomFilterNumberParameter*);
+ void bindProgramParameters();
void bindProgramAndBuffers(ByteArray* srcPixelArray);
Document* m_document;
@@ -81,9 +85,9 @@ private:
RefPtr<CustomFilterShader> m_shader;
RefPtr<CustomFilterMesh> m_mesh;
IntSize m_contextSize;
-
- String m_vertexShader;
- String m_fragmentShader;
+
+ RefPtr<CustomFilterProgram> m_program;
+ CustomFilterParameterList m_parameters;
unsigned m_meshRows;
unsigned m_meshColumns;
diff --git a/Source/WebCore/platform/graphics/filters/FETile.cpp b/Source/WebCore/platform/graphics/filters/FETile.cpp
index a6e1da334..e4a9508ee 100644
--- a/Source/WebCore/platform/graphics/filters/FETile.cpp
+++ b/Source/WebCore/platform/graphics/filters/FETile.cpp
@@ -67,7 +67,7 @@ void FETile::platformApplySoftware()
}
OwnPtr<ImageBuffer> tileImage;
- if (!SVGImageBufferTools::createImageBuffer(tileRect, tileRect, tileImage, ColorSpaceDeviceRGB, filter()->renderingMode()))
+ if (!SVGImageBufferTools::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 3ca45717e..d5d64c130 100644
--- a/Source/WebCore/platform/graphics/filters/FETurbulence.cpp
+++ b/Source/WebCore/platform/graphics/filters/FETurbulence.cpp
@@ -148,16 +148,6 @@ bool FETurbulence::setStitchTiles(bool stitch)
// The turbulence calculation code is an adapted version of what appears in the SVG 1.1 specification:
// http://www.w3.org/TR/SVG11/filters.html#feTurbulence
-FETurbulence::PaintingData::PaintingData(long paintingSeed, const IntSize& paintingSize)
- : seed(paintingSeed)
- , width(0)
- , height(0)
- , wrapX(0)
- , wrapY(0)
- , filterSize(paintingSize)
-{
-}
-
// Compute pseudo random number.
inline long FETurbulence::PaintingData::random()
{
@@ -225,7 +215,7 @@ inline void checkNoise(int& noiseValue, int limitValue, int newValue)
noiseValue -= newValue - 1;
}
-float FETurbulence::noise2D(int channel, PaintingData& paintingData, const FloatPoint& noiseVector)
+float FETurbulence::noise2D(int channel, PaintingData& paintingData, StitchData& stitchData, const FloatPoint& noiseVector)
{
struct Noise {
int noisePositionIntegerValue;
@@ -246,8 +236,8 @@ float FETurbulence::noise2D(int channel, PaintingData& paintingData, const Float
// If stitching, adjust lattice points accordingly.
if (m_stitchTiles) {
- checkNoise(noiseX.noisePositionIntegerValue, paintingData.wrapX, paintingData.width);
- checkNoise(noiseY.noisePositionIntegerValue, paintingData.wrapY, paintingData.height);
+ checkNoise(noiseX.noisePositionIntegerValue, stitchData.wrapX, stitchData.width);
+ checkNoise(noiseY.noisePositionIntegerValue, stitchData.wrapY, stitchData.height);
}
noiseX.noisePositionIntegerValue &= s_blockMask;
@@ -276,57 +266,58 @@ float FETurbulence::noise2D(int channel, PaintingData& paintingData, const Float
return linearInterpolation(sy, a, b);
}
-unsigned char FETurbulence::calculateTurbulenceValueForPoint(int channel, PaintingData& paintingData, const FloatPoint& point)
+unsigned char FETurbulence::calculateTurbulenceValueForPoint(int channel, PaintingData& paintingData, StitchData& stitchData, const FloatPoint& point)
{
float tileWidth = paintingData.filterSize.width();
- ASSERT(tileWidth > 0);
float tileHeight = paintingData.filterSize.height();
- ASSERT(tileHeight > 0);
+ ASSERT(tileWidth > 0 && tileHeight > 0);
+ float baseFrequencyX = m_baseFrequencyX;
+ float baseFrequencyY = m_baseFrequencyY;
// Adjust the base frequencies if necessary for stitching.
if (m_stitchTiles) {
// When stitching tiled turbulence, the frequencies must be adjusted
// so that the tile borders will be continuous.
- if (m_baseFrequencyX) {
- float lowFrequency = floorf(tileWidth * m_baseFrequencyX) / tileWidth;
- float highFrequency = ceilf(tileWidth * m_baseFrequencyX) / tileWidth;
+ if (baseFrequencyX) {
+ float lowFrequency = floorf(tileWidth * baseFrequencyX) / tileWidth;
+ float highFrequency = ceilf(tileWidth * baseFrequencyX) / tileWidth;
// BaseFrequency should be non-negative according to the standard.
- if (m_baseFrequencyX / lowFrequency < highFrequency / m_baseFrequencyX)
- m_baseFrequencyX = lowFrequency;
+ if (baseFrequencyX / lowFrequency < highFrequency / baseFrequencyX)
+ baseFrequencyX = lowFrequency;
else
- m_baseFrequencyX = highFrequency;
+ baseFrequencyX = highFrequency;
}
- if (m_baseFrequencyY) {
- float lowFrequency = floorf(tileHeight * m_baseFrequencyY) / tileHeight;
- float highFrequency = ceilf(tileHeight * m_baseFrequencyY) / tileHeight;
- if (m_baseFrequencyY / lowFrequency < highFrequency / m_baseFrequencyY)
- m_baseFrequencyY = lowFrequency;
+ if (baseFrequencyY) {
+ float lowFrequency = floorf(tileHeight * baseFrequencyY) / tileHeight;
+ float highFrequency = ceilf(tileHeight * baseFrequencyY) / tileHeight;
+ if (baseFrequencyY / lowFrequency < highFrequency / baseFrequencyY)
+ baseFrequencyY = lowFrequency;
else
- m_baseFrequencyY = highFrequency;
+ baseFrequencyY = highFrequency;
}
// Set up TurbulenceInitial stitch values.
- paintingData.width = roundf(tileWidth * m_baseFrequencyX);
- paintingData.wrapX = s_perlinNoise + paintingData.width;
- paintingData.height = roundf(tileHeight * m_baseFrequencyY);
- paintingData.wrapY = s_perlinNoise + paintingData.height;
+ stitchData.width = roundf(tileWidth * baseFrequencyX);
+ stitchData.wrapX = s_perlinNoise + stitchData.width;
+ stitchData.height = roundf(tileHeight * baseFrequencyY);
+ stitchData.wrapY = s_perlinNoise + stitchData.height;
}
float turbulenceFunctionResult = 0;
- FloatPoint noiseVector(point.x() * m_baseFrequencyX, point.y() * m_baseFrequencyY);
+ FloatPoint noiseVector(point.x() * baseFrequencyX, point.y() * baseFrequencyY);
float ratio = 1;
for (int octave = 0; octave < m_numOctaves; ++octave) {
if (m_type == FETURBULENCE_TYPE_FRACTALNOISE)
- turbulenceFunctionResult += noise2D(channel, paintingData, noiseVector) / ratio;
+ turbulenceFunctionResult += noise2D(channel, paintingData, stitchData, noiseVector) / ratio;
else
- turbulenceFunctionResult += fabsf(noise2D(channel, paintingData, noiseVector)) / ratio;
+ turbulenceFunctionResult += fabsf(noise2D(channel, paintingData, stitchData, noiseVector)) / ratio;
noiseVector.setX(noiseVector.x() * 2);
noiseVector.setY(noiseVector.y() * 2);
ratio *= 2;
if (m_stitchTiles) {
// Update stitch values. Subtracting s_perlinNoiseoise before the multiplication and
// adding it afterward simplifies to subtracting it once.
- paintingData.width *= 2;
- paintingData.wrapX = 2 * paintingData.wrapX - s_perlinNoise;
- paintingData.height *= 2;
- paintingData.wrapY = 2 * paintingData.wrapY - s_perlinNoise;
+ stitchData.width *= 2;
+ stitchData.wrapX = 2 * stitchData.wrapX - s_perlinNoise;
+ stitchData.height *= 2;
+ stitchData.wrapY = 2 * stitchData.wrapY - s_perlinNoise;
}
}
@@ -345,6 +336,7 @@ inline void FETurbulence::fillRegion(ByteArray* pixelArray, PaintingData& painti
IntPoint point(0, filterRegion.y() + startY);
int indexOfPixelChannel = startY * (filterRegion.width() << 2);
int channel;
+ StitchData stitchData;
for (int y = startY; y < endY; ++y) {
point.setY(point.y() + 1);
@@ -352,7 +344,7 @@ inline void FETurbulence::fillRegion(ByteArray* pixelArray, PaintingData& painti
for (int x = 0; x < filterRegion.width(); ++x) {
point.setX(point.x() + 1);
for (channel = 0; channel < 4; ++channel, ++indexOfPixelChannel)
- pixelArray->set(indexOfPixelChannel, calculateTurbulenceValueForPoint(channel, paintingData, filter()->mapAbsolutePointToLocalPoint(point)));
+ pixelArray->set(indexOfPixelChannel, calculateTurbulenceValueForPoint(channel, paintingData, stitchData, filter()->mapAbsolutePointToLocalPoint(point)));
}
}
}
diff --git a/Source/WebCore/platform/graphics/filters/FETurbulence.h b/Source/WebCore/platform/graphics/filters/FETurbulence.h
index 01d3c597a..59257d026 100644
--- a/Source/WebCore/platform/graphics/filters/FETurbulence.h
+++ b/Source/WebCore/platform/graphics/filters/FETurbulence.h
@@ -74,19 +74,35 @@ private:
static const int s_minimalRectDimension = (100 * 100); // Empirical data limit for parallel jobs.
struct PaintingData {
+ PaintingData(long paintingSeed, const IntSize& paintingSize)
+ : seed(paintingSeed)
+ , filterSize(paintingSize)
+ {
+ }
+
long seed;
int latticeSelector[2 * s_blockSize + 2];
float gradient[4][2 * s_blockSize + 2][2];
- int width; // How much to subtract to wrap for stitching.
- int height;
- int wrapX; // Minimum value to wrap.
- int wrapY;
IntSize filterSize;
- PaintingData(long paintingSeed, const IntSize& paintingSize);
inline long random();
};
+ struct StitchData {
+ StitchData()
+ : width(0)
+ , wrapX(0)
+ , height(0)
+ , wrapY(0)
+ {
+ }
+
+ int width; // How much to subtract to wrap for stitching.
+ int wrapX; // Minimum value to wrap.
+ int height;
+ int wrapY;
+ };
+
template<typename Type>
friend class ParallelJobs;
@@ -103,8 +119,8 @@ private:
FETurbulence(Filter*, TurbulenceType, float, float, int, float, bool);
inline void initPaint(PaintingData&);
- float noise2D(int channel, PaintingData&, const FloatPoint&);
- unsigned char calculateTurbulenceValueForPoint(int channel, PaintingData&, const FloatPoint&);
+ float noise2D(int channel, PaintingData&, StitchData&, const FloatPoint&);
+ unsigned char calculateTurbulenceValueForPoint(int channel, PaintingData&, StitchData&, const FloatPoint&);
inline void fillRegion(ByteArray*, PaintingData&, int, int);
TurbulenceType m_type;
diff --git a/Source/WebCore/platform/graphics/gtk/GraphicsContext3DPrivate.cpp b/Source/WebCore/platform/graphics/glx/GraphicsContext3DPrivate.cpp
index 523bc7e36..a628a4bd6 100644
--- a/Source/WebCore/platform/graphics/gtk/GraphicsContext3DPrivate.cpp
+++ b/Source/WebCore/platform/graphics/glx/GraphicsContext3DPrivate.cpp
@@ -240,9 +240,8 @@ bool GraphicsContext3DPrivate::makeContextCurrent()
return true;
if (!m_context)
return false;
- if (m_pbuffer) {
+ if (m_pbuffer)
return ::glXMakeCurrent(sharedDisplay(), m_pbuffer, m_context);
- }
ASSERT(m_glxPixmap);
return ::glXMakeCurrent(sharedDisplay(), m_glxPixmap, m_context);
diff --git a/Source/WebCore/platform/graphics/gtk/GraphicsContext3DPrivate.h b/Source/WebCore/platform/graphics/glx/GraphicsContext3DPrivate.h
index 4134895b7..33a500d0a 100644
--- a/Source/WebCore/platform/graphics/gtk/GraphicsContext3DPrivate.h
+++ b/Source/WebCore/platform/graphics/glx/GraphicsContext3DPrivate.h
@@ -33,12 +33,12 @@ namespace WebCore {
class GraphicsContext3D;
class GraphicsContext3DPrivate {
- public:
+public:
static PassOwnPtr<GraphicsContext3DPrivate> create();
~GraphicsContext3DPrivate();
bool makeContextCurrent();
- private:
+private:
friend class GraphicsContext3D;
static GraphicsContext3DPrivate* createPbufferContext();
static GraphicsContext3DPrivate* createPixmapContext();
diff --git a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
index d1d2cf2c3..9dd3b9de5 100644
--- a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
@@ -72,8 +72,10 @@ void DrawingBuffer::clear()
return;
m_context->makeContextCurrent();
- if (!m_size.isEmpty())
+ if (!m_size.isEmpty()) {
s_currentResourceUsePixels -= m_size.width() * m_size.height();
+ m_size = IntSize();
+ }
if (m_colorBuffer) {
m_context->deleteTexture(m_colorBuffer);
diff --git a/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
index fd5e977ce..ad4c24d82 100644
--- a/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
@@ -18,6 +18,7 @@
#include "config.h"
#include "WebKitWebSourceGStreamer.h"
+
#if ENABLE(VIDEO) && USE(GSTREAMER)
#include "Document.h"
@@ -31,9 +32,9 @@
#include "ResourceHandleInternal.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
-#include <wtf/text/CString.h>
#include <gst/app/gstappsrc.h>
#include <gst/pbutils/missing-plugins.h>
+#include <wtf/text/CString.h>
using namespace WebCore;
@@ -106,22 +107,23 @@ static GstStaticPadTemplate srcTemplate = GST_STATIC_PAD_TEMPLATE("src",
GST_DEBUG_CATEGORY_STATIC(webkit_web_src_debug);
#define GST_CAT_DEFAULT webkit_web_src_debug
-static void webKitWebSrcUriHandlerInit(gpointer gIface,
- gpointer ifaceData);
+static void webKitWebSrcUriHandlerInit(gpointer gIface, gpointer ifaceData);
+
+static void webKitWebSrcFinalize(GObject*);
+static void webKitWebSrcSetProperty(GObject*, guint propertyID, const GValue*, GParamSpec*);
+static void webKitWebSrcGetProperty(GObject*, guint propertyID, GValue*, GParamSpec*);
+static GstStateChangeReturn webKitWebSrcChangeState(GstElement*, GstStateChange);
-static void webKitWebSrcFinalize(GObject* object);
-static void webKitWebSrcSetProperty(GObject* object, guint propID, const GValue* value, GParamSpec* pspec);
-static void webKitWebSrcGetProperty(GObject* object, guint propID, GValue* value, GParamSpec* pspec);
-static GstStateChangeReturn webKitWebSrcChangeState(GstElement* element, GstStateChange transition);
-static gboolean webKitWebSrcQuery(GstPad* pad, GstQuery* query);
+static gboolean webKitWebSrcQueryWithParent(GstPad*, GstObject*, GstQuery*);
+#ifndef GST_API_VERSION_1
+static gboolean webKitWebSrcQuery(GstPad*, GstQuery*);
+#endif
-static void webKitWebSrcNeedDataCb(GstAppSrc* appsrc, guint length, gpointer userData);
-static void webKitWebSrcEnoughDataCb(GstAppSrc* appsrc, gpointer userData);
-static gboolean webKitWebSrcSeekDataCb(GstAppSrc* appsrc, guint64 offset, gpointer userData);
+static void webKitWebSrcNeedDataCb(GstAppSrc*, guint length, gpointer userData);
+static void webKitWebSrcEnoughDataCb(GstAppSrc*, gpointer userData);
+static gboolean webKitWebSrcSeekDataCb(GstAppSrc*, guint64 offset, gpointer userData);
-static void webKitWebSrcStop(WebKitWebSrc* src, bool seeking);
-static gboolean webKitWebSrcSetUri(GstURIHandler*, const gchar*);
-static const gchar* webKitWebSrcGetUri(GstURIHandler*);
+static void webKitWebSrcStop(WebKitWebSrc*, bool);
static GstAppSrcCallbacks appsrcCallbacks = {
webKitWebSrcNeedDataCb,
@@ -148,7 +150,11 @@ static void webkit_web_src_class_init(WebKitWebSrcClass* klass)
gst_element_class_add_pad_template(eklass,
gst_static_pad_template_get(&srcTemplate));
+#ifdef GST_API_VERSION_1
+ gst_element_class_set_metadata(eklass,
+#else
gst_element_class_set_details_simple(eklass,
+#endif
(gchar*) "WebKit Web source element",
(gchar*) "Source",
(gchar*) "Handles HTTP/HTTPS uris",
@@ -235,7 +241,13 @@ static void webkit_web_src_init(WebKitWebSrc* src)
priv->srcpad = gst_ghost_pad_new_from_template("src", targetPad.get(), padTemplate.get());
gst_element_add_pad(GST_ELEMENT(src), priv->srcpad);
+
+#ifdef GST_API_VERSION_1
+ GST_OBJECT_FLAG_SET(priv->srcpad, GST_PAD_FLAG_NEED_PARENT);
+ gst_pad_set_query_function(priv->srcpad, webKitWebSrcQueryWithParent);
+#else
gst_pad_set_query_function(priv->srcpad, webKitWebSrcQuery);
+#endif
gst_app_src_set_callbacks(priv->appsrc, &appsrcCallbacks, src, 0);
gst_app_src_set_emit_signals(priv->appsrc, FALSE);
@@ -286,7 +298,11 @@ static void webKitWebSrcSetProperty(GObject* object, guint propID, const GValue*
priv->iradioMode = g_value_get_boolean(value);
break;
case PROP_LOCATION:
- webKitWebSrcSetUri(reinterpret_cast<GstURIHandler*>(src), g_value_get_string(value));
+#ifdef GST_API_VERSION_1
+ gst_uri_handler_set_uri(reinterpret_cast<GstURIHandler*>(src), g_value_get_string(value), 0);
+#else
+ gst_uri_handler_set_uri(reinterpret_cast<GstURIHandler*>(src), g_value_get_string(value));
+#endif
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, pspec);
@@ -316,7 +332,7 @@ static void webKitWebSrcGetProperty(GObject* object, guint propID, GValue* value
g_value_set_string(value, priv->iradioTitle);
break;
case PROP_LOCATION:
- g_value_set_string(value, webKitWebSrcGetUri(reinterpret_cast<GstURIHandler*>(src)));
+ g_value_set_string(value, priv->uri);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, pspec);
@@ -481,15 +497,13 @@ static GstStateChangeReturn webKitWebSrcChangeState(GstElement* element, GstStat
return ret;
}
-static gboolean webKitWebSrcQuery(GstPad* pad, GstQuery* query)
+static gboolean webKitWebSrcQueryWithParent(GstPad* pad, GstObject* parent, GstQuery* query)
{
- GRefPtr<GstElement> src = adoptGRef(gst_pad_get_parent_element(pad));
- WebKitWebSrc* webkitSrc = WEBKIT_WEB_SRC(src.get());
+ WebKitWebSrc* webkitSrc = WEBKIT_WEB_SRC(GST_ELEMENT(parent));
gboolean result = FALSE;
switch (GST_QUERY_TYPE(query)) {
- case GST_QUERY_DURATION:
- {
+ case GST_QUERY_DURATION: {
GstFormat format;
gst_query_parse_duration(query, &format, NULL);
@@ -501,24 +515,79 @@ static gboolean webKitWebSrcQuery(GstPad* pad, GstQuery* query)
}
break;
}
- case GST_QUERY_URI:
- {
+ case GST_QUERY_URI: {
gst_query_set_uri(query, webkitSrc->priv->uri);
result = TRUE;
break;
}
- default:
+ default: {
+ GRefPtr<GstPad> target = adoptGRef(gst_ghost_pad_get_target(GST_GHOST_PAD_CAST(pad)));
+
+ // Forward the query to the proxy target pad.
+ if (target)
+ result = gst_pad_query(target.get(), query);
break;
}
-
- if (!result)
- result = gst_pad_query_default(pad, query);
+ }
return result;
}
+#ifndef GST_API_VERSION_1
+static gboolean webKitWebSrcQuery(GstPad* pad, GstQuery* query)
+{
+ GRefPtr<GstElement> src = adoptGRef(gst_pad_get_parent_element(pad));
+ return webKitWebSrcQueryWithParent(pad, GST_OBJECT(src.get()), query);
+}
+#endif
+
// uri handler interface
+#ifdef GST_API_VERSION_1
+static GstURIType webKitWebSrcUriGetType(GType)
+{
+ return GST_URI_SRC;
+}
+
+const gchar* const* webKitWebSrcGetProtocols(GType)
+{
+ static const char* protocols[] = {"http", "https", 0 };
+ return protocols;
+}
+
+static gchar* webKitWebSrcGetUri(GstURIHandler* handler)
+{
+ return g_strdup(WEBKIT_WEB_SRC(handler)->priv->uri);
+}
+
+static gboolean webKitWebSrcSetUri(GstURIHandler* handler, const gchar* uri, GError** error)
+{
+ WebKitWebSrc* src = WEBKIT_WEB_SRC(handler);
+ WebKitWebSrcPrivate* priv = src->priv;
+
+ if (GST_STATE(src) >= GST_STATE_PAUSED) {
+ GST_ERROR_OBJECT(src, "URI can only be set in states < PAUSED");
+ return FALSE;
+ }
+
+ g_free(priv->uri);
+ priv->uri = 0;
+
+ if (!uri)
+ return TRUE;
+
+ KURL url(KURL(), uri);
+
+ if (!url.isValid() || !url.protocolInHTTPFamily()) {
+ g_set_error(error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI, "Invalid URI '%s'", uri);
+ return FALSE;
+ }
+
+ priv->uri = g_strdup(url.string().utf8().data());
+ return TRUE;
+}
+
+#else
static GstURIType webKitWebSrcUriGetType(void)
{
return GST_URI_SRC;
@@ -527,16 +596,12 @@ static GstURIType webKitWebSrcUriGetType(void)
static gchar** webKitWebSrcGetProtocols(void)
{
static gchar* protocols[] = {(gchar*) "http", (gchar*) "https", 0 };
-
return protocols;
}
static const gchar* webKitWebSrcGetUri(GstURIHandler* handler)
{
- WebKitWebSrc* src = WEBKIT_WEB_SRC(handler);
- WebKitWebSrcPrivate* priv = src->priv;
-
- return priv->uri;
+ return g_strdup(WEBKIT_WEB_SRC(handler)->priv->uri);
}
static gboolean webKitWebSrcSetUri(GstURIHandler* handler, const gchar* uri)
@@ -565,6 +630,7 @@ static gboolean webKitWebSrcSetUri(GstURIHandler* handler, const gchar* uri)
priv->uri = g_strdup(url.string().utf8().data());
return TRUE;
}
+#endif
static void webKitWebSrcUriHandlerInit(gpointer gIface, gpointer ifaceData)
{
@@ -713,7 +779,13 @@ void StreamingClient::didReceiveResponse(ResourceHandle*, const ResourceResponse
length += priv->requestedOffset;
gst_app_src_set_size(priv->appsrc, length);
if (!priv->haveAppSrc27) {
+#ifdef GST_API_VERSION_1
+ GstSegment* segment = &GST_BASE_SRC(priv->appsrc)->segment;
+ segment->duration = length;
+ segment->format = GST_FORMAT_BYTES;
+#else
gst_segment_set_duration(&GST_BASE_SRC(priv->appsrc)->segment, GST_FORMAT_BYTES, length);
+#endif
gst_element_post_message(GST_ELEMENT(priv->appsrc),
gst_message_new_duration(GST_OBJECT(priv->appsrc),
GST_FORMAT_BYTES, length));
@@ -736,7 +808,11 @@ void StreamingClient::didReceiveResponse(ResourceHandle*, const ResourceResponse
}
}
+#ifdef GST_API_VERSION_1
+ GstTagList* tags = gst_tag_list_new_empty();
+#else
GstTagList* tags = gst_tag_list_new();
+#endif
value = response.httpHeaderField("icy-name");
if (!value.isEmpty()) {
g_free(priv->iradioName);
@@ -769,7 +845,11 @@ void StreamingClient::didReceiveResponse(ResourceHandle*, const ResourceResponse
if (gst_tag_list_is_empty(tags))
gst_tag_list_free(tags);
else
+#ifdef GST_API_VERSION_1
+ gst_pad_push_event(GST_PAD_CAST(m_src->priv->srcpad), gst_event_new_tag(tags));
+#else
gst_element_found_tags_for_pad(GST_ELEMENT(m_src), m_src->priv->srcpad, tags);
+#endif
}
void StreamingClient::didReceiveData(ResourceHandle* handle, const char* data, int length, int encodedDataLength)
@@ -785,13 +865,21 @@ void StreamingClient::didReceiveData(ResourceHandle* handle, const char* data, i
GstBuffer* buffer = gst_buffer_new_and_alloc(length);
+#ifdef GST_API_VERSION_1
+ gst_buffer_fill(buffer, 0, data, length);
+#else
memcpy(GST_BUFFER_DATA(buffer), data, length);
+#endif
GST_BUFFER_OFFSET(buffer) = priv->offset;
priv->offset += length;
GST_BUFFER_OFFSET_END(buffer) = priv->offset;
GstFlowReturn ret = gst_app_src_push_buffer(priv->appsrc, buffer);
+#ifdef GST_API_VERSION_1
+ if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)
+#else
if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED)
+#endif
GST_ELEMENT_ERROR(m_src, CORE, FAILED, (0), (0));
}
diff --git a/Source/WebCore/platform/graphics/gtk/ImageGtk.cpp b/Source/WebCore/platform/graphics/gtk/ImageGtk.cpp
index 9dd82a93a..6e81e33a3 100644
--- a/Source/WebCore/platform/graphics/gtk/ImageGtk.cpp
+++ b/Source/WebCore/platform/graphics/gtk/ImageGtk.cpp
@@ -48,36 +48,42 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
}
}
-static const char* getWebKitDataDirectory()
+static char* getPathToImageResource(char* resource)
{
static char* dataDirectory = 0;
- if (dataDirectory)
- return dataDirectory;
-
- dataDirectory = new char[PATH_MAX];
- if (!GetModuleFileName(hmodule, static_cast<CHAR*>(dataDirectory), sizeof(dataDirectory) - 10))
- return DATA_DIR;
-
- // FIXME: This is pretty ugly. Ideally we should be using Windows API
- // functions or GLib methods to calculate paths.
- unsigned char *p;
- p = _mbsrchr(static_cast<const unsigned char *>(dataDirectory), '\\');
- *p = '\0';
- p = _mbsrchr(static_cast<const unsigned char *>(dataDirectory), '\\');
- if (p) {
- if (!stricmp((const char *) (p+1), "bin"))
- *p = '\0';
+ if (!dataDirectory) {
+ dataDirectory = new char[PATH_MAX];
+ if (!GetModuleFileName(hmodule, static_cast<CHAR*>(dataDirectory), sizeof(dataDirectory) - 10))
+ dataDirectory = DATA_DIR;
+
+ // FIXME: This is pretty ugly. Ideally we should be using Windows API
+ // functions or GLib methods to calculate paths.
+ unsigned char *p;
+ p = _mbsrchr(static_cast<const unsigned char *>(dataDirectory), '\\');
+ *p = '\0';
+ p = _mbsrchr(static_cast<const unsigned char *>(dataDirectory), '\\');
+ if (p) {
+ if (!stricmp((const char *) (p+1), "bin"))
+ *p = '\0';
+ }
+ strcat(dataDirectory, "\\share\\webkitgtk-"WEBKITGTK_API_VERSION_STRING"\\images\\");
}
- strcat(dataDirectory, "\\share");
- return dataDirectory;
+ char* imageResourcePath = new char[PATH_MAX];
+ strcat(imageResourcePath, dataDirectory);
+ strcat(imageResourcePath, resource);
+
+ return imageResourcePath;
}
#else
-static const char* getWebKitDataDirectory()
+static char* getPathToImageResource(char* resource)
{
- return DATA_DIR;
+ if (g_getenv("WEBKIT_TOP_LEVEL"))
+ return g_build_filename(g_getenv("WEBKIT_TOP_LEVEL"), "Source", "WebCore", "Resources", resource, NULL);
+
+ return g_build_filename(DATA_DIR, "webkitgtk-"WEBKITGTK_API_VERSION_STRING, "images", resource, NULL);
}
#endif
@@ -138,7 +144,7 @@ PassRefPtr<Image> Image::loadPlatformResource(const char* name)
fileName = getThemeIconFileName(GTK_STOCK_MISSING_IMAGE, 16);
if (fileName.isNull()) {
GOwnPtr<gchar> imageName(g_strdup_printf("%s.png", name));
- GOwnPtr<gchar> glibFileName(g_build_filename(getWebKitDataDirectory(), "webkitgtk-"WEBKITGTK_API_VERSION_STRING, "images", imageName.get(), NULL));
+ GOwnPtr<gchar> glibFileName(getPathToImageResource(imageName.get()));
fileName = glibFileName.get();
}
diff --git a/Source/WebCore/platform/graphics/mac/ColorMac.h b/Source/WebCore/platform/graphics/mac/ColorMac.h
index b68b15763..2482b593b 100644
--- a/Source/WebCore/platform/graphics/mac/ColorMac.h
+++ b/Source/WebCore/platform/graphics/mac/ColorMac.h
@@ -31,11 +31,7 @@
#include "Color.h"
-#ifdef __OBJC__
-@class NSColor;
-#else
-class NSColor;
-#endif
+OBJC_CLASS NSColor;
namespace WebCore {
diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp
index 8ecc4b11b..6ed931f8c 100644
--- a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp
+++ b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp
@@ -204,9 +204,14 @@ static bool advanceByCombiningCharacterSequence(const UChar*& iterator, const UC
}
// Consume marks.
- while (iterator < end && ((U_GET_GC_MASK(*iterator) & U_GC_M_MASK) || *iterator == zeroWidthJoiner || *iterator == zeroWidthNonJoiner)) {
- iterator++;
- markCount++;
+ while (iterator < end) {
+ UChar32 nextCharacter;
+ int markLength = 0;
+ U16_NEXT(iterator, markLength, end - iterator, nextCharacter);
+ if (!(U_GET_GC_MASK(nextCharacter) & U_GC_M_MASK) && nextCharacter != zeroWidthJoiner && nextCharacter != zeroWidthNonJoiner)
+ break;
+ markCount += markLength;
+ iterator += markLength;
}
return true;
diff --git a/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp b/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
index d07f4dc17..5aa23d38f 100644
--- a/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
+++ b/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
@@ -64,7 +64,8 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b
haveGlyphs = true;
}
}
- } else if (wkGetVerticalGlyphsForCharacters(fontData->platformData().ctFont(), buffer, glyphs.data(), bufferLength)) {
+ } else if ((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);
diff --git a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
index e3c371a2c..a83e0de97 100644
--- a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
+++ b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
@@ -278,6 +278,10 @@ void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>)
{
}
+void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<ErrorMessageCallback>)
+{
+}
+
}
#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
index 951dfff97..3089ae2d4 100644
--- a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
+++ b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
@@ -35,22 +35,18 @@
#ifdef __OBJC__
#import <QTKit/QTTime.h>
-@class QTMovie;
-@class QTMovieView;
-@class QTMovieLayer;
-@class QTVideoRendererWebKitOnly;
-@class WebCoreMovieObserver;
#else
-class NSDictionary;
-class NSMutableDictionary;
-class QTMovie;
-class QTMovieView;
class QTTime;
-class QTMovieLayer;
-class QTVideoRendererWebKitOnly;
-class WebCoreMovieObserver;
#endif
+OBJC_CLASS NSDictionary;
+OBJC_CLASS NSMutableDictionary;
+OBJC_CLASS QTMovie;
+OBJC_CLASS QTMovieView;
+OBJC_CLASS QTMovieLayer;
+OBJC_CLASS QTVideoRendererWebKitOnly;
+OBJC_CLASS WebCoreMovieObserver;
+
#ifndef DRAW_FRAME_RATE
#define DRAW_FRAME_RATE 0
#endif
diff --git a/Source/WebCore/platform/graphics/mac/MediaPlayerProxy.h b/Source/WebCore/platform/graphics/mac/MediaPlayerProxy.h
index cc7ec9556..c586fb86f 100644
--- a/Source/WebCore/platform/graphics/mac/MediaPlayerProxy.h
+++ b/Source/WebCore/platform/graphics/mac/MediaPlayerProxy.h
@@ -26,11 +26,7 @@
#ifndef MediaPlayerProxy_h
#define MediaPlayerProxy_h
-#ifdef __OBJC__
-@class WebMediaPlayerProxy;
-#else
-class WebMediaPlayerProxy;
-#endif
+OBJC_CLASS WebMediaPlayerProxy;
enum MediaPlayerProxyNotificationType {
diff --git a/Source/WebCore/platform/graphics/mac/WebLayer.mm b/Source/WebCore/platform/graphics/mac/WebLayer.mm
index 7c388d31f..277104148 100644
--- a/Source/WebCore/platform/graphics/mac/WebLayer.mm
+++ b/Source/WebCore/platform/graphics/mac/WebLayer.mm
@@ -85,7 +85,7 @@ void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCA
// Re-fetch the layer owner, since <rdar://problem/9125151> indicates that it might have been destroyed during painting.
layerContents = platformLayer->owner();
ASSERT(layerContents);
- if (layerContents && layerContents->platformCALayerShowRepaintCounter()) {
+ if (platformLayer->layerType() != PlatformCALayer::LayerTypeTileCacheLayer && layerContents && layerContents->platformCALayerShowRepaintCounter()) {
bool isTiledLayer = [layer isKindOfClass:[CATiledLayer class]];
char text[16]; // that's a lot of repaints
diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
index 16a3b4a9c..47a41c6d0 100644
--- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
+++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
@@ -29,22 +29,8 @@
#include "GraphicsContext3D.h"
-#include "CanvasRenderingContext.h"
#include "Extensions3DOpenGL.h"
-#include "GraphicsContext.h"
-#include "HTMLCanvasElement.h"
-#include "ImageBuffer.h"
-#include "ImageData.h"
#include "NotImplemented.h"
-#include "WebGLObject.h"
-#include <cstring>
-#include <wtf/ArrayBuffer.h>
-#include <wtf/ArrayBufferView.h>
-#include <wtf/Float32Array.h>
-#include <wtf/Int32Array.h>
-#include <wtf/Uint8Array.h>
-#include <wtf/UnusedParam.h>
-#include <wtf/text/CString.h>
#if PLATFORM(MAC)
#include <OpenGL/gl.h>
@@ -57,30 +43,6 @@
namespace WebCore {
-void GraphicsContext3D::validateAttributes()
-{
- Extensions3D* extensions = getExtensions();
- if (m_attrs.stencil) {
- if (extensions->supports("GL_EXT_packed_depth_stencil")) {
- extensions->ensureEnabled("GL_EXT_packed_depth_stencil");
- // Force depth if stencil is true.
- m_attrs.depth = true;
- } else
- m_attrs.stencil = false;
- }
- if (m_attrs.antialias) {
- bool isValidVendor = true;
- // Currently in Mac we only turn on antialias if vendor is NVIDIA.
- const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR));
- if (!std::strstr(vendor, "NVIDIA"))
- isValidVendor = false;
- if (!isValidVendor || !extensions->supports("GL_ANGLE_framebuffer_multisample"))
- m_attrs.antialias = false;
- else
- extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample");
- }
-}
-
void GraphicsContext3D::readRenderingResults(unsigned char *pixels, int pixelsSize)
{
if (pixelsSize < m_currentWidth * m_currentHeight * 4)
@@ -119,66 +81,6 @@ void GraphicsContext3D::readRenderingResults(unsigned char *pixels, int pixelsSi
::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO);
}
-bool GraphicsContext3D::isResourceSafe()
-{
- return false;
-}
-
-#if !PLATFORM(QT)
-void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* context, DrawingBuffer*)
-{
- HTMLCanvasElement* canvas = context->canvas();
- ImageBuffer* imageBuffer = canvas->buffer();
-
- int rowBytes = m_currentWidth * 4;
- int totalBytes = rowBytes * m_currentHeight;
-
- OwnArrayPtr<unsigned char> pixels = adoptArrayPtr(new unsigned char[totalBytes]);
- if (!pixels)
- return;
-
- readRenderingResults(pixels.get(), totalBytes);
-
- if (!m_attrs.premultipliedAlpha) {
- for (int i = 0; i < totalBytes; i += 4) {
- // Premultiply alpha
- pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255);
- pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255);
- pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255);
- }
- }
-
- paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight,
- canvas->width(), canvas->height(), imageBuffer->context()->platformContext());
-}
-#endif
-
-bool GraphicsContext3D::paintCompositedResultsToCanvas(CanvasRenderingContext*)
-{
- // Not needed at the moment, so return that nothing was done.
- return false;
-}
-
-PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData(DrawingBuffer*)
-{
- // Reading premultiplied alpha would involve unpremultiplying, which is
- // lossy
- if (m_attrs.premultipliedAlpha)
- return 0;
-
- RefPtr<ImageData> imageData = ImageData::create(IntSize(m_currentWidth, m_currentHeight));
- unsigned char* pixels = imageData->data()->data()->data();
- int totalBytes = 4 * m_currentWidth * m_currentHeight;
-
- readRenderingResults(pixels, totalBytes);
-
- // Convert to RGBA
- for (int i = 0; i < totalBytes; i += 4)
- std::swap(pixels[i], pixels[i + 2]);
-
- return imageData.release();
-}
-
void GraphicsContext3D::reshape(int width, int height)
{
if (!platformGraphicsContext3D())
@@ -333,11 +235,6 @@ void GraphicsContext3D::reshape(int width, int height)
::glFlush();
}
-IntSize GraphicsContext3D::getInternalFramebufferSize() const
-{
- return IntSize(m_currentWidth, m_currentHeight);
-}
-
void GraphicsContext3D::prepareTexture()
{
if (m_layerComposited)
@@ -359,35 +256,6 @@ void GraphicsContext3D::prepareTexture()
m_layerComposited = true;
}
-void GraphicsContext3D::activeTexture(GC3Denum texture)
-{
- makeContextCurrent();
- m_activeTexture = texture;
- ::glActiveTexture(texture);
-}
-
-void GraphicsContext3D::attachShader(Platform3DObject program, Platform3DObject shader)
-{
- ASSERT(program);
- ASSERT(shader);
- makeContextCurrent();
- ::glAttachShader(program, shader);
-}
-
-void GraphicsContext3D::bindAttribLocation(Platform3DObject program, GC3Duint index, const String& name)
-{
- ASSERT(program);
- makeContextCurrent();
- ::glBindAttribLocation(program, index, name.utf8().data());
-}
-
-void GraphicsContext3D::bindBuffer(GC3Denum target, Platform3DObject buffer)
-{
- makeContextCurrent();
- ::glBindBuffer(target, buffer);
-}
-
-
void GraphicsContext3D::bindFramebuffer(GC3Denum target, Platform3DObject buffer)
{
makeContextCurrent();
@@ -402,158 +270,6 @@ void GraphicsContext3D::bindFramebuffer(GC3Denum target, Platform3DObject buffer
}
}
-void GraphicsContext3D::bindRenderbuffer(GC3Denum target, Platform3DObject renderbuffer)
-{
- makeContextCurrent();
- ::glBindRenderbufferEXT(target, renderbuffer);
-}
-
-
-void GraphicsContext3D::bindTexture(GC3Denum target, Platform3DObject texture)
-{
- makeContextCurrent();
- if (m_activeTexture && target == GL_TEXTURE_2D)
- m_boundTexture0 = texture;
- ::glBindTexture(target, texture);
-}
-
-void GraphicsContext3D::blendColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha)
-{
- makeContextCurrent();
- ::glBlendColor(red, green, blue, alpha);
-}
-
-void GraphicsContext3D::blendEquation(GC3Denum mode)
-{
- makeContextCurrent();
- ::glBlendEquation(mode);
-}
-
-void GraphicsContext3D::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha)
-{
- makeContextCurrent();
- ::glBlendEquationSeparate(modeRGB, modeAlpha);
-}
-
-
-void GraphicsContext3D::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
-{
- makeContextCurrent();
- ::glBlendFunc(sfactor, dfactor);
-}
-
-void GraphicsContext3D::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha)
-{
- makeContextCurrent();
- ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
-}
-
-void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage)
-{
- makeContextCurrent();
- ::glBufferData(target, size, 0, usage);
-}
-
-void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage)
-{
- makeContextCurrent();
- ::glBufferData(target, size, data, usage);
-}
-
-void GraphicsContext3D::bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr size, const void* data)
-{
- makeContextCurrent();
- ::glBufferSubData(target, offset, size, data);
-}
-
-GC3Denum GraphicsContext3D::checkFramebufferStatus(GC3Denum target)
-{
- makeContextCurrent();
- return ::glCheckFramebufferStatusEXT(target);
-}
-
-void GraphicsContext3D::clearColor(GC3Dclampf r, GC3Dclampf g, GC3Dclampf b, GC3Dclampf a)
-{
- makeContextCurrent();
- ::glClearColor(r, g, b, a);
-}
-
-void GraphicsContext3D::clear(GC3Dbitfield mask)
-{
- makeContextCurrent();
- ::glClear(mask);
-}
-
-void GraphicsContext3D::clearDepth(GC3Dclampf depth)
-{
- makeContextCurrent();
- ::glClearDepth(depth);
-}
-
-void GraphicsContext3D::clearStencil(GC3Dint s)
-{
- makeContextCurrent();
- ::glClearStencil(s);
-}
-
-void GraphicsContext3D::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha)
-{
- makeContextCurrent();
- ::glColorMask(red, green, blue, alpha);
-}
-
-void GraphicsContext3D::compileShader(Platform3DObject shader)
-{
- ASSERT(shader);
- makeContextCurrent();
-
- int GLshaderType;
- ANGLEShaderType shaderType;
-
- glGetShaderiv(shader, SHADER_TYPE, &GLshaderType);
-
- if (GLshaderType == VERTEX_SHADER)
- shaderType = SHADER_TYPE_VERTEX;
- else if (GLshaderType == FRAGMENT_SHADER)
- shaderType = SHADER_TYPE_FRAGMENT;
- else
- return; // Invalid shader type.
-
- HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
-
- if (result == m_shaderSourceMap.end())
- return;
-
- ShaderSourceEntry& entry = result->second;
-
- String translatedShaderSource;
- String shaderInfoLog;
-
- bool isValid = m_compiler.validateShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog);
-
- entry.log = shaderInfoLog;
- entry.isValid = isValid;
-
- if (!isValid)
- return; // Shader didn't validate, don't move forward with compiling translated source
-
- int translatedShaderLength = translatedShaderSource.length();
-
- const CString& translatedShaderCString = translatedShaderSource.utf8();
- const char* translatedShaderPtr = translatedShaderCString.data();
-
- ::glShaderSource(shader, 1, &translatedShaderPtr, &translatedShaderLength);
-
- ::glCompileShader(shader);
-
- int GLCompileSuccess;
-
- ::glGetShaderiv(shader, COMPILE_STATUS, &GLCompileSuccess);
-
- // ASSERT that ANGLE generated GLSL will be accepted by OpenGL
- ASSERT(GLCompileSuccess == GL_TRUE);
-}
-
void GraphicsContext3D::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
{
makeContextCurrent();
@@ -582,132 +298,6 @@ void GraphicsContext3D::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Din
::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO);
}
-void GraphicsContext3D::cullFace(GC3Denum mode)
-{
- makeContextCurrent();
- ::glCullFace(mode);
-}
-
-void GraphicsContext3D::depthFunc(GC3Denum func)
-{
- makeContextCurrent();
- ::glDepthFunc(func);
-}
-
-void GraphicsContext3D::depthMask(GC3Dboolean flag)
-{
- makeContextCurrent();
- ::glDepthMask(flag);
-}
-
-void GraphicsContext3D::depthRange(GC3Dclampf zNear, GC3Dclampf zFar)
-{
- makeContextCurrent();
- ::glDepthRange(zNear, zFar);
-}
-
-void GraphicsContext3D::detachShader(Platform3DObject program, Platform3DObject shader)
-{
- ASSERT(program);
- ASSERT(shader);
- makeContextCurrent();
- ::glDetachShader(program, shader);
-}
-
-void GraphicsContext3D::disable(GC3Denum cap)
-{
- makeContextCurrent();
- ::glDisable(cap);
-}
-
-void GraphicsContext3D::disableVertexAttribArray(GC3Duint index)
-{
- makeContextCurrent();
- ::glDisableVertexAttribArray(index);
-}
-
-void GraphicsContext3D::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count)
-{
- makeContextCurrent();
- ::glDrawArrays(mode, first, count);
-}
-
-void GraphicsContext3D::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset)
-{
- makeContextCurrent();
- ::glDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)));
-}
-
-void GraphicsContext3D::enable(GC3Denum cap)
-{
- makeContextCurrent();
- ::glEnable(cap);
-}
-
-void GraphicsContext3D::enableVertexAttribArray(GC3Duint index)
-{
- makeContextCurrent();
- ::glEnableVertexAttribArray(index);
-}
-
-void GraphicsContext3D::finish()
-{
- makeContextCurrent();
- ::glFinish();
-}
-
-void GraphicsContext3D::flush()
-{
- makeContextCurrent();
- ::glFlush();
-}
-
-void GraphicsContext3D::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, Platform3DObject buffer)
-{
- makeContextCurrent();
- ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, buffer);
-}
-
-void GraphicsContext3D::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, Platform3DObject texture, GC3Dint level)
-{
- makeContextCurrent();
- ::glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
-}
-
-void GraphicsContext3D::frontFace(GC3Denum mode)
-{
- makeContextCurrent();
- ::glFrontFace(mode);
-}
-
-void GraphicsContext3D::generateMipmap(GC3Denum target)
-{
- makeContextCurrent();
- ::glGenerateMipmapEXT(target);
-}
-
-bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info)
-{
- if (!program) {
- synthesizeGLError(INVALID_VALUE);
- return false;
- }
- makeContextCurrent();
- GLint maxAttributeSize = 0;
- ::glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeSize);
- GLchar name[maxAttributeSize]; // GL_ACTIVE_ATTRIBUTE_MAX_LENGTH includes null termination
- GLsizei nameLength = 0;
- GLint size = 0;
- GLenum type = 0;
- ::glGetActiveAttrib(program, index, maxAttributeSize, &nameLength, &size, &type, name);
- if (!nameLength)
- return false;
- info.name = String(name, nameLength);
- info.type = type;
- info.size = size;
- return true;
-}
-
bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info)
{
if (!program) {
@@ -730,139 +320,6 @@ bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint inde
return true;
}
-void GraphicsContext3D::getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount, GC3Dsizei* count, Platform3DObject* shaders)
-{
- if (!program) {
- synthesizeGLError(INVALID_VALUE);
- return;
- }
- makeContextCurrent();
- ::glGetAttachedShaders(program, maxCount, count, shaders);
-}
-
-int GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name)
-{
- if (!program)
- return -1;
-
- makeContextCurrent();
- return ::glGetAttribLocation(program, name.utf8().data());
-}
-
-GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes()
-{
- return m_attrs;
-}
-
-GC3Denum GraphicsContext3D::getError()
-{
- if (m_syntheticErrors.size() > 0) {
- ListHashSet<GC3Denum>::iterator iter = m_syntheticErrors.begin();
- GC3Denum err = *iter;
- m_syntheticErrors.remove(iter);
- return err;
- }
-
- makeContextCurrent();
- return ::glGetError();
-}
-
-String GraphicsContext3D::getString(GC3Denum name)
-{
- makeContextCurrent();
- return String(reinterpret_cast<const char*>(::glGetString(name)));
-}
-
-void GraphicsContext3D::hint(GC3Denum target, GC3Denum mode)
-{
- makeContextCurrent();
- ::glHint(target, mode);
-}
-
-GC3Dboolean GraphicsContext3D::isBuffer(Platform3DObject buffer)
-{
- if (!buffer)
- return GL_FALSE;
-
- makeContextCurrent();
- return ::glIsBuffer(buffer);
-}
-
-GC3Dboolean GraphicsContext3D::isEnabled(GC3Denum cap)
-{
- makeContextCurrent();
- return ::glIsEnabled(cap);
-}
-
-GC3Dboolean GraphicsContext3D::isFramebuffer(Platform3DObject framebuffer)
-{
- if (!framebuffer)
- return GL_FALSE;
-
- makeContextCurrent();
- return ::glIsFramebufferEXT(framebuffer);
-}
-
-GC3Dboolean GraphicsContext3D::isProgram(Platform3DObject program)
-{
- if (!program)
- return GL_FALSE;
-
- makeContextCurrent();
- return ::glIsProgram(program);
-}
-
-GC3Dboolean GraphicsContext3D::isRenderbuffer(Platform3DObject renderbuffer)
-{
- if (!renderbuffer)
- return GL_FALSE;
-
- makeContextCurrent();
- return ::glIsRenderbufferEXT(renderbuffer);
-}
-
-GC3Dboolean GraphicsContext3D::isShader(Platform3DObject shader)
-{
- if (!shader)
- return GL_FALSE;
-
- makeContextCurrent();
- return ::glIsShader(shader);
-}
-
-GC3Dboolean GraphicsContext3D::isTexture(Platform3DObject texture)
-{
- if (!texture)
- return GL_FALSE;
-
- makeContextCurrent();
- return ::glIsTexture(texture);
-}
-
-void GraphicsContext3D::lineWidth(GC3Dfloat width)
-{
- makeContextCurrent();
- ::glLineWidth(width);
-}
-
-void GraphicsContext3D::linkProgram(Platform3DObject program)
-{
- ASSERT(program);
- makeContextCurrent();
- ::glLinkProgram(program);
-}
-
-void GraphicsContext3D::pixelStorei(GC3Denum pname, GC3Dint param)
-{
- makeContextCurrent();
- ::glPixelStorei(pname, param);
-}
-
-void GraphicsContext3D::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
-{
- makeContextCurrent();
- ::glPolygonOffset(factor, units);
-}
void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data)
{
@@ -882,13 +339,6 @@ void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsi
::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO);
}
-void GraphicsContext3D::releaseShaderCompiler()
-{
- // FIXME: This is not implemented on desktop OpenGL. We need to have ifdefs for the different GL variants.
- makeContextCurrent();
- notImplemented();
-}
-
void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
{
makeContextCurrent();
@@ -910,302 +360,6 @@ void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalfo
::glRenderbufferStorageEXT(target, internalformat, width, height);
}
-void GraphicsContext3D::sampleCoverage(GC3Dclampf value, GC3Dboolean invert)
-{
- makeContextCurrent();
- ::glSampleCoverage(value, invert);
-}
-
-void GraphicsContext3D::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
-{
- makeContextCurrent();
- ::glScissor(x, y, width, height);
-}
-
-void GraphicsContext3D::shaderSource(Platform3DObject shader, const String& string)
-{
- ASSERT(shader);
-
- makeContextCurrent();
-
- ShaderSourceEntry entry;
-
- entry.source = string;
-
- m_shaderSourceMap.set(shader, entry);
-}
-
-void GraphicsContext3D::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
-{
- makeContextCurrent();
- ::glStencilFunc(func, ref, mask);
-}
-
-void GraphicsContext3D::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask)
-{
- makeContextCurrent();
- ::glStencilFuncSeparate(face, func, ref, mask);
-}
-
-void GraphicsContext3D::stencilMask(GC3Duint mask)
-{
- makeContextCurrent();
- ::glStencilMask(mask);
-}
-
-void GraphicsContext3D::stencilMaskSeparate(GC3Denum face, GC3Duint mask)
-{
- makeContextCurrent();
- ::glStencilMaskSeparate(face, mask);
-}
-
-void GraphicsContext3D::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
-{
- makeContextCurrent();
- ::glStencilOp(fail, zfail, zpass);
-}
-
-void GraphicsContext3D::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
-{
- makeContextCurrent();
- ::glStencilOpSeparate(face, fail, zfail, zpass);
-}
-
-void GraphicsContext3D::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat value)
-{
- makeContextCurrent();
- ::glTexParameterf(target, pname, value);
-}
-
-void GraphicsContext3D::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint value)
-{
- makeContextCurrent();
- ::glTexParameteri(target, pname, value);
-}
-
-void GraphicsContext3D::uniform1f(GC3Dint location, GC3Dfloat v0)
-{
- makeContextCurrent();
- ::glUniform1f(location, v0);
-}
-
-void GraphicsContext3D::uniform1fv(GC3Dint location, GC3Dfloat* array, GC3Dsizei size)
-{
- makeContextCurrent();
- ::glUniform1fv(location, size, array);
-}
-
-void GraphicsContext3D::uniform2f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1)
-{
- makeContextCurrent();
- ::glUniform2f(location, v0, v1);
-}
-
-void GraphicsContext3D::uniform2fv(GC3Dint location, GC3Dfloat* array, GC3Dsizei size)
-{
- // FIXME: length needs to be a multiple of 2
- makeContextCurrent();
- ::glUniform2fv(location, size, array);
-}
-
-void GraphicsContext3D::uniform3f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
-{
- makeContextCurrent();
- ::glUniform3f(location, v0, v1, v2);
-}
-
-void GraphicsContext3D::uniform3fv(GC3Dint location, GC3Dfloat* array, GC3Dsizei size)
-{
- // FIXME: length needs to be a multiple of 3
- makeContextCurrent();
- ::glUniform3fv(location, size, array);
-}
-
-void GraphicsContext3D::uniform4f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
-{
- makeContextCurrent();
- ::glUniform4f(location, v0, v1, v2, v3);
-}
-
-void GraphicsContext3D::uniform4fv(GC3Dint location, GC3Dfloat* array, GC3Dsizei size)
-{
- // FIXME: length needs to be a multiple of 4
- makeContextCurrent();
- ::glUniform4fv(location, size, array);
-}
-
-void GraphicsContext3D::uniform1i(GC3Dint location, GC3Dint v0)
-{
- makeContextCurrent();
- ::glUniform1i(location, v0);
-}
-
-void GraphicsContext3D::uniform1iv(GC3Dint location, GC3Dint* array, GC3Dsizei size)
-{
- makeContextCurrent();
- ::glUniform1iv(location, size, array);
-}
-
-void GraphicsContext3D::uniform2i(GC3Dint location, GC3Dint v0, GC3Dint v1)
-{
- makeContextCurrent();
- ::glUniform2i(location, v0, v1);
-}
-
-void GraphicsContext3D::uniform2iv(GC3Dint location, GC3Dint* array, GC3Dsizei size)
-{
- // FIXME: length needs to be a multiple of 2
- makeContextCurrent();
- ::glUniform2iv(location, size, array);
-}
-
-void GraphicsContext3D::uniform3i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3Dint v2)
-{
- makeContextCurrent();
- ::glUniform3i(location, v0, v1, v2);
-}
-
-void GraphicsContext3D::uniform3iv(GC3Dint location, GC3Dint* array, GC3Dsizei size)
-{
- // FIXME: length needs to be a multiple of 3
- makeContextCurrent();
- ::glUniform3iv(location, size, array);
-}
-
-void GraphicsContext3D::uniform4i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3Dint v2, GC3Dint v3)
-{
- makeContextCurrent();
- ::glUniform4i(location, v0, v1, v2, v3);
-}
-
-void GraphicsContext3D::uniform4iv(GC3Dint location, GC3Dint* array, GC3Dsizei size)
-{
- // FIXME: length needs to be a multiple of 4
- makeContextCurrent();
- ::glUniform4iv(location, size, array);
-}
-
-void GraphicsContext3D::uniformMatrix2fv(GC3Dint location, GC3Dboolean transpose, GC3Dfloat* array, GC3Dsizei size)
-{
- // FIXME: length needs to be a multiple of 4
- makeContextCurrent();
- ::glUniformMatrix2fv(location, size, transpose, array);
-}
-
-void GraphicsContext3D::uniformMatrix3fv(GC3Dint location, GC3Dboolean transpose, GC3Dfloat* array, GC3Dsizei size)
-{
- // FIXME: length needs to be a multiple of 9
- makeContextCurrent();
- ::glUniformMatrix3fv(location, size, transpose, array);
-}
-
-void GraphicsContext3D::uniformMatrix4fv(GC3Dint location, GC3Dboolean transpose, GC3Dfloat* array, GC3Dsizei size)
-{
- // FIXME: length needs to be a multiple of 16
- makeContextCurrent();
- ::glUniformMatrix4fv(location, size, transpose, array);
-}
-
-void GraphicsContext3D::useProgram(Platform3DObject program)
-{
- makeContextCurrent();
- ::glUseProgram(program);
-}
-
-void GraphicsContext3D::validateProgram(Platform3DObject program)
-{
- ASSERT(program);
-
- makeContextCurrent();
- ::glValidateProgram(program);
-}
-
-void GraphicsContext3D::vertexAttrib1f(GC3Duint index, GC3Dfloat v0)
-{
- makeContextCurrent();
- ::glVertexAttrib1f(index, v0);
-}
-
-void GraphicsContext3D::vertexAttrib1fv(GC3Duint index, GC3Dfloat* array)
-{
- makeContextCurrent();
- ::glVertexAttrib1fv(index, array);
-}
-
-void GraphicsContext3D::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1)
-{
- makeContextCurrent();
- ::glVertexAttrib2f(index, v0, v1);
-}
-
-void GraphicsContext3D::vertexAttrib2fv(GC3Duint index, GC3Dfloat* array)
-{
- makeContextCurrent();
- ::glVertexAttrib2fv(index, array);
-}
-
-void GraphicsContext3D::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
-{
- makeContextCurrent();
- ::glVertexAttrib3f(index, v0, v1, v2);
-}
-
-void GraphicsContext3D::vertexAttrib3fv(GC3Duint index, GC3Dfloat* array)
-{
- makeContextCurrent();
- ::glVertexAttrib3fv(index, array);
-}
-
-void GraphicsContext3D::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
-{
- makeContextCurrent();
- ::glVertexAttrib4f(index, v0, v1, v2, v3);
-}
-
-void GraphicsContext3D::vertexAttrib4fv(GC3Duint index, GC3Dfloat* array)
-{
- makeContextCurrent();
- ::glVertexAttrib4fv(index, array);
-}
-
-void GraphicsContext3D::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset)
-{
- makeContextCurrent();
- ::glVertexAttribPointer(index, size, type, normalized, stride, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)));
-}
-
-void GraphicsContext3D::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
-{
- makeContextCurrent();
- ::glViewport(x, y, width, height);
-}
-
-void GraphicsContext3D::getBooleanv(GC3Denum pname, GC3Dboolean* value)
-{
- makeContextCurrent();
- ::glGetBooleanv(pname, value);
-}
-
-void GraphicsContext3D::getBufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
-{
- makeContextCurrent();
- ::glGetBufferParameteriv(target, pname, value);
-}
-
-void GraphicsContext3D::getFloatv(GC3Denum pname, GC3Dfloat* value)
-{
- makeContextCurrent();
- ::glGetFloatv(pname, value);
-}
-
-void GraphicsContext3D::getFramebufferAttachmentParameteriv(GC3Denum target, GC3Denum attachment, GC3Denum pname, GC3Dint* value)
-{
- makeContextCurrent();
- if (attachment == DEPTH_STENCIL_ATTACHMENT)
- attachment = DEPTH_ATTACHMENT; // Or STENCIL_ATTACHMENT, either works.
- ::glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value);
-}
-
void GraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value)
{
// Need to emulate MAX_FRAGMENT/VERTEX_UNIFORM_VECTORS and MAX_VARYING_VECTORS
@@ -1231,163 +385,6 @@ void GraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value)
}
}
-void GraphicsContext3D::getProgramiv(Platform3DObject program, GC3Denum pname, GC3Dint* value)
-{
- makeContextCurrent();
- ::glGetProgramiv(program, pname, value);
-}
-
-String GraphicsContext3D::getProgramInfoLog(Platform3DObject program)
-{
- ASSERT(program);
-
- makeContextCurrent();
- GLint length = 0;
- ::glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
- if (!length)
- return String();
-
- GLsizei size = 0;
- OwnArrayPtr<GLchar> info = adoptArrayPtr(new GLchar[length]);
- ::glGetProgramInfoLog(program, length, &size, info.get());
-
- return String(info.get());
-}
-
-void GraphicsContext3D::getRenderbufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
-{
- makeContextCurrent();
- ::glGetRenderbufferParameterivEXT(target, pname, value);
-}
-
-void GraphicsContext3D::getShaderiv(Platform3DObject shader, GC3Denum pname, GC3Dint* value)
-{
- ASSERT(shader);
-
- makeContextCurrent();
-
- HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
-
- switch (pname) {
- case DELETE_STATUS:
- case SHADER_TYPE:
- ::glGetShaderiv(shader, pname, value);
- break;
- case COMPILE_STATUS:
- if (result == m_shaderSourceMap.end()) {
- *value = static_cast<int>(false);
- return;
- }
- *value = static_cast<int>(result->second.isValid);
- break;
- case INFO_LOG_LENGTH:
- if (result == m_shaderSourceMap.end()) {
- *value = 0;
- return;
- }
- *value = getShaderInfoLog(shader).length();
- break;
- case SHADER_SOURCE_LENGTH:
- *value = getShaderSource(shader).length();
- break;
- default:
- synthesizeGLError(INVALID_ENUM);
- }
-}
-
-String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader)
-{
- ASSERT(shader);
-
- makeContextCurrent();
-
- HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
- if (result == m_shaderSourceMap.end())
- return String();
-
- ShaderSourceEntry entry = result->second;
- if (!entry.isValid)
- return entry.log;
-
- GLint length = 0;
- ::glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
- if (!length)
- return String();
-
- GLsizei size = 0;
- OwnArrayPtr<GLchar> info = adoptArrayPtr(new GLchar[length]);
- ::glGetShaderInfoLog(shader, length, &size, info.get());
-
- return String(info.get());
-}
-
-String GraphicsContext3D::getShaderSource(Platform3DObject shader)
-{
- ASSERT(shader);
-
- makeContextCurrent();
-
- HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
- if (result == m_shaderSourceMap.end())
- return String();
-
- return result->second.source;
-}
-
-
-void GraphicsContext3D::getTexParameterfv(GC3Denum target, GC3Denum pname, GC3Dfloat* value)
-{
- makeContextCurrent();
- ::glGetTexParameterfv(target, pname, value);
-}
-
-void GraphicsContext3D::getTexParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
-{
- makeContextCurrent();
- ::glGetTexParameteriv(target, pname, value);
-}
-
-void GraphicsContext3D::getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value)
-{
- makeContextCurrent();
- ::glGetUniformfv(program, location, value);
-}
-
-void GraphicsContext3D::getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value)
-{
- makeContextCurrent();
- ::glGetUniformiv(program, location, value);
-}
-
-GC3Dint GraphicsContext3D::getUniformLocation(Platform3DObject program, const String& name)
-{
- ASSERT(program);
-
- makeContextCurrent();
- return ::glGetUniformLocation(program, name.utf8().data());
-}
-
-void GraphicsContext3D::getVertexAttribfv(GC3Duint index, GC3Denum pname, GC3Dfloat* value)
-{
- makeContextCurrent();
- ::glGetVertexAttribfv(index, pname, value);
-}
-
-void GraphicsContext3D::getVertexAttribiv(GC3Duint index, GC3Denum pname, GC3Dint* value)
-{
- makeContextCurrent();
- ::glGetVertexAttribiv(index, pname, value);
-}
-
-GC3Dsizeiptr GraphicsContext3D::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
-{
- makeContextCurrent();
-
- GLvoid* pointer = 0;
- ::glGetVertexAttribPointerv(index, pname, &pointer);
- return static_cast<GC3Dsizeiptr>(reinterpret_cast<intptr_t>(pointer));
-}
-
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) {
@@ -1407,133 +404,6 @@ bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum inte
return true;
}
-void GraphicsContext3D::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoff, GC3Dint yoff, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels)
-{
- makeContextCurrent();
-
- // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size
- ::glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels);
-}
-
-void GraphicsContext3D::compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Dsizei imageSize, const void* data)
-{
- makeContextCurrent();
- ::glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
-}
-
-void GraphicsContext3D::compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Dsizei imageSize, const void* data)
-{
- makeContextCurrent();
- ::glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
-}
-
-Platform3DObject GraphicsContext3D::createBuffer()
-{
- makeContextCurrent();
- GLuint o = 0;
- glGenBuffers(1, &o);
- return o;
-}
-
-Platform3DObject GraphicsContext3D::createFramebuffer()
-{
- makeContextCurrent();
- GLuint o = 0;
- glGenFramebuffersEXT(1, &o);
- return o;
-}
-
-Platform3DObject GraphicsContext3D::createProgram()
-{
- makeContextCurrent();
- return glCreateProgram();
-}
-
-Platform3DObject GraphicsContext3D::createRenderbuffer()
-{
- makeContextCurrent();
- GLuint o = 0;
- glGenRenderbuffersEXT(1, &o);
- return o;
-}
-
-Platform3DObject GraphicsContext3D::createShader(GC3Denum type)
-{
- makeContextCurrent();
- return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER);
-}
-
-Platform3DObject GraphicsContext3D::createTexture()
-{
- makeContextCurrent();
- GLuint o = 0;
- glGenTextures(1, &o);
- return o;
-}
-
-void GraphicsContext3D::deleteBuffer(Platform3DObject buffer)
-{
- makeContextCurrent();
- glDeleteBuffers(1, &buffer);
-}
-
-void GraphicsContext3D::deleteFramebuffer(Platform3DObject framebuffer)
-{
- makeContextCurrent();
- glDeleteFramebuffersEXT(1, &framebuffer);
-}
-
-void GraphicsContext3D::deleteProgram(Platform3DObject program)
-{
- makeContextCurrent();
- glDeleteProgram(program);
-}
-
-void GraphicsContext3D::deleteRenderbuffer(Platform3DObject renderbuffer)
-{
- makeContextCurrent();
- glDeleteRenderbuffersEXT(1, &renderbuffer);
-}
-
-void GraphicsContext3D::deleteShader(Platform3DObject shader)
-{
- makeContextCurrent();
- glDeleteShader(shader);
-}
-
-void GraphicsContext3D::deleteTexture(Platform3DObject texture)
-{
- makeContextCurrent();
- glDeleteTextures(1, &texture);
-}
-
-void GraphicsContext3D::synthesizeGLError(GC3Denum error)
-{
- m_syntheticErrors.add(error);
-}
-
-void GraphicsContext3D::markContextChanged()
-{
- m_layerComposited = false;
-}
-
-void GraphicsContext3D::markLayerComposited()
-{
- m_layerComposited = true;
-}
-
-bool GraphicsContext3D::layerComposited() const
-{
- return m_layerComposited;
-}
-
-Extensions3D* GraphicsContext3D::getExtensions()
-{
- if (!m_extensions)
- m_extensions = adoptPtr(new Extensions3DOpenGL(this));
- return m_extensions.get();
-}
-
}
#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp
new file mode 100644
index 000000000..e68bba7fd
--- /dev/null
+++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp
@@ -0,0 +1,1178 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(WEBGL)
+
+#include "GraphicsContext3D.h"
+
+#include "CanvasRenderingContext.h"
+#include "Extensions3DOpenGL.h"
+#include "GraphicsContext.h"
+#include "HTMLCanvasElement.h"
+#include "ImageBuffer.h"
+#include "ImageData.h"
+#include "NotImplemented.h"
+#include "WebGLObject.h"
+#include <cstring>
+#include <wtf/ArrayBuffer.h>
+#include <wtf/ArrayBufferView.h>
+#include <wtf/Float32Array.h>
+#include <wtf/Int32Array.h>
+#include <wtf/Uint8Array.h>
+#include <wtf/UnusedParam.h>
+#include <wtf/text/CString.h>
+
+#if PLATFORM(MAC)
+#include <OpenGL/gl.h>
+#elif PLATFORM(GTK)
+#include "OpenGLShims.h"
+#elif PLATFORM(QT)
+#include <QtGlobal>
+#include <cairo/OpenGLShims.h>
+#endif
+
+namespace WebCore {
+
+void GraphicsContext3D::validateAttributes()
+{
+ Extensions3D* extensions = getExtensions();
+ if (m_attrs.stencil) {
+ if (extensions->supports("GL_EXT_packed_depth_stencil")) {
+ extensions->ensureEnabled("GL_EXT_packed_depth_stencil");
+ // Force depth if stencil is true.
+ m_attrs.depth = true;
+ } else
+ m_attrs.stencil = false;
+ }
+ if (m_attrs.antialias) {
+ bool isValidVendor = true;
+ // Currently in Mac we only turn on antialias if vendor is NVIDIA.
+ const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR));
+ if (!std::strstr(vendor, "NVIDIA"))
+ isValidVendor = false;
+ if (!isValidVendor || !extensions->supports("GL_ANGLE_framebuffer_multisample"))
+ m_attrs.antialias = false;
+ else
+ extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample");
+ }
+}
+
+bool GraphicsContext3D::isResourceSafe()
+{
+ return false;
+}
+
+#if !PLATFORM(QT)
+void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* context, DrawingBuffer*)
+{
+ HTMLCanvasElement* canvas = context->canvas();
+ ImageBuffer* imageBuffer = canvas->buffer();
+
+ int rowBytes = m_currentWidth * 4;
+ int totalBytes = rowBytes * m_currentHeight;
+
+ OwnArrayPtr<unsigned char> pixels = adoptArrayPtr(new unsigned char[totalBytes]);
+ if (!pixels)
+ return;
+
+ readRenderingResults(pixels.get(), totalBytes);
+
+ if (!m_attrs.premultipliedAlpha) {
+ for (int i = 0; i < totalBytes; i += 4) {
+ // Premultiply alpha
+ pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255);
+ pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255);
+ pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255);
+ }
+ }
+
+ paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight,
+ canvas->width(), canvas->height(), imageBuffer->context()->platformContext());
+}
+#endif
+
+bool GraphicsContext3D::paintCompositedResultsToCanvas(CanvasRenderingContext*)
+{
+ // Not needed at the moment, so return that nothing was done.
+ return false;
+}
+
+PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData(DrawingBuffer*)
+{
+ // Reading premultiplied alpha would involve unpremultiplying, which is
+ // lossy
+ if (m_attrs.premultipliedAlpha)
+ return 0;
+
+ RefPtr<ImageData> imageData = ImageData::create(IntSize(m_currentWidth, m_currentHeight));
+ unsigned char* pixels = imageData->data()->data()->data();
+ int totalBytes = 4 * m_currentWidth * m_currentHeight;
+
+ readRenderingResults(pixels, totalBytes);
+
+ // Convert to RGBA
+ for (int i = 0; i < totalBytes; i += 4)
+ std::swap(pixels[i], pixels[i + 2]);
+
+ return imageData.release();
+}
+
+IntSize GraphicsContext3D::getInternalFramebufferSize() const
+{
+ return IntSize(m_currentWidth, m_currentHeight);
+}
+
+void GraphicsContext3D::activeTexture(GC3Denum texture)
+{
+ makeContextCurrent();
+ m_activeTexture = texture;
+ ::glActiveTexture(texture);
+}
+
+void GraphicsContext3D::attachShader(Platform3DObject program, Platform3DObject shader)
+{
+ ASSERT(program);
+ ASSERT(shader);
+ makeContextCurrent();
+ ::glAttachShader(program, shader);
+}
+
+void GraphicsContext3D::bindAttribLocation(Platform3DObject program, GC3Duint index, const String& name)
+{
+ ASSERT(program);
+ makeContextCurrent();
+ ::glBindAttribLocation(program, index, name.utf8().data());
+}
+
+void GraphicsContext3D::bindBuffer(GC3Denum target, Platform3DObject buffer)
+{
+ makeContextCurrent();
+ ::glBindBuffer(target, buffer);
+}
+
+void GraphicsContext3D::bindRenderbuffer(GC3Denum target, Platform3DObject renderbuffer)
+{
+ makeContextCurrent();
+ ::glBindRenderbufferEXT(target, renderbuffer);
+}
+
+
+void GraphicsContext3D::bindTexture(GC3Denum target, Platform3DObject texture)
+{
+ makeContextCurrent();
+ if (m_activeTexture && target == GL_TEXTURE_2D)
+ m_boundTexture0 = texture;
+ ::glBindTexture(target, texture);
+}
+
+void GraphicsContext3D::blendColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha)
+{
+ makeContextCurrent();
+ ::glBlendColor(red, green, blue, alpha);
+}
+
+void GraphicsContext3D::blendEquation(GC3Denum mode)
+{
+ makeContextCurrent();
+ ::glBlendEquation(mode);
+}
+
+void GraphicsContext3D::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha)
+{
+ makeContextCurrent();
+ ::glBlendEquationSeparate(modeRGB, modeAlpha);
+}
+
+
+void GraphicsContext3D::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
+{
+ makeContextCurrent();
+ ::glBlendFunc(sfactor, dfactor);
+}
+
+void GraphicsContext3D::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha)
+{
+ makeContextCurrent();
+ ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+
+void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage)
+{
+ makeContextCurrent();
+ ::glBufferData(target, size, 0, usage);
+}
+
+void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage)
+{
+ makeContextCurrent();
+ ::glBufferData(target, size, data, usage);
+}
+
+void GraphicsContext3D::bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr size, const void* data)
+{
+ makeContextCurrent();
+ ::glBufferSubData(target, offset, size, data);
+}
+
+GC3Denum GraphicsContext3D::checkFramebufferStatus(GC3Denum target)
+{
+ makeContextCurrent();
+ return ::glCheckFramebufferStatusEXT(target);
+}
+
+void GraphicsContext3D::clearColor(GC3Dclampf r, GC3Dclampf g, GC3Dclampf b, GC3Dclampf a)
+{
+ makeContextCurrent();
+ ::glClearColor(r, g, b, a);
+}
+
+void GraphicsContext3D::clear(GC3Dbitfield mask)
+{
+ makeContextCurrent();
+ ::glClear(mask);
+}
+
+void GraphicsContext3D::clearDepth(GC3Dclampf depth)
+{
+ makeContextCurrent();
+ ::glClearDepth(depth);
+}
+
+void GraphicsContext3D::clearStencil(GC3Dint s)
+{
+ makeContextCurrent();
+ ::glClearStencil(s);
+}
+
+void GraphicsContext3D::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha)
+{
+ makeContextCurrent();
+ ::glColorMask(red, green, blue, alpha);
+}
+
+void GraphicsContext3D::compileShader(Platform3DObject shader)
+{
+ ASSERT(shader);
+ makeContextCurrent();
+
+ int GLshaderType;
+ ANGLEShaderType shaderType;
+
+ glGetShaderiv(shader, SHADER_TYPE, &GLshaderType);
+
+ if (GLshaderType == VERTEX_SHADER)
+ shaderType = SHADER_TYPE_VERTEX;
+ else if (GLshaderType == FRAGMENT_SHADER)
+ shaderType = SHADER_TYPE_FRAGMENT;
+ else
+ return; // Invalid shader type.
+
+ HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
+
+ if (result == m_shaderSourceMap.end())
+ return;
+
+ ShaderSourceEntry& entry = result->second;
+
+ String translatedShaderSource;
+ String shaderInfoLog;
+
+ bool isValid = m_compiler.validateShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog);
+
+ entry.log = shaderInfoLog;
+ entry.isValid = isValid;
+
+ if (!isValid)
+ return; // Shader didn't validate, don't move forward with compiling translated source
+
+ int translatedShaderLength = translatedShaderSource.length();
+
+ const CString& translatedShaderCString = translatedShaderSource.utf8();
+ const char* translatedShaderPtr = translatedShaderCString.data();
+
+ ::glShaderSource(shader, 1, &translatedShaderPtr, &translatedShaderLength);
+
+ ::glCompileShader(shader);
+
+ int GLCompileSuccess;
+
+ ::glGetShaderiv(shader, COMPILE_STATUS, &GLCompileSuccess);
+
+ // ASSERT that ANGLE generated GLSL will be accepted by OpenGL
+ ASSERT(GLCompileSuccess == GL_TRUE);
+}
+
+void GraphicsContext3D::cullFace(GC3Denum mode)
+{
+ makeContextCurrent();
+ ::glCullFace(mode);
+}
+
+void GraphicsContext3D::depthFunc(GC3Denum func)
+{
+ makeContextCurrent();
+ ::glDepthFunc(func);
+}
+
+void GraphicsContext3D::depthMask(GC3Dboolean flag)
+{
+ makeContextCurrent();
+ ::glDepthMask(flag);
+}
+
+void GraphicsContext3D::depthRange(GC3Dclampf zNear, GC3Dclampf zFar)
+{
+ makeContextCurrent();
+ ::glDepthRange(zNear, zFar);
+}
+
+void GraphicsContext3D::detachShader(Platform3DObject program, Platform3DObject shader)
+{
+ ASSERT(program);
+ ASSERT(shader);
+ makeContextCurrent();
+ ::glDetachShader(program, shader);
+}
+
+void GraphicsContext3D::disable(GC3Denum cap)
+{
+ makeContextCurrent();
+ ::glDisable(cap);
+}
+
+void GraphicsContext3D::disableVertexAttribArray(GC3Duint index)
+{
+ makeContextCurrent();
+ ::glDisableVertexAttribArray(index);
+}
+
+void GraphicsContext3D::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count)
+{
+ makeContextCurrent();
+ ::glDrawArrays(mode, first, count);
+}
+
+void GraphicsContext3D::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset)
+{
+ makeContextCurrent();
+ ::glDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)));
+}
+
+void GraphicsContext3D::enable(GC3Denum cap)
+{
+ makeContextCurrent();
+ ::glEnable(cap);
+}
+
+void GraphicsContext3D::enableVertexAttribArray(GC3Duint index)
+{
+ makeContextCurrent();
+ ::glEnableVertexAttribArray(index);
+}
+
+void GraphicsContext3D::finish()
+{
+ makeContextCurrent();
+ ::glFinish();
+}
+
+void GraphicsContext3D::flush()
+{
+ makeContextCurrent();
+ ::glFlush();
+}
+
+void GraphicsContext3D::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, Platform3DObject buffer)
+{
+ makeContextCurrent();
+ ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, buffer);
+}
+
+void GraphicsContext3D::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, Platform3DObject texture, GC3Dint level)
+{
+ makeContextCurrent();
+ ::glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
+}
+
+void GraphicsContext3D::frontFace(GC3Denum mode)
+{
+ makeContextCurrent();
+ ::glFrontFace(mode);
+}
+
+void GraphicsContext3D::generateMipmap(GC3Denum target)
+{
+ makeContextCurrent();
+ ::glGenerateMipmapEXT(target);
+}
+
+bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info)
+{
+ if (!program) {
+ synthesizeGLError(INVALID_VALUE);
+ return false;
+ }
+ makeContextCurrent();
+ GLint maxAttributeSize = 0;
+ ::glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeSize);
+ GLchar name[maxAttributeSize]; // GL_ACTIVE_ATTRIBUTE_MAX_LENGTH includes null termination
+ GLsizei nameLength = 0;
+ GLint size = 0;
+ GLenum type = 0;
+ ::glGetActiveAttrib(program, index, maxAttributeSize, &nameLength, &size, &type, name);
+ if (!nameLength)
+ return false;
+ info.name = String(name, nameLength);
+ info.type = type;
+ info.size = size;
+ return true;
+}
+
+void GraphicsContext3D::getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount, GC3Dsizei* count, Platform3DObject* shaders)
+{
+ if (!program) {
+ synthesizeGLError(INVALID_VALUE);
+ return;
+ }
+ makeContextCurrent();
+ ::glGetAttachedShaders(program, maxCount, count, shaders);
+}
+
+int GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name)
+{
+ if (!program)
+ return -1;
+
+ makeContextCurrent();
+ return ::glGetAttribLocation(program, name.utf8().data());
+}
+
+GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes()
+{
+ return m_attrs;
+}
+
+GC3Denum GraphicsContext3D::getError()
+{
+ if (m_syntheticErrors.size() > 0) {
+ ListHashSet<GC3Denum>::iterator iter = m_syntheticErrors.begin();
+ GC3Denum err = *iter;
+ m_syntheticErrors.remove(iter);
+ return err;
+ }
+
+ makeContextCurrent();
+ return ::glGetError();
+}
+
+String GraphicsContext3D::getString(GC3Denum name)
+{
+ makeContextCurrent();
+ return String(reinterpret_cast<const char*>(::glGetString(name)));
+}
+
+void GraphicsContext3D::hint(GC3Denum target, GC3Denum mode)
+{
+ makeContextCurrent();
+ ::glHint(target, mode);
+}
+
+GC3Dboolean GraphicsContext3D::isBuffer(Platform3DObject buffer)
+{
+ if (!buffer)
+ return GL_FALSE;
+
+ makeContextCurrent();
+ return ::glIsBuffer(buffer);
+}
+
+GC3Dboolean GraphicsContext3D::isEnabled(GC3Denum cap)
+{
+ makeContextCurrent();
+ return ::glIsEnabled(cap);
+}
+
+GC3Dboolean GraphicsContext3D::isFramebuffer(Platform3DObject framebuffer)
+{
+ if (!framebuffer)
+ return GL_FALSE;
+
+ makeContextCurrent();
+ return ::glIsFramebufferEXT(framebuffer);
+}
+
+GC3Dboolean GraphicsContext3D::isProgram(Platform3DObject program)
+{
+ if (!program)
+ return GL_FALSE;
+
+ makeContextCurrent();
+ return ::glIsProgram(program);
+}
+
+GC3Dboolean GraphicsContext3D::isRenderbuffer(Platform3DObject renderbuffer)
+{
+ if (!renderbuffer)
+ return GL_FALSE;
+
+ makeContextCurrent();
+ return ::glIsRenderbufferEXT(renderbuffer);
+}
+
+GC3Dboolean GraphicsContext3D::isShader(Platform3DObject shader)
+{
+ if (!shader)
+ return GL_FALSE;
+
+ makeContextCurrent();
+ return ::glIsShader(shader);
+}
+
+GC3Dboolean GraphicsContext3D::isTexture(Platform3DObject texture)
+{
+ if (!texture)
+ return GL_FALSE;
+
+ makeContextCurrent();
+ return ::glIsTexture(texture);
+}
+
+void GraphicsContext3D::lineWidth(GC3Dfloat width)
+{
+ makeContextCurrent();
+ ::glLineWidth(width);
+}
+
+void GraphicsContext3D::linkProgram(Platform3DObject program)
+{
+ ASSERT(program);
+ makeContextCurrent();
+ ::glLinkProgram(program);
+}
+
+void GraphicsContext3D::pixelStorei(GC3Denum pname, GC3Dint param)
+{
+ makeContextCurrent();
+ ::glPixelStorei(pname, param);
+}
+
+void GraphicsContext3D::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
+{
+ makeContextCurrent();
+ ::glPolygonOffset(factor, units);
+}
+
+void GraphicsContext3D::releaseShaderCompiler()
+{
+ // FIXME: This is not implemented on desktop OpenGL. We need to have ifdefs for the different GL variants.
+ makeContextCurrent();
+ notImplemented();
+}
+
+void GraphicsContext3D::sampleCoverage(GC3Dclampf value, GC3Dboolean invert)
+{
+ makeContextCurrent();
+ ::glSampleCoverage(value, invert);
+}
+
+void GraphicsContext3D::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
+{
+ makeContextCurrent();
+ ::glScissor(x, y, width, height);
+}
+
+void GraphicsContext3D::shaderSource(Platform3DObject shader, const String& string)
+{
+ ASSERT(shader);
+
+ makeContextCurrent();
+
+ ShaderSourceEntry entry;
+
+ entry.source = string;
+
+ m_shaderSourceMap.set(shader, entry);
+}
+
+void GraphicsContext3D::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
+{
+ makeContextCurrent();
+ ::glStencilFunc(func, ref, mask);
+}
+
+void GraphicsContext3D::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask)
+{
+ makeContextCurrent();
+ ::glStencilFuncSeparate(face, func, ref, mask);
+}
+
+void GraphicsContext3D::stencilMask(GC3Duint mask)
+{
+ makeContextCurrent();
+ ::glStencilMask(mask);
+}
+
+void GraphicsContext3D::stencilMaskSeparate(GC3Denum face, GC3Duint mask)
+{
+ makeContextCurrent();
+ ::glStencilMaskSeparate(face, mask);
+}
+
+void GraphicsContext3D::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
+{
+ makeContextCurrent();
+ ::glStencilOp(fail, zfail, zpass);
+}
+
+void GraphicsContext3D::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
+{
+ makeContextCurrent();
+ ::glStencilOpSeparate(face, fail, zfail, zpass);
+}
+
+void GraphicsContext3D::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat value)
+{
+ makeContextCurrent();
+ ::glTexParameterf(target, pname, value);
+}
+
+void GraphicsContext3D::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint value)
+{
+ makeContextCurrent();
+ ::glTexParameteri(target, pname, value);
+}
+
+void GraphicsContext3D::uniform1f(GC3Dint location, GC3Dfloat v0)
+{
+ makeContextCurrent();
+ ::glUniform1f(location, v0);
+}
+
+void GraphicsContext3D::uniform1fv(GC3Dint location, GC3Dfloat* array, GC3Dsizei size)
+{
+ makeContextCurrent();
+ ::glUniform1fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform2f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1)
+{
+ makeContextCurrent();
+ ::glUniform2f(location, v0, v1);
+}
+
+void GraphicsContext3D::uniform2fv(GC3Dint location, GC3Dfloat* array, GC3Dsizei size)
+{
+ // FIXME: length needs to be a multiple of 2
+ makeContextCurrent();
+ ::glUniform2fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform3f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
+{
+ makeContextCurrent();
+ ::glUniform3f(location, v0, v1, v2);
+}
+
+void GraphicsContext3D::uniform3fv(GC3Dint location, GC3Dfloat* array, GC3Dsizei size)
+{
+ // FIXME: length needs to be a multiple of 3
+ makeContextCurrent();
+ ::glUniform3fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform4f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
+{
+ makeContextCurrent();
+ ::glUniform4f(location, v0, v1, v2, v3);
+}
+
+void GraphicsContext3D::uniform4fv(GC3Dint location, GC3Dfloat* array, GC3Dsizei size)
+{
+ // FIXME: length needs to be a multiple of 4
+ makeContextCurrent();
+ ::glUniform4fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform1i(GC3Dint location, GC3Dint v0)
+{
+ makeContextCurrent();
+ ::glUniform1i(location, v0);
+}
+
+void GraphicsContext3D::uniform1iv(GC3Dint location, GC3Dint* array, GC3Dsizei size)
+{
+ makeContextCurrent();
+ ::glUniform1iv(location, size, array);
+}
+
+void GraphicsContext3D::uniform2i(GC3Dint location, GC3Dint v0, GC3Dint v1)
+{
+ makeContextCurrent();
+ ::glUniform2i(location, v0, v1);
+}
+
+void GraphicsContext3D::uniform2iv(GC3Dint location, GC3Dint* array, GC3Dsizei size)
+{
+ // FIXME: length needs to be a multiple of 2
+ makeContextCurrent();
+ ::glUniform2iv(location, size, array);
+}
+
+void GraphicsContext3D::uniform3i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3Dint v2)
+{
+ makeContextCurrent();
+ ::glUniform3i(location, v0, v1, v2);
+}
+
+void GraphicsContext3D::uniform3iv(GC3Dint location, GC3Dint* array, GC3Dsizei size)
+{
+ // FIXME: length needs to be a multiple of 3
+ makeContextCurrent();
+ ::glUniform3iv(location, size, array);
+}
+
+void GraphicsContext3D::uniform4i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3Dint v2, GC3Dint v3)
+{
+ makeContextCurrent();
+ ::glUniform4i(location, v0, v1, v2, v3);
+}
+
+void GraphicsContext3D::uniform4iv(GC3Dint location, GC3Dint* array, GC3Dsizei size)
+{
+ // FIXME: length needs to be a multiple of 4
+ makeContextCurrent();
+ ::glUniform4iv(location, size, array);
+}
+
+void GraphicsContext3D::uniformMatrix2fv(GC3Dint location, GC3Dboolean transpose, GC3Dfloat* array, GC3Dsizei size)
+{
+ // FIXME: length needs to be a multiple of 4
+ makeContextCurrent();
+ ::glUniformMatrix2fv(location, size, transpose, array);
+}
+
+void GraphicsContext3D::uniformMatrix3fv(GC3Dint location, GC3Dboolean transpose, GC3Dfloat* array, GC3Dsizei size)
+{
+ // FIXME: length needs to be a multiple of 9
+ makeContextCurrent();
+ ::glUniformMatrix3fv(location, size, transpose, array);
+}
+
+void GraphicsContext3D::uniformMatrix4fv(GC3Dint location, GC3Dboolean transpose, GC3Dfloat* array, GC3Dsizei size)
+{
+ // FIXME: length needs to be a multiple of 16
+ makeContextCurrent();
+ ::glUniformMatrix4fv(location, size, transpose, array);
+}
+
+void GraphicsContext3D::useProgram(Platform3DObject program)
+{
+ makeContextCurrent();
+ ::glUseProgram(program);
+}
+
+void GraphicsContext3D::validateProgram(Platform3DObject program)
+{
+ ASSERT(program);
+
+ makeContextCurrent();
+ ::glValidateProgram(program);
+}
+
+void GraphicsContext3D::vertexAttrib1f(GC3Duint index, GC3Dfloat v0)
+{
+ makeContextCurrent();
+ ::glVertexAttrib1f(index, v0);
+}
+
+void GraphicsContext3D::vertexAttrib1fv(GC3Duint index, GC3Dfloat* array)
+{
+ makeContextCurrent();
+ ::glVertexAttrib1fv(index, array);
+}
+
+void GraphicsContext3D::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1)
+{
+ makeContextCurrent();
+ ::glVertexAttrib2f(index, v0, v1);
+}
+
+void GraphicsContext3D::vertexAttrib2fv(GC3Duint index, GC3Dfloat* array)
+{
+ makeContextCurrent();
+ ::glVertexAttrib2fv(index, array);
+}
+
+void GraphicsContext3D::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
+{
+ makeContextCurrent();
+ ::glVertexAttrib3f(index, v0, v1, v2);
+}
+
+void GraphicsContext3D::vertexAttrib3fv(GC3Duint index, GC3Dfloat* array)
+{
+ makeContextCurrent();
+ ::glVertexAttrib3fv(index, array);
+}
+
+void GraphicsContext3D::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
+{
+ makeContextCurrent();
+ ::glVertexAttrib4f(index, v0, v1, v2, v3);
+}
+
+void GraphicsContext3D::vertexAttrib4fv(GC3Duint index, GC3Dfloat* array)
+{
+ makeContextCurrent();
+ ::glVertexAttrib4fv(index, array);
+}
+
+void GraphicsContext3D::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset)
+{
+ makeContextCurrent();
+ ::glVertexAttribPointer(index, size, type, normalized, stride, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)));
+}
+
+void GraphicsContext3D::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
+{
+ makeContextCurrent();
+ ::glViewport(x, y, width, height);
+}
+
+void GraphicsContext3D::getBooleanv(GC3Denum pname, GC3Dboolean* value)
+{
+ makeContextCurrent();
+ ::glGetBooleanv(pname, value);
+}
+
+void GraphicsContext3D::getBufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
+{
+ makeContextCurrent();
+ ::glGetBufferParameteriv(target, pname, value);
+}
+
+void GraphicsContext3D::getFloatv(GC3Denum pname, GC3Dfloat* value)
+{
+ makeContextCurrent();
+ ::glGetFloatv(pname, value);
+}
+
+void GraphicsContext3D::getFramebufferAttachmentParameteriv(GC3Denum target, GC3Denum attachment, GC3Denum pname, GC3Dint* value)
+{
+ makeContextCurrent();
+ if (attachment == DEPTH_STENCIL_ATTACHMENT)
+ attachment = DEPTH_ATTACHMENT; // Or STENCIL_ATTACHMENT, either works.
+ ::glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value);
+}
+
+void GraphicsContext3D::getProgramiv(Platform3DObject program, GC3Denum pname, GC3Dint* value)
+{
+ makeContextCurrent();
+ ::glGetProgramiv(program, pname, value);
+}
+
+String GraphicsContext3D::getProgramInfoLog(Platform3DObject program)
+{
+ ASSERT(program);
+
+ makeContextCurrent();
+ GLint length = 0;
+ ::glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
+ if (!length)
+ return String();
+
+ GLsizei size = 0;
+ OwnArrayPtr<GLchar> info = adoptArrayPtr(new GLchar[length]);
+ ::glGetProgramInfoLog(program, length, &size, info.get());
+
+ return String(info.get());
+}
+
+void GraphicsContext3D::getRenderbufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
+{
+ makeContextCurrent();
+ ::glGetRenderbufferParameterivEXT(target, pname, value);
+}
+
+void GraphicsContext3D::getShaderiv(Platform3DObject shader, GC3Denum pname, GC3Dint* value)
+{
+ ASSERT(shader);
+
+ makeContextCurrent();
+
+ HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
+
+ switch (pname) {
+ case DELETE_STATUS:
+ case SHADER_TYPE:
+ ::glGetShaderiv(shader, pname, value);
+ break;
+ case COMPILE_STATUS:
+ if (result == m_shaderSourceMap.end()) {
+ *value = static_cast<int>(false);
+ return;
+ }
+ *value = static_cast<int>(result->second.isValid);
+ break;
+ case INFO_LOG_LENGTH:
+ if (result == m_shaderSourceMap.end()) {
+ *value = 0;
+ return;
+ }
+ *value = getShaderInfoLog(shader).length();
+ break;
+ case SHADER_SOURCE_LENGTH:
+ *value = getShaderSource(shader).length();
+ break;
+ default:
+ synthesizeGLError(INVALID_ENUM);
+ }
+}
+
+String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader)
+{
+ ASSERT(shader);
+
+ makeContextCurrent();
+
+ HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
+ if (result == m_shaderSourceMap.end())
+ return String();
+
+ ShaderSourceEntry entry = result->second;
+ if (!entry.isValid)
+ return entry.log;
+
+ GLint length = 0;
+ ::glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
+ if (!length)
+ return String();
+
+ GLsizei size = 0;
+ OwnArrayPtr<GLchar> info = adoptArrayPtr(new GLchar[length]);
+ ::glGetShaderInfoLog(shader, length, &size, info.get());
+
+ return String(info.get());
+}
+
+String GraphicsContext3D::getShaderSource(Platform3DObject shader)
+{
+ ASSERT(shader);
+
+ makeContextCurrent();
+
+ HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
+ if (result == m_shaderSourceMap.end())
+ return String();
+
+ return result->second.source;
+}
+
+
+void GraphicsContext3D::getTexParameterfv(GC3Denum target, GC3Denum pname, GC3Dfloat* value)
+{
+ makeContextCurrent();
+ ::glGetTexParameterfv(target, pname, value);
+}
+
+void GraphicsContext3D::getTexParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
+{
+ makeContextCurrent();
+ ::glGetTexParameteriv(target, pname, value);
+}
+
+void GraphicsContext3D::getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value)
+{
+ makeContextCurrent();
+ ::glGetUniformfv(program, location, value);
+}
+
+void GraphicsContext3D::getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value)
+{
+ makeContextCurrent();
+ ::glGetUniformiv(program, location, value);
+}
+
+GC3Dint GraphicsContext3D::getUniformLocation(Platform3DObject program, const String& name)
+{
+ ASSERT(program);
+
+ makeContextCurrent();
+ return ::glGetUniformLocation(program, name.utf8().data());
+}
+
+void GraphicsContext3D::getVertexAttribfv(GC3Duint index, GC3Denum pname, GC3Dfloat* value)
+{
+ makeContextCurrent();
+ ::glGetVertexAttribfv(index, pname, value);
+}
+
+void GraphicsContext3D::getVertexAttribiv(GC3Duint index, GC3Denum pname, GC3Dint* value)
+{
+ makeContextCurrent();
+ ::glGetVertexAttribiv(index, pname, value);
+}
+
+GC3Dsizeiptr GraphicsContext3D::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
+{
+ makeContextCurrent();
+
+ GLvoid* pointer = 0;
+ ::glGetVertexAttribPointerv(index, pname, &pointer);
+ return static_cast<GC3Dsizeiptr>(reinterpret_cast<intptr_t>(pointer));
+}
+
+void GraphicsContext3D::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoff, GC3Dint yoff, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels)
+{
+ makeContextCurrent();
+
+ // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size
+ ::glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels);
+}
+
+void GraphicsContext3D::compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Dsizei imageSize, const void* data)
+{
+ makeContextCurrent();
+ ::glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
+}
+
+void GraphicsContext3D::compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Dsizei imageSize, const void* data)
+{
+ makeContextCurrent();
+ ::glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
+}
+
+Platform3DObject GraphicsContext3D::createBuffer()
+{
+ makeContextCurrent();
+ GLuint o = 0;
+ glGenBuffers(1, &o);
+ return o;
+}
+
+Platform3DObject GraphicsContext3D::createFramebuffer()
+{
+ makeContextCurrent();
+ GLuint o = 0;
+ glGenFramebuffersEXT(1, &o);
+ return o;
+}
+
+Platform3DObject GraphicsContext3D::createProgram()
+{
+ makeContextCurrent();
+ return glCreateProgram();
+}
+
+Platform3DObject GraphicsContext3D::createRenderbuffer()
+{
+ makeContextCurrent();
+ GLuint o = 0;
+ glGenRenderbuffersEXT(1, &o);
+ return o;
+}
+
+Platform3DObject GraphicsContext3D::createShader(GC3Denum type)
+{
+ makeContextCurrent();
+ return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER);
+}
+
+Platform3DObject GraphicsContext3D::createTexture()
+{
+ makeContextCurrent();
+ GLuint o = 0;
+ glGenTextures(1, &o);
+ return o;
+}
+
+void GraphicsContext3D::deleteBuffer(Platform3DObject buffer)
+{
+ makeContextCurrent();
+ glDeleteBuffers(1, &buffer);
+}
+
+void GraphicsContext3D::deleteFramebuffer(Platform3DObject framebuffer)
+{
+ makeContextCurrent();
+ glDeleteFramebuffersEXT(1, &framebuffer);
+}
+
+void GraphicsContext3D::deleteProgram(Platform3DObject program)
+{
+ makeContextCurrent();
+ glDeleteProgram(program);
+}
+
+void GraphicsContext3D::deleteRenderbuffer(Platform3DObject renderbuffer)
+{
+ makeContextCurrent();
+ glDeleteRenderbuffersEXT(1, &renderbuffer);
+}
+
+void GraphicsContext3D::deleteShader(Platform3DObject shader)
+{
+ makeContextCurrent();
+ glDeleteShader(shader);
+}
+
+void GraphicsContext3D::deleteTexture(Platform3DObject texture)
+{
+ makeContextCurrent();
+ glDeleteTextures(1, &texture);
+}
+
+void GraphicsContext3D::synthesizeGLError(GC3Denum error)
+{
+ m_syntheticErrors.add(error);
+}
+
+void GraphicsContext3D::markContextChanged()
+{
+ m_layerComposited = false;
+}
+
+void GraphicsContext3D::markLayerComposited()
+{
+ m_layerComposited = true;
+}
+
+bool GraphicsContext3D::layerComposited() const
+{
+ return m_layerComposited;
+}
+
+Extensions3D* GraphicsContext3D::getExtensions()
+{
+ if (!m_extensions)
+ m_extensions = adoptPtr(new Extensions3DOpenGL(this));
+ return m_extensions.get();
+}
+
+}
+
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp
new file mode 100644
index 000000000..90ff5a0a3
--- /dev/null
+++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 ChangSeok Oh <shivamidow@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 COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(WEBGL)
+
+#include "GraphicsContext3D.h"
+
+#include "NotImplemented.h"
+
+#if PLATFORM(GTK)
+#include "OpenGLShims.h"
+#endif
+
+namespace WebCore {
+
+void GraphicsContext3D::readRenderingResults(unsigned char *pixels, int pixelsSize)
+{
+ notImplemented();
+}
+
+void GraphicsContext3D::reshape(int width, int height)
+{
+ notImplemented();
+}
+
+void GraphicsContext3D::prepareTexture()
+{
+ notImplemented();
+}
+
+void GraphicsContext3D::bindFramebuffer(GC3Denum target, Platform3DObject buffer)
+{
+ notImplemented();
+}
+
+void GraphicsContext3D::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
+{
+ notImplemented();
+}
+
+void GraphicsContext3D::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
+{
+ notImplemented();
+}
+
+bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info)
+{
+ notImplemented();
+}
+
+
+void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data)
+{
+ notImplemented();
+}
+
+void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
+{
+ notImplemented();
+}
+
+void GraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value)
+{
+ notImplemented();
+}
+
+bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels)
+{
+ notImplemented();
+ return false;
+}
+
+}
+
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp
index 0ff7022e3..ddff6051c 100644
--- a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp
+++ b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp
@@ -238,8 +238,10 @@ struct TextureMapperGLData {
ProgramInfo programs[ProgramCount];
int stencilIndex;
+ Vector<IntRect> clipStack;
- SharedGLData(GLContext glContext) : stencilIndex(1)
+ SharedGLData(GLContext glContext)
+ : stencilIndex(1)
{
glContextDataMap().add(glContext, this);
initializeShaders();
@@ -321,12 +323,15 @@ struct TextureMapperGLData {
TextureMapperGLData()
: currentProgram(SharedGLData::NoProgram)
+ , previousProgram(0)
+ , previousScissorState(0)
, m_sharedGLData(TextureMapperGLData::SharedGLData::currentSharedGLData())
{ }
TransformationMatrix projectionMatrix;
int currentProgram;
- int previousProgram;
+ GLint previousProgram;
+ GLint previousScissorState;
RefPtr<SharedGLData> m_sharedGLData;
};
@@ -347,6 +352,7 @@ public:
void setTextureMapper(TextureMapperGL* texmap) { m_textureMapper = texmap; }
void updateContents(PixelFormat, const IntRect&, void*);
+ void updateRawContents(const IntRect&, const void*);
void pack()
{
// This is currently a stub.
@@ -519,28 +525,40 @@ void TextureMapperGLData::SharedGLData::initializeShaders()
void TextureMapperGL::beginPainting()
{
-#if PLATFORM(QT)
+ // Make sure that no GL error code stays from previous operations.
+ glGetError();
+
if (!initializeOpenGLShims())
return;
- glGetIntegerv(GL_CURRENT_PROGRAM, &m_data->previousProgram);
+ glGetIntegerv(GL_CURRENT_PROGRAM, &data().previousProgram);
+ data().previousScissorState = glIsEnabled(GL_SCISSOR_TEST);
+
+ glEnable(GL_SCISSOR_TEST);
+#if PLATFORM(QT)
if (m_context) {
QPainter* painter = m_context->platformContext();
painter->save();
painter->beginNativePainting();
}
+#endif
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
bindSurface(0);
-#endif
}
void TextureMapperGL::endPainting()
{
-#if PLATFORM(QT)
glClearStencil(1);
glClear(GL_STENCIL_BUFFER_BIT);
- glUseProgram(m_data->previousProgram);
+ glUseProgram(data().previousProgram);
+
+ if (data().previousScissorState)
+ glEnable(GL_SCISSOR_TEST);
+ else
+ glDisable(GL_SCISSOR_TEST);
+
+#if PLATFORM(QT)
if (!m_context)
return;
QPainter* painter = m_context->platformContext();
@@ -619,6 +637,7 @@ void TextureMapperGL::drawTexture(uint32_t texture, bool opaque, const FloatSize
}
GL_CMD(glDisable(GL_DEPTH_TEST))
+
GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4))
GL_CMD(glDisableVertexAttribArray(programInfo.vertexAttrib))
}
@@ -737,6 +756,13 @@ void BitmapTextureGL::updateContents(PixelFormat pixelFormat, const IntRect& rec
GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), glFormat, GL_UNSIGNED_BYTE, bits))
}
+void BitmapTextureGL::updateRawContents(const IntRect& rect, const void* bits)
+{
+ GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id))
+ GLuint glFormat = isOpaque() ? GL_RGB : GL_RGBA;
+ GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), glFormat, GL_UNSIGNED_BYTE, bits))
+}
+
void BitmapTextureGL::setContentsToImage(Image* image)
{
ImageUID uid = image ? uidForImage(image) : 0;
@@ -807,7 +833,6 @@ void BitmapTextureGL::bind()
glStencilFunc(stencilIndex > 1 ? GL_GEQUAL : GL_ALWAYS, stencilIndex - 1, stencilIndex - 1);
GL_CMD(glViewport(0, 0, size().width(), size().height()))
m_textureMapper->data().projectionMatrix = createProjectionMatrix(size(), false);
- glDisable(GL_SCISSOR_TEST);
}
void BitmapTextureGL::destroy()
@@ -852,14 +877,58 @@ void TextureMapperGL::bindSurface(BitmapTexture *surfacePointer)
GL_CMD(glStencilFunc(data().sharedGLData().stencilIndex > 1 ? GL_EQUAL : GL_ALWAYS, data().sharedGLData().stencilIndex - 1, data().sharedGLData().stencilIndex - 1))
GL_CMD(glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP))
GL_CMD(glViewport(0, 0, viewportSize().width(), viewportSize().height()))
+ data().sharedGLData().clipStack.append(IntRect(IntPoint::zero(), viewportSize()));
return;
}
surface->bind();
}
+static void scissorClip(const IntRect& rect)
+{
+ GLint viewport[4];
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ glScissor(rect.x(), viewport[3] - rect.maxY(), rect.width(), rect.height());
+}
+
+bool TextureMapperGL::beginScissorClip(const TransformationMatrix& modelViewMatrix, const FloatRect& targetRect)
+{
+ FloatQuad quad = modelViewMatrix.projectQuad(targetRect);
+ IntRect rect = quad.enclosingBoundingBox();
+
+ // Only use scissors on rectilinear clips.
+ if (!quad.isRectilinear() || rect.isEmpty()) {
+ data().sharedGLData().clipStack.append(IntRect());
+ return false;
+ }
+
+ // Intersect with previous clip.
+ if (!data().sharedGLData().clipStack.isEmpty())
+ rect.intersect(data().sharedGLData().clipStack.last());
+
+ scissorClip(rect);
+ data().sharedGLData().clipStack.append(rect);
+
+ return true;
+}
+
+bool TextureMapperGL::endScissorClip()
+{
+ data().sharedGLData().clipStack.removeLast();
+ ASSERT(!data().sharedGLData().clipStack.isEmpty());
+
+ IntRect rect = data().sharedGLData().clipStack.last();
+ if (rect.isEmpty())
+ return false;
+
+ scissorClip(rect);
+ return true;
+}
+
void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, const FloatRect& targetRect)
{
+ if (beginScissorClip(modelViewMatrix, targetRect))
+ return;
TextureMapperGLData::SharedGLData::ShaderProgramIndex program = TextureMapperGLData::SharedGLData::ClipProgram;
const TextureMapperGLData::SharedGLData::ProgramInfo& programInfo = data().sharedGLData().programs[program];
GL_CMD(glUseProgram(programInfo.id))
@@ -897,8 +966,16 @@ void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, con
void TextureMapperGL::endClip()
{
+ if (endScissorClip())
+ return;
+
data().sharedGLData().stencilIndex >>= 1;
- glStencilFunc(data().sharedGLData().stencilIndex > 1 ? GL_EQUAL : GL_ALWAYS, data().sharedGLData().stencilIndex - 1, data().sharedGLData().stencilIndex - 1);
+ glStencilFunc(data().sharedGLData().stencilIndex > 1 ? GL_EQUAL : GL_ALWAYS, data().sharedGLData().stencilIndex - 1, data().sharedGLData().stencilIndex - 1);
+
+ // After we've cleared the last non-rectalinear clip, we disable the stencil test.
+ if (data().sharedGLData().stencilIndex == 1)
+ GL_CMD(glDisable(GL_STENCIL_TEST))
+
}
PassRefPtr<BitmapTexture> TextureMapperGL::createTexture()
diff --git a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.h b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.h
index dd2e1a7c9..1b411857c 100644
--- a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.h
+++ b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.h
@@ -55,6 +55,8 @@ public:
virtual bool isOpenGLBacked() const { return true; }
private:
+ bool beginScissorClip(const TransformationMatrix&, const FloatRect&);
+ bool endScissorClip();
inline TextureMapperGLData& data() { return *m_data; }
TextureMapperGLData* m_data;
GraphicsContext* m_context;
diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
index 9173a5dcc..495bcadd3 100644
--- a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
@@ -1639,6 +1639,10 @@ void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>)
{
}
+void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<ErrorMessageCallback>)
+{
+}
+
}
#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp
index 919cba368..e36ff85b1 100644
--- a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp
@@ -94,7 +94,7 @@ QImage ImageBufferData::toQImage() const
return image;
}
-ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode, DeferralMode, bool& success)
: m_data(size)
, m_size(size)
{
diff --git a/Source/WebCore/platform/graphics/qt/TextureMapperQt.cpp b/Source/WebCore/platform/graphics/qt/TextureMapperQt.cpp
index f41a4212d..44641ce63 100644
--- a/Source/WebCore/platform/graphics/qt/TextureMapperQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/TextureMapperQt.cpp
@@ -76,7 +76,6 @@ void BitmapTextureQt::updateContents(PixelFormat pixelFormat, const IntRect& rec
m_painter.end();
}
-
bool BitmapTextureQt::save(const String& path)
{
return m_pixmap.save(path, "PNG");
@@ -142,7 +141,7 @@ TextureMapperQt::TextureMapperQt()
void TextureMapperQt::setGraphicsContext(GraphicsContext* context)
{
m_context = context;
- m_painter = context->platformContext();
+ m_painter = context ? context->platformContext() : 0;
initialize(m_painter);
}
diff --git a/Source/WebCore/platform/graphics/qt/TextureMapperQt.h b/Source/WebCore/platform/graphics/qt/TextureMapperQt.h
index de571974f..08fee03f1 100644
--- a/Source/WebCore/platform/graphics/qt/TextureMapperQt.h
+++ b/Source/WebCore/platform/graphics/qt/TextureMapperQt.h
@@ -70,7 +70,8 @@ public:
static void initialize(QPainter* painter)
{
- painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, false);
+ if (painter)
+ painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, false);
}
static PassOwnPtr<TextureMapper> create() { return adoptPtr(new TextureMapperQt); }
diff --git a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
index db343615f..355a6b5ef 100644
--- a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
@@ -339,6 +339,7 @@ void GraphicsContext::clearRect(const FloatRect& rect)
platformContext()->setupPaintForFilling(&paint);
paint.setXfermodeMode(SkXfermode::kClear_Mode);
platformContext()->canvas()->drawRect(r, paint);
+ platformContext()->didDrawRect(r, paint);
}
void GraphicsContext::clip(const FloatRect& rect)
@@ -473,11 +474,13 @@ void GraphicsContext::drawConvexPolygon(size_t numPoints,
platformContext()->setupPaintForFilling(&paint);
paint.setAntiAlias(shouldAntialias);
platformContext()->canvas()->drawPath(path, paint);
+ platformContext()->didDrawPath(path, paint);
if (strokeStyle() != NoStroke) {
paint.reset();
platformContext()->setupPaintForStroking(&paint, 0, 0);
platformContext()->canvas()->drawPath(path, paint);
+ platformContext()->didDrawPath(path, paint);
}
}
@@ -513,11 +516,13 @@ void GraphicsContext::drawEllipse(const IntRect& elipseRect)
SkPaint paint;
platformContext()->setupPaintForFilling(&paint);
platformContext()->canvas()->drawOval(rect, paint);
+ platformContext()->didDrawBounded(rect, paint);
if (strokeStyle() != NoStroke) {
paint.reset();
platformContext()->setupPaintForStroking(&paint, &rect, 0);
platformContext()->canvas()->drawOval(rect, paint);
+ platformContext()->didDrawBounded(rect, paint);
}
}
@@ -526,7 +531,7 @@ void GraphicsContext::drawFocusRing(const Path& path, int width, int offset, con
// FIXME: implement
}
-static inline void drawOuterPath(SkCanvas* canvas, const SkPath& path, SkPaint& paint, int width)
+static inline void drawOuterPath(PlatformContextSkia* context, const SkPath& path, SkPaint& paint, int width)
{
#if PLATFORM(CHROMIUM) && OS(DARWIN)
paint.setAlpha(64);
@@ -536,15 +541,17 @@ static inline void drawOuterPath(SkCanvas* canvas, const SkPath& path, SkPaint&
paint.setStrokeWidth(1);
paint.setPathEffect(new SkCornerPathEffect(1))->unref();
#endif
- canvas->drawPath(path, paint);
+ context->canvas()->drawPath(path, paint);
+ context->didDrawPath(path, paint);
}
-static inline void drawInnerPath(SkCanvas* canvas, const SkPath& path, SkPaint& paint, int width)
+static inline void drawInnerPath(PlatformContextSkia* context, const SkPath& path, SkPaint& paint, int width)
{
#if PLATFORM(CHROMIUM) && OS(DARWIN)
paint.setAlpha(128);
paint.setStrokeWidth(width * 0.5f);
- canvas->drawPath(path, paint);
+ context->canvas()->drawPath(path, paint);
+ context->didDrawPath(path, paint);
#endif
}
@@ -581,9 +588,8 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int
paint.setColor(color.rgb());
focusRingRegion.getBoundaryPath(&path);
- SkCanvas* canvas = platformContext()->canvas();
- drawOuterPath(canvas, path, paint, width);
- drawInnerPath(canvas, path, paint, width);
+ drawOuterPath(platformContext(), path, paint, width);
+ drawInnerPath(platformContext(), path, paint, width);
}
// This is only used to draw borders.
@@ -631,12 +637,15 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
fillPaint.setColor(paint.getColor());
platformContext()->canvas()->drawRect(r1, fillPaint);
platformContext()->canvas()->drawRect(r2, fillPaint);
+ platformContext()->didDrawRect(r1, fillPaint);
+ platformContext()->didDrawRect(r2, fillPaint);
}
adjustLineToPixelBoundaries(p1, p2, width, penStyle);
SkPoint pts[2] = { (SkPoint)p1, (SkPoint)p2 };
platformContext()->canvas()->drawPoints(SkCanvas::kLines_PointMode, 2, pts, paint);
+ platformContext()->didDrawPoints(SkCanvas::kLines_PointMode, 2, pts, paint);
}
void GraphicsContext::drawLineForTextChecking(const FloatPoint& pt, float width, TextCheckingLineStyle style)
@@ -647,17 +656,40 @@ void GraphicsContext::drawLineForTextChecking(const FloatPoint& pt, float width,
// Create the pattern we'll use to draw the underline.
static SkBitmap* misspellBitmap = 0;
if (!misspellBitmap) {
+#if PLATFORM(CHROMIUM) && OS(DARWIN)
+ // Match the artwork used by the Mac.
+ const int rowPixels = 4;
+ const int colPixels = 3;
+#else
// We use a 2-pixel-high misspelling indicator because that seems to be
// what WebKit is designed for, and how much room there is in a typical
// page for it.
const int rowPixels = 32; // Must be multiple of 4 for pattern below.
const int colPixels = 2;
+#endif
misspellBitmap = new SkBitmap;
misspellBitmap->setConfig(SkBitmap::kARGB_8888_Config,
rowPixels, colPixels);
misspellBitmap->allocPixels();
misspellBitmap->eraseARGB(0, 0, 0, 0);
+#if PLATFORM(CHROMIUM) && OS(DARWIN)
+ const uint32_t colors[] = { 0x2A2A0600, 0x57571000, // left half of 4x3
+ 0xA8A81B00, 0xBFBF1F00,
+ 0x70701200, 0xE0E02400 };
+ const uint32_t transparentColor = 0x00000000;
+
+ // Pattern: a b a a b a
+ // c d c c d c
+ // e f e e f e
+ for (int x = 0; x < colPixels; ++x) {
+ uint32_t* row = misspellBitmap->getAddr32(0, x);
+ row[0] = colors[x * 2];
+ row[1] = colors[x * 2 + 1];
+ row[2] = colors[x * 2];
+ row[3] = transparentColor;
+ }
+#else
const uint32_t lineColor = 0xFFFF0000; // Opaque red.
const uint32_t antiColor = 0x60600000; // Semitransparent red.
@@ -683,11 +715,16 @@ void GraphicsContext::drawLineForTextChecking(const FloatPoint& pt, float width,
break;
}
}
+#endif
}
- // Offset it vertically by 1 so that there's some space under the text.
SkScalar originX = WebCoreFloatToSkScalar(pt.x());
+#if PLATFORM(CHROMIUM) && OS(DARWIN)
+ SkScalar originY = WebCoreFloatToSkScalar(pt.y());
+#else
+ // Offset it vertically by 1 so that there's some space under the text.
SkScalar originY = WebCoreFloatToSkScalar(pt.y()) + 1;
+#endif
// Make a shader for the bitmap with an origin of the box we'll draw. This
// shader is refcounted and will have an initial refcount of 1.
@@ -712,6 +749,7 @@ void GraphicsContext::drawLineForTextChecking(const FloatPoint& pt, float width,
originX + WebCoreFloatToSkScalar(width),
originY + SkIntToScalar(misspellBitmap->height()));
platformContext()->canvas()->drawRect(rect, paint);
+ platformContext()->didDrawRect(rect, paint);
}
void GraphicsContext::drawLineForText(const FloatPoint& pt,
@@ -736,6 +774,7 @@ void GraphicsContext::drawLineForText(const FloatPoint& pt,
// Text lines are drawn using the stroke color.
paint.setColor(platformContext()->effectiveStrokeColor());
platformContext()->canvas()->drawRect(r, paint);
+ platformContext()->didDrawRect(r, paint);
}
// Draws a filled rectangle with a stroked border.
@@ -770,6 +809,7 @@ void GraphicsContext::fillPath(const Path& pathToFill)
platformContext()->setupPaintForFilling(&paint);
platformContext()->canvas()->drawPath(path, paint);
+ platformContext()->didDrawPath(path, paint);
}
void GraphicsContext::fillRect(const FloatRect& rect)
@@ -788,6 +828,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
SkPaint paint;
platformContext()->setupPaintForFilling(&paint);
platformContext()->canvas()->drawRect(r, paint);
+ platformContext()->didDrawRect(r, paint);
platformContext()->restore();
}
@@ -816,6 +857,7 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS
platformContext()->setupPaintCommon(&paint);
paint.setColor(color.rgb());
platformContext()->canvas()->drawRect(r, paint);
+ platformContext()->didDrawRect(r, paint);
}
void GraphicsContext::fillRoundedRect(const IntRect& rect,
@@ -855,6 +897,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect,
platformContext()->setupPaintForFilling(&paint);
paint.setColor(color.rgb());
platformContext()->canvas()->drawPath(path, paint);
+ platformContext()->didDrawPath(path, paint);
}
AffineTransform GraphicsContext::getCTM() const
@@ -1139,6 +1182,7 @@ void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan)
if (!isPathSkiaSafe(getCTM(), path))
return;
platformContext()->canvas()->drawPath(path, paint);
+ platformContext()->didDrawPath(path, paint);
}
void GraphicsContext::strokePath(const Path& pathToStroke)
@@ -1153,6 +1197,7 @@ void GraphicsContext::strokePath(const Path& pathToStroke)
SkPaint paint;
platformContext()->setupPaintForStroking(&paint, 0, 0);
platformContext()->canvas()->drawPath(path, paint);
+ platformContext()->didDrawPath(path, paint);
}
void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
@@ -1173,9 +1218,10 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
bool validW = r.width() > 0;
bool validH = r.height() > 0;
SkCanvas* canvas = platformContext()->canvas();
- if (validW && validH)
+ if (validW && validH) {
canvas->drawRect(r, paint);
- else if (validW || validH) {
+ platformContext()->didDrawRect(r, paint);
+ } else if (validW || validH) {
// we are expected to respect the lineJoin, so we can't just call
// drawLine -- we have to create a path that doubles back on itself.
SkPath path;
@@ -1183,6 +1229,7 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
path.lineTo(r.fRight, r.fBottom);
path.close();
canvas->drawPath(path, paint);
+ platformContext()->didDrawPath(path, paint);
}
}
diff --git a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
index f96c5690d..eaa1d77b4 100644
--- a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
@@ -46,6 +46,7 @@
#include "PlatformContextSkia.h"
#include "SharedGraphicsContext3D.h"
#include "SkColorPriv.h"
+#include "SkDeferredCanvas.h"
#include "SkGpuDevice.h"
#include "SkiaUtils.h"
#include "WEBPImageEncoder.h"
@@ -65,7 +66,29 @@ ImageBufferData::ImageBufferData(const IntSize& size)
{
}
-static SkCanvas* createAcceleratedCanvas(const IntSize& size, ImageBufferData* data)
+class AcceleratedDeviceContext : public SkDeferredCanvas::DeviceContext {
+public:
+ AcceleratedDeviceContext(GraphicsContext3D* context3D)
+ {
+ ASSERT(context3D);
+ m_context3D = context3D;
+ }
+
+ virtual void prepareForDraw()
+ {
+ m_context3D->makeContextCurrent();
+ }
+
+ virtual void flush()
+ {
+ m_context3D->flush();
+ }
+
+private:
+ GraphicsContext3D* m_context3D;
+};
+
+static SkCanvas* createAcceleratedCanvas(const IntSize& size, ImageBufferData* data, DeferralMode deferralMode)
{
GraphicsContext3D* context3D = SharedGraphicsContext3D::get();
if (!context3D)
@@ -83,12 +106,18 @@ static SkCanvas* createAcceleratedCanvas(const IntSize& size, ImageBufferData* d
SkAutoTUnref<GrTexture> texture(gr->createUncachedTexture(desc, 0, 0));
if (!texture.get())
return 0;
- SkCanvas* canvas = new SkCanvas();
- canvas->setDevice(new SkGpuDevice(gr, texture.get()))->unref();
+ SkCanvas* canvas;
+ SkAutoTUnref<SkDevice> device(new SkGpuDevice(gr, texture.get()));
+ if (deferralMode == Deferred) {
+ SkAutoTUnref<AcceleratedDeviceContext> deviceContext(new AcceleratedDeviceContext(context3D));
+ canvas = new SkDeferredCanvas(device.get(), deviceContext.get());
+ } else
+ canvas = new SkCanvas(device.get());
data->m_platformContext.setGraphicsContext3D(context3D);
#if USE(ACCELERATED_COMPOSITING)
data->m_platformLayer = Canvas2DLayerChromium::create(context3D, size);
data->m_platformLayer->setTextureId(texture.get()->getTextureHandle());
+ data->m_platformLayer->setCanvas(canvas);
#endif
return canvas;
}
@@ -100,14 +129,14 @@ static SkCanvas* createNonPlatformCanvas(const IntSize& size)
return canvas;
}
-ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode renderingMode, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode renderingMode, DeferralMode deferralMode, bool& success)
: m_data(size)
, m_size(size)
{
OwnPtr<SkCanvas> canvas;
if (renderingMode == Accelerated)
- canvas = adoptPtr(createAcceleratedCanvas(size, &m_data));
+ canvas = adoptPtr(createAcceleratedCanvas(size, &m_data, deferralMode));
else if (renderingMode == UnacceleratedNonPlatformBuffer)
canvas = adoptPtr(createNonPlatformCanvas(size));
@@ -226,65 +255,18 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, SkCanvas* canvas,
|| rect.maxY() > size.height())
memset(data, 0, result->length());
- int originX = rect.x();
- int destX = 0;
- if (originX < 0) {
- destX = -originX;
- originX = 0;
- }
- int endX = rect.maxX();
- if (endX > size.width())
- endX = size.width();
- int numColumns = endX - originX;
-
- if (numColumns <= 0)
- return result.release();
-
- int originY = rect.y();
- int destY = 0;
- if (originY < 0) {
- destY = -originY;
- originY = 0;
- }
- int endY = rect.maxY();
- if (endY > size.height())
- endY = size.height();
- int numRows = endY - originY;
-
- if (numRows <= 0)
- return result.release();
-
- SkBitmap srcBitmap;
- if (!canvas->readPixels(SkIRect::MakeXYWH(originX, originY, numColumns, numRows), &srcBitmap))
- return result.release();
-
unsigned destBytesPerRow = 4 * rect.width();
- unsigned char* destRow = data + destY * destBytesPerRow + destX * 4;
-
- // Do conversion of byte order and alpha divide (if necessary)
- for (int y = 0; y < numRows; ++y) {
- SkPMColor* srcBitmapRow = srcBitmap.getAddr32(0, y);
- for (int x = 0; x < numColumns; ++x) {
- SkPMColor srcPMColor = srcBitmapRow[x];
- unsigned char* destPixel = &destRow[x * 4];
- if (multiplied == Unmultiplied) {
- unsigned char a = SkGetPackedA32(srcPMColor);
- destPixel[0] = a ? SkGetPackedR32(srcPMColor) * 255 / a : 0;
- destPixel[1] = a ? SkGetPackedG32(srcPMColor) * 255 / a : 0;
- destPixel[2] = a ? SkGetPackedB32(srcPMColor) * 255 / a : 0;
- destPixel[3] = a;
- } else {
- // Input and output are both pre-multiplied, we just need to re-arrange the
- // bytes from the bitmap format to RGBA.
- destPixel[0] = SkGetPackedR32(srcPMColor);
- destPixel[1] = SkGetPackedG32(srcPMColor);
- destPixel[2] = SkGetPackedB32(srcPMColor);
- destPixel[3] = SkGetPackedA32(srcPMColor);
- }
- }
- destRow += destBytesPerRow;
- }
+ SkBitmap destBitmap;
+ destBitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height(), destBytesPerRow);
+ destBitmap.setPixels(data);
+
+ SkCanvas::Config8888 config8888;
+ if (multiplied == Premultiplied)
+ config8888 = SkCanvas::kRGBA_Premul_Config8888;
+ else
+ config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
+ canvas->readPixels(&destBitmap, rect.x(), rect.y(), config8888);
return result.release();
}
diff --git a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp
index e66dbab43..1d5d9911b 100644
--- a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp
@@ -248,6 +248,7 @@ static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImag
// we don't send extra pixels.
canvas->drawBitmapRect(bitmap.bitmap(), &srcRect, destRect, &paint);
}
+ platformContext->didDrawRect(destRect, paint, &bitmap.bitmap());
}
// Transforms the given dimensions with the given matrix. Used to see how big
diff --git a/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.cpp b/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.cpp
new file mode 100644
index 000000000..64a4ee4f3
--- /dev/null
+++ b/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.cpp
@@ -0,0 +1,309 @@
+/*
+ * 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 "OpaqueRegionSkia.h"
+
+#include "PlatformContextSkia.h"
+
+#include "SkShader.h"
+
+namespace WebCore {
+
+OpaqueRegionSkia::OpaqueRegionSkia()
+ : m_opaqueRect(SkRect::MakeEmpty())
+{
+}
+
+OpaqueRegionSkia::~OpaqueRegionSkia()
+{
+}
+
+IntRect OpaqueRegionSkia::asRect() const
+{
+ // Returns the largest enclosed rect.
+ int left = SkScalarCeil(m_opaqueRect.fLeft);
+ int top = SkScalarCeil(m_opaqueRect.fTop);
+ int right = SkScalarFloor(m_opaqueRect.fRight);
+ int bottom = SkScalarFloor(m_opaqueRect.fBottom);
+ return IntRect(left, top, right-left, bottom-top);
+}
+
+// Returns true if the xfermode will force the dst to be opaque, regardless of the current dst.
+static inline bool xfermodeIsOpaque(const SkPaint& paint, bool srcIsOpaque)
+{
+ if (!srcIsOpaque)
+ return false;
+
+ SkXfermode* xfermode = paint.getXfermode();
+ if (!xfermode)
+ return true; // default to kSrcOver_Mode
+ SkXfermode::Mode mode;
+ if (!xfermode->asMode(&mode))
+ return false;
+
+ switch (mode) {
+ case SkXfermode::kSrc_Mode: // source
+ case SkXfermode::kSrcOver_Mode: // source + dest - source*dest
+ case SkXfermode::kDstOver_Mode: // source + dest - source*dest
+ case SkXfermode::kDstATop_Mode: // source
+ case SkXfermode::kPlus_Mode: // source+dest
+ default: // the rest are all source + dest - source*dest
+ return true;
+ case SkXfermode::kClear_Mode: // 0
+ case SkXfermode::kDst_Mode: // dest
+ case SkXfermode::kSrcIn_Mode: // source * dest
+ case SkXfermode::kDstIn_Mode: // dest * source
+ case SkXfermode::kSrcOut_Mode: // source * (1-dest)
+ case SkXfermode::kDstOut_Mode: // dest * (1-source)
+ case SkXfermode::kSrcATop_Mode: // dest
+ case SkXfermode::kXor_Mode: // source + dest - 2*(source*dest)
+ return false;
+ }
+}
+
+// Returns true if the xfermode will keep the dst opaque, assuming the dst is already opaque.
+static inline bool xfermodePreservesOpaque(const SkPaint& paint, bool srcIsOpaque)
+{
+ SkXfermode* xfermode = paint.getXfermode();
+ if (!xfermode)
+ return true; // default to kSrcOver_Mode
+ SkXfermode::Mode mode;
+ if (!xfermode->asMode(&mode))
+ return false;
+
+ switch (mode) {
+ case SkXfermode::kDst_Mode: // dest
+ case SkXfermode::kSrcOver_Mode: // source + dest - source*dest
+ case SkXfermode::kDstOver_Mode: // source + dest - source*dest
+ case SkXfermode::kSrcATop_Mode: // dest
+ case SkXfermode::kPlus_Mode: // source+dest
+ default: // the rest are all source + dest - source*dest
+ return true;
+ case SkXfermode::kClear_Mode: // 0
+ case SkXfermode::kSrcOut_Mode: // source * (1-dest)
+ case SkXfermode::kDstOut_Mode: // dest * (1-source)
+ case SkXfermode::kXor_Mode: // source + dest - 2*(source*dest)
+ return false;
+ case SkXfermode::kSrc_Mode: // source
+ case SkXfermode::kSrcIn_Mode: // source * dest
+ case SkXfermode::kDstIn_Mode: // dest * source
+ case SkXfermode::kDstATop_Mode: // source
+ return srcIsOpaque;
+ }
+}
+
+// Returns true if all pixels painted will be opaque.
+static inline bool paintIsOpaque(const SkPaint& paint, const SkBitmap* bitmap = 0, bool checkFillOnly = false)
+{
+ if (paint.getAlpha() < 0xFF)
+ return false;
+ if (!checkFillOnly && paint.getStyle() != SkPaint::kFill_Style && paint.isAntiAlias())
+ return false;
+ SkShader* shader = paint.getShader();
+ if (shader && !shader->isOpaque())
+ return false;
+ if (bitmap && !bitmap->isOpaque())
+ return false;
+ return true;
+}
+
+void OpaqueRegionSkia::didDrawRect(const PlatformContextSkia* context, const SkRect& fillRect, const SkPaint& paint, const SkBitmap* bitmap)
+{
+ // 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);
+ else {
+ SkRect strokeRect;
+ strokeRect = paint.computeFastBounds(fillRect, &strokeRect);
+ didDraw(context, strokeRect, paint, opaque, fillsBounds);
+ }
+ }
+
+ bool checkFillOnly = true;
+ bool opaque = paintIsOpaque(paint, bitmap, checkFillOnly);
+ bool fillsBounds = paint.getStyle() != SkPaint::kStroke_Style;
+ didDraw(context, fillRect, paint, opaque, fillsBounds);
+}
+
+void OpaqueRegionSkia::didDrawPath(const PlatformContextSkia* context, const SkPath& path, const SkPaint& paint)
+{
+ SkRect rect;
+ if (path.isRect(&rect)) {
+ didDrawRect(context, rect, paint, 0);
+ return;
+ }
+
+ bool opaque = paintIsOpaque(paint);
+ bool fillsBounds = false;
+
+ if (!paint.canComputeFastBounds())
+ didDrawUnbounded(paint, opaque);
+ else {
+ rect = paint.computeFastBounds(path.getBounds(), &rect);
+ didDraw(context, rect, paint, opaque, fillsBounds);
+ }
+}
+
+void OpaqueRegionSkia::didDrawPoints(const PlatformContextSkia* context, SkCanvas::PointMode mode, int numPoints, const SkPoint points[], const SkPaint& paint)
+{
+ if (!numPoints)
+ return;
+
+ SkRect rect;
+ rect.fLeft = points[0].fX;
+ rect.fRight = points[0].fX + 1;
+ rect.fTop = points[0].fY;
+ rect.fBottom = points[0].fY + 1;
+
+ for (int i = 1; i < numPoints; ++i) {
+ rect.fLeft = std::min(rect.fLeft, points[i].fX);
+ rect.fRight = std::max(rect.fRight, points[i].fX + 1);
+ rect.fTop = std::min(rect.fTop, points[i].fY);
+ rect.fBottom = std::max(rect.fBottom, points[i].fY + 1);
+ }
+
+ bool opaque = paintIsOpaque(paint);
+ bool fillsBounds = false;
+
+ if (!paint.canComputeFastBounds())
+ didDrawUnbounded(paint, opaque);
+ else {
+ rect = paint.computeFastBounds(rect, &rect);
+ didDraw(context, rect, paint, opaque, fillsBounds);
+ }
+}
+
+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);
+ else {
+ SkRect rect;
+ rect = paint.computeFastBounds(bounds, &rect);
+ didDraw(context, rect, paint, opaque, fillsBounds);
+ }
+}
+
+void OpaqueRegionSkia::didDraw(const PlatformContextSkia* context, const SkRect& rect, const SkPaint& paint, bool drawsOpaque, bool fillsBounds)
+{
+ if (fillsBounds && xfermodeIsOpaque(paint, drawsOpaque))
+ markRectAsOpaque(context, rect);
+ else if (SkRect::Intersects(rect, m_opaqueRect) && !xfermodePreservesOpaque(paint, drawsOpaque))
+ markRectAsNonOpaque(rect);
+}
+
+void OpaqueRegionSkia::didDrawUnbounded(const SkPaint& paint, bool drawsOpaque)
+{
+ if (!xfermodePreservesOpaque(paint, drawsOpaque)) {
+ // We don't know what was drawn on so just destroy the known opaque area.
+ m_opaqueRect = SkRect::MakeEmpty();
+ }
+}
+
+void OpaqueRegionSkia::markRectAsOpaque(const PlatformContextSkia* context, const SkRect& rect)
+{
+ // We want to keep track of an opaque region but bound its complexity at a constant size.
+ // We keep track of the largest rectangle seen by area. If we can add the new rect to this
+ // rectangle then we do that, as that is the cheapest way to increase the area returned
+ // without increasing the complexity.
+
+ if (rect.isEmpty())
+ return;
+ if (!context->clippedToImage().isOpaque())
+ return;
+ if (m_opaqueRect.contains(rect))
+ return;
+ if (rect.contains(m_opaqueRect)) {
+ m_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;
+ }
+
+ long opaqueArea = (long)m_opaqueRect.width() * (long)m_opaqueRect.height();
+ long area = (long)rect.width() * (long)rect.height();
+ if (area > opaqueArea)
+ m_opaqueRect = rect;
+}
+
+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();
+ 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;
+
+ // 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;
+ if (deltaTop > deltaBottom)
+ horizontal.fBottom = rect.fTop;
+ else
+ horizontal.fTop = rect.fBottom;
+ SkRect vertical = m_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;
+ else
+ m_opaqueRect = vertical;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.h b/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.h
new file mode 100644
index 000000000..93f2c5a1b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.h
@@ -0,0 +1,70 @@
+/*
+ * 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 OpaqueRegionSkia_h
+#define OpaqueRegionSkia_h
+
+#include "IntRect.h"
+
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkPoint.h"
+#include "SkRect.h"
+
+namespace WebCore {
+class PlatformContextSkia;
+
+// This class is an encapsulation of functionality for PlatformContextSkia, and its methods are mirrored
+// there for the outside world. It tracks paints and computes what area will be opaque.
+class OpaqueRegionSkia {
+public:
+ OpaqueRegionSkia();
+ virtual ~OpaqueRegionSkia();
+
+ // The resulting opaque region as a single rect.
+ IntRect asRect() const;
+
+ void didDrawRect(const PlatformContextSkia*, const SkRect&, const SkPaint&, const SkBitmap*);
+ 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&);
+
+private:
+ void didDraw(const PlatformContextSkia*, const SkRect&, const SkPaint&, bool drawsOpaque, bool fillsBounds);
+ void didDrawUnbounded(const SkPaint&, bool drawsOpaque);
+ void markRectAsOpaque(const PlatformContextSkia*, const SkRect&);
+ void markRectAsNonOpaque(const SkRect&);
+
+ SkRect m_opaqueRect;
+};
+
+}
+#endif // OpaqueRegionSkia_h
diff --git a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
index a5e18680d..034c3319e 100644
--- a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
@@ -179,6 +179,7 @@ SkColor PlatformContextSkia::State::applyAlpha(SkColor c) const
// Danger: canvas can be NULL.
PlatformContextSkia::PlatformContextSkia(SkCanvas* canvas)
: m_canvas(canvas)
+ , m_trackOpaqueRegion(false)
, m_printing(false)
, m_deferred(false)
, m_drawingToImageBuffer(false)
@@ -266,6 +267,11 @@ void PlatformContextSkia::clipPathAntiAliased(const SkPath& clipPath)
canvas()->clipPath(clipPath, SkRegion::kIntersect_Op, true);
}
+const SkBitmap& PlatformContextSkia::clippedToImage() const
+{
+ return m_state->m_imageBufferClip;
+}
+
void PlatformContextSkia::restore()
{
if (!m_state->m_imageBufferClip.empty()) {
@@ -287,6 +293,7 @@ void PlatformContextSkia::drawRect(SkRect rect)
if (fillcolorNotTransparent) {
setupPaintForFilling(&paint);
canvas()->drawRect(rect, paint);
+ didDrawRect(rect, paint);
}
if (m_state->m_strokeStyle != NoStroke
@@ -299,12 +306,16 @@ void PlatformContextSkia::drawRect(SkRect rect)
SkRect topBorder = { rect.fLeft, rect.fTop, rect.fRight, rect.fTop + 1 };
canvas()->drawRect(topBorder, paint);
+ didDrawRect(topBorder, paint);
SkRect bottomBorder = { rect.fLeft, rect.fBottom - 1, rect.fRight, rect.fBottom };
canvas()->drawRect(bottomBorder, paint);
+ didDrawRect(bottomBorder, paint);
SkRect leftBorder = { rect.fLeft, rect.fTop + 1, rect.fLeft + 1, rect.fBottom - 1 };
canvas()->drawRect(leftBorder, paint);
+ didDrawRect(leftBorder, paint);
SkRect rightBorder = { rect.fRight - 1, rect.fTop + 1, rect.fRight, rect.fBottom - 1 };
canvas()->drawRect(rightBorder, paint);
+ didDrawRect(rightBorder, paint);
}
}
@@ -539,6 +550,7 @@ void PlatformContextSkia::paintSkPaint(const SkRect& rect,
const SkPaint& paint)
{
m_canvas->drawRect(rect, paint);
+ didDrawRect(rect, paint);
}
const SkBitmap* PlatformContextSkia::bitmap() const
@@ -597,4 +609,28 @@ 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, rect, paint, bitmap);
+}
+
+void PlatformContextSkia::didDrawPath(const SkPath& path, const SkPaint& paint)
+{
+ if (m_trackOpaqueRegion)
+ 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, mode, numPoints, points, paint);
+}
+
+void PlatformContextSkia::didDrawBounded(const SkRect& rect, const SkPaint& paint)
+{
+ if (m_trackOpaqueRegion)
+ m_opaqueRegion.didDrawBounded(this, rect, paint);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h
index 7dcfbe2e3..fe3abb6f5 100644
--- a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h
+++ b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h
@@ -33,6 +33,7 @@
#include "GraphicsContext.h"
#include "Noncopyable.h"
+#include "OpaqueRegionSkia.h"
#include "SkCanvas.h"
#include "SkDashPathEffect.h"
@@ -98,6 +99,8 @@ public:
// NOTE: |imageBuffer| may be deleted before the |restore| is invoked.
void beginLayerClippedToImage(const FloatRect&, const ImageBuffer*);
void clipPathAntiAliased(const SkPath&);
+ // If non-empty, the layer is clipped to the bitmap.
+ const SkBitmap& clippedToImage() const;
// Sets up the common flags on a paint for antialiasing, effects, etc.
// This is implicitly called by setupPaintFill and setupPaintStroke, but
@@ -187,6 +190,18 @@ public:
bool isDeferred() const { return m_deferred; }
void setDeferred(bool deferred) { m_deferred = deferred; }
+ void setTrackOpaqueRegion(bool track) { m_trackOpaqueRegion = track; }
+
+ // This will be an empty region unless tracking is enabled.
+ const OpaqueRegionSkia& opaqueRegion() const { return m_opaqueRegion; }
+
+ // After drawing in the context's canvas, use these functions to notify the context so it can track the opaque region.
+ void didDrawRect(const SkRect&, const SkPaint&, const SkBitmap* = 0);
+ void didDrawPath(const SkPath&, const SkPaint&);
+ void didDrawPoints(SkCanvas::PointMode, int numPoints, const SkPoint[], const SkPaint&);
+ // For drawing operations that do not fill the entire rect.
+ void didDrawBounded(const SkRect&, const SkPaint&);
+
private:
// Used when restoring and the state has an image clip. Only shows the pixels in
// m_canvas that are also in imageBuffer.
@@ -210,6 +225,10 @@ private:
// mStateStack.back().
State* m_state;
+ // Tracks the region painted opaque via the GraphicsContext.
+ OpaqueRegionSkia m_opaqueRegion;
+ bool m_trackOpaqueRegion;
+
// Stores image sizes for a hint to compute image resampling modes.
// Values are used in ImageSkia.cpp
IntSize m_imageResamplingHintSrcSize;
diff --git a/Source/WebCore/platform/graphics/harfbuzz/SimpleFontDataSkia.cpp b/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp
index 782b02fa9..782b02fa9 100644
--- a/Source/WebCore/platform/graphics/harfbuzz/SimpleFontDataSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp
diff --git a/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp b/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp
index 8bed35454..1087cd0cb 100644
--- a/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp
+++ b/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp
@@ -205,12 +205,24 @@ static void setupPaintForFont(SkPaint* paint, PlatformContextSkia* pcs,
textFlags &= getDefaultGDITextFlags();
// do this check after our switch on lfQuality
- if (disableTextLCD(pcs))
+ if (disableTextLCD(pcs)) {
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
+ // original intent was LCD, we want to force AA (rather than BW), so we
+ // add a special bit to tell Skia to do its best to avoid the BW: by
+ // drawing LCD offscreen and downsampling that to AA.
+ textFlags |= SkPaint::kGenA8FromLCD_Flag;
+ }
+
+ static const uint32_t textFlagsMask = SkPaint::kAntiAlias_Flag |
+ SkPaint::kLCDRenderText_Flag |
+ SkPaint::kGenA8FromLCD_Flag;
// now copy in just the text flags
+ SkASSERT(!(textFlags & ~textFlagsMask));
uint32_t flags = paint->getFlags();
- flags &= ~(SkPaint::kAntiAlias_Flag | SkPaint::kLCDRenderText_Flag);
+ flags &= ~textFlagsMask;
flags |= textFlags;
paint->setFlags(flags);
}
diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
index 7ef9818ed..b521d1a21 100644
--- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
+++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
@@ -365,59 +365,26 @@ bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList
if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyWebkitTransform && valueList.property() != AnimatedPropertyOpacity))
return false;
- for (size_t i = 0; i < m_animations.size(); ++i) {
- // The same animation name can be used for two animations with different properties.
- if (m_animations[i]->name != keyframesName || m_animations[i]->keyframes.property() != valueList.property())
- continue;
-
- // We already have a copy of this animation, that means that we're resuming it rather than adding it.
- RefPtr<TextureMapperAnimation>& animation = m_animations[i];
- animation->animation = Animation::create(anim);
- animation->paused = false;
- animation->startTime = WTF::currentTime() - timeOffset;
- notifyChange(TextureMapperNode::AnimationChange);
- m_animationStartedTimer.startOneShot(0);
- return true;
- }
+ bool listsMatch = false;
+ bool hasBigRotation;
- RefPtr<TextureMapperAnimation> animation = TextureMapperAnimation::create(valueList);
- animation->boxSize = boxSize;
- animation->name = keyframesName;
- animation->animation = Animation::create(anim);
- animation->paused = false;
- animation->startTime = WTF::currentTime() - timeOffset;
-
- if (valueList.property() == AnimatedPropertyWebkitTransform) {
- bool hasBigRotation; // Not used, but required as a pointer parameter for the function.
- fetchTransformOperationList(valueList, animation->functionList, animation->listsMatch, hasBigRotation);
- }
+ if (valueList.property() == AnimatedPropertyWebkitTransform)
+ listsMatch = validateTransformOperations(valueList, hasBigRotation) >= 0;
- m_animations.append(animation);
+ m_animations.add(keyframesName, TextureMapperAnimation(valueList, boxSize, anim, timeOffset, listsMatch));
notifyChange(TextureMapperNode::AnimationChange);
m_animationStartedTimer.startOneShot(0);
-
return true;
}
void GraphicsLayerTextureMapper::pauseAnimation(const String& animationName, double timeOffset)
{
- for (size_t i = 0; i < m_animations.size(); ++i) {
- if (m_animations[i]->name != animationName)
- continue;
- m_animations[i]->paused = true;
- notifyChange(TextureMapperNode::AnimationChange);
- }
+ m_animations.pause(animationName, timeOffset);
}
void GraphicsLayerTextureMapper::removeAnimation(const String& animationName)
{
- for (int i = m_animations.size() - 1; i >= 0; --i) {
- // The same animation name can be used for two animations with different properties. We should remove both.
- if (m_animations[i]->name != animationName)
- continue;
- m_animations.remove(i);
- notifyChange(TextureMapperNode::AnimationChange);
- }
+ m_animations.remove(animationName);
}
void GraphicsLayerTextureMapper::animationStartedTimerFired(Timer<GraphicsLayerTextureMapper>*)
diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
index ebb9b536d..172fdda24 100644
--- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
+++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
@@ -95,7 +95,7 @@ private:
bool m_syncQueued;
int m_changeMask;
TextureMapperNode::ContentData m_pendingContent;
- Vector<RefPtr<TextureMapperAnimation> > m_animations;
+ TextureMapperAnimations m_animations;
void animationStartedTimerFired(Timer<GraphicsLayerTextureMapper>*);
Timer<GraphicsLayerTextureMapper> m_animationStartedTimer;
};
diff --git a/Source/WebCore/platform/graphics/texmap/LayerTransform.cpp b/Source/WebCore/platform/graphics/texmap/LayerTransform.cpp
new file mode 100644
index 000000000..1c3c02e57
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/LayerTransform.cpp
@@ -0,0 +1,116 @@
+/*
+ Copyright (C) 2011 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 "LayerTransform.h"
+
+namespace WebCore {
+
+LayerTransform::LayerTransform()
+: m_flattening(false)
+, m_dirty(false) // false by default since all default values would be combined as the identity matrix
+, m_childrenDirty(false)
+{
+}
+
+void LayerTransform::setPosition(const FloatPoint& position)
+{
+ m_position = position;
+ m_dirty = true;
+}
+
+void LayerTransform::setSize(const FloatSize& size)
+{
+ m_size = size;
+ m_dirty = true;
+}
+
+void LayerTransform::setAnchorPoint(const FloatPoint3D& anchorPoint)
+{
+ m_anchorPoint = anchorPoint;
+ m_dirty = true;
+}
+
+void LayerTransform::setFlattening(bool flattening)
+{
+ m_flattening = flattening;
+ m_dirty = true;
+}
+
+void LayerTransform::setLocalTransform(const TransformationMatrix& transform)
+{
+ m_local = transform;
+ m_dirty = true;
+}
+
+void LayerTransform::setChildrenTransform(const TransformationMatrix& transform)
+{
+ m_children = transform;
+ m_dirty = true;
+}
+
+TransformationMatrix LayerTransform::combined()
+{
+ ASSERT(!m_dirty);
+ return m_combined;
+}
+
+TransformationMatrix LayerTransform::combinedForChildren()
+{
+ ASSERT(!m_dirty);
+ if (m_childrenDirty)
+ combineTransformsForChildren();
+ return m_combinedForChildren;
+}
+
+void LayerTransform::combineTransforms(const TransformationMatrix& parentTransform)
+{
+ float originX = m_anchorPoint.x() * m_size.width();
+ float originY = m_anchorPoint.y() * m_size.height();
+ m_combined =
+ TransformationMatrix(parentTransform)
+ .translate3d(originX + m_position.x(), originY + m_position.y(), m_anchorPoint.z() )
+ .multiply(m_local);
+
+ // The children transform will take it from here, if it gets used.
+ m_combinedForChildren = m_combined;
+ m_combined.translate3d(-originX, -originY, -m_anchorPoint.z());
+
+ m_dirty = false;
+ m_childrenDirty = true;
+}
+
+void LayerTransform::combineTransformsForChildren()
+{
+ ASSERT(!m_dirty);
+ ASSERT(m_childrenDirty);
+
+ float originX = m_anchorPoint.x() * m_size.width();
+ float originY = m_anchorPoint.y() * m_size.height();
+
+ // In case a parent had preserves3D and this layer has not, flatten our children.
+ if (m_flattening)
+ m_combinedForChildren = m_combinedForChildren.to2dTransform();
+ m_combinedForChildren.multiply(m_children);
+ m_combinedForChildren.translate3d(-originX, -originY, -m_anchorPoint.z());
+
+ m_childrenDirty = false;
+}
+
+}
diff --git a/Source/WebCore/platform/graphics/texmap/LayerTransform.h b/Source/WebCore/platform/graphics/texmap/LayerTransform.h
new file mode 100644
index 000000000..b73818501
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/LayerTransform.h
@@ -0,0 +1,62 @@
+/*
+ Copyright (C) 2011 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 LayerTransform_h
+#define LayerTransform_h
+
+#include "FloatPoint.h"
+#include "FloatPoint3D.h"
+#include "FloatSize.h"
+#include "TransformationMatrix.h"
+
+namespace WebCore {
+
+class LayerTransform {
+public:
+ LayerTransform();
+ void setPosition(const FloatPoint&);
+ void setSize(const FloatSize&);
+ void setAnchorPoint(const FloatPoint3D&);
+ void setFlattening(bool);
+ void setLocalTransform(const TransformationMatrix&);
+ void setChildrenTransform(const TransformationMatrix&);
+ TransformationMatrix combined();
+ TransformationMatrix combinedForChildren();
+
+ void combineTransforms(const TransformationMatrix& parentTransform);
+
+private:
+ void combineTransformsForChildren();
+
+ FloatPoint3D m_anchorPoint;
+ FloatPoint m_position;
+ FloatSize m_size;
+ bool m_flattening;
+ bool m_dirty;
+ bool m_childrenDirty;
+
+ TransformationMatrix m_local;
+ TransformationMatrix m_children;
+ TransformationMatrix m_combined;
+ TransformationMatrix m_combinedForChildren;
+};
+
+}
+
+#endif // LayerTransform_h
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp
index 2622d21ca..dd33f0d2a 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp
@@ -26,18 +26,20 @@ namespace WebCore {
PassRefPtr<BitmapTexture> TextureMapper::acquireTextureFromPool(const IntSize& size)
{
- if (m_texturePool.isEmpty()) {
- RefPtr<BitmapTexture> selectedTexture = createTexture();
- selectedTexture->reset(size, false);
- selectedTexture->lock();
- return selectedTexture;
- }
+ RefPtr<BitmapTexture> selectedTexture;
- size_t index = 0;
- RefPtr<BitmapTexture> selectedTexture = m_texturePool[0];
+ for (size_t i = 0; i < m_texturePool.size(); ++i) {
+ RefPtr<BitmapTexture>& texture = m_texturePool[i];
- for (size_t i = 1; i < m_texturePool.size(); ++i) {
- RefPtr<BitmapTexture> texture = m_texturePool[i];
+ // If the surface has only one reference (the one in m_texturePool), we can safely reuse it.
+ if (texture->refCount() > 1)
+ continue;
+
+ // We default to the first available texture.
+ if (!selectedTexture) {
+ selectedTexture = texture;
+ continue;
+ }
IntSize textureSize = texture->size();
IntSize selectedTextureSize = selectedTexture->size();
@@ -58,22 +60,16 @@ PassRefPtr<BitmapTexture> TextureMapper::acquireTextureFromPool(const IntSize& s
continue;
selectedTexture = texture;
- index = i;
}
- m_texturePool.remove(index);
+ if (!selectedTexture) {
+ selectedTexture = createTexture();
+ m_texturePool.append(selectedTexture);
+ }
+
selectedTexture->reset(size, false);
- selectedTexture->lock();
return selectedTexture;
}
-void TextureMapper::releaseTextureToPool(BitmapTexture* texture)
-{
- if (!texture)
- return;
- m_texturePool.append(texture);
- texture->unlock();
-}
-
}
#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.h b/Source/WebCore/platform/graphics/texmap/TextureMapper.h
index d81333daa..d66fe2fb4 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapper.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.h
@@ -71,6 +71,7 @@ public:
// For performance reasons, BitmapTexture might modify the bits directly (swizzle).
// Thus, this method is only recommended for buffer update, such as used by WebKit2.
virtual void updateContents(PixelFormat, const IntRect&, void* bits) = 0;
+ virtual void updateRawContents(const IntRect&, const void* bits) { }
virtual PlatformGraphicsContext* beginPaintMedia()
{
return beginPaint(IntRect(0, 0, size().width(), size().height()));
@@ -126,7 +127,7 @@ public:
virtual void beginPainting() { }
virtual void endPainting() { }
- virtual void releaseTextureToPool(BitmapTexture* surface);
+ // A surface is released implicitly when dereferenced.
virtual PassRefPtr<BitmapTexture> acquireTextureFromPool(const IntSize&);
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp
new file mode 100644
index 000000000..09714d909
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp
@@ -0,0 +1,255 @@
+/*
+ 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 "TextureMapperAnimation.h"
+
+#include "CurrentTime.h"
+#include "UnitBezier.h"
+
+#if USE(TEXTURE_MAPPER)
+namespace WebCore {
+
+static double normalizedAnimationValue(double runningTime, double duration, bool alternate)
+{
+ if (!duration)
+ return 0;
+
+ const int loopCount = runningTime / duration;
+ const double lastFullLoop = duration * double(loopCount);
+ const double remainder = runningTime - lastFullLoop;
+ const double normalized = remainder / duration;
+ return (loopCount % 2 && alternate) ? (1 - normalized) : normalized;
+}
+
+static float applyOpacityAnimation(float fromOpacity, float toOpacity, double progress)
+{
+ // Optimization: special case the edge values (0 and 1).
+ if (progress == 1.0)
+ return toOpacity;
+
+ if (!progress)
+ return fromOpacity;
+
+ return fromOpacity + progress * (toOpacity - fromOpacity);
+}
+
+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)
+{
+ return UnitBezier(p1x, p1y, p2x, p2y).solve(t, solveEpsilon(duration));
+}
+
+static inline double solveStepsFunction(int numSteps, bool stepAtStart, double t)
+{
+ if (stepAtStart)
+ return std::min(1.0, (floor(numSteps * t) + 1) / numSteps);
+ return floor(numSteps * t) / numSteps;
+}
+
+static inline float applyTimingFunction(const TimingFunction* timingFunction, float progress, double duration)
+{
+ if (!timingFunction)
+ return progress;
+
+ if (timingFunction->isCubicBezierTimingFunction()) {
+ const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(timingFunction);
+ return solveCubicBezierFunction(ctf->x1(), ctf->y1(), ctf->x2(), ctf->y2(), progress, duration);
+ }
+
+ if (timingFunction->isStepsTimingFunction()) {
+ const StepsTimingFunction* stf = static_cast<const StepsTimingFunction*>(timingFunction);
+ return solveStepsFunction(stf->numberOfSteps(), stf->stepAtStart(), double(progress));
+ }
+
+ return progress;
+}
+
+static TransformationMatrix applyTransformAnimation(const TransformOperations* from, const TransformOperations* to, double progress, const IntSize& boxSize, bool listsMatch)
+{
+ TransformationMatrix matrix;
+
+ // First frame of an animation.
+ if (!progress) {
+ from->apply(boxSize, matrix);
+ return matrix;
+ }
+
+ // Last frame of an animation.
+ if (progress == 1) {
+ to->apply(boxSize, matrix);
+ return matrix;
+ }
+
+ // If we have incompatible operation lists, we blend the resulting matrices.
+ if (!listsMatch) {
+ TransformationMatrix fromMatrix;
+ to->apply(boxSize, matrix);
+ from->apply(boxSize, fromMatrix);
+ matrix.blend(fromMatrix, progress);
+ return matrix;
+ }
+
+ // Animation to "-webkit-transform: none".
+ if (!to->size()) {
+ TransformOperations blended(*to);
+ for (size_t i = 0; i < blended.operations().size(); ++i)
+ blended.operations()[i]->blend(0, progress, true)->apply(matrix, boxSize);
+ return matrix;
+ }
+
+ // Animation from "-webkit-transform: none".
+ if (!from->size()) {
+ TransformOperations blended(*from);
+ for (size_t i = 0; i < blended.operations().size(); ++i)
+ blended.operations()[i]->blend(0, 1. - progress, true)->apply(matrix, boxSize);
+ return matrix;
+ }
+
+ // Normal animation with a matching operation list.
+ TransformOperations blended(*to);
+ for (size_t i = 0; i < blended.operations().size(); ++i)
+ blended.operations()[i]->blend(from->at(i), progress, !from->at(i))->apply(matrix, boxSize);
+ return matrix;
+}
+
+
+TextureMapperAnimation::TextureMapperAnimation(const KeyframeValueList& keyframes, const IntSize& boxSize, const Animation* animation, double timeOffset, bool listsMatch)
+ : m_keyframes(keyframes)
+ , m_boxSize(boxSize)
+ , m_animation(Animation::create(animation))
+ , m_listsMatch(listsMatch)
+ , m_startTime(WTF::currentTime() - timeOffset)
+ , m_pauseTime(0)
+ , m_state(PlayingState)
+{
+}
+
+void TextureMapperAnimation::applyInternal(TextureMapperAnimationClient* client, const AnimationValue* from, const AnimationValue* to, float progress)
+{
+ switch (m_keyframes.property()) {
+ case AnimatedPropertyOpacity:
+ client->setOpacity(applyOpacityAnimation((static_cast<const FloatAnimationValue*>(from)->value()), (static_cast<const FloatAnimationValue*>(to)->value()), progress));
+ return;
+ case AnimatedPropertyWebkitTransform:
+ client->setTransform(applyTransformAnimation(static_cast<const TransformAnimationValue*>(from)->value(), static_cast<const TransformAnimationValue*>(to)->value(), progress, m_boxSize, m_listsMatch));
+ return;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+
+bool TextureMapperAnimation::isActive() const
+{
+ if (state() != StoppedState)
+ return true;
+
+ return m_animation->fillsForwards();
+}
+
+bool TextureMapperAnimations::hasActiveAnimationsOfType(AnimatedPropertyID type) const
+{
+ HashMap<String, TextureMapperAnimation>::const_iterator end = m_animations.end();
+ for (HashMap<String, TextureMapperAnimation>::const_iterator it = m_animations.begin(); it != end; ++it) {
+ const TextureMapperAnimation& animation = it->second;
+ if (animation.isActive() && animation.property() == type)
+ return true;
+ }
+ return false;
+}
+
+bool TextureMapperAnimations::hasRunningAnimations() const
+{
+ HashMap<String, TextureMapperAnimation>::const_iterator end = m_animations.end();
+ for (HashMap<String, TextureMapperAnimation>::const_iterator it = m_animations.begin(); it != end; ++it) {
+ const TextureMapperAnimation& animation = it->second;
+ if (animation.state() == TextureMapperAnimation::PlayingState)
+ return true;
+ }
+
+ return false;
+}
+
+void TextureMapperAnimation::apply(TextureMapperAnimationClient* client)
+{
+ if (state() == StoppedState)
+ return;
+
+ double totalRunningTime = m_state == PausedState ? m_pauseTime : WTF::currentTime() - m_startTime;
+ double normalizedValue = normalizedAnimationValue(totalRunningTime, m_animation->duration(), m_animation->direction());
+
+ if (m_animation->iterationCount() != Animation::IterationCountInfinite && totalRunningTime >= m_animation->duration() * m_animation->iterationCount())
+ setState(StoppedState);
+
+ if (!normalizedValue) {
+ applyInternal(client, m_keyframes.at(0), m_keyframes.at(1), 0);
+ return;
+ }
+
+ if (normalizedValue == 1.0) {
+ applyInternal(client, m_keyframes.at(m_keyframes.size() - 2), m_keyframes.at(m_keyframes.size() - 1), 1);
+ return;
+ }
+ if (m_keyframes.size() == 2) {
+ normalizedValue = applyTimingFunction(m_animation->timingFunction().get(), normalizedValue, m_animation->duration());
+ applyInternal(client, m_keyframes.at(0), m_keyframes.at(1), normalizedValue);
+ return;
+ }
+
+ for (size_t i = 0; i < m_keyframes.size() - 1; ++i) {
+ const AnimationValue* from = m_keyframes.at(i);
+ const AnimationValue* to = m_keyframes.at(i + 1);
+ if (from->keyTime() > normalizedValue || to->keyTime() < normalizedValue)
+ continue;
+
+ normalizedValue = (normalizedValue - from->keyTime()) / (to->keyTime() - from->keyTime());
+ normalizedValue = applyTimingFunction(from->timingFunction(), normalizedValue, m_animation->duration());
+ applyInternal(client, from, to, normalizedValue);
+ break;
+ }
+}
+
+void TextureMapperAnimation::pause(double offset)
+{
+ // FIXME: should apply offset here.
+ setState(PausedState);
+ m_pauseTime = WTF::currentTime() - offset;
+}
+
+void TextureMapperAnimations::pause(const String& name, double offset)
+{
+ HashMap<String, TextureMapperAnimation>::iterator it = m_animations.find(name);
+ if (it == m_animations.end())
+ return;
+ it->second.pause(offset);
+}
+
+void TextureMapperAnimations::apply(TextureMapperAnimationClient* client)
+{
+ HashMap<String, TextureMapperAnimation>::iterator end = m_animations.end();
+ for (HashMap<String, TextureMapperAnimation>::iterator it = m_animations.begin(); it != end; ++it)
+ it->second.apply(client);
+}
+
+}
+#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.h b/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.h
new file mode 100644
index 000000000..a3f1ca60f
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.h
@@ -0,0 +1,85 @@
+/*
+ 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 TextureMapperAnimation_h
+#define TextureMapperAnimation_h
+
+#include "GraphicsLayer.h"
+#include "HashMap.h"
+#include "TransformationMatrix.h"
+#include <wtf/text/StringHash.h>
+
+#if USE(TEXTURE_MAPPER)
+namespace WebCore {
+
+class TextureMapperAnimationClient {
+public:
+ virtual void setTransform(const TransformationMatrix&) = 0;
+ virtual void setOpacity(float) = 0;
+};
+
+class TextureMapperAnimation {
+public:
+ enum AnimationState { PlayingState, PausedState, StoppedState };
+
+ TextureMapperAnimation()
+ : m_keyframes(AnimatedPropertyInvalid)
+ { }
+ TextureMapperAnimation(const KeyframeValueList&, const IntSize&, const Animation*, double, bool);
+ void apply(TextureMapperAnimationClient*);
+ void pause(double);
+ AnimationState state() const { return m_state; }
+ void setState(AnimationState s) { m_state = s; }
+ AnimatedPropertyID property() const { return m_keyframes.property(); }
+ bool isActive() const;
+
+private:
+ void applyInternal(TextureMapperAnimationClient*, const AnimationValue* from, const AnimationValue* to, float progress);
+ KeyframeValueList m_keyframes;
+ IntSize m_boxSize;
+ RefPtr<Animation> m_animation;
+ String m_name;
+ bool m_listsMatch;
+ bool m_hasBigRotation;
+ double m_startTime;
+ double m_pauseTime;
+ AnimationState m_state;
+};
+
+class TextureMapperAnimations {
+public:
+ TextureMapperAnimations() { }
+
+ void add(const String& name, const TextureMapperAnimation& animation) { m_animations.add(name, animation); }
+ void remove(const String& name) { m_animations.remove(name); }
+ void pause(const String&, double);
+ void apply(TextureMapperAnimationClient*);
+ bool isEmpty() const { return m_animations.isEmpty(); }
+
+ bool hasRunningAnimations() const;
+ bool hasActiveAnimationsOfType(AnimatedPropertyID type) const;
+
+private:
+ HashMap<String, TextureMapperAnimation> m_animations;
+};
+
+}
+#endif // USE(TEXTURE_MAPPER)
+
+#endif // TextureMapperAnimation_h
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp
index 15dff5aeb..ccf49bc98 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp
@@ -47,95 +47,37 @@ TextureMapperNode* TextureMapperNode::rootLayer()
void TextureMapperNode::setTransform(const TransformationMatrix& matrix)
{
- if (m_transforms.base == matrix)
- return;
-
- m_transforms.base = matrix;
-}
-
-void TextureMapperNode::computePerspectiveTransformIfNeeded()
-{
- if (m_children.isEmpty() || m_state.childrenTransform.isIdentity())
- return;
-
- const FloatPoint centerPoint = FloatPoint(m_size.width() / 2, m_size.height() / 2);
- m_transforms.perspective = TransformationMatrix()
- .translate(centerPoint.x(), centerPoint.y())
- .multiply(m_state.childrenTransform)
- .translate(-centerPoint.x(), -centerPoint.y());
-}
-
-int TextureMapperNode::countDescendantsWithContent() const
-{
- if (!m_state.visible || (!m_size.width() && !m_size.height() && m_state.masksToBounds))
- return 0;
- int count = (m_size.width() && m_size.height() && (m_state.drawsContent || m_currentContent.contentType != HTMLContentType)) ? 1 : 0;
- for (size_t i = 0; i < m_children.size(); ++i)
- count += m_children[i]->countDescendantsWithContent();
-
- return count;
+ m_transform.setLocalTransform(matrix);
}
-void TextureMapperNode::computeOverlapsIfNeeded()
-{
- m_state.mightHaveOverlaps = countDescendantsWithContent() > 1;
-}
-
-void TextureMapperNode::computeReplicaTransformIfNeeded()
-{
- if (!m_state.replicaLayer)
- return;
-
- m_transforms.replica =
- TransformationMatrix(m_transforms.target)
- .multiply(m_state.replicaLayer->m_transforms.local)
- .multiply(TransformationMatrix(m_transforms.target).inverse());
-}
-
-void TextureMapperNode::computeLocalTransformIfNeeded()
-{
- float originX = m_state.anchorPoint.x() * m_size.width();
- float originY = m_state.anchorPoint.y() * m_size.height();
- m_transforms.local =
- TransformationMatrix()
- .translate3d(originX + m_state.pos.x(), originY + m_state.pos.y(), m_state.anchorPoint.z() )
- .multiply(m_transforms.base)
- .translate3d(-originX, -originY, -m_state.anchorPoint.z());
-}
-
-void TextureMapperNode::computeAllTransforms()
+void TextureMapperNode::computeTransformsRecursive()
{
if (m_size.isEmpty() && m_state.masksToBounds)
return;
- computeLocalTransformIfNeeded();
- computeReplicaTransformIfNeeded();
- computePerspectiveTransformIfNeeded();
-
- m_transforms.target = TransformationMatrix(m_parent ? m_parent->m_transforms.forDescendants : TransformationMatrix()).multiply(m_transforms.local);
+ // Compute transforms recursively on the way down to leafs.
+ TransformationMatrix parentTransform;
+ if (m_parent)
+ parentTransform = m_parent->m_transform.combinedForChildren();
+ else if (m_effectTarget)
+ parentTransform = m_effectTarget->m_transform.combined();
+ m_transform.combineTransforms(parentTransform);
- m_state.visible = m_state.backfaceVisibility || m_transforms.target.inverse().m33() >= 0;
- if (!m_state.visible)
- return;
+ m_state.visible = m_state.backfaceVisibility || m_transform.combined().inverse().m33() >= 0;
- // This transform is only applied if using a two-pass for the replica, because the transform needs to be adjusted to the size of the intermediate surface, insteaf of the size of the content layer.
if (m_parent && m_parent->m_state.preserves3D)
- m_transforms.centerZ = m_transforms.target.mapPoint(FloatPoint3D(m_size.width() / 2, m_size.height() / 2, 0)).z();
-
- if (!m_children.size())
- return;
-
- m_transforms.forDescendants = m_transforms.target;
+ m_centerZ = m_transform.combined().mapPoint(FloatPoint3D(m_size.width() / 2, m_size.height() / 2, 0)).z();
- if (!m_state.preserves3D) {
- m_transforms.forDescendants = TransformationMatrix(
- m_transforms.forDescendants.m11(), m_transforms.forDescendants.m12(), 0, m_transforms.forDescendants.m14(),
- m_transforms.forDescendants.m21(), m_transforms.forDescendants.m22(), 0, m_transforms.forDescendants.m24(),
- 0, 0, 1, 0,
- m_transforms.forDescendants.m41(), m_transforms.forDescendants.m42(), 0, m_transforms.forDescendants.m44());
- }
+ if (m_state.maskLayer)
+ m_state.maskLayer->computeTransformsRecursive();
+ if (m_state.replicaLayer)
+ m_state.replicaLayer->computeTransformsRecursive();
+ for (int i = 0; i < m_children.size(); ++i)
+ m_children[i]->computeTransformsRecursive();
- m_transforms.forDescendants.multiply(m_transforms.perspective);
+ // Reorder children if needed on the way back up.
+ if (m_state.preserves3D)
+ sortByZOrder(m_children, 0, m_children.size());
}
void TextureMapperNode::computeTiles()
@@ -158,9 +100,6 @@ void TextureMapperNode::computeTiles()
for (float x = 0; x < contentRect.width(); x += gTileDimension) {
FloatRect tileRect(x, y, gTileDimension, gTileDimension);
tileRect.intersect(contentRect);
- FloatRect tileRectInRootCoordinates = tileRect;
- tileRectInRootCoordinates.scale(1.0);
- tileRectInRootCoordinates = m_transforms.target.mapRect(tileRectInRootCoordinates);
tilesToAdd.append(tileRect);
}
}
@@ -202,52 +141,6 @@ void TextureMapperNode::computeTiles()
m_ownedTiles.remove(tilesToRemove[i]);
}
-#if USE(TILED_BACKING_STORE)
-static void clampRect(IntRect& rect, int dimension)
-{
- rect.shiftXEdgeTo(rect.x() - rect.x() % dimension);
- rect.shiftYEdgeTo(rect.y() - rect.y() % dimension);
- rect.shiftMaxXEdgeTo(rect.maxX() - rect.x() % dimension + dimension);
- rect.shiftMaxYEdgeTo(rect.maxY() - rect.y() % dimension + dimension);
-}
-
-bool TextureMapperNode::collectVisibleContentsRects(NodeRectMap& rectMap, const FloatRect& rootVisibleRect)
-{
- if (!m_state.visible)
- return false;
- bool exists = false;
-
- for (int i = 0; i < m_children.size(); ++i)
- exists = m_children[i]->collectVisibleContentsRects(rectMap, rootVisibleRect) || exists;
- if (m_state.maskLayer)
- exists = m_state.maskLayer->collectVisibleContentsRects(rectMap, rootVisibleRect) || exists;
- if (m_state.replicaLayer)
- exists = m_state.replicaLayer->collectVisibleContentsRects(rectMap, rootVisibleRect) || exists;
-
- // Non-invertible layers are not visible.
- if (!m_transforms.target.isInvertible())
- return exists;
-
- static const int tilingThreshold = 256;
-
- IntRect visibleContentsRect(0, 0, m_size.width(), m_size.height());
- if (m_size.width() > tilingThreshold || m_size.height() > tilingThreshold) {
- IntRect visibleRectInLocalCoordinates = enclosingIntRect(TransformationMatrix(m_transforms.target).inverse().mapRect(rootVisibleRect));
- if (!visibleRectInLocalCoordinates.isEmpty())
- clampRect(visibleRectInLocalCoordinates, gTileDimension);
- visibleContentsRect.intersect(visibleRectInLocalCoordinates);
- }
-
- if (visibleContentsRect.isEmpty() || visibleContentsRect == m_state.visibleRect)
- return exists;
-
- m_state.visibleRect = visibleContentsRect;
- rectMap.add(this, m_state.visibleRect);
-
- return true;
-}
-#endif
-
void TextureMapperNode::renderContent(TextureMapper* textureMapper, GraphicsLayer* layer)
{
#if USE(TILED_BACKING_STORE)
@@ -312,6 +205,8 @@ void TextureMapperNode::paint()
if (m_size.isEmpty())
return;
+ computeTransformsRecursive();
+
TextureMapperPaintOptions opt;
opt.textureMapper = m_textureMapper;
opt.textureMapper->bindSurface(0);
@@ -332,17 +227,16 @@ void TextureMapperNode::paintSelf(const TextureMapperPaintOptions& options)
if (m_size.isEmpty() || (!m_state.drawsContent && m_currentContent.contentType == HTMLContentType))
return;
- RefPtr<BitmapTexture> maskTexture;
- RefPtr<BitmapTexture> replicaMaskTexture;
-
- if (m_state.maskLayer)
- maskTexture = m_state.maskLayer->texture();
- if (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer)
- replicaMaskTexture = m_state.replicaLayer->m_state.maskLayer->texture();
-
- float opacity = options.isSurface ? 1 : options.opacity;
+ float opacity = options.opacity;
+ BitmapTexture* mask = options.mask;
FloatRect targetRect = this->targetRect();
+ // 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());
+
#if USE(TILED_BACKING_STORE)
Vector<ExternallyManagedTile> tilesToPaint;
@@ -364,20 +258,11 @@ void TextureMapperNode::paintSelf(const TextureMapperPaintOptions& options)
tiles.prepend(&it->second);
}
- TransformationMatrix replicaMatrix;
for (int i = 0; i < tiles.size(); ++i) {
ExternallyManagedTile& tile = *tiles[i];
FloatRect rect = tile.frontBuffer.targetRect;
-
- float replicaOpacity = 1.0;
- if (m_state.replicaLayer) {
- replicaMatrix = TransformationMatrix(m_transforms.target).scale(1.0 / tile.scale).multiply(m_state.replicaLayer->m_transforms.local);
- replicaOpacity = opacity * m_state.replicaLayer->m_opacity;
- }
BitmapTexture& texture = *tile.frontBuffer.texture;
- if (m_state.replicaLayer)
- options.textureMapper->drawTexture(texture, rect, replicaMatrix, replicaOpacity, replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get());
- options.textureMapper->drawTexture(texture, rect, m_transforms.target, opacity, options.isSurface ? 0 : maskTexture.get());
+ options.textureMapper->drawTexture(texture, rect, transform, opacity, mask);
}
return;
}
@@ -386,32 +271,19 @@ void TextureMapperNode::paintSelf(const TextureMapperPaintOptions& options)
// Now we paint owned tiles, if we're in OwnedTileMode.
for (size_t i = 0; i < m_ownedTiles.size(); ++i) {
BitmapTexture* texture = m_ownedTiles[i].texture.get();
- if (m_state.replicaLayer && !options.isSurface) {
- options.textureMapper->drawTexture(*texture, targetRectForTileRect(targetRect, m_ownedTiles[i].rect),
- TransformationMatrix(m_transforms.target).multiply(m_state.replicaLayer->m_transforms.local),
- opacity * m_state.replicaLayer->m_opacity,
- replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get());
- }
-
const FloatRect rect = targetRectForTileRect(targetRect, m_ownedTiles[i].rect);
- options.textureMapper->drawTexture(*texture, rect, m_transforms.target, opacity, options.isSurface ? 0 : maskTexture.get());
+ options.textureMapper->drawTexture(*texture, rect, transform, opacity, mask);
}
- if (m_currentContent.contentType == MediaContentType && m_currentContent.media) {
- if (m_state.replicaLayer && !options.isSurface)
- m_currentContent.media->paintToTextureMapper(options.textureMapper, targetRect,
- TransformationMatrix(m_transforms.target).multiply(m_state.replicaLayer->m_transforms.local),
- opacity * m_state.replicaLayer->m_opacity,
- replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get());
- m_currentContent.media->paintToTextureMapper(options.textureMapper, targetRect, m_transforms.target, opacity, options.isSurface ? 0 : maskTexture.get());
- }
+ if (m_currentContent.contentType == MediaContentType && m_currentContent.media)
+ m_currentContent.media->paintToTextureMapper(options.textureMapper, targetRect, transform, opacity, mask);
}
int TextureMapperNode::compareGraphicsLayersZValue(const void* a, const void* b)
{
TextureMapperNode* const* nodeA = static_cast<TextureMapperNode* const*>(a);
TextureMapperNode* const* nodeB = static_cast<TextureMapperNode* const*>(b);
- return int(((*nodeA)->m_transforms.centerZ - (*nodeB)->m_transforms.centerZ) * 1000);
+ return int(((*nodeA)->m_centerZ - (*nodeB)->m_centerZ) * 1000);
}
void TextureMapperNode::sortByZOrder(Vector<TextureMapperNode* >& array, int first, int last)
@@ -419,139 +291,138 @@ void TextureMapperNode::sortByZOrder(Vector<TextureMapperNode* >& array, int fir
qsort(array.data(), array.size(), sizeof(TextureMapperNode*), compareGraphicsLayersZValue);
}
-void TextureMapperNode::paintSelfAndChildren(const TextureMapperPaintOptions& options, TextureMapperPaintOptions& optionsForDescendants)
+void TextureMapperNode::paintSelfAndChildren(const TextureMapperPaintOptions& options)
{
bool hasClip = m_state.masksToBounds && !m_children.isEmpty();
if (hasClip)
- options.textureMapper->beginClip(m_transforms.forDescendants, FloatRect(0, 0, m_size.width(), m_size.height()));
+ options.textureMapper->beginClip(TransformationMatrix(options.transform).multiply(m_transform.combined()), FloatRect(0, 0, m_size.width(), m_size.height()));
paintSelf(options);
for (int i = 0; i < m_children.size(); ++i)
- m_children[i]->paintRecursive(optionsForDescendants);
+ m_children[i]->paintRecursive(options);
if (hasClip)
options.textureMapper->endClip();
}
-bool TextureMapperNode::paintReflection(const TextureMapperPaintOptions& options, BitmapTexture* contentSurface)
+IntRect TextureMapperNode::intermediateSurfaceRect()
{
- if (!m_state.replicaLayer)
- return false;
+ // FIXME: Add an inverse transform to LayerTransform.
+ return intermediateSurfaceRect(m_transform.combined().inverse());
+}
- RefPtr<BitmapTexture> surface(contentSurface);
- RefPtr<BitmapTexture> maskSurface;
- RefPtr<BitmapTexture> replicaMaskSurface;
- RefPtr<BitmapTexture> replicaMaskTexture;
-
- if (TextureMapperNode* replicaMask = m_state.replicaLayer->m_state.maskLayer)
- replicaMaskTexture = replicaMask->texture();
-
- RefPtr<BitmapTexture> maskTexture;
- if (TextureMapperNode* mask = m_state.maskLayer)
- maskTexture = mask->texture();
-
- const IntSize viewportSize = options.textureMapper->viewportSize();
- const bool useIntermediateBufferForReplica = m_state.replicaLayer && options.opacity < 0.99;
- const bool useIntermediateBufferForMask = maskTexture && replicaMaskTexture;
- const FloatRect viewportRect(0, 0, viewportSize.width(), viewportSize.height());
-
- // The mask has to be adjusted to target coordinates.
- if (maskTexture) {
- maskSurface = options.textureMapper->acquireTextureFromPool(options.textureMapper->viewportSize());
- options.textureMapper->bindSurface(maskSurface.get());
- options.textureMapper->drawTexture(*maskTexture.get(), entireRect(), m_transforms.target, 1, 0);
- maskTexture = maskSurface;
+IntRect TextureMapperNode::intermediateSurfaceRect(const TransformationMatrix& matrix)
+{
+ IntRect rect;
+ TransformationMatrix localTransform = TransformationMatrix(matrix).multiply(m_transform.combined());
+ rect = enclosingIntRect(localTransform.mapRect(entireRect()));
+ if (!m_state.masksToBounds && !m_state.maskLayer) {
+ for (int i = 0; i < m_children.size(); ++i)
+ rect.unite(m_children[i]->intermediateSurfaceRect(matrix));
}
- // The replica's mask has to be adjusted to target coordinates.
- if (replicaMaskTexture) {
- replicaMaskSurface = options.textureMapper->acquireTextureFromPool(options.textureMapper->viewportSize());
- options.textureMapper->bindSurface(replicaMaskSurface.get());
- options.textureMapper->drawTexture(*replicaMaskTexture.get(), entireRect(), m_transforms.target, 1, 0);
- replicaMaskTexture = replicaMaskSurface;
- }
+ if (m_state.replicaLayer)
+ rect.unite(m_state.replicaLayer->intermediateSurfaceRect(matrix));
- // We might need to apply the mask of the content layer before we draw the reflection, as there might be yet another mask for the reflection itself.
- if (useIntermediateBufferForMask) {
- RefPtr<BitmapTexture> maskSurface = options.textureMapper->acquireTextureFromPool(options.textureMapper->viewportSize());
- options.textureMapper->bindSurface(maskSurface.get());
- options.textureMapper->drawTexture(*surface.get(), viewportRect, TransformationMatrix(), 1, maskTexture.get());
- options.textureMapper->releaseTextureToPool(surface.get());
- surface = maskSurface;
- maskTexture.clear();
- }
+ return rect;
+}
- // We blend the layer and its replica in an intermediate buffer before blending into the target surface.
- if (useIntermediateBufferForReplica) {
- RefPtr<BitmapTexture> replicaSurface = options.textureMapper->acquireTextureFromPool(options.textureMapper->viewportSize());
- options.textureMapper->bindSurface(replicaSurface.get());
- options.textureMapper->drawTexture(*surface.get(), viewportRect, m_transforms.replica, m_state.replicaLayer->m_opacity, replicaMaskTexture.get());
- options.textureMapper->drawTexture(*surface.get(), viewportRect, TransformationMatrix(), 1, maskTexture.get());
- options.textureMapper->releaseTextureToPool(surface.get());
- surface = replicaSurface;
- }
+bool TextureMapperNode::shouldPaintToIntermediateSurface() const
+{
+ bool hasOpacity = m_opacity < 0.99;
+ bool hasChildren = !m_children.isEmpty();
+ bool hasReplica = !!m_state.replicaLayer;
+ bool hasMask = !!m_state.maskLayer;
- options.textureMapper->bindSurface(options.surface);
+ // We don't use two-pass blending for preserves-3d, that's in sync with Safari.
+ if (m_state.preserves3D)
+ return false;
- // Draw the reflection.
- if (!useIntermediateBufferForReplica)
- options.textureMapper->drawTexture(*surface.get(), viewportRect, m_transforms.replica, m_state.replicaLayer->m_opacity, replicaMaskTexture.get());
+ // 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))
+ return true;
- // Draw the original.
- options.textureMapper->drawTexture(*surface.get(), viewportRect, TransformationMatrix(), options.opacity, maskTexture.get());
+ // 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)
+ return true;
- options.textureMapper->releaseTextureToPool(maskSurface.get());
- options.textureMapper->releaseTextureToPool(replicaMaskSurface.get());
+ return false;
+}
+bool TextureMapperNode::isVisible() const
+{
+ if (m_size.isEmpty() && (m_state.masksToBounds || m_state.maskLayer || m_children.isEmpty()))
+ return false;
+ if (!m_state.visible || m_opacity < 0.01)
+ return false;
return true;
}
-void TextureMapperNode::paintRecursive(TextureMapperPaintOptions options)
+void TextureMapperNode::paintSelfAndChildrenWithReplica(const TextureMapperPaintOptions& options)
{
- if ((m_size.isEmpty() && (m_state.masksToBounds
- || m_children.isEmpty())) || !m_state.visible || options.opacity < 0.01 || m_opacity < 0.01)
- return;
+ if (m_state.replicaLayer) {
+ TextureMapperPaintOptions replicaOptions(options);
+ // We choose either the content's mask or the replica's mask.
+ // FIXME: blend the two if both exist.
+ if (m_state.replicaLayer->m_state.maskLayer)
+ replicaOptions.mask = m_state.replicaLayer->m_state.maskLayer->texture();
- options.opacity *= m_opacity;
- RefPtr<BitmapTexture> surface;
- const bool needsTwoPass = ((m_state.replicaLayer || m_state.maskLayer) && !m_children.isEmpty()) || (m_opacity < 0.99 && m_state.mightHaveOverlaps) || (m_opacity < 0.99 && m_state.replicaLayer);
- const IntSize viewportSize = options.textureMapper->viewportSize();
- options.isSurface = false;
+ replicaOptions.transform
+ .multiply(m_state.replicaLayer->m_transform.combined())
+ .multiply(m_transform.combined().inverse());
+ paintSelfAndChildren(replicaOptions);
+ }
- TextureMapperPaintOptions optionsForDescendants(options);
+ paintSelfAndChildren(options);
+}
- if (!needsTwoPass) {
- paintSelfAndChildren(options, optionsForDescendants);
+void TextureMapperNode::paintRecursive(const TextureMapperPaintOptions& options)
+{
+ if (!isVisible())
return;
- }
- FloatRect viewportRect(0, 0, viewportSize.width(), viewportSize.height());
+ float opacity = options.opacity * m_opacity;
+ RefPtr<BitmapTexture> maskTexture = m_state.maskLayer ? m_state.maskLayer->texture() : 0;
- RefPtr<BitmapTexture> maskSurface;
+ TextureMapperPaintOptions paintOptions(options);
+ paintOptions.mask = maskTexture.get();
+ IntRect surfaceRect;
- // The mask has to be adjusted to target coordinates.
- if (m_state.maskLayer) {
- maskSurface = options.textureMapper->acquireTextureFromPool(options.textureMapper->viewportSize());
- options.textureMapper->bindSurface(maskSurface.get());
- options.textureMapper->drawTexture(*m_state.maskLayer->texture(), entireRect(), m_transforms.target, 1.0, 0);
+ RefPtr<BitmapTexture> surface;
+
+ if (!shouldPaintToIntermediateSurface()) {
+ paintOptions.opacity = opacity;
+ paintSelfAndChildrenWithReplica(paintOptions);
+ return;
}
- surface = options.textureMapper->acquireTextureFromPool(options.textureMapper->viewportSize());
- optionsForDescendants.surface = surface.get();
- options.isSurface = true;
- optionsForDescendants.opacity = 1;
+ // Prepare a surface to paint into.
+ // We paint into the surface ignoring the opacity/transform of the current layer.
+ surfaceRect = intermediateSurfaceRect();
+ surface = options.textureMapper->acquireTextureFromPool(surfaceRect.size());
options.textureMapper->bindSurface(surface.get());
+ paintOptions.opacity = 1;
- paintSelfAndChildren(options, optionsForDescendants);
+ // We have to use combinedForChildren() and not combined(), otherwise preserve-3D doesn't work.
+ paintOptions.transform = m_transform.combinedForChildren().inverse();
+ paintOptions.offset = -IntSize(surfaceRect.x(), surfaceRect.y());
- if (!paintReflection(options, surface.get())) {
- options.textureMapper->bindSurface(options.surface);
- options.textureMapper->drawTexture(*surface.get(), viewportRect, TransformationMatrix(), options.opacity, 0);
- }
+ paintSelfAndChildrenWithReplica(paintOptions);
+
+ // If we painted the replica, the mask is already applied so we don't need to paint it again.
+ if (m_state.replicaLayer)
+ maskTexture = 0;
- options.textureMapper->releaseTextureToPool(surface.get());
- options.textureMapper->releaseTextureToPool(maskSurface.get());
+ options.textureMapper->bindSurface(options.surface);
+ TransformationMatrix targetTransform =
+ TransformationMatrix(options.transform)
+ .multiply(m_transform.combined())
+ .translate(options.offset.width(), options.offset.height());
+ options.textureMapper->drawTexture(*surface.get(), surfaceRect, targetTransform, opacity, maskTexture.get());
}
TextureMapperNode::~TextureMapperNode()
@@ -610,7 +481,7 @@ void TextureMapperNode::clearAllDirectlyCompositedImageTiles()
}
}
-void TextureMapperNode::setContentsTileBackBuffer(int id, const IntRect& sourceRect, const IntRect& targetRect, void* bits, BitmapTexture::PixelFormat format)
+void TextureMapperNode::setContentsTileBackBuffer(int id, const IntRect& sourceRect, const IntRect& targetRect, const void* bits)
{
ASSERT(m_textureMapper);
@@ -627,7 +498,7 @@ void TextureMapperNode::setContentsTileBackBuffer(int id, const IntRect& sourceR
if (!tile.backBuffer.texture)
tile.backBuffer.texture = m_textureMapper->createTexture();
tile.backBuffer.texture->reset(sourceRect.size(), false);
- tile.backBuffer.texture->updateContents(format, sourceRect, bits);
+ tile.backBuffer.texture->updateRawContents(sourceRect, bits);
tile.isBackBufferUpdated = true;
}
@@ -714,11 +585,8 @@ void TextureMapperNode::syncCompositingStateSelf(GraphicsLayerTextureMapper* gra
layer->m_effectTarget = this;
}
- if (changeMask & AnimationChange) {
- m_animations.clear();
- for (size_t i = 0; i < graphicsLayer->m_animations.size(); ++i)
- m_animations.append(graphicsLayer->m_animations[i]);
- }
+ if (changeMask & AnimationChange)
+ m_animations = graphicsLayer->m_animations;
m_state.maskLayer = toTextureMapperNode(graphicsLayer->maskLayer());
m_state.replicaLayer = toTextureMapperNode(graphicsLayer->replicaLayer());
@@ -735,6 +603,7 @@ void TextureMapperNode::syncCompositingStateSelf(GraphicsLayerTextureMapper* gra
m_state.backfaceVisibility = graphicsLayer->backfaceVisibility();
m_state.childrenTransform = graphicsLayer->childrenTransform();
m_state.opacity = graphicsLayer->opacity();
+
m_currentContent.contentType = pendingContent.contentType;
m_currentContent.image = pendingContent.image;
m_currentContent.media = pendingContent.media;
@@ -742,18 +611,17 @@ void TextureMapperNode::syncCompositingStateSelf(GraphicsLayerTextureMapper* gra
if (!m_currentContent.needsDisplay)
m_currentContent.needsDisplayRect.unite(pendingContent.needsDisplayRect);
- if (!hasOpacityAnimation())
- m_opacity = m_state.opacity;
- if (!hasTransformAnimation())
- m_transforms.base = m_state.transform;
+ m_transform.setPosition(m_state.pos);
+ m_transform.setAnchorPoint(m_state.anchorPoint);
+ m_transform.setSize(m_state.size);
+ m_transform.setFlattening(!m_state.preserves3D);
+ m_transform.setChildrenTransform(m_state.childrenTransform);
}
bool TextureMapperNode::descendantsOrSelfHaveRunningAnimations() const
{
- for (size_t i = 0; i < m_animations.size(); ++i) {
- if (!m_animations[i]->paused)
- return true;
- }
+ if (m_animations.hasRunningAnimations())
+ return true;
for (size_t i = 0; i < m_children.size(); ++i) {
if (m_children[i]->descendantsOrSelfHaveRunningAnimations())
@@ -763,199 +631,18 @@ bool TextureMapperNode::descendantsOrSelfHaveRunningAnimations() const
return false;
}
-static double normalizedAnimationValue(double runningTime, double duration, bool alternate)
-{
- if (!duration)
- return 0;
- const int loopCount = runningTime / duration;
- const double lastFullLoop = duration * double(loopCount);
- const double remainder = runningTime - lastFullLoop;
- const double normalized = remainder / duration;
- return (loopCount % 2 && alternate) ? (1 - normalized) : normalized;
-}
-
-void TextureMapperNode::applyOpacityAnimation(float fromOpacity, float toOpacity, double progress)
-{
- // Optimization: special case the edge values (0 and 1).
- if (progress == 1.0)
- setOpacity(toOpacity);
- else if (!progress)
- setOpacity(fromOpacity);
- else
- setOpacity(fromOpacity + progress * (toOpacity - fromOpacity));
-}
-
-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)
-{
- 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 std::min(1.0, (floor(numSteps * t) + 1) / numSteps);
- return floor(numSteps * t) / numSteps;
-}
-
-static inline float applyTimingFunction(const TimingFunction* timingFunction, float progress, double duration)
-{
- if (!timingFunction)
- return progress;
-
- if (timingFunction->isCubicBezierTimingFunction()) {
- const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(timingFunction);
- return solveCubicBezierFunction(ctf->x1(),
- ctf->y1(),
- ctf->x2(),
- ctf->y2(),
- progress, duration);
- }
-
- if (timingFunction->isStepsTimingFunction()) {
- const StepsTimingFunction* stf = static_cast<const StepsTimingFunction*>(timingFunction);
- return solveStepsFunction(stf->numberOfSteps(), stf->stepAtStart(), double(progress));
- }
-
- return progress;
-}
-
-void TextureMapperNode::applyTransformAnimation(const TextureMapperAnimation& animation, const TransformOperations* from, const TransformOperations* to, double progress)
-{
- // Optimization: special case the edge values (0 and 1).
- if (progress == 1.0 || !progress) {
- TransformationMatrix matrix;
- const TransformOperations* ops = progress ? to : from;
- ops->apply(animation.boxSize, matrix);
- setTransform(matrix);
- }
-
- if (!animation.listsMatch) {
- TransformationMatrix toMatrix, fromMatrix;
- to->apply(animation.boxSize, toMatrix);
- from->apply(animation.boxSize, fromMatrix);
- toMatrix.blend(fromMatrix, progress);
- setTransform(toMatrix);
- return;
- }
-
- TransformationMatrix matrix;
-
- if (!to->size()) {
- const TransformOperations* swap = to;
- to = from;
- from = swap;
- } else if (!from->size())
- progress = 1.0 - progress;
-
- TransformOperations blended(*to);
- for (size_t i = 0; i < animation.functionList.size(); ++i)
- blended.operations()[i]->blend(from->at(i), progress, !from->at(i))->apply(matrix, animation.boxSize);
-
- setTransform(matrix);
-}
-
-void TextureMapperNode::applyAnimationFrame(const TextureMapperAnimation& animation, const AnimationValue* from, const AnimationValue* to, float progress)
-{
- switch (animation.keyframes.property()) {
- case AnimatedPropertyOpacity:
- applyOpacityAnimation((static_cast<const FloatAnimationValue*>(from)->value()), (static_cast<const FloatAnimationValue*>(to)->value()), progress);
- return;
- case AnimatedPropertyWebkitTransform:
- applyTransformAnimation(animation, static_cast<const TransformAnimationValue*>(from)->value(), static_cast<const TransformAnimationValue*>(to)->value(), progress);
- return;
- default:
- ASSERT_NOT_REACHED();
- }
-}
-
-void TextureMapperNode::applyAnimation(const TextureMapperAnimation& animation, double normalizedValue)
-{
- // Optimization: special case the edge values (0 and 1).
- if (!normalizedValue) {
- applyAnimationFrame(animation, animation.keyframes.at(0), animation.keyframes.at(1), 0);
- return;
- }
- if (normalizedValue == 1.0) {
- applyAnimationFrame(animation, animation.keyframes.at(animation.keyframes.size() - 2), animation.keyframes.at(animation.keyframes.size() - 1), 1);
- return;
- }
- if (animation.keyframes.size() == 2) {
- normalizedValue = applyTimingFunction(animation.animation->timingFunction().get(), normalizedValue, animation.animation->duration());
- applyAnimationFrame(animation, animation.keyframes.at(0), animation.keyframes.at(1), normalizedValue);
- return;
- }
-
- for (size_t i = 0; i < animation.keyframes.size() - 1; ++i) {
- const AnimationValue* from = animation.keyframes.at(i);
- const AnimationValue* to = animation.keyframes.at(i + 1);
- if (from->keyTime() > normalizedValue || to->keyTime() < normalizedValue)
- continue;
-
- normalizedValue = (normalizedValue - from->keyTime()) / (to->keyTime() - from->keyTime());
- normalizedValue = applyTimingFunction(from->timingFunction(), normalizedValue, animation.animation->duration());
- applyAnimationFrame(animation, from, to, normalizedValue);
- break;
- }
-}
-
-bool TextureMapperNode::hasOpacityAnimation() const
-{
- for (size_t i = 0; i < m_animations.size(); ++i) {
- const TextureMapperAnimation& animation = *m_animations[i].get();
- if (animation.keyframes.property() == AnimatedPropertyOpacity)
- return true;
- }
- return false;
-}
-
-bool TextureMapperNode::hasTransformAnimation() const
-{
- for (size_t i = 0; i < m_animations.size(); ++i) {
- const TextureMapperAnimation& animation = *m_animations[i].get();
- if (animation.keyframes.property() == AnimatedPropertyWebkitTransform)
- return true;
- }
- return false;
-}
-
-void TextureMapperNode::syncAnimations(GraphicsLayerTextureMapper* layer)
+void TextureMapperNode::syncAnimations()
{
- for (int i = m_animations.size() - 1; i >= 0; --i) {
- RefPtr<TextureMapperAnimation> animation = m_animations[i];
-
- double totalRunningTime = WTF::currentTime() - animation->startTime;
- RefPtr<Animation> anim = animation->animation;
- double normalizedValue = normalizedAnimationValue(totalRunningTime, anim->duration(), anim->direction());
-
- if (anim->iterationCount() != Animation::IterationCountInfinite && totalRunningTime >= anim->duration() * anim->iterationCount()) {
- // We apply an animation that very close to the edge, so that the final frame is applied, oterwise we might get, for example, an opacity of 0.01 which is still visible.
- if (anim->fillsForwards()) {
- if (animation->keyframes.property() == AnimatedPropertyWebkitTransform)
- m_state.transform = m_transforms.base;
- else if (animation->keyframes.property() == AnimatedPropertyOpacity)
- m_opacity = m_state.opacity;
- }
-
- m_animations.remove(i);
- continue;
- }
-
- if (!animation->paused)
- applyAnimation(*animation.get(), normalizedValue);
- }
+ m_animations.apply(this);
+ if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitTransform))
+ setTransform(m_state.transform);
+ if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyOpacity))
+ setOpacity(m_state.opacity);
}
void TextureMapperNode::syncAnimationsRecursively()
{
- syncAnimations(0);
-
- computeAllTransforms();
+ syncAnimations();
for (int i = m_children.size() - 1; i >= 0; --i)
m_children[i]->syncAnimationsRecursively();
@@ -979,11 +666,8 @@ void TextureMapperNode::syncCompositingState(GraphicsLayerTextureMapper* graphic
if (m_state.replicaLayer)
m_state.replicaLayer->syncCompositingState(toGraphicsLayerTextureMapper(graphicsLayer->replicaLayer()), textureMapper);
- syncAnimations(graphicsLayer);
-
- computeAllTransforms();
+ syncAnimations();
computeTiles();
- computeOverlapsIfNeeded();
if (graphicsLayer)
renderContent(textureMapper, graphicsLayer);
@@ -1003,16 +687,7 @@ void TextureMapperNode::syncCompositingState(GraphicsLayerTextureMapper* graphic
for (int i = m_children.size() - 1; i >= 0; --i)
m_children[i]->syncCompositingState(0, textureMapper, options);
}
-
- if (m_state.preserves3D)
- sortByZOrder(m_children, 0, m_children.size());
}
-TextureMapperAnimation::TextureMapperAnimation(const KeyframeValueList& values)
- : keyframes(values)
-{
}
-
-}
-
#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h
index b40cd5d38..fe4b14c73 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h
@@ -25,11 +25,11 @@
#include "GraphicsLayer.h"
#include "Image.h"
#include "IntPointHash.h"
+#include "LayerTransform.h"
#include "TextureMapper.h"
+#include "TextureMapperAnimation.h"
#include "Timer.h"
#include "TransformOperations.h"
-#include "TranslateTransformOperation.h"
-#include "UnitBezier.h"
#include <wtf/CurrentTime.h>
#include <wtf/HashMap.h>
#include <wtf/RefCounted.h>
@@ -43,34 +43,20 @@ class GraphicsLayerTextureMapper;
class TextureMapperPaintOptions {
public:
BitmapTexture* surface;
- TextureMapper* textureMapper;
-
+ BitmapTexture* mask;
float opacity;
- bool isSurface;
+ TransformationMatrix transform;
+ IntSize offset;
+ TextureMapper* textureMapper;
TextureMapperPaintOptions()
: surface(0)
- , textureMapper(0)
+ , mask(0)
, opacity(1)
- , isSurface(false)
+ , textureMapper(0)
{ }
};
-class TextureMapperAnimation : public RefCounted<TextureMapperAnimation> {
-public:
- String name;
- KeyframeValueList keyframes;
- IntSize boxSize;
- RefPtr<Animation> animation;
- bool paused;
- Vector<TransformOperation::OperationType> functionList;
- bool listsMatch;
- bool hasBigRotation;
- double startTime;
- TextureMapperAnimation(const KeyframeValueList&);
- static PassRefPtr<TextureMapperAnimation> create(const KeyframeValueList& values) { return adoptRef(new TextureMapperAnimation(values)); }
-};
-
-class TextureMapperNode {
+class TextureMapperNode : public TextureMapperAnimationClient {
public:
// This set of flags help us defer which properties of the layer have been
@@ -141,6 +127,7 @@ public:
: m_parent(0)
, m_effectTarget(0)
, m_opacity(1)
+ , m_centerZ(0)
, m_textureMapper(0)
{ }
@@ -161,10 +148,9 @@ public:
void setTileOwnership(TileOwnership ownership) { m_state.tileOwnership = ownership; }
int createContentsTile(float scale);
void removeContentsTile(int id);
- void setContentsTileBackBuffer(int id, const IntRect& sourceRect, const IntRect& targetRect, void* bits, BitmapTexture::PixelFormat);
+ void setContentsTileBackBuffer(int id, const IntRect& sourceRect, const IntRect& targetRect, const void* bits);
void setTileBackBufferTextureForDirectlyCompositedImage(int id, const IntRect& sourceRect, const FloatRect& targetRect, BitmapTexture*);
void clearAllDirectlyCompositedImageTiles();
- bool collectVisibleContentsRects(NodeRectMap&, const FloatRect&);
void purgeNodeTexturesRecursive();
#endif
void setID(int id) { m_id = id; }
@@ -174,15 +160,12 @@ public:
private:
TextureMapperNode* rootLayer();
- void computeAllTransforms();
- void computeVisibleRect(const FloatRect& rootVisibleRect);
- void computePerspectiveTransformIfNeeded();
- void computeReplicaTransformIfNeeded();
+ void computeTransformsRecursive();
void computeOverlapsIfNeeded();
- void computeLocalTransformIfNeeded();
void computeTiles();
+ IntRect intermediateSurfaceRect(const TransformationMatrix&);
+ IntRect intermediateSurfaceRect();
void swapContentsBuffers();
- int countDescendantsWithContent() const;
FloatRect targetRectForTileRect(const FloatRect& totalTargetRect, const FloatRect& tileRect) const;
void invalidateViewport(const FloatRect&);
void notifyChange(ChangeMask);
@@ -193,32 +176,17 @@ private:
BitmapTexture* texture() { return m_ownedTiles.isEmpty() ? 0 : m_ownedTiles[0].texture.get(); }
- void paintRecursive(TextureMapperPaintOptions);
- bool paintReflection(const TextureMapperPaintOptions&, BitmapTexture* surface);
+ void paintRecursive(const TextureMapperPaintOptions&);
void paintSelf(const TextureMapperPaintOptions&);
- void paintSelfAndChildren(const TextureMapperPaintOptions&, TextureMapperPaintOptions& optionsForDescendants);
+ void paintSelfAndChildren(const TextureMapperPaintOptions&);
+ void paintSelfAndChildrenWithReplica(const TextureMapperPaintOptions&);
void renderContent(TextureMapper*, GraphicsLayer*);
- void syncAnimations(GraphicsLayerTextureMapper*);
- void applyAnimation(const TextureMapperAnimation&, double runningTime);
- void applyAnimationFrame(const TextureMapperAnimation&, const AnimationValue* from, const AnimationValue* to, float progress);
- void applyOpacityAnimation(float fromOpacity, float toOpacity, double);
- void applyTransformAnimation(const TextureMapperAnimation&, const TransformOperations* start, const TransformOperations* end, double);
- bool hasOpacityAnimation() const;
- bool hasTransformAnimation() const;
-
- struct TransformData {
- TransformationMatrix target;
- TransformationMatrix replica;
- TransformationMatrix forDescendants;
- TransformationMatrix local;
- TransformationMatrix base;
- TransformationMatrix perspective;
- float centerZ;
- TransformData() { }
- };
+ void syncAnimations();
+ bool isVisible() const;
+ bool shouldPaintToIntermediateSurface() const;
- TransformData m_transforms;
+ LayerTransform m_transform;
inline FloatRect targetRect() const
{
@@ -274,6 +242,7 @@ private:
TextureMapperNode* m_effectTarget;
FloatSize m_size;
float m_opacity;
+ float m_centerZ;
String m_name;
int m_id;
@@ -297,7 +266,6 @@ private:
bool needsReset: 1;
bool mightHaveOverlaps : 1;
bool needsRepaint;
- IntRect visibleRect;
float contentScale;
#if USE(TILED_BACKING_STORE)
TileOwnership tileOwnership;
@@ -325,8 +293,7 @@ private:
State m_state;
TextureMapper* m_textureMapper;
-
- Vector<RefPtr<TextureMapperAnimation> > m_animations;
+ TextureMapperAnimations m_animations;
};
diff --git a/Source/WebCore/platform/graphics/transforms/AffineTransform.cpp b/Source/WebCore/platform/graphics/transforms/AffineTransform.cpp
index 60c8df3ef..4131ca4c4 100644
--- a/Source/WebCore/platform/graphics/transforms/AffineTransform.cpp
+++ b/Source/WebCore/platform/graphics/transforms/AffineTransform.cpp
@@ -250,6 +250,22 @@ FloatPoint AffineTransform::mapPoint(const FloatPoint& point) const
return FloatPoint(narrowPrecisionToFloat(x2), narrowPrecisionToFloat(y2));
}
+IntSize AffineTransform::mapSize(const IntSize& size) const
+{
+ double width2 = size.width() * xScale();
+ double height2 = size.height() * yScale();
+
+ return IntSize(lround(width2), lround(height2));
+}
+
+FloatSize AffineTransform::mapSize(const FloatSize& size) const
+{
+ double width2 = size.width() * xScale();
+ double height2 = size.height() * yScale();
+
+ return FloatSize(narrowPrecisionToFloat(width2), narrowPrecisionToFloat(height2));
+}
+
IntRect AffineTransform::mapRect(const IntRect &rect) const
{
return enclosingIntRect(mapRect(FloatRect(rect)));
diff --git a/Source/WebCore/platform/graphics/transforms/AffineTransform.h b/Source/WebCore/platform/graphics/transforms/AffineTransform.h
index d3970da29..7d83f592f 100644
--- a/Source/WebCore/platform/graphics/transforms/AffineTransform.h
+++ b/Source/WebCore/platform/graphics/transforms/AffineTransform.h
@@ -76,6 +76,10 @@ public:
FloatPoint mapPoint(const FloatPoint&) const;
+ IntSize mapSize(const IntSize&) const;
+
+ FloatSize mapSize(const FloatSize&) const;
+
// Rounds the resulting mapped rectangle out. This is helpful for bounding
// box computations but may not be what is wanted in other contexts.
IntRect mapRect(const IntRect&) const;
diff --git a/Source/WebCore/platform/graphics/win/FontCacheWin.cpp b/Source/WebCore/platform/graphics/win/FontCacheWin.cpp
index 3eb7436ee..4d1b2cfd3 100644
--- a/Source/WebCore/platform/graphics/win/FontCacheWin.cpp
+++ b/Source/WebCore/platform/graphics/win/FontCacheWin.cpp
@@ -30,6 +30,7 @@
#include <winsock2.h>
#include "FontCache.h"
#include "Font.h"
+#include "HWndDC.h"
#include "SimpleFontData.h"
#include "UnicodeRange.h"
#include <mlang.h>
@@ -189,7 +190,7 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons
{
UChar character = characters[0];
SimpleFontData* fontData = 0;
- HDC hdc = GetDC(0);
+ HWndDC hdc(0);
HFONT primaryFont = font.primaryFont()->fontDataForCharacter(character)->platformData().hfont();
HGDIOBJ oldFont = SelectObject(hdc, primaryFont);
HFONT hfont = 0;
@@ -292,7 +293,6 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons
DeleteObject(hfont);
}
- ReleaseDC(0, hdc);
return fontData;
}
@@ -447,7 +447,7 @@ static int CALLBACK matchImprovingEnumProc(CONST LOGFONT* candidate, CONST TEXTM
static HFONT createGDIFont(const AtomicString& family, LONG desiredWeight, bool desiredItalic, int size, bool synthesizeItalic)
{
- HDC hdc = GetDC(0);
+ HWndDC hdc(0);
LOGFONT logFont;
logFont.lfCharSet = DEFAULT_CHARSET;
@@ -459,8 +459,6 @@ static HFONT createGDIFont(const AtomicString& family, LONG desiredWeight, bool
MatchImprovingProcData matchData(desiredWeight, desiredItalic);
EnumFontFamiliesEx(hdc, &logFont, matchImprovingEnumProc, reinterpret_cast<LPARAM>(&matchData), 0);
- ReleaseDC(0, hdc);
-
if (!matchData.m_hasMatched)
return 0;
@@ -486,13 +484,12 @@ static HFONT createGDIFont(const AtomicString& family, LONG desiredWeight, bool
if (!result)
return 0;
- HDC dc = GetDC(0);
+ HWndDC dc(0);
SaveDC(dc);
SelectObject(dc, result);
WCHAR actualName[LF_FACESIZE];
GetTextFace(dc, LF_FACESIZE, actualName);
RestoreDC(dc, -1);
- ReleaseDC(0, dc);
if (wcsicmp(matchData.m_chosen.lfFaceName, actualName)) {
DeleteObject(result);
@@ -534,7 +531,7 @@ static int CALLBACK traitsInFamilyEnumProc(CONST LOGFONT* logFont, CONST TEXTMET
}
void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks)
{
- HDC hdc = GetDC(0);
+ HWndDC hdc(0);
LOGFONT logFont;
logFont.lfCharSet = DEFAULT_CHARSET;
@@ -546,8 +543,6 @@ void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigne
TraitsInFamilyProcData procData(familyName);
EnumFontFamiliesEx(hdc, &logFont, traitsInFamilyEnumProc, reinterpret_cast<LPARAM>(&procData), 0);
copyToVector(procData.m_traitsMasks, traitsMasks);
-
- ReleaseDC(0, hdc);
}
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
diff --git a/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp b/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
index d0b37bda3..9860df6a2 100644
--- a/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
+++ b/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
@@ -25,6 +25,7 @@
#include "config.h"
#include "FontPlatformData.h"
+#include "HWndDC.h"
#include "PlatformString.h"
#include <wtf/HashMap.h>
#include <wtf/RetainPtr.h>
@@ -51,7 +52,7 @@ FontPlatformData::FontPlatformData(HFONT font, float size, bool bold, bool obliq
, m_syntheticOblique(oblique)
, m_useGDI(useGDI)
{
- HDC hdc = GetDC(0);
+ HWndDC hdc(0);
SaveDC(hdc);
SelectObject(hdc, font);
@@ -71,7 +72,6 @@ FontPlatformData::FontPlatformData(HFONT font, float size, bool bold, bool obliq
}
RestoreDC(hdc, -1);
- ReleaseDC(0, hdc);
}
#ifndef NDEBUG
diff --git a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
index e2e0c1027..d8be4f5f3 100644
--- a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
+++ b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
@@ -107,6 +107,7 @@ private:
virtual bool platformCALayerContentsOpaque() const { return false; }
virtual bool platformCALayerDrawsContent() const { return false; }
virtual void platformCALayerLayerDidDisplay(PlatformLayer*) { }
+ virtual void platformCALayerDidCreateTiles() { }
MediaPlayerPrivateQuickTimeVisualContext* m_parent;
};
@@ -302,7 +303,8 @@ void MediaPlayerPrivateQuickTimeVisualContext::setUpCookiesForQuickTime(const St
} else
cookieURL = movieURL;
- InternetSetCookieExW(cookieURL.charactersWithNullTermination(), 0, cookieBuilder.toString().charactersWithNullTermination(), 0, 0);
+ String string = cookieBuilder.toString();
+ InternetSetCookieExW(cookieURL.charactersWithNullTermination(), 0, string.charactersWithNullTermination(), 0, 0);
}
}
diff --git a/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp b/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
index 2d8f13e36..ad025b803 100644
--- a/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
+++ b/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
@@ -33,6 +33,7 @@
#include "FontCache.h"
#include "FloatRect.h"
#include "FontDescription.h"
+#include "HWndDC.h"
#include "PlatformString.h"
#include <ApplicationServices/ApplicationServices.h>
#include <WebKitSystemInterface/WebKitSystemInterface.h>
@@ -55,7 +56,7 @@ void SimpleFontData::platformInit()
m_isSystemFont = false;
if (m_platformData.useGDI())
- return initGDIFont();
+ return initGDIFont();
CGFontRef font = m_platformData.cgFont();
int iAscent = CGFontGetAscent(font);
@@ -68,14 +69,13 @@ void SimpleFontData::platformInit()
float fLineGap = scaleEmToUnits(iLineGap, unitsPerEm) * pointSize;
if (!isCustomFont()) {
- HDC dc = GetDC(0);
+ HWndDC dc(0);
HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
int faceLength = GetTextFace(dc, 0, 0);
Vector<WCHAR> faceName(faceLength);
GetTextFace(dc, faceLength, faceName.data());
m_isSystemFont = !wcscmp(faceName.data(), L"Lucida Grande");
SelectObject(dc, oldFont);
- ReleaseDC(0, dc);
fAscent = ascentConsideringMacAscentHack(faceName.data(), fAscent, fDescent);
}
diff --git a/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp b/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
index de6687f5c..983c1bf92 100644
--- a/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
+++ b/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
@@ -33,6 +33,7 @@
#include "FontCache.h"
#include "FloatRect.h"
#include "FontDescription.h"
+#include "HWndDC.h"
#include <mlang.h>
#include <unicode/uchar.h>
#include <unicode/unorm.h>
@@ -89,7 +90,7 @@ void SimpleFontData::initGDIFont()
return;
}
- HDC hdc = GetDC(0);
+ HWndDC hdc(0);
HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont());
OUTLINETEXTMETRIC metrics;
GetOutlineTextMetrics(hdc, sizeof(metrics), &metrics);
@@ -115,9 +116,6 @@ void SimpleFontData::initGDIFont()
m_fontMetrics.setUnitsPerEm(metrics.otmEMSquare);
SelectObject(hdc, oldFont);
- ReleaseDC(0, hdc);
-
- return;
}
void SimpleFontData::platformCharWidthInit()
@@ -185,8 +183,8 @@ bool SimpleFontData::containsCharacters(const UChar* characters, int length) con
if (!langFontLink)
return false;
- HDC dc = GetDC(0);
-
+ HWndDC dc(0);
+
DWORD acpCodePages;
langFontLink->CodePageToCodePages(CP_ACP, &acpCodePages);
@@ -203,8 +201,6 @@ bool SimpleFontData::containsCharacters(const UChar* characters, int length) con
offset += numCharactersProcessed;
}
- ReleaseDC(0, dc);
-
return true;
}
@@ -216,7 +212,7 @@ void SimpleFontData::determinePitch()
}
// TEXTMETRICS have this. Set m_treatAsFixedPitch based off that.
- HDC dc = GetDC(0);
+ HWndDC dc(0);
SaveDC(dc);
SelectObject(dc, m_platformData.hfont());
@@ -227,12 +223,11 @@ void SimpleFontData::determinePitch()
m_treatAsFixedPitch = ((tm.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0);
RestoreDC(dc, -1);
- ReleaseDC(0, dc);
}
FloatRect SimpleFontData::boundsForGDIGlyph(Glyph glyph) const
{
- HDC hdc = GetDC(0);
+ HWndDC hdc(0);
SetGraphicsMode(hdc, GM_ADVANCED);
HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont());
@@ -241,7 +236,6 @@ FloatRect SimpleFontData::boundsForGDIGlyph(Glyph glyph) const
GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0, &identity);
SelectObject(hdc, oldFont);
- ReleaseDC(0, hdc);
return FloatRect(gdiMetrics.gmptGlyphOrigin.x, -gdiMetrics.gmptGlyphOrigin.y,
gdiMetrics.gmBlackBoxX + m_syntheticBoldOffset, gdiMetrics.gmBlackBoxY);
@@ -249,7 +243,7 @@ FloatRect SimpleFontData::boundsForGDIGlyph(Glyph glyph) const
float SimpleFontData::widthForGDIGlyph(Glyph glyph) const
{
- HDC hdc = GetDC(0);
+ HWndDC hdc(0);
SetGraphicsMode(hdc, GM_ADVANCED);
HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont());
@@ -258,7 +252,6 @@ float SimpleFontData::widthForGDIGlyph(Glyph glyph) const
GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0, &identity);
SelectObject(hdc, oldFont);
- ReleaseDC(0, hdc);
return gdiMetrics.gmCellIncX + m_syntheticBoldOffset;
}
@@ -271,12 +264,11 @@ SCRIPT_FONTPROPERTIES* SimpleFontData::scriptFontProperties() const
m_scriptFontProperties->cBytes = sizeof(SCRIPT_FONTPROPERTIES);
HRESULT result = ScriptGetFontProperties(0, scriptCache(), m_scriptFontProperties);
if (result == E_PENDING) {
- HDC dc = GetDC(0);
+ HWndDC dc(0);
SaveDC(dc);
SelectObject(dc, m_platformData.hfont());
ScriptGetFontProperties(dc, scriptCache(), m_scriptFontProperties);
RestoreDC(dc, -1);
- ReleaseDC(0, dc);
}
}
return m_scriptFontProperties;
diff --git a/Source/WebCore/platform/graphics/win/UniscribeController.cpp b/Source/WebCore/platform/graphics/win/UniscribeController.cpp
index 67e34a71d..336b4e642 100644
--- a/Source/WebCore/platform/graphics/win/UniscribeController.cpp
+++ b/Source/WebCore/platform/graphics/win/UniscribeController.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "UniscribeController.h"
#include "Font.h"
+#include "HWndDC.h"
#include "SimpleFontData.h"
#include "TextRun.h"
#include <wtf/MathExtras.h>
@@ -248,13 +249,12 @@ bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, const S
if (placeResult == E_PENDING) {
// The script cache isn't primed with enough info yet. We need to select our HFONT into
// a DC and pass the DC in to ScriptPlace.
- HDC hdc = GetDC(0);
+ HWndDC hdc(0);
HFONT hfont = fontData->platformData().hfont();
HFONT oldFont = (HFONT)SelectObject(hdc, hfont);
placeResult = ScriptPlace(hdc, fontData->scriptCache(), glyphs.data(), glyphs.size(), visualAttributes.data(),
&item.a, advances.data(), offsets.data(), 0);
SelectObject(hdc, oldFont);
- ReleaseDC(0, hdc);
}
if (FAILED(placeResult) || glyphs.isEmpty())
@@ -380,7 +380,7 @@ bool UniscribeController::shape(const UChar* str, int len, SCRIPT_ITEM item, con
Vector<WORD>& glyphs, Vector<WORD>& clusters,
Vector<SCRIPT_VISATTR>& visualAttributes)
{
- HDC hdc = 0;
+ HWndDC hdc;
HFONT oldFont = 0;
HRESULT shapeResult = E_PENDING;
int glyphCount = 0;
@@ -391,7 +391,7 @@ bool UniscribeController::shape(const UChar* str, int len, SCRIPT_ITEM item, con
// The script cache isn't primed with enough info yet. We need to select our HFONT into
// a DC and pass the DC in to ScriptShape.
ASSERT(!hdc);
- hdc = GetDC(0);
+ hdc.setHWnd(0);
HFONT hfont = fontData->platformData().hfont();
oldFont = (HFONT)SelectObject(hdc, hfont);
} else if (shapeResult == E_OUTOFMEMORY) {
@@ -401,10 +401,8 @@ bool UniscribeController::shape(const UChar* str, int len, SCRIPT_ITEM item, con
}
} while (shapeResult == E_PENDING || shapeResult == E_OUTOFMEMORY);
- if (hdc) {
+ if (hdc)
SelectObject(hdc, oldFont);
- ReleaseDC(0, hdc);
- }
if (FAILED(shapeResult))
return false;
diff --git a/Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp b/Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp
index c1de965c4..39ef15503 100644
--- a/Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp
+++ b/Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp
@@ -72,7 +72,7 @@ ImageBufferData::ImageBufferData(const IntSize& size)
m_bitmap->setHasAlpha(true);
}
-ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace colorSpace, RenderingMode, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace colorSpace, RenderingMode, DeferralMode, bool& success)
: m_data(size)
, m_size(size)
{
diff --git a/Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp b/Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp
index d01391f6c..7c909b54d 100644
--- a/Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp
+++ b/Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp
@@ -37,7 +37,7 @@ ImageBufferData::ImageBufferData(const IntSize&)
{
}
-ImageBuffer::ImageBuffer(const IntSize&, ColorSpace imageColorSpace, RenderingMode, bool& success) :
+ImageBuffer::ImageBuffer(const IntSize&, ColorSpace imageColorSpace, RenderingMode, DeferralMode, bool& success) :
m_data(IntSize())
{
notImplemented();
diff --git a/Source/WebCore/platform/gtk/GtkUtilities.cpp b/Source/WebCore/platform/gtk/GtkUtilities.cpp
index 2cf69c9d0..246687958 100644
--- a/Source/WebCore/platform/gtk/GtkUtilities.cpp
+++ b/Source/WebCore/platform/gtk/GtkUtilities.cpp
@@ -42,4 +42,9 @@ IntPoint convertWidgetPointToScreenPoint(GtkWidget* widget, const IntPoint& poin
return IntPoint(windowOriginX + xInWindow, windowOriginY + yInWindow);
}
+bool widgetIsOnscreenToplevelWindow(GtkWidget* widget)
+{
+ return gtk_widget_is_toplevel(widget) && GTK_IS_WINDOW(widget) && !GTK_IS_OFFSCREEN_WINDOW(widget);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/gtk/GtkUtilities.h b/Source/WebCore/platform/gtk/GtkUtilities.h
index a33858fa1..b9bdde659 100644
--- a/Source/WebCore/platform/gtk/GtkUtilities.h
+++ b/Source/WebCore/platform/gtk/GtkUtilities.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, Igalia S.L.
+ * 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
@@ -24,6 +24,7 @@ namespace WebCore {
class IntPoint;
IntPoint convertWidgetPointToScreenPoint(GtkWidget*, const IntPoint&);
+bool widgetIsOnscreenToplevelWindow(GtkWidget*);
} // namespace WebCore
diff --git a/Source/WebCore/platform/gtk/LanguageGtk.cpp b/Source/WebCore/platform/gtk/LanguageGtk.cpp
index 7d7a66d2e..f0fae5300 100644
--- a/Source/WebCore/platform/gtk/LanguageGtk.cpp
+++ b/Source/WebCore/platform/gtk/LanguageGtk.cpp
@@ -22,6 +22,7 @@
#include "GOwnPtr.h"
#include "PlatformString.h"
+#include <wtf/Vector.h>
#include <wtf/text/CString.h>
#include <glib.h>
@@ -32,7 +33,7 @@ namespace WebCore {
// Using pango_language_get_default() here is not an option, because
// it doesn't support changing the locale in runtime, so it returns
// always the same value.
-String platformDefaultLanguage()
+static String platformLanguage()
{
char* localeDefault = setlocale(LC_CTYPE, NULL);
@@ -53,4 +54,11 @@ String platformDefaultLanguage()
return String(normalizedDefault.get());
}
+Vector<String> platformUserPreferredLanguages()
+{
+ Vector<String> userPreferredLanguages;
+ userPreferredLanguages.append(platformLanguage());
+ return userPreferredLanguages;
+}
+
}
diff --git a/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp b/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp
index 0a3b486dc..74e4f18ca 100644
--- a/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp
+++ b/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp
@@ -31,6 +31,7 @@
#include "config.h"
#include "PlatformScreen.h"
+#include "FrameView.h"
#include "GtkVersioning.h"
#include "HostWindow.h"
#include "NotImplemented.h"
@@ -100,9 +101,9 @@ static GdkScreen* getScreen(GtkWidget* widget)
return gtk_widget_has_screen(widget) ? gtk_widget_get_screen(widget) : gdk_screen_get_default();
}
-FloatRect screenRect(Widget* widget)
+FloatRect screenRect(FrameView* frameView)
{
- GtkWidget* container = widget ? GTK_WIDGET(widget->root()->hostWindow()->platformPageClient()) : 0;
+ GtkWidget* container = frameView ? GTK_WIDGET(frameView->root()->hostWindow()->platformPageClient()) : 0;
if (container)
container = getToplevel(container);
@@ -118,11 +119,11 @@ FloatRect screenRect(Widget* widget)
return FloatRect(geometry.x, geometry.y, geometry.width, geometry.height);
}
-FloatRect screenAvailableRect(Widget* widget)
+FloatRect screenAvailableRect(FrameView* frameView)
{
- GtkWidget* container = widget ? GTK_WIDGET(widget->root()->hostWindow()->platformPageClient()) : 0;
+ GtkWidget* container = frameView ? GTK_WIDGET(frameView->root()->hostWindow()->platformPageClient()) : 0;
if (container && !gtk_widget_get_realized(container))
- return screenRect(widget);
+ return screenRect(frameView);
GdkScreen* screen = container ? getScreen(container) : gdk_screen_get_default();
if (!screen)
diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk.h b/Source/WebCore/platform/gtk/RenderThemeGtk.h
index 408b05f8d..ea61674f4 100644
--- a/Source/WebCore/platform/gtk/RenderThemeGtk.h
+++ b/Source/WebCore/platform/gtk/RenderThemeGtk.h
@@ -82,6 +82,8 @@ public:
virtual void systemFont(int propId, FontDescription&) const;
virtual Color systemColor(int cssValueId) const;
+ virtual bool popsMenuBySpaceOrReturn() const OVERRIDE { return true; }
+
#if ENABLE(VIDEO)
virtual String extraMediaControlsStyleSheet();
virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const;
diff --git a/Source/WebCore/platform/gtk/RunLoopGtk.cpp b/Source/WebCore/platform/gtk/RunLoopGtk.cpp
new file mode 100644
index 000000000..929a7b98e
--- /dev/null
+++ b/Source/WebCore/platform/gtk/RunLoopGtk.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Portions Copyright (c) 2010 Motorola Mobility, 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 "RunLoop.h"
+
+#include <glib.h>
+
+namespace WebCore {
+
+RunLoop::RunLoop()
+{
+ m_runLoopContext = g_main_context_default();
+ ASSERT(m_runLoopContext);
+ m_runLoopMain = g_main_loop_new(m_runLoopContext, FALSE);
+ ASSERT(m_runLoopMain);
+}
+
+RunLoop::~RunLoop()
+{
+ if (m_runLoopMain) {
+ if (g_main_loop_is_running(m_runLoopMain))
+ g_main_loop_quit(m_runLoopMain);
+ g_main_loop_unref(m_runLoopMain);
+ }
+
+ if (m_runLoopContext)
+ g_main_context_unref(m_runLoopContext);
+}
+
+void RunLoop::run()
+{
+ g_main_loop_run(RunLoop::main()->mainLoop());
+}
+
+GMainLoop* RunLoop::mainLoop()
+{
+ return m_runLoopMain;
+}
+
+void RunLoop::stop()
+{
+ g_main_loop_quit(m_runLoopMain);
+}
+
+gboolean RunLoop::queueWork(RunLoop* runLoop)
+{
+ runLoop->performWork();
+ return FALSE;
+}
+
+void RunLoop::wakeUp()
+{
+ GRefPtr<GSource> source = adoptGRef(g_idle_source_new());
+ g_source_set_priority(source.get(), G_PRIORITY_DEFAULT);
+ g_source_set_callback(source.get(), reinterpret_cast<GSourceFunc>(&RunLoop::queueWork), this, 0);
+ g_source_attach(source.get(), m_runLoopContext);
+
+ g_main_context_wakeup(m_runLoopContext);
+}
+
+RunLoop::TimerBase::TimerBase(RunLoop* runLoop)
+ : m_runLoop(runLoop)
+ , m_timerSource(0)
+{
+}
+
+RunLoop::TimerBase::~TimerBase()
+{
+ stop();
+}
+
+void RunLoop::TimerBase::clearTimerSource()
+{
+ m_timerSource = 0;
+}
+
+gboolean RunLoop::TimerBase::timerFiredCallback(RunLoop::TimerBase* timer)
+{
+ GSource* currentTimerSource = timer->m_timerSource.get();
+ bool isRepeating = timer->isRepeating();
+ // This can change the timerSource by starting a new timer within the callback.
+ timer->fired();
+ if (!isRepeating && currentTimerSource == timer->m_timerSource.get())
+ timer->clearTimerSource();
+ return isRepeating;
+}
+
+void RunLoop::TimerBase::start(double fireInterval, bool repeat)
+{
+ if (m_timerSource)
+ stop();
+
+ m_timerSource = adoptGRef(g_timeout_source_new(static_cast<guint>(fireInterval * 1000)));
+ m_isRepeating = repeat;
+ g_source_set_callback(m_timerSource.get(), reinterpret_cast<GSourceFunc>(&RunLoop::TimerBase::timerFiredCallback), this, 0);
+ g_source_attach(m_timerSource.get(), m_runLoop->m_runLoopContext);
+}
+
+void RunLoop::TimerBase::stop()
+{
+ if (!m_timerSource)
+ return;
+
+ g_source_destroy(m_timerSource.get());
+ clearTimerSource();
+}
+
+bool RunLoop::TimerBase::isActive() const
+{
+ return m_timerSource;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp b/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp
index b5c5002a4..e99364f2a 100644
--- a/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp
+++ b/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp
@@ -97,6 +97,8 @@ IntRect ScrollbarThemeGtk::backButtonRect(Scrollbar* scrollbar, ScrollbarPart pa
{
if (part == BackButtonEndPart && !m_hasBackButtonEndPart)
return IntRect();
+ if (part == BackButtonStartPart && !m_hasBackButtonStartPart)
+ return IntRect();
int x = scrollbar->x() + m_troughBorderWidth;
int y = scrollbar->y() + m_troughBorderWidth;
@@ -116,6 +118,8 @@ IntRect ScrollbarThemeGtk::forwardButtonRect(Scrollbar* scrollbar, ScrollbarPart
{
if (part == ForwardButtonStartPart && !m_hasForwardButtonStartPart)
return IntRect();
+ if (part == ForwardButtonEndPart && !m_hasForwardButtonEndPart)
+ return IntRect();
IntSize size = buttonSize(scrollbar);
if (scrollbar->orientation() == HorizontalScrollbar) {
@@ -138,37 +142,42 @@ IntRect ScrollbarThemeGtk::forwardButtonRect(Scrollbar* scrollbar, ScrollbarPart
IntRect ScrollbarThemeGtk::trackRect(Scrollbar* scrollbar, bool)
{
- // The padding along the thumb movement axis (from outside to in)
- // is the size of trough border plus the size of the stepper (button)
+ // The padding along the thumb movement axis includes the trough border
// plus the size of stepper spacing (the space between the stepper and
// the place where the thumb stops). There is often no stepper spacing.
- int movementAxisPadding = m_troughBorderWidth + m_stepperSize + m_stepperSpacing;
+ int movementAxisPadding = m_troughBorderWidth + m_stepperSpacing;
// The fatness of the scrollbar on the non-movement axis.
int thickness = scrollbarThickness(scrollbar->controlSize());
- int alternateButtonOffset = 0;
- int alternateButtonWidth = 0;
+ int startButtonsOffset = 0;
+ int buttonsWidth = 0;
if (m_hasForwardButtonStartPart) {
- alternateButtonOffset += m_stepperSize;
- alternateButtonWidth += m_stepperSize;
+ startButtonsOffset += m_stepperSize;
+ buttonsWidth += m_stepperSize;
+ }
+ if (m_hasBackButtonStartPart) {
+ startButtonsOffset += m_stepperSize;
+ buttonsWidth += m_stepperSize;
}
if (m_hasBackButtonEndPart)
- alternateButtonWidth += m_stepperSize;
+ buttonsWidth += m_stepperSize;
+ if (m_hasForwardButtonEndPart)
+ buttonsWidth += m_stepperSize;
if (scrollbar->orientation() == HorizontalScrollbar) {
// Once the scrollbar becomes smaller than the natural size of the
// two buttons, the track disappears.
if (scrollbar->width() < 2 * thickness)
return IntRect();
- return IntRect(scrollbar->x() + movementAxisPadding + alternateButtonOffset, scrollbar->y(),
- scrollbar->width() - (2 * movementAxisPadding) - alternateButtonWidth, thickness);
+ return IntRect(scrollbar->x() + movementAxisPadding + startButtonsOffset, scrollbar->y(),
+ scrollbar->width() - (2 * movementAxisPadding) - buttonsWidth, thickness);
}
if (scrollbar->height() < 2 * thickness)
return IntRect();
- return IntRect(scrollbar->x(), scrollbar->y() + movementAxisPadding + alternateButtonOffset,
- thickness, scrollbar->height() - (2 * movementAxisPadding) - alternateButtonWidth);
+ return IntRect(scrollbar->x(), scrollbar->y() + movementAxisPadding + startButtonsOffset,
+ thickness, scrollbar->height() - (2 * movementAxisPadding) - buttonsWidth);
}
IntRect ScrollbarThemeGtk::thumbRect(Scrollbar* scrollbar, const IntRect& unconstrainedTrackRect)
diff --git a/Source/WebCore/platform/gtk/ScrollbarThemeGtk.h b/Source/WebCore/platform/gtk/ScrollbarThemeGtk.h
index 323d55442..45e093b1e 100644
--- a/Source/WebCore/platform/gtk/ScrollbarThemeGtk.h
+++ b/Source/WebCore/platform/gtk/ScrollbarThemeGtk.h
@@ -72,6 +72,8 @@ protected:
int m_minThumbLength;
gboolean m_troughUnderSteppers;
gboolean m_hasForwardButtonStartPart;
+ gboolean m_hasForwardButtonEndPart;
+ gboolean m_hasBackButtonStartPart;
gboolean m_hasBackButtonEndPart;
};
diff --git a/Source/WebCore/platform/gtk/ScrollbarThemeGtk2.cpp b/Source/WebCore/platform/gtk/ScrollbarThemeGtk2.cpp
index 1ab88504b..729bd124d 100644
--- a/Source/WebCore/platform/gtk/ScrollbarThemeGtk2.cpp
+++ b/Source/WebCore/platform/gtk/ScrollbarThemeGtk2.cpp
@@ -58,6 +58,8 @@ void ScrollbarThemeGtk::updateThemeProperties()
"trough_border", &m_troughBorderWidth,
"stepper-size", &m_stepperSize,
"trough-under-steppers", &m_troughUnderSteppers,
+ "has-backward-stepper", &m_hasBackButtonStartPart,
+ "has-forward-stepper", &m_hasForwardButtonEndPart,
"has-secondary-forward-stepper", &m_hasForwardButtonStartPart,
"has-secondary-backward-stepper", &m_hasBackButtonEndPart, NULL);
m_minThumbLength = gtk_range_get_min_slider_size(GTK_RANGE(scrollbar));
diff --git a/Source/WebCore/platform/gtk/ScrollbarThemeGtk3.cpp b/Source/WebCore/platform/gtk/ScrollbarThemeGtk3.cpp
index e0e2e66ff..4c33e66db 100644
--- a/Source/WebCore/platform/gtk/ScrollbarThemeGtk3.cpp
+++ b/Source/WebCore/platform/gtk/ScrollbarThemeGtk3.cpp
@@ -58,6 +58,8 @@ void ScrollbarThemeGtk::updateThemeProperties()
"stepper-size", &m_stepperSize,
"stepper-spacing", &m_stepperSpacing,
"trough-under-steppers", &m_troughUnderSteppers,
+ "has-backward-stepper", &m_hasBackButtonStartPart,
+ "has-forward-stepper", &m_hasForwardButtonEndPart,
"has-secondary-backward-stepper", &m_hasBackButtonEndPart,
"has-secondary-forward-stepper", &m_hasForwardButtonStartPart,
NULL);
diff --git a/Source/WebCore/platform/image-decoders/ImageDecoder.h b/Source/WebCore/platform/image-decoders/ImageDecoder.h
index 95688e7a1..9d9b34f60 100644
--- a/Source/WebCore/platform/image-decoders/ImageDecoder.h
+++ b/Source/WebCore/platform/image-decoders/ImageDecoder.h
@@ -47,7 +47,6 @@
namespace WebCore {
- // FIXME: Do we want better encapsulation?
typedef Vector<char> ColorProfile;
// ImageFrame represents the decoded image data. This buffer is what all
@@ -301,6 +300,22 @@ namespace WebCore {
void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; }
bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; }
+ enum { iccColorProfileHeaderLength = 128 };
+
+ static bool rgbColorProfile(const char* profileData, unsigned profileLength)
+ {
+ ASSERT(profileLength >= iccColorProfileHeaderLength);
+
+ return !memcmp(&profileData[16], "RGB ", 4);
+ }
+
+ static bool inputDeviceColorProfile(const char* profileData, unsigned profileLength)
+ {
+ ASSERT(profileLength >= iccColorProfileHeaderLength);
+
+ return !memcmp(&profileData[12], "mntr", 4) || !memcmp(&profileData[12], "scnr", 4);
+ }
+
// Sets the "decode failure" flag. For caller convenience (since so
// many callers want to return false after calling this), returns false
// to enable easy tailcalling. Subclasses may override this to also
diff --git a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
index 0cbdd0453..5b42490ab 100644
--- a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
@@ -56,16 +56,12 @@
#endif
extern "C" {
-
#include "jpeglib.h"
-
#if USE(ICCJPEG)
#include "iccjpeg.h"
#endif
-
-}
-
#include <setjmp.h>
+}
#if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN)
#define ASSUME_LITTLE_ENDIAN 0
@@ -73,12 +69,12 @@ extern "C" {
#define ASSUME_LITTLE_ENDIAN 1
#endif
-#if defined(JCS_EXTENSIONS) && ASSUME_LITTLE_ENDIAN
+#if defined(JCS_ALPHA_EXTENSIONS) && ASSUME_LITTLE_ENDIAN
#define TURBO_JPEG_RGB_SWIZZLE
#if USE(SKIA) && (!SK_R32_SHIFT && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16)
-inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_EXT_RGBX; }
+inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_EXT_RGBA; }
#else
-inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_EXT_BGRX; }
+inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_EXT_BGRA; }
#endif
inline bool turboSwizzled(J_COLOR_SPACE colorSpace) { return colorSpace == rgbOutputColorSpace(); }
#else
@@ -98,7 +94,7 @@ enum jstate {
JPEG_DECOMPRESS_PROGRESSIVE, // Output progressive pixels
JPEG_DECOMPRESS_SEQUENTIAL, // Output sequential pixels
JPEG_DONE,
- JPEG_ERROR
+ JPEG_ERROR
};
void init_source(j_decompress_ptr jd);
@@ -115,32 +111,6 @@ struct decoder_source_mgr {
JPEGImageReader* decoder;
};
-#if USE(ICCJPEG)
-
-#define iccProfileHeaderSize 128
-
-static bool rgbColorProfile(const char* profileData, unsigned profileLength)
-{
- ASSERT(profileLength >= iccProfileHeaderSize);
-
- if (!memcmp(&profileData[16], "RGB ", 4))
- return true;
- return false;
-}
-
-static bool inputDeviceColorProfile(const char* profileData, unsigned profileLength)
-{
- ASSERT(profileLength >= iccProfileHeaderSize);
-
- if (!memcmp(&profileData[12], "mntr", 4))
- return true;
- if (!memcmp(&profileData[12], "scnr", 4))
- return true;
- return false;
-}
-
-#endif
-
static ColorProfile readColorProfile(jpeg_decompress_struct* info)
{
#if USE(ICCJPEG)
@@ -153,11 +123,11 @@ static ColorProfile readColorProfile(jpeg_decompress_struct* info)
// Only accept RGB color profiles from input class devices.
bool ignoreProfile = false;
char* profileData = reinterpret_cast<char*>(profile);
- if (profileLength < iccProfileHeaderSize)
+ if (profileLength < ImageDecoder::iccColorProfileHeaderLength)
ignoreProfile = true;
- else if (!rgbColorProfile(profileData, profileLength))
+ else if (!ImageDecoder::rgbColorProfile(profileData, profileLength))
ignoreProfile = true;
- else if (!inputDeviceColorProfile(profileData, profileLength))
+ else if (!ImageDecoder::inputDeviceColorProfile(profileData, profileLength))
ignoreProfile = true;
ColorProfile colorProfile;
@@ -181,14 +151,14 @@ public:
, m_samples(0)
{
memset(&m_info, 0, sizeof(jpeg_decompress_struct));
-
+
// We set up the normal JPEG error routines, then override error_exit.
m_info.err = jpeg_std_error(&m_err.pub);
m_err.pub.error_exit = error_exit;
// Allocate and initialize JPEG decompression object.
jpeg_create_decompress(&m_info);
-
+
decoder_source_mgr* src = 0;
if (!m_info.src) {
src = (decoder_source_mgr*)fastCalloc(sizeof(decoder_source_mgr), 1);
@@ -254,7 +224,7 @@ public:
skipBytes(m_bytesToSkip);
m_bufferLength = data.size();
-
+
// We need to do the setjmp here. Otherwise bad things will happen
if (setjmp(m_err.setjmp_buffer))
return m_decoder->setFailed();
@@ -337,10 +307,10 @@ public:
case JPEG_DECOMPRESS_SEQUENTIAL:
if (m_state == JPEG_DECOMPRESS_SEQUENTIAL) {
-
+
if (!m_decoder->outputScanlines())
return false; // I/O suspension.
-
+
// If we've completed image output...
ASSERT(m_info.output_scanline == m_info.output_height);
m_state = JPEG_DONE;
diff --git a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
index fcef1335f..c50ebe957 100644
--- a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
@@ -227,8 +227,10 @@ bool PNGImageDecoder::setFailed()
return ImageDecoder::setFailed();
}
-static ColorProfile readColorProfile(png_structp png, png_infop info)
+static void readColorProfile(png_structp png, png_infop info, ColorProfile& colorProfile)
{
+ ASSERT(colorProfile.isEmpty());
+
#ifdef PNG_iCCP_SUPPORTED
char* profileName;
int compressionType;
@@ -238,13 +240,22 @@ static ColorProfile readColorProfile(png_structp png, png_infop info)
png_bytep profile;
#endif
png_uint_32 profileLength;
- if (png_get_iCCP(png, info, &profileName, &compressionType, &profile, &profileLength)) {
- ColorProfile colorProfile;
- colorProfile.append(profile, profileLength);
- return colorProfile;
- }
+ if (!png_get_iCCP(png, info, &profileName, &compressionType, &profile, &profileLength))
+ return;
+
+ // Only accept RGB color profiles from input class devices.
+ bool ignoreProfile = false;
+ char* profileData = reinterpret_cast<char*>(profile);
+ if (profileLength < ImageDecoder::iccColorProfileHeaderLength)
+ ignoreProfile = true;
+ else if (!ImageDecoder::rgbColorProfile(profileData, profileLength))
+ ignoreProfile = true;
+ else if (!ImageDecoder::inputDeviceColorProfile(profileData, profileLength))
+ ignoreProfile = true;
+
+ if (!ignoreProfile)
+ colorProfile.append(profileData, profileLength);
#endif
- return ColorProfile();
}
void PNGImageDecoder::headerAvailable()
@@ -253,13 +264,13 @@ void PNGImageDecoder::headerAvailable()
png_infop info = m_reader->infoPtr();
png_uint_32 width = png_get_image_width(png, info);
png_uint_32 height = png_get_image_height(png, info);
-
+
// Protect against large images.
if (width > cMaxPNGSize || height > cMaxPNGSize) {
longjmp(JMPBUF(png), 1);
return;
}
-
+
// We can fill in the size now that the header is available. Avoid memory
// corruption issues by neutering setFailed() during this call; if we don't
// do this, failures will cause |m_reader| to be deleted, and our jmpbuf
@@ -283,7 +294,7 @@ void PNGImageDecoder::headerAvailable()
// don't similarly transform the color profile. We'd either need to transform
// the color profile or we'd need to decode into a gray-scale image buffer and
// hand that to CoreGraphics.
- m_colorProfile = readColorProfile(png, info);
+ readColorProfile(png, info, m_colorProfile);
}
// The options we set here match what Mozilla does.
@@ -291,7 +302,7 @@ void PNGImageDecoder::headerAvailable()
// Expand to ensure we use 24-bit for RGB and 32-bit for RGBA.
if (colorType == PNG_COLOR_TYPE_PALETTE || (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8))
png_set_expand(png);
-
+
png_bytep trns = 0;
int trnsCount = 0;
if (png_get_valid(png, info, PNG_INFO_tRNS)) {
diff --git a/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp b/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
index c7fcbd589..f3fd769cd 100644
--- a/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
+++ b/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
@@ -158,7 +158,9 @@ void ImageFrame::setStatus(FrameStatus status)
if (m_status == FrameComplete) {
m_bitmap.setDataComplete(); // Tell the bitmap it's done.
#if PLATFORM(CHROMIUM) && OS(DARWIN)
- if (m_colorProfile.isEmpty())
+ // resolveColorSpace() and callees assume that the alpha channel is
+ // premultiplied, so don't apply the color profile if it isn't.
+ if (m_colorProfile.isEmpty() || (!m_premultiplyAlpha && hasAlpha()))
return;
RetainPtr<CGColorSpaceRef> cgColorSpace(AdoptCF, createColorSpace(m_colorProfile));
resolveColorSpace(m_bitmap.bitmap(), cgColorSpace.get());
diff --git a/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h b/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h
index 3ccab2516..61ea13953 100644
--- a/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h
+++ b/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h
@@ -42,7 +42,7 @@ public:
WEBPImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
virtual ~WEBPImageDecoder();
- virtual String filenameExtension() const { return "vp8"; }
+ virtual String filenameExtension() const { return "webp"; }
virtual bool isSizeAvailable();
virtual ImageFrame* frameBufferAtIndex(size_t index);
diff --git a/Source/WebCore/platform/image-encoders/skia/WEBPImageEncoder.cpp b/Source/WebCore/platform/image-encoders/skia/WEBPImageEncoder.cpp
index 631cf97cf..9cb24fc02 100644
--- a/Source/WebCore/platform/image-encoders/skia/WEBPImageEncoder.cpp
+++ b/Source/WebCore/platform/image-encoders/skia/WEBPImageEncoder.cpp
@@ -96,10 +96,10 @@ static bool encodePixels(IntSize imageSize, const unsigned char* pixels, bool pr
return false;
imageSize.clampNegativeToZero();
- if (!imageSize.width() || imageSize.width() > WEBPImageEncoder::MaximumImageDimension)
+ if (!imageSize.width() || imageSize.width() > WEBP_MAX_DIMENSION)
return false;
picture.width = imageSize.width();
- if (!imageSize.height() || imageSize.height() > WEBPImageEncoder::MaximumImageDimension)
+ if (!imageSize.height() || imageSize.height() > WEBP_MAX_DIMENSION)
return false;
picture.height = imageSize.height();
diff --git a/Source/WebCore/platform/image-encoders/skia/WEBPImageEncoder.h b/Source/WebCore/platform/image-encoders/skia/WEBPImageEncoder.h
index ad786f606..4ec928e8d 100644
--- a/Source/WebCore/platform/image-encoders/skia/WEBPImageEncoder.h
+++ b/Source/WebCore/platform/image-encoders/skia/WEBPImageEncoder.h
@@ -49,9 +49,6 @@ public:
// For callers: provide a reasonable compression quality default.
enum Quality { DefaultCompressionQuality = 80 };
-
- // Maximum image width or height allowed by the WEBP specification.
- enum Dimension { MaximumImageDimension = 16383 };
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/mac/ClipboardMac.h b/Source/WebCore/platform/mac/ClipboardMac.h
index 6c93ed5b9..24e9b8060 100644
--- a/Source/WebCore/platform/mac/ClipboardMac.h
+++ b/Source/WebCore/platform/mac/ClipboardMac.h
@@ -30,13 +30,8 @@
#include "Clipboard.h"
#include <wtf/RetainPtr.h>
-#ifdef __OBJC__
-@class NSImage;
-@class NSPasteboard;
-#else
-class NSImage;
-class NSPasteboard;
-#endif
+OBJC_CLASS NSImage;
+OBJC_CLASS NSPasteboard;
namespace WebCore {
diff --git a/Source/WebCore/platform/mac/ClipboardMac.mm b/Source/WebCore/platform/mac/ClipboardMac.mm
index ef759fb6b..2806fc625 100644
--- a/Source/WebCore/platform/mac/ClipboardMac.mm
+++ b/Source/WebCore/platform/mac/ClipboardMac.mm
@@ -68,13 +68,13 @@ bool ClipboardMac::hasData()
static RetainPtr<NSString> cocoaTypeFromHTMLClipboardType(const String& type)
{
- String qType = type.stripWhiteSpace();
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dom-datatransfer-setdata
+ String qType = type.lower();
- // two special cases for IE compatibility
- if (qType == "Text")
- return NSStringPboardType;
- if (qType == "URL")
- return NSURLPboardType;
+ if (qType == "text")
+ qType = "text/plain";
+ if (qType == "url")
+ qType = "text/uri-list";
// Ignore any trailing charset - JS strings are Unicode, which encapsulates the charset issue
if (qType == "text/plain" || qType.startsWith("text/plain;"))
@@ -82,7 +82,7 @@ static RetainPtr<NSString> cocoaTypeFromHTMLClipboardType(const String& type)
if (qType == "text/uri-list")
// special case because UTI doesn't work with Cocoa's URL type
return NSURLPboardType; // note special case in getData to read NSFilenamesType
-
+
// Try UTI now
NSString *mimeType = qType;
RetainPtr<CFStringRef> utiType(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (CFStringRef)mimeType, NULL));
@@ -218,8 +218,8 @@ String ClipboardMac::getData(const String& type, bool& success) const
// Grab the value off the pasteboard corresponding to the cocoaType
if ([cocoaType.get() isEqualToString:NSURLPboardType]) {
- // "URL" and "text/url-list" both map to NSURLPboardType in cocoaTypeFromHTMLClipboardType(), "URL" only wants the first URL
- bool onlyFirstURL = (type == "URL");
+ // "url" and "text/url-list" both map to NSURLPboardType in cocoaTypeFromHTMLClipboardType(), "url" only wants the first URL
+ bool onlyFirstURL = (equalIgnoringCase(type, "url"));
NSArray *absoluteURLs = absoluteURLsFromPasteboard(m_pasteboard.get(), onlyFirstURL);
cocoaValue = [absoluteURLs componentsJoinedByString:@"\n"];
} else if ([cocoaType.get() isEqualToString:NSStringPboardType]) {
@@ -367,19 +367,22 @@ void ClipboardMac::writeRange(Range* range, Frame* frame)
{
ASSERT(range);
ASSERT(frame);
- Pasteboard::writeSelection(m_pasteboard.get(), 0, range, frame->editor()->smartInsertDeleteEnabled() && frame->selection()->granularity() == WordGranularity, frame);
+ Pasteboard pasteboard([m_pasteboard.get() name]);
+ pasteboard.writeSelectionForTypes(nil, range, frame->editor()->smartInsertDeleteEnabled() && frame->selection()->granularity() == WordGranularity, frame);
}
void ClipboardMac::writePlainText(const String& text)
{
- Pasteboard::writePlainText(m_pasteboard.get(), text);
+ Pasteboard pasteboard([m_pasteboard.get() name]);
+ pasteboard.writePlainText(text);
}
void ClipboardMac::writeURL(const KURL& url, const String& title, Frame* frame)
{
ASSERT(frame);
ASSERT(m_pasteboard);
- Pasteboard::writeURL(m_pasteboard.get(), nil, url, title, frame);
+ Pasteboard pasteboard([m_pasteboard.get() name]);
+ pasteboard.writeURLForTypes(nil, url, title, frame);
}
#if ENABLE(DRAG_SUPPORT)
diff --git a/Source/WebCore/platform/mac/DragDataMac.mm b/Source/WebCore/platform/mac/DragDataMac.mm
index fd9f60a70..d6f4155c5 100644
--- a/Source/WebCore/platform/mac/DragDataMac.mm
+++ b/Source/WebCore/platform/mac/DragDataMac.mm
@@ -105,7 +105,7 @@ bool DragData::containsPlainText() const
String DragData::asPlainText(Frame *frame) const
{
- Pasteboard pasteboard(m_pasteboard.get());
+ Pasteboard pasteboard([m_pasteboard.get() name]);
return pasteboard.plainText(frame);
}
@@ -157,13 +157,13 @@ String DragData::asURL(Frame* frame, FilenameConversionPolicy filenamePolicy, St
if (NSString *URLTitleString = [m_pasteboard.get() stringForType:WebURLNamePboardType])
*title = URLTitleString;
}
- Pasteboard pasteboard(m_pasteboard.get());
+ Pasteboard pasteboard([m_pasteboard.get() name]);
return pasteboard.asURL(frame);
}
PassRefPtr<DocumentFragment> DragData::asFragment(Frame* frame, PassRefPtr<Range> range, bool allowPlainText, bool& chosePlainText) const
{
- Pasteboard pasteboard(m_pasteboard.get());
+ Pasteboard pasteboard([m_pasteboard.get() name]);
return pasteboard.documentFragment(frame, range, allowPlainText, chosePlainText);
}
diff --git a/Source/WebCore/platform/mac/HTMLConverter.mm b/Source/WebCore/platform/mac/HTMLConverter.mm
index ef4ca3a24..5ce5446eb 100644
--- a/Source/WebCore/platform/mac/HTMLConverter.mm
+++ b/Source/WebCore/platform/mac/HTMLConverter.mm
@@ -1693,6 +1693,8 @@ static NSInteger _colCompare(id block1, id block2, void *)
if (!renderer)
continue;
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 (style->visitedDependentColor(CSSPropertyColor).alpha())
diff --git a/Source/WebCore/platform/mac/KURLMac.mm b/Source/WebCore/platform/mac/KURLMac.mm
index bc20f3828..a5d15f5ea 100644
--- a/Source/WebCore/platform/mac/KURLMac.mm
+++ b/Source/WebCore/platform/mac/KURLMac.mm
@@ -42,22 +42,11 @@ KURL::KURL(NSURL *url)
}
CFIndex bytesLength = CFURLGetBytes(reinterpret_cast<CFURLRef>(url), 0, 0);
- Vector<char, 512> buffer(bytesLength + 6); // 5 for "file:", 1 for null character to end C string
- char* bytes = &buffer[5];
+ Vector<char, 512> buffer(bytesLength + 1);
+ char* bytes = &buffer[0];
CFURLGetBytes(reinterpret_cast<CFURLRef>(url), reinterpret_cast<UInt8*>(bytes), bytesLength);
bytes[bytesLength] = '\0';
- if (bytes[0] != '/') {
- parse(bytes);
- return;
- }
-
- buffer[0] = 'f';
- buffer[1] = 'i';
- buffer[2] = 'l';
- buffer[3] = 'e';
- buffer[4] = ':';
-
- parse(buffer.data());
+ parse(bytes);
}
KURL::operator NSURL *() const
diff --git a/Source/WebCore/platform/mac/Language.mm b/Source/WebCore/platform/mac/Language.mm
index 8e01f06bc..78ff1dd31 100644
--- a/Source/WebCore/platform/mac/Language.mm
+++ b/Source/WebCore/platform/mac/Language.mm
@@ -30,11 +30,12 @@
#import "WebCoreSystemInterface.h"
#import <wtf/Assertions.h>
#import <wtf/MainThread.h>
+#import <wtf/RetainPtr.h>
#import <wtf/text/WTFString.h>
using namespace WebCore;
-static NSString *preferredLanguageCode;
+static BOOL useCachedPreferredLanguages;
@interface WebLanguageChangeObserver : NSObject {
}
@@ -46,8 +47,7 @@ static NSString *preferredLanguageCode;
{
ASSERT(isMainThread());
- [preferredLanguageCode release];
- preferredLanguageCode = nil;
+ useCachedPreferredLanguages = NO;
languageDidChange();
}
@@ -85,23 +85,28 @@ static NSString *createHTTPStyleLanguageCode(NSString *languageCode)
return httpStyleLanguageCode;
}
-String platformDefaultLanguage()
+Vector<String> platformUserPreferredLanguages()
{
+ DEFINE_STATIC_LOCAL(Vector<String>, userPreferredLanguages, ());
+
ASSERT(isMainThread());
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- if (!preferredLanguageCode) {
- [[NSUserDefaults standardUserDefaults] synchronize];
- NSArray *languages = [[NSUserDefaults standardUserDefaults] stringArrayForKey:@"AppleLanguages"];
- if (![languages count])
- preferredLanguageCode = @"en";
- else
- preferredLanguageCode = createHTTPStyleLanguageCode([languages objectAtIndex:0]);
+ if (!useCachedPreferredLanguages) {
+ useCachedPreferredLanguages = YES;
+ userPreferredLanguages.clear();
+
+ RetainPtr<CFArrayRef> languages(AdoptCF, CFLocaleCopyPreferredLanguages());
+ CFIndex languageCount = CFArrayGetCount(languages.get());
+ if (!languageCount)
+ userPreferredLanguages.append("en");
+ else {
+ for (CFIndex i = 0; i < languageCount; i++)
+ userPreferredLanguages.append(createHTTPStyleLanguageCode((NSString *)CFArrayGetValueAtIndex(languages.get(), i)));
+ }
}
- NSString *code = [[preferredLanguageCode retain] autorelease];
-
#if !PLATFORM(IOS)
static bool languageChangeObserverAdded;
if (!languageChangeObserverAdded) {
@@ -112,11 +117,12 @@ String platformDefaultLanguage()
languageChangeObserverAdded = true;
}
#endif // !PLATFORM(IOS)
-
- return code;
+
+ return userPreferredLanguages;
END_BLOCK_OBJC_EXCEPTIONS;
- return String();
+
+ return Vector<String>();
}
}
diff --git a/Source/WebCore/platform/mac/LocalCurrentGraphicsContext.h b/Source/WebCore/platform/mac/LocalCurrentGraphicsContext.h
index 0907fac52..d4df7e60e 100644
--- a/Source/WebCore/platform/mac/LocalCurrentGraphicsContext.h
+++ b/Source/WebCore/platform/mac/LocalCurrentGraphicsContext.h
@@ -24,11 +24,7 @@
#include "skia/ext/skia_utils_mac.h"
#endif
-#ifdef __OBJC__
-@class NSGraphicsContext;
-#else
-class NSGraphicsContext;
-#endif
+OBJC_CLASS NSGraphicsContext;
namespace WebCore {
diff --git a/Source/WebCore/platform/mac/LoggingMac.mm b/Source/WebCore/platform/mac/LoggingMac.mm
index 7f2ee1fd0..45cf6e5a4 100644
--- a/Source/WebCore/platform/mac/LoggingMac.mm
+++ b/Source/WebCore/platform/mac/LoggingMac.mm
@@ -72,6 +72,7 @@ void initializeLoggingChannelsIfNecessary()
initializeWithUserDefault(LogMedia);
initializeWithUserDefault(LogPlugins);
initializeWithUserDefault(LogArchives);
+ initializeWithUserDefault(LogWebAudio);
}
}
diff --git a/Source/WebCore/platform/mac/MemoryPressureHandlerMac.mm b/Source/WebCore/platform/mac/MemoryPressureHandlerMac.mm
index 838c12409..0e410d94f 100644
--- a/Source/WebCore/platform/mac/MemoryPressureHandlerMac.mm
+++ b/Source/WebCore/platform/mac/MemoryPressureHandlerMac.mm
@@ -32,7 +32,7 @@
#import <WebCore/PageCache.h>
#import <wtf/FastMalloc.h>
-#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) && !PLATFORM(IOS)
#import "WebCoreSystemInterface.h"
#import <notify.h>
#endif
@@ -41,6 +41,7 @@ namespace WebCore {
#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+#if !PLATFORM(IOS)
static dispatch_source_t _cache_event_source = 0;
static dispatch_source_t _timer_event_source = 0;
static int _notifyToken;
@@ -114,19 +115,25 @@ void MemoryPressureHandler::respondToMemoryPressure()
{
holdOff(s_secondsBetweenMemoryCleanup);
+ releaseMemory(false);
+}
+#endif // !PLATFORM(IOS)
+
+void MemoryPressureHandler::releaseMemory(bool critical)
+{
int savedPageCacheCapacity = pageCache()->capacity();
- pageCache()->setCapacity(pageCache()->pageCount()/2);
+ pageCache()->setCapacity(critical ? 0 : pageCache()->pageCount() / 2);
pageCache()->setCapacity(savedPageCacheCapacity);
pageCache()->releaseAutoreleasedPagesNow();
NSURLCache *nsurlCache = [NSURLCache sharedURLCache];
NSUInteger savedNsurlCacheMemoryCapacity = [nsurlCache memoryCapacity];
- [nsurlCache setMemoryCapacity:[nsurlCache currentMemoryUsage]/2];
+ [nsurlCache setMemoryCapacity:critical ? 0 : [nsurlCache currentMemoryUsage] / 2];
[nsurlCache setMemoryCapacity:savedNsurlCacheMemoryCapacity];
-
+
fontCache()->purgeInactiveFontData();
- memoryCache()->pruneToPercentage(0.5f);
+ memoryCache()->pruneToPercentage(critical ? 0 : 0.5f);
gcController().garbageCollectNow();
diff --git a/Source/WebCore/platform/mac/NSScrollerImpDetails.h b/Source/WebCore/platform/mac/NSScrollerImpDetails.h
index 7b3d14cfc..f06800c16 100644
--- a/Source/WebCore/platform/mac/NSScrollerImpDetails.h
+++ b/Source/WebCore/platform/mac/NSScrollerImpDetails.h
@@ -61,6 +61,7 @@ typedef NSInteger NSScrollerKnobStyle;
- (void)setDoubleValue:(double)doubleValue;
- (void)setKnobProportion:(CGFloat)proportion;
- (void)setKnobStyle:(NSScrollerKnobStyle)knobStyle;
+- (void)setExpanded:(BOOL)expanded;
- (void)setDelegate:(id)delegate;
- (void)setUiStateTransitionProgress:(CGFloat)uiStateTransitionProgress;
- (BOOL)isHorizontal;
diff --git a/Source/WebCore/platform/mac/PasteboardHelper.h b/Source/WebCore/platform/mac/PasteboardHelper.h
index 7bd62e5fb..6c1e844ea 100644
--- a/Source/WebCore/platform/mac/PasteboardHelper.h
+++ b/Source/WebCore/platform/mac/PasteboardHelper.h
@@ -34,11 +34,7 @@
#import <wtf/Forward.h>
-#ifdef __OBJC__
-@class DOMDocumentFragment;
-#else
-class DOMDocumentFragment;
-#endif
+OBJC_CLASS DOMDocumentFragment;
namespace WebCore {
diff --git a/Source/WebCore/platform/mac/PasteboardMac.mm b/Source/WebCore/platform/mac/PasteboardMac.mm
index 852e17a96..cb501e512 100644
--- a/Source/WebCore/platform/mac/PasteboardMac.mm
+++ b/Source/WebCore/platform/mac/PasteboardMac.mm
@@ -113,13 +113,14 @@ static NSArray* writableTypesForImage()
Pasteboard* Pasteboard::generalPasteboard()
{
- static Pasteboard* pasteboard = new Pasteboard([NSPasteboard generalPasteboard]);
+ static Pasteboard* pasteboard = new Pasteboard(NSGeneralPboard);
return pasteboard;
}
-Pasteboard::Pasteboard(NSPasteboard* pboard)
- : m_pasteboard(pboard)
+Pasteboard::Pasteboard(const String& pasteboardName)
+ : m_pasteboard([NSPasteboard pasteboardWithName:pasteboardName])
{
+ ASSERT(pasteboardName);
}
void Pasteboard::clear()
@@ -127,7 +128,7 @@ void Pasteboard::clear()
[m_pasteboard.get() declareTypes:[NSArray array] owner:nil];
}
-void Pasteboard::writeSelection(NSPasteboard* pasteboard, NSArray* pasteboardTypes, Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
+void Pasteboard::writeSelectionForTypes(NSArray* pasteboardTypes, Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
{
if (!WebArchivePboardType)
Pasteboard::generalPasteboard(); // Initializes pasteboard types.
@@ -158,26 +159,26 @@ void Pasteboard::writeSelection(NSPasteboard* pasteboard, NSArray* pasteboardTyp
#endif
NSArray *types = pasteboardTypes ? pasteboardTypes : selectionPasteboardTypes(canSmartCopyOrDelete, [attributedString containsAttachments]);
- [pasteboard declareTypes:types owner:nil];
+ [m_pasteboard.get() declareTypes:types owner:nil];
frame->editor()->client()->didSetSelectionTypesForPasteboard();
// Put HTML on the pasteboard.
if ([types containsObject:WebArchivePboardType]) {
RefPtr<LegacyWebArchive> archive = LegacyWebArchive::createFromSelection(frame);
RetainPtr<CFDataRef> data = archive ? archive->rawDataRepresentation() : 0;
- [pasteboard setData:(NSData *)data.get() forType:WebArchivePboardType];
+ [m_pasteboard.get() setData:(NSData *)data.get() forType:WebArchivePboardType];
}
// Put the attributed string on the pasteboard (RTF/RTFD format).
if ([types containsObject:NSRTFDPboardType]) {
NSData *RTFDData = [attributedString RTFDFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
- [pasteboard setData:RTFDData forType:NSRTFDPboardType];
+ [m_pasteboard.get() setData:RTFDData forType:NSRTFDPboardType];
}
if ([types containsObject:NSRTFPboardType]) {
if ([attributedString containsAttachments])
attributedString = attributedStringByStrippingAttachmentCharacters(attributedString);
NSData *RTFData = [attributedString RTFFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
- [pasteboard setData:RTFData forType:NSRTFPboardType];
+ [m_pasteboard.get() setData:RTFData forType:NSRTFPboardType];
}
// Put plain string on the pasteboard.
@@ -189,48 +190,34 @@ void Pasteboard::writeSelection(NSPasteboard* pasteboard, NSArray* pasteboardTyp
NSString *NonBreakingSpaceString = [NSString stringWithCharacters:&noBreakSpace length:1];
[s replaceOccurrencesOfString:NonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])];
- [pasteboard setString:s forType:NSStringPboardType];
+ [m_pasteboard.get() setString:s forType:NSStringPboardType];
[s release];
}
if ([types containsObject:WebSmartPastePboardType]) {
- [pasteboard setData:nil forType:WebSmartPastePboardType];
+ [m_pasteboard.get() setData:nil forType:WebSmartPastePboardType];
}
}
-void Pasteboard::writePlainText(NSPasteboard* pasteboard, const String& text)
+void Pasteboard::writePlainText(const String& text)
{
- NSArray *types = [NSArray arrayWithObject:NSStringPboardType];
- [pasteboard declareTypes:types owner:nil];
-
- [pasteboard setString:text forType:NSStringPboardType];
+ [m_pasteboard.get() declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
+ [m_pasteboard.get() setString:text forType:NSStringPboardType];
}
void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
{
- Pasteboard::writeSelection(m_pasteboard.get(), 0, selectedRange, canSmartCopyOrDelete, frame);
-}
-
-void Pasteboard::writePlainText(const String& text)
-{
- if (!WebArchivePboardType)
- Pasteboard::generalPasteboard(); // Initializes pasteboard types.
-
- NSArray *types = [NSArray arrayWithObject:NSStringPboardType];
- NSPasteboard *pasteboard = m_pasteboard.get();
- [pasteboard declareTypes:types owner:nil];
-
- [pasteboard setString:text forType:NSStringPboardType];
+ writeSelectionForTypes(nil, selectedRange, canSmartCopyOrDelete, frame);
}
-void Pasteboard::writeURL(NSPasteboard* pasteboard, NSArray* types, const KURL& url, const String& titleStr, Frame* frame)
+void Pasteboard::writeURLForTypes(NSArray* types, const KURL& url, const String& titleStr, Frame* frame)
{
if (!WebArchivePboardType)
Pasteboard::generalPasteboard(); // Initializes pasteboard types.
if (!types) {
types = writableTypesForURL();
- [pasteboard declareTypes:types owner:nil];
+ [m_pasteboard.get() declareTypes:types owner:nil];
}
ASSERT(!url.isEmpty());
@@ -246,23 +233,23 @@ void Pasteboard::writeURL(NSPasteboard* pasteboard, NSArray* types, const KURL&
}
if ([types containsObject:WebURLsWithTitlesPboardType])
- [pasteboard setPropertyList:[NSArray arrayWithObjects:[NSArray arrayWithObject:userVisibleString],
+ [m_pasteboard.get() setPropertyList:[NSArray arrayWithObjects:[NSArray arrayWithObject:userVisibleString],
[NSArray arrayWithObject:(NSString*)titleStr.stripWhiteSpace()],
nil]
forType:WebURLsWithTitlesPboardType];
if ([types containsObject:NSURLPboardType])
- [cocoaURL writeToPasteboard:pasteboard];
+ [cocoaURL writeToPasteboard:m_pasteboard.get()];
if ([types containsObject:WebURLPboardType])
- [pasteboard setString:userVisibleString forType:WebURLPboardType];
+ [m_pasteboard.get() setString:userVisibleString forType:WebURLPboardType];
if ([types containsObject:WebURLNamePboardType])
- [pasteboard setString:title forType:WebURLNamePboardType];
+ [m_pasteboard.get() setString:title forType:WebURLNamePboardType];
if ([types containsObject:NSStringPboardType])
- [pasteboard setString:userVisibleString forType:NSStringPboardType];
+ [m_pasteboard.get() setString:userVisibleString forType:NSStringPboardType];
}
void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame)
{
- Pasteboard::writeURL(m_pasteboard.get(), nil, url, titleStr, frame);
+ writeURLForTypes(nil, url, titleStr, frame);
}
static NSFileWrapper* fileWrapperForImage(CachedResource* resource, NSURL *url)
@@ -308,7 +295,7 @@ void Pasteboard::writeImage(Node* node, const KURL& url, const String& title)
NSArray* types = writableTypesForImage();
[m_pasteboard.get() declareTypes:types owner:nil];
- writeURL(m_pasteboard.get(), types, cocoaURL, nsStringNilIfEmpty(title), frame);
+ writeURLForTypes(types, cocoaURL, nsStringNilIfEmpty(title), frame);
Image* image = cachedImage->imageForRenderer(renderer);
ASSERT(image);
diff --git a/Source/WebCore/platform/mac/PlatformEventFactoryMac.h b/Source/WebCore/platform/mac/PlatformEventFactoryMac.h
index 12ede1fab..8c186dafd 100644
--- a/Source/WebCore/platform/mac/PlatformEventFactoryMac.h
+++ b/Source/WebCore/platform/mac/PlatformEventFactoryMac.h
@@ -46,10 +46,14 @@ public:
#endif
};
-// FIXME: This doesn't really belong here.
-
#if PLATFORM(MAC) && defined(__OBJC__)
+// FIXME: This doesn't really belong here.
IntPoint globalPoint(const NSPoint& windowPoint, NSWindow *);
+
+// FIXME: WebKit2 has a lot of code copy/pasted from PlatformEventFactoryMac in WebEventFactory. It should be carefully shared with WebCore.
+int windowsKeyCodeForKeyEvent(NSEvent*);
+String keyIdentifierForKeyEvent(NSEvent*);
+
#endif
} // namespace WebCore
diff --git a/Source/WebCore/platform/mac/PlatformEventFactoryMac.mm b/Source/WebCore/platform/mac/PlatformEventFactoryMac.mm
index 43623c712..f0ebf5cae 100644
--- a/Source/WebCore/platform/mac/PlatformEventFactoryMac.mm
+++ b/Source/WebCore/platform/mac/PlatformEventFactoryMac.mm
@@ -201,6 +201,11 @@ static PlatformWheelEventPhase phaseForEvent(NSEvent *event)
phase |= PlatformWheelEventPhaseEnded;
if ([event phase] & NSEventPhaseCancelled)
phase |= PlatformWheelEventPhaseCancelled;
+#if !defined(BUILDING_ON_LION)
+ if ([event momentumPhase] & NSEventPhaseMayBegin)
+ phase |= PlatformWheelEventPhaseMayBegin;
+#endif
+
return static_cast<PlatformWheelEventPhase>(phase);
#else
UNUSED_PARAM(event);
@@ -237,7 +242,7 @@ static inline String unmodifiedTextFromEvent(NSEvent* event)
return String([event charactersIgnoringModifiers]);
}
-static String keyIdentifierForKeyEvent(NSEvent* event)
+String keyIdentifierForKeyEvent(NSEvent* event)
{
if ([event type] == NSFlagsChanged)
switch ([event keyCode]) {
@@ -313,7 +318,7 @@ static bool isKeypadEvent(NSEvent* event)
return false;
}
-static int windowsKeyCodeForKeyEvent(NSEvent* event)
+int windowsKeyCodeForKeyEvent(NSEvent* event)
{
int code = 0;
// There are several kinds of characters for which we produce key code from char code:
diff --git a/Source/WebCore/platform/mac/PlatformScreenMac.mm b/Source/WebCore/platform/mac/PlatformScreenMac.mm
index 9065854c6..f14f1e2e3 100644
--- a/Source/WebCore/platform/mac/PlatformScreenMac.mm
+++ b/Source/WebCore/platform/mac/PlatformScreenMac.mm
@@ -64,16 +64,16 @@ bool screenIsMonochrome(Widget*)
// These functions scale between screen and page coordinates because JavaScript/DOM operations
// assume that the screen and the page share the same coordinate system.
-FloatRect screenRect(Widget* widget)
+FloatRect screenRect(FrameView* frameView)
{
- NSWindow *window = widget ? [widget->platformWidget() window] : nil;
- return toUserSpace([screenForWindow(window) frame], window);
+ NSWindow *window = frameView ? [frameView->platformWidget() window] : nil;
+ return toUserSpace([screenForWindow(window) frame], window, WebCore::deviceScaleFactor(frameView->frame()));
}
-FloatRect screenAvailableRect(Widget* widget)
+FloatRect screenAvailableRect(FrameView* frameView)
{
- NSWindow *window = widget ? [widget->platformWidget() window] : nil;
- return toUserSpace([screenForWindow(window) visibleFrame], window);
+ NSWindow *window = frameView ? [frameView->platformWidget() window] : nil;
+ return toUserSpace([screenForWindow(window) visibleFrame], window, WebCore::deviceScaleFactor(frameView->frame()));
}
NSScreen *screenForWindow(NSWindow *window)
@@ -89,29 +89,18 @@ NSScreen *screenForWindow(NSWindow *window)
return nil;
}
-static CGFloat windowScaleFactor(NSWindow *window)
-{
-#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
- return [window backingScaleFactor];
-#else
- return [window userSpaceScaleFactor];
-#endif
-}
-
-FloatRect toUserSpace(const NSRect& rect, NSWindow *destination)
+FloatRect toUserSpace(const NSRect& rect, NSWindow *destination, float deviceScaleFactor)
{
FloatRect userRect = rect;
userRect.setY(NSMaxY([screenForWindow(destination) frame]) - (userRect.y() + userRect.height())); // flip
- if (destination)
- userRect.scale(1 / windowScaleFactor(destination)); // scale down
+ userRect.scale(1 / deviceScaleFactor); // scale down
return userRect;
}
-NSRect toDeviceSpace(const FloatRect& rect, NSWindow *source)
+NSRect toDeviceSpace(const FloatRect& rect, NSWindow *source, float deviceScaleFactor)
{
FloatRect deviceRect = rect;
- if (source)
- deviceRect.scale(windowScaleFactor(source)); // scale up
+ deviceRect.scale(deviceScaleFactor); // scale up
deviceRect.setY(NSMaxY([screenForWindow(source) frame]) - (deviceRect.y() + deviceRect.height())); // flip
return deviceRect;
}
diff --git a/Source/WebCore/platform/mac/PopupMenuMac.h b/Source/WebCore/platform/mac/PopupMenuMac.h
index 8e21913a2..8dd6aff60 100644
--- a/Source/WebCore/platform/mac/PopupMenuMac.h
+++ b/Source/WebCore/platform/mac/PopupMenuMac.h
@@ -26,11 +26,7 @@
#include <wtf/RefCounted.h>
#include <wtf/RetainPtr.h>
-#ifdef __OBJC__
-@class NSPopUpButtonCell;
-#else
-class NSPopUpButtonCell;
-#endif
+OBJC_CLASS NSPopUpButtonCell;
namespace WebCore {
diff --git a/Source/WebCore/platform/mac/RunLoopMac.mm b/Source/WebCore/platform/mac/RunLoopMac.mm
new file mode 100644
index 000000000..46fa4c2cb
--- /dev/null
+++ b/Source/WebCore/platform/mac/RunLoopMac.mm
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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.
+ */
+
+#import "config.h"
+#import "RunLoop.h"
+
+#import <dispatch/dispatch.h>
+
+namespace WebCore {
+
+static RunLoop* s_mainRunLoop;
+
+void RunLoop::initializeMainRunLoop()
+{
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ s_mainRunLoop = new RunLoop(CFRunLoopGetMain());
+ });
+}
+
+RunLoop* RunLoop::current()
+{
+ if (pthread_main_np())
+ return RunLoop::main();
+
+ DEFINE_STATIC_LOCAL(WTF::ThreadSpecific<RunLoop>, runLoopData, ());
+ return &*runLoopData;
+}
+
+RunLoop* RunLoop::main()
+{
+ ASSERT(s_mainRunLoop);
+ return s_mainRunLoop;
+}
+
+void RunLoop::performWork(void* context)
+{
+ // Wrap main thread in an Autorelease pool. Sending messages can call
+ // into objc code and accumulate memory.
+ if (current() == main()) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ static_cast<RunLoop*>(context)->performWork();
+ [pool drain];
+ } else
+ static_cast<RunLoop*>(context)->performWork();
+}
+
+RunLoop::RunLoop()
+ : m_runLoop(CFRunLoopGetCurrent())
+ , m_nestingLevel(0)
+{
+ CFRunLoopSourceContext context = { 0, this, 0, 0, 0, 0, 0, 0, 0, performWork };
+ m_runLoopSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
+ CFRunLoopAddSource(m_runLoop, m_runLoopSource, kCFRunLoopCommonModes);
+}
+
+RunLoop::RunLoop(CFRunLoopRef runLoop)
+ : m_runLoop(runLoop)
+ , m_nestingLevel(0)
+{
+ CFRunLoopSourceContext context = { 0, this, 0, 0, 0, 0, 0, 0, 0, performWork };
+ m_runLoopSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
+ CFRunLoopAddSource(m_runLoop, m_runLoopSource, kCFRunLoopCommonModes);
+}
+
+RunLoop::~RunLoop()
+{
+ // FIXME: Tear down the work item queue here.
+ CFRunLoopSourceInvalidate(m_runLoopSource);
+ CFRelease(m_runLoopSource);
+}
+
+void RunLoop::run()
+{
+ current()->m_nestingLevel++;
+ if (current() == main() && current()->m_nestingLevel == 1) {
+ // Use -[NSApplication run] for the main run loop.
+ [NSApp run];
+ } else {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ CFRunLoopRun();
+ [pool drain];
+ }
+ current()->m_nestingLevel--;
+}
+
+void RunLoop::runForDuration(double duration)
+{
+ CFRunLoopRunInMode(kCFRunLoopDefaultMode, duration, true);
+}
+
+void RunLoop::stop()
+{
+ ASSERT(m_runLoop == CFRunLoopGetCurrent());
+
+ if (m_runLoop == main()->m_runLoop && m_nestingLevel == 1) {
+ [NSApp stop:nil];
+ NSEvent *event = [NSEvent otherEventWithType:NSApplicationDefined
+ location:NSMakePoint(0, 0)
+ modifierFlags:0
+ timestamp:0.0
+ windowNumber:0
+ context:nil
+ subtype: 0
+ data1:0
+ data2:0];
+ [NSApp postEvent:event atStart:true];
+ } else
+ CFRunLoopStop(m_runLoop);
+}
+
+void RunLoop::wakeUp()
+{
+ CFRunLoopSourceSignal(m_runLoopSource);
+ CFRunLoopWakeUp(m_runLoop);
+}
+
+// RunLoop::Timer
+
+void RunLoop::TimerBase::timerFired(CFRunLoopTimerRef, void* context)
+{
+ TimerBase* timer = static_cast<TimerBase*>(context);
+
+ // Wrap main thread in an Autorelease pool. The timer can call
+ // into objc code and accumulate memory outside of the main event loop.
+ if (current() == main()) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ timer->fired();
+ [pool drain];
+ } else
+ timer->fired();
+}
+
+RunLoop::TimerBase::TimerBase(RunLoop* runLoop)
+ : m_runLoop(runLoop)
+ , m_timer(0)
+{
+}
+
+RunLoop::TimerBase::~TimerBase()
+{
+ stop();
+}
+
+void RunLoop::TimerBase::start(double nextFireInterval, bool repeat)
+{
+ if (m_timer)
+ stop();
+
+ CFRunLoopTimerContext context = { 0, this, 0, 0, 0 };
+ CFTimeInterval repeatInterval = repeat ? nextFireInterval : 0;
+ m_timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + nextFireInterval, repeatInterval, 0, 0, timerFired, &context);
+ CFRunLoopAddTimer(m_runLoop->m_runLoop, m_timer, kCFRunLoopCommonModes);
+}
+
+void RunLoop::TimerBase::stop()
+{
+ if (!m_timer)
+ return;
+
+ CFRunLoopTimerInvalidate(m_timer);
+ CFRelease(m_timer);
+ m_timer = 0;
+}
+
+bool RunLoop::TimerBase::isActive() const
+{
+ return m_timer && CFRunLoopTimerIsValid(m_timer);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/mac/ScrollAnimatorMac.h b/Source/WebCore/platform/mac/ScrollAnimatorMac.h
index 94383ca5e..c8d9b232a 100644
--- a/Source/WebCore/platform/mac/ScrollAnimatorMac.h
+++ b/Source/WebCore/platform/mac/ScrollAnimatorMac.h
@@ -36,15 +36,9 @@
#include "Timer.h"
#include <wtf/RetainPtr.h>
-#ifdef __OBJC__
-@class WebScrollAnimationHelperDelegate;
-@class WebScrollbarPainterControllerDelegate;
-@class WebScrollbarPainterDelegate;
-#else
-class WebScrollAnimationHelperDelegate;
-class WebScrollbarPainterControllerDelegate;
-class WebScrollbarPainterDelegate;
-#endif
+OBJC_CLASS WebScrollAnimationHelperDelegate;
+OBJC_CLASS WebScrollbarPainterControllerDelegate;
+OBJC_CLASS WebScrollbarPainterDelegate;
typedef id ScrollbarPainterController;
@@ -90,9 +84,6 @@ private:
#if ENABLE(RUBBER_BANDING)
virtual bool handleWheelEvent(const PlatformWheelEvent&) OVERRIDE;
-#if ENABLE(GESTURE_EVENTS)
- virtual void handleGestureEvent(const PlatformGestureEvent&);
-#endif
#endif
virtual void cancelAnimations();
@@ -118,6 +109,8 @@ private:
virtual void didAddHorizontalScrollbar(Scrollbar*);
virtual void willRemoveHorizontalScrollbar(Scrollbar*);
+ virtual bool shouldScrollbarParticipateInHitTesting(Scrollbar*);
+
float adjustScrollXPositionIfNecessary(float) const;
float adjustScrollYPositionIfNecessary(float) const;
FloatPoint adjustScrollPositionIfNecessary(const FloatPoint&) const;
@@ -127,31 +120,23 @@ private:
#if ENABLE(RUBBER_BANDING)
/// ScrollElasticityControllerClient member functions.
virtual IntSize stretchAmount() OVERRIDE;
+ virtual bool allowsHorizontalStretching() OVERRIDE;
+ virtual bool allowsVerticalStretching() OVERRIDE;
virtual bool pinnedInDirection(const FloatSize&) OVERRIDE;
virtual bool canScrollHorizontally() OVERRIDE;
virtual bool canScrollVertically() OVERRIDE;
+ virtual bool shouldRubberBandInDirection(ScrollDirection) OVERRIDE;
virtual WebCore::IntPoint absoluteScrollPosition() OVERRIDE;
virtual void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) OVERRIDE;
virtual void immediateScrollBy(const FloatSize&) OVERRIDE;
virtual void startSnapRubberbandTimer() OVERRIDE;
virtual void stopSnapRubberbandTimer() OVERRIDE;
- bool allowsVerticalStretching() const;
- bool allowsHorizontalStretching() const;
bool pinnedInDirection(float deltaX, float deltaY);
- void snapRubberBand();
void snapRubberBandTimerFired(Timer<ScrollAnimatorMac>*);
- bool smoothScrollWithEvent(const PlatformWheelEvent&);
- void beginScrollGesture();
- void endScrollGesture();
ScrollElasticityController m_scrollElasticityController;
Timer<ScrollAnimatorMac> m_snapRubberBandTimer;
-
- bool m_scrollerInitiallyPinnedOnLeft;
- bool m_scrollerInitiallyPinnedOnRight;
- int m_cumulativeHorizontalScroll;
- bool m_didCumulativeHorizontalScrollEverSwitchToOppositeDirectionOfPin;
#endif
bool m_haveScrolledSincePageLoad;
diff --git a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm b/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
index 4011f33e8..7bed38f1b 100644
--- a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
+++ b/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
@@ -40,20 +40,12 @@
#include "ScrollbarTheme.h"
#include "ScrollbarThemeMac.h"
#include "WebCoreSystemInterface.h"
-#include <sys/time.h>
-#include <sys/sysctl.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/UnusedParam.h>
using namespace WebCore;
using namespace std;
-#ifdef BUILDING_ON_LEOPARD
-@interface NSProcessInfo (ScrollAnimatorMacExt)
-- (NSTimeInterval)systemUptime;
-@end
-#endif
-
static bool supportsUIStateTransitionProgress()
{
// FIXME: This is temporary until all platforms that support ScrollbarPainter support this part of the API.
@@ -75,31 +67,6 @@ static ScrollbarPainter scrollbarPainterForScrollbar(Scrollbar* scrollbar)
return nil;
}
-#if ENABLE(RUBBER_BANDING)
-static NSTimeInterval systemUptime()
-{
- if ([[NSProcessInfo processInfo] respondsToSelector:@selector(systemUptime)])
- return [[NSProcessInfo processInfo] systemUptime];
-
- // Get how long system has been up. Found by looking getting "boottime" from the kernel.
- static struct timeval boottime = {0, 0};
- if (!boottime.tv_sec) {
- int mib[2] = {CTL_KERN, KERN_BOOTTIME};
- size_t size = sizeof(boottime);
- if (-1 == sysctl(mib, 2, &boottime, &size, 0, 0))
- boottime.tv_sec = 0;
- }
- struct timeval now;
- if (boottime.tv_sec && -1 != gettimeofday(&now, 0)) {
- struct timeval uptime;
- timersub(&now, &boottime, &uptime);
- NSTimeInterval result = uptime.tv_sec + (uptime.tv_usec / 1E+6);
- return result;
- }
- return 0;
-}
-#endif
-
@interface NSObject (ScrollAnimationHelperDetails)
- (id)initWithDelegate:(id)delegate;
- (void)_stopRun;
@@ -586,10 +553,6 @@ ScrollAnimatorMac::ScrollAnimatorMac(ScrollableArea* scrollableArea)
#if ENABLE(RUBBER_BANDING)
, m_scrollElasticityController(this)
, m_snapRubberBandTimer(this, &ScrollAnimatorMac::snapRubberBandTimerFired)
- , m_scrollerInitiallyPinnedOnLeft(false)
- , m_scrollerInitiallyPinnedOnRight(false)
- , m_cumulativeHorizontalScroll(0)
- , m_didCumulativeHorizontalScrollEverSwitchToOppositeDirectionOfPin(false)
#endif
, m_haveScrolledSincePageLoad(false)
, m_needsScrollerStyleUpdate(false)
@@ -742,8 +705,13 @@ void ScrollAnimatorMac::mouseMovedInContentArea() const
void ScrollAnimatorMac::mouseEnteredScrollbar(Scrollbar* scrollbar) const
{
+ // At this time, only legacy scrollbars needs to send notifications here.
+ if (recommendedScrollerStyle() != NSScrollerStyleLegacy)
+ return;
+
if (!scrollableArea()->isOnActivePage())
return;
+
if (isScrollbarOverlayAPIAvailable()) {
if (!supportsUIStateTransitionProgress())
return;
@@ -754,8 +722,13 @@ void ScrollAnimatorMac::mouseEnteredScrollbar(Scrollbar* scrollbar) const
void ScrollAnimatorMac::mouseExitedScrollbar(Scrollbar* scrollbar) const
{
+ // At this time, only legacy scrollbars needs to send notifications here.
+ if (recommendedScrollerStyle() != NSScrollerStyleLegacy)
+ return;
+
if (!scrollableArea()->isOnActivePage())
return;
+
if (isScrollbarOverlayAPIAvailable()) {
if (!supportsUIStateTransitionProgress())
return;
@@ -886,6 +859,22 @@ void ScrollAnimatorMac::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
}
}
+bool ScrollAnimatorMac::shouldScrollbarParticipateInHitTesting(Scrollbar* scrollbar)
+{
+ // Non-overlay scrollbars should always participate in hit testing.
+ if (recommendedScrollerStyle() != NSScrollerStyleOverlay)
+ return true;
+
+ if (!isScrollbarOverlayAPIAvailable())
+ return true;
+
+ // Overlay scrollbars should participate in hit testing whenever they are at all visible.
+ ScrollbarPainter painter = scrollbarPainterForScrollbar(scrollbar);
+ if (!painter)
+ return false;
+ return [painter knobAlpha] > 0;
+}
+
void ScrollAnimatorMac::cancelAnimations()
{
m_haveScrolledSincePageLoad = false;
@@ -899,55 +888,6 @@ void ScrollAnimatorMac::cancelAnimations()
}
#if ENABLE(RUBBER_BANDING)
-
-static const float scrollVelocityZeroingTimeout = 0.10f;
-static const float rubberbandStiffness = 20;
-static const float rubberbandDirectionLockStretchRatio = 1;
-static const float rubberbandMinimumRequiredDeltaBeforeStretch = 10;
-static const float rubberbandAmplitude = 0.31f;
-static const float rubberbandPeriod = 1.6f;
-
-static float elasticDeltaForTimeDelta(float initialPosition, float initialVelocity, float elapsedTime)
-{
- float amplitude = rubberbandAmplitude;
- float period = rubberbandPeriod;
- float criticalDampeningFactor = expf((-elapsedTime * rubberbandStiffness) / period);
-
- return (initialPosition + (-initialVelocity * elapsedTime * amplitude)) * criticalDampeningFactor;
-}
-
-static float elasticDeltaForReboundDelta(float delta)
-{
- float stiffness = std::max(rubberbandStiffness, 1.0f);
- return delta / stiffness;
-}
-
-static float reboundDeltaForElasticDelta(float delta)
-{
- return delta * rubberbandStiffness;
-}
-
-static float scrollWheelMultiplier()
-{
- static float multiplier = -1;
- if (multiplier < 0) {
- multiplier = [[NSUserDefaults standardUserDefaults] floatForKey:@"NSScrollWheelMultiplier"];
- if (multiplier <= 0)
- multiplier = 1;
- }
- return multiplier;
-}
-
-static inline bool isScrollingLeftAndShouldNotRubberBand(const PlatformWheelEvent& wheelEvent, ScrollableArea* scrollableArea)
-{
- return wheelEvent.deltaX() > 0 && !scrollableArea->shouldRubberBandInDirection(ScrollLeft);
-}
-
-static inline bool isScrollingRightAndShouldNotRubberBand(const PlatformWheelEvent& wheelEvent, ScrollableArea* scrollableArea)
-{
- return wheelEvent.deltaX() < 0 && !scrollableArea->shouldRubberBandInDirection(ScrollRight);
-}
-
bool ScrollAnimatorMac::handleWheelEvent(const PlatformWheelEvent& wheelEvent)
{
m_haveScrolledSincePageLoad = true;
@@ -965,45 +905,18 @@ bool ScrollAnimatorMac::handleWheelEvent(const PlatformWheelEvent& wheelEvent)
} else {
if (!allowsHorizontalStretching())
return ScrollAnimator::handleWheelEvent(wheelEvent);
-
- if (m_scrollableArea->horizontalScrollbar()) {
- // If there is a scrollbar, we aggregate the wheel events to get an
- // overall trend of the scroll. If the direction of the scroll is ever
- // in the opposite direction of the pin location, then we switch the
- // boolean, and rubber band. That is, if we were pinned to the left,
- // and we ended up scrolling to the right, we rubber band.
- m_cumulativeHorizontalScroll += wheelEvent.deltaX();
- if (m_scrollerInitiallyPinnedOnLeft && m_cumulativeHorizontalScroll < 0)
- m_didCumulativeHorizontalScrollEverSwitchToOppositeDirectionOfPin = true;
- if (m_scrollerInitiallyPinnedOnRight && m_cumulativeHorizontalScroll > 0)
- m_didCumulativeHorizontalScrollEverSwitchToOppositeDirectionOfPin = true;
- }
-
- // After a gesture begins, we go through:
- // 1+ PlatformWheelEventPhaseNone
- // 0+ PlatformWheelEventPhaseChanged
- // 1 PlatformWheelEventPhaseEnded if there was at least one changed event
- if (wheelEvent.momentumPhase() == PlatformWheelEventPhaseNone && !m_didCumulativeHorizontalScrollEverSwitchToOppositeDirectionOfPin) {
- if ((isScrollingLeftAndShouldNotRubberBand(wheelEvent, m_scrollableArea) &&
- m_scrollerInitiallyPinnedOnLeft &&
- m_scrollableArea->isHorizontalScrollerPinnedToMinimumPosition()) ||
- (isScrollingRightAndShouldNotRubberBand(wheelEvent, m_scrollableArea) &&
- m_scrollerInitiallyPinnedOnRight &&
- m_scrollableArea->isHorizontalScrollerPinnedToMaximumPosition())) {
- return ScrollAnimator::handleWheelEvent(wheelEvent);
- }
- }
}
- return smoothScrollWithEvent(wheelEvent);
-}
+ bool didHandleEvent = m_scrollElasticityController.handleWheelEvent(wheelEvent);
-void ScrollAnimatorMac::handleGestureEvent(const PlatformGestureEvent& gestureEvent)
-{
- if (gestureEvent.type() == PlatformEvent::GestureScrollBegin)
- beginScrollGesture();
- else if (gestureEvent.type() == PlatformEvent::GestureScrollEnd)
- endScrollGesture();
+ if (didHandleEvent) {
+ if (wheelEvent.phase() == PlatformWheelEventPhaseBegan)
+ didBeginScrollGesture();
+ else if (wheelEvent.phase() == PlatformWheelEventPhaseEnded)
+ didEndScrollGesture();
+ }
+
+ return didHandleEvent;
}
bool ScrollAnimatorMac::pinnedInDirection(float deltaX, float deltaY)
@@ -1032,6 +945,42 @@ bool ScrollAnimatorMac::pinnedInDirection(float deltaX, float deltaY)
return false;
}
+bool ScrollAnimatorMac::allowsVerticalStretching()
+{
+ switch (m_scrollableArea->verticalScrollElasticity()) {
+ case ScrollElasticityAutomatic: {
+ Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
+ Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
+ return (((vScroller && vScroller->enabled()) || (!hScroller || !hScroller->enabled())));
+ }
+ case ScrollElasticityNone:
+ return false;
+ case ScrollElasticityAllowed:
+ return true;
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+bool ScrollAnimatorMac::allowsHorizontalStretching()
+{
+ switch (m_scrollableArea->horizontalScrollElasticity()) {
+ case ScrollElasticityAutomatic: {
+ Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
+ Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
+ return (((hScroller && hScroller->enabled()) || (!vScroller || !vScroller->enabled())));
+ }
+ case ScrollElasticityNone:
+ return false;
+ case ScrollElasticityAllowed:
+ return true;
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
IntSize ScrollAnimatorMac::stretchAmount()
{
return m_scrollableArea->overhangAmount();
@@ -1058,6 +1007,11 @@ bool ScrollAnimatorMac::canScrollVertically()
return scrollbar->enabled();
}
+bool ScrollAnimatorMac::shouldRubberBandInDirection(ScrollDirection direction)
+{
+ return m_scrollableArea->shouldRubberBandInDirection(direction);
+}
+
IntPoint ScrollAnimatorMac::absoluteScrollPosition()
{
return m_scrollableArea->visibleContentRect().location() + m_scrollableArea->scrollOrigin();
@@ -1093,313 +1047,9 @@ void ScrollAnimatorMac::stopSnapRubberbandTimer()
m_snapRubberBandTimer.stop();
}
-bool ScrollAnimatorMac::allowsVerticalStretching() const
-{
- switch (m_scrollableArea->verticalScrollElasticity()) {
- case ScrollElasticityAutomatic: {
- Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
- Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
- return (((vScroller && vScroller->enabled()) || (!hScroller || !hScroller->enabled())));
- }
- case ScrollElasticityNone:
- return false;
- case ScrollElasticityAllowed:
- return true;
- }
-
- ASSERT_NOT_REACHED();
- return false;
-}
-
-bool ScrollAnimatorMac::allowsHorizontalStretching() const
-{
- switch (m_scrollableArea->horizontalScrollElasticity()) {
- case ScrollElasticityAutomatic: {
- Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
- Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
- return (((hScroller && hScroller->enabled()) || (!vScroller || !vScroller->enabled())));
- }
- case ScrollElasticityNone:
- return false;
- case ScrollElasticityAllowed:
- return true;
- }
-
- ASSERT_NOT_REACHED();
- return false;
-}
-
-bool ScrollAnimatorMac::smoothScrollWithEvent(const PlatformWheelEvent& wheelEvent)
-{
- bool isMomentumScrollEvent = (wheelEvent.momentumPhase() != PlatformWheelEventPhaseNone);
- if (m_scrollElasticityController.m_ignoreMomentumScrolls && (isMomentumScrollEvent || m_scrollElasticityController.m_snapRubberbandTimerIsActive)) {
- if (wheelEvent.momentumPhase() == PlatformWheelEventPhaseEnded) {
- m_scrollElasticityController.m_ignoreMomentumScrolls = false;
- return true;
- }
- return false;
- }
-
- m_haveScrolledSincePageLoad = true;
-
- float deltaX = m_scrollElasticityController.m_overflowScrollDelta.width();
- float deltaY = m_scrollElasticityController.m_overflowScrollDelta.height();
-
- // Reset overflow values because we may decide to remove delta at various points and put it into overflow.
- m_scrollElasticityController.m_overflowScrollDelta = FloatSize();
-
- float eventCoalescedDeltaX = -wheelEvent.deltaX();
- float eventCoalescedDeltaY = -wheelEvent.deltaY();
-
- deltaX += eventCoalescedDeltaX;
- deltaY += eventCoalescedDeltaY;
-
- // Slightly prefer scrolling vertically by applying the = case to deltaY
- if (fabsf(deltaY) >= fabsf(deltaX))
- deltaX = 0;
- else
- deltaY = 0;
-
- bool isVerticallyStretched = false;
- bool isHorizontallyStretched = false;
- bool shouldStretch = false;
-
- IntSize stretchAmount = m_scrollElasticityController.m_client->stretchAmount();
-
- isHorizontallyStretched = stretchAmount.width();
- isVerticallyStretched = stretchAmount.height();
-
- PlatformWheelEventPhase phase = wheelEvent.momentumPhase();
-
- // If we are starting momentum scrolling then do some setup.
- if (!m_scrollElasticityController.m_momentumScrollInProgress && (phase == PlatformWheelEventPhaseBegan || phase == PlatformWheelEventPhaseChanged))
- m_scrollElasticityController.m_momentumScrollInProgress = true;
-
- CFTimeInterval timeDelta = wheelEvent.timestamp() - m_scrollElasticityController.m_lastMomentumScrollTimestamp;
- if (m_scrollElasticityController.m_inScrollGesture || m_scrollElasticityController.m_momentumScrollInProgress) {
- if (m_scrollElasticityController.m_lastMomentumScrollTimestamp && timeDelta > 0 && timeDelta < scrollVelocityZeroingTimeout) {
- m_scrollElasticityController.m_momentumVelocity.setWidth(eventCoalescedDeltaX / (float)timeDelta);
- m_scrollElasticityController.m_momentumVelocity.setHeight(eventCoalescedDeltaY / (float)timeDelta);
- m_scrollElasticityController.m_lastMomentumScrollTimestamp = wheelEvent.timestamp();
- } else {
- m_scrollElasticityController.m_lastMomentumScrollTimestamp = wheelEvent.timestamp();
- m_scrollElasticityController.m_momentumVelocity = FloatSize();
- }
-
- if (isVerticallyStretched) {
- if (!isHorizontallyStretched && pinnedInDirection(deltaX, 0)) {
- // Stretching only in the vertical.
- if (deltaY != 0 && (fabsf(deltaX / deltaY) < rubberbandDirectionLockStretchRatio))
- deltaX = 0;
- else if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
- m_scrollElasticityController.m_overflowScrollDelta.setWidth(m_scrollElasticityController.m_overflowScrollDelta.width() + deltaX);
- deltaX = 0;
- } else
- m_scrollElasticityController.m_overflowScrollDelta.setWidth(m_scrollElasticityController.m_overflowScrollDelta.width() + deltaX);
- }
- } else if (isHorizontallyStretched) {
- // Stretching only in the horizontal.
- if (pinnedInDirection(0, deltaY)) {
- if (deltaX != 0 && (fabsf(deltaY / deltaX) < rubberbandDirectionLockStretchRatio))
- deltaY = 0;
- else if (fabsf(deltaY) < rubberbandMinimumRequiredDeltaBeforeStretch) {
- m_scrollElasticityController.m_overflowScrollDelta.setHeight(m_scrollElasticityController.m_overflowScrollDelta.height() + deltaY);
- deltaY = 0;
- } else
- m_scrollElasticityController.m_overflowScrollDelta.setHeight(m_scrollElasticityController.m_overflowScrollDelta.height() + deltaY);
- }
- } else {
- // Not stretching at all yet.
- if (pinnedInDirection(deltaX, deltaY)) {
- if (fabsf(deltaY) >= fabsf(deltaX)) {
- if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
- m_scrollElasticityController.m_overflowScrollDelta.setWidth(m_scrollElasticityController.m_overflowScrollDelta.width() + deltaX);
- deltaX = 0;
- } else
- m_scrollElasticityController.m_overflowScrollDelta.setWidth(m_scrollElasticityController.m_overflowScrollDelta.width() + deltaX);
- }
- shouldStretch = true;
- }
- }
- }
-
- if (deltaX != 0 || deltaY != 0) {
- if (!(shouldStretch || isVerticallyStretched || isHorizontallyStretched)) {
- if (deltaY != 0) {
- deltaY *= scrollWheelMultiplier();
- m_scrollElasticityController.m_client->immediateScrollBy(FloatSize(0, deltaY));
- }
- if (deltaX != 0) {
- deltaX *= scrollWheelMultiplier();
- m_scrollElasticityController.m_client->immediateScrollBy(FloatSize(deltaX, 0));
- }
- } else {
- if (!allowsHorizontalStretching()) {
- deltaX = 0;
- eventCoalescedDeltaX = 0;
- } else if ((deltaX != 0) && !isHorizontallyStretched && !pinnedInDirection(deltaX, 0)) {
- deltaX *= scrollWheelMultiplier();
-
- m_scrollElasticityController.m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(deltaX, 0));
- deltaX = 0;
- }
-
- if (!allowsVerticalStretching()) {
- deltaY = 0;
- eventCoalescedDeltaY = 0;
- } else if ((deltaY != 0) && !isVerticallyStretched && !pinnedInDirection(0, deltaY)) {
- deltaY *= scrollWheelMultiplier();
-
- m_scrollElasticityController.m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(0, deltaY));
- deltaY = 0;
- }
-
- IntSize stretchAmount = m_scrollElasticityController.m_client->stretchAmount();
-
- if (m_scrollElasticityController.m_momentumScrollInProgress) {
- if ((pinnedInDirection(eventCoalescedDeltaX, eventCoalescedDeltaY) || (fabsf(eventCoalescedDeltaX) + fabsf(eventCoalescedDeltaY) <= 0)) && m_scrollElasticityController.m_lastMomentumScrollTimestamp) {
- m_scrollElasticityController.m_ignoreMomentumScrolls = true;
- m_scrollElasticityController.m_momentumScrollInProgress = false;
- snapRubberBand();
- }
- }
-
- m_scrollElasticityController.m_stretchScrollForce.setWidth(m_scrollElasticityController.m_stretchScrollForce.width() + deltaX);
- m_scrollElasticityController.m_stretchScrollForce.setHeight(m_scrollElasticityController.m_stretchScrollForce.height() + deltaY);
-
- FloatSize dampedDelta(ceilf(elasticDeltaForReboundDelta(m_scrollElasticityController.m_stretchScrollForce.width())), ceilf(elasticDeltaForReboundDelta(m_scrollElasticityController.m_stretchScrollForce.height())));
-
- m_scrollElasticityController.m_client->immediateScrollByWithoutContentEdgeConstraints(dampedDelta - stretchAmount);
- }
- }
-
- if (m_scrollElasticityController.m_momentumScrollInProgress && phase == PlatformWheelEventPhaseEnded) {
- m_scrollElasticityController.m_momentumScrollInProgress = false;
- m_scrollElasticityController.m_ignoreMomentumScrolls = false;
- m_scrollElasticityController.m_lastMomentumScrollTimestamp = 0;
- }
-
- return true;
-}
-
-void ScrollAnimatorMac::beginScrollGesture()
-{
- didBeginScrollGesture();
-
- m_scrollerInitiallyPinnedOnLeft = m_scrollableArea->isHorizontalScrollerPinnedToMinimumPosition();
- m_scrollerInitiallyPinnedOnRight = m_scrollableArea->isHorizontalScrollerPinnedToMaximumPosition();
- m_haveScrolledSincePageLoad = true;
- m_cumulativeHorizontalScroll = 0;
- m_didCumulativeHorizontalScrollEverSwitchToOppositeDirectionOfPin = false;
-
- m_scrollElasticityController.beginScrollGesture();
-}
-
-void ScrollAnimatorMac::endScrollGesture()
-{
- didEndScrollGesture();
-
- snapRubberBand();
-}
-
-void ScrollAnimatorMac::snapRubberBand()
-{
- CFTimeInterval timeDelta = systemUptime() - m_scrollElasticityController.m_lastMomentumScrollTimestamp;
- if (m_scrollElasticityController.m_lastMomentumScrollTimestamp && timeDelta >= scrollVelocityZeroingTimeout)
- m_scrollElasticityController.m_momentumVelocity = FloatSize();
-
- m_scrollElasticityController.m_inScrollGesture = false;
-
- if (m_scrollElasticityController.m_snapRubberbandTimerIsActive)
- return;
-
- m_scrollElasticityController.m_startTime = [NSDate timeIntervalSinceReferenceDate];
- m_scrollElasticityController.m_startStretch = FloatSize();
- m_scrollElasticityController.m_origOrigin = FloatPoint();
- m_scrollElasticityController.m_origVelocity = FloatSize();
-
- m_scrollElasticityController.m_client->startSnapRubberbandTimer();
- m_scrollElasticityController.m_snapRubberbandTimerIsActive = true;
-}
-
-static inline float roundTowardZero(float num)
-{
- return num > 0 ? ceilf(num - 0.5f) : floorf(num + 0.5f);
-}
-
-static inline float roundToDevicePixelTowardZero(float num)
-{
- float roundedNum = roundf(num);
- if (fabs(num - roundedNum) < 0.125)
- num = roundedNum;
-
- return roundTowardZero(num);
-}
-
void ScrollAnimatorMac::snapRubberBandTimerFired(Timer<ScrollAnimatorMac>*)
{
- if (!m_scrollElasticityController.m_momentumScrollInProgress || m_scrollElasticityController.m_ignoreMomentumScrolls) {
- CFTimeInterval timeDelta = [NSDate timeIntervalSinceReferenceDate] - m_scrollElasticityController.m_startTime;
-
- if (m_scrollElasticityController.m_startStretch == FloatSize()) {
- m_scrollElasticityController.m_startStretch = m_scrollElasticityController.m_client->stretchAmount();
- if (m_scrollElasticityController.m_startStretch == FloatSize()) {
- m_scrollElasticityController.m_client->stopSnapRubberbandTimer();
-
- m_scrollElasticityController.m_stretchScrollForce = FloatSize();
- m_scrollElasticityController.m_startTime = 0;
- m_scrollElasticityController.m_startStretch = FloatSize();
- m_scrollElasticityController.m_origOrigin = FloatPoint();
- m_scrollElasticityController.m_origVelocity = FloatSize();
- m_scrollElasticityController.m_snapRubberbandTimerIsActive = false;
-
- return;
- }
-
- m_scrollElasticityController.m_origOrigin = m_scrollElasticityController.m_client->absoluteScrollPosition() - m_scrollElasticityController.m_startStretch;
- m_scrollElasticityController.m_origVelocity = m_scrollElasticityController.m_momentumVelocity;
-
- // Just like normal scrolling, prefer vertical rubberbanding
- if (fabsf(m_scrollElasticityController.m_origVelocity.height()) >= fabsf(m_scrollElasticityController.m_origVelocity.width()))
- m_scrollElasticityController.m_origVelocity.setWidth(0);
-
- // Don't rubber-band horizontally if it's not possible to scroll horizontally
- if (!m_scrollElasticityController.m_client->canScrollHorizontally())
- m_scrollElasticityController.m_origVelocity.setWidth(0);
-
- // Don't rubber-band vertically if it's not possible to scroll vertically
- if (!m_scrollElasticityController.m_client->canScrollVertically())
- m_scrollElasticityController.m_origVelocity.setHeight(0);
- }
-
- FloatPoint delta(roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_scrollElasticityController.m_startStretch.width(), -m_scrollElasticityController.m_origVelocity.width(), (float)timeDelta)),
- roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_scrollElasticityController.m_startStretch.height(), -m_scrollElasticityController.m_origVelocity.height(), (float)timeDelta)));
-
- if (fabs(delta.x()) >= 1 || fabs(delta.y()) >= 1) {
- FloatPoint newOrigin = m_scrollElasticityController.m_origOrigin + delta;
-
- m_scrollElasticityController.m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(delta.x(), delta.y()) - m_scrollElasticityController.m_client->stretchAmount());
-
- FloatSize newStretch = m_scrollElasticityController.m_client->stretchAmount();
-
- m_scrollElasticityController.m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(newStretch.width()));
- m_scrollElasticityController.m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(newStretch.height()));
- } else {
- immediateScrollTo(m_scrollElasticityController.m_origOrigin);
-
- m_scrollElasticityController.m_client->stopSnapRubberbandTimer();
-
- m_scrollElasticityController.m_stretchScrollForce = FloatSize();
- m_scrollElasticityController.m_startTime = 0;
- m_scrollElasticityController.m_startStretch = FloatSize();
- m_scrollElasticityController.m_origOrigin = FloatPoint();
- m_scrollElasticityController.m_origVelocity = FloatSize();
- m_scrollElasticityController.m_snapRubberbandTimerIsActive = false;
- }
- } else {
- m_scrollElasticityController.m_startTime = [NSDate timeIntervalSinceReferenceDate];
- m_scrollElasticityController.m_startStretch = FloatSize();
- }
+ m_scrollElasticityController.snapRubberBandTimerFired();
}
#endif
@@ -1440,8 +1090,8 @@ void ScrollAnimatorMac::updateScrollerStyle()
controlSize:(NSControlSize)verticalScrollbar->controlSize()
horizontal:NO
replacingScrollerImp:oldVerticalPainter];
- macTheme->setNewPainterForScrollbar(verticalScrollbar, newVerticalPainter);
[m_scrollbarPainterController.get() setVerticalScrollerImp:newVerticalPainter];
+ macTheme->setNewPainterForScrollbar(verticalScrollbar, newVerticalPainter);
// The different scrollbar styles have different thicknesses, so we must re-set the
// frameRect to the new thickness, and the re-layout below will ensure the position
@@ -1458,8 +1108,8 @@ void ScrollAnimatorMac::updateScrollerStyle()
controlSize:(NSControlSize)horizontalScrollbar->controlSize()
horizontal:YES
replacingScrollerImp:oldHorizontalPainter];
- macTheme->setNewPainterForScrollbar(horizontalScrollbar, newHorizontalPainter);
[m_scrollbarPainterController.get() setHorizontalScrollerImp:newHorizontalPainter];
+ macTheme->setNewPainterForScrollbar(horizontalScrollbar, newHorizontalPainter);
// The different scrollbar styles have different thicknesses, so we must re-set the
// frameRect to the new thickness, and the re-layout below will ensure the position
diff --git a/Source/WebCore/platform/mac/ScrollElasticityController.h b/Source/WebCore/platform/mac/ScrollElasticityController.h
index 066184473..9f52443b8 100644
--- a/Source/WebCore/platform/mac/ScrollElasticityController.h
+++ b/Source/WebCore/platform/mac/ScrollElasticityController.h
@@ -30,19 +30,25 @@
#include "FloatPoint.h"
#include "FloatSize.h"
+#include "ScrollTypes.h"
#include <wtf/Noncopyable.h>
namespace WebCore {
+class PlatformWheelEvent;
+
class ScrollElasticityControllerClient {
protected:
virtual ~ScrollElasticityControllerClient() { }
public:
+ virtual bool allowsHorizontalStretching() = 0;
+ virtual bool allowsVerticalStretching() = 0;
virtual IntSize stretchAmount() = 0;
virtual bool pinnedInDirection(const FloatSize&) = 0;
virtual bool canScrollHorizontally() = 0;
virtual bool canScrollVertically() = 0;
+ virtual bool shouldRubberBandInDirection(ScrollDirection) = 0;
// Return the absolute scroll position, not relative to the scroll origin.
virtual WebCore::IntPoint absoluteScrollPosition() = 0;
@@ -59,14 +65,15 @@ class ScrollElasticityController {
public:
explicit ScrollElasticityController(ScrollElasticityControllerClient*);
- void beginScrollGesture();
+ bool handleWheelEvent(const PlatformWheelEvent&);
+ void snapRubberBandTimerFired();
private:
void stopSnapRubberbandTimer();
+ void snapRubberBand();
+
+ bool shouldRubberBandInHorizontalDirection(const PlatformWheelEvent&);
- // FIXME: These member variables should be private. They are currently public as a stop-gap measure, while
- // the rubber-band related code from ScrollAnimatorMac is being moved over.
-public:
ScrollElasticityControllerClient* m_client;
bool m_inScrollGesture;
diff --git a/Source/WebCore/platform/mac/ScrollElasticityController.mm b/Source/WebCore/platform/mac/ScrollElasticityController.mm
index fa841337e..d3247142b 100644
--- a/Source/WebCore/platform/mac/ScrollElasticityController.mm
+++ b/Source/WebCore/platform/mac/ScrollElasticityController.mm
@@ -26,17 +26,84 @@
#include "config.h"
#include "ScrollElasticityController.h"
+#include "PlatformWheelEvent.h"
+#include <sys/time.h>
+#include <sys/sysctl.h>
+
#if ENABLE(RUBBER_BANDING)
+#ifdef BUILDING_ON_LEOPARD
+@interface NSProcessInfo (ScrollAnimatorMacExt)
+- (NSTimeInterval)systemUptime;
+@end
+#endif
+
+#if ENABLE(RUBBER_BANDING)
+static NSTimeInterval systemUptime()
+{
+ if ([[NSProcessInfo processInfo] respondsToSelector:@selector(systemUptime)])
+ return [[NSProcessInfo processInfo] systemUptime];
+
+ // Get how long system has been up. Found by looking getting "boottime" from the kernel.
+ static struct timeval boottime = {0, 0};
+ if (!boottime.tv_sec) {
+ int mib[2] = {CTL_KERN, KERN_BOOTTIME};
+ size_t size = sizeof(boottime);
+ if (-1 == sysctl(mib, 2, &boottime, &size, 0, 0))
+ boottime.tv_sec = 0;
+ }
+ struct timeval now;
+ if (boottime.tv_sec && -1 != gettimeofday(&now, 0)) {
+ struct timeval uptime;
+ timersub(&now, &boottime, &uptime);
+ NSTimeInterval result = uptime.tv_sec + (uptime.tv_usec / 1E+6);
+ return result;
+ }
+ return 0;
+}
+#endif
+
+
namespace WebCore {
+static const float scrollVelocityZeroingTimeout = 0.10f;
static const float rubberbandStiffness = 20;
+static const float rubberbandDirectionLockStretchRatio = 1;
+static const float rubberbandMinimumRequiredDeltaBeforeStretch = 10;
+static const float rubberbandAmplitude = 0.31f;
+static const float rubberbandPeriod = 1.6f;
+
+static float elasticDeltaForTimeDelta(float initialPosition, float initialVelocity, float elapsedTime)
+{
+ float amplitude = rubberbandAmplitude;
+ float period = rubberbandPeriod;
+ float criticalDampeningFactor = expf((-elapsedTime * rubberbandStiffness) / period);
+
+ return (initialPosition + (-initialVelocity * elapsedTime * amplitude)) * criticalDampeningFactor;
+}
+
+static float elasticDeltaForReboundDelta(float delta)
+{
+ float stiffness = std::max(rubberbandStiffness, 1.0f);
+ return delta / stiffness;
+}
static float reboundDeltaForElasticDelta(float delta)
{
return delta * rubberbandStiffness;
}
+static float scrollWheelMultiplier()
+{
+ static float multiplier = -1;
+ if (multiplier < 0) {
+ multiplier = [[NSUserDefaults standardUserDefaults] floatForKey:@"NSScrollWheelMultiplier"];
+ if (multiplier <= 0)
+ multiplier = 1;
+ }
+ return multiplier;
+}
+
ScrollElasticityController::ScrollElasticityController(ScrollElasticityControllerClient* client)
: m_client(client)
, m_inScrollGesture(false)
@@ -48,21 +115,256 @@ ScrollElasticityController::ScrollElasticityController(ScrollElasticityControlle
{
}
-void ScrollElasticityController::beginScrollGesture()
+bool ScrollElasticityController::handleWheelEvent(const PlatformWheelEvent& wheelEvent)
{
- m_inScrollGesture = true;
- m_momentumScrollInProgress = false;
- m_ignoreMomentumScrolls = false;
- m_lastMomentumScrollTimestamp = 0;
- m_momentumVelocity = FloatSize();
-
- IntSize stretchAmount = m_client->stretchAmount();
- m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(stretchAmount.width()));
- m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(stretchAmount.height()));
-
+ if (wheelEvent.phase() == PlatformWheelEventPhaseBegan) {
+ // First, check if we should rubber-band at all.
+ if (m_client->pinnedInDirection(FloatSize(-wheelEvent.deltaX(), 0)) &&
+ !shouldRubberBandInHorizontalDirection(wheelEvent))
+ return false;
+
+ m_inScrollGesture = true;
+ m_momentumScrollInProgress = false;
+ m_ignoreMomentumScrolls = false;
+ m_lastMomentumScrollTimestamp = 0;
+ m_momentumVelocity = FloatSize();
+
+ IntSize stretchAmount = m_client->stretchAmount();
+ m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(stretchAmount.width()));
+ m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(stretchAmount.height()));
+ m_overflowScrollDelta = FloatSize();
+
+ stopSnapRubberbandTimer();
+
+ return true;
+ }
+
+ if (wheelEvent.phase() == PlatformWheelEventPhaseEnded) {
+ snapRubberBand();
+ return true;
+ }
+
+ bool isMomentumScrollEvent = (wheelEvent.momentumPhase() != PlatformWheelEventPhaseNone);
+ if (m_ignoreMomentumScrolls && (isMomentumScrollEvent || m_snapRubberbandTimerIsActive)) {
+ if (wheelEvent.momentumPhase() == PlatformWheelEventPhaseEnded) {
+ m_ignoreMomentumScrolls = false;
+ return true;
+ }
+ return false;
+ }
+
+ float deltaX = m_overflowScrollDelta.width();
+ float deltaY = m_overflowScrollDelta.height();
+
+ // Reset overflow values because we may decide to remove delta at various points and put it into overflow.
m_overflowScrollDelta = FloatSize();
- stopSnapRubberbandTimer();
+ float eventCoalescedDeltaX = -wheelEvent.deltaX();
+ float eventCoalescedDeltaY = -wheelEvent.deltaY();
+
+ deltaX += eventCoalescedDeltaX;
+ deltaY += eventCoalescedDeltaY;
+
+ // Slightly prefer scrolling vertically by applying the = case to deltaY
+ if (fabsf(deltaY) >= fabsf(deltaX))
+ deltaX = 0;
+ else
+ deltaY = 0;
+
+ bool isVerticallyStretched = false;
+ bool isHorizontallyStretched = false;
+ bool shouldStretch = false;
+
+ IntSize stretchAmount = m_client->stretchAmount();
+
+ isHorizontallyStretched = stretchAmount.width();
+ isVerticallyStretched = stretchAmount.height();
+
+ PlatformWheelEventPhase momentumPhase = wheelEvent.momentumPhase();
+
+ // If we are starting momentum scrolling then do some setup.
+ if (!m_momentumScrollInProgress && (momentumPhase == PlatformWheelEventPhaseBegan || momentumPhase == PlatformWheelEventPhaseChanged))
+ m_momentumScrollInProgress = true;
+
+ CFTimeInterval timeDelta = wheelEvent.timestamp() - m_lastMomentumScrollTimestamp;
+ if (m_inScrollGesture || m_momentumScrollInProgress) {
+ if (m_lastMomentumScrollTimestamp && timeDelta > 0 && timeDelta < scrollVelocityZeroingTimeout) {
+ m_momentumVelocity.setWidth(eventCoalescedDeltaX / (float)timeDelta);
+ m_momentumVelocity.setHeight(eventCoalescedDeltaY / (float)timeDelta);
+ m_lastMomentumScrollTimestamp = wheelEvent.timestamp();
+ } else {
+ m_lastMomentumScrollTimestamp = wheelEvent.timestamp();
+ m_momentumVelocity = FloatSize();
+ }
+
+ if (isVerticallyStretched) {
+ if (!isHorizontallyStretched && m_client->pinnedInDirection(FloatSize(deltaX, 0))) {
+ // Stretching only in the vertical.
+ if (deltaY != 0 && (fabsf(deltaX / deltaY) < rubberbandDirectionLockStretchRatio))
+ deltaX = 0;
+ else if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
+ deltaX = 0;
+ } else
+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
+ }
+ } else if (isHorizontallyStretched) {
+ // Stretching only in the horizontal.
+ if (m_client->pinnedInDirection(FloatSize(0, deltaY))) {
+ if (deltaX != 0 && (fabsf(deltaY / deltaX) < rubberbandDirectionLockStretchRatio))
+ deltaY = 0;
+ else if (fabsf(deltaY) < rubberbandMinimumRequiredDeltaBeforeStretch) {
+ m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY);
+ deltaY = 0;
+ } else
+ m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY);
+ }
+ } else {
+ // Not stretching at all yet.
+ if (m_client->pinnedInDirection(FloatSize(deltaX, deltaY))) {
+ if (fabsf(deltaY) >= fabsf(deltaX)) {
+ if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
+ deltaX = 0;
+ } else
+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
+ }
+ shouldStretch = true;
+ }
+ }
+ }
+
+ if (deltaX != 0 || deltaY != 0) {
+ if (!(shouldStretch || isVerticallyStretched || isHorizontallyStretched)) {
+ if (deltaY != 0) {
+ deltaY *= scrollWheelMultiplier();
+ m_client->immediateScrollBy(FloatSize(0, deltaY));
+ }
+ if (deltaX != 0) {
+ deltaX *= scrollWheelMultiplier();
+ m_client->immediateScrollBy(FloatSize(deltaX, 0));
+ }
+ } else {
+ if (!m_client->allowsHorizontalStretching()) {
+ deltaX = 0;
+ eventCoalescedDeltaX = 0;
+ } else if ((deltaX != 0) && !isHorizontallyStretched && !m_client->pinnedInDirection(FloatSize(deltaX, 0))) {
+ deltaX *= scrollWheelMultiplier();
+
+ m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(deltaX, 0));
+ deltaX = 0;
+ }
+
+ if (!m_client->allowsVerticalStretching()) {
+ deltaY = 0;
+ eventCoalescedDeltaY = 0;
+ } else if ((deltaY != 0) && !isVerticallyStretched && !m_client->pinnedInDirection(FloatSize(0, deltaY))) {
+ deltaY *= scrollWheelMultiplier();
+
+ m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(0, deltaY));
+ deltaY = 0;
+ }
+
+ IntSize stretchAmount = m_client->stretchAmount();
+
+ if (m_momentumScrollInProgress) {
+ if ((m_client->pinnedInDirection(FloatSize(eventCoalescedDeltaX, eventCoalescedDeltaY)) || (fabsf(eventCoalescedDeltaX) + fabsf(eventCoalescedDeltaY) <= 0)) && m_lastMomentumScrollTimestamp) {
+ m_ignoreMomentumScrolls = true;
+ m_momentumScrollInProgress = false;
+ snapRubberBand();
+ }
+ }
+
+ m_stretchScrollForce.setWidth(m_stretchScrollForce.width() + deltaX);
+ m_stretchScrollForce.setHeight(m_stretchScrollForce.height() + deltaY);
+
+ FloatSize dampedDelta(ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.width())), ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.height())));
+
+ m_client->immediateScrollByWithoutContentEdgeConstraints(dampedDelta - stretchAmount);
+ }
+ }
+
+ if (m_momentumScrollInProgress && momentumPhase == PlatformWheelEventPhaseEnded) {
+ m_momentumScrollInProgress = false;
+ m_ignoreMomentumScrolls = false;
+ m_lastMomentumScrollTimestamp = 0;
+ }
+
+ return true;
+}
+
+static inline float roundTowardZero(float num)
+{
+ return num > 0 ? ceilf(num - 0.5f) : floorf(num + 0.5f);
+}
+
+static inline float roundToDevicePixelTowardZero(float num)
+{
+ float roundedNum = roundf(num);
+ if (fabs(num - roundedNum) < 0.125)
+ num = roundedNum;
+
+ return roundTowardZero(num);
+}
+
+void ScrollElasticityController::snapRubberBandTimerFired()
+{
+ if (!m_momentumScrollInProgress || m_ignoreMomentumScrolls) {
+ CFTimeInterval timeDelta = [NSDate timeIntervalSinceReferenceDate] - m_startTime;
+
+ if (m_startStretch == FloatSize()) {
+ m_startStretch = m_client->stretchAmount();
+ if (m_startStretch == FloatSize()) {
+ stopSnapRubberbandTimer();
+
+ m_stretchScrollForce = FloatSize();
+ m_startTime = 0;
+ m_startStretch = FloatSize();
+ m_origOrigin = FloatPoint();
+ m_origVelocity = FloatSize();
+ return;
+ }
+
+ m_origOrigin = m_client->absoluteScrollPosition() - m_startStretch;
+ m_origVelocity = m_momentumVelocity;
+
+ // Just like normal scrolling, prefer vertical rubberbanding
+ if (fabsf(m_origVelocity.height()) >= fabsf(m_origVelocity.width()))
+ m_origVelocity.setWidth(0);
+
+ // Don't rubber-band horizontally if it's not possible to scroll horizontally
+ if (!m_client->canScrollHorizontally())
+ m_origVelocity.setWidth(0);
+
+ // Don't rubber-band vertically if it's not possible to scroll vertically
+ if (!m_client->canScrollVertically())
+ m_origVelocity.setHeight(0);
+ }
+
+ FloatPoint delta(roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.width(), -m_origVelocity.width(), (float)timeDelta)),
+ roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.height(), -m_origVelocity.height(), (float)timeDelta)));
+
+ if (fabs(delta.x()) >= 1 || fabs(delta.y()) >= 1) {
+ m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(delta.x(), delta.y()) - m_client->stretchAmount());
+
+ FloatSize newStretch = m_client->stretchAmount();
+
+ m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(newStretch.width()));
+ m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(newStretch.height()));
+ } else {
+ m_client->immediateScrollBy(m_origOrigin - m_client->absoluteScrollPosition());
+
+ stopSnapRubberbandTimer();
+ m_stretchScrollForce = FloatSize();
+ m_startTime = 0;
+ m_startStretch = FloatSize();
+ m_origOrigin = FloatPoint();
+ m_origVelocity = FloatSize();
+ }
+ } else {
+ m_startTime = [NSDate timeIntervalSinceReferenceDate];
+ m_startStretch = FloatSize();
+ }
}
void ScrollElasticityController::stopSnapRubberbandTimer()
@@ -71,6 +373,36 @@ void ScrollElasticityController::stopSnapRubberbandTimer()
m_snapRubberbandTimerIsActive = false;
}
+void ScrollElasticityController::snapRubberBand()
+{
+ CFTimeInterval timeDelta = systemUptime() - m_lastMomentumScrollTimestamp;
+ if (m_lastMomentumScrollTimestamp && timeDelta >= scrollVelocityZeroingTimeout)
+ m_momentumVelocity = FloatSize();
+
+ m_inScrollGesture = false;
+
+ if (m_snapRubberbandTimerIsActive)
+ return;
+
+ m_startTime = [NSDate timeIntervalSinceReferenceDate];
+ m_startStretch = FloatSize();
+ m_origOrigin = FloatPoint();
+ m_origVelocity = FloatSize();
+
+ m_client->startSnapRubberbandTimer();
+ m_snapRubberbandTimerIsActive = true;
+}
+
+bool ScrollElasticityController::shouldRubberBandInHorizontalDirection(const PlatformWheelEvent& wheelEvent)
+{
+ if (wheelEvent.deltaX() > 0)
+ return m_client->shouldRubberBandInDirection(ScrollLeft);
+ if (wheelEvent.deltaX() < 0)
+ return m_client->shouldRubberBandInDirection(ScrollRight);
+
+ return true;
+}
+
} // namespace WebCore
#endif // ENABLE(RUBBER_BANDING)
diff --git a/Source/WebCore/platform/mac/ScrollbarThemeMac.mm b/Source/WebCore/platform/mac/ScrollbarThemeMac.mm
index 0fe1c0d6f..85809244d 100644
--- a/Source/WebCore/platform/mac/ScrollbarThemeMac.mm
+++ b/Source/WebCore/platform/mac/ScrollbarThemeMac.mm
@@ -133,6 +133,13 @@ static bool gJumpOnTrackClick = false;
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)];
+ return globalSupportsExpandedScrollbars;
+}
+
static void updateArrowPlacement()
{
if (isScrollbarOverlayAPIAvailable())
@@ -222,6 +229,8 @@ int ScrollbarThemeMac::scrollbarThickness(ScrollbarControlSize controlSize)
{
if (isScrollbarOverlayAPIAvailable()) {
ScrollbarPainter scrollbarPainter = [NSClassFromString(@"NSScrollerImp") scrollerImpWithStyle:recommendedScrollerStyle() controlSize:controlSize horizontal:NO replacingScrollerImp:nil];
+ if (supportsExpandedScrollbars())
+ [scrollbarPainter setExpanded:YES];
return [scrollbarPainter trackBoxWidth];
} else
return cScrollbarThickness[controlSize];
diff --git a/Source/WebCore/platform/mac/WebCoreSystemInterface.h b/Source/WebCore/platform/mac/WebCoreSystemInterface.h
index beb36ca06..21eb94a18 100644
--- a/Source/WebCore/platform/mac/WebCoreSystemInterface.h
+++ b/Source/WebCore/platform/mac/WebCoreSystemInterface.h
@@ -77,56 +77,29 @@ typedef struct _CFURLRequest* CFMutableURLRequestRef;
typedef const struct _CFURLRequest* CFURLRequestRef;
#endif
-#ifdef __OBJC__
-@class AVAsset;
-@class NSArray;
-@class NSButtonCell;
-@class NSControl;
-@class NSCursor;
-@class NSData;
-@class NSDate;
-@class NSEvent;
-@class NSFont;
-@class NSHTTPCookie;
-@class NSImage;
-@class NSMenu;
-@class NSMutableURLRequest;
-@class NSString;
-@class NSTextFieldCell;
-@class NSURL;
-@class NSURLConnection;
-@class NSURLRequest;
-@class NSURLResponse;
-@class NSView;
-@class NSWindow;
-@class QTMovie;
-@class QTMovieView;
-#else
-class AVAsset;
-class NSArray;
-class NSButtonCell;
-class NSControl;
-class NSCursor;
-class NSData;
-class NSDate;
-class NSEvent;
-class NSFont;
-class NSHTTPCookie;
-class NSImage;
-class NSMenu;
-class NSMutableArray;
-class NSMutableURLRequest;
-class NSURL;
-class NSURLRequest;
-class NSString;
-class NSTextFieldCell;
-class NSURLConnection;
-class NSURLResponse;
-class NSView;
-class NSWindow;
-class QTMovie;
-class QTMovieView;
-#endif
+OBJC_CLASS AVAsset;
+OBJC_CLASS NSArray;
+OBJC_CLASS NSButtonCell;
+OBJC_CLASS NSControl;
+OBJC_CLASS NSCursor;
+OBJC_CLASS NSData;
+OBJC_CLASS NSDate;
+OBJC_CLASS NSEvent;
+OBJC_CLASS NSFont;
+OBJC_CLASS NSHTTPCookie;
+OBJC_CLASS NSImage;
+OBJC_CLASS NSMenu;
+OBJC_CLASS NSMutableURLRequest;
+OBJC_CLASS NSString;
+OBJC_CLASS NSTextFieldCell;
+OBJC_CLASS NSURL;
+OBJC_CLASS NSURLConnection;
+OBJC_CLASS NSURLRequest;
+OBJC_CLASS NSURLResponse;
+OBJC_CLASS NSView;
+OBJC_CLASS NSWindow;
+OBJC_CLASS QTMovie;
+OBJC_CLASS QTMovieView;
extern "C" {
@@ -255,8 +228,10 @@ extern CTLineRef (*wkCreateCTLineWithUniCharProvider)(const UniChar* (*provide)(
extern CTTypesetterRef (*wkCreateCTTypesetterWithUniCharProviderAndOptions)(const UniChar* (*provide)(CFIndex stringIndex, CFIndex* charCount, CFDictionaryRef* attributes, void*), void (*dispose)(const UniChar* chars, void*), void*, CFDictionaryRef options);
+#if PLATFORM(MAC) && USE(CA)
extern CGContextRef (*wkIOSurfaceContextCreate)(IOSurfaceRef surface, unsigned width, unsigned height, CGColorSpaceRef colorSpace);
extern CGImageRef (*wkIOSurfaceContextCreateImage)(CGContextRef context);
+#endif
extern int (*wkRecommendedScrollerStyle)(void);
@@ -321,6 +296,7 @@ extern dispatch_source_t (*wkCreateVMPressureDispatchOnMainQueue)(void);
#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION)
extern NSString *(*wkGetMacOSXVersionString)(void);
+extern bool (*wkExecutableWasLinkedOnOrBeforeLion)(void);
#endif
}
diff --git a/Source/WebCore/platform/mac/WebCoreSystemInterface.mm b/Source/WebCore/platform/mac/WebCoreSystemInterface.mm
index b4ca5407d..f01747d5f 100644
--- a/Source/WebCore/platform/mac/WebCoreSystemInterface.mm
+++ b/Source/WebCore/platform/mac/WebCoreSystemInterface.mm
@@ -179,4 +179,5 @@ dispatch_source_t (*wkCreateVMPressureDispatchOnMainQueue)(void);
#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION)
NSString *(*wkGetMacOSXVersionString)(void);
+bool (*wkExecutableWasLinkedOnOrBeforeLion)(void);
#endif
diff --git a/Source/WebCore/platform/mediastream/MediaStreamCenter.cpp b/Source/WebCore/platform/mediastream/MediaStreamCenter.cpp
index a484a2bc2..9203ce3ac 100644
--- a/Source/WebCore/platform/mediastream/MediaStreamCenter.cpp
+++ b/Source/WebCore/platform/mediastream/MediaStreamCenter.cpp
@@ -57,6 +57,7 @@ void MediaStreamCenter::endLocalMediaStream(MediaStreamDescriptor* streamDescrip
// FIXME: remove when real implementations are available
// Empty implementations for ports that build with MEDIA_STREAM enabled by default.
+
MediaStreamCenter::MediaStreamCenter()
{
}
@@ -67,11 +68,11 @@ MediaStreamCenter::~MediaStreamCenter()
void MediaStreamCenter::queryMediaStreamSources(PassRefPtr<MediaStreamSourcesQueryClient> client)
{
- MediaStreamSourceVector sources;
- client->mediaStreamSourcesQueryCompleted(sources);
+ MediaStreamSourceVector audioSources, videoSources;
+ client->mediaStreamSourcesQueryCompleted(audioSources, videoSources);
}
-void MediaStreamCenter::didSetMediaStreamTrackEnabled(MediaStreamDescriptor*, unsigned)
+void MediaStreamCenter::didSetMediaStreamTrackEnabled(MediaStreamDescriptor*, MediaStreamComponent*)
{
}
@@ -79,6 +80,10 @@ void MediaStreamCenter::didStopLocalMediaStream(MediaStreamDescriptor*)
{
}
+void MediaStreamCenter::didConstructMediaStream(MediaStreamDescriptor*)
+{
+}
+
} // namespace WebCore
#endif // ENABLE(MEDIA_STREAM)
diff --git a/Source/WebCore/platform/mediastream/MediaStreamCenter.h b/Source/WebCore/platform/mediastream/MediaStreamCenter.h
index 8efc8b32f..7d98fc52d 100644
--- a/Source/WebCore/platform/mediastream/MediaStreamCenter.h
+++ b/Source/WebCore/platform/mediastream/MediaStreamCenter.h
@@ -38,6 +38,7 @@
namespace WebCore {
+class MediaStreamComponent;
class MediaStreamDescriptor;
class MediaStreamSourcesQueryClient : public RefCounted<MediaStreamSourcesQueryClient> {
@@ -47,7 +48,7 @@ public:
virtual bool audio() const = 0;
virtual bool video() const = 0;
- virtual void mediaStreamSourcesQueryCompleted(const MediaStreamSourceVector&) = 0;
+ virtual void mediaStreamSourcesQueryCompleted(const MediaStreamSourceVector& audioSources, const MediaStreamSourceVector& videoSources) = 0;
};
class MediaStreamCenter {
@@ -63,8 +64,9 @@ public:
// 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*, unsigned componentIndex);
+ void didSetMediaStreamTrackEnabled(MediaStreamDescriptor*, MediaStreamComponent*);
void didStopLocalMediaStream(MediaStreamDescriptor*);
+ void didConstructMediaStream(MediaStreamDescriptor*);
// Calls from the platform to update the DOM objects
void endLocalMediaStream(MediaStreamDescriptor*);
diff --git a/Source/WebCore/platform/mediastream/MediaStreamDescriptor.h b/Source/WebCore/platform/mediastream/MediaStreamDescriptor.h
index a046d45fb..b3b273fa7 100644
--- a/Source/WebCore/platform/mediastream/MediaStreamDescriptor.h
+++ b/Source/WebCore/platform/mediastream/MediaStreamDescriptor.h
@@ -48,9 +48,9 @@ public:
class MediaStreamDescriptor : public RefCounted<MediaStreamDescriptor> {
public:
- static PassRefPtr<MediaStreamDescriptor> create(const String& label, const MediaStreamSourceVector& sources)
+ static PassRefPtr<MediaStreamDescriptor> create(const String& label, const MediaStreamSourceVector& audioSources, const MediaStreamSourceVector& videoSources)
{
- return adoptRef(new MediaStreamDescriptor(label, sources));
+ return adoptRef(new MediaStreamDescriptor(label, audioSources, videoSources));
}
MediaStreamDescriptorOwner* owner() const { return m_owner; }
@@ -58,25 +58,32 @@ public:
String label() const { return m_label; }
- MediaStreamComponent* component(unsigned index) const { return m_components[index].get(); }
- unsigned numberOfComponents() const { return m_components.size(); }
+ unsigned numberOfAudioComponents() const { return m_audioComponents.size(); }
+ MediaStreamComponent* audioComponent(unsigned index) const { return m_audioComponents[index].get(); }
+
+ unsigned numberOfVideoComponents() const { return m_videoComponents.size(); }
+ MediaStreamComponent* videoComponent(unsigned index) const { return m_videoComponents[index].get(); }
bool ended() const { return m_ended; }
void setEnded() { m_ended = true; }
private:
- MediaStreamDescriptor(const String& label, const MediaStreamSourceVector& sources)
+ MediaStreamDescriptor(const String& label, const MediaStreamSourceVector& audioSources, const MediaStreamSourceVector& videoSources)
: m_owner(0)
, m_label(label)
, m_ended(false)
{
- for (size_t i = 0; i < sources.size(); i++)
- m_components.append(MediaStreamComponent::create(sources[i]));
+ for (size_t i = 0; i < audioSources.size(); i++)
+ m_audioComponents.append(MediaStreamComponent::create(audioSources[i]));
+
+ for (size_t i = 0; i < videoSources.size(); i++)
+ m_videoComponents.append(MediaStreamComponent::create(videoSources[i]));
}
MediaStreamDescriptorOwner* m_owner;
String m_label;
- Vector<RefPtr<MediaStreamComponent> > m_components;
+ Vector<RefPtr<MediaStreamComponent> > m_audioComponents;
+ Vector<RefPtr<MediaStreamComponent> > m_videoComponents;
bool m_ended;
};
diff --git a/Source/WebCore/platform/mock/SpeechInputClientMock.cpp b/Source/WebCore/platform/mock/SpeechInputClientMock.cpp
deleted file mode 100644
index 9aa3113dc..000000000
--- a/Source/WebCore/platform/mock/SpeechInputClientMock.cpp
+++ /dev/null
@@ -1,146 +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"
-#include "SpeechInputClientMock.h"
-
-#if ENABLE(INPUT_SPEECH)
-
-#include "SecurityOrigin.h"
-#include "SpeechInputListener.h"
-
-namespace WebCore {
-
-SpeechInputClientMock::SpeechInputClientMock()
- : m_recording(false)
- , m_timer(this, &SpeechInputClientMock::timerFired)
- , m_listener(0)
- , m_requestId(0)
-{
-}
-
-void SpeechInputClientMock::setListener(SpeechInputListener* listener)
-{
- m_listener = listener;
-}
-
-bool SpeechInputClientMock::startRecognition(int requestId, const IntRect& elementRect, const AtomicString& language, const String& grammar, SecurityOrigin* origin)
-{
- if (m_timer.isActive())
- return false;
- m_requestId = requestId;
- m_recording = true;
- m_language = language;
- m_timer.startOneShot(0);
- return true;
-}
-
-void SpeechInputClientMock::stopRecording(int requestId)
-{
- ASSERT(requestId == m_requestId);
- if (m_timer.isActive() && m_recording) {
- m_timer.stop();
- timerFired(&m_timer);
- }
-}
-
-void SpeechInputClientMock::cancelRecognition(int requestId)
-{
- if (m_timer.isActive()) {
- ASSERT(requestId == m_requestId);
- m_timer.stop();
- m_recording = false;
- m_listener->didCompleteRecognition(m_requestId);
- m_requestId = 0;
- }
-}
-
-void SpeechInputClientMock::addRecognitionResult(const String& result, double confidence, const AtomicString& language)
-{
- if (language.isEmpty())
- m_resultsForEmptyLanguage.append(SpeechInputResult::create(result, confidence));
- else {
- if (!m_recognitionResults.contains(language))
- m_recognitionResults.set(language, SpeechInputResultArray());
- m_recognitionResults.find(language)->second.append(SpeechInputResult::create(result, confidence));
- }
-}
-
-void SpeechInputClientMock::clearResults()
-{
- m_resultsForEmptyLanguage.clear();
- m_recognitionResults.clear();
-}
-
-void SpeechInputClientMock::timerFired(WebCore::Timer<SpeechInputClientMock>*)
-{
- if (m_recording) {
- m_recording = false;
- m_listener->didCompleteRecording(m_requestId);
- m_timer.startOneShot(0);
- } else {
- bool noResultsFound = false;
-
- // We take a copy of the requestId here so that if scripts destroyed the input element
- // inside one of the callbacks below, we'll still know what this session's requestId was.
- int requestId = m_requestId;
- m_requestId = 0;
-
- // Empty language case must be handled separately to avoid problems with HashMap and empty keys.
- if (m_language.isEmpty()) {
- if (!m_resultsForEmptyLanguage.isEmpty())
- m_listener->setRecognitionResult(requestId, m_resultsForEmptyLanguage);
- else
- noResultsFound = true;
- } else {
- if (m_recognitionResults.contains(m_language))
- m_listener->setRecognitionResult(requestId, m_recognitionResults.get(m_language));
- else
- noResultsFound = true;
- }
-
- if (noResultsFound) {
- // Can't avoid setting a result even if no result was set for the given language.
- // This would avoid generating the events used to check the results and the test would timeout.
- String error("error: no result found for language '");
- error.append(m_language);
- error.append("'");
- SpeechInputResultArray results;
- results.append(SpeechInputResult::create(error, 1.0));
- m_listener->setRecognitionResult(requestId, results);
- }
-
- m_listener->didCompleteRecognition(requestId);
- }
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(INPUT_SPEECH)
diff --git a/Source/WebCore/platform/network/HTTPParsers.cpp b/Source/WebCore/platform/network/HTTPParsers.cpp
index 4ef54ef29..8cbd4ff14 100644
--- a/Source/WebCore/platform/network/HTTPParsers.cpp
+++ b/Source/WebCore/platform/network/HTTPParsers.cpp
@@ -73,28 +73,45 @@ static inline bool skipToken(const String& str, unsigned& pos, const char* token
return true;
}
+// See RFC 2616, Section 2.2.
+bool isRFC2616Token(const String& characters)
+{
+ if (characters.isEmpty())
+ return false;
+ for (unsigned i = 0; i < characters.length(); ++i) {
+ UChar c = characters[i];
+ if (c >= 0x80 || c <= 0x1F || c == 0x7F
+ || c == '(' || c == ')' || c == '<' || c == '>' || c == '@'
+ || c == ',' || c == ';' || c == ':' || c == '\\' || c == '"'
+ || c == '/' || c == '[' || c == ']' || c == '?' || c == '='
+ || c == '{' || c == '}' || c == ' ' || c == '\t')
+ return false;
+ }
+ return true;
+}
+
ContentDispositionType contentDispositionType(const String& contentDisposition)
-{
+{
if (contentDisposition.isEmpty())
return ContentDispositionNone;
- // Some broken sites just send
- // Content-Disposition: ; filename="file"
- // screen those out here.
- if (contentDisposition.startsWith(";"))
- return ContentDispositionNone;
+ Vector<String> parameters;
+ contentDisposition.split(';', parameters);
- if (contentDisposition.startsWith("inline", false))
+ String dispositionType = parameters[0];
+ dispositionType.stripWhiteSpace();
+
+ if (equalIgnoringCase(dispositionType, "inline"))
return ContentDispositionInline;
- // Some broken sites just send
- // Content-Disposition: filename="file"
+ // Some broken sites just send bogus headers like
+ //
+ // Content-Disposition: ; filename="file"
+ // Content-Disposition: filename="file"
+ // Content-Disposition: name="file"
+ //
// without a disposition token... screen those out.
- if (contentDisposition.startsWith("filename", false))
- return ContentDispositionNone;
-
- // Also in use is Content-Disposition: name="file"
- if (contentDisposition.startsWith("name", false))
+ if (!isRFC2616Token(dispositionType))
return ContentDispositionNone;
// We have a content-disposition of "attachment" or unknown.
@@ -167,6 +184,11 @@ double parseDate(const String& value)
return parseDateFromNullTerminatedCharacters(value.utf8().data());
}
+// FIXME: This function doesn't comply with RFC 6266.
+// For example, this function doesn't handle the interaction between " and ;
+// that arises from quoted-string, nor does this function properly unquote
+// attribute values. Further this function appears to process parameter names
+// in a case-sensitive manner. (There are likely other bugs as well.)
String filenameFromHTTPContentDisposition(const String& value)
{
Vector<String> keyValuePairs;
diff --git a/Source/WebCore/platform/network/HTTPParsers.h b/Source/WebCore/platform/network/HTTPParsers.h
index 55b8c7b90..3c808af62 100644
--- a/Source/WebCore/platform/network/HTTPParsers.h
+++ b/Source/WebCore/platform/network/HTTPParsers.h
@@ -50,6 +50,7 @@ typedef enum {
} ContentDispositionType;
ContentDispositionType contentDispositionType(const String&);
+bool isRFC2616Token(const String&);
bool parseHTTPRefresh(const String& refresh, bool fromHttpEquivMeta, double& delay, String& url);
double parseDate(const String&);
String filenameFromHTTPContentDisposition(const String&);
diff --git a/Source/WebCore/platform/network/ResourceHandle.h b/Source/WebCore/platform/network/ResourceHandle.h
index a3633b25a..1b1eacc73 100644
--- a/Source/WebCore/platform/network/ResourceHandle.h
+++ b/Source/WebCore/platform/network/ResourceHandle.h
@@ -52,16 +52,11 @@ typedef LPVOID HINTERNET;
#endif
#if PLATFORM(MAC)
-#ifdef __OBJC__
-@class NSData;
-@class NSError;
-@class NSURLConnection;
-@class WebCoreResourceHandleAsDelegate;
-#else
-class NSData;
-class NSError;
-class NSURLConnection;
-class WebCoreResourceHandleAsDelegate;
+OBJC_CLASS NSData;
+OBJC_CLASS NSError;
+OBJC_CLASS NSURLConnection;
+OBJC_CLASS WebCoreResourceHandleAsDelegate;
+#ifndef __OBJC__
typedef struct objc_object *id;
#endif
#endif
diff --git a/Source/WebCore/platform/network/ResourceHandleClient.h b/Source/WebCore/platform/network/ResourceHandleClient.h
index a458b5da2..befbccfa0 100644
--- a/Source/WebCore/platform/network/ResourceHandleClient.h
+++ b/Source/WebCore/platform/network/ResourceHandleClient.h
@@ -40,11 +40,7 @@
#endif
#if PLATFORM(MAC)
-#ifdef __OBJC__
-@class NSCachedURLResponse;
-#else
-class NSCachedURLResponse;
-#endif
+OBJC_CLASS NSCachedURLResponse;
#endif
namespace WebCore {
diff --git a/Source/WebCore/platform/network/ResourceHandleInternal.h b/Source/WebCore/platform/network/ResourceHandleInternal.h
index cad38341a..877997963 100644
--- a/Source/WebCore/platform/network/ResourceHandleInternal.h
+++ b/Source/WebCore/platform/network/ResourceHandleInternal.h
@@ -61,13 +61,8 @@ class QNetworkReplyHandler;
#endif
#if PLATFORM(MAC)
-#ifdef __OBJC__
-@class NSURLAuthenticationChallenge;
-@class NSURLConnection;
-#else
-class NSURLAuthenticationChallenge;
-class NSURLConnection;
-#endif
+OBJC_CLASS NSURLAuthenticationChallenge;
+OBJC_CLASS NSURLConnection;
#endif
// The allocations and releases in ResourceHandleInternal are
diff --git a/Source/WebCore/platform/network/ResourceRequestBase.cpp b/Source/WebCore/platform/network/ResourceRequestBase.cpp
index c5bd30814..e1e96c409 100644
--- a/Source/WebCore/platform/network/ResourceRequestBase.cpp
+++ b/Source/WebCore/platform/network/ResourceRequestBase.cpp
@@ -57,7 +57,6 @@ PassOwnPtr<ResourceRequest> ResourceRequestBase::adopt(PassOwnPtr<CrossThreadRes
request->updateResourceRequest();
request->m_httpHeaderFields.adopt(data->m_httpHeaders.release());
-#if PLATFORM(MAC) || PLATFORM(WIN)
size_t encodingCount = data->m_responseContentDispositionEncodingFallbackArray.size();
if (encodingCount > 0) {
String encoding1 = data->m_responseContentDispositionEncodingFallbackArray[0];
@@ -71,7 +70,6 @@ PassOwnPtr<ResourceRequest> ResourceRequestBase::adopt(PassOwnPtr<CrossThreadRes
ASSERT(encodingCount <= 3);
request->setResponseContentDispositionEncodingFallbackArray(encoding1, encoding2, encoding3);
}
-#endif
request->setHTTPBody(data->m_httpBody);
request->setAllowCookies(data->m_allowCookies);
request->doPlatformAdopt(data);
@@ -89,13 +87,11 @@ PassOwnPtr<CrossThreadResourceRequestData> ResourceRequestBase::copyData() const
data->m_httpHeaders = httpHeaderFields().copyData();
data->m_priority = priority();
-#if PLATFORM(MAC) || PLATFORM(WIN)
data->m_responseContentDispositionEncodingFallbackArray.reserveInitialCapacity(m_responseContentDispositionEncodingFallbackArray.size());
size_t encodingArraySize = m_responseContentDispositionEncodingFallbackArray.size();
for (size_t index = 0; index < encodingArraySize; ++index) {
data->m_responseContentDispositionEncodingFallbackArray.append(m_responseContentDispositionEncodingFallbackArray[index].isolatedCopy());
}
-#endif
if (m_httpBody)
data->m_httpBody = m_httpBody->deepCopy();
data->m_allowCookies = m_allowCookies;
@@ -275,7 +271,6 @@ void ResourceRequestBase::clearHTTPOrigin()
m_platformRequestUpdated = false;
}
-#if PLATFORM(MAC) || PLATFORM(WIN)
void ResourceRequestBase::setResponseContentDispositionEncodingFallbackArray(const String& encoding1, const String& encoding2, const String& encoding3)
{
updateResourceRequest();
@@ -291,7 +286,6 @@ void ResourceRequestBase::setResponseContentDispositionEncodingFallbackArray(con
if (url().protocolInHTTPFamily())
m_platformRequestUpdated = false;
}
-#endif
FormData* ResourceRequestBase::httpBody() const
{
diff --git a/Source/WebCore/platform/network/ResourceRequestBase.h b/Source/WebCore/platform/network/ResourceRequestBase.h
index b5dc11e4a..0b154d60f 100644
--- a/Source/WebCore/platform/network/ResourceRequestBase.h
+++ b/Source/WebCore/platform/network/ResourceRequestBase.h
@@ -103,11 +103,7 @@ namespace WebCore {
String httpAccept() const { return httpHeaderField("Accept"); }
void setHTTPAccept(const String& httpAccept) { setHTTPHeaderField("Accept", httpAccept); }
-#if PLATFORM(MAC) || PLATFORM(WIN)
- // FIXME: This state should either be moved to a CFNetwork-specific
- // ResourceRequest or should be removed.
void setResponseContentDispositionEncodingFallbackArray(const String& encoding1, const String& encoding2 = String(), const String& encoding3 = String());
-#endif
FormData* httpBody() const;
void setHTTPBody(PassRefPtr<FormData> httpBody);
@@ -178,11 +174,7 @@ namespace WebCore {
KURL m_firstPartyForCookies;
String m_httpMethod;
HTTPHeaderMap m_httpHeaderFields;
-#if PLATFORM(MAC) || PLATFORM(WIN)
- // FIXME: This state should either be moved to a CFNetwork-specific
- // ResourceRequest or should be removed.
Vector<String> m_responseContentDispositionEncodingFallbackArray;
-#endif
RefPtr<FormData> m_httpBody;
bool m_allowCookies : 1;
mutable bool m_resourceRequestUpdated : 1;
@@ -215,9 +207,7 @@ namespace WebCore {
String m_httpMethod;
OwnPtr<CrossThreadHTTPHeaderMapData> m_httpHeaders;
-#if PLATFORM(MAC) || PLATFORM(WIN)
Vector<String> m_responseContentDispositionEncodingFallbackArray;
-#endif
RefPtr<FormData> m_httpBody;
bool m_allowCookies;
ResourceLoadPriority m_priority;
diff --git a/Source/WebCore/platform/network/blackberry/CredentialBackingStore.cpp b/Source/WebCore/platform/network/blackberry/CredentialBackingStore.cpp
index bbb2bfc5e..acacc3789 100644
--- a/Source/WebCore/platform/network/blackberry/CredentialBackingStore.cpp
+++ b/Source/WebCore/platform/network/blackberry/CredentialBackingStore.cpp
@@ -28,6 +28,12 @@
#include "SQLiteStatement.h"
#include <wtf/UnusedParam.h>
+#define HANDLE_SQL_EXEC_FAILURE(statement, returnValue, ...) \
+ if (statement) { \
+ LOG_ERROR(__VAR_ARGS__); \
+ return returnValue; \
+ }
+
namespace WebCore {
CredentialBackingStore* CredentialBackingStore::instance()
@@ -49,69 +55,212 @@ CredentialBackingStore::CredentialBackingStore()
CredentialBackingStore::~CredentialBackingStore()
{
+ if (m_database.isOpen())
+ m_database.close();
}
bool CredentialBackingStore::open(const String& dbPath)
{
- UNUSED_PARAM(dbPath);
+ ASSERT(!m_database.isOpen());
- notImplemented();
- return false;
+ HANDLE_SQL_EXEC_FAILURE(!m_database.open(dbPath), false,
+ "Failed to open database file %s for login database", dbPath.utf8().data());
+
+ if (!m_database.tableExists("logins")) {
+ HANDLE_SQL_EXEC_FAILURE(!m_database.executeCommand("CREATE TABLE logins (origin_url VARCHAR NOT NULL, host VARCHAR NOT NULL, port INTEGER, service_type INTEGER NOT NULL, realm VARCHAR, auth_scheme INTEGER NOT NULL, username VARCHAR, password BLOB) "),
+ false, "Failed to create table logins for login database");
+
+ // Create index for table logins.
+ HANDLE_SQL_EXEC_FAILURE(!m_database.executeCommand("CREATE INDEX logins_signon ON logins (host)"),
+ false, "Failed to create index for table logins");
+ } else { // Initiate CredentialStorage.
+ SQLiteStatement query(m_database, "SELECT origin_url, host, port, service_type, realm, auth_scheme, username, password FROM logins");
+ HANDLE_SQL_EXEC_FAILURE(query.prepare() != SQLResultOk,
+ false, "Failed to prepare query statement to initiate CredentialStorage");
+
+ int result = query.step();
+ while (result == SQLResultRow) {
+ String strUrl = query.getColumnText(1);
+ String strHost = query.getColumnText(2);
+ int intPort = query.getColumnInt(3);
+ ProtectionSpaceServerType serviceType = static_cast<ProtectionSpaceServerType>(query.getColumnInt(4));
+ String strRealm = query.getColumnText(5);
+ ProtectionSpaceAuthenticationScheme authScheme = static_cast<ProtectionSpaceAuthenticationScheme>(query.getColumnInt(6));
+ String strUserName = query.getColumnText(7);
+ String strPassword = decryptedString(query.getColumnText(8));
+
+ KURL url(ParsedURLString, strUrl);
+ ProtectionSpace protectionSpace(strHost, intPort, serviceType, strRealm, authScheme);
+ Credential credential(strUserName, strPassword, CredentialPersistencePermanent);
+ CredentialStorage::set(credential, protectionSpace, url);
+
+ result = query.step();
+ }
+ }
+
+ // Prepare the statements.
+ m_addStatement = new SQLiteStatement(m_database, "INSERT OR REPLACE INTO logins (origin_url, host, port, service_type, realm, auth_scheme, username, password) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
+ HANDLE_SQL_EXEC_FAILURE(m_addStatement->prepare() != SQLResultOk,
+ false, "Failed to prepare addLogin statement");
+
+ m_updateStatement = new SQLiteStatement(m_database, "UPDATE logins SET username = ?, password = ? WHERE origin_url = ? AND host = ? AND port = ? AND service_type = ? AND realm = ? AND auth_scheme = ?");
+ HANDLE_SQL_EXEC_FAILURE(m_updateStatement->prepare() != SQLResultOk,
+ false, "Failed to prepare updateLogin statement");
+
+ m_hasStatement = new SQLiteStatement(m_database, "SELECT COUNT(*) FROM logins WHERE host = ? AND port = ? AND service_type = ? AND realm = ? AND auth_scheme = ?");
+ HANDLE_SQL_EXEC_FAILURE(m_hasStatement->prepare() != SQLResultOk,
+ false, "Failed to prepare hasLogin statement");
+
+ m_getStatement = new SQLiteStatement(m_database, "SELECT username, password FROM logins WHERE host = ? AND port = ? AND service_type = ? AND realm = ? AND auth_scheme = ?");
+ HANDLE_SQL_EXEC_FAILURE(m_getStatement->prepare() != SQLResultOk,
+ false, "Failed to prepare getLogin statement");
+
+ m_removeStatement = new SQLiteStatement(m_database, "DELETE FROM logins WHERE host = ? AND port = ? AND service_type = ? AND realm = ? AND auth_scheme = ?");
+ HANDLE_SQL_EXEC_FAILURE(m_removeStatement->prepare() != SQLResultOk,
+ false, "Failed to prepare removeLogin statement");
+
+ return true;
}
void CredentialBackingStore::close()
{
- notImplemented();
+ delete m_addStatement;
+ m_addStatement = 0;
+ delete m_updateStatement;
+ m_updateStatement = 0;
+ delete m_hasStatement;
+ m_hasStatement = 0;
+ delete m_getStatement;
+ m_getStatement = 0;
+ delete m_removeStatement;
+ m_removeStatement = 0;
+
+ if (m_database.isOpen())
+ m_database.close();
}
bool CredentialBackingStore::addLogin(const KURL& url, const ProtectionSpace& protectionSpace, const Credential& credential)
{
- UNUSED_PARAM(url);
- UNUSED_PARAM(protectionSpace);
- UNUSED_PARAM(credential);
+ ASSERT(m_database.isOpen());
+ ASSERT(m_database.tableExists("logins"));
- notImplemented();
- return false;
+ if (!m_addStatement)
+ return false;
+
+ m_addStatement->bindText(1, url.string());
+ m_addStatement->bindText(2, protectionSpace.host());
+ m_addStatement->bindInt(3, protectionSpace.port());
+ m_addStatement->bindInt(4, static_cast<int>(protectionSpace.serverType()));
+ m_addStatement->bindText(5, protectionSpace.realm());
+ m_addStatement->bindInt(6, static_cast<int>(protectionSpace.authenticationScheme()));
+ m_addStatement->bindText(7, credential.user());
+ m_addStatement->bindBlob(8, encryptedString(credential.password()));
+
+ int result = m_addStatement->step();
+ HANDLE_SQL_EXEC_FAILURE(result != SQLResultDone, false,
+ "Failed to add login info into table logins - %i", result);
+
+ return true;
}
bool CredentialBackingStore::updateLogin(const KURL& url, const ProtectionSpace& protectionSpace, const Credential& credential)
{
- UNUSED_PARAM(url);
- UNUSED_PARAM(protectionSpace);
- UNUSED_PARAM(credential);
+ ASSERT(m_database.isOpen());
+ ASSERT(m_database.tableExists("logins"));
- notImplemented();
- return false;
+ if (!m_updateStatement)
+ return false;
+
+ m_updateStatement->bindText(1, url.string());
+ m_updateStatement->bindText(2, credential.user());
+ m_updateStatement->bindBlob(3, encryptedString(credential.password()));
+ m_updateStatement->bindText(4, protectionSpace.host());
+ m_updateStatement->bindInt(5, protectionSpace.port());
+ m_updateStatement->bindInt(6, static_cast<int>(protectionSpace.serverType()));
+ m_updateStatement->bindText(7, protectionSpace.realm());
+ m_updateStatement->bindInt(8, static_cast<int>(protectionSpace.authenticationScheme()));
+
+ int result = m_updateStatement->step();
+ HANDLE_SQL_EXEC_FAILURE(result != SQLResultDone, false,
+ "Failed to update login info in table logins - %i", result);
+
+ return true;
}
bool CredentialBackingStore::hasLogin(const ProtectionSpace& protectionSpace)
{
- UNUSED_PARAM(protectionSpace);
+ ASSERT(m_database.isOpen());
+ ASSERT(m_database.tableExists("logins"));
- notImplemented();
+ if (!m_hasStatement)
+ return false;
+
+ m_hasStatement->bindText(1, protectionSpace.host());
+ m_hasStatement->bindInt(2, protectionSpace.port());
+ m_hasStatement->bindInt(3, static_cast<int>(protectionSpace.serverType()));
+ m_hasStatement->bindText(4, protectionSpace.realm());
+ m_hasStatement->bindInt(5, static_cast<int>(protectionSpace.authenticationScheme()));
+
+ int result = m_hasStatement->step();
+ HANDLE_SQL_EXEC_FAILURE(result != SQLResultRow, false,
+ "Failed to execute select login info from table logins in hasLogin - %i", result);
+
+ if (m_hasStatement->getColumnInt(0))
+ return true;
return false;
}
Credential CredentialBackingStore::getLogin(const ProtectionSpace& protectionSpace)
{
- UNUSED_PARAM(protectionSpace);
+ ASSERT(m_database.isOpen());
+ ASSERT(m_database.tableExists("logins"));
- notImplemented();
- return Credential();
+ if (!m_getStatement)
+ return Credential();
+
+ m_getStatement->bindText(1, protectionSpace.host());
+ m_getStatement->bindInt(2, protectionSpace.port());
+ m_getStatement->bindInt(3, static_cast<int>(protectionSpace.serverType()));
+ m_getStatement->bindText(4, protectionSpace.realm());
+ m_getStatement->bindInt(5, static_cast<int>(protectionSpace.authenticationScheme()));
+
+ int result = m_getStatement->step();
+ HANDLE_SQL_EXEC_FAILURE(result != SQLResultRow, Credential(),
+ "Failed to execute select login info from table logins in getLogin - %i", result);
+
+ return Credential(m_getStatement->getColumnText(0), decryptedString(m_getStatement->getColumnText(1)), CredentialPersistencePermanent);
}
bool CredentialBackingStore::removeLogin(const ProtectionSpace& protectionSpace)
{
- UNUSED_PARAM(protectionSpace);
+ ASSERT(m_database.isOpen());
+ ASSERT(m_database.tableExists("logins"));
- notImplemented();
- return false;
+ if (!m_removeStatement)
+ return false;
+
+ m_removeStatement->bindText(1, protectionSpace.host());
+ m_removeStatement->bindInt(2, protectionSpace.port());
+ m_removeStatement->bindInt(3, static_cast<int>(protectionSpace.serverType()));
+ m_removeStatement->bindText(4, protectionSpace.realm());
+ m_removeStatement->bindInt(5, static_cast<int>(protectionSpace.authenticationScheme()));
+
+ int result = m_removeStatement->step();
+ HANDLE_SQL_EXEC_FAILURE(result != SQLResultDone, false,
+ "Failed to remove login info from table logins - %i", result);
+
+ return true;
}
bool CredentialBackingStore::clear()
{
- notImplemented();
- return false;
+ ASSERT(m_database.isOpen());
+ ASSERT(m_database.tableExists("logins"));
+
+ HANDLE_SQL_EXEC_FAILURE(!m_database.executeCommand("DELETE * FROM logins"),
+ false, "Failed to clear table logins");
+
+ return true;
}
String CredentialBackingStore::encryptedString(const String& plainText) const
diff --git a/Source/WebCore/platform/network/blackberry/NetworkJob.cpp b/Source/WebCore/platform/network/blackberry/NetworkJob.cpp
index 2cf3d17df..fc7c416ee 100644
--- a/Source/WebCore/platform/network/blackberry/NetworkJob.cpp
+++ b/Source/WebCore/platform/network/blackberry/NetworkJob.cpp
@@ -316,7 +316,9 @@ void NetworkJob::handleNotifyHeaderReceived(const String& key, const String& val
}
if (lowerKey == "www-authenticate")
- handleAuthHeader(value);
+ 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))
handleFTPHeader(value);
@@ -701,7 +703,7 @@ void NetworkJob::parseData()
notifyClose(BlackBerry::Platform::FilterStream::StatusSuccess);
}
-bool NetworkJob::handleAuthHeader(const String& header)
+bool NetworkJob::handleAuthHeader(const ProtectionSpaceServerType space, const String& header)
{
if (!m_handle)
return false;
@@ -713,12 +715,12 @@ bool NetworkJob::handleAuthHeader(const String& header)
return false;
if (equalIgnoringCase(header, "ntlm"))
- sendRequestWithCredentials(ProtectionSpaceServerHTTP, ProtectionSpaceAuthenticationSchemeNTLM, "NTLM");
+ sendRequestWithCredentials(space, ProtectionSpaceAuthenticationSchemeNTLM, "NTLM");
// Extract the auth scheme and realm from the header.
size_t spacePos = header.find(' ');
if (spacePos == notFound) {
- LOG(Network, "WWW-Authenticate field '%s' badly formatted: missing scheme.", header.utf8().data());
+ LOG(Network, "%s-Authenticate field '%s' badly formatted: missing scheme.", space == ProtectionSpaceServerHTTP ? "WWW" : "Proxy", header.utf8().data());
return false;
}
@@ -736,7 +738,7 @@ bool NetworkJob::handleAuthHeader(const String& header)
size_t realmPos = header.findIgnoringCase("realm=", spacePos);
if (realmPos == notFound) {
- LOG(Network, "WWW-Authenticate field '%s' badly formatted: missing realm.", header.utf8().data());
+ LOG(Network, "%s-Authenticate field '%s' badly formatted: missing realm.", space == ProtectionSpaceServerHTTP ? "WWW" : "Proxy", header.utf8().data());
return false;
}
size_t beginPos = realmPos + 6;
@@ -745,14 +747,14 @@ bool NetworkJob::handleAuthHeader(const String& header)
beginPos += 1;
size_t endPos = header.find("\"", beginPos);
if (endPos == notFound) {
- LOG(Network, "WWW-Authenticate field '%s' badly formatted: invalid realm.", header.utf8().data());
+ LOG(Network, "%s-Authenticate field '%s' badly formatted: invalid realm.", space == ProtectionSpaceServerHTTP ? "WWW" : "Proxy", header.utf8().data());
return false;
}
realm = header.substring(beginPos, endPos - beginPos);
}
// Get the user's credentials and resend the request.
- sendRequestWithCredentials(ProtectionSpaceServerHTTP, protectionSpaceScheme, realm);
+ sendRequestWithCredentials(space, protectionSpaceScheme, realm);
return true;
}
@@ -796,7 +798,15 @@ bool NetworkJob::sendRequestWithCredentials(ProtectionSpaceServerType type, Prot
if (!newURL.isValid())
return false;
- ProtectionSpace protectionSpace(m_response.url().host(), m_response.url().port(), type, realm, scheme);
+ int port = 0;
+ if (type == ProtectionSpaceProxyHTTP) {
+ std::stringstream toPort(BlackBerry::Platform::Client::get()->getProxyPort());
+ toPort >> port;
+ } else
+ port = m_response.url().port();
+
+ ProtectionSpace protectionSpace((type == ProtectionSpaceProxyHTTP) ? BlackBerry::Platform::Client::get()->getProxyAddress().c_str() : m_response.url().host()
+ , port, type, realm, scheme);
// We've got the scheme and realm. Now we need a username and password.
// First search the CredentialStorage.
diff --git a/Source/WebCore/platform/network/blackberry/NetworkJob.h b/Source/WebCore/platform/network/blackberry/NetworkJob.h
index 3781610df..4d60a6aed 100644
--- a/Source/WebCore/platform/network/blackberry/NetworkJob.h
+++ b/Source/WebCore/platform/network/blackberry/NetworkJob.h
@@ -129,7 +129,7 @@ private:
// The server needs authentication credentials. Search in the
// CredentialStorage or prompt the user via dialog.
- bool handleAuthHeader(const String& header);
+ bool handleAuthHeader(const ProtectionSpaceServerType, const String& header);
bool handleFTPHeader(const String& header);
diff --git a/Source/WebCore/platform/network/blackberry/NetworkManager.cpp b/Source/WebCore/platform/network/blackberry/NetworkManager.cpp
index 38f09e618..077b4c219 100644
--- a/Source/WebCore/platform/network/blackberry/NetworkManager.cpp
+++ b/Source/WebCore/platform/network/blackberry/NetworkManager.cpp
@@ -104,6 +104,8 @@ bool NetworkManager::startJob(int playerId, const String& pageGroupName, PassRef
}
} else if (type == ProtectionSpaceServerFTP)
authType = BlackBerry::Platform::NetworkRequest::AuthFTP;
+ else if (type == ProtectionSpaceProxyHTTP)
+ authType = BlackBerry::Platform::NetworkRequest::AuthProxy;
if (authType != BlackBerry::Platform::NetworkRequest::AuthNone)
platformRequest.setCredentials(username.utf8().data(), password.utf8().data(), authType);
diff --git a/Source/WebCore/platform/network/blackberry/ResourceRequestBlackBerry.cpp b/Source/WebCore/platform/network/blackberry/ResourceRequestBlackBerry.cpp
index 8416862f2..d86b88cf1 100644
--- a/Source/WebCore/platform/network/blackberry/ResourceRequestBlackBerry.cpp
+++ b/Source/WebCore/platform/network/blackberry/ResourceRequestBlackBerry.cpp
@@ -96,6 +96,8 @@ void ResourceRequest::initializePlatformRequest(NetworkRequest& platformRequest,
platformTargetTypeForRequest(*this),
timeoutInterval());
+ platformRequest.setConditional(isConditional());
+
if (httpBody() && !httpBody()->isEmpty()) {
const Vector<FormDataElement>& elements = httpBody()->elements();
// Use setData for simple forms because it is slightly more efficient.
diff --git a/Source/WebCore/platform/network/cf/AuthenticationChallenge.h b/Source/WebCore/platform/network/cf/AuthenticationChallenge.h
index ca4a06c55..109ede81b 100644
--- a/Source/WebCore/platform/network/cf/AuthenticationChallenge.h
+++ b/Source/WebCore/platform/network/cf/AuthenticationChallenge.h
@@ -31,14 +31,17 @@
#include <wtf/RefPtr.h>
#if USE(CFNETWORK)
+
typedef struct _CFURLAuthChallenge* CFURLAuthChallengeRef;
+
#else
+
#ifndef __OBJC__
typedef struct objc_object *id;
-class NSURLAuthenticationChallenge;
-#else
-@class NSURLAuthenticationChallenge;
#endif
+
+OBJC_CLASS NSURLAuthenticationChallenge;
+
#endif
namespace WebCore {
diff --git a/Source/WebCore/platform/network/cf/ResourceError.h b/Source/WebCore/platform/network/cf/ResourceError.h
index 27c63ff5f..30e0a5ea0 100644
--- a/Source/WebCore/platform/network/cf/ResourceError.h
+++ b/Source/WebCore/platform/network/cf/ResourceError.h
@@ -37,10 +37,8 @@
#include <wincrypt.h> // windows.h must be included before wincrypt.h.
#endif
-#ifdef __OBJC__
-@class NSError;
-#else
-class NSError;
+#if PLATFORM(MAC)
+OBJC_CLASS NSError;
#endif
namespace WebCore {
diff --git a/Source/WebCore/platform/network/cf/ResourceRequest.h b/Source/WebCore/platform/network/cf/ResourceRequest.h
index 47b155b71..72522d9ed 100644
--- a/Source/WebCore/platform/network/cf/ResourceRequest.h
+++ b/Source/WebCore/platform/network/cf/ResourceRequest.h
@@ -34,11 +34,7 @@
typedef const struct _CFURLRequest* CFURLRequestRef;
#endif
-#ifdef __OBJC__
-@class NSURLRequest;
-#else
-class NSURLRequest;
-#endif
+OBJC_CLASS NSURLRequest;
#if USE(CFURLSTORAGESESSIONS) && (defined(BUILDING_ON_SNOW_LEOPARD) || defined(BUILDING_ON_LEOPARD))
typedef struct __CFURLStorageSession* CFURLStorageSessionRef;
diff --git a/Source/WebCore/platform/network/cf/ResourceResponse.h b/Source/WebCore/platform/network/cf/ResourceResponse.h
index 946eee083..d83a6610f 100644
--- a/Source/WebCore/platform/network/cf/ResourceResponse.h
+++ b/Source/WebCore/platform/network/cf/ResourceResponse.h
@@ -33,11 +33,7 @@
typedef struct _CFURLResponse* CFURLResponseRef;
#endif
-#ifdef __OBJC__
-@class NSURLResponse;
-#else
-class NSURLResponse;
-#endif
+OBJC_CLASS NSURLResponse;
namespace WebCore {
diff --git a/Source/WebCore/platform/network/soup/ResourceResponse.h b/Source/WebCore/platform/network/soup/ResourceResponse.h
index 6ebba8b55..8624c0591 100644
--- a/Source/WebCore/platform/network/soup/ResourceResponse.h
+++ b/Source/WebCore/platform/network/soup/ResourceResponse.h
@@ -42,6 +42,7 @@ public:
ResourceResponse(const KURL& url, const String& mimeType, long long expectedLength, const String& textEncodingName, const String& filename)
: ResourceResponseBase(url, mimeType, expectedLength, textEncodingName, filename)
+ , m_soupFlags(static_cast<SoupMessageFlags>(0))
{
}
diff --git a/Source/WebCore/platform/qt/DataTransferItemListQt.cpp b/Source/WebCore/platform/qt/DataTransferItemListQt.cpp
index 45fb6bc76..1806a7f6f 100644
--- a/Source/WebCore/platform/qt/DataTransferItemListQt.cpp
+++ b/Source/WebCore/platform/qt/DataTransferItemListQt.cpp
@@ -40,10 +40,73 @@ PassRefPtr<DataTransferItemListQt> DataTransferItemListQt::create(PassRefPtr<Cli
}
DataTransferItemListQt::DataTransferItemListQt(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context)
- : DataTransferItemList(owner, context)
+ : m_owner(clipboard)
+ , m_context(context)
{
}
+size_t DataTransferItemListQt::length() const
+{
+ if (m_owner->policy() == ClipboardNumb)
+ return 0;
+
+ return m_items.size();
+}
+
+PassRefPtr<DataTransferItem> DataTransferItemListQt::item(unsigned long index)
+{
+ if (m_owner->policy() == ClipboardNumb || index >= length())
+ return 0;
+
+ return m_items[index];
+}
+
+void DataTransferItemListQt::deleteItem(unsigned long index, ExceptionCode& ec)
+{
+ if (m_owner->policy() != ClipboardWritable) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+
+ if (index >= length())
+ return;
+
+ m_items.remove(index);
+}
+
+void DataTransferItemListQt::clear()
+{
+ if (m_owner->policy() != ClipboardWritable)
+ return;
+
+ m_items.clear();
+
+}
+
+void DataTransferItemListQt::add(const String& data, const String& type, ExceptionCode& ec)
+{
+ if (m_owner->policy() != ClipboardWritable)
+ return;
+
+ // Only one 'string' item with a given type is allowed in the collection.
+ for (size_t i = 0; i < m_items.size(); ++i) {
+ if (m_items[i]->type() == type && m_items[i]->kind() == DataTransferItem::kindString) {
+ ec = NOT_SUPPORTED_ERR;
+ return;
+ }
+ }
+
+ m_items.append(DataTransferItem::create(m_owner, m_context, data, type));
+}
+
+void DataTransferItemListQt::add(PassRefPtr<File> file)
+{
+ if (m_owner->policy() != ClipboardWritable || !file)
+ return;
+
+ m_items.append(DataTransferItem::create(m_owner, m_context, file));
+}
+
void DataTransferItemListQt::addPasteboardItem(const String& type)
{
m_items.append(DataTransferItemQt::createFromPasteboard(m_owner, m_context, type));
diff --git a/Source/WebCore/platform/qt/DataTransferItemListQt.h b/Source/WebCore/platform/qt/DataTransferItemListQt.h
index 1442563ee..d5c39a4a5 100644
--- a/Source/WebCore/platform/qt/DataTransferItemListQt.h
+++ b/Source/WebCore/platform/qt/DataTransferItemListQt.h
@@ -42,11 +42,24 @@ class DataTransferItemListQt : public DataTransferItemList {
public:
static PassRefPtr<DataTransferItemListQt> create(PassRefPtr<Clipboard>, ScriptExecutionContext*);
+ 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>);
+
+
friend class ClipboardQt;
private:
DataTransferItemListQt(PassRefPtr<Clipboard>, ScriptExecutionContext*);
virtual void addPasteboardItem(const String& type);
+
+ RefPtr<Clipboard> m_owner;
+ // Indirectly owned by our parent.
+ ScriptExecutionContext* m_context;
+ Vector<RefPtr<DataTransferItem> > m_items;
};
}
diff --git a/Source/WebCore/platform/qt/DataTransferItemQt.cpp b/Source/WebCore/platform/qt/DataTransferItemQt.cpp
index b277bef04..9ff621ef4 100644
--- a/Source/WebCore/platform/qt/DataTransferItemQt.cpp
+++ b/Source/WebCore/platform/qt/DataTransferItemQt.cpp
@@ -31,6 +31,7 @@
#include "Blob.h"
#include "Clipboard.h"
+#include "File.h"
#include "NotImplemented.h"
#include "StringCallback.h"
#include <QApplication>
@@ -40,12 +41,19 @@
namespace WebCore {
-PassRefPtr<DataTransferItem> DataTransferItem::create(PassRefPtr<Clipboard> owner,
- ScriptExecutionContext* context,
- const String& data,
- const String& type)
+PassRefPtr<DataTransferItemQt> DataTransferItemQt::create(PassRefPtr<Clipboard> owner,
+ ScriptExecutionContext* context,
+ const String& data,
+ const String& type)
+{
+ return adoptRef(new DataTransferItemQt(owner, context, DataTransferItemQt::InternalSource, kindString, type, data));
+}
+
+PassRefPtr<DataTransferItemQt> DataTransferItemQt::create(PassRefPtr<Clipboard> owner,
+ ScriptExecutionContext* context,
+ PassRefPtr<File> file)
{
- return DataTransferItemQt::create(owner, context, type, data);
+ return adoptRef(new DataTransferItemQt(owner, context, DataTransferItemQt::InternalSource, file));
}
PassRefPtr<DataTransferItemQt> DataTransferItemQt::createFromPasteboard(PassRefPtr<Clipboard> owner,
@@ -58,27 +66,34 @@ PassRefPtr<DataTransferItemQt> DataTransferItemQt::createFromPasteboard(PassRefP
return adoptRef(new DataTransferItemQt(owner, context, PasteboardSource, DataTransferItem::kindFile, type, ""));
}
-PassRefPtr<DataTransferItemQt> DataTransferItemQt::create(PassRefPtr<Clipboard> owner,
- ScriptExecutionContext* context,
- const String& type,
- const String& data)
-{
- return adoptRef(new DataTransferItemQt(owner, context, InternalSource, DataTransferItem::kindString, type, data));
-}
-
DataTransferItemQt::DataTransferItemQt(PassRefPtr<Clipboard> owner,
ScriptExecutionContext* context,
DataSource source,
const String& kind, const String& type,
const String& data)
- : DataTransferItem(owner, kind, type)
+ : m_owner(owner)
, m_context(context)
+ , m_kind(kind)
+ , m_type(type)
, m_dataSource(source)
, m_data(data)
{
}
-void DataTransferItemQt::getAsString(PassRefPtr<StringCallback> callback)
+DataTransferItemQt::DataTransferItemQt(PassRefPtr<Clipboard> owner,
+ ScriptExecutionContext* context,
+ DataSource source,
+ PassRefPtr<File> file)
+ : m_owner(owner)
+ , m_context(context)
+ , m_kind(kindFile)
+ , m_type(file.get() ? file->type() : "");
+ , m_source(source)
+ , m_file(file)
+{
+}
+
+void DataTransferItemQt::getAsString(PassRefPtr<StringCallback> callback) const
{
if ((owner()->policy() != ClipboardReadable && owner()->policy() != ClipboardWritable)
|| kind() != kindString)
@@ -106,9 +121,11 @@ void DataTransferItemQt::getAsString(PassRefPtr<StringCallback> callback)
callback->scheduleCallback(m_context, data);
}
-PassRefPtr<Blob> DataTransferItemQt::getAsFile()
+PassRefPtr<Blob> DataTransferItemQt::getAsFile() const
{
- notImplemented();
+ if (kind() == kindFile && m_dataSource == InternalSource)
+ return m_file;
+
return 0;
}
diff --git a/Source/WebCore/platform/qt/DataTransferItemQt.h b/Source/WebCore/platform/qt/DataTransferItemQt.h
index 025ba4161..de88b8ad2 100644
--- a/Source/WebCore/platform/qt/DataTransferItemQt.h
+++ b/Source/WebCore/platform/qt/DataTransferItemQt.h
@@ -34,22 +34,25 @@
namespace WebCore {
class Clipboard;
+class File;
class ScriptExecutionContext;
class DataTransferItemQt : public DataTransferItem {
public:
+ static PassRefPtr<DataTransferItemQt> create(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, const String& data, const String& type);
+ static PassRefPtr<DataTransferItemQt> create(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, PassRefPtr<File>);
static PassRefPtr<DataTransferItemQt> createFromPasteboard(PassRefPtr<Clipboard> owner,
ScriptExecutionContext*,
const String&);
- static PassRefPtr<DataTransferItemQt> create(PassRefPtr<Clipboard> owner,
- ScriptExecutionContext*,
- const String&,
- const String&);
- virtual void getAsString(PassRefPtr<StringCallback>);
- virtual PassRefPtr<Blob> getAsFile();
+ 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 DataTransferItemListQt;
+
enum DataSource {
PasteboardSource,
InternalSource
@@ -59,10 +62,18 @@ private:
ScriptExecutionContext*,
DataSource,
const String&, const String&, const String&);
+ DataTransferItemQt(PassRefPtr<Clipboard> owner,
+ ScriptExecutionContext*,
+ DataSource,
+ PassRefPtr<File>);
+ const RefPtr<Clipboard> m_owner;
ScriptExecutionContext* m_context;
+ const String m_kind;
+ const String m_type;
const DataSource m_dataSource;
const String m_data;
+ RefPtr<File> m_file;
};
}
diff --git a/Source/WebCore/platform/qt/LanguageQt.cpp b/Source/WebCore/platform/qt/LanguageQt.cpp
index 5a1d70721..bdccfcd5e 100644
--- a/Source/WebCore/platform/qt/LanguageQt.cpp
+++ b/Source/WebCore/platform/qt/LanguageQt.cpp
@@ -29,13 +29,21 @@
#include "PlatformString.h"
#include <QLocale>
+#include <wtf/Vector.h>
namespace WebCore {
-String platformDefaultLanguage()
+static String platformLanguage()
{
QLocale locale;
return locale.name().replace(QLatin1Char('_'), QLatin1Char('-'));
}
+Vector<String> platformUserPreferredLanguages()
+{
+ Vector<String> userPreferredLanguages;
+ userPreferredLanguages.append(platformLanguage());
+ return userPreferredLanguages;
+}
+
}
diff --git a/Source/WebCore/platform/qt/PlatformScreenQt.cpp b/Source/WebCore/platform/qt/PlatformScreenQt.cpp
index 7a267fc6c..846f0b8a4 100644
--- a/Source/WebCore/platform/qt/PlatformScreenQt.cpp
+++ b/Source/WebCore/platform/qt/PlatformScreenQt.cpp
@@ -102,15 +102,15 @@ bool screenIsMonochrome(Widget* w)
return QApplication::desktop()->screen(screenNumber(w))->colorCount() == 2;
}
-FloatRect screenRect(Widget* w)
+FloatRect screenRect(FrameView* frameView)
{
- QRect r = QApplication::desktop()->screenGeometry(screenNumber(w));
+ QRect r = QApplication::desktop()->screenGeometry(screenNumber(frameView));
return FloatRect(r.x(), r.y(), r.width(), r.height());
}
-FloatRect screenAvailableRect(Widget* w)
+FloatRect screenAvailableRect(FrameView* frameView)
{
- QRect r = QApplication::desktop()->availableGeometry(screenNumber(w));
+ QRect r = QApplication::desktop()->availableGeometry(screenNumber(frameView));
return FloatRect(r.x(), r.y(), r.width(), r.height());
}
diff --git a/Source/WebCore/platform/qt/PlatformTouchPointQt.cpp b/Source/WebCore/platform/qt/PlatformTouchPointQt.cpp
index c2932129c..ee5e56df7 100644
--- a/Source/WebCore/platform/qt/PlatformTouchPointQt.cpp
+++ b/Source/WebCore/platform/qt/PlatformTouchPointQt.cpp
@@ -1,7 +1,7 @@
/*
* This file is part of the WebKit project.
*
- * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+ * 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
@@ -28,17 +28,29 @@
namespace WebCore {
PlatformTouchPoint::PlatformTouchPoint(const QTouchEvent::TouchPoint& point)
-{
// The QTouchEvent::TouchPoint API states that ids will be >= 0.
- m_id = static_cast<unsigned>(point.id());
+ : m_id(point.id())
+ , m_screenPos(point.screenPos().toPoint())
+ , m_pos(point.pos().toPoint())
+{
switch (point.state()) {
case Qt::TouchPointReleased: m_state = TouchReleased; break;
case Qt::TouchPointMoved: m_state = TouchMoved; break;
case Qt::TouchPointPressed: m_state = TouchPressed; break;
case Qt::TouchPointStationary: m_state = TouchStationary; break;
}
- 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.
}
}
diff --git a/Source/WebCore/platform/qt/RenderThemeQtMobile.cpp b/Source/WebCore/platform/qt/RenderThemeQtMobile.cpp
index ca47cf93d..c2f4228b0 100644
--- a/Source/WebCore/platform/qt/RenderThemeQtMobile.cpp
+++ b/Source/WebCore/platform/qt/RenderThemeQtMobile.cpp
@@ -63,6 +63,7 @@ static const int radioWidth = 21;
static const int sliderSize = 19;
static const int buttonHeightRatio = 1.5;
+static const float multipleComboDotsOffsetFactor = 1.8;
static const float buttonPaddingLeft = 18;
static const float buttonPaddingRight = 18;
static const float buttonPaddingTop = 2;
@@ -80,6 +81,18 @@ static const QColor highlightColor(16, 128, 221);
static const QColor buttonGradientBottom(245, 245, 245);
static const QColor shadowColor(80, 80, 80, 160);
+static QHash<KeyIdentifier, CacheKey> cacheKeys;
+
+uint qHash(const KeyIdentifier& id)
+{
+ const quint32 value = id.trait1 + (id.trait2 << 1) + (uint(id.type) << 2) + (id.height << 5) + (id.width << 14) + (id.trait3 << 25);
+ const unsigned char* p = reinterpret_cast<const unsigned char*>(&value);
+ uint hash = 0;
+ for (int i = 0; i < 4; ++i)
+ hash ^= (hash << 5) + (hash >> 2) + p[i];
+ return hash;
+}
+
static void drawControlBackground(QPainter* painter, const QPen& pen, const QRect& rect, const QBrush& brush)
{
QPen oldPen = painter->pen();
@@ -150,6 +163,28 @@ StylePainterMobile::~StylePainterMobile()
painter->setRenderHints(QPainter::SmoothPixmapTransform, m_previousSmoothPixmapTransform);
}
+bool StylePainterMobile::findCachedControl(const KeyIdentifier& keyId, QPixmap* result)
+{
+ static CacheKey emptyKey;
+ CacheKey key = cacheKeys.value(keyId, emptyKey);
+ if (key == emptyKey)
+ return false;
+ const bool ret = QPixmapCache::find(key, result);
+ if (!ret)
+ cacheKeys.remove(keyId);
+ return ret;
+}
+
+void StylePainterMobile::insertIntoCache(const KeyIdentifier& keyId, const QPixmap& pixmap)
+{
+ ASSERT(keyId.type);
+ const int sizeInKiloBytes = pixmap.width() * pixmap.height() * pixmap.depth() / (8 * 1024);
+ // Don't cache pixmaps over 512 KB;
+ if (sizeInKiloBytes > 512)
+ return;
+ cacheKeys.insert(keyId, QPixmapCache::insert(pixmap));
+}
+
void StylePainterMobile::drawCheckableBackground(QPainter* painter, const QRect& rect, bool checked, bool enabled) const
{
QBrush brush;
@@ -196,10 +231,12 @@ QPixmap StylePainterMobile::findCheckBox(const QSize& size, bool checked, bool e
{
ASSERT(size.width() == size.height());
QPixmap result;
- static const QString prefix = QLatin1String("$qt-webkit-mobile-theme-checkbox-");
- QString key = prefix + QString::number(size.width()) + QLatin1String("-") + (enabled ? QLatin1String("on") : QLatin1String("off"))
- + (checked ? QLatin1String("-checked") : QString());
- if (!QPixmapCache::find(key, result)) {
+ KeyIdentifier id;
+ id.type = KeyIdentifier::CheckBox;
+ id.height = size.height();
+ id.trait1 = enabled;
+ id.trait2 = checked;
+ if (!findCachedControl(id, &result)) {
result = QPixmap(size);
result.fill(Qt::transparent);
QPainter cachePainter(&result);
@@ -207,14 +244,13 @@ QPixmap StylePainterMobile::findCheckBox(const QSize& size, bool checked, bool e
drawCheckableBackground(&cachePainter, rect, checked, enabled);
if (checked || !enabled)
drawChecker(&cachePainter, rect, enabled ? Qt::white : Qt::gray);
- QPixmapCache::insert(key, result);
+ insertIntoCache(id, result);
}
return result;
}
void StylePainterMobile::drawRadio(QPainter* painter, const QSize& size, bool checked, bool enabled) const
{
- ASSERT(size.width() == size.height());
QRect rect(QPoint(0, 0), size);
drawCheckableBackground(painter, rect, checked, enabled);
@@ -225,21 +261,24 @@ void StylePainterMobile::drawRadio(QPainter* painter, const QSize& size, bool ch
QPixmap StylePainterMobile::findRadio(const QSize& size, bool checked, bool enabled) const
{
+ ASSERT(size.width() == size.height());
QPixmap result;
- static const QString prefix = QLatin1String("$qt-webkit-mobile-theme-radio-");
- QString key = prefix + QString::number(size.width()) + QLatin1String("-") + (enabled ? QLatin1String("on") : QLatin1String("off"))
- + (checked ? QLatin1String("-checked") : QString());
- if (!QPixmapCache::find(key, result)) {
+ KeyIdentifier id;
+ id.type = KeyIdentifier::Radio;
+ id.height = size.height();
+ id.trait1 = enabled;
+ id.trait2 = checked;
+ if (!findCachedControl(id, &result)) {
result = QPixmap(size);
result.fill(Qt::transparent);
QPainter cachePainter(&result);
drawRadio(&cachePainter, size, checked, enabled);
- QPixmapCache::insert(key, result);
+ insertIntoCache(id, result);
}
return result;
}
-void StylePainterMobile::drawMultipleComboButton(QPainter* painter, const QSize& size, const QColor& color) const
+void StylePainterMobile::drawMultipleComboButton(QPainter* painter, const QSizeF& size, const QColor& color) const
{
const qreal dotDiameter = size.height();
const qreal dotRadii = dotDiameter / 2;
@@ -248,59 +287,66 @@ void StylePainterMobile::drawMultipleComboButton(QPainter* painter, const QSize&
painter->setPen(color);
painter->setBrush(color);
- const qreal offsetFactor = 1.8;
for (int i = 0; i < 3; ++i) {
- QPointF center(offsetFactor * dotRadii + i * offsetFactor * dotDiameter, dotRadii);
+ QPointF center(dotRadii + i * multipleComboDotsOffsetFactor * dotDiameter, dotRadii);
painter->drawEllipse(center, dotRadii, dotRadii);
}
}
-void StylePainterMobile::drawSimpleComboButton(QPainter* painter, const QSize& size, const QColor& color) const
+void StylePainterMobile::drawSimpleComboButton(QPainter* painter, const QSizeF& size, const QColor& color) const
{
- const int gap = (size.height() - 1) / 5;
- const int arrowHeight = 2 * gap;
- const int right = arrowHeight * 2;
- const int bottomBaseline = arrowHeight + gap + 1;
- QPolygon upArrow, downArrow;
- upArrow << QPoint(0, arrowHeight) << QPoint(arrowHeight, 0) << QPoint(right, arrowHeight);
- downArrow << QPoint(0, bottomBaseline) << QPoint(arrowHeight, bottomBaseline + arrowHeight)
- << QPoint(right, bottomBaseline);
+ const qreal gap = size.height() / 5.0;
+ const qreal arrowHeight = (size.height() - gap) / 2.0;
+ const qreal right = arrowHeight * 2;
+ const qreal bottomBaseline = size.height() - arrowHeight;
+ QPolygonF upArrow, downArrow;
+ upArrow << QPointF(0, arrowHeight) << QPointF(arrowHeight, 0) << QPointF(right, arrowHeight);
+ downArrow << QPointF(0, bottomBaseline) << QPointF(arrowHeight, bottomBaseline + arrowHeight)
+ << QPointF(right, bottomBaseline);
- painter->setPen(color);
+ painter->setPen(Qt::NoPen);
painter->setBrush(color);
painter->drawPolygon(upArrow);
painter->drawPolygon(downArrow);
}
-QSize StylePainterMobile::getButtonImageSize(int buttonHeight, bool multiple) const
+QSizeF StylePainterMobile::getButtonImageSize(int buttonHeight, bool multiple) const
{
if (multiple)
- return QSize(buttonHeight / 2, buttonHeight / 10);
+ return QSizeF(qreal(2 + buttonHeight * 3 * multipleComboDotsOffsetFactor/ 10.0)
+ , qreal(2 + buttonHeight / 10.0));
- const int height = buttonHeight / 2.5;
- const int width = 4 * height / 5;
- return QSize(width, height);
+ const qreal height = buttonHeight / 2.5;
+ const qreal width = 4 * height / 5.0;
+ return QSizeF(2 + width, 2 + height);
}
QPixmap StylePainterMobile::findComboButton(const QSize& size, bool multiple, bool enabled) const
{
if (size.isNull())
return QPixmap();
- static const QString prefix = QLatin1String("$qt-webkit-mobile-theme-combo-");
QPixmap result;
- QString key = prefix + (multiple ? QLatin1String("multiple-") : QLatin1String("simple-"))
- + QString::number(size.width()) + QLatin1String("-") + QString::number(size.height())
- + QLatin1String("-") + (enabled ? QLatin1String("on") : QLatin1String("off"));
-
- if (!QPixmapCache::find(key, result)) {
+ KeyIdentifier id;
+ id.type = KeyIdentifier::ComboButton;
+ id.width = size.width();
+ id.height = size.height();
+ id.trait1 = multiple;
+ id.trait2 = enabled;
+
+ if (!findCachedControl(id, &result)) {
result = QPixmap(size);
+ const qreal border = painterScale(painter);
+ const QSizeF padding(2 * border, 2 * border);
+ const QSizeF innerSize = size - padding;
+ ASSERT(innerSize.isValid());
result.fill(Qt::transparent);
QPainter cachePainter(&result);
+ cachePainter.translate(border, border);
if (multiple)
- drawMultipleComboButton(&cachePainter, size, enabled ? darkColor : Qt::lightGray);
+ drawMultipleComboButton(&cachePainter, innerSize, enabled ? darkColor : Qt::lightGray);
else
- drawSimpleComboButton(&cachePainter, size, enabled ? darkColor : Qt::lightGray);
- QPixmapCache::insert(key, result);
+ drawSimpleComboButton(&cachePainter, innerSize, enabled ? darkColor : Qt::lightGray);
+ insertIntoCache(id, result);
}
return result;
}
@@ -317,10 +363,13 @@ void StylePainterMobile::drawLineEdit(const QRect& rect, bool focused, bool enab
QPixmap StylePainterMobile::findLineEdit(const QSize & size, bool focused) const
{
QPixmap result;
- static const QString prefix = QLatin1String("$qt-webkit-mobile-theme-lineEdit-");
- QString key = prefix + QString::number(size.width()) + QLatin1String("x") + QString::number(size.height())
- + (focused ? QLatin1String("-focused") : QString());
- if (!QPixmapCache::find(key, result)) {
+ KeyIdentifier id;
+ id.type = KeyIdentifier::LineEdit;
+ id.width = size.width();
+ id.height = size.height();
+ id.trait1 = focused;
+
+ if (!findCachedControl(id, &result)) {
const int focusFrame = painterScale(painter);
result = QPixmap(size + QSize(2 * focusFrame, 2 * focusFrame));
result.fill(Qt::transparent);
@@ -332,7 +381,7 @@ QPixmap StylePainterMobile::findLineEdit(const QSize & size, bool focused) const
QPen focusPen(highlightColor, focusFrame, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
drawControlBackground(&cachePainter, focusPen, rect, Qt::NoBrush);
}
- QPixmapCache::insert(key, result);
+ insertIntoCache(id, result);
}
return result;
}
@@ -366,10 +415,13 @@ void StylePainterMobile::drawPushButton(const QRect& rect, bool sunken, bool ena
QPixmap StylePainterMobile::findPushButton(const QSize& size, bool sunken, bool enabled) const
{
QPixmap result;
- static const QString prefix = QLatin1String("$qt-webkit-mobile-theme-pushButton-");
- QString key = prefix + QString::number(size.width()) + QLatin1String("x") + QString::number(size.height())
- + (sunken ? QLatin1String("-sunken") : QString()) + (enabled ? QLatin1String("-on") : QString());
- if (!QPixmapCache::find(key, result)) {
+ KeyIdentifier id;
+ id.type = KeyIdentifier::PushButton;
+ id.width = size.width();
+ id.height = size.height();
+ id.trait1 = sunken;
+ id.trait2 = enabled;
+ if (!findCachedControl(id, &result)) {
const qreal dropShadowSize = painterScale(painter);
result = QPixmap(size);
result.fill(Qt::transparent);
@@ -396,7 +448,7 @@ QPixmap StylePainterMobile::findPushButton(const QSize& size, bool sunken, bool
brush = linearGradient;
}
drawControlBackground(&cachePainter, borderPen(painter), rect, brush);
- QPixmapCache::insert(key, result);
+ insertIntoCache(id, result);
}
return result;
}
@@ -407,28 +459,31 @@ void StylePainterMobile::drawComboBox(const QRect& rect, bool multiple, bool ena
if (pushButton.isNull())
return;
painter->drawPixmap(rect, pushButton);
- QRect targetRect(QPoint(0, 0), getButtonImageSize(rect.height() - 1, multiple));
- const QPoint buttonCenter(rect.right() - arrowBoxWidth / 2, rect.height() / 2 - 1);
+ QRectF targetRect(QPointF(0, 0), getButtonImageSize(rect.height() - 1, multiple));
+ const QPointF buttonCenter(rect.right() - arrowBoxWidth / 2, rect.top() + (rect.height() - 1) / 2);
targetRect.moveCenter(buttonCenter);
- QPixmap pic = findComboButton(sizeForPainterScale(targetRect), multiple, enabled);
+ QPixmap pic = findComboButton(sizeForPainterScale(targetRect.toRect()), multiple, enabled);
if (pic.isNull())
return;
- painter->drawPixmap(targetRect, pic);
+ painter->drawPixmap(targetRect.toRect(), pic);
}
void StylePainterMobile::drawProgress(const QRect& rect, double progress, bool leftToRight, bool animated) const
{
- static const QString prefix = QLatin1String("$qt-webkit-mobile-theme-progress-");
const int border = rect.height() / 4;
const QRect targetRect = rect.adjusted(0, border, 0, -border);
QPixmap result;
const QSize imageSize = sizeForPainterScale(targetRect);
- QString key = prefix + QString::number(imageSize.width()) + QLatin1String("-") + QString::number(imageSize.height())
- + QLatin1String("-") + QString::number(progress, 'f', 3) + (animated? QLatin1String("-anim") : QString())
- + ((!animated && !leftToRight) ? QLatin1String("-rtl") : QString());
- if (!QPixmapCache::find(key, result)) {
+ KeyIdentifier id;
+ id.type = KeyIdentifier::Progress;
+ id.width = imageSize.width();
+ id.height = imageSize.height();
+ id.trait1 = animated;
+ id.trait2 = (!animated && !leftToRight);
+ id.trait3 = progress * 100;
+ if (!findCachedControl(id, &result)) {
if (imageSize.isNull())
return;
result = QPixmap(imageSize);
@@ -463,25 +518,28 @@ void StylePainterMobile::drawProgress(const QRect& rect, double progress, bool l
radius = radiusFactor * progressRect.height();
painter.drawRoundedRect(progressRect, radius, radius);
}
- QPixmapCache::insert(key, result);
+ insertIntoCache(id, result);
}
painter->drawPixmap(targetRect, result);
}
void StylePainterMobile::drawSliderThumb(const QRect & rect, bool pressed) const
{
- static const QString prefix = QLatin1String("$qt-webkit-mobile-theme-slider-thumb-");
QPixmap result;
const QSize size = sizeForPainterScale(rect);
- const QString key = prefix + QString::number(size.width());
- if (!QPixmapCache::find(key, &result)) {
+ KeyIdentifier id;
+ id.type = KeyIdentifier::SliderThumb;
+ id.width = size.width();
+ id.height = size.height();
+ id.trait1 = pressed;
+ if (!findCachedControl(id, &result)) {
if (size.isNull())
return;
result = QPixmap(size);
result.fill(Qt::transparent);
QPainter cachePainter(&result);
drawControlBackground(&cachePainter, borderPen(painter), QRect(QPoint(0, 0), size), pressed? Qt::lightGray : buttonGradientBottom);
- QPixmapCache::insert(key, result);
+ insertIntoCache(id, result);
}
painter->drawPixmap(rect, result);
}
@@ -661,6 +719,8 @@ bool RenderThemeQtMobile::paintTextField(RenderObject* o, const PaintInfo& i, co
// Now paint the text field.
if (appearance == TextAreaPart) {
+ const bool previousAntialiasing = p.painter->testRenderHint(QPainter::Antialiasing);
+ p.painter->setRenderHint(QPainter::Antialiasing);
p.painter->setPen(borderPen());
p.painter->setBrush(Qt::white);
const int radius = checkBoxWidth * radiusFactor;
@@ -672,7 +732,7 @@ bool RenderThemeQtMobile::paintTextField(RenderObject* o, const PaintInfo& i, co
p.painter->setBrush(Qt::NoBrush);
p.painter->drawRoundedRect(r, radius, radius);
}
-
+ p.painter->setRenderHint(QPainter::Antialiasing, previousAntialiasing);
} else
p.drawLineEdit(r, isFocused(o), isEnabled(o));
return false;
@@ -702,12 +762,7 @@ bool RenderThemeQtMobile::paintMenuList(RenderObject* o, const PaintInfo& i, con
if (!p.isValid())
return true;
- const QPoint topLeft = r.location();
- p.painter->translate(topLeft);
- const QRect rect(QPoint(0, 0), r.size());
-
- p.drawComboBox(rect, checkMultiple(o), isEnabled(o));
- p.painter->translate(-topLeft);
+ p.drawComboBox(r, checkMultiple(o), isEnabled(o));
return false;
}
diff --git a/Source/WebCore/platform/qt/RenderThemeQtMobile.h b/Source/WebCore/platform/qt/RenderThemeQtMobile.h
index 9e9b8143e..c57a18029 100644
--- a/Source/WebCore/platform/qt/RenderThemeQtMobile.h
+++ b/Source/WebCore/platform/qt/RenderThemeQtMobile.h
@@ -25,13 +25,16 @@
#include "RenderThemeQt.h"
#include <QBrush>
+#include <QHash>
+#include <QPixmapCache>
QT_BEGIN_NAMESPACE
class QColor;
-class QPixmap;
class QSize;
QT_END_NAMESPACE
+typedef QPixmapCache::Key CacheKey;
+
namespace WebCore {
class RenderThemeQtMobile : public RenderThemeQt {
@@ -83,6 +86,44 @@ private:
void setPaletteFromPageClientIfExists(QPalette&) const;
};
+struct KeyIdentifier {
+
+ KeyIdentifier()
+ : type(Undefined)
+ , width(0)
+ , height(0)
+ , trait1(0)
+ , trait2(0)
+ , trait3(0)
+ {
+ }
+
+ enum ControlType {
+ Undefined,
+ CheckBox,
+ Radio,
+ ComboButton,
+ LineEdit,
+ PushButton,
+ Progress,
+ SliderThumb
+ };
+
+ ControlType type : 3;
+ uint width : 11;
+ uint height : 9;
+ uint trait1 : 1;
+ uint trait2 : 1;
+ uint trait3 : 7;
+
+ inline bool operator==(const KeyIdentifier& other) const
+ {
+ return (type == other.type && width == other.width
+ && height == other.height && trait1 == other.trait1
+ && trait2 == other.trait2 && trait3 == other.trait3);
+ }
+};
+
class StylePainterMobile : public StylePainter {
public:
@@ -105,9 +146,9 @@ private:
void drawRadio(QPainter*, const QSize&, bool checked, bool enabled) const;
QPixmap findRadio(const QSize&, bool checked, bool enabled) const;
- QSize getButtonImageSize(int , bool multiple) const;
- void drawSimpleComboButton(QPainter*, const QSize&, const QColor&) const;
- void drawMultipleComboButton(QPainter*, const QSize&, const QColor&) const;
+ QSizeF getButtonImageSize(int , bool multiple) const;
+ void drawSimpleComboButton(QPainter*, const QSizeF&, const QColor&) const;
+ void drawMultipleComboButton(QPainter*, const QSizeF&, const QColor&) const;
QPixmap findComboButton(const QSize&, bool multiple, bool enabled) const;
QPixmap findLineEdit(const QSize&, bool focused) const;
@@ -115,9 +156,12 @@ private:
QSize sizeForPainterScale(const QRect&) const;
+ static bool findCachedControl(const KeyIdentifier&, QPixmap*);
+ static void insertIntoCache(const KeyIdentifier&, const QPixmap&);
+
bool m_previousSmoothPixmapTransform;
- Q_DISABLE_COPY(StylePainterMobile);
+ Q_DISABLE_COPY(StylePainterMobile)
};
}
diff --git a/Source/WebCore/platform/qt/RunLoopQt.cpp b/Source/WebCore/platform/qt/RunLoopQt.cpp
new file mode 100644
index 000000000..2a87e2fc8
--- /dev/null
+++ b/Source/WebCore/platform/qt/RunLoopQt.cpp
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 "RunLoop.h"
+
+#include <QAbstractEventDispatcher>
+#include <QCoreApplication>
+#include <QMetaMethod>
+#include <QMetaObject>
+#include <QObject>
+#include <QTimerEvent>
+
+namespace WebCore {
+
+class RunLoop::TimerObject : public QObject {
+ Q_OBJECT
+public:
+ TimerObject(RunLoop* runLoop) : m_runLoop(runLoop)
+ {
+ int methodIndex = metaObject()->indexOfMethod("performWork()");
+ m_method = metaObject()->method(methodIndex);
+ }
+
+ Q_SLOT void performWork() { m_runLoop->performWork(); }
+ inline void wakeUp() { m_method.invoke(this, Qt::QueuedConnection); }
+
+protected:
+ virtual void timerEvent(QTimerEvent* event)
+ {
+ RunLoop::TimerBase::timerFired(m_runLoop, event->timerId());
+ }
+
+private:
+ RunLoop* m_runLoop;
+ QMetaMethod m_method;
+};
+
+static QEventLoop* currentEventLoop;
+
+void RunLoop::run()
+{
+ static bool mainEventLoopIsRunning = false;
+ if (!mainEventLoopIsRunning) {
+ mainEventLoopIsRunning = true;
+ QCoreApplication::exec();
+ mainEventLoopIsRunning = false;
+ } else {
+ QEventLoop eventLoop;
+
+ QEventLoop* previousEventLoop = currentEventLoop;
+ currentEventLoop = &eventLoop;
+
+ eventLoop.exec();
+
+ currentEventLoop = previousEventLoop;
+ }
+}
+
+void RunLoop::stop()
+{
+ if (currentEventLoop)
+ currentEventLoop->exit();
+ else
+ QCoreApplication::exit();
+}
+
+RunLoop::RunLoop()
+ : m_timerObject(new TimerObject(this))
+{
+}
+
+RunLoop::~RunLoop()
+{
+ delete m_timerObject;
+}
+
+void RunLoop::wakeUp()
+{
+ m_timerObject->wakeUp();
+}
+
+// RunLoop::Timer
+
+void RunLoop::TimerBase::timerFired(RunLoop* runLoop, int ID)
+{
+ TimerMap::iterator it = runLoop->m_activeTimers.find(ID);
+ ASSERT(it != runLoop->m_activeTimers.end());
+ TimerBase* timer = it->second;
+
+ if (!timer->m_isRepeating) {
+ // Stop the timer (calling stop would need another hash table lookup).
+ runLoop->m_activeTimers.remove(it);
+ runLoop->m_timerObject->killTimer(timer->m_ID);
+ timer->m_ID = 0;
+ }
+
+ timer->fired();
+}
+
+RunLoop::TimerBase::TimerBase(RunLoop* runLoop)
+ : m_runLoop(runLoop)
+ , m_ID(0)
+ , m_isRepeating(false)
+{
+}
+
+RunLoop::TimerBase::~TimerBase()
+{
+ stop();
+}
+
+void RunLoop::TimerBase::start(double nextFireInterval, bool repeat)
+{
+ stop();
+ int millis = static_cast<int>(nextFireInterval * 1000);
+ m_isRepeating = repeat;
+ m_ID = m_runLoop->m_timerObject->startTimer(millis);
+ ASSERT(m_ID);
+ m_runLoop->m_activeTimers.set(m_ID, this);
+}
+
+void RunLoop::TimerBase::stop()
+{
+ if (!m_ID)
+ return;
+ TimerMap::iterator it = m_runLoop->m_activeTimers.find(m_ID);
+ if (it == m_runLoop->m_activeTimers.end())
+ return;
+
+ m_runLoop->m_activeTimers.remove(it);
+ m_runLoop->m_timerObject->killTimer(m_ID);
+ m_ID = 0;
+}
+
+bool RunLoop::TimerBase::isActive() const
+{
+ return m_ID;
+}
+
+#include "RunLoopQt.moc"
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/text/DecodeEscapeSequences.h b/Source/WebCore/platform/text/DecodeEscapeSequences.h
index a795698db..22a47ac14 100644
--- a/Source/WebCore/platform/text/DecodeEscapeSequences.h
+++ b/Source/WebCore/platform/text/DecodeEscapeSequences.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2011 Daniel Bates (dbates@intudata.com). 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
@@ -9,6 +10,9 @@
* 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 APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -36,52 +40,81 @@ namespace WebCore {
// See <http://en.wikipedia.org/wiki/Percent-encoding#Non-standard_implementations>.
struct Unicode16BitEscapeSequence {
- enum { size = 6 }; // e.g. %u26C4
- static size_t findInString(const String& string, unsigned start = 0) { return string.find("%u", start); }
- static bool matchStringPrefix(const String& string, unsigned start = 0)
+ enum { sequenceSize = 6 }; // e.g. %u26C4
+ static size_t findInString(const String& string, size_t startPosition) { return string.find("%u", startPosition); }
+ static size_t findEndOfRun(const String& string, size_t startPosition, size_t endPosition)
{
- if (string.length() - start < size)
- return false;
- return string[start] == '%' && string[start + 1] == 'u'
- && isASCIIHexDigit(string[start + 2]) && isASCIIHexDigit(string[start + 3])
- && isASCIIHexDigit(string[start + 4]) && isASCIIHexDigit(string[start + 5]);
+ size_t runEnd = startPosition;
+ while (endPosition - runEnd >= sequenceSize && string[runEnd] == '%' && string[runEnd + 1] == 'u'
+ && isASCIIHexDigit(string[runEnd + 2]) && isASCIIHexDigit(string[runEnd + 3])
+ && isASCIIHexDigit(string[runEnd + 4]) && isASCIIHexDigit(string[runEnd + 5])) {
+ runEnd += sequenceSize;
+ }
+ return runEnd;
}
static String decodeRun(const UChar* run, size_t runLength, const TextEncoding&)
{
// Each %u-escape sequence represents a UTF-16 code unit.
// See <http://www.w3.org/International/iri-edit/draft-duerst-iri.html#anchor29>.
- size_t numberOfSequences = runLength / size;
+ // For 16-bit escape sequences, we know that findEndOfRun() has given us a contiguous run of sequences
+ // without any intervening characters, so decode the run without additional checks.
+ size_t numberOfSequences = runLength / sequenceSize;
StringBuilder builder;
builder.reserveCapacity(numberOfSequences);
while (numberOfSequences--) {
UChar codeUnit = (toASCIIHexValue(run[2]) << 12) | (toASCIIHexValue(run[3]) << 8) | (toASCIIHexValue(run[4]) << 4) | toASCIIHexValue(run[5]);
builder.append(codeUnit);
- run += size;
+ run += sequenceSize;
}
return builder.toString();
}
};
struct URLEscapeSequence {
- enum { size = 3 }; // e.g. %41
- static size_t findInString(const String& string, unsigned start = 0) { return string.find('%', start); }
- static bool matchStringPrefix(const String& string, unsigned start = 0)
+ enum { sequenceSize = 3 }; // e.g. %41
+ static size_t findInString(const String& string, size_t startPosition) { return string.find('%', startPosition); }
+ static size_t findEndOfRun(const String& string, size_t startPosition, size_t endPosition)
{
- if (string.length() - start < size)
- return false;
- return string[start] == '%' && isASCIIHexDigit(string[start + 1]) && isASCIIHexDigit(string[start + 2]);
+ // Make the simplifying assumption that supported encodings may have up to two unescaped characters
+ // in the range 0x40 - 0x7F as the trailing bytes of their sequences which need to be passed into the
+ // decoder as part of the run. In other words, we end the run at the first value outside of the
+ // 0x40 - 0x7F range, after two values in this range, or at a %-sign that does not introduce a valid
+ // escape sequence.
+ size_t runEnd = startPosition;
+ int numberOfTrailingCharacters = 0;
+ while (runEnd < endPosition) {
+ if (string[runEnd] == '%') {
+ if (endPosition - runEnd >= sequenceSize && isASCIIHexDigit(string[runEnd + 1]) && isASCIIHexDigit(string[runEnd + 2])) {
+ runEnd += sequenceSize;
+ numberOfTrailingCharacters = 0;
+ } else
+ break;
+ } else if (string[runEnd] >= 0x40 && string[runEnd] <= 0x7F && numberOfTrailingCharacters < 2) {
+ runEnd += 1;
+ numberOfTrailingCharacters += 1;
+ } else
+ break;
+ }
+ return runEnd;
}
static String decodeRun(const UChar* run, size_t runLength, const TextEncoding& encoding)
{
- size_t numberOfSequences = runLength / size;
+ // For URL escape sequences, we know that findEndOfRun() has given us a run where every %-sign introduces
+ // a valid escape sequence, but there may be characters between the sequences.
Vector<char, 512> buffer;
- buffer.resize(numberOfSequences);
+ buffer.resize(runLength); // Unescaping hex sequences only makes the length smaller.
char* p = buffer.data();
- while (numberOfSequences--) {
- *p++ = (toASCIIHexValue(run[1]) << 4) | toASCIIHexValue(run[2]);
- run += size;
+ const UChar* runEnd = run + runLength;
+ while (run < runEnd) {
+ if (run[0] == '%') {
+ *p++ = (toASCIIHexValue(run[1]) << 4) | toASCIIHexValue(run[2]);
+ run += sequenceSize;
+ } else {
+ *p++ = run[0];
+ run += 1;
+ }
}
- ASSERT(buffer.size() == static_cast<size_t>(p - buffer.data()));
+ ASSERT(buffer.size() >= static_cast<size_t>(p - buffer.data())); // Prove buffer not overrun.
return (encoding.isValid() ? encoding : UTF8Encoding()).decode(buffer.data(), p - buffer.data());
}
};
@@ -95,9 +128,7 @@ String decodeEscapeSequences(const String& string, const TextEncoding& encoding)
size_t searchPosition = 0;
size_t encodedRunPosition;
while ((encodedRunPosition = EscapeSequence::findInString(string, searchPosition)) != notFound) {
- unsigned encodedRunEnd = encodedRunPosition;
- while (length - encodedRunEnd >= EscapeSequence::size && EscapeSequence::matchStringPrefix(string, encodedRunEnd))
- encodedRunEnd += EscapeSequence::size;
+ size_t encodedRunEnd = EscapeSequence::findEndOfRun(string, encodedRunPosition, length);
searchPosition = encodedRunEnd;
if (encodedRunEnd == encodedRunPosition) {
++searchPosition;
@@ -108,11 +139,11 @@ String decodeEscapeSequences(const String& string, const TextEncoding& encoding)
if (decoded.isEmpty())
continue;
- result.append(string.characters() + decodedPosition, encodedRunPosition - decodedPosition);
+ result.append(string, decodedPosition, encodedRunPosition - decodedPosition);
result.append(decoded);
decodedPosition = encodedRunEnd;
}
- result.append(string.characters() + decodedPosition, length - decodedPosition);
+ result.append(string, decodedPosition, length - decodedPosition);
return result.toString();
}
diff --git a/Source/WebCore/platform/text/LocalizedNumber.h b/Source/WebCore/platform/text/LocalizedNumber.h
index 01d2553ef..350dac0db 100644
--- a/Source/WebCore/platform/text/LocalizedNumber.h
+++ b/Source/WebCore/platform/text/LocalizedNumber.h
@@ -35,21 +35,20 @@
namespace WebCore {
-// Parses a string representation of a floating point number localized
-// for the browser's current locale. If the input string is not valid
-// or an implementation doesn't support localized numbers, this
-// function returns NaN. This function doesn't need to support
-// scientific notation, NaN, +Infinity and -Infinity, and doesn't need
-// to support the standard representations of ECMAScript and HTML5.
-double parseLocalizedNumber(const String&);
+// Converts the specified number string to another number string
+// localized for the browser's current locale. The input string must
+// conform to HTML floating-point numbers, and is not empty. The
+// fractionDigits argument is deprecated. The function implementaion
+// should not use the argument.
+String convertToLocalizedNumber(const String&, unsigned fractionDigits);
-// Serializes the specified floating point number for the browser's
-// current locale. If an implementation doesn't support localized
-// numbers or the input value is NaN or Infinitiy, the function should
-// return an empty string.
-// fractionDigits is the maximum length of the fractional parts of the
-// resultant string.
-String formatLocalizedNumber(double, unsigned fractionDigits);
+// Converts the specified localized number string to a number string
+// in the HTML floating-point number format. The input string is
+// provided by a end user, and might not be a number string. It's ok
+// that the function returns a string which is not conforms to the
+// HTML floating-point number format, callers of this function are
+// responsible to check the format of the resultant string.
+String convertFromLocalizedNumber(const String&);
} // namespace WebCore
diff --git a/Source/WebCore/platform/text/LocalizedNumberICU.cpp b/Source/WebCore/platform/text/LocalizedNumberICU.cpp
index dc226df12..03db4d546 100644
--- a/Source/WebCore/platform/text/LocalizedNumberICU.cpp
+++ b/Source/WebCore/platform/text/LocalizedNumberICU.cpp
@@ -37,6 +37,7 @@
#include <wtf/MainThread.h>
#include <wtf/MathExtras.h>
#include <wtf/PassOwnPtr.h>
+#include <wtf/dtoa.h>
using namespace icu;
using namespace std;
@@ -76,7 +77,7 @@ static NumberFormat* numberFormatterForDisplay()
return formatter;
}
-double parseLocalizedNumber(const String& numberString)
+static double parseLocalizedNumber(const String& numberString)
{
if (numberString.isEmpty())
return numeric_limits<double>::quiet_NaN();
@@ -94,7 +95,7 @@ double parseLocalizedNumber(const String& numberString)
return U_SUCCESS(status) ? numericResult : numeric_limits<double>::quiet_NaN();
}
-String formatLocalizedNumber(double number, unsigned fractionDigits)
+static String formatLocalizedNumber(double number, unsigned fractionDigits)
{
NumberFormat* formatter = numberFormatterForDisplay();
if (!formatter)
@@ -105,4 +106,30 @@ String formatLocalizedNumber(double number, unsigned fractionDigits)
return String(result.getBuffer(), result.length());
}
+String convertToLocalizedNumber(const String& canonicalNumberString, unsigned fractionDigits)
+{
+ // FIXME: We should not do parse-then-format. It makes some
+ // problems such as removing leading zeros, changing trailing
+ // digits to zeros.
+ // FIXME: We should not use the fractionDigits argument.
+
+ double doubleValue = canonicalNumberString.toDouble();
+ // The input string must be valid.
+ return formatLocalizedNumber(doubleValue, fractionDigits);
+
+}
+
+String convertFromLocalizedNumber(const String& localizedNumberString)
+{
+ // FIXME: We should not do parse-then-format. It makes some
+ // problems such as removing leading zeros, changing trailing
+ // digits to zeros.
+
+ double doubleValue = parseLocalizedNumber(localizedNumberString);
+ if (!isfinite(doubleValue))
+ return localizedNumberString;
+ NumberToStringBuffer buffer;
+ return String(numberToString(doubleValue, buffer));
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/text/LocalizedNumberNone.cpp b/Source/WebCore/platform/text/LocalizedNumberNone.cpp
index c7a8ed274..a1400855d 100644
--- a/Source/WebCore/platform/text/LocalizedNumberNone.cpp
+++ b/Source/WebCore/platform/text/LocalizedNumberNone.cpp
@@ -37,14 +37,14 @@ using namespace std;
namespace WebCore {
-double parseLocalizedNumber(const String&)
+String convertToLocalizedNumber(const String& canonicalNumberString, unsigned)
{
- return numeric_limits<double>::quiet_NaN();
+ return canonicalNumberString;
}
-String formatLocalizedNumber(double, unsigned)
+String convertFromLocalizedNumber(const String& localizedNumberString)
{
- return String();
+ return localizedNumberString;
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm b/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm
index ac6e70990..c2a7ea013 100644
--- a/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm
+++ b/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm
@@ -33,7 +33,9 @@
#import <Foundation/NSNumberFormatter.h>
#import <limits>
+#import <wtf/dtoa.h>
#import <wtf/MainThread.h>
+#import <wtf/MathExtras.h>
#import <wtf/RetainPtr.h>
#import <wtf/text/CString.h>
@@ -70,7 +72,7 @@ static NSNumberFormatter *numberFormatterForDisplay()
return formatter;
}
-double parseLocalizedNumber(const String& numberString)
+static double parseLocalizedNumber(const String& numberString)
{
if (numberString.isEmpty())
return numeric_limits<double>::quiet_NaN();
@@ -80,7 +82,7 @@ double parseLocalizedNumber(const String& numberString)
return [number doubleValue];
}
-String formatLocalizedNumber(double inputNumber, unsigned fractionDigits)
+static String formatLocalizedNumber(double inputNumber, unsigned fractionDigits)
{
RetainPtr<NSNumber> number(AdoptNS, [[NSNumber alloc] initWithDouble:inputNumber]);
RetainPtr<NSNumberFormatter> formatter = numberFormatterForDisplay();
@@ -88,5 +90,31 @@ String formatLocalizedNumber(double inputNumber, unsigned fractionDigits)
return String([formatter.get() stringFromNumber:number.get()]);
}
+String convertToLocalizedNumber(const String& canonicalNumberString, unsigned fractionDigits)
+{
+ // FIXME: We should not do parse-then-format. It makes some
+ // problems such as removing leading zeros, changing trailing
+ // digits to zeros.
+ // FIXME: We should not use the fractionDigits argument.
+
+ double doubleValue = canonicalNumberString.toDouble();
+ // The input string must be valid.
+ return formatLocalizedNumber(doubleValue, fractionDigits);
+
+}
+
+String convertFromLocalizedNumber(const String& localizedNumberString)
+{
+ // FIXME: We should not do parse-then-format. It makes some
+ // problems such as removing leading zeros, changing trailing
+ // digits to zeros.
+
+ double doubleValue = parseLocalizedNumber(localizedNumberString);
+ if (!isfinite(doubleValue))
+ return localizedNumberString;
+ NumberToStringBuffer buffer;
+ return String(numberToString(doubleValue, buffer));
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/win/CursorWin.cpp b/Source/WebCore/platform/win/CursorWin.cpp
index 544b9a77b..ce4d58fb4 100644
--- a/Source/WebCore/platform/win/CursorWin.cpp
+++ b/Source/WebCore/platform/win/CursorWin.cpp
@@ -28,6 +28,7 @@
#include "Cursor.h"
#include "BitmapInfo.h"
+#include "HWndDC.h"
#include "Image.h"
#include "IntPoint.h"
#include "SystemInfo.h"
@@ -49,7 +50,7 @@ static PassRefPtr<SharedCursor> createSharedCursor(Image* img, const IntPoint& h
static bool doAlpha = windowsVersion() >= WindowsXP;
BitmapInfo cursorImage = BitmapInfo::create(IntSize(img->width(), img->height()));
- HDC dc = GetDC(0);
+ HWndDC dc(0);
HDC workingDC = CreateCompatibleDC(dc);
if (doAlpha) {
OwnPtr<HBITMAP> hCursor = adoptPtr(CreateDIBSection(dc, (BITMAPINFO *)&cursorImage, DIB_RGB_COLORS, 0, 0, 0));
@@ -112,7 +113,6 @@ static PassRefPtr<SharedCursor> createSharedCursor(Image* img, const IntPoint& h
DeleteDC(andMaskDC);
}
DeleteDC(workingDC);
- ReleaseDC(0, dc);
return impl.release();
}
diff --git a/Source/WebCore/platform/win/DragImageCGWin.cpp b/Source/WebCore/platform/win/DragImageCGWin.cpp
index bc45e22c3..741016846 100644
--- a/Source/WebCore/platform/win/DragImageCGWin.cpp
+++ b/Source/WebCore/platform/win/DragImageCGWin.cpp
@@ -29,6 +29,7 @@
#include "BitmapInfo.h"
#include "CachedImage.h"
#include "GraphicsContextCG.h"
+#include "HWndDC.h"
#include "Image.h"
#include "RetainPtr.h"
@@ -89,7 +90,7 @@ DragImageRef scaleDragImage(DragImageRef image, FloatSize scale)
IntSize srcSize = dragImageSize(image);
IntSize dstSize(static_cast<int>(srcSize.width() * scale.width()), static_cast<int>(srcSize.height() * scale.height()));
HBITMAP hbmp = 0;
- HDC dc = GetDC(0);
+ HWndDC dc(0);
HDC dstDC = CreateCompatibleDC(dc);
if (!dstDC)
goto exit;
@@ -116,14 +117,13 @@ exit:
hbmp = image;
if (dstDC)
DeleteDC(dstDC);
- ReleaseDC(0, dc);
return hbmp;
}
DragImageRef createDragImageFromImage(Image* img)
{
HBITMAP hbmp = 0;
- HDC dc = GetDC(0);
+ HWndDC dc(0);
HDC workingDC = CreateCompatibleDC(dc);
CGContextRef drawContext = 0;
if (!workingDC)
@@ -155,7 +155,6 @@ DragImageRef createDragImageFromImage(Image* img)
exit:
if (workingDC)
DeleteDC(workingDC);
- ReleaseDC(0, dc);
return hbmp;
}
diff --git a/Source/WebCore/platform/win/DragImageWin.cpp b/Source/WebCore/platform/win/DragImageWin.cpp
index f858b07f1..1f6b73e89 100644
--- a/Source/WebCore/platform/win/DragImageWin.cpp
+++ b/Source/WebCore/platform/win/DragImageWin.cpp
@@ -33,6 +33,7 @@
#include "FontSelector.h"
#include "Frame.h"
#include "GraphicsContext.h"
+#include "HWndDC.h"
#include "Image.h"
#include "RetainPtr.h"
#include "Settings.h"
@@ -183,18 +184,15 @@ DragImageRef createDragImageForLink(KURL& url, const String& inLabel, Frame* fra
// We now know how big the image needs to be, so we create and
// fill the background
HBITMAP image = 0;
- HDC dc = GetDC(0);
+ HWndDC dc(0);
HDC workingDC = CreateCompatibleDC(dc);
- if (!workingDC) {
- ReleaseDC(0, dc);
+ if (!workingDC)
return 0;
- }
PlatformGraphicsContext* contextRef;
image = allocImage(workingDC, imageSize, &contextRef);
if (!image) {
DeleteDC(workingDC);
- ReleaseDC(0, dc);
return 0;
}
@@ -225,7 +223,6 @@ DragImageRef createDragImageForLink(KURL& url, const String& inLabel, Frame* fra
deallocContext(contextRef);
DeleteDC(workingDC);
- ReleaseDC(0, dc);
return image;
}
diff --git a/Source/WebCore/platform/efl/CookieJarEfl.cpp b/Source/WebCore/platform/win/HWndDC.h
index 261ab233a..2eaecaddc 100644
--- a/Source/WebCore/platform/efl/CookieJarEfl.cpp
+++ b/Source/WebCore/platform/win/HWndDC.h
@@ -1,7 +1,5 @@
/*
- * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2009-2010 ProFUSION embedded systems
- * Copyright (C) 2009-2010 Samsung Electronics
+ * 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
@@ -25,46 +23,67 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config.h"
-#include "CookieJar.h"
+#ifndef HWndDC_h
+#define HWndDC_h
-#include "KURL.h"
-#include "PlatformString.h"
-#include <wtf/HashMap.h>
-#include <wtf/text/StringHash.h>
+#include <windows.h>
+#include <wtf/NonCopyable.h>
namespace WebCore {
-static HashMap<String, String> cookieJar;
+class HWndDC {
+ WTF_MAKE_NONCOPYABLE(HWndDC);
+public:
+ HWndDC()
+ : m_hwnd(0)
+ , m_hdc(0)
+ {
+ }
-void setCookies(Document* document, const KURL& url, const KURL& policyURL, const String& value)
-{
- cookieJar.set(url.string(), value);
-}
+ explicit HWndDC(HWND hwnd)
+ : m_hwnd(hwnd)
+ , m_hdc(::GetDC(hwnd))
+ {
+ }
-String cookies(const Document* document, const KURL& url)
-{
- return cookieJar.get(url.string());
-}
+ HWndDC(HWND hwnd, HRGN hrgnClip, DWORD flags)
+ : m_hwnd(hwnd)
+ , m_hdc(::GetDCEx(hwnd, hrgnClip, flags))
+ {
+ }
-bool cookiesEnabled(const Document* document)
-{
- return true;
-}
+ ~HWndDC()
+ {
+ clear();
+ }
-void getHostnamesWithCookies(HashSet<String>& hostnames)
-{
- // FIXME: Not yet implemented
-}
+ HDC setHWnd(HWND hwnd)
+ {
+ clear();
+ m_hwnd = hwnd;
+ m_hdc = ::GetDC(hwnd);
+ return m_hdc;
+ }
-void deleteCookiesForHostname(const String& hostname)
-{
- // FIXME: Not yet implemented
-}
+ void clear()
+ {
+ if (!m_hdc)
+ return;
+ ::ReleaseDC(m_hwnd, m_hdc);
+ m_hwnd = 0;
+ m_hdc = 0;
+ }
-void deleteAllCookies()
-{
- // FIXME: Not yet implemented
-}
+ operator HDC()
+ {
+ return m_hdc;
+ }
-}
+private:
+ HWND m_hwnd;
+ HDC m_hdc;
+};
+
+} // namespace WebCore
+
+#endif // HWndDC_h
diff --git a/Source/WebCore/platform/win/LanguageWin.cpp b/Source/WebCore/platform/win/LanguageWin.cpp
index aa050a78e..006dc1051 100644
--- a/Source/WebCore/platform/win/LanguageWin.cpp
+++ b/Source/WebCore/platform/win/LanguageWin.cpp
@@ -27,6 +27,7 @@
#include "Language.h"
#include <windows.h>
+#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>
namespace WebCore {
@@ -49,7 +50,7 @@ static String localeInfo(LCTYPE localeType, const String& fallback)
return localeName;
}
-String platformDefaultLanguage()
+static String platformLanguage()
{
static String computedDefaultLanguage;
if (!computedDefaultLanguage.isEmpty())
@@ -66,4 +67,11 @@ String platformDefaultLanguage()
return computedDefaultLanguage;
}
+Vector<String> platformUserPreferredLanguages()
+{
+ Vector<String> userPreferredLanguages;
+ userPreferredLanguages.append(platformLanguage());
+ return userPreferredLanguages;
+}
+
}
diff --git a/Source/WebCore/platform/win/PasteboardWin.cpp b/Source/WebCore/platform/win/PasteboardWin.cpp
index d768a3d53..887fc912c 100644
--- a/Source/WebCore/platform/win/PasteboardWin.cpp
+++ b/Source/WebCore/platform/win/PasteboardWin.cpp
@@ -32,6 +32,7 @@
#include "DocumentFragment.h"
#include "Element.h"
#include "Frame.h"
+#include "HWndDC.h"
#include "HitTestResult.h"
#include "Image.h"
#include "KURL.h"
@@ -223,7 +224,7 @@ void Pasteboard::writeImage(Node* node, const KURL&, const String&)
clear();
- HDC dc = GetDC(0);
+ HWndDC dc(0);
HDC compatibleDC = CreateCompatibleDC(0);
HDC sourceDC = CreateCompatibleDC(0);
OwnPtr<HBITMAP> resultBitmap = adoptPtr(CreateCompatibleBitmap(dc, image->width(), image->height()));
@@ -243,7 +244,6 @@ void Pasteboard::writeImage(Node* node, const KURL&, const String&)
SelectObject(compatibleDC, oldBitmap);
DeleteDC(sourceDC);
DeleteDC(compatibleDC);
- ReleaseDC(0, dc);
if (::OpenClipboard(m_owner)) {
::SetClipboardData(CF_BITMAP, resultBitmap.leakPtr());
diff --git a/Source/WebCore/platform/win/PlatformScreenWin.cpp b/Source/WebCore/platform/win/PlatformScreenWin.cpp
index caadde943..936f8a747 100644
--- a/Source/WebCore/platform/win/PlatformScreenWin.cpp
+++ b/Source/WebCore/platform/win/PlatformScreenWin.cpp
@@ -106,15 +106,15 @@ bool screenIsMonochrome(Widget* widget)
#endif
}
-FloatRect screenRect(Widget* widget)
+FloatRect screenRect(FrameView* frameView)
{
- MONITORINFOEX monitorInfo = monitorInfoForWidget(widget);
+ MONITORINFOEX monitorInfo = monitorInfoForWidget(frameView);
return monitorInfo.rcMonitor;
}
-FloatRect screenAvailableRect(Widget* widget)
+FloatRect screenAvailableRect(FrameView* frameView)
{
- MONITORINFOEX monitorInfo = monitorInfoForWidget(widget);
+ MONITORINFOEX monitorInfo = monitorInfoForWidget(frameView);
return monitorInfo.rcWork;
}
diff --git a/Source/WebCore/platform/win/PopupMenuWin.cpp b/Source/WebCore/platform/win/PopupMenuWin.cpp
index 097fc8231..d0b3ec940 100644
--- a/Source/WebCore/platform/win/PopupMenuWin.cpp
+++ b/Source/WebCore/platform/win/PopupMenuWin.cpp
@@ -31,6 +31,7 @@
#include "FrameView.h"
#include "GraphicsContext.h"
#include "HTMLNames.h"
+#include "HWndDC.h"
#include "HostWindow.h"
#include "Page.h"
#include "PlatformMouseEvent.h"
@@ -42,6 +43,7 @@
#include "SimpleFontData.h"
#include "TextRun.h"
#include "WebCoreInstanceHandle.h"
+
#include <windows.h>
#include <windowsx.h>
#if OS(WINCE)
@@ -566,7 +568,7 @@ void PopupMenuWin::paint(const IntRect& damageRect, HDC hdc)
return;
if (!m_DC) {
- m_DC = ::CreateCompatibleDC(::GetDC(m_popup));
+ m_DC = ::CreateCompatibleDC(HWndDC(m_popup));
if (!m_DC)
return;
}
@@ -660,12 +662,10 @@ void PopupMenuWin::paint(const IntRect& damageRect, HDC hdc)
if (m_scrollbar)
m_scrollbar->paint(&context, damageRect);
- HDC localDC = hdc ? hdc : ::GetDC(m_popup);
+ HWndDC hWndDC;
+ HDC localDC = hdc ? hdc : hWndDC.setHWnd(m_popup);
::BitBlt(localDC, damageRect.x(), damageRect.y(), damageRect.width(), damageRect.height(), m_DC, damageRect.x(), damageRect.y(), SRCCOPY);
-
- if (!hdc)
- ::ReleaseDC(m_popup, localDC);
}
int PopupMenuWin::scrollSize(ScrollbarOrientation orientation) const
diff --git a/Source/WebCore/platform/win/RunLoopWin.cpp b/Source/WebCore/platform/win/RunLoopWin.cpp
new file mode 100644
index 000000000..120c252a6
--- /dev/null
+++ b/Source/WebCore/platform/win/RunLoopWin.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 "RunLoop.h"
+
+#include <wtf/CurrentTime.h>
+
+using namespace std;
+
+namespace WebCore {
+
+static const UINT PerformWorkMessage = WM_USER + 1;
+static const LPWSTR kRunLoopMessageWindowClassName = L"RunLoopMessageWindow";
+
+LRESULT CALLBACK RunLoop::RunLoopWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ LONG_PTR longPtr = ::GetWindowLongPtr(hWnd, 0);
+
+ if (RunLoop* runLoop = reinterpret_cast<RunLoop*>(longPtr))
+ return runLoop->wndProc(hWnd, message, wParam, lParam);
+
+ if (message == WM_CREATE) {
+ LPCREATESTRUCT createStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
+
+ // Associate the RunLoop with the window.
+ ::SetWindowLongPtr(hWnd, 0, (LONG_PTR)createStruct->lpCreateParams);
+ return 0;
+ }
+
+ return ::DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+LRESULT RunLoop::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message) {
+ case PerformWorkMessage:
+ performWork();
+ return 0;
+ case WM_TIMER:
+ RunLoop::TimerBase::timerFired(this, wParam);
+ return 0;
+ }
+
+ return ::DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+void RunLoop::run()
+{
+ MSG message;
+ while (BOOL result = ::GetMessage(&message, 0, 0, 0)) {
+ if (result == -1)
+ break;
+ ::TranslateMessage(&message);
+ ::DispatchMessage(&message);
+ }
+}
+
+void RunLoop::stop()
+{
+ ::PostQuitMessage(0);
+}
+
+bool RunLoop::registerRunLoopMessageWindowClass()
+{
+ // FIXME: This really only needs to be called once.
+
+ WNDCLASSEX windowClass = { 0 };
+ windowClass.cbSize = sizeof(windowClass);
+ windowClass.lpfnWndProc = RunLoop::RunLoopWndProc;
+ windowClass.cbWndExtra = sizeof(RunLoop*);
+ windowClass.lpszClassName = kRunLoopMessageWindowClassName;
+
+ return !!::RegisterClassEx(&windowClass);
+}
+
+RunLoop::RunLoop()
+{
+ registerRunLoopMessageWindowClass();
+
+ m_runLoopMessageWindow = ::CreateWindow(kRunLoopMessageWindowClassName, 0, 0,
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
+ HWND_MESSAGE, 0, 0, this);
+ ASSERT(::IsWindow(m_runLoopMessageWindow));
+}
+
+RunLoop::~RunLoop()
+{
+ // FIXME: Tear down the work item queue here.
+}
+
+void RunLoop::wakeUp()
+{
+ // FIXME: No need to wake up the run loop if we've already called dispatch
+ // before the run loop has had the time to respond.
+ ::PostMessage(m_runLoopMessageWindow, PerformWorkMessage, reinterpret_cast<WPARAM>(this), 0);
+}
+
+// RunLoop::Timer
+
+void RunLoop::TimerBase::timerFired(RunLoop* runLoop, uint64_t ID)
+{
+ TimerMap::iterator it = runLoop->m_activeTimers.find(ID);
+ if (it == runLoop->m_activeTimers.end()) {
+ // The timer must have been stopped after the WM_TIMER message was posted to the message queue.
+ return;
+ }
+
+ TimerBase* timer = it->second;
+
+ if (!timer->m_isRepeating) {
+ runLoop->m_activeTimers.remove(it);
+ ::KillTimer(runLoop->m_runLoopMessageWindow, ID);
+ }
+
+ timer->fired();
+}
+
+static uint64_t generateTimerID()
+{
+ static uint64_t uniqueTimerID = 1;
+ return uniqueTimerID++;
+}
+
+RunLoop::TimerBase::TimerBase(RunLoop* runLoop)
+ : m_runLoop(runLoop)
+ , m_ID(generateTimerID())
+ , m_isRepeating(false)
+{
+}
+
+RunLoop::TimerBase::~TimerBase()
+{
+ stop();
+}
+
+void RunLoop::TimerBase::start(double nextFireInterval, bool repeat)
+{
+ m_isRepeating = repeat;
+ m_runLoop->m_activeTimers.set(m_ID, this);
+ ::SetTimer(m_runLoop->m_runLoopMessageWindow, m_ID, nextFireInterval * 1000, 0);
+}
+
+void RunLoop::TimerBase::stop()
+{
+ TimerMap::iterator it = m_runLoop->m_activeTimers.find(m_ID);
+ if (it == m_runLoop->m_activeTimers.end())
+ return;
+
+ m_runLoop->m_activeTimers.remove(it);
+ ::KillTimer(m_runLoop->m_runLoopMessageWindow, m_ID);
+}
+
+bool RunLoop::TimerBase::isActive() const
+{
+ return m_runLoop->m_activeTimers.contains(m_ID);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/wx/KeyboardEventWx.cpp b/Source/WebCore/platform/wx/KeyboardEventWx.cpp
index ce85ffa10..963b56350 100644
--- a/Source/WebCore/platform/wx/KeyboardEventWx.cpp
+++ b/Source/WebCore/platform/wx/KeyboardEventWx.cpp
@@ -364,10 +364,20 @@ PlatformKeyboardEvent::PlatformKeyboardEvent(wxKeyEvent& event)
m_windowsVirtualKeyCode = windowsKeyCodeForKeyEvent(event.GetKeyCode());
m_nativeVirtualKeyCode = event.GetKeyCode();
m_isKeypad = (event.GetKeyCode() >= WXK_NUMPAD_SPACE) && (event.GetKeyCode() <= WXK_NUMPAD_DIVIDE);
- m_shiftKey = event.ShiftDown();
- m_ctrlKey = event.CmdDown();
- m_altKey = event.AltDown();
- m_metaKey = event.MetaDown();
+
+ m_modifiers = 0;
+ if (event.ShiftDown())
+ m_modifiers |= ShiftKey;
+
+ if (event.CmdDown())
+ m_modifiers |= CtrlKey;
+
+ if (event.AltDown())
+ m_modifiers |= AltKey;
+
+ if (event.MetaDown())
+ m_modifiers |= MetaKey;
+
m_timestamp = WTF::currentTime();
}
diff --git a/Source/WebCore/platform/chromium/ClipboardChromiumLinux.cpp b/Source/WebCore/platform/wx/LanguageWx.cpp
index 2c89f6e8e..d66b29974 100644
--- a/Source/WebCore/platform/chromium/ClipboardChromiumLinux.cpp
+++ b/Source/WebCore/platform/wx/LanguageWx.cpp
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2009 Google Inc.
+ * Copyright (C) 2012 Kevin Ollivier <kevino@theolliviers.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,17 +24,24 @@
*/
#include "config.h"
-#include "ClipboardChromium.h"
+#include "Language.h"
-#include "ChromiumDataObject.h"
#include "NotImplemented.h"
+#include "PlatformString.h"
namespace WebCore {
-String ClipboardChromium::validateFileName(const String& title, ChromiumDataObject* dataObject)
+static String platformLanguage()
{
notImplemented();
- return title;
+ return String();
}
-} // namespace WebCore
+Vector<String> platformUserPreferredLanguages()
+{
+ notImplemented();
+ Vector<String> userPreferredLanguages;
+ return userPreferredLanguages;
+}
+
+}
diff --git a/Source/WebCore/platform/wx/RunLoopWx.cpp b/Source/WebCore/platform/wx/RunLoopWx.cpp
new file mode 100644
index 000000000..bd14dd545
--- /dev/null
+++ b/Source/WebCore/platform/wx/RunLoopWx.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 Kevin Ollivier <kevino@theolliviers.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 "RunLoop.h"
+
+#include "NotImplemented.h"
+
+namespace WebCore {
+
+void RunLoop::run()
+{
+ notImplemented();
+}
+
+void RunLoop::stop()
+{
+ notImplemented();
+}
+
+RunLoop::RunLoop()
+{
+ notImplemented();
+}
+
+RunLoop::~RunLoop()
+{
+}
+
+void RunLoop::wakeUp()
+{
+ notImplemented();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/wx/ScreenWx.cpp b/Source/WebCore/platform/wx/ScreenWx.cpp
index 41edf1561..779d4fdf5 100644
--- a/Source/WebCore/platform/wx/ScreenWx.cpp
+++ b/Source/WebCore/platform/wx/ScreenWx.cpp
@@ -28,6 +28,7 @@
#include "Screen.h"
#include "IntRect.h"
#include "FloatRect.h"
+#include "FrameView.h"
#include "NotImplemented.h"
#include "Widget.h"
@@ -48,7 +49,7 @@ int screenVerticalDPI(Widget*)
return 0;
}
-FloatRect screenRect(Widget* widget)
+FloatRect screenRect(FrameView* frameView)
{
/*
int displayNum;
@@ -77,7 +78,7 @@ bool screenIsMonochrome(Widget* widget)
return wxColourDisplay();
}
-FloatRect screenAvailableRect(Widget* widget)
+FloatRect screenAvailableRect(FrameView* frameView)
{
/*
Widget* widget = widget->widget();