summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-25 19:08:45 +0100
committerSteve Block <steveblock@google.com>2011-06-08 13:51:31 +0100
commit2bde8e466a4451c7319e3a072d118917957d6554 (patch)
tree28f4a1b869a513e565c7760d0e6a06e7cf1fe95a /Source/WebCore/platform
parent6939c99b71d9372d14a0c74a772108052e8c48c8 (diff)
downloadexternal_webkit-2bde8e466a4451c7319e3a072d118917957d6554.zip
external_webkit-2bde8e466a4451c7319e3a072d118917957d6554.tar.gz
external_webkit-2bde8e466a4451c7319e3a072d118917957d6554.tar.bz2
Merge WebKit at r82507: Initial merge by git
Change-Id: I60ce9d780725b58b45e54165733a8ffee23b683e
Diffstat (limited to 'Source/WebCore/platform')
-rw-r--r--Source/WebCore/platform/ColorData.gperf4
-rw-r--r--Source/WebCore/platform/CrossThreadCopier.h6
-rw-r--r--Source/WebCore/platform/DefaultLocalizationStrategy.cpp874
-rw-r--r--Source/WebCore/platform/DefaultLocalizationStrategy.h187
-rw-r--r--Source/WebCore/platform/FileMetadata.h4
-rw-r--r--Source/WebCore/platform/FileSystem.cpp7
-rw-r--r--Source/WebCore/platform/FileSystem.h2
-rw-r--r--Source/WebCore/platform/HostWindow.h2
-rw-r--r--Source/WebCore/platform/KURL.cpp24
-rw-r--r--Source/WebCore/platform/KURL.h2
-rw-r--r--Source/WebCore/platform/KURLGoogle.cpp16
-rw-r--r--Source/WebCore/platform/KillRingNone.cpp4
-rw-r--r--Source/WebCore/platform/Length.h127
-rw-r--r--Source/WebCore/platform/LinkHash.cpp2
-rw-r--r--Source/WebCore/platform/LocalizationStrategy.h9
-rw-r--r--Source/WebCore/platform/LocalizedStrings.cpp34
-rw-r--r--Source/WebCore/platform/LocalizedStrings.h15
-rw-r--r--Source/WebCore/platform/MIMETypeRegistry.cpp41
-rw-r--r--Source/WebCore/platform/MIMETypeRegistry.h5
-rw-r--r--Source/WebCore/platform/PlatformGestureRecognizer.cpp46
-rw-r--r--Source/WebCore/platform/PlatformGestureRecognizer.h64
-rw-r--r--Source/WebCore/platform/PlatformKeyboardEvent.h2
-rw-r--r--Source/WebCore/platform/PlatformStrategies.cpp9
-rw-r--r--Source/WebCore/platform/PlatformStrategies.h2
-rw-r--r--Source/WebCore/platform/ScrollAnimator.h2
-rw-r--r--Source/WebCore/platform/ScrollTypes.h4
-rw-r--r--Source/WebCore/platform/ScrollView.cpp51
-rw-r--r--Source/WebCore/platform/ScrollView.h14
-rw-r--r--Source/WebCore/platform/ScrollableArea.h19
-rw-r--r--Source/WebCore/platform/SharedBuffer.cpp6
-rw-r--r--Source/WebCore/platform/SharedBuffer.h8
-rw-r--r--Source/WebCore/platform/UUID.cpp16
-rw-r--r--Source/WebCore/platform/android/FileSystemAndroid.cpp11
-rw-r--r--Source/WebCore/platform/android/LocalizedStringsAndroid.cpp2
-rw-r--r--Source/WebCore/platform/audio/AudioBus.cpp87
-rw-r--r--Source/WebCore/platform/audio/AudioBus.h12
-rw-r--r--Source/WebCore/platform/audio/HRTFKernel.cpp13
-rw-r--r--Source/WebCore/platform/audio/SincResampler.cpp342
-rw-r--r--Source/WebCore/platform/audio/SincResampler.h79
-rw-r--r--Source/WebCore/platform/audio/chromium/AudioBusChromium.cpp28
-rw-r--r--Source/WebCore/platform/audio/mac/AudioDestinationMac.cpp4
-rw-r--r--Source/WebCore/platform/brew/FileSystemBrew.cpp12
-rw-r--r--Source/WebCore/platform/brew/LocalizedStringsBrew.cpp2
-rw-r--r--Source/WebCore/platform/cf/BinaryPropertyList.cpp2
-rw-r--r--Source/WebCore/platform/cf/SchedulePair.h2
-rw-r--r--Source/WebCore/platform/cf/SharedBufferCF.cpp26
-rw-r--r--Source/WebCore/platform/cf/win/CertificateCFWin.cpp52
-rw-r--r--Source/WebCore/platform/cf/win/CertificateCFWin.h38
-rw-r--r--Source/WebCore/platform/chromium/ClipboardChromium.cpp19
-rw-r--r--Source/WebCore/platform/chromium/ClipboardChromium.h4
-rw-r--r--Source/WebCore/platform/chromium/DataTransferItemChromium.cpp108
-rw-r--r--Source/WebCore/platform/chromium/DataTransferItemChromium.h75
-rw-r--r--Source/WebCore/platform/chromium/DataTransferItemsChromium.cpp111
-rw-r--r--Source/WebCore/platform/chromium/DataTransferItemsChromium.h77
-rw-r--r--Source/WebCore/platform/chromium/FileSystemChromium.cpp7
-rw-r--r--Source/WebCore/platform/chromium/PasteboardPrivate.h1
-rw-r--r--Source/WebCore/platform/chromium/ScrollbarThemeChromiumWin.cpp24
-rw-r--r--Source/WebCore/platform/chromium/TraceEvent.h74
-rw-r--r--Source/WebCore/platform/chromium/WindowsVersion.cpp52
-rw-r--r--Source/WebCore/platform/efl/ContextMenuEfl.cpp14
-rw-r--r--Source/WebCore/platform/efl/ContextMenuItemEfl.cpp16
-rw-r--r--Source/WebCore/platform/efl/FileSystemEfl.cpp8
-rw-r--r--Source/WebCore/platform/efl/GeolocationServiceEfl.cpp80
-rw-r--r--Source/WebCore/platform/efl/GeolocationServiceEfl.h56
-rw-r--r--Source/WebCore/platform/efl/LocalizedStringsEfl.cpp2
-rw-r--r--Source/WebCore/platform/efl/PlatformKeyboardEventEfl.cpp28
-rw-r--r--Source/WebCore/platform/efl/PlatformMouseEventEfl.cpp52
-rw-r--r--Source/WebCore/platform/efl/RenderThemeEfl.cpp65
-rw-r--r--Source/WebCore/platform/efl/RenderThemeEfl.h11
-rw-r--r--Source/WebCore/platform/efl/ScrollbarEfl.cpp72
-rw-r--r--Source/WebCore/platform/efl/ScrollbarEfl.h4
-rw-r--r--Source/WebCore/platform/efl/WidgetEfl.cpp18
-rw-r--r--Source/WebCore/platform/graphics/BitmapImage.h2
-rw-r--r--Source/WebCore/platform/graphics/Color.cpp27
-rw-r--r--Source/WebCore/platform/graphics/ContextShadow.h2
-rw-r--r--Source/WebCore/platform/graphics/Font.cpp2
-rw-r--r--Source/WebCore/platform/graphics/Font.h11
-rw-r--r--Source/WebCore/platform/graphics/FontCache.cpp14
-rw-r--r--Source/WebCore/platform/graphics/FontDescription.h10
-rw-r--r--Source/WebCore/platform/graphics/FontFallbackList.cpp17
-rw-r--r--Source/WebCore/platform/graphics/FontFallbackList.h3
-rw-r--r--Source/WebCore/platform/graphics/FontFastPath.cpp64
-rw-r--r--Source/WebCore/platform/graphics/FontPlatformData.cpp63
-rw-r--r--Source/WebCore/platform/graphics/FontPlatformData.h359
-rw-r--r--Source/WebCore/platform/graphics/GraphicsContext.h7
-rw-r--r--Source/WebCore/platform/graphics/GraphicsContext3D.h30
-rw-r--r--Source/WebCore/platform/graphics/GraphicsLayer.h5
-rw-r--r--Source/WebCore/platform/graphics/ImageBuffer.h4
-rw-r--r--Source/WebCore/platform/graphics/MediaPlayer.cpp31
-rw-r--r--Source/WebCore/platform/graphics/MediaPlayer.h35
-rw-r--r--Source/WebCore/platform/graphics/Path.cpp8
-rw-r--r--Source/WebCore/platform/graphics/Path.h8
-rw-r--r--Source/WebCore/platform/graphics/SimpleFontData.cpp42
-rw-r--r--Source/WebCore/platform/graphics/SimpleFontData.h30
-rw-r--r--Source/WebCore/platform/graphics/TextRun.h23
-rw-r--r--Source/WebCore/platform/graphics/Tile.h2
-rw-r--r--Source/WebCore/platform/graphics/TiledBackingStore.cpp10
-rw-r--r--Source/WebCore/platform/graphics/WOFFFileFormat.cpp4
-rw-r--r--Source/WebCore/platform/graphics/WidthIterator.cpp24
-rw-r--r--Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp731
-rw-r--r--Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h262
-rw-r--r--Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.h131
-rw-r--r--Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.mm811
-rw-r--r--Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp12
-rw-r--r--Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h5
-rw-r--r--Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp7
-rw-r--r--Source/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp7
-rw-r--r--Source/WebCore/platform/graphics/cairo/FontCairo.cpp9
-rw-r--r--Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h3
-rw-r--r--Source/WebCore/platform/graphics/cairo/GradientCairo.cpp3
-rw-r--r--Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp116
-rw-r--r--Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h30
-rw-r--r--Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp11
-rw-r--r--Source/WebCore/platform/graphics/cairo/ImageBufferData.h5
-rw-r--r--Source/WebCore/platform/graphics/cairo/ImageCairo.cpp6
-rw-r--r--Source/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp4
-rw-r--r--Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h4
-rw-r--r--Source/WebCore/platform/graphics/cairo/PathCairo.cpp2
-rw-r--r--Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp (renamed from Source/WebCore/platform/mac/WebCoreKeyGenerator.h)18
-rw-r--r--Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h (renamed from Source/WebCore/platform/mac/SSLKeyGeneratorMac.mm)45
-rw-r--r--Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp4
-rw-r--r--Source/WebCore/platform/graphics/cairo/RefPtrCairo.h4
-rw-r--r--Source/WebCore/platform/graphics/cg/FontPlatformData.h105
-rw-r--r--Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp36
-rw-r--r--Source/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h13
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp60
-rw-r--r--Source/WebCore/platform/graphics/cg/PathCG.cpp2
-rw-r--r--Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp2
-rw-r--r--Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h4
-rw-r--r--Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp28
-rw-r--r--Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h7
-rw-r--r--Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp51
-rw-r--r--Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h6
-rw-r--r--Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm2
-rw-r--r--Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp19
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp3
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp30
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontLinux.cpp2
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h3
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp10
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h11
-rw-r--r--Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp394
-rw-r--r--Source/WebCore/platform/graphics/chromium/GLES2Canvas.h19
-rw-r--r--Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp4
-rw-r--r--Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp4
-rw-r--r--Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerChromium.cpp101
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerChromium.h38
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp313
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h61
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp148
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h51
-rw-r--r--Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp38
-rw-r--r--Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h13
-rw-r--r--Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp17
-rw-r--r--Source/WebCore/platform/graphics/chromium/ShaderChromium.h4
-rw-r--r--Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp6
-rw-r--r--Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp227
-rw-r--r--Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h45
-rw-r--r--Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp16
-rw-r--r--Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h4
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp80
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h61
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp4
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp27
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h62
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp84
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h60
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp173
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h75
-rw-r--r--Source/WebCore/platform/graphics/cocoa/FontPlatformData.h176
-rw-r--r--Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm42
-rw-r--r--Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp2
-rw-r--r--Source/WebCore/platform/graphics/freetype/FontPlatformData.h1
-rw-r--r--Source/WebCore/platform/graphics/gpu/BicubicShader.cpp137
-rw-r--r--Source/WebCore/platform/graphics/gpu/BicubicShader.h58
-rw-r--r--Source/WebCore/platform/graphics/gpu/ConvolutionShader.cpp125
-rw-r--r--Source/WebCore/platform/graphics/gpu/ConvolutionShader.h58
-rw-r--r--Source/WebCore/platform/graphics/gpu/DrawingBuffer.h13
-rw-r--r--Source/WebCore/platform/graphics/gpu/LoopBlinnPathProcessor.cpp5
-rw-r--r--Source/WebCore/platform/graphics/gpu/PODRedBlackTree.h4
-rw-r--r--Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp69
-rw-r--r--Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h28
-rw-r--r--Source/WebCore/platform/graphics/gpu/TilingData.cpp2
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp36
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h2
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp2
-rw-r--r--Source/WebCore/platform/graphics/gtk/FontGtk.cpp23
-rw-r--r--Source/WebCore/platform/graphics/gtk/IconGtk.cpp6
-rw-r--r--Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp2
-rw-r--r--Source/WebCore/platform/graphics/gtk/ImageGtk.cpp5
-rw-r--r--Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp2
-rw-r--r--Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.h3
-rw-r--r--Source/WebCore/platform/graphics/mac/ComplexTextController.cpp24
-rw-r--r--Source/WebCore/platform/graphics/mac/ComplexTextController.h1
-rw-r--r--Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp2
-rw-r--r--Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp6
-rw-r--r--Source/WebCore/platform/graphics/mac/FontCacheMac.mm2
-rw-r--r--Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp4
-rw-r--r--Source/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp4
-rw-r--r--Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h3
-rw-r--r--Source/WebCore/platform/graphics/mac/FontMac.mm86
-rw-r--r--Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp4
-rw-r--r--Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm12
-rw-r--r--Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h6
-rw-r--r--Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm88
-rw-r--r--Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp10
-rw-r--r--Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm56
-rw-r--r--Source/WebCore/platform/graphics/mac/WebLayer.h3
-rw-r--r--Source/WebCore/platform/graphics/mac/WebLayer.mm6
-rw-r--r--Source/WebCore/platform/graphics/mac/WebTiledLayer.mm2
-rw-r--r--Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp125
-rw-r--r--Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp6
-rw-r--r--Source/WebCore/platform/graphics/opengl/TextureMapperGL.h2
-rw-r--r--Source/WebCore/platform/graphics/openvg/PathOpenVG.cpp8
-rw-r--r--Source/WebCore/platform/graphics/pango/FontCustomPlatformDataPango.cpp2
-rw-r--r--Source/WebCore/platform/graphics/pango/FontPlatformData.h2
-rw-r--r--Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp1
-rw-r--r--Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h4
-rw-r--r--Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp2
-rw-r--r--Source/WebCore/platform/graphics/qt/FontPlatformData.h1
-rw-r--r--Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp2
-rw-r--r--Source/WebCore/platform/graphics/qt/FontQt.cpp32
-rw-r--r--Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp324
-rw-r--r--Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp3
-rw-r--r--Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp44
-rw-r--r--Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h8
-rw-r--r--Source/WebCore/platform/graphics/qt/ImageBufferData.h2
-rw-r--r--Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp23
-rw-r--r--Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp10
-rw-r--r--Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp70
-rw-r--r--Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h7
-rw-r--r--Source/WebCore/platform/graphics/qt/PathQt.cpp22
-rw-r--r--Source/WebCore/platform/graphics/qt/TileQt.cpp8
-rw-r--r--Source/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp5
-rw-r--r--Source/WebCore/platform/graphics/skia/FontCustomPlatformData.h5
-rw-r--r--Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp2
-rw-r--r--Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp13
-rw-r--r--Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp42
-rw-r--r--Source/WebCore/platform/graphics/skia/ImageSkia.cpp1
-rw-r--r--Source/WebCore/platform/graphics/skia/PathSkia.cpp2
-rw-r--r--Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp27
-rw-r--r--Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp7
-rw-r--r--Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp9
-rw-r--r--Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h1
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapper.h4
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperNode.h8
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h8
-rw-r--r--Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.cpp9
-rw-r--r--Source/WebCore/platform/graphics/win/FontCacheWin.cpp2
-rw-r--r--Source/WebCore/platform/graphics/win/FontCustomPlatformData.cpp2
-rw-r--r--Source/WebCore/platform/graphics/win/FontCustomPlatformData.h4
-rw-r--r--Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp5
-rw-r--r--Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h2
-rw-r--r--Source/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp33
-rw-r--r--Source/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp69
-rw-r--r--Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp19
-rw-r--r--Source/WebCore/platform/graphics/win/FontWin.cpp4
-rw-r--r--Source/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp34
-rw-r--r--Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp14
-rw-r--r--Source/WebCore/platform/graphics/win/QTMovie.cpp11
-rw-r--r--Source/WebCore/platform/graphics/win/QTMovie.h1
-rw-r--r--Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp10
-rw-r--r--Source/WebCore/platform/graphics/win/cairo/FontPlatformData.h114
-rw-r--r--Source/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp2
-rw-r--r--Source/WebCore/platform/graphics/wince/FontCustomPlatformData.h3
-rw-r--r--Source/WebCore/platform/graphics/wince/FontPlatformData.cpp2
-rw-r--r--Source/WebCore/platform/graphics/wince/FontPlatformData.h1
-rw-r--r--Source/WebCore/platform/graphics/wince/PathWinCE.cpp2
-rw-r--r--Source/WebCore/platform/graphics/wx/FontPlatformData.h1
-rw-r--r--Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp4
-rw-r--r--Source/WebCore/platform/graphics/wx/PathWx.cpp2
-rw-r--r--Source/WebCore/platform/gtk/FileSystemGtk.cpp8
-rw-r--r--Source/WebCore/platform/gtk/LocalizedStringsGtk.cpp2
-rw-r--r--Source/WebCore/platform/gtk/RenderThemeGtk.cpp3
-rw-r--r--Source/WebCore/platform/gtk/RenderThemeGtk.h2
-rw-r--r--Source/WebCore/platform/gtk/RenderThemeGtk2.cpp94
-rw-r--r--Source/WebCore/platform/gtk/RenderThemeGtk3.cpp4
-rw-r--r--Source/WebCore/platform/gtk/ScrollViewGtk.cpp5
-rw-r--r--Source/WebCore/platform/gtk/ScrollbarThemeGtk3.cpp36
-rw-r--r--Source/WebCore/platform/gtk/WidgetGtk.cpp7
-rw-r--r--Source/WebCore/platform/gtk/WidgetRenderingContext.cpp3
-rw-r--r--Source/WebCore/platform/haiku/FileSystemHaiku.cpp4
-rw-r--r--Source/WebCore/platform/haiku/LocalizedStringsHaiku.cpp2
-rw-r--r--Source/WebCore/platform/image-decoders/ImageDecoder.h2
-rw-r--r--Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp15
-rw-r--r--Source/WebCore/platform/image-encoders/skia/JPEGImageEncoder.cpp49
-rw-r--r--Source/WebCore/platform/image-encoders/skia/JPEGImageEncoder.h7
-rw-r--r--Source/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp43
-rw-r--r--Source/WebCore/platform/image-encoders/skia/PNGImageEncoder.h5
-rw-r--r--Source/WebCore/platform/mac/FileSystemMac.mm13
-rw-r--r--Source/WebCore/platform/mac/HTMLConverter.h88
-rw-r--r--Source/WebCore/platform/mac/HTMLConverter.mm1682
-rw-r--r--Source/WebCore/platform/mac/LoggingMac.mm2
-rw-r--r--Source/WebCore/platform/mac/PasteboardMac.mm29
-rw-r--r--Source/WebCore/platform/mac/PlatformScreenMac.mm13
-rw-r--r--Source/WebCore/platform/mac/SSLKeyGeneratorMac.cpp70
-rw-r--r--Source/WebCore/platform/mac/ScrollAnimatorMac.h17
-rw-r--r--Source/WebCore/platform/mac/ScrollAnimatorMac.mm161
-rw-r--r--Source/WebCore/platform/mac/ScrollbarThemeMac.h3
-rw-r--r--Source/WebCore/platform/mac/ScrollbarThemeMac.mm8
-rw-r--r--Source/WebCore/platform/mac/ThemeMac.mm5
-rw-r--r--Source/WebCore/platform/mac/WebCoreObjCExtras.mm5
-rw-r--r--Source/WebCore/platform/mac/WebCoreSystemInterface.h15
-rw-r--r--Source/WebCore/platform/mac/WebCoreSystemInterface.mm10
-rw-r--r--Source/WebCore/platform/mac/WidgetMac.mm11
-rw-r--r--Source/WebCore/platform/mock/GeolocationClientMock.cpp5
-rw-r--r--Source/WebCore/platform/mock/GeolocationClientMock.h1
-rw-r--r--Source/WebCore/platform/network/BlobData.h4
-rw-r--r--Source/WebCore/platform/network/FormDataBuilder.cpp6
-rw-r--r--Source/WebCore/platform/network/ProtectionSpace.h2
-rw-r--r--Source/WebCore/platform/network/ProtectionSpaceHash.h2
-rw-r--r--Source/WebCore/platform/network/ResourceErrorBase.cpp1
-rw-r--r--Source/WebCore/platform/network/ResourceErrorBase.h3
-rw-r--r--Source/WebCore/platform/network/ResourceHandleClient.h7
-rw-r--r--Source/WebCore/platform/network/ResourceRequestBase.h2
-rw-r--r--Source/WebCore/platform/network/cf/CookieStorageCFNet.cpp27
-rw-r--r--Source/WebCore/platform/network/cf/CookieStorageCFNet.h2
-rw-r--r--Source/WebCore/platform/network/cf/LoaderRunLoopCF.h2
-rw-r--r--Source/WebCore/platform/network/cf/ResourceError.h35
-rw-r--r--Source/WebCore/platform/network/cf/ResourceErrorCF.cpp106
-rw-r--r--Source/WebCore/platform/network/cf/ResourceRequestCFNet.h5
-rw-r--r--Source/WebCore/platform/network/cf/ResourceResponse.h4
-rw-r--r--Source/WebCore/platform/network/cf/ResourceResponseCFNet.cpp9
-rw-r--r--Source/WebCore/platform/network/cf/SocketStreamHandle.h6
-rw-r--r--Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp4
-rw-r--r--Source/WebCore/platform/network/mac/CookieStorageMac.mm7
-rw-r--r--Source/WebCore/platform/network/mac/FormDataStreamMac.mm4
-rw-r--r--Source/WebCore/platform/network/mac/ResourceErrorMac.mm34
-rw-r--r--Source/WebCore/platform/network/mac/ResourceHandleMac.mm30
-rw-r--r--Source/WebCore/platform/network/mac/WebCoreURLResponse.h11
-rw-r--r--Source/WebCore/platform/network/mac/WebCoreURLResponse.mm743
-rw-r--r--Source/WebCore/platform/network/qt/DnsPrefetchHelper.h23
-rw-r--r--Source/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h10
-rw-r--r--Source/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp4
-rw-r--r--Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp512
-rw-r--r--Source/WebCore/platform/network/qt/QNetworkReplyHandler.h70
-rw-r--r--Source/WebCore/platform/network/qt/ResourceHandleQt.cpp12
-rw-r--r--Source/WebCore/platform/network/qt/ResourceRequestQt.cpp2
-rw-r--r--Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp5
-rw-r--r--Source/WebCore/platform/network/win/ResourceHandleWin.cpp10
-rw-r--r--Source/WebCore/platform/posix/FileSystemPOSIX.cpp37
-rw-r--r--Source/WebCore/platform/qt/CookieJarQt.cpp9
-rw-r--r--Source/WebCore/platform/qt/FileSystemQt.cpp8
-rw-r--r--Source/WebCore/platform/qt/LanguageQt.cpp2
-rw-r--r--Source/WebCore/platform/qt/PasteboardQt.cpp2
-rw-r--r--Source/WebCore/platform/qt/RenderThemeQt.cpp2
-rw-r--r--Source/WebCore/platform/text/BidiContext.cpp50
-rw-r--r--Source/WebCore/platform/text/BidiContext.h25
-rw-r--r--Source/WebCore/platform/text/BidiResolver.h375
-rw-r--r--Source/WebCore/platform/text/LocalizedNumber.h4
-rw-r--r--Source/WebCore/platform/text/LocalizedNumberICU.cpp4
-rw-r--r--Source/WebCore/platform/text/LocalizedNumberNone.cpp2
-rw-r--r--Source/WebCore/platform/text/TextCheckerClient.h4
-rw-r--r--Source/WebCore/platform/text/TextChecking.h (renamed from Source/WebCore/platform/chromium/WindowsVersion.h)19
-rw-r--r--Source/WebCore/platform/text/TextCodec.h2
-rw-r--r--Source/WebCore/platform/text/TextCodecICU.cpp7
-rw-r--r--Source/WebCore/platform/text/TextEncodingRegistry.cpp2
-rw-r--r--Source/WebCore/platform/text/TextOrientation.h (renamed from Source/WebCore/platform/mac/WebCoreKeyGenerator.m)40
-rw-r--r--Source/WebCore/platform/text/mac/LocalizedNumberMac.mm6
-rw-r--r--Source/WebCore/platform/text/qt/TextBreakIteratorQt.cpp3
-rw-r--r--Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp2
-rw-r--r--Source/WebCore/platform/win/CursorWin.cpp11
-rw-r--r--Source/WebCore/platform/win/FileSystemWin.cpp46
-rw-r--r--Source/WebCore/platform/win/LocalizedStringsWin.cpp39
-rw-r--r--Source/WebCore/platform/win/PathWalker.cpp51
-rw-r--r--Source/WebCore/platform/win/PathWalker.h51
-rw-r--r--Source/WebCore/platform/win/SSLKeyGeneratorWin.cpp1
-rw-r--r--Source/WebCore/platform/win/ScrollbarThemeWin.cpp2
-rw-r--r--Source/WebCore/platform/win/SystemInfo.cpp149
-rw-r--r--Source/WebCore/platform/win/SystemInfo.h37
-rw-r--r--Source/WebCore/platform/wince/FileSystemWinCE.cpp29
-rw-r--r--Source/WebCore/platform/wx/FileSystemWx.cpp4
-rw-r--r--Source/WebCore/platform/wx/LocalizedStringsWx.cpp2
375 files changed, 12822 insertions, 3542 deletions
diff --git a/Source/WebCore/platform/ColorData.gperf b/Source/WebCore/platform/ColorData.gperf
index 2a72237..277d83e 100644
--- a/Source/WebCore/platform/ColorData.gperf
+++ b/Source/WebCore/platform/ColorData.gperf
@@ -107,7 +107,7 @@ maroon, 0xff800000
mediumaquamarine, 0xff66cdaa
mediumblue, 0xff0000cd
mediumorchid, 0xffba55d3
-mediumpurple, 0xff9370d8
+mediumpurple, 0xff9370db
mediumseagreen, 0xff3cb371
mediumslateblue, 0xff7b68ee
mediumspringgreen, 0xff00fa9a
@@ -128,7 +128,7 @@ orchid, 0xffda70d6
palegoldenrod, 0xffeee8aa
palegreen, 0xff98fb98
paleturquoise, 0xffafeeee
-palevioletred, 0xffd87093
+palevioletred, 0xffdb7093
papayawhip, 0xffffefd5
peachpuff, 0xffffdab9
peru, 0xffcd853f
diff --git a/Source/WebCore/platform/CrossThreadCopier.h b/Source/WebCore/platform/CrossThreadCopier.h
index 5eb40ee..a25d6fa 100644
--- a/Source/WebCore/platform/CrossThreadCopier.h
+++ b/Source/WebCore/platform/CrossThreadCopier.h
@@ -56,7 +56,7 @@ namespace WebCore {
}
};
- template<bool isConvertibleToInteger, bool isThreadsafeShared, typename T> struct CrossThreadCopierBase;
+ template<bool isConvertibleToInteger, bool isThreadSafeRefCounted, typename T> struct CrossThreadCopierBase;
// Integers get passed through without any changes.
template<typename T> struct CrossThreadCopierBase<true, false, T> : public CrossThreadCopierPassThrough<T> {
@@ -114,8 +114,8 @@ namespace WebCore {
};
template<typename T> struct CrossThreadCopier : public CrossThreadCopierBase<WTF::IsConvertibleToInteger<T>::value,
- WTF::IsSubclassOfTemplate<typename WTF::RemoveTemplate<T, RefPtr>::Type, ThreadSafeShared>::value
- || WTF::IsSubclassOfTemplate<typename WTF::RemoveTemplate<T, PassRefPtr>::Type, ThreadSafeShared>::value,
+ WTF::IsSubclassOfTemplate<typename WTF::RemoveTemplate<T, RefPtr>::Type, ThreadSafeRefCounted>::value
+ || WTF::IsSubclassOfTemplate<typename WTF::RemoveTemplate<T, PassRefPtr>::Type, ThreadSafeRefCounted>::value,
T> {
};
diff --git a/Source/WebCore/platform/DefaultLocalizationStrategy.cpp b/Source/WebCore/platform/DefaultLocalizationStrategy.cpp
new file mode 100644
index 0000000..1a50c3c
--- /dev/null
+++ b/Source/WebCore/platform/DefaultLocalizationStrategy.cpp
@@ -0,0 +1,874 @@
+/*
+ * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 "DefaultLocalizationStrategy.h"
+
+#if USE(PLATFORM_STRATEGIES)
+
+#include "IntSize.h"
+#include "LocalizedStrings.h"
+#include "NotImplemented.h"
+#include <wtf/MathExtras.h>
+#include <wtf/text/CString.h>
+#include <wtf/UnusedParam.h>
+
+#if USE(CF)
+#include <wtf/RetainPtr.h>
+#endif
+
+namespace WebCore {
+
+// We can't use String::format for two reasons:
+// 1) It doesn't handle non-ASCII characters in the format string.
+// 2) It doesn't handle the %2$d syntax.
+// Note that because |format| is used as the second parameter to va_start, it cannot be a reference
+// type according to section 18.7/3 of the C++ N1905 standard.
+static String formatLocalizedString(String format, ...)
+{
+#if USE(CF)
+ va_list arguments;
+ va_start(arguments, format);
+ RetainPtr<CFStringRef> formatCFString(AdoptCF, format.createCFString());
+ RetainPtr<CFStringRef> result(AdoptCF, CFStringCreateWithFormatAndArguments(0, 0, formatCFString.get(), arguments));
+ va_end(arguments);
+ return result.get();
+#elif PLATFORM(QT)
+ va_list arguments;
+ va_start(arguments, format);
+ QString result;
+ result.vsprintf(format.latin1().data(), arguments);
+ va_end(arguments);
+ return result;
+#else
+ notImplemented();
+ return format;
+#endif
+}
+
+DefaultLocalizationStrategy::DefaultLocalizationStrategy()
+{
+}
+
+String DefaultLocalizationStrategy::inputElementAltText()
+{
+ return UI_STRING_KEY("Submit", "Submit (input element)", "alt text for <input> elements with no alt, title, or value");
+}
+
+String DefaultLocalizationStrategy::resetButtonDefaultLabel()
+{
+ return UI_STRING("Reset", "default label for Reset buttons in forms on web pages");
+}
+
+String DefaultLocalizationStrategy::searchableIndexIntroduction()
+{
+ return UI_STRING("This is a searchable index. Enter search keywords: ",
+ "text that appears at the start of nearly-obsolete web pages in the form of a 'searchable index'");
+}
+
+String DefaultLocalizationStrategy::submitButtonDefaultLabel()
+{
+ return UI_STRING("Submit", "default label for Submit buttons in forms on web pages");
+}
+
+String DefaultLocalizationStrategy::fileButtonChooseFileLabel()
+{
+ return UI_STRING("Choose File", "title for file button used in HTML forms");
+}
+
+String DefaultLocalizationStrategy::fileButtonNoFileSelectedLabel()
+{
+ return UI_STRING("no file selected", "text to display in file button used in HTML forms when no file is selected");
+}
+
+String DefaultLocalizationStrategy::defaultDetailsSummaryText()
+{
+ return UI_STRING("Details", "text to display in <details> tag when it has no <summary> child");
+}
+
+#if PLATFORM(MAC)
+String DefaultLocalizationStrategy::copyImageUnknownFileLabel()
+{
+ return UI_STRING("unknown", "Unknown filename");
+}
+#endif
+
+#if ENABLE(CONTEXT_MENUS)
+
+String DefaultLocalizationStrategy::contextMenuItemTagOpenLinkInNewWindow()
+{
+ return UI_STRING("Open Link in New Window", "Open in New Window context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagDownloadLinkToDisk()
+{
+ return UI_STRING("Download Linked File", "Download Linked File context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagCopyLinkToClipboard()
+{
+ return UI_STRING("Copy Link", "Copy Link context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagOpenImageInNewWindow()
+{
+ return UI_STRING("Open Image in New Window", "Open Image in New Window context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagDownloadImageToDisk()
+{
+ return UI_STRING("Download Image", "Download Image context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagCopyImageToClipboard()
+{
+ return UI_STRING("Copy Image", "Copy Image context menu item");
+}
+
+#if PLATFORM(QT)
+String DefaultLocalizationStrategy::contextMenuItemTagCopyImageUrlToClipboard()
+{
+ return UI_STRING("Copy Image Address", "Copy Image Address menu item");
+}
+#endif
+
+String DefaultLocalizationStrategy::contextMenuItemTagOpenVideoInNewWindow()
+{
+ return UI_STRING("Open Video in New Window", "Open Video in New Window context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagOpenAudioInNewWindow()
+{
+ return UI_STRING("Open Audio in New Window", "Open Audio in New Window context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagCopyVideoLinkToClipboard()
+{
+ return UI_STRING("Copy Video Address", "Copy Video Address Location context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagCopyAudioLinkToClipboard()
+{
+ return UI_STRING("Copy Audio Address", "Copy Audio Address Location context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagToggleMediaControls()
+{
+ return UI_STRING("Controls", "Media Controls context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagToggleMediaLoop()
+{
+ return UI_STRING("Loop", "Media Loop context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagEnterVideoFullscreen()
+{
+ return UI_STRING("Enter Fullscreen", "Video Enter Fullscreen context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagMediaPlay()
+{
+ return UI_STRING("Play", "Media Play context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagMediaPause()
+{
+ return UI_STRING("Pause", "Media Pause context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagMediaMute()
+{
+ return UI_STRING("Mute", "Media Mute context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagOpenFrameInNewWindow()
+{
+ return UI_STRING("Open Frame in New Window", "Open Frame in New Window context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagCopy()
+{
+ return UI_STRING("Copy", "Copy context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagGoBack()
+{
+ return UI_STRING("Back", "Back context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagGoForward()
+{
+ return UI_STRING("Forward", "Forward context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagStop()
+{
+ return UI_STRING("Stop", "Stop context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagReload()
+{
+ return UI_STRING("Reload", "Reload context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagCut()
+{
+ return UI_STRING("Cut", "Cut context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagPaste()
+{
+ return UI_STRING("Paste", "Paste context menu item");
+}
+
+#if PLATFORM(GTK)
+
+String DefaultLocalizationStrategy::contextMenuItemTagDelete()
+{
+ notImplemented();
+ return "Delete";
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagInputMethods()
+{
+ notImplemented();
+ return "Input Methods";
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagUnicode()
+{
+ notImplemented();
+ return "Unicode";
+}
+
+#endif
+
+#if PLATFORM(GTK) || PLATFORM(QT)
+
+String DefaultLocalizationStrategy::contextMenuItemTagSelectAll()
+{
+ notImplemented();
+ return "Select All";
+}
+
+#endif
+
+String DefaultLocalizationStrategy::contextMenuItemTagNoGuessesFound()
+{
+ return UI_STRING("No Guesses Found", "No Guesses Found context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagIgnoreSpelling()
+{
+ return UI_STRING("Ignore Spelling", "Ignore Spelling context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagLearnSpelling()
+{
+ return UI_STRING("Learn Spelling", "Learn Spelling context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagSearchWeb()
+{
+ return UI_STRING("Search in Google", "Search in Google context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagLookUpInDictionary(const String& selectedString)
+{
+#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD)
+ UNUSED_PARAM(selectedString);
+ return UI_STRING("Look Up in Dictionary", "Look Up in Dictionary context menu item");
+#else
+ return UI_STRING("Look Up “<selection>”", "Look Up context menu item with selected word").replace("<selection>", selectedString);
+#endif
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagOpenLink()
+{
+ return UI_STRING("Open Link", "Open Link context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagIgnoreGrammar()
+{
+ return UI_STRING("Ignore Grammar", "Ignore Grammar context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagSpellingMenu()
+{
+ return UI_STRING("Spelling and Grammar", "Spelling and Grammar context sub-menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagShowSpellingPanel(bool show)
+{
+ if (show)
+ return UI_STRING("Show Spelling and Grammar", "menu item title");
+ return UI_STRING("Hide Spelling and Grammar", "menu item title");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagCheckSpelling()
+{
+ return UI_STRING("Check Document Now", "Check spelling context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagCheckSpellingWhileTyping()
+{
+ return UI_STRING("Check Spelling While Typing", "Check spelling while typing context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagCheckGrammarWithSpelling()
+{
+ return UI_STRING("Check Grammar With Spelling", "Check grammar with spelling context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagFontMenu()
+{
+ return UI_STRING("Font", "Font context sub-menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagBold()
+{
+ return UI_STRING("Bold", "Bold context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagItalic()
+{
+ return UI_STRING("Italic", "Italic context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagUnderline()
+{
+ return UI_STRING("Underline", "Underline context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagOutline()
+{
+ return UI_STRING("Outline", "Outline context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagWritingDirectionMenu()
+{
+ return UI_STRING("Paragraph Direction", "Paragraph direction context sub-menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagTextDirectionMenu()
+{
+ return UI_STRING("Selection Direction", "Selection direction context sub-menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagDefaultDirection()
+{
+ return UI_STRING("Default", "Default writing direction context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagLeftToRight()
+{
+ return UI_STRING("Left to Right", "Left to Right context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagRightToLeft()
+{
+ return UI_STRING("Right to Left", "Right to Left context menu item");
+}
+
+#if PLATFORM(MAC)
+
+String DefaultLocalizationStrategy::contextMenuItemTagSearchInSpotlight()
+{
+ return UI_STRING("Search in Spotlight", "Search in Spotlight context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagShowFonts()
+{
+ return UI_STRING("Show Fonts", "Show fonts context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagStyles()
+{
+ return UI_STRING("Styles...", "Styles context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagShowColors()
+{
+ return UI_STRING("Show Colors", "Show colors context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagSpeechMenu()
+{
+ return UI_STRING("Speech", "Speech context sub-menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagStartSpeaking()
+{
+ return UI_STRING("Start Speaking", "Start speaking context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagStopSpeaking()
+{
+ return UI_STRING("Stop Speaking", "Stop speaking context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagCorrectSpellingAutomatically()
+{
+ return UI_STRING("Correct Spelling Automatically", "Correct Spelling Automatically context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagSubstitutionsMenu()
+{
+ return UI_STRING("Substitutions", "Substitutions context sub-menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagShowSubstitutions(bool show)
+{
+ if (show)
+ return UI_STRING("Show Substitutions", "menu item title");
+ return UI_STRING("Hide Substitutions", "menu item title");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagSmartCopyPaste()
+{
+ return UI_STRING("Smart Copy/Paste", "Smart Copy/Paste context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagSmartQuotes()
+{
+ return UI_STRING("Smart Quotes", "Smart Quotes context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagSmartDashes()
+{
+ return UI_STRING("Smart Dashes", "Smart Dashes context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagSmartLinks()
+{
+ return UI_STRING("Smart Links", "Smart Links context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagTextReplacement()
+{
+ return UI_STRING("Text Replacement", "Text Replacement context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagTransformationsMenu()
+{
+ return UI_STRING("Transformations", "Transformations context sub-menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagMakeUpperCase()
+{
+ return UI_STRING("Make Upper Case", "Make Upper Case context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagMakeLowerCase()
+{
+ return UI_STRING("Make Lower Case", "Make Lower Case context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagCapitalize()
+{
+ return UI_STRING("Capitalize", "Capitalize context menu item");
+}
+
+String DefaultLocalizationStrategy::contextMenuItemTagChangeBack(const String& replacedString)
+{
+ notImplemented();
+ return replacedString;
+}
+
+#endif
+
+String DefaultLocalizationStrategy::contextMenuItemTagInspectElement()
+{
+ return UI_STRING("Inspect Element", "Inspect Element context menu item");
+}
+
+#endif // ENABLE(CONTEXT_MENUS)
+
+String DefaultLocalizationStrategy::searchMenuNoRecentSearchesText()
+{
+ return UI_STRING("No recent searches", "Label for only item in menu that appears when clicking on the search field image, when no searches have been performed");
+}
+
+String DefaultLocalizationStrategy::searchMenuRecentSearchesText()
+{
+ return UI_STRING("Recent Searches", "label for first item in the menu that appears when clicking on the search field image, used as embedded menu title");
+}
+
+String DefaultLocalizationStrategy::searchMenuClearRecentSearchesText()
+{
+ return UI_STRING("Clear Recent Searches", "menu item in Recent Searches menu that empties menu's contents");
+}
+
+String DefaultLocalizationStrategy::AXWebAreaText()
+{
+ return UI_STRING("HTML content", "accessibility role description for web area");
+}
+
+String DefaultLocalizationStrategy::AXLinkText()
+{
+ return UI_STRING("link", "accessibility role description for link");
+}
+
+String DefaultLocalizationStrategy::AXListMarkerText()
+{
+ return UI_STRING("list marker", "accessibility role description for list marker");
+}
+
+String DefaultLocalizationStrategy::AXImageMapText()
+{
+ return UI_STRING("image map", "accessibility role description for image map");
+}
+
+String DefaultLocalizationStrategy::AXHeadingText()
+{
+ return UI_STRING("heading", "accessibility role description for headings");
+}
+
+String DefaultLocalizationStrategy::AXDefinitionListTermText()
+{
+ return UI_STRING("term", "term word of a definition");
+}
+
+String DefaultLocalizationStrategy::AXDefinitionListDefinitionText()
+{
+ return UI_STRING("definition", "definition phrase");
+}
+
+#if PLATFORM(MAC)
+String DefaultLocalizationStrategy::AXARIAContentGroupText(const String& ariaType)
+{
+ if (ariaType == "ARIAApplicationAlert")
+ return UI_STRING("alert", "An ARIA accessibility group that acts as an alert.");
+ if (ariaType == "ARIAApplicationAlertDialog")
+ return UI_STRING("alert dialog", "An ARIA accessibility group that acts as an alert dialog.");
+ if (ariaType == "ARIAApplicationDialog")
+ return UI_STRING("dialog", "An ARIA accessibility group that acts as an dialog.");
+ if (ariaType == "ARIAApplicationLog")
+ return UI_STRING("log", "An ARIA accessibility group that acts as a console log.");
+ if (ariaType == "ARIAApplicationMarquee")
+ return UI_STRING("marquee", "An ARIA accessibility group that acts as a marquee.");
+ if (ariaType == "ARIAApplicationStatus")
+ return UI_STRING("application status", "An ARIA accessibility group that acts as a status update.");
+ if (ariaType == "ARIAApplicationTimer")
+ return UI_STRING("timer", "An ARIA accessibility group that acts as an updating timer.");
+ if (ariaType == "ARIADocument")
+ return UI_STRING("document", "An ARIA accessibility group that acts as a document.");
+ if (ariaType == "ARIADocumentArticle")
+ return UI_STRING("article", "An ARIA accessibility group that acts as an article.");
+ if (ariaType == "ARIADocumentNote")
+ return UI_STRING("note", "An ARIA accessibility group that acts as a note in a document.");
+ if (ariaType == "ARIADocumentRegion")
+ return UI_STRING("region", "An ARIA accessibility group that acts as a distinct region in a document.");
+ if (ariaType == "ARIALandmarkApplication")
+ return UI_STRING("application", "An ARIA accessibility group that acts as an application.");
+ if (ariaType == "ARIALandmarkBanner")
+ return UI_STRING("banner", "An ARIA accessibility group that acts as a banner.");
+ if (ariaType == "ARIALandmarkComplementary")
+ return UI_STRING("complementary", "An ARIA accessibility group that acts as a region of complementary information.");
+ if (ariaType == "ARIALandmarkContentInfo")
+ return UI_STRING("content", "An ARIA accessibility group that contains content.");
+ if (ariaType == "ARIALandmarkMain")
+ return UI_STRING("main", "An ARIA accessibility group that is the main portion of the website.");
+ if (ariaType == "ARIALandmarkNavigation")
+ return UI_STRING("navigation", "An ARIA accessibility group that contains the main navigation elements of a website.");
+ if (ariaType == "ARIALandmarkSearch")
+ return UI_STRING("search", "An ARIA accessibility group that contains a search feature of a website.");
+ if (ariaType == "ARIAUserInterfaceTooltip")
+ return UI_STRING("tooltip", "An ARIA accessibility group that acts as a tooltip.");
+ if (ariaType == "ARIATabPanel")
+ return UI_STRING("tab panel", "An ARIA accessibility group that contains the content of a tab.");
+ if (ariaType == "ARIADocumentMath")
+ return UI_STRING("math", "An ARIA accessibility group that contains mathematical symbols.");
+ return String();
+}
+#endif
+
+String DefaultLocalizationStrategy::AXButtonActionVerb()
+{
+ return UI_STRING("press", "Verb stating the action that will occur when a button is pressed, as used by accessibility");
+}
+
+String DefaultLocalizationStrategy::AXRadioButtonActionVerb()
+{
+ return UI_STRING("select", "Verb stating the action that will occur when a radio button is clicked, as used by accessibility");
+}
+
+String DefaultLocalizationStrategy::AXTextFieldActionVerb()
+{
+ return UI_STRING("activate", "Verb stating the action that will occur when a text field is selected, as used by accessibility");
+}
+
+String DefaultLocalizationStrategy::AXCheckedCheckBoxActionVerb()
+{
+ return UI_STRING("uncheck", "Verb stating the action that will occur when a checked checkbox is clicked, as used by accessibility");
+}
+
+String DefaultLocalizationStrategy::AXUncheckedCheckBoxActionVerb()
+{
+ return UI_STRING("check", "Verb stating the action that will occur when an unchecked checkbox is clicked, as used by accessibility");
+}
+
+String DefaultLocalizationStrategy::AXMenuListActionVerb()
+{
+ notImplemented();
+ return "select";
+}
+
+String DefaultLocalizationStrategy::AXMenuListPopupActionVerb()
+{
+ notImplemented();
+ return "select";
+}
+
+String DefaultLocalizationStrategy::AXLinkActionVerb()
+{
+ return UI_STRING("jump", "Verb stating the action that will occur when a link is clicked, as used by accessibility");
+}
+
+String DefaultLocalizationStrategy::missingPluginText()
+{
+ return UI_STRING("Missing Plug-in", "Label text to be used when a plugin is missing");
+}
+
+String DefaultLocalizationStrategy::crashedPluginText()
+{
+ return UI_STRING("Plug-in Failure", "Label text to be used if plugin host process has crashed");
+}
+
+String DefaultLocalizationStrategy::multipleFileUploadText(unsigned numberOfFiles)
+{
+ return formatLocalizedString(UI_STRING("%d files", "Label to describe the number of files selected in a file upload control that allows multiple files"), numberOfFiles);
+}
+
+String DefaultLocalizationStrategy::unknownFileSizeText()
+{
+ return UI_STRING("Unknown", "Unknown filesize FTP directory listing item");
+}
+
+#if PLATFORM(WIN)
+
+String DefaultLocalizationStrategy::uploadFileText()
+{
+ notImplemented();
+ return "upload";
+}
+
+String DefaultLocalizationStrategy::allFilesText()
+{
+ notImplemented();
+ return "all files";
+}
+
+#endif
+
+#if PLATFORM(MAC)
+
+String DefaultLocalizationStrategy::keygenMenuItem512()
+{
+ return UI_STRING("512 (Low Grade)", "Menu item title for KEYGEN pop-up menu");
+}
+
+String DefaultLocalizationStrategy::keygenMenuItem1024()
+{
+ return UI_STRING("1024 (Medium Grade)", "Menu item title for KEYGEN pop-up menu");
+}
+
+String DefaultLocalizationStrategy::keygenMenuItem2048()
+{
+ return UI_STRING("2048 (High Grade)", "Menu item title for KEYGEN pop-up menu");
+}
+
+String DefaultLocalizationStrategy::keygenKeychainItemName(const String& host)
+{
+ return UI_STRING("Key from <hostname>", "Name of keychain key generated by the KEYGEN tag").replace("<hostname>", host);
+}
+
+#endif
+
+String DefaultLocalizationStrategy::imageTitle(const String& filename, const IntSize& size)
+{
+ // FIXME: This should format the numbers correctly. In Mac WebKit, we used +[NSNumberFormatter localizedStringFromNumber:numberStyle:].
+ return formatLocalizedString(UI_STRING("<filename> %d×%d pixels", "window title suffix for a standalone image (uses multiplication symbol, not x)"), size.width(), size.height()).replace("<filename>", filename);
+}
+
+String DefaultLocalizationStrategy::mediaElementLoadingStateText()
+{
+ return UI_STRING("Loading...", "Media controller status message when the media is loading");
+}
+
+String DefaultLocalizationStrategy::mediaElementLiveBroadcastStateText()
+{
+ return UI_STRING("Live Broadcast", "Media controller status message when watching a live broadcast");
+}
+
+String DefaultLocalizationStrategy::localizedMediaControlElementString(const String& name)
+{
+ if (name == "AudioElement")
+ return UI_STRING("audio element controller", "accessibility role description for audio element controller");
+ if (name == "VideoElement")
+ return UI_STRING("video element controller", "accessibility role description for video element controller");
+ if (name == "MuteButton")
+ return UI_STRING("mute", "accessibility role description for mute button");
+ if (name == "UnMuteButton")
+ return UI_STRING("unmute", "accessibility role description for turn mute off button");
+ if (name == "PlayButton")
+ return UI_STRING("play", "accessibility role description for play button");
+ if (name == "PauseButton")
+ return UI_STRING("pause", "accessibility role description for pause button");
+ if (name == "Slider")
+ return UI_STRING("movie time", "accessibility role description for timeline slider");
+ if (name == "SliderThumb")
+ return UI_STRING("timeline slider thumb", "accessibility role description for timeline thumb");
+ if (name == "RewindButton")
+ return UI_STRING("back 30 seconds", "accessibility role description for seek back 30 seconds button");
+ if (name == "ReturnToRealtimeButton")
+ return UI_STRING("return to realtime", "accessibility role description for return to real time button");
+ if (name == "CurrentTimeDisplay")
+ return UI_STRING("elapsed time", "accessibility role description for elapsed time display");
+ if (name == "TimeRemainingDisplay")
+ return UI_STRING("remaining time", "accessibility role description for time remaining display");
+ if (name == "StatusDisplay")
+ return UI_STRING("status", "accessibility role description for movie status");
+ if (name == "FullscreenButton")
+ return UI_STRING("fullscreen", "accessibility role description for enter fullscreen button");
+ if (name == "SeekForwardButton")
+ return UI_STRING("fast forward", "accessibility role description for fast forward button");
+ if (name == "SeekBackButton")
+ return UI_STRING("fast reverse", "accessibility role description for fast reverse button");
+ if (name == "ShowClosedCaptionsButton")
+ return UI_STRING("show closed captions", "accessibility role description for show closed captions button");
+ if (name == "HideClosedCaptionsButton")
+ return UI_STRING("hide closed captions", "accessibility role description for hide closed captions button");
+
+ // FIXME: the ControlsPanel container should never be visible in the accessibility hierarchy.
+ if (name == "ControlsPanel")
+ return String();
+
+ ASSERT_NOT_REACHED();
+ return String();
+}
+
+String DefaultLocalizationStrategy::localizedMediaControlElementHelpText(const String& name)
+{
+ if (name == "AudioElement")
+ return UI_STRING("audio element playback controls and status display", "accessibility role description for audio element controller");
+ if (name == "VideoElement")
+ return UI_STRING("video element playback controls and status display", "accessibility role description for video element controller");
+ if (name == "MuteButton")
+ return UI_STRING("mute audio tracks", "accessibility help text for mute button");
+ if (name == "UnMuteButton")
+ return UI_STRING("unmute audio tracks", "accessibility help text for un mute button");
+ if (name == "PlayButton")
+ return UI_STRING("begin playback", "accessibility help text for play button");
+ if (name == "PauseButton")
+ return UI_STRING("pause playback", "accessibility help text for pause button");
+ if (name == "Slider")
+ return UI_STRING("movie time scrubber", "accessibility help text for timeline slider");
+ if (name == "SliderThumb")
+ return UI_STRING("movie time scrubber thumb", "accessibility help text for timeline slider thumb");
+ if (name == "RewindButton")
+ return UI_STRING("seek movie back 30 seconds", "accessibility help text for jump back 30 seconds button");
+ if (name == "ReturnToRealtimeButton")
+ return UI_STRING("return streaming movie to real time", "accessibility help text for return streaming movie to real time button");
+ if (name == "CurrentTimeDisplay")
+ return UI_STRING("current movie time in seconds", "accessibility help text for elapsed time display");
+ if (name == "TimeRemainingDisplay")
+ return UI_STRING("number of seconds of movie remaining", "accessibility help text for remaining time display");
+ if (name == "StatusDisplay")
+ return UI_STRING("current movie status", "accessibility help text for movie status display");
+ if (name == "SeekBackButton")
+ return UI_STRING("seek quickly back", "accessibility help text for fast rewind button");
+ if (name == "SeekForwardButton")
+ return UI_STRING("seek quickly forward", "accessibility help text for fast forward button");
+ if (name == "FullscreenButton")
+ return UI_STRING("Play movie in fullscreen mode", "accessibility help text for enter fullscreen button");
+ if (name == "ShowClosedCaptionsButton")
+ return UI_STRING("start displaying closed captions", "accessibility help text for show closed captions button");
+ if (name == "HideClosedCaptionsButton")
+ return UI_STRING("stop displaying closed captions", "accessibility help text for hide closed captions button");
+
+ ASSERT_NOT_REACHED();
+ return String();
+}
+
+String DefaultLocalizationStrategy::localizedMediaTimeDescription(float time)
+{
+ if (!isfinite(time))
+ return UI_STRING("indefinite time", "accessibility help text for an indefinite media controller time value");
+
+ int seconds = static_cast<int>(fabsf(time));
+ int days = seconds / (60 * 60 * 24);
+ int hours = seconds / (60 * 60);
+ int minutes = (seconds / 60) % 60;
+ seconds %= 60;
+
+ if (days)
+ return formatLocalizedString(UI_STRING("%1$d days %2$d hours %3$d minutes %4$d seconds", "accessibility help text for media controller time value >= 1 day"), days, hours, minutes, seconds);
+ if (hours)
+ return formatLocalizedString(UI_STRING("%1$d hours %2$d minutes %3$d seconds", "accessibility help text for media controller time value >= 60 minutes"), hours, minutes, seconds);
+ if (minutes)
+ return formatLocalizedString(UI_STRING("%1$d minutes %2$d seconds", "accessibility help text for media controller time value >= 60 seconds"), minutes, seconds);
+ return formatLocalizedString(UI_STRING("%1$d seconds", "accessibility help text for media controller time value < 60 seconds"), seconds);
+}
+
+String DefaultLocalizationStrategy::validationMessageValueMissingText()
+{
+ return UI_STRING("value missing", "Validation message for required form control elements that have no value");
+}
+
+String DefaultLocalizationStrategy::validationMessageTypeMismatchText()
+{
+ return UI_STRING("type mismatch", "Validation message for input form controls with a value not matching type");
+}
+
+String DefaultLocalizationStrategy::validationMessagePatternMismatchText()
+{
+ return UI_STRING("pattern mismatch", "Validation message for input form controls requiring a constrained value according to pattern");
+}
+
+String DefaultLocalizationStrategy::validationMessageTooLongText()
+{
+ return UI_STRING("too long", "Validation message for form control elements with a value longer than maximum allowed length");
+}
+
+String DefaultLocalizationStrategy::validationMessageRangeUnderflowText()
+{
+ return UI_STRING("range underflow", "Validation message for input form controls with value lower than allowed minimum");
+}
+
+String DefaultLocalizationStrategy::validationMessageRangeOverflowText()
+{
+ return UI_STRING("range overflow", "Validation message for input form controls with value higher than allowed maximum");
+}
+
+String DefaultLocalizationStrategy::validationMessageStepMismatchText()
+{
+ return UI_STRING("step mismatch", "Validation message for input form controls with value not respecting the step attribute");
+}
+
+} // namespace WebCore
+
+#endif // USE(PLATFORM_STRATEGIES)
diff --git a/Source/WebCore/platform/DefaultLocalizationStrategy.h b/Source/WebCore/platform/DefaultLocalizationStrategy.h
new file mode 100644
index 0000000..56120e0
--- /dev/null
+++ b/Source/WebCore/platform/DefaultLocalizationStrategy.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 DefaultLocalizationStrategy_h
+#define DefaultLocalizationStrategy_h
+
+#if USE(PLATFORM_STRATEGIES)
+
+#include "LocalizationStrategy.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class DefaultLocalizationStrategy : public LocalizationStrategy {
+public:
+ DefaultLocalizationStrategy();
+
+private:
+ virtual String inputElementAltText();
+ virtual String resetButtonDefaultLabel();
+ virtual String searchableIndexIntroduction();
+ virtual String submitButtonDefaultLabel();
+ virtual String fileButtonChooseFileLabel();
+ virtual String fileButtonNoFileSelectedLabel();
+ virtual String defaultDetailsSummaryText();
+#if PLATFORM(MAC)
+ virtual String copyImageUnknownFileLabel();
+#endif
+#if ENABLE(CONTEXT_MENUS)
+ virtual String contextMenuItemTagOpenLinkInNewWindow();
+ virtual String contextMenuItemTagDownloadLinkToDisk();
+ virtual String contextMenuItemTagCopyLinkToClipboard();
+ virtual String contextMenuItemTagOpenImageInNewWindow();
+ virtual String contextMenuItemTagDownloadImageToDisk();
+ virtual String contextMenuItemTagCopyImageToClipboard();
+#if PLATFORM(QT)
+ virtual String contextMenuItemTagCopyImageUrlToClipboard();
+#endif
+ virtual String contextMenuItemTagOpenFrameInNewWindow();
+ virtual String contextMenuItemTagCopy();
+ virtual String contextMenuItemTagGoBack();
+ virtual String contextMenuItemTagGoForward();
+ virtual String contextMenuItemTagStop();
+ virtual String contextMenuItemTagReload();
+ virtual String contextMenuItemTagCut();
+ virtual String contextMenuItemTagPaste();
+#if PLATFORM(GTK)
+ virtual String contextMenuItemTagDelete();
+ virtual String contextMenuItemTagInputMethods();
+ virtual String contextMenuItemTagUnicode();
+#endif
+#if PLATFORM(GTK) || PLATFORM(QT)
+ virtual String contextMenuItemTagSelectAll();
+#endif
+ virtual String contextMenuItemTagNoGuessesFound();
+ virtual String contextMenuItemTagIgnoreSpelling();
+ virtual String contextMenuItemTagLearnSpelling();
+ virtual String contextMenuItemTagSearchWeb();
+ virtual String contextMenuItemTagLookUpInDictionary(const String& selectedString);
+ virtual String contextMenuItemTagOpenLink();
+ virtual String contextMenuItemTagIgnoreGrammar();
+ virtual String contextMenuItemTagSpellingMenu();
+ virtual String contextMenuItemTagShowSpellingPanel(bool show);
+ virtual String contextMenuItemTagCheckSpelling();
+ virtual String contextMenuItemTagCheckSpellingWhileTyping();
+ virtual String contextMenuItemTagCheckGrammarWithSpelling();
+ virtual String contextMenuItemTagFontMenu();
+ virtual String contextMenuItemTagBold();
+ virtual String contextMenuItemTagItalic();
+ virtual String contextMenuItemTagUnderline();
+ virtual String contextMenuItemTagOutline();
+ virtual String contextMenuItemTagWritingDirectionMenu();
+ virtual String contextMenuItemTagTextDirectionMenu();
+ virtual String contextMenuItemTagDefaultDirection();
+ virtual String contextMenuItemTagLeftToRight();
+ virtual String contextMenuItemTagRightToLeft();
+#if PLATFORM(MAC)
+ virtual String contextMenuItemTagSearchInSpotlight();
+ virtual String contextMenuItemTagShowFonts();
+ virtual String contextMenuItemTagStyles();
+ virtual String contextMenuItemTagShowColors();
+ virtual String contextMenuItemTagSpeechMenu();
+ virtual String contextMenuItemTagStartSpeaking();
+ virtual String contextMenuItemTagStopSpeaking();
+ virtual String contextMenuItemTagCorrectSpellingAutomatically();
+ virtual String contextMenuItemTagSubstitutionsMenu();
+ virtual String contextMenuItemTagShowSubstitutions(bool show);
+ virtual String contextMenuItemTagSmartCopyPaste();
+ virtual String contextMenuItemTagSmartQuotes();
+ virtual String contextMenuItemTagSmartDashes();
+ virtual String contextMenuItemTagSmartLinks();
+ virtual String contextMenuItemTagTextReplacement();
+ virtual String contextMenuItemTagTransformationsMenu();
+ virtual String contextMenuItemTagMakeUpperCase();
+ virtual String contextMenuItemTagMakeLowerCase();
+ virtual String contextMenuItemTagCapitalize();
+ virtual String contextMenuItemTagChangeBack(const String& replacedString);
+#endif
+ virtual String contextMenuItemTagInspectElement();
+ virtual String contextMenuItemTagOpenVideoInNewWindow();
+ virtual String contextMenuItemTagOpenAudioInNewWindow();
+ virtual String contextMenuItemTagCopyVideoLinkToClipboard();
+ virtual String contextMenuItemTagCopyAudioLinkToClipboard();
+ virtual String contextMenuItemTagToggleMediaControls();
+ virtual String contextMenuItemTagToggleMediaLoop();
+ virtual String contextMenuItemTagEnterVideoFullscreen();
+ virtual String contextMenuItemTagMediaPlay();
+ virtual String contextMenuItemTagMediaPause();
+ virtual String contextMenuItemTagMediaMute();
+#endif // ENABLE(CONTEXT_MENUS)
+ virtual String searchMenuNoRecentSearchesText();
+ virtual String searchMenuRecentSearchesText();
+ virtual String searchMenuClearRecentSearchesText();
+ virtual String AXWebAreaText();
+ virtual String AXLinkText();
+ virtual String AXListMarkerText();
+ virtual String AXImageMapText();
+ virtual String AXHeadingText();
+ virtual String AXDefinitionListTermText();
+ virtual String AXDefinitionListDefinitionText();
+#if PLATFORM(MAC)
+ virtual String AXARIAContentGroupText(const String& ariaType);
+#endif
+ virtual String AXButtonActionVerb();
+ virtual String AXRadioButtonActionVerb();
+ virtual String AXTextFieldActionVerb();
+ virtual String AXCheckedCheckBoxActionVerb();
+ virtual String AXUncheckedCheckBoxActionVerb();
+ virtual String AXMenuListActionVerb();
+ virtual String AXMenuListPopupActionVerb();
+ virtual String AXLinkActionVerb();
+ virtual String missingPluginText();
+ virtual String crashedPluginText();
+ virtual String multipleFileUploadText(unsigned numberOfFiles);
+ virtual String unknownFileSizeText();
+#if PLATFORM(WIN)
+ virtual String uploadFileText();
+ virtual String allFilesText();
+#endif
+#if PLATFORM(MAC)
+ virtual String keygenMenuItem512();
+ virtual String keygenMenuItem1024();
+ virtual String keygenMenuItem2048();
+ virtual String keygenKeychainItemName(const String& host);
+#endif
+ virtual String imageTitle(const String& filename, const IntSize&);
+ virtual String mediaElementLoadingStateText();
+ virtual String mediaElementLiveBroadcastStateText();
+ virtual String localizedMediaControlElementString(const String&);
+ virtual String localizedMediaControlElementHelpText(const String&);
+ virtual String localizedMediaTimeDescription(float);
+ virtual String validationMessageValueMissingText();
+ virtual String validationMessageTypeMismatchText();
+ virtual String validationMessagePatternMismatchText();
+ virtual String validationMessageTooLongText();
+ virtual String validationMessageRangeUnderflowText();
+ virtual String validationMessageRangeOverflowText();
+ virtual String validationMessageStepMismatchText();
+};
+
+} // namespace WebCore
+
+#endif // USE(PLATFORM_STRATEGIES)
+
+#endif // DefaultLocalizationStrategy_h
diff --git a/Source/WebCore/platform/FileMetadata.h b/Source/WebCore/platform/FileMetadata.h
index 9b7d09b..99fe2f3 100644
--- a/Source/WebCore/platform/FileMetadata.h
+++ b/Source/WebCore/platform/FileMetadata.h
@@ -31,6 +31,8 @@
#ifndef FileMetadata_h
#define FileMetadata_h
+#include <wtf/text/WTFString.h>
+
#if ENABLE(FILE_SYSTEM)
namespace WebCore {
@@ -52,6 +54,8 @@ struct FileMetadata {
Type type;
+ String platformPath;
+
FileMetadata() : modificationTime(0.0), length(-1), type(TypeUnknown) { }
};
diff --git a/Source/WebCore/platform/FileSystem.cpp b/Source/WebCore/platform/FileSystem.cpp
index 0f69b7f..cc2e904 100644
--- a/Source/WebCore/platform/FileSystem.cpp
+++ b/Source/WebCore/platform/FileSystem.cpp
@@ -26,6 +26,8 @@
#include "config.h"
#include "FileSystem.h"
+#include <wtf/HexNumber.h>
+
namespace WebCore {
// The following lower-ASCII characters need escaping to be used in a filename
@@ -75,8 +77,6 @@ static inline bool shouldEscapeUChar(UChar c)
return c > 127 ? false : needsEscaping[c];
}
-static const char hexDigits[17] = "0123456789ABCDEF";
-
String encodeForFileName(const String& inputStr)
{
unsigned length = inputStr.length();
@@ -90,8 +90,7 @@ String encodeForFileName(const String& inputStr)
UChar c = *str++;
if (shouldEscapeUChar(c)) {
*p++ = '%';
- *p++ = hexDigits[(c >> 4) & 0xF];
- *p++ = hexDigits[c & 0xF];
+ placeByteAsHex(c, p);
} else
*p++ = c;
}
diff --git a/Source/WebCore/platform/FileSystem.h b/Source/WebCore/platform/FileSystem.h
index 8b7d0f0..49a78e8 100644
--- a/Source/WebCore/platform/FileSystem.h
+++ b/Source/WebCore/platform/FileSystem.h
@@ -172,7 +172,7 @@ CString fileSystemRepresentation(const String&);
inline bool isHandleValid(const PlatformFileHandle& handle) { return handle != invalidPlatformFileHandle; }
// Prefix is what the filename should be prefixed with, not the full path.
-CString openTemporaryFile(const char* prefix, PlatformFileHandle&);
+String openTemporaryFile(const String& prefix, PlatformFileHandle&);
PlatformFileHandle openFile(const String& path, FileOpenMode);
void closeFile(PlatformFileHandle&);
// Returns the resulting offset from the beginning of the file if successful, -1 otherwise.
diff --git a/Source/WebCore/platform/HostWindow.h b/Source/WebCore/platform/HostWindow.h
index 0d19356..316f043 100644
--- a/Source/WebCore/platform/HostWindow.h
+++ b/Source/WebCore/platform/HostWindow.h
@@ -52,7 +52,7 @@ public:
#if ENABLE(TILED_BACKING_STORE)
// Requests the host to do the actual scrolling. This is only used in combination with a tiled backing store.
- virtual void delegatedScrollRequested(const IntSize& scrollDelta) = 0;
+ virtual void delegatedScrollRequested(const IntPoint& scrollPoint) = 0;
#endif
// Methods for doing coordinate conversions to and from screen coordinates.
diff --git a/Source/WebCore/platform/KURL.cpp b/Source/WebCore/platform/KURL.cpp
index 0032f09..88ad3d9 100644
--- a/Source/WebCore/platform/KURL.cpp
+++ b/Source/WebCore/platform/KURL.cpp
@@ -30,6 +30,7 @@
#include "TextEncoding.h"
#include <wtf/text/CString.h>
#include <wtf/HashMap.h>
+#include <wtf/HexNumber.h>
#include <wtf/StdLibExtras.h>
#include <wtf/text/StringHash.h>
@@ -89,8 +90,6 @@ enum URLCharacterClasses {
BadChar = 1 << 6
};
-static const char hexDigits[17] = "0123456789ABCDEF";
-
static const unsigned char characterClassTable[256] = {
/* 0 nul */ PathSegmentEndChar, /* 1 soh */ BadChar,
/* 2 stx */ BadChar, /* 3 etx */ BadChar,
@@ -221,7 +220,6 @@ static const unsigned char characterClassTable[256] = {
static int copyPathRemovingDots(char* dst, const char* src, int srcStart, int srcEnd);
static void encodeRelativeString(const String& rel, const TextEncoding&, CharBuffer& ouput);
static String substituteBackslashes(const String&);
-static bool isValidProtocol(const String&);
static inline bool isSchemeFirstChar(char c) { return characterClassTable[static_cast<unsigned char>(c)] & SchemeFirstChar; }
static inline bool isSchemeFirstChar(UChar c) { return c <= 0xff && (characterClassTable[c] & SchemeFirstChar); }
@@ -861,7 +859,11 @@ void KURL::setPath(const String& s)
// FIXME: encodeWithURLEscapeSequences does not correctly escape '#' and '?', so fragment and query parts
// may be inadvertently affected.
- parse(m_string.left(m_portEnd) + encodeWithURLEscapeSequences(s) + m_string.substring(m_pathEnd));
+ String path = s;
+ if (path.isEmpty() || path[0] != '/')
+ path = "/" + path;
+
+ parse(m_string.left(m_portEnd) + encodeWithURLEscapeSequences(path) + m_string.substring(m_pathEnd));
}
String KURL::prettyURL() const
@@ -971,8 +973,7 @@ String decodeURLEscapeSequences(const String& str, const TextEncoding& encoding)
static void appendEscapedChar(char*& buffer, unsigned char c)
{
*buffer++ = '%';
- *buffer++ = hexDigits[c >> 4];
- *buffer++ = hexDigits[c & 0xF];
+ placeByteAsHex(c, buffer);
}
static void appendEscapingBadChars(char*& buffer, const char* strStart, size_t length)
@@ -1131,6 +1132,11 @@ static inline bool isDefaultPortForScheme(const char* port, size_t portLength, c
return false;
}
+static inline bool hostPortIsEmptyButCredentialsArePresent(int hostStart, int portEnd, char userEndChar)
+{
+ return userEndChar == '@' && hostStart == portEnd;
+}
+
void KURL::parse(const char* url, const String* originalString)
{
if (!url || url[0] == '\0') {
@@ -1256,6 +1262,12 @@ void KURL::parse(const char* url, const String* originalString)
return;
}
+ if (hostPortIsEmptyButCredentialsArePresent(hostStart, portEnd, url[userEnd])) {
+ // in this circumstance, act as if there is an erroneous hostname containing an '@'
+ userEnd = userStart;
+ hostStart = userEnd;
+ }
+
if (userStart == portEnd && !m_protocolInHTTPFamily && !isFile) {
// No authority found, which means that this is not a net_path, but rather an abs_path whose first two
// path segments are empty. For file, http and https only, an empty authority is allowed.
diff --git a/Source/WebCore/platform/KURL.h b/Source/WebCore/platform/KURL.h
index be72824..5764494 100644
--- a/Source/WebCore/platform/KURL.h
+++ b/Source/WebCore/platform/KURL.h
@@ -279,6 +279,8 @@ bool protocolIsJavaScript(const String& url);
bool isDefaultPortForProtocol(unsigned short port, const String& protocol);
bool portAllowed(const KURL&); // Blacklist ports that should never be used for Web resources.
+bool isValidProtocol(const String&);
+
String mimeTypeFromDataURL(const String& url);
// Unescapes the given string using URL escaping rules, given an optional
diff --git a/Source/WebCore/platform/KURLGoogle.cpp b/Source/WebCore/platform/KURLGoogle.cpp
index 231c43d..88120a8 100644
--- a/Source/WebCore/platform/KURLGoogle.cpp
+++ b/Source/WebCore/platform/KURLGoogle.cpp
@@ -133,6 +133,22 @@ static inline bool isSchemeChar(char c)
return isSchemeFirstChar(c) || (c >= '0' && c <= '9') || c == '.' || c == '-' || c == '*';
}
+bool isValidProtocol(const String& protocol)
+{
+ // NOTE This is a copy of the function in KURL.cpp.
+ // RFC3986: ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+ if (protocol.isEmpty())
+ return false;
+ if (!isSchemeFirstChar(protocol[0]))
+ return false;
+ unsigned protocolLength = protocol.length();
+ for (unsigned i = 1; i < protocolLength; i++) {
+ if (!isSchemeChar(protocol[i]))
+ return false;
+ }
+ return true;
+}
+
// KURLGooglePrivate -----------------------------------------------------------
diff --git a/Source/WebCore/platform/KillRingNone.cpp b/Source/WebCore/platform/KillRingNone.cpp
index 35098aa..310aa08 100644
--- a/Source/WebCore/platform/KillRingNone.cpp
+++ b/Source/WebCore/platform/KillRingNone.cpp
@@ -28,11 +28,11 @@
namespace WebCore {
-void KillRing::append(const String& string)
+void KillRing::append(const String&)
{
}
-void KillRing::prepend(const String& string)
+void KillRing::prepend(const String&)
{
}
diff --git a/Source/WebCore/platform/Length.h b/Source/WebCore/platform/Length.h
index 886dfec..2b11a5f 100644
--- a/Source/WebCore/platform/Length.h
+++ b/Source/WebCore/platform/Length.h
@@ -1,6 +1,7 @@
/*
Copyright (C) 1999 Lars Knoll (knoll@kde.org)
Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ Copyright (C) 2011 Rik Cabanier (cabanier@adobe.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -30,7 +31,6 @@
namespace WebCore {
const int undefinedLength = -1;
-const int percentScaleFactor = 128;
const int intMaxForLength = 0x7ffffff; // max value for a 28-bit int
const int intMinForLength = (-0x7ffffff - 1); // min value for a 28-bit int
@@ -40,72 +40,79 @@ struct Length {
WTF_MAKE_FAST_ALLOCATED;
public:
Length()
- : m_value(0)
+ : m_intValue(0), m_quirk(false), m_type(Auto), m_isFloat(false)
{
}
Length(LengthType t)
- : m_value(t)
+ : m_intValue(0), m_quirk(false), m_type(t), m_isFloat(false)
{
}
Length(int v, LengthType t, bool q = false)
- : m_value((v * 16) | (q << 3) | t) // FIXME: Doesn't work if the passed-in value is very large!
+ : m_intValue(v), m_quirk(q), m_type(t), m_isFloat(false)
{
- ASSERT(t != Percent);
+ }
+
+ Length(float v, LengthType t, bool q = false)
+ : m_floatValue(v), m_quirk(q), m_type(t), m_isFloat(true)
+ {
}
Length(double v, LengthType t, bool q = false)
- : m_value(static_cast<int>(v * percentScaleFactor) * 16 | (q << 3) | t)
- {
- ASSERT(t == Percent);
+ : m_quirk(q), m_type(t), m_isFloat(true)
+ {
+ m_floatValue = static_cast<float>(v);
}
- bool operator==(const Length& o) const { return m_value == o.m_value; }
- bool operator!=(const Length& o) const { return m_value != o.m_value; }
+ bool operator==(const Length& o) const { return (getFloatValue() == o.getFloatValue()) && (m_type == o.m_type) && (m_quirk == o.m_quirk); }
+ bool operator!=(const Length& o) const { return (getFloatValue() != o.getFloatValue()) || (m_type != o.m_type) || (m_quirk != o.m_quirk); }
+ const Length& operator*=(float v)
+ {
+ if (m_isFloat)
+ m_floatValue = static_cast<float>(m_floatValue * v);
+ else
+ m_intValue = static_cast<int>(m_intValue * v);
+
+ return *this;
+ }
+
int value() const {
- ASSERT(type() != Percent);
- return rawValue();
+ return getIntValue();
}
- int rawValue() const { return (m_value & ~0xF) / 16; }
-
- double percent() const
+ float percent() const
{
ASSERT(type() == Percent);
- return static_cast<double>(rawValue()) / percentScaleFactor;
+ return getFloatValue();
}
- LengthType type() const { return static_cast<LengthType>(m_value & 7); }
- bool quirk() const { return (m_value >> 3) & 1; }
+ LengthType type() const { return static_cast<LengthType>(m_type); }
+ bool quirk() const { return m_quirk; }
void setValue(LengthType t, int value)
{
- ASSERT(t != Percent);
- setRawValue(t, value);
+ m_type = t;
+ m_intValue = value;
+ m_isFloat = false;
}
- void setRawValue(LengthType t, int value) { m_value = value * 16 | (m_value & 0x8) | t; }
-
void setValue(int value)
{
- ASSERT(!value || type() != Percent);
- setRawValue(value);
+ setValue(Fixed, value);
}
- void setRawValue(int value) { m_value = value * 16 | (m_value & 0xF); }
-
- void setValue(LengthType t, double value)
+ void setValue(LengthType t, float value)
{
- ASSERT(t == Percent);
- m_value = static_cast<int>(value * percentScaleFactor) * 16 | (m_value & 0x8) | t;
+ m_type = t;
+ m_floatValue = value;
+ m_isFloat = true;
}
- void setValue(double value)
+ void setValue(float value)
{
- ASSERT(type() == Percent);
- m_value = static_cast<int>(value * percentScaleFactor) * 16 | (m_value & 0xF);
+ *this = Length(value, Fixed);
}
// note: works only for certain types, returns undefinedLength otherwise
@@ -113,11 +120,8 @@ public:
{
switch (type()) {
case Fixed:
- return value();
case Percent:
- if (roundPercentages)
- return static_cast<int>(round(maxValue * percent() / 100.0));
- return maxValue * rawValue() / (100 * percentScaleFactor);
+ return calcMinValue(maxValue, roundPercentages);
case Auto:
return maxValue;
default:
@@ -132,8 +136,9 @@ public:
return value();
case Percent:
if (roundPercentages)
- return static_cast<int>(round(maxValue * percent() / 100.0));
- return maxValue * rawValue() / (100 * percentScaleFactor);
+ return static_cast<int>(round(maxValue * percent() / 100.0f));
+ // Don't remove the extra cast to float. It is needed for rounding on 32-bit Intel machines that use the FPU stack.
+ return static_cast<int>(static_cast<float>(maxValue * percent() / 100.0f));
case Auto:
default:
return 0;
@@ -144,9 +149,9 @@ public:
{
switch (type()) {
case Fixed:
- return static_cast<float>(value());
+ return getFloatValue();
case Percent:
- return static_cast<float>(maxValue * percent() / 100.0);
+ return static_cast<float>(maxValue * percent() / 100.0f);
case Auto:
return static_cast<float>(maxValue);
default:
@@ -154,10 +159,14 @@ public:
}
}
- bool isUndefined() const { return rawValue() == undefinedLength; }
- bool isZero() const { return !(m_value & ~0xF); }
- bool isPositive() const { return rawValue() > 0; }
- bool isNegative() const { return rawValue() < 0; }
+ bool isUndefined() const { return value() == undefinedLength; }
+ bool isZero() const
+ {
+ return m_isFloat ? !m_floatValue : !m_intValue;
+ }
+
+ bool isPositive() const { return getFloatValue() > 0; }
+ bool isNegative() const { return getFloatValue() < 0; }
bool isAuto() const { return type() == Auto; }
bool isRelative() const { return type() == Relative; }
@@ -165,7 +174,7 @@ public:
bool isFixed() const { return type() == Fixed; }
bool isIntrinsicOrAuto() const { return type() == Auto || type() == MinIntrinsic || type() == Intrinsic; }
- Length blend(const Length& from, double progress) const
+ Length blend(const Length& from, float progress) const
{
// Blend two lengths to produce a new length that is in between them. Used for animation.
if (!from.isZero() && !isZero() && from.type() != type())
@@ -179,18 +188,34 @@ public:
resultType = from.type();
if (resultType == Percent) {
- double fromPercent = from.isZero() ? 0. : from.percent();
- double toPercent = isZero() ? 0. : percent();
+ float fromPercent = from.isZero() ? 0 : from.percent();
+ float toPercent = isZero() ? 0 : percent();
return Length(fromPercent + (toPercent - fromPercent) * progress, Percent);
}
- int fromValue = from.isZero() ? 0 : from.value();
- int toValue = isZero() ? 0 : value();
- return Length(int(fromValue + (toValue - fromValue) * progress), resultType);
+ float fromValue = from.isZero() ? 0 : from.value();
+ float toValue = isZero() ? 0 : value();
+ return Length(fromValue + (toValue - fromValue) * progress, resultType);
}
private:
- int m_value;
+ int getIntValue() const
+ {
+ return m_isFloat ? static_cast<int>(m_floatValue) : m_intValue;
+ }
+
+ float getFloatValue() const
+ {
+ return m_isFloat ? m_floatValue : m_intValue;
+ }
+
+ union {
+ int m_intValue;
+ float m_floatValue;
+ };
+ bool m_quirk;
+ unsigned char m_type;
+ bool m_isFloat;
};
PassOwnArrayPtr<Length> newCoordsArray(const String&, int& len);
diff --git a/Source/WebCore/platform/LinkHash.cpp b/Source/WebCore/platform/LinkHash.cpp
index a2acad1..29671a0 100644
--- a/Source/WebCore/platform/LinkHash.cpp
+++ b/Source/WebCore/platform/LinkHash.cpp
@@ -197,7 +197,7 @@ static inline bool needsTrailingSlash(const UChar* characters, unsigned length)
static ALWAYS_INLINE LinkHash visitedLinkHashInline(const UChar* url, unsigned length)
{
- return AlreadyHashed::avoidDeletedValue(WTF::StringHasher::createHash(url, length));
+ return AlreadyHashed::avoidDeletedValue(StringHasher::computeHash(url, length));
}
LinkHash visitedLinkHash(const UChar* url, unsigned length)
diff --git a/Source/WebCore/platform/LocalizationStrategy.h b/Source/WebCore/platform/LocalizationStrategy.h
index eba0e7c..f883893 100644
--- a/Source/WebCore/platform/LocalizationStrategy.h
+++ b/Source/WebCore/platform/LocalizationStrategy.h
@@ -79,7 +79,7 @@ public:
virtual String contextMenuItemTagIgnoreSpelling() = 0;
virtual String contextMenuItemTagLearnSpelling() = 0;
virtual String contextMenuItemTagSearchWeb() = 0;
- virtual String contextMenuItemTagLookUpInDictionary() = 0;
+ virtual String contextMenuItemTagLookUpInDictionary(const String& selectedString) = 0;
virtual String contextMenuItemTagOpenLink() = 0;
virtual String contextMenuItemTagIgnoreGrammar() = 0;
virtual String contextMenuItemTagSpellingMenu() = 0;
@@ -167,6 +167,13 @@ public:
virtual String allFilesText() = 0;
#endif
+#if PLATFORM(MAC)
+ virtual String keygenMenuItem512() = 0;
+ virtual String keygenMenuItem1024() = 0;
+ virtual String keygenMenuItem2048() = 0;
+ virtual String keygenKeychainItemName(const String& host) = 0;
+#endif
+
virtual String imageTitle(const String& filename, const IntSize& size) = 0;
virtual String mediaElementLoadingStateText() = 0;
diff --git a/Source/WebCore/platform/LocalizedStrings.cpp b/Source/WebCore/platform/LocalizedStrings.cpp
index 9656dbe..f5ad0b7 100644
--- a/Source/WebCore/platform/LocalizedStrings.cpp
+++ b/Source/WebCore/platform/LocalizedStrings.cpp
@@ -190,9 +190,9 @@ String contextMenuItemTagSearchWeb()
return platformStrategies()->localizationStrategy()->contextMenuItemTagSearchWeb();
}
-String contextMenuItemTagLookUpInDictionary()
+String contextMenuItemTagLookUpInDictionary(const String& selectedString)
{
- return platformStrategies()->localizationStrategy()->contextMenuItemTagLookUpInDictionary();
+ return platformStrategies()->localizationStrategy()->contextMenuItemTagLookUpInDictionary(selectedString);
}
String contextMenuItemTagOpenLink()
@@ -569,6 +569,29 @@ String allFilesText()
}
#endif
+#if PLATFORM(MAC)
+String keygenMenuItem512()
+{
+ return platformStrategies()->localizationStrategy()->keygenMenuItem512();
+}
+
+String keygenMenuItem1024()
+{
+ return platformStrategies()->localizationStrategy()->keygenMenuItem1024();
+}
+
+String keygenMenuItem2048()
+{
+ return platformStrategies()->localizationStrategy()->keygenMenuItem2048();
+}
+
+String keygenKeychainItemName(const String& host)
+{
+ return platformStrategies()->localizationStrategy()->keygenKeychainItemName(host);
+}
+
+#endif
+
String imageTitle(const String& filename, const IntSize& size)
{
return platformStrategies()->localizationStrategy()->imageTitle(filename, size);
@@ -676,4 +699,11 @@ String validationMessageStepMismatchText(const String&, const String&)
#endif // USE(PLATFORM_STRATEGIES)
+#if !PLATFORM(MAC) && !PLATFORM(WIN)
+String localizedString(const char* key)
+{
+ return String::fromUTF8(key, strlen(key));
+}
+#endif
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/LocalizedStrings.h b/Source/WebCore/platform/LocalizedStrings.h
index f22c975..3885439 100644
--- a/Source/WebCore/platform/LocalizedStrings.h
+++ b/Source/WebCore/platform/LocalizedStrings.h
@@ -75,7 +75,7 @@ namespace WebCore {
String contextMenuItemTagIgnoreSpelling();
String contextMenuItemTagLearnSpelling();
String contextMenuItemTagSearchWeb();
- String contextMenuItemTagLookUpInDictionary();
+ String contextMenuItemTagLookUpInDictionary(const String& selectedString);
String contextMenuItemTagOpenLink();
String contextMenuItemTagIgnoreGrammar();
String contextMenuItemTagSpellingMenu();
@@ -163,6 +163,13 @@ namespace WebCore {
String allFilesText();
#endif
+#if PLATFORM(MAC)
+ String keygenMenuItem512();
+ String keygenMenuItem1024();
+ String keygenMenuItem2048();
+ String keygenKeychainItemName(const String& host);
+#endif
+
String imageTitle(const String& filename, const IntSize& size);
String mediaElementLoadingStateText();
@@ -187,9 +194,11 @@ namespace WebCore {
String validationMessageRangeOverflowText(const String& maximum);
String validationMessageStepMismatchText(const String& base, const String& step);
-#if PLATFORM(MAC)
+
+#define UI_STRING(string, description) WebCore::localizedString(string)
+#define UI_STRING_KEY(string, key, description) WebCore::localizedString(key)
+
String localizedString(const char* key);
-#endif
} // namespace WebCore
diff --git a/Source/WebCore/platform/MIMETypeRegistry.cpp b/Source/WebCore/platform/MIMETypeRegistry.cpp
index e76906e..d0ad985 100644
--- a/Source/WebCore/platform/MIMETypeRegistry.cpp
+++ b/Source/WebCore/platform/MIMETypeRegistry.cpp
@@ -55,6 +55,7 @@ static HashSet<String>* supportedImageMIMETypesForEncoding;
static HashSet<String>* supportedJavaScriptMIMETypes;
static HashSet<String>* supportedNonImageMIMETypes;
static HashSet<String>* supportedMediaMIMETypes;
+static HashSet<String>* unsupportedTextMIMETypes;
typedef HashMap<String, Vector<String>*, CaseFoldingHash> MediaMIMETypeMap;
@@ -419,6 +420,27 @@ static void initializeSupportedMediaMIMETypes()
#endif
}
+static void initializeUnsupportedTextMIMETypes()
+{
+ static const char* types[] = {
+ "text/calendar",
+ "text/x-calendar",
+ "text/x-vcalendar",
+ "text/vcalendar",
+ "text/vcard",
+ "text/x-vcard",
+ "text/directory",
+ "text/ldif",
+ "text/qif",
+ "text/x-qif",
+ "text/x-csv",
+ "text/x-vcf",
+ "text/rtf",
+ };
+ for (size_t i = 0; i < WTF_ARRAY_LENGTH(types); ++i)
+ unsupportedTextMIMETypes->add(types[i]);
+}
+
static void initializeMIMETypeRegistry()
{
supportedJavaScriptMIMETypes = new HashSet<String>;
@@ -430,6 +452,9 @@ static void initializeMIMETypeRegistry()
supportedImageResourceMIMETypes = new HashSet<String>;
supportedImageMIMETypes = new HashSet<String>;
initializeSupportedImageMIMETypes();
+
+ unsupportedTextMIMETypes = new HashSet<String>;
+ initializeUnsupportedTextMIMETypes();
}
String MIMETypeRegistry::getMIMETypeForPath(const String& path)
@@ -500,6 +525,15 @@ bool MIMETypeRegistry::isSupportedMediaMIMEType(const String& mimeType)
return supportedMediaMIMETypes->contains(mimeType);
}
+bool MIMETypeRegistry::isUnsupportedTextMIMEType(const String& mimeType)
+{
+ if (mimeType.isEmpty())
+ return false;
+ if (!unsupportedTextMIMETypes)
+ initializeMIMETypeRegistry();
+ return unsupportedTextMIMETypes->contains(mimeType);
+}
+
bool MIMETypeRegistry::isJavaAppletMIMEType(const String& mimeType)
{
// Since this set is very limited and is likely to remain so we won't bother with the overhead
@@ -546,6 +580,13 @@ HashSet<String>& MIMETypeRegistry::getSupportedMediaMIMETypes()
return *supportedMediaMIMETypes;
}
+HashSet<String>& MIMETypeRegistry::getUnsupportedTextMIMETypes()
+{
+ if (!unsupportedTextMIMETypes)
+ initializeMIMETypeRegistry();
+ return *unsupportedTextMIMETypes;
+}
+
const String& defaultMIMEType()
{
DEFINE_STATIC_LOCAL(const String, defaultMIMEType, ("application/octet-stream"));
diff --git a/Source/WebCore/platform/MIMETypeRegistry.h b/Source/WebCore/platform/MIMETypeRegistry.h
index d069035..19d1b4b 100644
--- a/Source/WebCore/platform/MIMETypeRegistry.h
+++ b/Source/WebCore/platform/MIMETypeRegistry.h
@@ -68,6 +68,10 @@ public:
// Check to see if a mime type is suitable for being loaded using <video> and <audio>
static bool isSupportedMediaMIMEType(const String& mimeType);
+ // Check to see if the mime type is not suitable for being loaded as a text
+ // document in a frame. Only valid for mime types begining with "text/".
+ static bool isUnsupportedTextMIMEType(const String& mimeType);
+
// Check to see if a mime type is a valid Java applet mime type
static bool isJavaAppletMIMEType(const String& mimeType);
@@ -80,6 +84,7 @@ public:
static HashSet<String>& getSupportedImageMIMETypesForEncoding();
static HashSet<String>& getSupportedNonImageMIMETypes();
static HashSet<String>& getSupportedMediaMIMETypes();
+ static HashSet<String>& getUnsupportedTextMIMETypes();
};
const String& defaultMIMEType();
diff --git a/Source/WebCore/platform/PlatformGestureRecognizer.cpp b/Source/WebCore/platform/PlatformGestureRecognizer.cpp
new file mode 100644
index 0000000..38fc3fe
--- /dev/null
+++ b/Source/WebCore/platform/PlatformGestureRecognizer.cpp
@@ -0,0 +1,46 @@
+/*
+ * 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 "PlatformGestureRecognizer.h"
+
+namespace WebCore {
+
+PlatformGestureRecognizer::PlatformGestureRecognizer() { }
+PlatformGestureRecognizer::~PlatformGestureRecognizer() { }
+
+// To get a useful GestureRecognizer, a specific platform should return something
+// here that meets its needs. EventHandler will ignore null GestureRecognizers.
+PlatformGestureRecognizer* PlatformGestureRecognizer::create()
+{
+ return 0;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/PlatformGestureRecognizer.h b/Source/WebCore/platform/PlatformGestureRecognizer.h
new file mode 100644
index 0000000..f6e85a5
--- /dev/null
+++ b/Source/WebCore/platform/PlatformGestureRecognizer.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PlatformGestureRecognizer_h
+#define PlatformGestureRecognizer_h
+
+namespace WebCore {
+
+class EventHandler;
+class PlatformGestureRecognizer;
+class PlatformTouchEvent;
+
+// A GestureRecognizer detects gestures occurring in the touch event.
+// In response to a given touch event, the GestureRecognizer, updates
+// its internal state and optionally dispatches synthetic events to the
+// invoking EventHandler instance.
+class PlatformGestureRecognizer {
+protected:
+ PlatformGestureRecognizer();
+
+public:
+ virtual ~PlatformGestureRecognizer();
+
+ // Invoked for each touch event that could contribute to the current gesture.
+ // Takes a PlatformTouchEvent and the EventHandler that originated it and which will also
+ // be the target of any generated synthetic event. Finally, |handled|
+ // specifies if the |event| was actually handled by |source| (by the JavaScript)
+ // Returns true if the event resulted in firing a synthetic event.
+ virtual bool processTouchEventForGesture(const PlatformTouchEvent&, EventHandler*, bool handled) = 0;
+
+ // Factory method for GestureManagers.
+ static PlatformGestureRecognizer* create();
+};
+
+} // namespace WebCore
+
+#endif // PlatformGestureRecognizer_h
diff --git a/Source/WebCore/platform/PlatformKeyboardEvent.h b/Source/WebCore/platform/PlatformKeyboardEvent.h
index fcca8bd..a3127c7 100644
--- a/Source/WebCore/platform/PlatformKeyboardEvent.h
+++ b/Source/WebCore/platform/PlatformKeyboardEvent.h
@@ -96,7 +96,7 @@ namespace WebCore {
AltKey = 1 << 0,
CtrlKey = 1 << 1,
MetaKey = 1 << 2,
- ShiftKey = 1 << 3,
+ ShiftKey = 1 << 3
};
PlatformKeyboardEvent()
diff --git a/Source/WebCore/platform/PlatformStrategies.cpp b/Source/WebCore/platform/PlatformStrategies.cpp
index e0baa70..9623108 100644
--- a/Source/WebCore/platform/PlatformStrategies.cpp
+++ b/Source/WebCore/platform/PlatformStrategies.cpp
@@ -29,6 +29,8 @@
#include "PlatformStrategies.h"
+#include "DefaultLocalizationStrategy.h"
+
namespace WebCore {
static PlatformStrategies* s_platformStrategies;
@@ -51,7 +53,12 @@ void setPlatformStrategies(PlatformStrategies* platformStrategies)
// throw an exception here in release builds.
ASSERT(platformStrategies != s_platformStrategies);
}
-
+
+LocalizationStrategy* PlatformStrategies::createLocalizationStrategy()
+{
+ return new DefaultLocalizationStrategy;
+}
+
} // namespace WebCore
#endif // USE(PLATFORM_STRATEGIES)
diff --git a/Source/WebCore/platform/PlatformStrategies.h b/Source/WebCore/platform/PlatformStrategies.h
index bda7c90..6768658 100644
--- a/Source/WebCore/platform/PlatformStrategies.h
+++ b/Source/WebCore/platform/PlatformStrategies.h
@@ -81,7 +81,7 @@ protected:
private:
virtual CookiesStrategy* createCookiesStrategy() = 0;
virtual PluginStrategy* createPluginStrategy() = 0;
- virtual LocalizationStrategy* createLocalizationStrategy() = 0;
+ virtual LocalizationStrategy* createLocalizationStrategy();
virtual VisitedLinkStrategy* createVisitedLinkStrategy() = 0;
CookiesStrategy* m_cookiesStrategy;
diff --git a/Source/WebCore/platform/ScrollAnimator.h b/Source/WebCore/platform/ScrollAnimator.h
index 060511c..6698b63 100644
--- a/Source/WebCore/platform/ScrollAnimator.h
+++ b/Source/WebCore/platform/ScrollAnimator.h
@@ -68,6 +68,8 @@ public:
FloatPoint currentPosition() const;
+ virtual void cancelAnimations() { }
+
virtual void contentAreaWillPaint() const { }
virtual void mouseEnteredContentArea() const { }
virtual void mouseExitedContentArea() const { }
diff --git a/Source/WebCore/platform/ScrollTypes.h b/Source/WebCore/platform/ScrollTypes.h
index f07fb1a..1f8e095 100644
--- a/Source/WebCore/platform/ScrollTypes.h
+++ b/Source/WebCore/platform/ScrollTypes.h
@@ -119,7 +119,7 @@ namespace WebCore {
enum ScrollbarControlStateMask {
ActiveScrollbarState = 1,
EnabledScrollbarState = 1 << 1,
- PressedScrollbarState = 1 << 2,
+ PressedScrollbarState = 1 << 2
};
enum ScrollbarPart {
@@ -133,7 +133,7 @@ namespace WebCore {
ForwardButtonEndPart = 1 << 6,
ScrollbarBGPart = 1 << 7,
TrackBGPart = 1 << 8,
- AllParts = 0xffffffff,
+ AllParts = 0xffffffff
};
enum ScrollbarButtonsPlacement {
diff --git a/Source/WebCore/platform/ScrollView.cpp b/Source/WebCore/platform/ScrollView.cpp
index baf2e32..58615fb 100644
--- a/Source/WebCore/platform/ScrollView.cpp
+++ b/Source/WebCore/platform/ScrollView.cpp
@@ -124,7 +124,7 @@ void ScrollView::setHasVerticalScrollbar(bool hasBar)
axObjectCache()->handleScrollbarUpdate(this);
}
-#if !PLATFORM(GTK)
+#if !USE(NATIVE_GTK_MAIN_FRAME_SCROLLBAR)
PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientation)
{
return Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
@@ -224,7 +224,7 @@ void ScrollView::setDelegatesScrolling(bool delegatesScrolling)
m_delegatesScrolling = delegatesScrolling;
}
-#if !PLATFORM(GTK)
+#if !USE(NATIVE_GTK_MAIN_FRAME_SCROLLBAR)
IntRect ScrollView::visibleContentRect(bool includeScrollbars) const
{
if (platformWidget())
@@ -357,6 +357,10 @@ void ScrollView::didCompleteRubberBand(const IntSize&) const
{
}
+void ScrollView::notifyPageThatContentAreaWillPaint() const
+{
+}
+
void ScrollView::setScrollOffset(const IntPoint& offset)
{
int horizontalOffset = offset.x();
@@ -408,7 +412,7 @@ void ScrollView::setScrollPosition(const IntPoint& scrollPoint)
#if ENABLE(TILED_BACKING_STORE)
if (delegatesScrolling()) {
- hostWindow()->delegatedScrollRequested(IntSize(scrollPoint.x(), scrollPoint.y()));
+ hostWindow()->delegatedScrollRequested(scrollPoint);
if (!m_actualVisibleContentRect.isEmpty())
m_actualVisibleContentRect.setLocation(scrollPoint);
return;
@@ -439,15 +443,18 @@ bool ScrollView::logicalScroll(ScrollLogicalDirection direction, ScrollGranulari
IntSize ScrollView::overhangAmount() const
{
IntSize stretch;
- if (scrollY() < 0)
- stretch.setHeight(scrollY());
- else if (scrollY() > contentsHeight() - visibleContentRect().height())
- stretch.setHeight(scrollY() - (contentsHeight() - visibleContentRect().height()));
- if (scrollX() < 0)
- stretch.setWidth(scrollX());
- else if (scrollX() > contentsWidth() - visibleContentRect().width())
- stretch.setWidth(scrollX() - (contentsWidth() - visibleContentRect().width()));
+ int physicalScrollY = scrollPosition().y() + m_scrollOrigin.y();
+ if (physicalScrollY < 0)
+ stretch.setHeight(physicalScrollY);
+ else if (physicalScrollY > contentsHeight() - visibleContentRect().height())
+ stretch.setHeight(physicalScrollY - (contentsHeight() - visibleContentRect().height()));
+
+ int physicalScrollX = scrollPosition().x() + m_scrollOrigin.x();
+ if (physicalScrollX < 0)
+ stretch.setWidth(physicalScrollX);
+ else if (physicalScrollX > contentsWidth() - visibleContentRect().width())
+ stretch.setWidth(physicalScrollX - (contentsWidth() - visibleContentRect().width()));
return stretch;
}
@@ -947,7 +954,7 @@ void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
if (context->paintingDisabled() && !context->updatingControlTints())
return;
- scrollAnimator()->contentAreaWillPaint();
+ notifyPageThatContentAreaWillPaint();
IntRect documentDirtyRect = rect;
documentDirtyRect.intersect(frameRect());
@@ -1000,26 +1007,28 @@ void ScrollView::calculateOverhangAreasForPainting(IntRect& horizontalOverhangRe
int horizontalScrollbarHeight = (horizontalScrollbar() && !horizontalScrollbar()->isOverlayScrollbar())
? horizontalScrollbar()->height() : 0;
- if (scrollY() < 0) {
+ int physicalScrollY = scrollPosition().y() + m_scrollOrigin.y();
+ if (physicalScrollY < 0) {
horizontalOverhangRect = frameRect();
- horizontalOverhangRect.setHeight(-scrollY());
- } else if (scrollY() > contentsHeight() - visibleContentRect().height()) {
- int height = scrollY() - (contentsHeight() - visibleContentRect().height());
+ horizontalOverhangRect.setHeight(-physicalScrollY);
+ } else if (physicalScrollY > contentsHeight() - visibleContentRect().height()) {
+ int height = physicalScrollY - (contentsHeight() - visibleContentRect().height());
horizontalOverhangRect = frameRect();
horizontalOverhangRect.setY(frameRect().maxY() - height - horizontalScrollbarHeight);
horizontalOverhangRect.setHeight(height);
}
- if (scrollX() < 0) {
- verticalOverhangRect.setWidth(-scrollX());
+ int physicalScrollX = scrollPosition().x() + m_scrollOrigin.x();
+ if (physicalScrollX < 0) {
+ verticalOverhangRect.setWidth(-physicalScrollX);
verticalOverhangRect.setHeight(frameRect().height() - horizontalOverhangRect.height());
verticalOverhangRect.setX(frameRect().x());
if (horizontalOverhangRect.y() == frameRect().y())
verticalOverhangRect.setY(frameRect().y() + horizontalOverhangRect.height());
else
verticalOverhangRect.setY(frameRect().y());
- } else if (scrollX() > contentsWidth() - visibleContentRect().width()) {
- int width = scrollX() - (contentsWidth() - visibleContentRect().width());
+ } else if (physicalScrollX > contentsWidth() - visibleContentRect().width()) {
+ int width = physicalScrollX - (contentsWidth() - visibleContentRect().width());
verticalOverhangRect.setWidth(width);
verticalOverhangRect.setHeight(frameRect().height() - horizontalOverhangRect.height());
verticalOverhangRect.setX(frameRect().maxX() - width - verticalScrollbarWidth);
@@ -1195,7 +1204,7 @@ void ScrollView::setScrollOrigin(const IntPoint& origin, bool updatePositionAtAl
updateScrollbars(scrollOffset());
}
-#if !PLATFORM(WX) && !PLATFORM(GTK) && !PLATFORM(EFL)
+#if !PLATFORM(WX) && !USE(NATIVE_GTK_MAIN_FRAME_SCROLLBAR) && !PLATFORM(EFL)
void ScrollView::platformInit()
{
diff --git a/Source/WebCore/platform/ScrollView.h b/Source/WebCore/platform/ScrollView.h
index 1d6fba5..bff77d5 100644
--- a/Source/WebCore/platform/ScrollView.h
+++ b/Source/WebCore/platform/ScrollView.h
@@ -62,6 +62,7 @@ public:
virtual int scrollPosition(Scrollbar*) const;
virtual void setScrollOffset(const IntPoint&);
virtual void didCompleteRubberBand(const IntSize&) const;
+ virtual void notifyPageThatContentAreaWillPaint() const;
// NOTE: This should only be called by the overriden setScrollOffset from ScrollableArea.
virtual void scrollTo(const IntSize& newOffset);
@@ -354,19 +355,6 @@ private:
bool m_clipsRepaints;
bool m_delegatesScrolling;
- // There are 8 possible combinations of writing mode and direction. Scroll origin will be non-zero in the x or y axis
- // if there is any reversed direction or writing-mode. The combinations are:
- // writing-mode / direction scrollOrigin.x() set scrollOrigin.y() set
- // horizontal-tb / ltr NO NO
- // horizontal-tb / rtl YES NO
- // horizontal-bt / ltr NO YES
- // horizontal-bt / rtl YES YES
- // vertical-lr / ltr NO NO
- // vertical-lr / rtl NO YES
- // vertical-rl / ltr YES NO
- // vertical-rl / rtl YES YES
- IntPoint m_scrollOrigin;
-
IntSize m_boundsSize;
void init();
diff --git a/Source/WebCore/platform/ScrollableArea.h b/Source/WebCore/platform/ScrollableArea.h
index f1c1308..d08de00 100644
--- a/Source/WebCore/platform/ScrollableArea.h
+++ b/Source/WebCore/platform/ScrollableArea.h
@@ -69,6 +69,7 @@ public:
bool hasOverlayScrollbars() const;
ScrollAnimator* scrollAnimator() const { return m_scrollAnimator.get(); }
+ const IntPoint& scrollOrigin() const { return m_scrollOrigin; }
virtual int scrollSize(ScrollbarOrientation) const = 0;
virtual int scrollPosition(Scrollbar*) const = 0;
@@ -114,6 +115,10 @@ public:
virtual IntSize overhangAmount() const { ASSERT_NOT_REACHED(); return IntSize(); }
virtual IntPoint currentMousePosition() const { return IntPoint(); }
virtual void didCompleteRubberBand(const IntSize&) const { ASSERT_NOT_REACHED(); }
+ virtual bool shouldSuspendScrollAnimations() const { return true; }
+ virtual void scrollbarStyleChanged() { }
+
+ virtual void disconnectFromPage() { }
private:
// NOTE: Only called from the ScrollAnimator.
@@ -124,6 +129,20 @@ private:
bool m_constrainsScrollingToContentEdge;
bool m_inLiveResize;
+
+protected:
+ // There are 8 possible combinations of writing mode and direction. Scroll origin will be non-zero in the x or y axis
+ // if there is any reversed direction or writing-mode. The combinations are:
+ // writing-mode / direction scrollOrigin.x() set scrollOrigin.y() set
+ // horizontal-tb / ltr NO NO
+ // horizontal-tb / rtl YES NO
+ // horizontal-bt / ltr NO YES
+ // horizontal-bt / rtl YES YES
+ // vertical-lr / ltr NO NO
+ // vertical-lr / rtl NO YES
+ // vertical-rl / ltr YES NO
+ // vertical-rl / rtl YES YES
+ IntPoint m_scrollOrigin;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/SharedBuffer.cpp b/Source/WebCore/platform/SharedBuffer.cpp
index 34553ec..0900ae4 100644
--- a/Source/WebCore/platform/SharedBuffer.cpp
+++ b/Source/WebCore/platform/SharedBuffer.cpp
@@ -167,6 +167,9 @@ void SharedBuffer::clear()
m_buffer.clear();
m_purgeableBuffer.clear();
+#if HAVE(CFNETWORK_DATA_ARRAY_CALLBACK)
+ m_dataArray.clear();
+#endif
}
PassRefPtr<SharedBuffer> SharedBuffer::copy() const
@@ -206,6 +209,9 @@ const Vector<char>& SharedBuffer::buffer() const
freeSegment(m_segments[i]);
}
m_segments.clear();
+#if HAVE(CFNETWORK_DATA_ARRAY_CALLBACK)
+ copyDataArrayAndClear(destination, bytesLeft);
+#endif
}
return m_buffer;
}
diff --git a/Source/WebCore/platform/SharedBuffer.h b/Source/WebCore/platform/SharedBuffer.h
index dfde5a1..f7318e3 100644
--- a/Source/WebCore/platform/SharedBuffer.h
+++ b/Source/WebCore/platform/SharedBuffer.h
@@ -97,6 +97,10 @@ public:
const char* platformData() const;
unsigned platformDataSize() const;
+#if HAVE(CFNETWORK_DATA_ARRAY_CALLBACK)
+ void append(CFDataRef);
+#endif
+
PassRefPtr<SharedBuffer> copy() const;
bool hasPurgeableBuffer() const { return m_purgeableBuffer.get(); }
@@ -138,6 +142,10 @@ private:
mutable Vector<char> m_buffer;
mutable Vector<char*> m_segments;
OwnPtr<PurgeableBuffer> m_purgeableBuffer;
+#if HAVE(CFNETWORK_DATA_ARRAY_CALLBACK)
+ mutable Vector<RetainPtr<CFDataRef> > m_dataArray;
+ void copyDataArrayAndClear(char *destination, unsigned bytesToCopy) const;
+#endif
#if USE(CF)
SharedBuffer(CFDataRef);
RetainPtr<CFDataRef> m_cfData;
diff --git a/Source/WebCore/platform/UUID.cpp b/Source/WebCore/platform/UUID.cpp
index 7f59081..fce0645 100644
--- a/Source/WebCore/platform/UUID.cpp
+++ b/Source/WebCore/platform/UUID.cpp
@@ -44,6 +44,7 @@
#elif OS(LINUX) && !PLATFORM(CHROMIUM)
#include <stdio.h>
#elif (OS(LINUX) && PLATFORM(CHROMIUM)) || (OS(DARWIN) && !USE(CF))
+#include <wtf/HexNumber.h>
#include <wtf/RandomNumber.h>
#include <wtf/text/StringBuilder.h>
#endif
@@ -100,17 +101,18 @@ String createCanonicalUUIDString()
// Format as Version 4 UUID.
StringBuilder builder;
- builder.append(String::format("%08x", randomData[0]));
+ appendUnsignedAsHexFixedSize(randomData[0], builder, 8, Lowercase);
builder.append("-");
- builder.append(String::format("%04x", randomData[1] >> 16));
+ appendUnsignedAsHexFixedSize(randomData[1] >> 16, builder, 4, Lowercase);
builder.append("-4");
- builder.append(String::format("%03x", randomData[1] & 0x00000fff));
+ appendUnsignedAsHexFixedSize(randomData[1] & 0x00000fff, builder, 3, Lowercase);
builder.append("-");
- builder.append(String::format("%x", (randomData[2] >> 30) | 0x8)); // Condense this byte to 8, 9, a, and b.
- builder.append(String::format("%03x", (randomData[2] >> 16) & 0x00000fff));
+ appendUnsignedAsHexFixedSize((randomData[2] >> 30) | 0x8, builder, 1, Lowercase);
+ appendUnsignedAsHexFixedSize((randomData[2] >> 16) & 0x00000fff, builder, 3, Lowercase);
builder.append("-");
- builder.append(String::format("%04x", randomData[2] & 0x0000ffff));
- builder.append(String::format("%08x", randomData[3]));
+ appendUnsignedAsHexFixedSize(randomData[2] & 0x0000ffff, builder, 4, Lowercase);
+ appendUnsignedAsHexFixedSize(randomData[3], builder, 8, Lowercase);
+ builder.append("\n");
return builder.toString();
#else
notImplemented();
diff --git a/Source/WebCore/platform/android/FileSystemAndroid.cpp b/Source/WebCore/platform/android/FileSystemAndroid.cpp
index 9ed43f0..30dc1d3 100644
--- a/Source/WebCore/platform/android/FileSystemAndroid.cpp
+++ b/Source/WebCore/platform/android/FileSystemAndroid.cpp
@@ -55,26 +55,25 @@ CString fileSystemRepresentation(const String& path)
return path.utf8();
}
-CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
+String openTemporaryFile(const String& prefix, PlatformFileHandle& handle)
{
int number = rand() % 10000 + 1;
- CString filename;
+ String filename;
do {
StringBuilder builder;
builder.append(sPluginPath);
builder.append('/');
builder.append(prefix);
builder.append(String::number(number));
- filename = builder.toString().utf8();
- const char* fstr = filename.data();
- handle = open(filename.data(), O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+ filename = builder.toString();
+ handle = open(filename.utf8().data(), O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
number++;
if (handle != -1)
return filename;
} while (errno == EEXIST);
- return CString();
+ return String();
}
bool unloadModule(PlatformModule module)
diff --git a/Source/WebCore/platform/android/LocalizedStringsAndroid.cpp b/Source/WebCore/platform/android/LocalizedStringsAndroid.cpp
index 5a96cf6..e5a733a 100644
--- a/Source/WebCore/platform/android/LocalizedStringsAndroid.cpp
+++ b/Source/WebCore/platform/android/LocalizedStringsAndroid.cpp
@@ -230,7 +230,7 @@ String contextMenuItemTagSearchWeb()
return String();
}
-String contextMenuItemTagLookUpInDictionary()
+String contextMenuItemTagLookUpInDictionary(const String&)
{
notImplemented();
return String();
diff --git a/Source/WebCore/platform/audio/AudioBus.cpp b/Source/WebCore/platform/audio/AudioBus.cpp
index dd4746d..6f74471 100644
--- a/Source/WebCore/platform/audio/AudioBus.cpp
+++ b/Source/WebCore/platform/audio/AudioBus.cpp
@@ -32,6 +32,9 @@
#include "AudioBus.h"
+#if !PLATFORM(MAC)
+#include "SincResampler.h"
+#endif
#include "VectorMath.h"
#include <algorithm>
#include <assert.h>
@@ -360,6 +363,90 @@ void AudioBus::sumWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, d
processWithGainFrom(sourceBus, lastMixGain, targetGain, true);
}
+#if !PLATFORM(MAC)
+PassOwnPtr<AudioBus> AudioBus::createBySampleRateConverting(AudioBus* sourceBus, bool mixToMono, double newSampleRate)
+{
+ // sourceBus's sample-rate must be known.
+ ASSERT(sourceBus && sourceBus->sampleRate());
+ if (!sourceBus || !sourceBus->sampleRate())
+ return 0;
+
+ double sourceSampleRate = sourceBus->sampleRate();
+ double destinationSampleRate = newSampleRate;
+ unsigned numberOfSourceChannels = sourceBus->numberOfChannels();
+
+ if (numberOfSourceChannels == 1)
+ mixToMono = false; // already mono
+
+ if (sourceSampleRate == destinationSampleRate) {
+ // No sample-rate conversion is necessary.
+ if (mixToMono)
+ return AudioBus::createByMixingToMono(sourceBus);
+
+ // Return exact copy.
+ return AudioBus::createBufferFromRange(sourceBus, 0, sourceBus->length());
+ }
+
+ // First, mix to mono (if necessary) then sample-rate convert.
+ AudioBus* resamplerSourceBus;
+ OwnPtr<AudioBus> mixedMonoBus;
+ if (mixToMono) {
+ mixedMonoBus = AudioBus::createByMixingToMono(sourceBus);
+ resamplerSourceBus = mixedMonoBus.get();
+ } else {
+ // Directly resample without down-mixing.
+ resamplerSourceBus = sourceBus;
+ }
+
+ // Calculate destination length based on the sample-rates.
+ double sampleRateRatio = sourceSampleRate / destinationSampleRate;
+ int sourceLength = resamplerSourceBus->length();
+ int destinationLength = sourceLength / sampleRateRatio;
+
+ // Create destination bus with same number of channels.
+ unsigned numberOfDestinationChannels = resamplerSourceBus->numberOfChannels();
+ OwnPtr<AudioBus> destinationBus(adoptPtr(new AudioBus(numberOfDestinationChannels, destinationLength)));
+
+ // Sample-rate convert each channel.
+ for (unsigned i = 0; i < numberOfDestinationChannels; ++i) {
+ float* source = resamplerSourceBus->channel(i)->data();
+ float* destination = destinationBus->channel(i)->data();
+
+ SincResampler resampler(sampleRateRatio);
+ resampler.process(source, destination, sourceLength);
+ }
+
+ return destinationBus.release();
+}
+#endif // !PLATFORM(MAC)
+
+PassOwnPtr<AudioBus> AudioBus::createByMixingToMono(AudioBus* sourceBus)
+{
+ switch (sourceBus->numberOfChannels()) {
+ case 1:
+ // Simply create an exact copy.
+ return AudioBus::createBufferFromRange(sourceBus, 0, sourceBus->length());
+ case 2:
+ {
+ 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();
+
+ // Do the mono mixdown.
+ for (unsigned i = 0; i < n; ++i)
+ destination[i] = 0.5 * (sourceL[i] + sourceR[i]);
+
+ return destinationBus.release();
+ }
+ }
+
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
} // WebCore
#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/platform/audio/AudioBus.h b/Source/WebCore/platform/audio/AudioBus.h
index 888f6bf..1943c0d 100644
--- a/Source/WebCore/platform/audio/AudioBus.h
+++ b/Source/WebCore/platform/audio/AudioBus.h
@@ -89,6 +89,18 @@ public:
// 0 may be returned if the range does not fit in the sourceBuffer
static PassOwnPtr<AudioBus> createBufferFromRange(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
+
+ // 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);
+
// Scales all samples by the same amount.
void scale(double scale);
diff --git a/Source/WebCore/platform/audio/HRTFKernel.cpp b/Source/WebCore/platform/audio/HRTFKernel.cpp
index 22d4b12..9db35ba 100644
--- a/Source/WebCore/platform/audio/HRTFKernel.cpp
+++ b/Source/WebCore/platform/audio/HRTFKernel.cpp
@@ -45,17 +45,18 @@ namespace WebCore {
// This represents the initial delay before the most energetic part of the impulse response.
// The sample-frame delay is removed from the impulseP impulse response, and this value is returned.
// the length of the passed in AudioChannel must be a power of 2.
-static double extractAverageGroupDelay(AudioChannel* channel)
+static double extractAverageGroupDelay(AudioChannel* channel, size_t analysisFFTSize)
{
ASSERT(channel);
float* impulseP = channel->data();
- size_t length = channel->length();
- // Check that length is power-of-2;
- ASSERT(1UL << static_cast<unsigned>(log2(length)) == length);
+ ASSERT(channel->length() >= analysisFFTSize);
+
+ // Check for power-of-2.
+ ASSERT(1UL << static_cast<unsigned>(log2(analysisFFTSize)) == analysisFFTSize);
- FFTFrame estimationFrame(length);
+ FFTFrame estimationFrame(analysisFFTSize);
estimationFrame.doFFT(impulseP);
double frameDelay = estimationFrame.extractAverageGroupDelay();
@@ -71,7 +72,7 @@ HRTFKernel::HRTFKernel(AudioChannel* channel, size_t fftSize, double sampleRate,
ASSERT(channel);
// Determine the leading delay (average group delay) for the response.
- m_frameDelay = extractAverageGroupDelay(channel);
+ m_frameDelay = extractAverageGroupDelay(channel, fftSize / 2);
float* impulseResponse = channel->data();
size_t responseLength = channel->length();
diff --git a/Source/WebCore/platform/audio/SincResampler.cpp b/Source/WebCore/platform/audio/SincResampler.cpp
new file mode 100644
index 0000000..e6f34b4
--- /dev/null
+++ b/Source/WebCore/platform/audio/SincResampler.cpp
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(WEB_AUDIO)
+
+#include "SincResampler.h"
+
+#include <wtf/MathExtras.h>
+
+using namespace std;
+
+// Input buffer layout, dividing the total buffer into regions (r0 - r5):
+//
+// |----------------|----------------------------------------------------------------|----------------|
+//
+// blockSize + kernelSize / 2
+// <-------------------------------------------------------------------------------->
+// r0
+//
+// kernelSize / 2 kernelSize / 2 kernelSize / 2 kernelSize / 2
+// <---------------> <---------------> <---------------> <--------------->
+// r1 r2 r3 r4
+//
+// blockSize
+// <-------------------------------------------------------------->
+// r5
+
+// The Algorithm:
+//
+// 1) Consume input frames into r0 (r1 is zero-initialized).
+// 2) Position kernel centered at start of r0 (r2) and generate output frames until kernel is centered at start of r4.
+// or we've finished generating all the output frames.
+// 3) Copy r3 to r1 and r4 to r2.
+// 4) Consume input frames into r5 (zero-pad if we run out of input).
+// 5) Goto (2) until all of input is consumed.
+//
+// note: we're glossing over how the sub-sample handling works with m_virtualSourceIndex, etc.
+
+namespace WebCore {
+
+SincResampler::SincResampler(double scaleFactor, unsigned kernelSize, unsigned numberOfKernelOffsets)
+ : m_scaleFactor(scaleFactor)
+ , m_kernelSize(kernelSize)
+ , m_numberOfKernelOffsets(numberOfKernelOffsets)
+ , m_kernelStorage(m_kernelSize * (m_numberOfKernelOffsets + 1))
+ , m_virtualSourceIndex(0.0)
+ , m_blockSize(512)
+ , m_inputBuffer(m_blockSize + m_kernelSize) // See input buffer layout above.
+ , m_source(0)
+ , m_sourceFramesAvailable(0)
+{
+ initializeKernel();
+}
+
+void SincResampler::initializeKernel()
+{
+ // Blackman window parameters.
+ double alpha = 0.16;
+ double a0 = 0.5 * (1.0 - alpha);
+ double a1 = 0.5;
+ double a2 = 0.5 * alpha;
+
+ // sincScaleFactor is basically the normalized cutoff frequency of the low-pass filter.
+ double sincScaleFactor = m_scaleFactor > 1.0 ? 1.0 / m_scaleFactor : 1.0;
+
+ // The sinc function is an idealized brick-wall filter, but since we're windowing it the
+ // transition from pass to stop does not happen right away. So we should adjust the
+ // lowpass filter cutoff slightly downward to avoid some aliasing at the very high-end.
+ // FIXME: this value is empirical and to be more exact should vary depending on m_kernelSize.
+ sincScaleFactor *= 0.9;
+
+ int n = m_kernelSize;
+ int halfSize = n / 2;
+
+ // Generates a set of windowed sinc() kernels.
+ // We generate a range of sub-sample offsets from 0.0 to 1.0.
+ for (unsigned offsetIndex = 0; offsetIndex <= m_numberOfKernelOffsets; ++offsetIndex) {
+ double subsampleOffset = static_cast<double>(offsetIndex) / m_numberOfKernelOffsets;
+
+ for (int i = 0; i < n; ++i) {
+ // Compute the sinc() with offset.
+ double s = sincScaleFactor * piDouble * (i - halfSize - subsampleOffset);
+ double sinc = !s ? 1.0 : sin(s) / s;
+ sinc *= sincScaleFactor;
+
+ // Compute Blackman window, matching the offset of the sinc().
+ double x = (i - subsampleOffset) / n;
+ double window = a0 - a1 * cos(2.0 * piDouble * x) + a2 * cos(4.0 * piDouble * x);
+
+ // Window the sinc() function and store at the correct offset.
+ m_kernelStorage[i + offsetIndex * m_kernelSize] = sinc * window;
+ }
+ }
+}
+
+void SincResampler::consumeSource(float* buffer, unsigned numberOfSourceFrames)
+{
+ ASSERT(m_source);
+ if (!m_source)
+ return;
+
+ // Clamp to number of frames available and zero-pad.
+ unsigned framesToCopy = min(m_sourceFramesAvailable, numberOfSourceFrames);
+ memcpy(buffer, m_source, sizeof(float) * framesToCopy);
+
+ // Zero-pad if necessary.
+ if (framesToCopy < numberOfSourceFrames)
+ memset(buffer + framesToCopy, 0, sizeof(float) * (numberOfSourceFrames - framesToCopy));
+
+ m_sourceFramesAvailable -= framesToCopy;
+ m_source += numberOfSourceFrames;
+}
+
+void SincResampler::process(float* source, float* destination, unsigned numberOfSourceFrames)
+{
+ ASSERT(m_blockSize > m_kernelSize);
+ ASSERT(m_inputBuffer.size() >= m_blockSize + m_kernelSize);
+ ASSERT(!(m_kernelSize % 2));
+
+ // Setup various region pointers in the buffer (see diagram above).
+ float* r0 = m_inputBuffer.data() + m_kernelSize / 2;
+ float* r1 = m_inputBuffer.data();
+ float* r2 = r0;
+ float* r3 = r0 + m_blockSize - m_kernelSize / 2;
+ float* r4 = r0 + m_blockSize;
+ float* r5 = r0 + m_kernelSize / 2;
+
+ m_source = source;
+ m_sourceFramesAvailable = numberOfSourceFrames;
+
+ unsigned numberOfDestinationFrames = static_cast<unsigned>(numberOfSourceFrames / m_scaleFactor);
+
+ // Step (1)
+ // Prime the input buffer.
+ consumeSource(r0, m_blockSize + m_kernelSize / 2);
+
+ // Step (2)
+ m_virtualSourceIndex = 0;
+
+ while (numberOfDestinationFrames) {
+ while (m_virtualSourceIndex < m_blockSize) {
+ // m_virtualSourceIndex lies in between two kernel offsets so figure out what they are.
+ int sourceIndexI = static_cast<int>(m_virtualSourceIndex);
+ double subsampleRemainder = m_virtualSourceIndex - sourceIndexI;
+
+ double virtualOffsetIndex = subsampleRemainder * m_numberOfKernelOffsets;
+ int offsetIndex = static_cast<int>(virtualOffsetIndex);
+
+ float* k1 = m_kernelStorage.data() + offsetIndex * m_kernelSize;
+ float* k2 = k1 + m_kernelSize;
+
+ // Initialize input pointer based on quantized m_virtualSourceIndex.
+ float* inputP = r1 + sourceIndexI;
+
+ // We'll compute "convolutions" for the two kernels which straddle m_virtualSourceIndex
+ float sum1 = 0;
+ float sum2 = 0;
+
+ // Figure out how much to weight each kernel's "convolution".
+ double kernelInterpolationFactor = virtualOffsetIndex - offsetIndex;
+
+ // Generate a single output sample.
+ int n = m_kernelSize;
+
+ // FIXME: add SIMD optimizations for the following. The scalar code-path can probably also be optimized better.
+
+#define CONVOLVE_ONE_SAMPLE \
+ input = *inputP++; \
+ sum1 += input * *k1; \
+ sum2 += input * *k2; \
+ ++k1; \
+ ++k2;
+
+ {
+ float input;
+
+ // Optimize size 32 and size 64 kernels by unrolling the while loop.
+ // A 20 - 30% speed improvement was measured in some cases by using this approach.
+
+ if (n == 32) {
+ CONVOLVE_ONE_SAMPLE // 1
+ CONVOLVE_ONE_SAMPLE // 2
+ CONVOLVE_ONE_SAMPLE // 3
+ CONVOLVE_ONE_SAMPLE // 4
+ CONVOLVE_ONE_SAMPLE // 5
+ CONVOLVE_ONE_SAMPLE // 6
+ CONVOLVE_ONE_SAMPLE // 7
+ CONVOLVE_ONE_SAMPLE // 8
+ CONVOLVE_ONE_SAMPLE // 9
+ CONVOLVE_ONE_SAMPLE // 10
+ CONVOLVE_ONE_SAMPLE // 11
+ CONVOLVE_ONE_SAMPLE // 12
+ CONVOLVE_ONE_SAMPLE // 13
+ CONVOLVE_ONE_SAMPLE // 14
+ CONVOLVE_ONE_SAMPLE // 15
+ CONVOLVE_ONE_SAMPLE // 16
+ CONVOLVE_ONE_SAMPLE // 17
+ CONVOLVE_ONE_SAMPLE // 18
+ CONVOLVE_ONE_SAMPLE // 19
+ CONVOLVE_ONE_SAMPLE // 20
+ CONVOLVE_ONE_SAMPLE // 21
+ CONVOLVE_ONE_SAMPLE // 22
+ CONVOLVE_ONE_SAMPLE // 23
+ CONVOLVE_ONE_SAMPLE // 24
+ CONVOLVE_ONE_SAMPLE // 25
+ CONVOLVE_ONE_SAMPLE // 26
+ CONVOLVE_ONE_SAMPLE // 27
+ CONVOLVE_ONE_SAMPLE // 28
+ CONVOLVE_ONE_SAMPLE // 29
+ CONVOLVE_ONE_SAMPLE // 30
+ CONVOLVE_ONE_SAMPLE // 31
+ CONVOLVE_ONE_SAMPLE // 32
+ } else if (n == 64) {
+ CONVOLVE_ONE_SAMPLE // 1
+ CONVOLVE_ONE_SAMPLE // 2
+ CONVOLVE_ONE_SAMPLE // 3
+ CONVOLVE_ONE_SAMPLE // 4
+ CONVOLVE_ONE_SAMPLE // 5
+ CONVOLVE_ONE_SAMPLE // 6
+ CONVOLVE_ONE_SAMPLE // 7
+ CONVOLVE_ONE_SAMPLE // 8
+ CONVOLVE_ONE_SAMPLE // 9
+ CONVOLVE_ONE_SAMPLE // 10
+ CONVOLVE_ONE_SAMPLE // 11
+ CONVOLVE_ONE_SAMPLE // 12
+ CONVOLVE_ONE_SAMPLE // 13
+ CONVOLVE_ONE_SAMPLE // 14
+ CONVOLVE_ONE_SAMPLE // 15
+ CONVOLVE_ONE_SAMPLE // 16
+ CONVOLVE_ONE_SAMPLE // 17
+ CONVOLVE_ONE_SAMPLE // 18
+ CONVOLVE_ONE_SAMPLE // 19
+ CONVOLVE_ONE_SAMPLE // 20
+ CONVOLVE_ONE_SAMPLE // 21
+ CONVOLVE_ONE_SAMPLE // 22
+ CONVOLVE_ONE_SAMPLE // 23
+ CONVOLVE_ONE_SAMPLE // 24
+ CONVOLVE_ONE_SAMPLE // 25
+ CONVOLVE_ONE_SAMPLE // 26
+ CONVOLVE_ONE_SAMPLE // 27
+ CONVOLVE_ONE_SAMPLE // 28
+ CONVOLVE_ONE_SAMPLE // 29
+ CONVOLVE_ONE_SAMPLE // 30
+ CONVOLVE_ONE_SAMPLE // 31
+ CONVOLVE_ONE_SAMPLE // 32
+ CONVOLVE_ONE_SAMPLE // 33
+ CONVOLVE_ONE_SAMPLE // 34
+ CONVOLVE_ONE_SAMPLE // 35
+ CONVOLVE_ONE_SAMPLE // 36
+ CONVOLVE_ONE_SAMPLE // 37
+ CONVOLVE_ONE_SAMPLE // 38
+ CONVOLVE_ONE_SAMPLE // 39
+ CONVOLVE_ONE_SAMPLE // 40
+ CONVOLVE_ONE_SAMPLE // 41
+ CONVOLVE_ONE_SAMPLE // 42
+ CONVOLVE_ONE_SAMPLE // 43
+ CONVOLVE_ONE_SAMPLE // 44
+ CONVOLVE_ONE_SAMPLE // 45
+ CONVOLVE_ONE_SAMPLE // 46
+ CONVOLVE_ONE_SAMPLE // 47
+ CONVOLVE_ONE_SAMPLE // 48
+ CONVOLVE_ONE_SAMPLE // 49
+ CONVOLVE_ONE_SAMPLE // 50
+ CONVOLVE_ONE_SAMPLE // 51
+ CONVOLVE_ONE_SAMPLE // 52
+ CONVOLVE_ONE_SAMPLE // 53
+ CONVOLVE_ONE_SAMPLE // 54
+ CONVOLVE_ONE_SAMPLE // 55
+ CONVOLVE_ONE_SAMPLE // 56
+ CONVOLVE_ONE_SAMPLE // 57
+ CONVOLVE_ONE_SAMPLE // 58
+ CONVOLVE_ONE_SAMPLE // 59
+ CONVOLVE_ONE_SAMPLE // 60
+ CONVOLVE_ONE_SAMPLE // 61
+ CONVOLVE_ONE_SAMPLE // 62
+ CONVOLVE_ONE_SAMPLE // 63
+ CONVOLVE_ONE_SAMPLE // 64
+ } else {
+ while (n--) {
+ // Non-optimized using actual while loop.
+ CONVOLVE_ONE_SAMPLE
+ }
+ }
+ }
+
+ // Linearly interpolate the two "convolutions".
+ double result = (1.0 - kernelInterpolationFactor) * sum1 + kernelInterpolationFactor * sum2;
+
+ *destination++ = result;
+
+ --numberOfDestinationFrames;
+ if (!numberOfDestinationFrames)
+ return;
+
+ // Advance the virtual index.
+ m_virtualSourceIndex += m_scaleFactor;
+ }
+
+ // Wrap back around to the start.
+ m_virtualSourceIndex -= m_blockSize;
+
+ // Step (3) Copy r3 to r1 and r4 to r2.
+ // This wraps the last input frames back to the start of the buffer.
+ memcpy(r1, r3, sizeof(float) * (m_kernelSize / 2));
+ memcpy(r2, r4, sizeof(float) * (m_kernelSize / 2));
+
+ // Step (4)
+ // Refresh the buffer with more input.
+ consumeSource(r5, m_blockSize);
+ }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/platform/audio/SincResampler.h b/Source/WebCore/platform/audio/SincResampler.h
new file mode 100644
index 0000000..92adb95
--- /dev/null
+++ b/Source/WebCore/platform/audio/SincResampler.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SincResampler_h
+#define SincResampler_h
+
+#include "AudioArray.h"
+
+namespace WebCore {
+
+// SincResampler is a high-quality sample-rate converter.
+
+class SincResampler {
+public:
+ // scaleFactor == sourceSampleRate / destinationSampleRate
+ // kernelSize can be adjusted for quality (higher is better)
+ // numberOfKernelOffsets is used for interpolation and is the number of sub-sample kernel shifts.
+ SincResampler(double scaleFactor, unsigned kernelSize = 64, unsigned numberOfKernelOffsets = 32);
+
+ // Processes numberOfSourceFrames from source to produce numberOfSourceFrames / scaleFactor frames in destination.
+ void process(float* source, float* destination, unsigned numberOfSourceFrames);
+
+ // FIXME: we can add a process() method which takes an input source callback function for streaming applications
+ // where the entire input buffer is not all available.
+
+protected:
+ void initializeKernel();
+ void consumeSource(float* buffer, unsigned numberOfSourceFrames);
+
+ double m_scaleFactor;
+ unsigned m_kernelSize;
+ unsigned m_numberOfKernelOffsets;
+
+ // m_kernelStorage has m_numberOfKernelOffsets kernels back-to-back, each of size m_kernelSize.
+ // The kernel offsets are sub-sample shifts of a windowed sinc() shifted from 0.0 to 1.0 sample.
+ AudioFloatArray m_kernelStorage;
+
+ // m_virtualSourceIndex is an index on the source input buffer with sub-sample precision.
+ // It must be double precision to avoid drift.
+ double m_virtualSourceIndex;
+
+ // This is the number of destination frames we generate per processing pass on the buffer.
+ unsigned m_blockSize;
+
+ // Source is copied into this buffer for each processing pass.
+ AudioFloatArray m_inputBuffer;
+
+ float* m_source;
+ unsigned m_sourceFramesAvailable;
+};
+
+} // namespace WebCore
+
+#endif // SincResampler_h
diff --git a/Source/WebCore/platform/audio/chromium/AudioBusChromium.cpp b/Source/WebCore/platform/audio/chromium/AudioBusChromium.cpp
index de44b1c..f34dc77 100644
--- a/Source/WebCore/platform/audio/chromium/AudioBusChromium.cpp
+++ b/Source/WebCore/platform/audio/chromium/AudioBusChromium.cpp
@@ -36,22 +36,30 @@ namespace WebCore {
PassOwnPtr<AudioBus> AudioBus::loadPlatformResource(const char* name, double sampleRate)
{
- return PlatformBridge::loadPlatformAudioResource(name, sampleRate);
+ // FIXME: the sampleRate parameter is ignored. It should be removed from the API.
+ OwnPtr<AudioBus> audioBus = PlatformBridge::loadPlatformAudioResource(name, sampleRate);
+ if (!audioBus.get())
+ return 0;
+
+ // If the bus is already at the requested sample-rate then return as is.
+ if (audioBus->sampleRate() == sampleRate)
+ return audioBus.release();
+
+ return AudioBus::createBySampleRateConverting(audioBus.get(), false, sampleRate);
}
PassOwnPtr<AudioBus> createBusFromInMemoryAudioFile(const void* data, size_t dataSize, bool mixToMono, double sampleRate)
{
+ // FIXME: the sampleRate parameter is ignored. It should be removed from the API.
OwnPtr<AudioBus> audioBus = PlatformBridge::decodeAudioFileData(static_cast<const char*>(data), dataSize, sampleRate);
- if (audioBus.get() && audioBus->numberOfChannels() == 2 && mixToMono) {
- OwnPtr<AudioBus> monoAudioBus = adoptPtr(new AudioBus(1, audioBus->length()));
-
- // FIXME: AudioBus::copyFrom() should be able to do a downmix to mono.
- // for now simply copy the left channel.
- monoAudioBus->channel(0)->copyFrom(audioBus->channel(0));
- return monoAudioBus.release();
- }
+ if (!audioBus.get())
+ return 0;
+
+ // If the bus needs no conversion then return as is.
+ if ((!mixToMono || audioBus->numberOfChannels() == 1) && audioBus->sampleRate() == sampleRate)
+ return audioBus.release();
- return audioBus.release();
+ return AudioBus::createBySampleRateConverting(audioBus.get(), mixToMono, sampleRate);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/audio/mac/AudioDestinationMac.cpp b/Source/WebCore/platform/audio/mac/AudioDestinationMac.cpp
index 523729f..d4ecaba 100644
--- a/Source/WebCore/platform/audio/mac/AudioDestinationMac.cpp
+++ b/Source/WebCore/platform/audio/mac/AudioDestinationMac.cpp
@@ -51,8 +51,8 @@ double AudioDestination::hardwareSampleRate()
AudioDeviceID deviceID = kAudioDeviceUnknown;
UInt32 infoSize = sizeof(deviceID);
- AudioObjectPropertyAddress defaultInputDeviceAddress = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
- OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &defaultInputDeviceAddress, 0, 0, &infoSize, (void*)&deviceID);
+ AudioObjectPropertyAddress defaultOutputDeviceAddress = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
+ OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &defaultOutputDeviceAddress, 0, 0, &infoSize, (void*)&deviceID);
if (result)
return 0.0; // error
diff --git a/Source/WebCore/platform/brew/FileSystemBrew.cpp b/Source/WebCore/platform/brew/FileSystemBrew.cpp
index 61d568d..251c004 100644
--- a/Source/WebCore/platform/brew/FileSystemBrew.cpp
+++ b/Source/WebCore/platform/brew/FileSystemBrew.cpp
@@ -186,7 +186,7 @@ String directoryName(const String& path)
return dirName;
}
-CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
+String openTemporaryFile(const String& prefix, PlatformFileHandle& handle)
{
// BREW does not have a system-wide temporary directory,
// use "fs:/~/tmp" as our temporary directory.
@@ -199,24 +199,24 @@ CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
// Loop until we find a temporary filename that does not exist.
int number = static_cast<int>(randomNumber() * 10000);
- CString filename;
+ String filename;
do {
StringBuilder builder;
builder.append(tempPath);
builder.append('/');
builder.append(prefix);
builder.append(String::number(number));
- filename = builder.toString().utf8();
+ filename = builder.toString();
number++;
- } while (IFILEMGR_Test(fileMgr.get(), filename.data()) == SUCCESS);
+ } while (IFILEMGR_Test(fileMgr.get(), filename.utf8().data()) == SUCCESS);
- IFile* tempFile = IFILEMGR_OpenFile(fileMgr.get(), filename.data(), _OFM_CREATE);
+ IFile* tempFile = IFILEMGR_OpenFile(fileMgr.get(), filename.utf8().data(), _OFM_CREATE);
if (tempFile) {
handle = tempFile;
return filename;
}
- return CString();
+ return String();
}
void closeFile(PlatformFileHandle& handle)
diff --git a/Source/WebCore/platform/brew/LocalizedStringsBrew.cpp b/Source/WebCore/platform/brew/LocalizedStringsBrew.cpp
index c4dac1a..ba5d4a9 100644
--- a/Source/WebCore/platform/brew/LocalizedStringsBrew.cpp
+++ b/Source/WebCore/platform/brew/LocalizedStringsBrew.cpp
@@ -206,7 +206,7 @@ String contextMenuItemTagSearchWeb()
return "Search web";
}
-String contextMenuItemTagLookUpInDictionary()
+String contextMenuItemTagLookUpInDictionary(const String&)
{
return "Lookup in dictionary";
}
diff --git a/Source/WebCore/platform/cf/BinaryPropertyList.cpp b/Source/WebCore/platform/cf/BinaryPropertyList.cpp
index 41769e8..65be70a 100644
--- a/Source/WebCore/platform/cf/BinaryPropertyList.cpp
+++ b/Source/WebCore/platform/cf/BinaryPropertyList.cpp
@@ -92,7 +92,7 @@ struct IntegerArrayHash {
unsigned IntegerArrayHash::hash(const IntegerArray& array)
{
- return WTF::StringHasher::createBlobHash(array.integers(), array.size());
+ return StringHasher::hashMemory(array.integers(), array.size() * sizeof(int));
}
bool IntegerArrayHash::equal(const IntegerArray& a, const IntegerArray& b)
diff --git a/Source/WebCore/platform/cf/SchedulePair.h b/Source/WebCore/platform/cf/SchedulePair.h
index 8361856..cb34d7d 100644
--- a/Source/WebCore/platform/cf/SchedulePair.h
+++ b/Source/WebCore/platform/cf/SchedulePair.h
@@ -73,7 +73,7 @@ struct SchedulePairHash {
static unsigned hash(const RefPtr<SchedulePair>& pair)
{
uintptr_t hashCodes[2] = { reinterpret_cast<uintptr_t>(pair->runLoop()), pair->mode() ? CFHash(pair->mode()) : 0 };
- return WTF::StringHasher::createBlobHash<sizeof(hashCodes)>(hashCodes);
+ return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
}
static bool equal(const RefPtr<SchedulePair>& a, const RefPtr<SchedulePair>& b) { return a == b; }
diff --git a/Source/WebCore/platform/cf/SharedBufferCF.cpp b/Source/WebCore/platform/cf/SharedBufferCF.cpp
index 18a65c2..319f484 100644
--- a/Source/WebCore/platform/cf/SharedBufferCF.cpp
+++ b/Source/WebCore/platform/cf/SharedBufferCF.cpp
@@ -91,4 +91,30 @@ void SharedBuffer::clearPlatformData()
m_cfData = 0;
}
+#if HAVE(CFNETWORK_DATA_ARRAY_CALLBACK)
+void SharedBuffer::append(CFDataRef data)
+{
+ ASSERT(data);
+ m_dataArray.append(data);
+ m_size += CFDataGetLength(data);
+}
+
+void SharedBuffer::copyDataArrayAndClear(char *destination, unsigned bytesToCopy) const
+{
+ if (m_dataArray.isEmpty())
+ return;
+
+ CFIndex bytesLeft = bytesToCopy;
+ Vector<RetainPtr<CFDataRef> >::const_iterator end = m_dataArray.end();
+ for (Vector<RetainPtr<CFDataRef> >::const_iterator it = m_dataArray.begin(); it != end; ++it) {
+ CFIndex dataLen = CFDataGetLength(it->get());
+ ASSERT(bytesLeft >= dataLen);
+ memcpy(destination, CFDataGetBytePtr(it->get()), dataLen);
+ destination += dataLen;
+ bytesLeft -= dataLen;
+ }
+ m_dataArray.clear();
+}
+#endif
+
}
diff --git a/Source/WebCore/platform/cf/win/CertificateCFWin.cpp b/Source/WebCore/platform/cf/win/CertificateCFWin.cpp
new file mode 100644
index 0000000..88ea933
--- /dev/null
+++ b/Source/WebCore/platform/cf/win/CertificateCFWin.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 "CertificateCFWin.h"
+
+namespace WebCore {
+
+static void deallocCertContext(void* ptr, void* info)
+{
+ if (ptr)
+ CertFreeCertificateContext(static_cast<PCCERT_CONTEXT>(ptr));
+}
+
+static CFAllocatorRef createCertContextDeallocator()
+{
+ CFAllocatorContext allocContext = {
+ 0, 0, 0, 0, 0, 0, 0, deallocCertContext, 0
+ };
+ return CFAllocatorCreate(kCFAllocatorDefault, &allocContext);
+}
+
+RetainPtr<CFDataRef> copyCertificateToData(PCCERT_CONTEXT certificate)
+{
+ static CFAllocatorRef certDealloc = createCertContextDeallocator();
+ PCCERT_CONTEXT certificateCopy = CertDuplicateCertificateContext(certificate);
+ return RetainPtr<CFDataRef>(AdoptCF, CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const UInt8*>(certificateCopy), sizeof(*certificateCopy), certDealloc));
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/cf/win/CertificateCFWin.h b/Source/WebCore/platform/cf/win/CertificateCFWin.h
new file mode 100644
index 0000000..b3ada0d
--- /dev/null
+++ b/Source/WebCore/platform/cf/win/CertificateCFWin.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 CertificateCFWin_h
+#define CertificateCFWin_h
+
+#include <windows.h>
+#include <wtf/RetainPtr.h>
+
+namespace WebCore {
+
+RetainPtr<CFDataRef> copyCertificateToData(PCCERT_CONTEXT);
+
+} // namespace WebCore
+
+#endif // CertificateCFWin_h
diff --git a/Source/WebCore/platform/chromium/ClipboardChromium.cpp b/Source/WebCore/platform/chromium/ClipboardChromium.cpp
index 7e58f03..6756313 100644
--- a/Source/WebCore/platform/chromium/ClipboardChromium.cpp
+++ b/Source/WebCore/platform/chromium/ClipboardChromium.cpp
@@ -31,6 +31,7 @@
#include "ChromiumDataObject.h"
#include "ClipboardMimeTypes.h"
#include "ClipboardUtilitiesChromium.h"
+#include "DataTransferItemsChromium.h"
#include "Document.h"
#include "DragData.h"
#include "Element.h"
@@ -342,4 +343,22 @@ bool ClipboardChromium::hasData()
return m_dataObject->hasData();
}
+#if ENABLE(DATA_TRANSFER_ITEMS)
+PassRefPtr<DataTransferItems> ClipboardChromium::items()
+{
+ RefPtr<DataTransferItemsChromium> items = DataTransferItemsChromium::create(this, m_frame->document()->scriptExecutionContext());
+
+ if (!m_dataObject)
+ return items;
+
+ 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);
+ }
+ return items;
+}
+#endif
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/ClipboardChromium.h b/Source/WebCore/platform/chromium/ClipboardChromium.h
index d30a1c4..61db0a5 100644
--- a/Source/WebCore/platform/chromium/ClipboardChromium.h
+++ b/Source/WebCore/platform/chromium/ClipboardChromium.h
@@ -80,6 +80,10 @@ namespace WebCore {
virtual bool hasData();
+#if ENABLE(DATA_TRANSFER_ITEMS)
+ virtual PassRefPtr<DataTransferItems> items();
+#endif
+
private:
ClipboardChromium(ClipboardType, PassRefPtr<ChromiumDataObject>, ClipboardAccessPolicy, Frame*);
diff --git a/Source/WebCore/platform/chromium/DataTransferItemChromium.cpp b/Source/WebCore/platform/chromium/DataTransferItemChromium.cpp
new file mode 100644
index 0000000..7857336
--- /dev/null
+++ b/Source/WebCore/platform/chromium/DataTransferItemChromium.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DataTransferItemChromium.h"
+
+#if ENABLE(DATA_TRANSFER_ITEMS)
+
+#include "Clipboard.h"
+#include "ClipboardMimeTypes.h"
+#include "PlatformBridge.h"
+#include "StringCallback.h"
+
+namespace WebCore {
+
+PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::createFromPasteboard(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context, const String& type)
+{
+ if (type == mimeTypeTextPlain || type == mimeTypeTextHTML)
+ return adoptRef(new DataTransferItemChromium(owner, context, PasteboardSource, DataTransferItem::kindString, type, ""));
+ return adoptRef(new DataTransferItemChromium(owner, context, PasteboardSource, DataTransferItem::kindFile, type, ""));
+}
+
+PassRefPtr<DataTransferItemChromium> DataTransferItemChromium::create(PassRefPtr<Clipboard> owner,
+ ScriptExecutionContext* context,
+ const String& data,
+ const String& type)
+{
+ return adoptRef(new DataTransferItemChromium(owner, context, InternalSource, DataTransferItem::kindString, type, data));
+}
+
+DataTransferItemChromium::DataTransferItemChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context, DataSource source, const String& kind, const String& type, const String& data)
+ : m_owner(owner)
+ , m_context(context)
+ , m_source(source)
+ , m_kind(kind)
+ , m_type(type)
+ , m_data(data)
+{
+}
+
+String DataTransferItemChromium::kind() const
+{
+ if (m_owner->policy() == ClipboardNumb)
+ return String();
+ return m_kind;
+}
+
+String DataTransferItemChromium::type() const
+{
+ if (m_owner->policy() == ClipboardNumb)
+ return String();
+ return m_type;
+}
+
+void DataTransferItemChromium::getAsString(PassRefPtr<StringCallback> callback)
+{
+ if ((m_owner->policy() != ClipboardReadable && m_owner->policy() != ClipboardWritable)
+ || m_kind != kindString)
+ return;
+ if (m_source == InternalSource) {
+ callback->scheduleCallback(m_context, m_data);
+ return;
+ }
+ // This is ugly but there's no real alternative.
+ if (m_type == mimeTypeTextPlain) {
+ callback->scheduleCallback(m_context, PlatformBridge::clipboardReadPlainText(PasteboardPrivate::StandardBuffer));
+ return;
+ }
+ if (m_type == mimeTypeTextHTML) {
+ String html;
+ KURL ignoredSourceURL;
+ PlatformBridge::clipboardReadHTML(PasteboardPrivate::StandardBuffer, &html, &ignoredSourceURL);
+ callback->scheduleCallback(m_context, html);
+ return;
+ }
+ ASSERT_NOT_REACHED();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(DATA_TRANSFER_ITEMS)
diff --git a/Source/WebCore/platform/chromium/DataTransferItemChromium.h b/Source/WebCore/platform/chromium/DataTransferItemChromium.h
new file mode 100644
index 0000000..77f74f2
--- /dev/null
+++ b/Source/WebCore/platform/chromium/DataTransferItemChromium.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DataTransferItemChromium_h
+#define DataTransferItemChromium_h
+
+#if ENABLE(DATA_TRANSFER_ITEMS)
+
+#include "DataTransferItem.h"
+#include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class Clipboard;
+class 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);
+
+ virtual String kind() const;
+ virtual String type() const;
+
+ virtual void getAsString(PassRefPtr<StringCallback>);
+
+private:
+ enum DataSource {
+ PasteboardSource,
+ InternalSource,
+ };
+
+ DataTransferItemChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext*, DataSource, const String& kind, const String& type, const String& data);
+
+ const RefPtr<Clipboard> m_owner;
+ ScriptExecutionContext* m_context;
+ const DataSource m_source;
+ const String m_kind;
+ const String m_type;
+ const String m_data;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(DATA_TRANSFER_ITEMS)
+
+#endif // DataTransferItem_h
diff --git a/Source/WebCore/platform/chromium/DataTransferItemsChromium.cpp b/Source/WebCore/platform/chromium/DataTransferItemsChromium.cpp
new file mode 100644
index 0000000..418b8b5
--- /dev/null
+++ b/Source/WebCore/platform/chromium/DataTransferItemsChromium.cpp
@@ -0,0 +1,111 @@
+/*
+ * 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 "DataTransferItemsChromium.h"
+
+#if ENABLE(DATA_TRANSFER_ITEMS)
+
+#include "Clipboard.h"
+#include "DataTransferItemChromium.h"
+#include "ExceptionCode.h"
+
+namespace WebCore {
+
+PassRefPtr<DataTransferItemsChromium> DataTransferItemsChromium::create(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context)
+{
+ return adoptRef(new DataTransferItemsChromium(owner, context));
+}
+
+DataTransferItemsChromium::DataTransferItemsChromium(PassRefPtr<Clipboard> owner, ScriptExecutionContext* context)
+ : m_owner(owner)
+ , m_context(context)
+{
+}
+
+unsigned long DataTransferItemsChromium::length() const
+{
+ if (m_owner->policy() == ClipboardNumb)
+ return 0;
+ return m_items.size();
+}
+
+PassRefPtr<DataTransferItem> DataTransferItemsChromium::item(unsigned long index) const
+{
+ if (m_owner->policy() == ClipboardNumb || index >= length())
+ return 0;
+ return m_items[index];
+}
+
+void DataTransferItemsChromium::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 DataTransferItemsChromium::clear()
+{
+ if (m_owner->policy() != ClipboardWritable)
+ return;
+
+ m_items.clear();
+}
+
+void DataTransferItemsChromium::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 = INVALID_STATE_ERR;
+ return;
+ }
+ }
+
+ m_items.append(DataTransferItemChromium::create(m_owner, m_context, data, type));
+}
+
+void DataTransferItemsChromium::addPasteboardItem(const String& type)
+{
+ m_items.append(DataTransferItemChromium::createFromPasteboard(m_owner, m_context, type));
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(DATA_TRANSFER_ITEMS)
diff --git a/Source/WebCore/platform/chromium/DataTransferItemsChromium.h b/Source/WebCore/platform/chromium/DataTransferItemsChromium.h
new file mode 100644
index 0000000..51c4fdb
--- /dev/null
+++ b/Source/WebCore/platform/chromium/DataTransferItemsChromium.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DataTransferItemsChromium_h
+#define DataTransferItemsChromium_h
+
+#if ENABLE(DATA_TRANSFER_ITEMS)
+
+#include "DataTransferItems.h"
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Clipboard;
+class DataTransferItemChromium;
+class ScriptExecutionContext;
+
+typedef int ExceptionCode;
+
+class DataTransferItemsChromium : public DataTransferItems {
+public:
+ static PassRefPtr<DataTransferItemsChromium> create(PassRefPtr<Clipboard>, ScriptExecutionContext*);
+
+ virtual unsigned long length() const;
+ virtual PassRefPtr<DataTransferItem> item(unsigned long index) const;
+ virtual void deleteItem(unsigned long index, ExceptionCode&);
+ virtual void clear();
+
+ virtual void add(const String& data, const String& type, ExceptionCode&);
+
+private:
+ friend class ClipboardChromium;
+
+ DataTransferItemsChromium(PassRefPtr<Clipboard>, ScriptExecutionContext*);
+
+ virtual void addPasteboardItem(const String& type);
+
+ RefPtr<Clipboard> m_owner;
+ // Indirectly owned by our parent.
+ ScriptExecutionContext* m_context;
+ Vector<RefPtr<DataTransferItemChromium> > m_items;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(DATA_TRANSFER_ITEMS)
+
+#endif // DataTransferItemsChromium_h
+
diff --git a/Source/WebCore/platform/chromium/FileSystemChromium.cpp b/Source/WebCore/platform/chromium/FileSystemChromium.cpp
index faf5e92..5e03c5b 100644
--- a/Source/WebCore/platform/chromium/FileSystemChromium.cpp
+++ b/Source/WebCore/platform/chromium/FileSystemChromium.cpp
@@ -112,4 +112,11 @@ int writeToFile(PlatformFileHandle handle, const char* data, int length)
return PlatformBridge::writeToFile(handle, data, length);
}
+Vector<String> listDirectory(const String& path, const String& filter)
+{
+ notImplemented();
+
+ return Vector<String>();
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/PasteboardPrivate.h b/Source/WebCore/platform/chromium/PasteboardPrivate.h
index 1de7fe3..5f167ba 100644
--- a/Source/WebCore/platform/chromium/PasteboardPrivate.h
+++ b/Source/WebCore/platform/chromium/PasteboardPrivate.h
@@ -36,6 +36,7 @@ namespace WebCore {
class PasteboardPrivate {
public:
enum ClipboardFormat {
+ PlainTextFormat,
HTMLFormat,
BookmarkFormat,
WebSmartPasteFormat,
diff --git a/Source/WebCore/platform/chromium/ScrollbarThemeChromiumWin.cpp b/Source/WebCore/platform/chromium/ScrollbarThemeChromiumWin.cpp
index 29e8b44..7229c51 100644
--- a/Source/WebCore/platform/chromium/ScrollbarThemeChromiumWin.cpp
+++ b/Source/WebCore/platform/chromium/ScrollbarThemeChromiumWin.cpp
@@ -35,7 +35,7 @@
#include "PlatformContextSkia.h"
#include "PlatformMouseEvent.h"
#include "Scrollbar.h"
-#include "WindowsVersion.h"
+#include "SystemInfo.h"
namespace WebCore {
@@ -70,7 +70,7 @@ int ScrollbarThemeChromiumWin::scrollbarThickness(ScrollbarControlSize controlSi
bool ScrollbarThemeChromiumWin::invalidateOnMouseEnterExit()
{
- return isVistaOrNewer();
+ return windowsVersion() >= WindowsVista;
}
bool ScrollbarThemeChromiumWin::shouldSnapBackToDragOrigin(Scrollbar* scrollbar, const PlatformMouseEvent& evt)
@@ -160,12 +160,12 @@ int ScrollbarThemeChromiumWin::getThemeState(Scrollbar* scrollbar, ScrollbarPart
if (scrollbar->pressedPart() == ThumbPart) {
if (part == ThumbPart)
return SCRBS_PRESSED;
- return isVistaOrNewer() ? SCRBS_HOVER : SCRBS_NORMAL;
+ return (windowsVersion() < WindowsVista) ? SCRBS_NORMAL : SCRBS_HOVER;
}
if (!scrollbar->enabled())
return SCRBS_DISABLED;
if (scrollbar->hoveredPart() != part || part == BackTrackPart || part == ForwardTrackPart)
- return (scrollbar->hoveredPart() == NoPart || !isVistaOrNewer()) ? SCRBS_NORMAL : SCRBS_HOVER;
+ return (scrollbar->hoveredPart() == NoPart || (windowsVersion() < WindowsVista)) ? SCRBS_NORMAL : SCRBS_HOVER;
if (scrollbar->pressedPart() == NoPart)
return SCRBS_HOT;
return (scrollbar->pressedPart() == part) ? SCRBS_PRESSED : SCRBS_NORMAL;
@@ -179,43 +179,43 @@ int ScrollbarThemeChromiumWin::getThemeArrowState(Scrollbar* scrollbar, Scrollba
if (part == BackButtonStartPart || part == ForwardButtonStartPart) {
if (scrollbar->orientation() == HorizontalScrollbar) {
if (scrollbar->pressedPart() == ThumbPart)
- return !isVistaOrNewer() ? ABS_LEFTNORMAL : ABS_LEFTHOVER;
+ return (windowsVersion() < WindowsVista) ? ABS_LEFTNORMAL : ABS_LEFTHOVER;
if (!scrollbar->enabled())
return ABS_LEFTDISABLED;
if (scrollbar->hoveredPart() != part)
- return ((scrollbar->hoveredPart() == NoPart) || !isVistaOrNewer()) ? ABS_LEFTNORMAL : ABS_LEFTHOVER;
+ return ((scrollbar->hoveredPart() == NoPart) || (windowsVersion() < WindowsVista)) ? ABS_LEFTNORMAL : ABS_LEFTHOVER;
if (scrollbar->pressedPart() == NoPart)
return ABS_LEFTHOT;
return (scrollbar->pressedPart() == part) ?
ABS_LEFTPRESSED : ABS_LEFTNORMAL;
}
if (scrollbar->pressedPart() == ThumbPart)
- return !isVistaOrNewer() ? ABS_UPNORMAL : ABS_UPHOVER;
+ return (windowsVersion() < WindowsVista) ? ABS_UPNORMAL : ABS_UPHOVER;
if (!scrollbar->enabled())
return ABS_UPDISABLED;
if (scrollbar->hoveredPart() != part)
- return ((scrollbar->hoveredPart() == NoPart) || !isVistaOrNewer()) ? ABS_UPNORMAL : ABS_UPHOVER;
+ return ((scrollbar->hoveredPart() == NoPart) || (windowsVersion() < WindowsVista)) ? ABS_UPNORMAL : ABS_UPHOVER;
if (scrollbar->pressedPart() == NoPart)
return ABS_UPHOT;
return (scrollbar->pressedPart() == part) ? ABS_UPPRESSED : ABS_UPNORMAL;
}
if (scrollbar->orientation() == HorizontalScrollbar) {
if (scrollbar->pressedPart() == ThumbPart)
- return !isVistaOrNewer() ? ABS_RIGHTNORMAL : ABS_RIGHTHOVER;
+ return (windowsVersion() < WindowsVista) ? ABS_RIGHTNORMAL : ABS_RIGHTHOVER;
if (!scrollbar->enabled())
return ABS_RIGHTDISABLED;
if (scrollbar->hoveredPart() != part)
- return ((scrollbar->hoveredPart() == NoPart) || !isVistaOrNewer()) ? ABS_RIGHTNORMAL : ABS_RIGHTHOVER;
+ return ((scrollbar->hoveredPart() == NoPart) || (windowsVersion() < WindowsVista)) ? ABS_RIGHTNORMAL : ABS_RIGHTHOVER;
if (scrollbar->pressedPart() == NoPart)
return ABS_RIGHTHOT;
return (scrollbar->pressedPart() == part) ? ABS_RIGHTPRESSED : ABS_RIGHTNORMAL;
}
if (scrollbar->pressedPart() == ThumbPart)
- return !isVistaOrNewer() ? ABS_DOWNNORMAL : ABS_DOWNHOVER;
+ return (windowsVersion() < WindowsVista) ? ABS_DOWNNORMAL : ABS_DOWNHOVER;
if (!scrollbar->enabled())
return ABS_DOWNDISABLED;
if (scrollbar->hoveredPart() != part)
- return ((scrollbar->hoveredPart() == NoPart) || !isVistaOrNewer()) ? ABS_DOWNNORMAL : ABS_DOWNHOVER;
+ return ((scrollbar->hoveredPart() == NoPart) || (windowsVersion() < WindowsVista)) ? ABS_DOWNNORMAL : ABS_DOWNHOVER;
if (scrollbar->pressedPart() == NoPart)
return ABS_DOWNHOT;
return (scrollbar->pressedPart() == part) ? ABS_DOWNPRESSED : ABS_DOWNNORMAL;
diff --git a/Source/WebCore/platform/chromium/TraceEvent.h b/Source/WebCore/platform/chromium/TraceEvent.h
new file mode 100644
index 0000000..9b92d58
--- /dev/null
+++ b/Source/WebCore/platform/chromium/TraceEvent.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef TraceEvent_h
+#define TraceEvent_h
+
+#include "PlatformBridge.h"
+
+// Implementation detail: trace event macros create temporary variables
+// to keep instrumentation overhead low. These macros give each temporary
+// variable a unique name based on the line number to prevent name collissions.
+#define TRACE_EVENT_MAKE_UNIQUE_IDENTIFIER3(a, b) a##b
+#define TRACE_EVENT_MAKE_UNIQUE_IDENTIFIER2(a, b) TRACE_EVENT_MAKE_UNIQUE_IDENTIFIER3(a, b)
+#define TRACE_EVENT_MAKE_UNIQUE_IDENTIFIER(name_prefix) TRACE_EVENT_MAKE_UNIQUE_IDENTIFIER2(name_prefix, __LINE__)
+
+// Issues PlatformBridge::traceEventBegin and traceEventEnd calls for the enclosing scope
+#define TRACE_EVENT(name, id, extra) WebCore::internal::ScopeTracer TRACE_EVENT_MAKE_UNIQUE_IDENTIFIER(__traceEventScope)(name, id, extra);
+
+namespace WebCore {
+
+namespace internal {
+
+// Used by TRACE_EVENT macro. Do not use directly.
+class ScopeTracer {
+public:
+ ScopeTracer(const char* name, void*, const char* extra);
+ ~ScopeTracer();
+
+private:
+ const char* m_name;
+ void* m_id;
+ OwnPtr<char*> m_extra;
+};
+
+inline ScopeTracer::ScopeTracer(const char* name, void* id, const char* extra)
+ : m_name(name)
+ , m_id(id)
+{
+ PlatformBridge::traceEventBegin(name, id, extra); \
+ if (extra)
+ m_extra = adoptPtr(strdup(extra));
+}
+
+inline ScopeTracer::~ScopeTracer()
+{
+ PlatformBridge::traceEventEnd(m_name, m_id, m_extra.get());
+}
+
+} // namespace internal
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/platform/chromium/WindowsVersion.cpp b/Source/WebCore/platform/chromium/WindowsVersion.cpp
deleted file mode 100644
index a9632cb..0000000
--- a/Source/WebCore/platform/chromium/WindowsVersion.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2008, 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 "WindowsVersion.h"
-
-#include <windows.h>
-
-namespace WebCore {
-
-bool isVistaOrNewer()
-{
- // Cache the result to avoid asking every time.
- static bool haveResult = false;
- static bool result = false;
- if (!haveResult) {
- OSVERSIONINFO versionInfo;
- versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
- GetVersionEx(&versionInfo);
-
- haveResult = true;
- result = versionInfo.dwMajorVersion >= 6;
- }
- return result;
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/efl/ContextMenuEfl.cpp b/Source/WebCore/platform/efl/ContextMenuEfl.cpp
index a5c6524..45d1758 100644
--- a/Source/WebCore/platform/efl/ContextMenuEfl.cpp
+++ b/Source/WebCore/platform/efl/ContextMenuEfl.cpp
@@ -2,7 +2,7 @@
* Copyright (C) 2007 Holger Hans Peter Freyther
* Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia
* Copyright (C) 2009-2010 ProFUSION embedded systems
- * Copyright (C) 2009-2010 Samsung Electronics
+ * Copyright (C) 2011 Samsung Electronics
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -26,16 +26,12 @@
namespace WebCore {
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
ContextMenu::ContextMenu(void* menu)
{
getContextMenuItems(menu, m_items);
}
-ContextMenu::ContextMenu()
-{
- notImplemented();
-}
-
void ContextMenu::getContextMenuItems(void* menu, Vector<ContextMenuItem>& items)
{
notImplemented();
@@ -51,5 +47,11 @@ void* ContextMenu::nativeMenu() const
{
return createNativeMenuFromItems(m_items);
}
+#else
+ContextMenu::ContextMenu()
+{
+ notImplemented();
+}
+#endif
}
diff --git a/Source/WebCore/platform/efl/ContextMenuItemEfl.cpp b/Source/WebCore/platform/efl/ContextMenuItemEfl.cpp
index 5ce8fab..425c6a6 100644
--- a/Source/WebCore/platform/efl/ContextMenuItemEfl.cpp
+++ b/Source/WebCore/platform/efl/ContextMenuItemEfl.cpp
@@ -3,7 +3,7 @@
* Copyright (C) 2007 Staikos Computing Services Inc. <info@staikos.net>
* Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia
* Copyright (C) 2009-2010 ProFUSION embedded systems
- * Copyright (C) 2009-2010 Samsung Electronics
+ * Copyright (C) 2011 Samsung Electronics
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,11 +34,13 @@
namespace WebCore {
-ContextMenuItem::ContextMenuItem(void* const&)
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+void* ContextMenuItem::nativeMenuItem() const
{
notImplemented();
+ return 0;
}
-
+#else
ContextMenuItem::ContextMenuItem(ContextMenuItemType, ContextMenuAction, const String&, ContextMenu*)
{
notImplemented();
@@ -49,12 +51,6 @@ ContextMenuItem::~ContextMenuItem()
notImplemented();
}
-void* ContextMenuItem::nativeMenuItem() const
-{
- notImplemented();
- return 0;
-}
-
ContextMenuItemType ContextMenuItem::type() const
{
notImplemented();
@@ -98,5 +94,5 @@ void ContextMenuItem::setSubMenu(ContextMenu*)
{
notImplemented();
}
-
+#endif
}
diff --git a/Source/WebCore/platform/efl/FileSystemEfl.cpp b/Source/WebCore/platform/efl/FileSystemEfl.cpp
index cb117bc..01c6c67 100644
--- a/Source/WebCore/platform/efl/FileSystemEfl.cpp
+++ b/Source/WebCore/platform/efl/FileSystemEfl.cpp
@@ -67,7 +67,7 @@ CString fileSystemRepresentation(const String& path)
#endif
}
-CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
+String openTemporaryFile(const String& prefix, PlatformFileHandle& handle)
{
char buffer[PATH_MAX];
const char* tmpDir = getenv("TMPDIR");
@@ -75,18 +75,18 @@ CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
if (!tmpDir)
tmpDir = "/tmp";
- if (snprintf(buffer, PATH_MAX, "%s/%sXXXXXX", tmpDir, prefix) >= PATH_MAX)
+ if (snprintf(buffer, PATH_MAX, "%s/%sXXXXXX", tmpDir, prefix.utf8().data()) >= PATH_MAX)
goto end;
handle = mkstemp(buffer);
if (handle < 0)
goto end;
- return CString(buffer);
+ return String::fromUTF8(buffer);
end:
handle = invalidPlatformFileHandle;
- return CString();
+ return String();
}
bool unloadModule(PlatformModule module)
diff --git a/Source/WebCore/platform/efl/GeolocationServiceEfl.cpp b/Source/WebCore/platform/efl/GeolocationServiceEfl.cpp
new file mode 100644
index 0000000..0c0e744
--- /dev/null
+++ b/Source/WebCore/platform/efl/GeolocationServiceEfl.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2008 Holger Hans Peter Freyther
+ * Copyright (C) 2011 Samsung Electronics
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "GeolocationServiceEfl.h"
+
+#if ENABLE(GEOLOCATION)
+#include "NotImplemented.h"
+#include "PositionOptions.h"
+#include <wtf/text/CString.h>
+
+namespace WebCore {
+
+GeolocationService::FactoryFunction* GeolocationService::s_factoryFunction = &GeolocationServiceEfl::create;
+
+GeolocationService* GeolocationServiceEfl::create(GeolocationServiceClient* client)
+{
+ return new GeolocationServiceEfl(client);
+}
+
+GeolocationServiceEfl::GeolocationServiceEfl(GeolocationServiceClient* client)
+ : GeolocationService(client)
+{
+}
+
+GeolocationServiceEfl::~GeolocationServiceEfl()
+{
+ notImplemented();
+}
+
+bool GeolocationServiceEfl::startUpdating(PositionOptions* options)
+{
+ notImplemented();
+ return false;
+}
+
+void GeolocationServiceEfl::stopUpdating()
+{
+ notImplemented();
+}
+
+void GeolocationServiceEfl::suspend()
+{
+ notImplemented();
+}
+
+void GeolocationServiceEfl::resume()
+{
+ notImplemented();
+}
+
+Geoposition* GeolocationServiceEfl::lastPosition() const
+{
+ return m_lastPosition.get();
+}
+
+PositionError* GeolocationServiceEfl::lastError() const
+{
+ return m_lastError.get();
+}
+
+}
+#endif // ENABLE(GEOLOCATION)
diff --git a/Source/WebCore/platform/efl/GeolocationServiceEfl.h b/Source/WebCore/platform/efl/GeolocationServiceEfl.h
new file mode 100644
index 0000000..e7ac66c
--- /dev/null
+++ b/Source/WebCore/platform/efl/GeolocationServiceEfl.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2008 Holger Hans Peter Freyther
+ * Copyright (C) 2011 Samsung Electronics
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef GeolocationServiceEfl_h
+#define GeolocationServiceEfl_h
+
+#if ENABLE(GEOLOCATION)
+#include "GeolocationService.h"
+#include "Geoposition.h"
+#include "PositionError.h"
+#include "RefPtr.h"
+
+namespace WebCore {
+
+class GeolocationServiceEfl : public GeolocationService {
+public:
+ static GeolocationService* create(GeolocationServiceClient*);
+ ~GeolocationServiceEfl();
+
+ virtual bool startUpdating(PositionOptions*);
+ virtual void stopUpdating();
+
+ virtual void suspend();
+ virtual void resume();
+
+ virtual Geoposition* lastPosition() const;
+ virtual PositionError* lastError() const;
+
+private:
+ GeolocationServiceEfl(GeolocationServiceClient*);
+
+ RefPtr<Geoposition> m_lastPosition;
+ RefPtr<PositionError> m_lastError;
+
+};
+
+}
+#endif // ENABLE(GEOLOCATION)
+#endif
diff --git a/Source/WebCore/platform/efl/LocalizedStringsEfl.cpp b/Source/WebCore/platform/efl/LocalizedStringsEfl.cpp
index 7e852f4..36a9f01 100644
--- a/Source/WebCore/platform/efl/LocalizedStringsEfl.cpp
+++ b/Source/WebCore/platform/efl/LocalizedStringsEfl.cpp
@@ -241,7 +241,7 @@ String contextMenuItemTagSearchWeb()
return String::fromUTF8("Search the Web");
}
-String contextMenuItemTagLookUpInDictionary()
+String contextMenuItemTagLookUpInDictionary(const String&)
{
return String::fromUTF8("Look Up in Dictionary");
}
diff --git a/Source/WebCore/platform/efl/PlatformKeyboardEventEfl.cpp b/Source/WebCore/platform/efl/PlatformKeyboardEventEfl.cpp
index 2888b22..10121df 100644
--- a/Source/WebCore/platform/efl/PlatformKeyboardEventEfl.cpp
+++ b/Source/WebCore/platform/efl/PlatformKeyboardEventEfl.cpp
@@ -188,15 +188,15 @@ static int windowsKeyCodeForEvasKeyName(String& keyName)
return 0;
}
-PlatformKeyboardEvent::PlatformKeyboardEvent(const Evas_Event_Key_Down* ev)
+PlatformKeyboardEvent::PlatformKeyboardEvent(const Evas_Event_Key_Down* event)
: m_type(KeyDown)
- , m_text(String::fromUTF8(ev->string))
- , m_shiftKey(evas_key_modifier_is_set(ev->modifiers, "Shift"))
- , m_ctrlKey(evas_key_modifier_is_set(ev->modifiers, "Control"))
- , m_altKey(evas_key_modifier_is_set(ev->modifiers, "Alt"))
- , m_metaKey(evas_key_modifier_is_set(ev->modifiers, "Meta"))
+ , m_text(String::fromUTF8(event->string))
+ , m_shiftKey(evas_key_modifier_is_set(event->modifiers, "Shift"))
+ , m_ctrlKey(evas_key_modifier_is_set(event->modifiers, "Control"))
+ , m_altKey(evas_key_modifier_is_set(event->modifiers, "Alt"))
+ , m_metaKey(evas_key_modifier_is_set(event->modifiers, "Meta"))
{
- String keyName = String(ev->key);
+ String keyName = String(event->key);
m_keyIdentifier = keyIdentifierForEvasKeyName(keyName);
m_windowsVirtualKeyCode = windowsKeyCodeForEvasKeyName(keyName);
@@ -205,15 +205,15 @@ PlatformKeyboardEvent::PlatformKeyboardEvent(const Evas_Event_Key_Down* ev)
m_autoRepeat = false;
}
-PlatformKeyboardEvent::PlatformKeyboardEvent(const Evas_Event_Key_Up* ev)
+PlatformKeyboardEvent::PlatformKeyboardEvent(const Evas_Event_Key_Up* event)
: m_type(KeyUp)
- , m_text(String::fromUTF8(ev->string))
- , m_shiftKey(evas_key_modifier_is_set(ev->modifiers, "Shift"))
- , m_ctrlKey(evas_key_modifier_is_set(ev->modifiers, "Control"))
- , m_altKey(evas_key_modifier_is_set(ev->modifiers, "Alt"))
- , m_metaKey(evas_key_modifier_is_set(ev->modifiers, "Meta"))
+ , m_text(String::fromUTF8(event->string))
+ , m_shiftKey(evas_key_modifier_is_set(event->modifiers, "Shift"))
+ , m_ctrlKey(evas_key_modifier_is_set(event->modifiers, "Control"))
+ , m_altKey(evas_key_modifier_is_set(event->modifiers, "Alt"))
+ , m_metaKey(evas_key_modifier_is_set(event->modifiers, "Meta"))
{
- String keyName = String(ev->key);
+ String keyName = String(event->key);
m_keyIdentifier = keyIdentifierForEvasKeyName(keyName);
m_windowsVirtualKeyCode = windowsKeyCodeForEvasKeyName(keyName);
diff --git a/Source/WebCore/platform/efl/PlatformMouseEventEfl.cpp b/Source/WebCore/platform/efl/PlatformMouseEventEfl.cpp
index 53de522..172b493 100644
--- a/Source/WebCore/platform/efl/PlatformMouseEventEfl.cpp
+++ b/Source/WebCore/platform/efl/PlatformMouseEventEfl.cpp
@@ -47,44 +47,44 @@ void PlatformMouseEvent::setClickCount(unsigned int flags)
m_clickCount = 1;
}
-PlatformMouseEvent::PlatformMouseEvent(const Evas_Event_Mouse_Down* ev, IntPoint pos)
- : m_position(IntPoint(ev->canvas.x - pos.x(), ev->canvas.y - pos.y()))
- , m_globalPosition(IntPoint(ev->canvas.x, ev->canvas.y))
- , m_button(MouseButton(ev->button - 1))
+PlatformMouseEvent::PlatformMouseEvent(const Evas_Event_Mouse_Down* event, IntPoint position)
+ : m_position(IntPoint(event->canvas.x - position.x(), event->canvas.y - position.y()))
+ , m_globalPosition(IntPoint(event->canvas.x, event->canvas.y))
+ , m_button(MouseButton(event->button - 1))
, m_eventType(MouseEventPressed)
- , m_shiftKey(evas_key_modifier_is_set(ev->modifiers, "Shift"))
- , m_ctrlKey(evas_key_modifier_is_set(ev->modifiers, "Control"))
- , m_altKey(evas_key_modifier_is_set(ev->modifiers, "Alt"))
- , m_metaKey(evas_key_modifier_is_set(ev->modifiers, "Meta"))
+ , m_shiftKey(evas_key_modifier_is_set(event->modifiers, "Shift"))
+ , m_ctrlKey(evas_key_modifier_is_set(event->modifiers, "Control"))
+ , m_altKey(evas_key_modifier_is_set(event->modifiers, "Alt"))
+ , m_metaKey(evas_key_modifier_is_set(event->modifiers, "Meta"))
, m_timestamp(currentTime())
{
- setClickCount(ev->flags);
+ setClickCount(event->flags);
}
-PlatformMouseEvent::PlatformMouseEvent(const Evas_Event_Mouse_Up* ev, IntPoint pos)
- : m_position(IntPoint(ev->canvas.x - pos.x(), ev->canvas.y - pos.y()))
- , m_globalPosition(IntPoint(ev->canvas.x, ev->canvas.y))
- , m_button(MouseButton(ev->button - 1))
+PlatformMouseEvent::PlatformMouseEvent(const Evas_Event_Mouse_Up* event, IntPoint position)
+ : m_position(IntPoint(event->canvas.x - position.x(), event->canvas.y - position.y()))
+ , m_globalPosition(IntPoint(event->canvas.x, event->canvas.y))
+ , m_button(MouseButton(event->button - 1))
, m_eventType(MouseEventReleased)
- , m_shiftKey(evas_key_modifier_is_set(ev->modifiers, "Shift"))
- , m_ctrlKey(evas_key_modifier_is_set(ev->modifiers, "Control"))
- , m_altKey(evas_key_modifier_is_set(ev->modifiers, "Alt"))
- , m_metaKey(evas_key_modifier_is_set(ev->modifiers, "Meta"))
+ , m_shiftKey(evas_key_modifier_is_set(event->modifiers, "Shift"))
+ , m_ctrlKey(evas_key_modifier_is_set(event->modifiers, "Control"))
+ , m_altKey(evas_key_modifier_is_set(event->modifiers, "Alt"))
+ , m_metaKey(evas_key_modifier_is_set(event->modifiers, "Meta"))
, m_timestamp(currentTime())
{
- setClickCount(ev->flags);
+ setClickCount(event->flags);
}
-PlatformMouseEvent::PlatformMouseEvent(const Evas_Event_Mouse_Move* ev, IntPoint pos)
- : m_position(IntPoint(ev->cur.canvas.x - pos.x(), ev->cur.canvas.y - pos.y()))
- , m_globalPosition(IntPoint(ev->cur.canvas.x, ev->cur.canvas.y))
- , m_button(MouseButton(ev->buttons - 1))
+PlatformMouseEvent::PlatformMouseEvent(const Evas_Event_Mouse_Move* event, IntPoint position)
+ : m_position(IntPoint(event->cur.canvas.x - position.x(), event->cur.canvas.y - position.y()))
+ , m_globalPosition(IntPoint(event->cur.canvas.x, event->cur.canvas.y))
+ , m_button(MouseButton(event->buttons - 1))
, m_eventType(MouseEventMoved)
, m_clickCount(0)
- , m_shiftKey(evas_key_modifier_is_set(ev->modifiers, "Shift"))
- , m_ctrlKey(evas_key_modifier_is_set(ev->modifiers, "Control"))
- , m_altKey(evas_key_modifier_is_set(ev->modifiers, "Alt"))
- , m_metaKey(evas_key_modifier_is_set(ev->modifiers, "Meta"))
+ , m_shiftKey(evas_key_modifier_is_set(event->modifiers, "Shift"))
+ , m_ctrlKey(evas_key_modifier_is_set(event->modifiers, "Control"))
+ , m_altKey(evas_key_modifier_is_set(event->modifiers, "Alt"))
+ , m_metaKey(evas_key_modifier_is_set(event->modifiers, "Meta"))
, m_timestamp(currentTime())
{
}
diff --git a/Source/WebCore/platform/efl/RenderThemeEfl.cpp b/Source/WebCore/platform/efl/RenderThemeEfl.cpp
index 3e8a646..439e377 100644
--- a/Source/WebCore/platform/efl/RenderThemeEfl.cpp
+++ b/Source/WebCore/platform/efl/RenderThemeEfl.cpp
@@ -38,11 +38,21 @@
#include "RenderObject.h"
#include "RenderProgress.h"
#include "RenderSlider.h"
+#include "UserAgentStyleSheets.h"
#include <wtf/text/CString.h>
#include <Ecore_Evas.h>
#include <Edje.h>
+
+#if ENABLE(VIDEO)
+#include "HTMLMediaElement.h"
+#include "HTMLNames.h"
+#endif
+
namespace WebCore {
+#if ENABLE(VIDEO)
+using namespace HTMLNames;
+#endif
// TODO: change from object count to ecore_evas size (bytes)
// TODO: as objects are webpage/user defined and they can be very large.
@@ -273,7 +283,7 @@ bool RenderThemeEfl::paintThemePart(RenderObject* object, FormType type, const P
applyEdjeStateFromForm(entry->o, controlStatesForRenderer(object));
- cairo = info.context->platformContext();
+ cairo = info.context->platformContext()->cr();
ASSERT(cairo);
// Currently, only sliders needs this message; if other widget ever needs special
@@ -592,6 +602,10 @@ const char* RenderThemeEfl::edjeGroupFromFormType(FormType type) const
W("search/cancel_button"),
W("slider/vertical"),
W("slider/horizontal"),
+#if ENABLE(VIDEO)
+ W("mediacontrol/playpause_button"),
+ W("mediacontrol/mute_button"),
+#endif
#undef W
0
};
@@ -1044,10 +1058,32 @@ bool RenderThemeEfl::paintProgressBar(RenderObject* object, const PaintInfo& inf
#endif
#if ENABLE(VIDEO)
+bool RenderThemeEfl::emitMediaButtonSignal(FormType formType, MediaControlElementType mediaElementType, const IntRect& rect)
+{
+ ThemePartCacheEntry* entry;
+
+ entry = cacheThemePartGet(formType, rect.size());
+ ASSERT(entry);
+ if (!entry)
+ return false;
+
+ if (mediaElementType == MediaPlayButton)
+ edje_object_signal_emit(entry->o, "play", "");
+ else if (mediaElementType == MediaPauseButton)
+ edje_object_signal_emit(entry->o, "pause", "");
+ else if (mediaElementType == MediaMuteButton)
+ edje_object_signal_emit(entry->o, "mute", "");
+ else if (mediaElementType == MediaUnMuteButton)
+ edje_object_signal_emit(entry->o, "sound", "");
+ else
+ return false;
+
+ return true;
+}
+
String RenderThemeEfl::extraMediaControlsStyleSheet()
{
- notImplemented();
- return String();
+ return String(mediaControlsEflUserAgentStyleSheet, sizeof(mediaControlsEflUserAgentStyleSheet));
}
String RenderThemeEfl::formatMediaControlsCurrentTime(float currentTime, float duration) const
@@ -1064,14 +1100,29 @@ bool RenderThemeEfl::paintMediaFullscreenButton(RenderObject* object, const Pain
bool RenderThemeEfl::paintMediaMuteButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
{
- notImplemented();
- return false;
+ Node* mediaNode = object->node() ? object->node()->shadowAncestorNode() : 0;
+ if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
+ return false;
+
+ HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
+
+ if (!emitMediaButtonSignal(MediaMuteUnMuteButton, mediaElement->muted() ? MediaMuteButton : MediaUnMuteButton, rect))
+ return false;
+
+ return paintThemePart(object, MediaMuteUnMuteButton, info, rect);
}
bool RenderThemeEfl::paintMediaPlayButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
{
- notImplemented();
- return false;
+ Node* node = object->node();
+ if (!node)
+ return false;
+
+ MediaControlPlayButtonElement* button = static_cast<MediaControlPlayButtonElement*>(node);
+ if (!emitMediaButtonSignal(MediaPlayPauseButton, button->displayType(), rect))
+ return false;
+
+ return paintThemePart(object, MediaPlayPauseButton, info, rect);
}
bool RenderThemeEfl::paintMediaSeekBackButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
diff --git a/Source/WebCore/platform/efl/RenderThemeEfl.h b/Source/WebCore/platform/efl/RenderThemeEfl.h
index 9970096..fe8e2d2 100644
--- a/Source/WebCore/platform/efl/RenderThemeEfl.h
+++ b/Source/WebCore/platform/efl/RenderThemeEfl.h
@@ -30,6 +30,9 @@
#ifndef RenderThemeEfl_h
#define RenderThemeEfl_h
+#if ENABLE(VIDEO)
+#include "MediaControlElements.h"
+#endif
#include "RenderTheme.h"
#include <cairo.h>
@@ -55,6 +58,10 @@ enum FormType { // KEEP IN SYNC WITH edjeGroupFromFormType()
SearchFieldCancelButton,
SliderVertical,
SliderHorizontal,
+#if ENABLE(VIDEO)
+ MediaPlayPauseButton,
+ MediaMuteUnMuteButton,
+#endif
FormTypeLast
};
@@ -182,6 +189,10 @@ private:
void applyEdjeStateFromForm(Evas_Object*, ControlStates);
bool paintThemePart(RenderObject*, FormType, const PaintInfo&, const IntRect&);
+#if ENABLE(VIDEO)
+ bool emitMediaButtonSignal(FormType, MediaControlElementType, const IntRect&);
+#endif
+
Page* m_page;
Color m_activeSelectionBackgroundColor;
Color m_activeSelectionForegroundColor;
diff --git a/Source/WebCore/platform/efl/ScrollbarEfl.cpp b/Source/WebCore/platform/efl/ScrollbarEfl.cpp
index e71d1e3..162c2a1 100644
--- a/Source/WebCore/platform/efl/ScrollbarEfl.cpp
+++ b/Source/WebCore/platform/efl/ScrollbarEfl.cpp
@@ -64,50 +64,50 @@ ScrollbarEfl::~ScrollbarEfl()
setEvasObject(0);
}
-static void scrollbarEflEdjeMessage(void* data, Evas_Object* o, Edje_Message_Type type, int id, void* msg)
+static void scrollbarEflEdjeMessage(void* data, Evas_Object* object, Edje_Message_Type messageType, int id, void* message)
{
ScrollbarEfl* that = static_cast<ScrollbarEfl*>(data);
- Edje_Message_Float* m;
- int v;
+ Edje_Message_Float* messageFloat;
+ int value;
if (!id) {
EINA_LOG_ERR("Unknown message id '%d' from scroll bar theme.", id);
return;
}
- if (type != EDJE_MESSAGE_FLOAT) {
+ if (messageType != EDJE_MESSAGE_FLOAT) {
EINA_LOG_ERR("Message id '%d' of incorrect type from scroll bar theme. "
"Expected '%d', got '%d'.",
- id, EDJE_MESSAGE_FLOAT, type);
+ id, EDJE_MESSAGE_FLOAT, messageType);
return;
}
- m = static_cast<Edje_Message_Float*>(msg);
- v = m->val * (that->totalSize() - that->visibleSize());
- that->scrollableArea()->scrollToOffsetWithoutAnimation(that->orientation(), v);
+ messageFloat = static_cast<Edje_Message_Float*>(message);
+ value = messageFloat->val * (that->totalSize() - that->visibleSize());
+ that->scrollableArea()->scrollToOffsetWithoutAnimation(that->orientation(), value);
}
void ScrollbarEfl::setParent(ScrollView* view)
{
- Evas_Object* o = evasObject();
+ Evas_Object* object = evasObject();
Evas_Coord w, h;
Widget::setParent(view);
- if (!o) {
+ if (!object) {
if (!view)
return;
- o = edje_object_add(view->evas());
- if (!o) {
+ object = edje_object_add(view->evas());
+ if (!object) {
EINA_LOG_ERR("Could not create edje object for view=%p (evas=%p)",
view, view->evas());
return;
}
- edje_object_message_handler_set(o, scrollbarEflEdjeMessage, this);
- setEvasObject(o);
+ edje_object_message_handler_set(object, scrollbarEflEdjeMessage, this);
+ setEvasObject(object);
} else if (!view) {
- evas_object_hide(o);
+ evas_object_hide(object);
return;
}
@@ -117,23 +117,23 @@ void ScrollbarEfl::setParent(ScrollView* view)
if (theme.isEmpty()) {
EINA_LOG_ERR("Could not load theme '%s': no theme path set.", group);
- evas_object_hide(o);
+ evas_object_hide(object);
return;
}
- if (!edje_object_file_set(o, theme.utf8().data(), group)) {
- Edje_Load_Error err = edje_object_load_error_get(o);
- const char* errmsg = edje_load_error_str(err);
+ if (!edje_object_file_set(object, theme.utf8().data(), group)) {
+ Edje_Load_Error err = edje_object_load_error_get(object);
+ const char* errmessage = edje_load_error_str(err);
EINA_LOG_ERR("Could not load theme '%s' from file '%s': #%d '%s'",
- group, theme.utf8().data(), err, errmsg);
+ group, theme.utf8().data(), err, errmessage);
return;
}
- setPlatformWidget(o);
- evas_object_smart_member_add(o, view->evasObject());
- evas_object_show(o);
+ setPlatformWidget(object);
+ evas_object_smart_member_add(object, view->evasObject());
+ evas_object_show(object);
- edje_object_size_min_get(o, &w, &h);
+ edje_object_size_min_get(object, &w, &h);
IntRect rect = frameRect();
rect.setSize(IntSize(w, h));
@@ -168,21 +168,21 @@ void ScrollbarEfl::updateThumbPositionAndProportion()
m_lastTotalSize = tSize;
m_lastVisibleSize = vSize;
- Edje_Message_Float_Set* msg = static_cast<Edje_Message_Float_Set*>
+ Edje_Message_Float_Set* message = static_cast<Edje_Message_Float_Set*>
(alloca(sizeof(Edje_Message_Float_Set) + sizeof(float)));
- msg->count = 2;
+ message->count = 2;
if (tSize - vSize > 0)
- msg->val[0] = pos / (float)(tSize - vSize);
+ message->val[0] = pos / static_cast<float>(tSize - vSize);
else
- msg->val[0] = 0.0;
+ message->val[0] = 0.0;
if (tSize > 0)
- msg->val[1] = vSize / (float)tSize;
+ message->val[1] = vSize / static_cast<float>(tSize);
else
- msg->val[1] = 0.0;
+ message->val[1] = 0.0;
- edje_object_message_send(platformWidget(), EDJE_MESSAGE_FLOAT_SET, 0, msg);
+ edje_object_message_send(platformWidget(), EDJE_MESSAGE_FLOAT_SET, 0, message);
}
void ScrollbarEfl::setFrameRect(const IntRect& rect)
@@ -193,10 +193,10 @@ void ScrollbarEfl::setFrameRect(const IntRect& rect)
void ScrollbarEfl::frameRectsChanged()
{
- Evas_Object* o = platformWidget();
+ Evas_Object* object = platformWidget();
Evas_Coord x, y;
- if (!parent() || !o)
+ if (!parent() || !object)
return;
IntRect rect = frameRect();
@@ -206,11 +206,11 @@ void ScrollbarEfl::frameRectsChanged()
rect.setLocation(parent()->contentsToWindow(rect.location()));
evas_object_geometry_get(root()->evasObject(), &x, &y, 0, 0);
- evas_object_move(o, x + rect.x(), y + rect.y());
- evas_object_resize(o, rect.width(), rect.height());
+ evas_object_move(object, x + rect.x(), y + rect.y());
+ evas_object_resize(object, rect.width(), rect.height());
}
-void ScrollbarEfl::paint(GraphicsContext* context, const IntRect& rect)
+void ScrollbarEfl::paint(GraphicsContext* graphicsContext, const IntRect& damageRect)
{
}
diff --git a/Source/WebCore/platform/efl/ScrollbarEfl.h b/Source/WebCore/platform/efl/ScrollbarEfl.h
index 09dc64f..1f67d2f 100644
--- a/Source/WebCore/platform/efl/ScrollbarEfl.h
+++ b/Source/WebCore/platform/efl/ScrollbarEfl.h
@@ -49,7 +49,7 @@ public:
virtual void frameRectsChanged();
- virtual void paint(GraphicsContext* context, const IntRect& damageRect);
+ virtual void paint(GraphicsContext*, const IntRect&);
protected:
ScrollbarEfl(ScrollableArea*, ScrollbarOrientation, ScrollbarControlSize);
@@ -58,7 +58,7 @@ protected:
virtual void updateThumbPosition();
virtual void updateThumbProportion();
- virtual void setParent(ScrollView* view);
+ virtual void setParent(ScrollView*);
private:
int m_lastPos;
diff --git a/Source/WebCore/platform/efl/WidgetEfl.cpp b/Source/WebCore/platform/efl/WidgetEfl.cpp
index 640e6e3..45d4792 100644
--- a/Source/WebCore/platform/efl/WidgetEfl.cpp
+++ b/Source/WebCore/platform/efl/WidgetEfl.cpp
@@ -183,10 +183,10 @@ void Widget::setFrameRect(const IntRect& rect)
void Widget::frameRectsChanged()
{
- Evas_Object* o = evasObject();
+ Evas_Object* object = evasObject();
Evas_Coord x, y;
- if (!parent() || !o)
+ if (!parent() || !object)
return;
IntRect rect = frameRect();
@@ -196,8 +196,8 @@ void Widget::frameRectsChanged()
rect.setLocation(parent()->contentsToWindow(rect.location()));
evas_object_geometry_get(root()->evasObject(), &x, &y, 0, 0);
- evas_object_move(o, x + rect.x(), y + rect.y());
- evas_object_resize(o, rect.width(), rect.height());
+ evas_object_move(object, x + rect.x(), y + rect.y());
+ evas_object_resize(object, rect.width(), rect.height());
}
void Widget::setFocus(bool focused)
@@ -332,14 +332,14 @@ Ecore_Evas* Widget::ecoreEvas() const
return static_cast<Ecore_Evas*>(evas_data_attach_get(evas()));
}
-void Widget::setEvasObject(Evas_Object *o)
+void Widget::setEvasObject(Evas_Object *object)
{
// FIXME: study platformWidget() and use it
// FIXME: right now platformWidget() requires implementing too much
- if (m_data->m_evasObject == o)
+ if (m_data->m_evasObject == object)
return;
- m_data->m_evasObject = o;
- if (!o) {
+ m_data->m_evasObject = object;
+ if (!object) {
m_data->m_evas = 0;
#ifdef HAVE_ECORE_X
m_data->m_isUsingEcoreX = false;
@@ -347,7 +347,7 @@ void Widget::setEvasObject(Evas_Object *o)
return;
}
- m_data->m_evas = evas_object_evas_get(o);
+ m_data->m_evas = evas_object_evas_get(object);
#ifdef HAVE_ECORE_X
const char *engine = ecore_evas_engine_name_get(ecoreEvas());
diff --git a/Source/WebCore/platform/graphics/BitmapImage.h b/Source/WebCore/platform/graphics/BitmapImage.h
index 14a3094..c8cf0ab 100644
--- a/Source/WebCore/platform/graphics/BitmapImage.h
+++ b/Source/WebCore/platform/graphics/BitmapImage.h
@@ -165,7 +165,7 @@ protected:
enum RepetitionCountStatus {
Unknown, // We haven't checked the source's repetition count.
Uncertain, // We have a repetition count, but it might be wrong (some GIFs have a count after the image data, and will report "loop once" until all data has been decoded).
- Certain, // The repetition count is known to be correct.
+ Certain // The repetition count is known to be correct.
};
BitmapImage(NativeImagePtr, ImageObserver* = 0);
diff --git a/Source/WebCore/platform/graphics/Color.cpp b/Source/WebCore/platform/graphics/Color.cpp
index a1c5cd7..7dea765 100644
--- a/Source/WebCore/platform/graphics/Color.cpp
+++ b/Source/WebCore/platform/graphics/Color.cpp
@@ -27,13 +27,12 @@
#include "Color.h"
#include "HashTools.h"
-#include "PlatformString.h"
-#include <math.h>
#include <wtf/Assertions.h>
+#include <wtf/HexNumber.h>
#include <wtf/MathExtras.h>
+#include <wtf/text/StringBuilder.h>
using namespace std;
-using namespace WTF;
namespace WebCore {
@@ -180,14 +179,6 @@ Color::Color(const char* name)
}
}
-static inline void appendHexNumber(UChar* destination, uint8_t number)
-{
- static const char hexDigits[17] = "0123456789abcdef";
-
- destination[0] = hexDigits[number >> 4];
- destination[1] = hexDigits[number & 0xF];
-}
-
String Color::serialized() const
{
DEFINE_STATIC_LOCAL(const String, commaSpace, (", "));
@@ -195,13 +186,13 @@ String Color::serialized() const
DEFINE_STATIC_LOCAL(const String, zeroPointZero, ("0.0"));
if (!hasAlpha()) {
- UChar* characters;
- String result = String::createUninitialized(7, characters);
- characters[0] = '#';
- appendHexNumber(characters + 1, red());
- appendHexNumber(characters + 3, green());
- appendHexNumber(characters + 5, blue());
- return result;
+ StringBuilder builder;
+ builder.reserveCapacity(7);
+ builder.append('#');
+ appendByteAsHex(red(), builder, Lowercase);
+ appendByteAsHex(green(), builder, Lowercase);
+ appendByteAsHex(blue(), builder, Lowercase);
+ return builder.toString();
}
Vector<UChar> result;
diff --git a/Source/WebCore/platform/graphics/ContextShadow.h b/Source/WebCore/platform/graphics/ContextShadow.h
index c0571f0..850d489 100644
--- a/Source/WebCore/platform/graphics/ContextShadow.h
+++ b/Source/WebCore/platform/graphics/ContextShadow.h
@@ -32,7 +32,7 @@
#include "Color.h"
#include "FloatRect.h"
#include "IntRect.h"
-#include "RefCounted.h"
+#include <wtf/RefCounted.h>
#if PLATFORM(CAIRO)
typedef struct _cairo cairo_t;
diff --git a/Source/WebCore/platform/graphics/Font.cpp b/Source/WebCore/platform/graphics/Font.cpp
index ee85e45..72e3e3b 100644
--- a/Source/WebCore/platform/graphics/Font.cpp
+++ b/Source/WebCore/platform/graphics/Font.cpp
@@ -177,7 +177,7 @@ float Font::width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFo
// If the complex text implementation cannot return fallback fonts, avoid
// returning them for simple text as well.
static bool returnFallbackFonts = canReturnFallbackFontsForComplexText();
- return floatWidthForSimpleText(run, 0, returnFallbackFonts ? fallbackFonts : 0, codePathToUse == SimpleWithGlyphOverflow ? glyphOverflow : 0);
+ return floatWidthForSimpleText(run, 0, returnFallbackFonts ? fallbackFonts : 0, codePathToUse == SimpleWithGlyphOverflow || (glyphOverflow && glyphOverflow->computeBounds) ? glyphOverflow : 0);
}
return floatWidthForComplexText(run, fallbackFonts, glyphOverflow);
diff --git a/Source/WebCore/platform/graphics/Font.h b/Source/WebCore/platform/graphics/Font.h
index ce03aed..554f8a0 100644
--- a/Source/WebCore/platform/graphics/Font.h
+++ b/Source/WebCore/platform/graphics/Font.h
@@ -61,6 +61,7 @@ struct GlyphOverflow {
, right(0)
, top(0)
, bottom(0)
+ , computeBounds(false)
{
}
@@ -68,8 +69,10 @@ struct GlyphOverflow {
int right;
int top;
int bottom;
+ bool computeBounds;
};
+
class Font {
public:
Font();
@@ -138,8 +141,6 @@ public:
const FontData* fontDataAt(unsigned) const;
GlyphData glyphDataForCharacter(UChar32, bool mirror, FontDataVariant = AutoVariant) const;
bool primaryFontHasGlyphForCharacter(UChar32) const;
- // Used for complex text, and does not utilize the glyph map cache.
- const FontData* fontDataForCharacters(const UChar*, int length) const;
static bool isCJKIdeograph(UChar32);
static bool isCJKIdeographOrSymbol(UChar32);
@@ -255,12 +256,6 @@ inline const FontData* Font::fontDataAt(unsigned index) const
return m_fontList->fontDataAt(this, index);
}
-inline const FontData* Font::fontDataForCharacters(const UChar* characters, int length) const
-{
- ASSERT(m_fontList);
- return m_fontList->fontDataForCharacters(this, characters, length);
-}
-
inline bool Font::isFixedPitch() const
{
ASSERT(m_fontList);
diff --git a/Source/WebCore/platform/graphics/FontCache.cpp b/Source/WebCore/platform/graphics/FontCache.cpp
index 5b508be..8c5edfe 100644
--- a/Source/WebCore/platform/graphics/FontCache.cpp
+++ b/Source/WebCore/platform/graphics/FontCache.cpp
@@ -57,7 +57,8 @@ struct FontPlatformDataCacheKey {
WTF_MAKE_FAST_ALLOCATED;
public:
FontPlatformDataCacheKey(const AtomicString& family = AtomicString(), unsigned size = 0, unsigned weight = 0, bool italic = false,
- bool isPrinterFont = false, FontRenderingMode renderingMode = NormalRenderingMode, FontOrientation orientation = Horizontal, FontWidthVariant widthVariant = RegularWidth)
+ bool isPrinterFont = false, FontRenderingMode renderingMode = NormalRenderingMode, FontOrientation orientation = Horizontal,
+ TextOrientation textOrientation = TextOrientationVerticalRight, FontWidthVariant widthVariant = RegularWidth)
: m_size(size)
, m_weight(weight)
, m_family(family)
@@ -65,6 +66,7 @@ public:
, m_printerFont(isPrinterFont)
, m_renderingMode(renderingMode)
, m_orientation(orientation)
+ , m_textOrientation(textOrientation)
, m_widthVariant(widthVariant)
{
}
@@ -76,7 +78,7 @@ public:
{
return equalIgnoringCase(m_family, other.m_family) && m_size == other.m_size &&
m_weight == other.m_weight && m_italic == other.m_italic && m_printerFont == other.m_printerFont &&
- m_renderingMode == other.m_renderingMode && m_orientation == other.m_orientation && m_widthVariant == other.m_widthVariant;
+ m_renderingMode == other.m_renderingMode && m_orientation == other.m_orientation && m_textOrientation == other.m_textOrientation && m_widthVariant == other.m_widthVariant;
}
unsigned m_size;
@@ -86,6 +88,7 @@ public:
bool m_printerFont;
FontRenderingMode m_renderingMode;
FontOrientation m_orientation;
+ TextOrientation m_textOrientation;
FontWidthVariant m_widthVariant;
private:
@@ -99,9 +102,9 @@ inline unsigned computeHash(const FontPlatformDataCacheKey& fontKey)
fontKey.m_size,
fontKey.m_weight,
fontKey.m_widthVariant,
- static_cast<unsigned>(fontKey.m_orientation) << 3 | static_cast<unsigned>(fontKey.m_italic) << 2 | static_cast<unsigned>(fontKey.m_printerFont) << 1 | static_cast<unsigned>(fontKey.m_renderingMode)
+ static_cast<unsigned>(fontKey.m_textOrientation) << 4 | static_cast<unsigned>(fontKey.m_orientation) << 3 | static_cast<unsigned>(fontKey.m_italic) << 2 | static_cast<unsigned>(fontKey.m_printerFont) << 1 | static_cast<unsigned>(fontKey.m_renderingMode)
};
- return WTF::StringHasher::createBlobHash<sizeof(hashCodes)>(hashCodes);
+ return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
}
struct FontPlatformDataCacheKeyHash {
@@ -198,7 +201,8 @@ FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fo
}
FontPlatformDataCacheKey key(familyName, fontDescription.computedPixelSize(), fontDescription.weight(), fontDescription.italic(),
- fontDescription.usePrinterFont(), fontDescription.renderingMode(), fontDescription.orientation(), fontDescription.widthVariant());
+ fontDescription.usePrinterFont(), fontDescription.renderingMode(), fontDescription.orientation(),
+ fontDescription.textOrientation(), fontDescription.widthVariant());
FontPlatformData* result = 0;
bool foundResult;
FontPlatformDataCache::iterator it = gFontPlatformDataCache->find(key);
diff --git a/Source/WebCore/platform/graphics/FontDescription.h b/Source/WebCore/platform/graphics/FontDescription.h
index 283d297..5b05f14 100644
--- a/Source/WebCore/platform/graphics/FontDescription.h
+++ b/Source/WebCore/platform/graphics/FontDescription.h
@@ -31,6 +31,7 @@
#include "FontSmoothingMode.h"
#include "FontTraitsMask.h"
#include "FontWidthVariant.h"
+#include "TextOrientation.h"
#include "TextRenderingMode.h"
namespace WebCore {
@@ -58,6 +59,7 @@ public:
: m_specifiedSize(0)
, m_computedSize(0)
, m_orientation(Horizontal)
+ , m_textOrientation(TextOrientationVerticalRight)
, m_widthVariant(RegularWidth)
, m_italic(false)
, m_smallCaps(false)
@@ -99,6 +101,7 @@ public:
FontTraitsMask traitsMask() const;
bool isSpecifiedFont() const { return m_isSpecifiedFont; }
FontOrientation orientation() const { return m_orientation; }
+ TextOrientation textOrientation() const { return m_textOrientation; }
FontWidthVariant widthVariant() const { return m_widthVariant; }
void setFamily(const FontFamily& family) { m_familyList = family; }
@@ -120,6 +123,7 @@ public:
void setTextRenderingMode(TextRenderingMode rendering) { m_textRendering = rendering; }
void setIsSpecifiedFont(bool isSpecifiedFont) { m_isSpecifiedFont = isSpecifiedFont; }
void setOrientation(FontOrientation orientation) { m_orientation = orientation; }
+ void setTextOrientation(TextOrientation textOrientation) { m_textOrientation = textOrientation; }
void setWidthVariant(FontWidthVariant widthVariant) { m_widthVariant = widthVariant; }
private:
@@ -129,8 +133,9 @@ private:
// rounding, minimum font sizes, and zooming.
float m_computedSize; // Computed size adjusted for the minimum font size and the zoom factor.
- FontOrientation m_orientation;
-
+ FontOrientation m_orientation; // Whether the font is rendering on a horizontal line or a vertical line.
+ TextOrientation m_textOrientation; // Only used by vertical text. Determines the default orientation for non-ideograph glyphs.
+
FontWidthVariant m_widthVariant;
bool m_italic : 1;
@@ -169,6 +174,7 @@ inline bool FontDescription::operator==(const FontDescription& other) const
&& m_textRendering == other.m_textRendering
&& m_isSpecifiedFont == other.m_isSpecifiedFont
&& m_orientation == other.m_orientation
+ && m_textOrientation == other.m_textOrientation
&& m_widthVariant == other.m_widthVariant;
}
diff --git a/Source/WebCore/platform/graphics/FontFallbackList.cpp b/Source/WebCore/platform/graphics/FontFallbackList.cpp
index 649c117..7df58d9 100644
--- a/Source/WebCore/platform/graphics/FontFallbackList.cpp
+++ b/Source/WebCore/platform/graphics/FontFallbackList.cpp
@@ -111,23 +111,6 @@ const FontData* FontFallbackList::fontDataAt(const Font* font, unsigned realized
return result;
}
-const FontData* FontFallbackList::fontDataForCharacters(const Font* font, const UChar* characters, int length) const
-{
- // This method is only called when the primary font does not contain the characters we need.
- // Begin our search at position 1.
- unsigned realizedFontIndex = 1;
- const FontData* fontData = fontDataAt(font, realizedFontIndex);
- while (fontData && !fontData->containsCharacters(characters, length))
- fontData = fontDataAt(font, ++realizedFontIndex);
-
- if (!fontData) {
- ASSERT(fontCache()->generation() == m_generation);
- fontData = fontCache()->getFontDataForCharacters(*font, characters, length);
- }
-
- return fontData;
-}
-
void FontFallbackList::setPlatformFont(const FontPlatformData& platformData)
{
m_familyIndex = cAllFamiliesScanned;
diff --git a/Source/WebCore/platform/graphics/FontFallbackList.h b/Source/WebCore/platform/graphics/FontFallbackList.h
index a10f5af..e18477c 100644
--- a/Source/WebCore/platform/graphics/FontFallbackList.h
+++ b/Source/WebCore/platform/graphics/FontFallbackList.h
@@ -65,8 +65,7 @@ private:
const FontData* primaryFontData(const Font* f) const { return fontDataAt(f, 0); }
const FontData* fontDataAt(const Font*, unsigned index) const;
- const FontData* fontDataForCharacters(const Font*, const UChar*, int length) const;
-
+
void setPlatformFont(const FontPlatformData&);
void releaseFontData();
diff --git a/Source/WebCore/platform/graphics/FontFastPath.cpp b/Source/WebCore/platform/graphics/FontFastPath.cpp
index e62df61..b741ca0 100644
--- a/Source/WebCore/platform/graphics/FontFastPath.cpp
+++ b/Source/WebCore/platform/graphics/FontFastPath.cpp
@@ -77,17 +77,57 @@ GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, FontDataVariant va
page = node->page();
if (page) {
GlyphData data = page->glyphDataForCharacter(c);
+ if (data.fontData && (data.fontData->platformData().orientation() == Horizontal || data.fontData->isTextOrientationFallback()))
+ return data;
+
if (data.fontData) {
- if (data.fontData->platformData().orientation() == Vertical && data.fontData->orientation() == Horizontal && Font::isCJKIdeographOrSymbol(c)) {
- const SimpleFontData* ideographFontData = data.fontData->brokenIdeographFontData();
- GlyphPageTreeNode* ideographNode = GlyphPageTreeNode::getRootChild(ideographFontData, pageNumber);
- const GlyphPage* ideographPage = ideographNode->page();
- if (ideographPage) {
- GlyphData data = ideographPage->glyphDataForCharacter(c);
- if (data.fontData)
- return data;
+ if (isCJKIdeographOrSymbol(c)) {
+ if (!data.fontData->hasVerticalGlyphs()) {
+ // Use the broken ideograph font data. The broken ideograph font will use the horizontal width of glyphs
+ // to make sure you get a square (even for broken glyphs like symbols used for punctuation).
+ const SimpleFontData* brokenIdeographFontData = data.fontData->brokenIdeographFontData();
+ GlyphPageTreeNode* brokenIdeographNode = GlyphPageTreeNode::getRootChild(brokenIdeographFontData, pageNumber);
+ const GlyphPage* brokenIdeographPage = brokenIdeographNode->page();
+ if (brokenIdeographPage) {
+ GlyphData brokenIdeographData = brokenIdeographPage->glyphDataForCharacter(c);
+ if (brokenIdeographData.fontData)
+ return brokenIdeographData;
+ }
+
+ // Shouldn't be possible to even reach this point.
+ ASSERT_NOT_REACHED();
+ }
+ } else {
+ if (m_fontDescription.textOrientation() == TextOrientationVerticalRight) {
+ const SimpleFontData* verticalRightFontData = data.fontData->verticalRightOrientationFontData();
+ GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData, pageNumber);
+ const GlyphPage* verticalRightPage = verticalRightNode->page();
+ if (verticalRightPage) {
+ GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(c);
+ // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked
+ // into it.
+ if (data.glyph != verticalRightData.glyph)
+ return data;
+ // The glyphs are identical, meaning that we should just use the horizontal glyph.
+ if (verticalRightData.fontData)
+ return verticalRightData;
+ }
+ } else if (m_fontDescription.textOrientation() == TextOrientationUpright) {
+ const SimpleFontData* uprightFontData = data.fontData->uprightOrientationFontData();
+ GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData, pageNumber);
+ const GlyphPage* uprightPage = uprightNode->page();
+ if (uprightPage) {
+ GlyphData uprightData = uprightPage->glyphDataForCharacter(c);
+ // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright.
+ if (data.glyph == uprightData.glyph)
+ return data;
+ // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that
+ // glyph, so we fall back to the upright data and use the horizontal glyph.
+ if (uprightData.fontData)
+ return uprightData;
+ }
}
-
+
// Shouldn't be possible to even reach this point.
ASSERT_NOT_REACHED();
}
@@ -364,7 +404,7 @@ void Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuf
inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph)
{
- if (fontData->orientation() == Horizontal) {
+ if (fontData->platformData().orientation() == Horizontal) {
FloatRect bounds = fontData->boundsForGlyph(glyph);
return bounds.x() + bounds.width() / 2;
}
@@ -412,8 +452,8 @@ float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer
it.advance(run.length(), glyphBuffer);
if (glyphOverflow) {
- glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - fontMetrics().ascent());
- glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - fontMetrics().descent());
+ glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent()));
+ glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent()));
glyphOverflow->left = ceilf(it.firstGlyphOverflow());
glyphOverflow->right = ceilf(it.lastGlyphOverflow());
}
diff --git a/Source/WebCore/platform/graphics/FontPlatformData.cpp b/Source/WebCore/platform/graphics/FontPlatformData.cpp
new file mode 100644
index 0000000..5a61cdf
--- /dev/null
+++ b/Source/WebCore/platform/graphics/FontPlatformData.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 Brent Fulgham
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "FontPlatformData.h"
+
+#include "PlatformString.h"
+#include <wtf/HashMap.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/text/StringHash.h>
+
+using namespace std;
+
+namespace WebCore {
+
+FontPlatformData::FontPlatformData(const FontPlatformData& source)
+ : m_syntheticBold(source.m_syntheticBold)
+ , m_syntheticOblique(source.m_syntheticOblique)
+ , m_orientation(source.m_orientation)
+ , m_textOrientation(source.m_textOrientation)
+ , m_size(source.m_size)
+ , m_widthVariant(source.m_widthVariant)
+ , m_isColorBitmapFont(source.m_isColorBitmapFont)
+{
+ platformDataInit(source);
+}
+
+const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other)
+{
+ // Check for self-assignment.
+ if (this == &other)
+ return *this;
+
+ m_syntheticBold = other.m_syntheticBold;
+ m_syntheticOblique = other.m_syntheticOblique;
+ m_orientation = other.m_orientation;
+ m_textOrientation = other.m_textOrientation;
+ m_size = other.m_size;
+ m_widthVariant = other.m_widthVariant;
+ m_isColorBitmapFont = other.m_isColorBitmapFont;
+
+ return platformDataAssign(other);
+}
+
+}
diff --git a/Source/WebCore/platform/graphics/FontPlatformData.h b/Source/WebCore/platform/graphics/FontPlatformData.h
new file mode 100644
index 0000000..78c86ef
--- /dev/null
+++ b/Source/WebCore/platform/graphics/FontPlatformData.h
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2007 Pioneer Research Center USA, Inc.
+ * Copyright (C) 2010, 2011 Brent Fulgham <bfulgham@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+// FIXME: This is temporary until all ports switch to using this file.
+#if PLATFORM(CHROMIUM) && !OS(DARWIN)
+#include "chromium/FontPlatformData.h"
+#elif PLATFORM(QT)
+#include "qt/FontPlatformData.h"
+#elif PLATFORM(WIN) && OS(WINCE)
+#include "wince/FontPlatformData.h"
+#elif PLATFORM(WX)
+#include "wx/FontPlatformData.h"
+#elif (PLATFORM(EFL) || PLATFORM(GTK)) && USE(FREETYPE)
+#include "freetype/FontPlatformData.h"
+#elif (PLATFORM(EFL) || PLATFORM(GTK)) && USE(PANGO)
+#include "pango/FontPlatformData.h"
+#else
+
+#ifndef FontPlatformData_h
+#define FontPlatformData_h
+
+#include "FontOrientation.h"
+#include "FontWidthVariant.h"
+#include "GlyphBuffer.h"
+#include "TextOrientation.h"
+
+#if PLATFORM(WIN)
+#include "RefCountedGDIHandle.h"
+#endif
+
+#if PLATFORM(CAIRO)
+#include "HashFunctions.h"
+#include <cairo.h>
+#endif
+
+#if OS(DARWIN)
+#ifdef __OBJC__
+@class NSFont;
+#else
+class NSFont;
+#endif
+
+typedef struct CGFont* CGFontRef;
+#ifndef BUILDING_ON_TIGER
+typedef const struct __CTFont* CTFontRef;
+#endif
+
+#include <CoreFoundation/CFBase.h>
+#include <objc/objc-auto.h>
+#endif
+
+#include <wtf/Forward.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/text/StringImpl.h>
+
+#if PLATFORM(CHROMIUM) && OS(DARWIN)
+#include "CrossProcessFontLoading.h"
+#endif
+
+#if PLATFORM(WIN)
+typedef struct HFONT__* HFONT;
+#endif
+
+#if PLATFORM(CG)
+typedef struct CGFont* CGFontRef;
+#if OS(DARWIN)
+#ifndef BUILDING_ON_TIGER
+typedef const struct __CTFont* CTFontRef;
+typedef UInt32 ATSUFontID;
+typedef UInt32 ATSFontRef;
+#endif
+#endif
+#endif
+
+namespace WebCore {
+
+class FontDescription;
+
+#if OS(DARWIN) && !defined(BUILDING_ON_TIGER)
+inline CTFontRef toCTFontRef(NSFont *nsFont) { return reinterpret_cast<CTFontRef>(nsFont); }
+#endif
+
+class FontPlatformData {
+public:
+ FontPlatformData(WTF::HashTableDeletedValueType)
+ : m_syntheticBold(false)
+ , m_syntheticOblique(false)
+ , m_orientation(Horizontal)
+ , m_textOrientation(TextOrientationVerticalRight)
+ , m_size(0)
+ , m_widthVariant(RegularWidth)
+#if PLATFORM(WIN)
+ , m_font(WTF::HashTableDeletedValue)
+#elif OS(DARWIN)
+ , m_font(hashTableDeletedFontValue())
+#endif
+#if PLATFORM(CG) && (defined(BUILDING_ON_TIGER) || PLATFORM(WIN))
+ , m_cgFont(0)
+#elif PLATFORM(CAIRO)
+ , m_scaledFont(hashTableDeletedFontValue())
+#endif
+ , m_isColorBitmapFont(false)
+#if PLATFORM(WIN)
+ , m_useGDI(false)
+#endif
+ {
+ }
+
+ FontPlatformData()
+ : m_syntheticBold(false)
+ , m_syntheticOblique(false)
+ , m_orientation(Horizontal)
+ , m_textOrientation(TextOrientationVerticalRight)
+ , m_size(0)
+ , m_widthVariant(RegularWidth)
+#if OS(DARWIN)
+ , m_font(0)
+#endif
+#if PLATFORM(CG) && (defined(BUILDING_ON_TIGER) || PLATFORM(WIN))
+ , m_cgFont(0)
+#elif PLATFORM(CAIRO)
+ , m_scaledFont(0)
+#endif
+ , m_isColorBitmapFont(false)
+#if PLATFORM(WIN)
+ , m_useGDI(false)
+#endif
+ {
+ }
+
+ FontPlatformData(const FontPlatformData&);
+ FontPlatformData(const FontDescription&, const AtomicString& family);
+ FontPlatformData(float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation = Horizontal,
+ TextOrientation textOrientation = TextOrientationVerticalRight, FontWidthVariant widthVariant = RegularWidth)
+ : m_syntheticBold(syntheticBold)
+ , m_syntheticOblique(syntheticOblique)
+ , m_orientation(orientation)
+ , m_textOrientation(textOrientation)
+ , m_size(size)
+ , m_widthVariant(widthVariant)
+#if OS(DARWIN)
+ , m_font(0)
+#endif
+#if PLATFORM(CG) && (defined(BUILDING_ON_TIGER) || PLATFORM(WIN))
+ , m_cgFont(0)
+#elif PLATFORM(CAIRO)
+ , m_scaledFont(0)
+#endif
+ , m_isColorBitmapFont(false)
+#if PLATFORM(WIN)
+ , m_useGDI(false)
+#endif
+ {
+ }
+
+#if OS(DARWIN)
+ FontPlatformData(NSFont*, float size, bool syntheticBold = false, bool syntheticOblique = false, FontOrientation = Horizontal,
+ TextOrientation = TextOrientationVerticalRight, FontWidthVariant = RegularWidth);
+ FontPlatformData(CGFontRef cgFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation,
+ TextOrientation textOrientation, FontWidthVariant widthVariant)
+ : m_syntheticBold(syntheticBold)
+ , m_syntheticOblique(syntheticOblique)
+ , m_orientation(orientation)
+ , m_textOrientation(textOrientation)
+ , m_size(size)
+ , m_widthVariant(widthVariant)
+ , m_font(0)
+ , m_cgFont(cgFont)
+ , m_isColorBitmapFont(false)
+ {
+ }
+#endif
+#if PLATFORM(WIN)
+ FontPlatformData(HFONT, float size, bool syntheticBold, bool syntheticOblique, bool useGDI);
+#if PLATFORM(CG)
+ FontPlatformData(HFONT, CGFontRef, float size, bool syntheticBold, bool syntheticOblique, bool useGDI);
+#endif
+#endif
+#if PLATFORM(CAIRO)
+ FontPlatformData(cairo_font_face_t*, float size, bool bold, bool italic);
+#endif
+
+ ~FontPlatformData();
+
+#if PLATFORM(WIN)
+ HFONT hfont() const { return m_font ? m_font->handle() : 0; }
+ bool useGDI() const { return m_useGDI; }
+#elif OS(DARWIN)
+ NSFont* font() const { return m_font; }
+ void setFont(NSFont*);
+#endif
+
+#if PLATFORM(CG)
+#if OS(DARWIN)
+#ifndef BUILDING_ON_TIGER
+ CGFontRef cgFont() const { return m_cgFont.get(); }
+#else
+ CGFontRef cgFont() const { return m_cgFont; }
+#endif
+ CTFontRef ctFont() const;
+
+ bool roundsGlyphAdvances() const;
+ bool allowsLigatures() const;
+#else
+ CGFontRef cgFont() const { return m_cgFont.get(); }
+#endif
+#endif
+
+ bool isFixedPitch() const;
+ float size() const { return m_size; }
+ void setSize(float size) { m_size = size; }
+ bool syntheticBold() const { return m_syntheticBold; }
+ bool syntheticOblique() const { return m_syntheticOblique; }
+ bool isColorBitmapFont() const { return m_isColorBitmapFont; }
+ FontOrientation orientation() const { return m_orientation; }
+ TextOrientation textOrientation() const { return m_textOrientation; }
+ FontWidthVariant widthVariant() const { return m_widthVariant; }
+
+ void setOrientation(FontOrientation orientation) { m_orientation = orientation; }
+
+#if PLATFORM(CAIRO)
+ cairo_scaled_font_t* scaledFont() const { return m_scaledFont; }
+#endif
+
+ unsigned hash() const
+ {
+#if PLATFORM(WIN) && !PLATFORM(CAIRO)
+ return m_font ? m_font->hash() : 0;
+#elif OS(DARWIN)
+ ASSERT(m_font || !m_cgFont);
+ uintptr_t hashCodes[3] = { (uintptr_t)m_font, m_widthVariant, m_textOrientation << 3 | m_orientation << 2 | m_syntheticBold << 1 | m_syntheticOblique };
+ return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
+#elif PLATFORM(CAIRO)
+ return PtrHash<cairo_scaled_font_t*>::hash(m_scaledFont);
+#endif
+ }
+
+ const FontPlatformData& operator=(const FontPlatformData&);
+
+ bool operator==(const FontPlatformData& other) const
+ {
+ return platformIsEqual(other)
+ && m_size == other.m_size
+ && m_syntheticBold == other.m_syntheticBold
+ && m_syntheticOblique == other.m_syntheticOblique
+ && m_isColorBitmapFont == other.m_isColorBitmapFont
+ && m_orientation == other.m_orientation
+ && m_textOrientation == other.m_textOrientation
+ && m_widthVariant == other.m_widthVariant;
+ }
+
+ bool isHashTableDeletedValue() const
+ {
+#if PLATFORM(WIN) && !PLATFORM(CAIRO)
+ return m_font.isHashTableDeletedValue();
+#elif OS(DARWIN)
+ return m_font == hashTableDeletedFontValue();
+#elif PLATFORM(CAIRO)
+ return m_scaledFont == hashTableDeletedFontValue();
+#endif
+ }
+
+
+#ifndef NDEBUG
+ String description() const;
+#endif
+
+private:
+ bool platformIsEqual(const FontPlatformData&) const;
+ void platformDataInit(const FontPlatformData&);
+ const FontPlatformData& platformDataAssign(const FontPlatformData&);
+#if OS(DARWIN)
+ // Load various data about the font specified by |nsFont| with the size fontSize into the following output paramters:
+ // Note: Callers should always take into account that for the Chromium port, |outNSFont| isn't necessarily the same
+ // font as |nsFont|. This because the sandbox may block loading of the original font.
+ // * outNSFont - The font that was actually loaded, for the Chromium port this may be different than nsFont.
+ // The caller is responsible for calling CFRelease() on this parameter when done with it.
+ // * cgFont - CGFontRef representing the input font at the specified point size.
+ void loadFont(NSFont*, float fontSize, NSFont*& outNSFont, CGFontRef&);
+ static NSFont* hashTableDeletedFontValue() { return reinterpret_cast<NSFont *>(-1); }
+#elif PLATFORM(WIN)
+ void platformDataInit(HFONT, float size, HDC, WCHAR* faceName);
+#endif
+
+#if PLATFORM(CAIRO)
+ static cairo_scaled_font_t* hashTableDeletedFontValue() { return reinterpret_cast<cairo_scaled_font_t*>(-1); }
+#endif
+
+public:
+ bool m_syntheticBold;
+ bool m_syntheticOblique;
+ FontOrientation m_orientation;
+ TextOrientation m_textOrientation;
+ float m_size;
+ FontWidthVariant m_widthVariant;
+
+private:
+#if OS(DARWIN)
+ NSFont* m_font;
+#elif PLATFORM(WIN)
+ RefPtr<RefCountedGDIHandle<HFONT> > m_font;
+#endif
+
+#if PLATFORM(CG)
+#if PLATFORM(WIN)
+ RetainPtr<CGFontRef> m_cgFont;
+#else
+#ifndef BUILDING_ON_TIGER
+ RetainPtr<CGFontRef> m_cgFont;
+#else
+ CGFontRef m_cgFont; // It is not necessary to refcount this, since either an NSFont owns it or some CachedFont has it referenced.
+#endif
+ mutable RetainPtr<CTFontRef> m_CTFont;
+#endif
+#endif
+
+#if PLATFORM(CAIRO)
+ cairo_scaled_font_t* m_scaledFont;
+#endif
+
+#if PLATFORM(CHROMIUM) && OS(DARWIN)
+ RefPtr<MemoryActivatedFont> m_inMemoryFont;
+#endif
+
+ bool m_isColorBitmapFont;
+
+#if PLATFORM(WIN)
+ bool m_useGDI;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // FontPlatformData_h
+
+#endif
diff --git a/Source/WebCore/platform/graphics/GraphicsContext.h b/Source/WebCore/platform/graphics/GraphicsContext.h
index 5eafa16..c555a5f 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext.h
+++ b/Source/WebCore/platform/graphics/GraphicsContext.h
@@ -42,8 +42,9 @@ typedef struct CGContext PlatformGraphicsContext;
#elif PLATFORM(CAIRO)
namespace WebCore {
class ContextShadow;
+class PlatformContextCairo;
}
-typedef struct _cairo PlatformGraphicsContext;
+typedef WebCore::PlatformContextCairo PlatformGraphicsContext;
#elif PLATFORM(OPENVG)
namespace WebCore {
class SurfaceOpenVG;
@@ -279,6 +280,9 @@ namespace WebCore {
void setIsCALayerContext(bool);
bool isCALayerContext() const;
+
+ void setIsAcceleratedContext(bool);
+ bool isAcceleratedContext() const;
#endif
#if PLATFORM(ANDROID)
@@ -522,6 +526,7 @@ namespace WebCore {
#endif
#if PLATFORM(CAIRO)
+ GraphicsContext(cairo_t*);
void pushImageMask(cairo_surface_t*, const FloatRect&);
#endif
diff --git a/Source/WebCore/platform/graphics/GraphicsContext3D.h b/Source/WebCore/platform/graphics/GraphicsContext3D.h
index a9db650..351b445 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext3D.h
+++ b/Source/WebCore/platform/graphics/GraphicsContext3D.h
@@ -51,8 +51,8 @@
@class CALayer;
@class WebGLLayer;
#else
-typedef void* CALayer;
-typedef void* WebGLLayer;
+class CALayer;
+class WebGLLayer;
#endif
#elif PLATFORM(QT)
QT_BEGIN_NAMESPACE
@@ -420,6 +420,7 @@ public:
, antialias(true)
, premultipliedAlpha(true)
, canRecoverFromContextLoss(true)
+ , preserveDrawingBuffer(false)
{
}
@@ -429,6 +430,7 @@ public:
bool antialias;
bool premultipliedAlpha;
bool canRecoverFromContextLoss;
+ bool preserveDrawingBuffer;
};
enum RenderStyle {
@@ -449,8 +451,8 @@ public:
#if PLATFORM(MAC)
PlatformGraphicsContext3D platformGraphicsContext3D() const { return m_contextObj; }
- Platform3DObject platformTexture() const { return m_texture; }
- CALayer* platformLayer() const { return static_cast<CALayer*>(m_webGLLayer.get()); }
+ Platform3DObject platformTexture() const { return m_compositorTexture; }
+ CALayer* platformLayer() const { return reinterpret_cast<CALayer*>(m_webGLLayer.get()); }
#elif PLATFORM(CHROMIUM)
PlatformGraphicsContext3D platformGraphicsContext3D() const;
Platform3DObject platformTexture() const;
@@ -461,7 +463,7 @@ public:
PlatformGraphicsContext3D platformGraphicsContext3D();
Platform3DObject platformTexture() const;
#if USE(ACCELERATED_COMPOSITING)
- PlatformLayer* platformLayer() const { return 0; }
+ PlatformLayer* platformLayer() const;
#endif
#else
PlatformGraphicsContext3D platformGraphicsContext3D() const { return NullPlatformGraphicsContext3D; }
@@ -756,10 +758,14 @@ public:
int canvasWidth, int canvasHeight, CGContextRef context);
#endif
+ void markContextChanged();
+ void markLayerComposited();
+ bool layerComposited() const;
+
void paintRenderingResultsToCanvas(CanvasRenderingContext* context);
+ PassRefPtr<ImageData> paintRenderingResultsToImageData();
#if PLATFORM(QT)
- void paint(QPainter* painter, const QRect& rect) const;
bool paintsIntoCanvasBuffer() const { return true; }
#elif PLATFORM(CHROMIUM)
bool paintsIntoCanvasBuffer() const;
@@ -859,6 +865,10 @@ public:
// could not be honored based on the capabilities of the OpenGL
// implementation.
void validateAttributes();
+
+ // Read rendering results into a pixel array with the same format as the
+ // backbuffer.
+ void readRenderingResults(unsigned char* pixels, int pixelsSize);
#endif
int m_currentWidth, m_currentHeight;
@@ -881,12 +891,16 @@ public:
CGLContextObj m_contextObj;
RetainPtr<WebGLLayer> m_webGLLayer;
- GC3Duint m_texture;
+ GC3Duint m_texture, m_compositorTexture;
GC3Duint m_fbo;
GC3Duint m_depthStencilBuffer;
+ bool m_layerComposited;
+ GC3Duint m_internalColorFormat;
- // For tracking which FBO is bound
+ // For tracking which FBO/texture is bound
GC3Duint m_boundFBO;
+ GC3Denum m_activeTexture;
+ GC3Duint m_boundTexture0;
// For multisampling
GC3Duint m_multisampleFBO;
diff --git a/Source/WebCore/platform/graphics/GraphicsLayer.h b/Source/WebCore/platform/graphics/GraphicsLayer.h
index e3a62b6..4f234d4 100644
--- a/Source/WebCore/platform/graphics/GraphicsLayer.h
+++ b/Source/WebCore/platform/graphics/GraphicsLayer.h
@@ -46,12 +46,11 @@
#if PLATFORM(MAC)
#ifdef __OBJC__
-@class WebLayer;
@class CALayer;
-typedef CALayer PlatformLayer;
#else
-typedef void* PlatformLayer;
+class CALayer;
#endif
+typedef CALayer PlatformLayer;
#elif PLATFORM(WIN)
typedef struct _CACFLayer PlatformLayer;
#elif PLATFORM(QT)
diff --git a/Source/WebCore/platform/graphics/ImageBuffer.h b/Source/WebCore/platform/graphics/ImageBuffer.h
index 48878da..860f574 100644
--- a/Source/WebCore/platform/graphics/ImageBuffer.h
+++ b/Source/WebCore/platform/graphics/ImageBuffer.h
@@ -132,6 +132,10 @@ namespace WebCore {
ImageBuffer(const IntSize&, ColorSpace colorSpace, RenderingMode renderingMode, bool& success);
};
+#if PLATFORM(CG) || USE(SKIA)
+ String ImageDataToDataURL(const ImageData& input, const String& mimeType, const double* quality);
+#endif
+
} // namespace WebCore
#endif // ImageBuffer_h
diff --git a/Source/WebCore/platform/graphics/MediaPlayer.cpp b/Source/WebCore/platform/graphics/MediaPlayer.cpp
index 70576a5..03004b6 100644
--- a/Source/WebCore/platform/graphics/MediaPlayer.cpp
+++ b/Source/WebCore/platform/graphics/MediaPlayer.cpp
@@ -47,6 +47,9 @@
#if PLATFORM(MAC)
#include "MediaPlayerPrivateQTKit.h"
+#if USE(AVFOUNDATION)
+#include "MediaPlayerPrivateAVFoundationObjC.h"
+#endif
#define PlatformMediaEngineClassName MediaPlayerPrivateQTKit
#elif OS(WINCE) && !PLATFORM(QT)
#include "MediaPlayerPrivateWinCE.h"
@@ -82,7 +85,7 @@ public:
virtual void load(const String&) { }
virtual void cancelLoad() { }
-
+
virtual void prepareToPlay() { }
virtual void play() { }
virtual void pause() { }
@@ -189,11 +192,15 @@ static Vector<MediaPlayerFactory*>& installedMediaEngines()
MediaPlayerPrivateGStreamer::registerMediaEngine(addMediaEngine);
#endif
+#if USE(AVFOUNDATION) && PLATFORM(MAC)
+ MediaPlayerPrivateAVFoundationObjC::registerMediaEngine(addMediaEngine);
+#endif
+
#if !PLATFORM(GTK) && !PLATFORM(EFL) && !(PLATFORM(QT) && USE(GSTREAMER))
PlatformMediaEngineClassName::registerMediaEngine(addMediaEngine);
#endif
}
-
+
return installedEngines;
}
@@ -241,7 +248,7 @@ static MediaPlayerFactory* bestMediaEngineForTypeAndCodecs(const String& type, c
if (!codecs.isEmpty())
return 0;
}
-
+
MediaPlayerFactory* engine = 0;
MediaPlayer::SupportsType supported = MediaPlayer::IsNotSupported;
unsigned count = engines.size();
@@ -292,6 +299,7 @@ MediaPlayer::MediaPlayer(MediaPlayerClient* client)
, m_muted(false)
, m_preservesPitch(true)
, m_privateBrowsing(false)
+ , m_shouldPrepareToRender(false)
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
, m_playerProxy(0)
#endif
@@ -351,7 +359,7 @@ void MediaPlayer::loadWithNextMediaEngine(MediaPlayerFactory* current)
engine = nextMediaEngine(current);
else
engine = bestMediaEngineForTypeAndCodecs(m_contentMIMEType, m_contentTypeCodecs, current);
-
+
// Don't delete and recreate the player unless it comes from a different engine.
if (!engine) {
m_currentMediaEngine = engine;
@@ -368,6 +376,8 @@ void MediaPlayer::loadWithNextMediaEngine(MediaPlayerFactory* current)
m_private->setPrivateBrowsingMode(m_privateBrowsing);
m_private->setPreload(m_preload);
m_private->setPreservesPitch(preservesPitch());
+ if (m_shouldPrepareToRender)
+ m_private->prepareForRendering();
}
if (m_private)
@@ -383,17 +393,18 @@ bool MediaPlayer::hasAvailableVideoFrame() const
{
return m_private->hasAvailableVideoFrame();
}
-
+
void MediaPlayer::prepareForRendering()
{
- return m_private->prepareForRendering();
+ m_shouldPrepareToRender = true;
+ m_private->prepareForRendering();
}
-
+
bool MediaPlayer::canLoadPoster() const
{
return m_private->canLoadPoster();
}
-
+
void MediaPlayer::setPoster(const String& url)
{
m_private->setPoster(url);
@@ -408,7 +419,7 @@ void MediaPlayer::prepareToPlay()
{
m_private->prepareToPlay();
}
-
+
void MediaPlayer::play()
{
m_private->play();
@@ -478,7 +489,7 @@ bool MediaPlayer::inMediaDocument()
{
Frame* frame = m_frameView ? m_frameView->frame() : 0;
Document* document = frame ? frame->document() : 0;
-
+
return document && document->isMediaDocument();
}
diff --git a/Source/WebCore/platform/graphics/MediaPlayer.h b/Source/WebCore/platform/graphics/MediaPlayer.h
index f41af01..5872c88 100644
--- a/Source/WebCore/platform/graphics/MediaPlayer.h
+++ b/Source/WebCore/platform/graphics/MediaPlayer.h
@@ -46,8 +46,10 @@
#endif
#ifdef __OBJC__
+@class AVPlayer;
@class QTMovie;
#else
+class AVPlayer;
class QTMovie;
#endif
class QTMovieGWorld;
@@ -71,6 +73,7 @@ struct PlatformMedia {
GStreamerGWorldType,
ChromiumMediaPlayerType,
QtMediaPlayerType,
+ AVFoundationMediaPlayerType,
} type;
union {
@@ -80,6 +83,7 @@ struct PlatformMedia {
GStreamerGWorld* gstreamerGWorld;
MediaPlayerPrivateInterface* chromiumMediaPlayer;
MediaPlayerPrivateInterface* qtMediaPlayer;
+ AVPlayer* avfMediaPlayer;
} media;
};
@@ -115,10 +119,10 @@ public:
// time has jumped, eg. not as a result of normal playback
virtual void mediaPlayerTimeChanged(MediaPlayer*) { }
-
+
// the media file duration has changed, or is now known
virtual void mediaPlayerDurationChanged(MediaPlayer*) { }
-
+
// the playback rate has changed
virtual void mediaPlayerRateChanged(MediaPlayer*) { }
@@ -178,49 +182,53 @@ public:
IntSize naturalSize();
bool hasVideo() const;
bool hasAudio() const;
+<<<<<<< HEAD
#if PLATFORM(ANDROID)
enum MediaElementType { Video, Audio };
void setMediaElementType(MediaElementType type) { m_mediaElementType = type; }
MediaElementType mediaElementType() { return m_mediaElementType; }
#endif
+=======
+
+>>>>>>> webkit.org at r82507
void setFrameView(FrameView* frameView) { m_frameView = frameView; }
FrameView* frameView() { return m_frameView; }
bool inMediaDocument();
-
+
IntSize size() const { return m_size; }
void setSize(const IntSize& size);
-
+
void load(const String& url, const ContentType&);
void cancelLoad();
-
+
bool visible() const;
void setVisible(bool);
-
+
void prepareToPlay();
void play();
void pause();
-
+
bool paused() const;
bool seeking() const;
-
+
float duration() const;
float currentTime() const;
void seek(float time);
float startTime() const;
-
+
float rate() const;
void setRate(float);
bool preservesPitch() const;
void setPreservesPitch(bool);
-
+
PassRefPtr<TimeRanges> buffered();
float maxTimeSeekable();
unsigned bytesLoaded();
-
+
float volume() const;
void setVolume(float);
@@ -235,13 +243,13 @@ public:
void paint(GraphicsContext*, const IntRect&);
void paintCurrentFrameInContext(GraphicsContext*, const IntRect&);
-
+
enum NetworkState { Empty, Idle, Loading, Loaded, FormatError, NetworkError, DecodeError };
NetworkState networkState();
enum ReadyState { HaveNothing, HaveMetadata, HaveCurrentData, HaveFutureData, HaveEnoughData };
ReadyState readyState();
-
+
enum MovieLoadType { Unknown, Download, StoredStream, LiveStream };
MovieLoadType movieLoadType() const;
@@ -320,6 +328,7 @@ private:
bool m_muted;
bool m_preservesPitch;
bool m_privateBrowsing;
+ bool m_shouldPrepareToRender;
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
WebMediaPlayerProxy* m_playerProxy; // not owned or used, passed to m_private
#endif
diff --git a/Source/WebCore/platform/graphics/Path.cpp b/Source/WebCore/platform/graphics/Path.cpp
index 55760b1..f7aedbe 100644
--- a/Source/WebCore/platform/graphics/Path.cpp
+++ b/Source/WebCore/platform/graphics/Path.cpp
@@ -83,14 +83,14 @@ static void pathLengthApplierFunction(void* info, const PathElement* element)
}
}
-float Path::length()
+float Path::length() const
{
PathTraversalState traversalState(PathTraversalState::TraversalTotalLength);
apply(&traversalState, pathLengthApplierFunction);
return traversalState.m_totalLength;
}
-FloatPoint Path::pointAtLength(float length, bool& ok)
+FloatPoint Path::pointAtLength(float length, bool& ok) const
{
PathTraversalState traversalState(PathTraversalState::TraversalPointAtLength);
traversalState.m_desiredLength = length;
@@ -99,10 +99,10 @@ FloatPoint Path::pointAtLength(float length, bool& ok)
return traversalState.m_current;
}
-float Path::normalAngleAtLength(float length, bool& ok)
+float Path::normalAngleAtLength(float length, bool& ok) const
{
PathTraversalState traversalState(PathTraversalState::TraversalNormalAngleAtLength);
- traversalState.m_desiredLength = length;
+ traversalState.m_desiredLength = length ? length : std::numeric_limits<float>::epsilon();
apply(&traversalState, pathLengthApplierFunction);
ok = traversalState.m_success;
return traversalState.m_normalAngle;
diff --git a/Source/WebCore/platform/graphics/Path.h b/Source/WebCore/platform/graphics/Path.h
index 31f2cd6..c2ca576 100644
--- a/Source/WebCore/platform/graphics/Path.h
+++ b/Source/WebCore/platform/graphics/Path.h
@@ -112,11 +112,11 @@ namespace WebCore {
bool contains(const FloatPoint&, WindRule rule = RULE_NONZERO) const;
bool strokeContains(StrokeStyleApplier*, const FloatPoint&) const;
FloatRect boundingRect() const;
- FloatRect strokeBoundingRect(StrokeStyleApplier* = 0);
+ FloatRect strokeBoundingRect(StrokeStyleApplier* = 0) const;
- float length();
- FloatPoint pointAtLength(float length, bool& ok);
- float normalAngleAtLength(float length, bool& ok);
+ float length() const;
+ FloatPoint pointAtLength(float length, bool& ok) const;
+ float normalAngleAtLength(float length, bool& ok) const;
void clear();
bool isEmpty() const;
diff --git a/Source/WebCore/platform/graphics/SimpleFontData.cpp b/Source/WebCore/platform/graphics/SimpleFontData.cpp
index aaab666..82f770d 100644
--- a/Source/WebCore/platform/graphics/SimpleFontData.cpp
+++ b/Source/WebCore/platform/graphics/SimpleFontData.cpp
@@ -47,15 +47,16 @@ using namespace std;
namespace WebCore {
-SimpleFontData::SimpleFontData(const FontPlatformData& platformData, bool isCustomFont, bool isLoading)
+SimpleFontData::SimpleFontData(const FontPlatformData& platformData, bool isCustomFont, bool isLoading, bool isTextOrientationFallback)
: m_maxCharWidth(-1)
, m_avgCharWidth(-1)
- , m_orientation(platformData.orientation())
, m_platformData(platformData)
, m_treatAsFixedPitch(false)
, m_isCustomFont(isCustomFont)
, m_isLoading(isLoading)
- , m_isBrokenIdeographFont(false)
+ , m_isTextOrientationFallback(isTextOrientationFallback)
+ , m_isBrokenIdeographFallback(false)
+ , m_hasVerticalGlyphs(false)
{
platformInit();
platformGlyphInit();
@@ -64,13 +65,14 @@ SimpleFontData::SimpleFontData(const FontPlatformData& platformData, bool isCust
#if ENABLE(SVG_FONTS)
SimpleFontData::SimpleFontData(PassOwnPtr<SVGFontData> svgFontData, int size, bool syntheticBold, bool syntheticItalic)
- : m_orientation(Horizontal)
- , m_platformData(FontPlatformData(size, syntheticBold, syntheticItalic))
+ : m_platformData(FontPlatformData(size, syntheticBold, syntheticItalic))
, m_treatAsFixedPitch(false)
, m_svgFontData(svgFontData)
, m_isCustomFont(true)
, m_isLoading(false)
- , m_isBrokenIdeographFont(false)
+ , m_isTextOrientationFallback(false)
+ , m_isBrokenIdeographFallback(false)
+ , m_hasVerticalGlyphs(false)
{
SVGFontFaceElement* svgFontFaceElement = m_svgFontData->svgFontFaceElement();
unsigned unitsPerEm = svgFontFaceElement->unitsPerEm();
@@ -202,14 +204,34 @@ bool SimpleFontData::isSegmented() const
return false;
}
+SimpleFontData* SimpleFontData::verticalRightOrientationFontData() const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->verticalRightOrientation) {
+ FontPlatformData verticalRightPlatformData(m_platformData);
+ verticalRightPlatformData.setOrientation(Horizontal);
+ m_derivedFontData->verticalRightOrientation = new SimpleFontData(verticalRightPlatformData, isCustomFont(), false, true);
+ }
+ return m_derivedFontData->verticalRightOrientation.get();
+}
+
+SimpleFontData* SimpleFontData::uprightOrientationFontData() const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->uprightOrientation)
+ m_derivedFontData->uprightOrientation = new SimpleFontData(m_platformData, isCustomFont(), false, true);
+ return m_derivedFontData->uprightOrientation.get();
+}
+
SimpleFontData* SimpleFontData::brokenIdeographFontData() const
{
if (!m_derivedFontData)
m_derivedFontData = DerivedFontData::create(isCustomFont());
if (!m_derivedFontData->brokenIdeograph) {
m_derivedFontData->brokenIdeograph = new SimpleFontData(m_platformData, isCustomFont(), false);
- m_derivedFontData->brokenIdeograph->m_orientation = Vertical;
- m_derivedFontData->brokenIdeograph->m_isBrokenIdeographFont = true;
+ m_derivedFontData->brokenIdeograph->m_isBrokenIdeographFallback = true;
}
return m_derivedFontData->brokenIdeograph.get();
}
@@ -242,6 +264,10 @@ SimpleFontData::DerivedFontData::~DerivedFontData()
GlyphPageTreeNode::pruneTreeCustomFontData(emphasisMark.get());
if (brokenIdeograph)
GlyphPageTreeNode::pruneTreeCustomFontData(brokenIdeograph.get());
+ if (verticalRightOrientation)
+ GlyphPageTreeNode::pruneTreeCustomFontData(verticalRightOrientation.get());
+ if (uprightOrientation)
+ GlyphPageTreeNode::pruneTreeCustomFontData(uprightOrientation.get());
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/SimpleFontData.h b/Source/WebCore/platform/graphics/SimpleFontData.h
index 93d33bb..dfb4be3 100644
--- a/Source/WebCore/platform/graphics/SimpleFontData.h
+++ b/Source/WebCore/platform/graphics/SimpleFontData.h
@@ -71,7 +71,7 @@ enum Pitch { UnknownPitch, FixedPitch, VariablePitch };
class SimpleFontData : public FontData {
public:
- SimpleFontData(const FontPlatformData&, bool isCustomFont = false, bool isLoading = false);
+ SimpleFontData(const FontPlatformData&, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false);
#if ENABLE(SVG_FONTS)
SimpleFontData(PassOwnPtr<SVGFontData>, int size, bool syntheticBold, bool syntheticItalic);
#endif
@@ -97,11 +97,13 @@ public:
return const_cast<SimpleFontData*>(this);
}
+ SimpleFontData* verticalRightOrientationFontData() const;
+ SimpleFontData* uprightOrientationFontData() const;
SimpleFontData* brokenIdeographFontData() const;
-
- // FIXME: Use the actual metrics for fonts with vertical tables instead of just hard-coding. If the font is horizontally oriented or
- // a broken ideographic font, then just hard-code to split ascent/descent down the middle. Otherwise we should actually use the metrics
- // from the font itself.
+
+ bool hasVerticalGlyphs() const { return m_hasVerticalGlyphs; }
+ bool isTextOrientationFallback() const { return m_isTextOrientationFallback; }
+
const FontMetrics& fontMetrics() const { return m_fontMetrics; }
float maxCharWidth() const { return m_maxCharWidth; }
float avgCharWidth() const { return m_avgCharWidth; }
@@ -137,8 +139,6 @@ public:
virtual bool isLoading() const { return m_isLoading; }
virtual bool isSegmented() const;
- bool isBrokenIdeographFont() const { return m_isBrokenIdeographFont; }
-
const GlyphData& missingGlyphData() const { return m_missingGlyphData; }
#ifndef NDEBUG
@@ -152,7 +152,7 @@ public:
#endif
#if PLATFORM(MAC) || USE(CORE_TEXT)
- CFDictionaryRef getCFStringAttributes(TypesettingFeatures) const;
+ CFDictionaryRef getCFStringAttributes(TypesettingFeatures, FontOrientation) const;
#endif
#if USE(ATSUI)
@@ -183,8 +183,6 @@ public:
wxFont* getWxFont() const { return m_platformData.font(); }
#endif
- FontOrientation orientation() const { return m_orientation; }
-
private:
void platformInit();
void platformGlyphInit();
@@ -209,9 +207,6 @@ private:
float m_maxCharWidth;
float m_avgCharWidth;
- FontOrientation m_orientation; // This is our supported orientation according to the tables in the font. FontPlatformData will just always have the desired orientation.
- // This value represents what we actually support.
-
FontPlatformData m_platformData;
mutable OwnPtr<GlyphMetricsMap<FloatRect> > m_glyphToBoundsMap;
@@ -225,8 +220,11 @@ private:
bool m_isCustomFont; // Whether or not we are custom font loaded via @font-face
bool m_isLoading; // Whether or not this custom font is still in the act of loading.
- bool m_isBrokenIdeographFont;
-
+
+ bool m_isTextOrientationFallback;
+ bool m_isBrokenIdeographFallback;
+ bool m_hasVerticalGlyphs;
+
Glyph m_spaceGlyph;
float m_spaceWidth;
@@ -242,6 +240,8 @@ private:
OwnPtr<SimpleFontData> smallCaps;
OwnPtr<SimpleFontData> emphasisMark;
OwnPtr<SimpleFontData> brokenIdeograph;
+ OwnPtr<SimpleFontData> verticalRightOrientation;
+ OwnPtr<SimpleFontData> uprightOrientation;
private:
DerivedFontData(bool custom)
diff --git a/Source/WebCore/platform/graphics/TextRun.h b/Source/WebCore/platform/graphics/TextRun.h
index 4e0980b..ec763b9 100644
--- a/Source/WebCore/platform/graphics/TextRun.h
+++ b/Source/WebCore/platform/graphics/TextRun.h
@@ -33,17 +33,21 @@ class RenderSVGResource;
class TextRun {
public:
- enum TrailingExpansionBehavior {
- AllowTrailingExpansion,
- ForbidTrailingExpansion
+ enum ExpansionBehaviorFlags {
+ ForbidTrailingExpansion = 0 << 0,
+ AllowTrailingExpansion = 1 << 0,
+ ForbidLeadingExpansion = 0 << 1,
+ AllowLeadingExpansion = 1 << 1,
};
- TextRun(const UChar* c, int len, bool allowTabs = false, float xpos = 0, float expansion = 0, TrailingExpansionBehavior trailingExpansionBehavior = AllowTrailingExpansion, bool rtl = false, bool directionalOverride = false)
+ typedef unsigned ExpansionBehavior;
+
+ TextRun(const UChar* c, int len, bool allowTabs = false, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, bool rtl = false, bool directionalOverride = false)
: m_characters(c)
, m_len(len)
, m_xpos(xpos)
, m_expansion(expansion)
- , m_trailingExpansionBehavior(trailingExpansionBehavior)
+ , m_expansionBehavior(expansionBehavior)
#if ENABLE(SVG)
, m_horizontalGlyphStretch(1)
#endif
@@ -58,12 +62,12 @@ public:
{
}
- TextRun(const String& s, bool allowTabs = false, float xpos = 0, float expansion = 0, TrailingExpansionBehavior trailingExpansionBehavior = AllowTrailingExpansion, bool rtl = false, bool directionalOverride = false)
+ TextRun(const String& s, bool allowTabs = false, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, bool rtl = false, bool directionalOverride = false)
: m_characters(s.characters())
, m_len(s.length())
, m_xpos(xpos)
, m_expansion(expansion)
- , m_trailingExpansionBehavior(trailingExpansionBehavior)
+ , m_expansionBehavior(expansionBehavior)
#if ENABLE(SVG)
, m_horizontalGlyphStretch(1)
#endif
@@ -94,7 +98,8 @@ public:
bool allowTabs() const { return m_allowTabs; }
float xPos() const { return m_xpos; }
float expansion() const { return m_expansion; }
- bool allowsTrailingExpansion() const { return m_trailingExpansionBehavior == AllowTrailingExpansion; }
+ bool allowsLeadingExpansion() const { return m_expansionBehavior & AllowLeadingExpansion; }
+ bool allowsTrailingExpansion() const { return m_expansionBehavior & AllowTrailingExpansion; }
bool rtl() const { return m_rtl; }
bool ltr() const { return !m_rtl; }
bool directionalOverride() const { return m_directionalOverride; }
@@ -121,7 +126,7 @@ private:
// the text line is not the same as left start of the containing block.
float m_xpos;
float m_expansion;
- TrailingExpansionBehavior m_trailingExpansionBehavior;
+ ExpansionBehavior m_expansionBehavior;
#if ENABLE(SVG)
float m_horizontalGlyphStretch;
#endif
diff --git a/Source/WebCore/platform/graphics/Tile.h b/Source/WebCore/platform/graphics/Tile.h
index c623ec9..02076d2 100644
--- a/Source/WebCore/platform/graphics/Tile.h
+++ b/Source/WebCore/platform/graphics/Tile.h
@@ -49,7 +49,7 @@ public:
bool isDirty() const;
void invalidate(const IntRect&);
- void updateBackBuffer();
+ Vector<IntRect> updateBackBuffer();
void swapBackBufferToFront();
bool isReadyToPaint() const;
void paint(GraphicsContext*, const IntRect&);
diff --git a/Source/WebCore/platform/graphics/TiledBackingStore.cpp b/Source/WebCore/platform/graphics/TiledBackingStore.cpp
index 4d69334..ac7e9c6 100644
--- a/Source/WebCore/platform/graphics/TiledBackingStore.cpp
+++ b/Source/WebCore/platform/graphics/TiledBackingStore.cpp
@@ -102,8 +102,6 @@ void TiledBackingStore::updateTileBuffers()
if (!it->second->isDirty())
continue;
dirtyTiles.append(it->second);
- // FIXME: should not request system repaint for the full tile.
- paintedArea.append(mapToContents(it->second->rect()));
}
if (dirtyTiles.isEmpty()) {
@@ -115,11 +113,11 @@ void TiledBackingStore::updateTileBuffers()
// one by one and then swapped to front in one go. This would minimize the time spent
// blocking on tile updates.
unsigned size = dirtyTiles.size();
- for (unsigned n = 0; n < size; ++n)
- dirtyTiles[n]->updateBackBuffer();
-
- for (unsigned n = 0; n < size; ++n)
+ for (unsigned n = 0; n < size; ++n) {
+ Vector<IntRect> paintedRects = dirtyTiles[n]->updateBackBuffer();
+ paintedArea.append(paintedRects);
dirtyTiles[n]->swapBackBufferToFront();
+ }
m_client->tiledBackingStorePaintEnd(paintedArea);
}
diff --git a/Source/WebCore/platform/graphics/WOFFFileFormat.cpp b/Source/WebCore/platform/graphics/WOFFFileFormat.cpp
index b1400ba..80a6dcb 100644
--- a/Source/WebCore/platform/graphics/WOFFFileFormat.cpp
+++ b/Source/WebCore/platform/graphics/WOFFFileFormat.cpp
@@ -248,7 +248,7 @@ bool convertWOFFToSfnt(SharedBuffer* woff, Vector<char>& sfnt)
return sfnt.size() == totalSfntSize;
}
+
+} // namespace WebCore
#endif // !ENABLE(OPENTYPE_SANITIZER)
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/WidthIterator.cpp b/Source/WebCore/platform/graphics/WidthIterator.cpp
index 27b0627..750a4ac 100644
--- a/Source/WebCore/platform/graphics/WidthIterator.cpp
+++ b/Source/WebCore/platform/graphics/WidthIterator.cpp
@@ -47,7 +47,7 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const
, m_end(run.length())
, m_currentCharacter(0)
, m_runWidthSoFar(0)
- , m_isAfterExpansion(true)
+ , m_isAfterExpansion(!run.allowsLeadingExpansion())
, m_fallbackFonts(fallbackFonts)
, m_accountForGlyphBounds(accountForGlyphBounds)
, m_maxGlyphBoundingBoxY(numeric_limits<float>::min())
@@ -62,7 +62,7 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const
if (!m_expansion)
m_expansionPerOpportunity = 0;
else {
- bool isAfterExpansion = true;
+ bool isAfterExpansion = m_isAfterExpansion;
unsigned expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion);
if (isAfterExpansion && !m_run.allowsTrailingExpansion())
expansionOpportunityCount--;
@@ -164,18 +164,24 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
bool treatAsSpace = Font::treatAsSpace(c);
if (treatAsSpace || (expandAroundIdeographs && Font::isCJKIdeographOrSymbol(c))) {
// Distribute the run's total expansion evenly over all expansion opportunities in the run.
- if (m_expansion && (m_run.allowsTrailingExpansion() || (m_run.ltr() && currentCharacter + clusterLength < static_cast<size_t>(m_run.length()))
- || (m_run.rtl() && currentCharacter))) {
+ if (m_expansion) {
if (!treatAsSpace && !m_isAfterExpansion) {
// Take the expansion opportunity before this ideograph.
m_expansion -= m_expansionPerOpportunity;
m_runWidthSoFar += m_expansionPerOpportunity;
- if (glyphBuffer)
- glyphBuffer->expandLastAdvance(m_expansionPerOpportunity);
+ if (glyphBuffer) {
+ if (glyphBuffer->isEmpty())
+ glyphBuffer->add(fontData->spaceGlyph(), fontData, m_expansionPerOpportunity);
+ else
+ glyphBuffer->expandLastAdvance(m_expansionPerOpportunity);
+ }
+ }
+ if (m_run.allowsTrailingExpansion() || (m_run.ltr() && currentCharacter + clusterLength < static_cast<size_t>(m_run.length()))
+ || (m_run.rtl() && currentCharacter)) {
+ m_expansion -= m_expansionPerOpportunity;
+ width += m_expansionPerOpportunity;
+ m_isAfterExpansion = true;
}
- m_expansion -= m_expansionPerOpportunity;
- width += m_expansionPerOpportunity;
- m_isAfterExpansion = true;
} else
m_isAfterExpansion = false;
diff --git a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp
new file mode 100644
index 0000000..eb96532
--- /dev/null
+++ b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp
@@ -0,0 +1,731 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(VIDEO) && USE(AVFOUNDATION)
+
+#include "MediaPlayerPrivateAVFoundation.h"
+
+#include "ApplicationCacheHost.h"
+#include "DocumentLoader.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "GraphicsLayer.h"
+#include "KURL.h"
+#include "Logging.h"
+#include "SoftLinking.h"
+#include "TimeRanges.h"
+#include <CoreMedia/CoreMedia.h>
+#include <wtf/UnusedParam.h>
+
+using namespace std;
+
+namespace WebCore {
+
+static const float invalidTime = -1.0f;
+
+MediaPlayerPrivateAVFoundation::MediaPlayerPrivateAVFoundation(MediaPlayer* player)
+ : m_player(player)
+ , m_queuedNotifications()
+ , m_queueMutex()
+ , m_mainThreadCallPending(false)
+ , m_networkState(MediaPlayer::Empty)
+ , m_readyState(MediaPlayer::HaveNothing)
+ , m_preload(MediaPlayer::Auto)
+ , m_scaleFactor(1, 1)
+ , m_cachedMaxTimeLoaded(0)
+ , m_cachedMaxTimeSeekable(0)
+ , m_cachedDuration(invalidTime)
+ , m_reportedDuration(invalidTime)
+ , m_seekTo(invalidTime)
+ , m_requestedRate(1)
+ , m_delayCallbacks(false)
+ , m_havePreparedToPlay(false)
+ , m_assetIsPlayable(false)
+ , m_visible(false)
+ , m_videoFrameHasDrawn(false)
+ , m_loadingMetadata(false)
+ , m_delayingLoad(false)
+ , m_isAllowedToRender(false)
+ , m_cachedHasAudio(false)
+ , m_cachedHasVideo(false)
+ , m_cachedHasCaptions(false)
+ , m_ignoreLoadStateChanges(false)
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundation::MediaPlayerPrivateAVFoundation(%p)", this);
+}
+
+MediaPlayerPrivateAVFoundation::~MediaPlayerPrivateAVFoundation()
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundation::~MediaPlayerPrivateAVFoundation(%p)", this);
+ cancelCallOnMainThread(mainThreadCallback, this);
+}
+
+MediaPlayerPrivateAVFoundation::MediaRenderingMode MediaPlayerPrivateAVFoundation::currentRenderingMode() const
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (platformLayer())
+ return MediaRenderingToLayer;
+#endif
+
+ if (hasContextRenderer())
+ return MediaRenderingToContext;
+
+ return MediaRenderingNone;
+}
+
+MediaPlayerPrivateAVFoundation::MediaRenderingMode MediaPlayerPrivateAVFoundation::preferredRenderingMode() const
+{
+ if (!m_player->visible() || !m_player->frameView() || assetStatus() == MediaPlayerAVAssetStatusUnknown)
+ return MediaRenderingNone;
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (supportsAcceleratedRendering() && m_player->mediaPlayerClient()->mediaPlayerRenderingCanBeAccelerated(m_player))
+ return MediaRenderingToLayer;
+#endif
+
+ return MediaRenderingToContext;
+}
+
+void MediaPlayerPrivateAVFoundation::setUpVideoRendering()
+{
+ if (!isReadyForVideoSetup())
+ return;
+
+ MediaRenderingMode currentMode = currentRenderingMode();
+ MediaRenderingMode preferredMode = preferredRenderingMode();
+ if (currentMode == preferredMode && currentMode != MediaRenderingNone)
+ return;
+
+ LOG(Media, "MediaPlayerPrivateAVFoundation::setUpVideoRendering(%p) - current mode = %d, preferred mode = %d",
+ this, static_cast<int>(currentMode), static_cast<int>(preferredMode));
+
+ if (currentMode != MediaRenderingNone)
+ tearDownVideoRendering();
+
+ switch (preferredMode) {
+ case MediaRenderingNone:
+ case MediaRenderingToContext:
+ createContextVideoRenderer();
+ break;
+
+#if USE(ACCELERATED_COMPOSITING)
+ case MediaRenderingToLayer:
+ createVideoLayer();
+ break;
+#endif
+ }
+
+#if USE(ACCELERATED_COMPOSITING)
+ // If using a movie layer, inform the client so the compositing tree is updated.
+ if (currentMode == MediaRenderingToLayer || preferredMode == MediaRenderingToLayer) {
+ LOG(Media, "MediaPlayerPrivateAVFoundation::setUpVideoRendering(%p) - calling mediaPlayerRenderingModeChanged()", this);
+ m_player->mediaPlayerClient()->mediaPlayerRenderingModeChanged(m_player);
+ }
+#endif
+}
+
+void MediaPlayerPrivateAVFoundation::tearDownVideoRendering()
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundation::tearDownVideoRendering(%p)", this);
+
+ destroyContextVideoRenderer();
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (platformLayer())
+ destroyVideoLayer();
+#endif
+}
+
+bool MediaPlayerPrivateAVFoundation::hasSetUpVideoRendering() const
+{
+ return hasLayerRenderer() || hasContextRenderer();
+}
+
+void MediaPlayerPrivateAVFoundation::resumeLoad()
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundation::resumeLoad(%p)", this);
+
+ ASSERT(m_delayingLoad);
+ m_delayingLoad = false;
+
+ if (m_assetURL.length())
+ prepareToPlay();
+}
+
+void MediaPlayerPrivateAVFoundation::load(const String& url)
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundation::load(%p)", this);
+
+ if (m_networkState != MediaPlayer::Loading) {
+ m_networkState = MediaPlayer::Loading;
+ m_player->networkStateChanged();
+ }
+ if (m_readyState != MediaPlayer::HaveNothing) {
+ m_readyState = MediaPlayer::HaveNothing;
+ m_player->readyStateChanged();
+ }
+
+ m_videoFrameHasDrawn = false;
+ m_assetURL = url;
+
+ // Don't do any more work if the url is empty.
+ if (!url.length())
+ return;
+
+ if (m_preload == MediaPlayer::None) {
+ LOG(Media, "MediaPlayerPrivateAVFoundation::load(%p) - preload==none so returning", this);
+ m_delayingLoad = true;
+ return;
+ }
+
+ prepareToPlay();
+}
+
+void MediaPlayerPrivateAVFoundation::playabilityKnown()
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundation::playabilityKnown(%p)", this);
+
+ updateStates();
+ if (m_assetIsPlayable)
+ return;
+
+ // Nothing more to do if we already have all of the item's metadata.
+ if (assetStatus() > MediaPlayerAVAssetStatusLoading) {
+ LOG(Media, "MediaPlayerPrivateAVFoundation::playabilityKnown(%p) - all metadata loaded", this);
+ return;
+ }
+
+ // At this point we are supposed to load metadata. It is OK to ask the asset to load the same
+ // information multiple times, because if it has already been loaded the completion handler
+ // will just be called synchronously.
+ m_loadingMetadata = true;
+ beginLoadingMetadata();
+}
+
+void MediaPlayerPrivateAVFoundation::prepareToPlay()
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundation::prepareToPlay(%p)", this);
+
+ m_preload = MediaPlayer::Auto;
+ if (m_havePreparedToPlay)
+ return;
+ m_havePreparedToPlay = true;
+
+ m_delayingLoad = false;
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : 0;
+ ApplicationCacheHost* cacheHost = frame ? frame->loader()->documentLoader()->applicationCacheHost() : 0;
+ ApplicationCacheResource* resource = 0;
+ if (cacheHost && cacheHost->shouldLoadResourceFromApplicationCache(ResourceRequest(m_assetURL), resource) && resource)
+ createAVPlayerForCacheResource(resource);
+ else
+#endif
+ createAVPlayerForURL(m_assetURL);
+ checkPlayability();
+}
+
+void MediaPlayerPrivateAVFoundation::paint(GraphicsContext*, const IntRect&)
+{
+ // This is the base class, only need to remember that a frame has been drawn.
+ m_videoFrameHasDrawn = true;
+}
+
+float MediaPlayerPrivateAVFoundation::duration() const
+{
+ if (!metaDataAvailable())
+ return 0;
+
+ if (m_cachedDuration == invalidTime) {
+ m_cachedDuration = platformDuration();
+ LOG(Media, "MediaPlayerPrivateAVFMac::duration(%p) - caching %f", this, m_cachedDuration);
+ }
+
+ return m_cachedDuration;
+}
+
+void MediaPlayerPrivateAVFoundation::seek(float time)
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundation::seek(%p) - seeking to %f", this, time);
+ if (!metaDataAvailable())
+ return;
+
+ if (time > duration())
+ time = duration();
+
+ m_seekTo = time;
+
+ seekToTime(time);
+}
+
+void MediaPlayerPrivateAVFoundation::setRate(float rate)
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundation::setRate(%p) - seting to %f", this, rate);
+ m_requestedRate = rate;
+}
+
+bool MediaPlayerPrivateAVFoundation::paused() const
+{
+ if (!metaDataAvailable())
+ return true;
+
+ return rate() == 0;
+}
+
+bool MediaPlayerPrivateAVFoundation::seeking() const
+{
+ if (!metaDataAvailable())
+ return false;
+
+ return m_seekTo != invalidTime;
+}
+
+IntSize MediaPlayerPrivateAVFoundation::naturalSize() const
+{
+ if (!metaDataAvailable())
+ return IntSize();
+
+ // In spite of the name of this method, return the natural size transformed by the
+ // initial movie scale because the spec says intrinsic size is:
+ //
+ // ... the dimensions of the resource in CSS pixels after taking into account the resource's
+ // dimensions, aspect ratio, clean aperture, resolution, and so forth, as defined for the
+ // format used by the resource
+
+ return m_cachedNaturalSize;
+}
+
+void MediaPlayerPrivateAVFoundation::setNaturalSize(IntSize size)
+{
+ IntSize oldSize = m_cachedNaturalSize;
+ m_cachedNaturalSize = size;
+ if (oldSize != m_cachedNaturalSize)
+ m_player->sizeChanged();
+}
+
+PassRefPtr<TimeRanges> MediaPlayerPrivateAVFoundation::buffered() const
+{
+ if (!m_cachedLoadedTimeRanges)
+ m_cachedLoadedTimeRanges = platformBufferedTimeRanges();
+
+ return m_cachedLoadedTimeRanges->copy();
+}
+
+float MediaPlayerPrivateAVFoundation::maxTimeSeekable() const
+{
+ if (!metaDataAvailable())
+ return 0;
+
+ if (!m_cachedMaxTimeSeekable)
+ m_cachedMaxTimeSeekable = platformMaxTimeSeekable();
+
+ LOG(Media, "MediaPlayerPrivateAVFoundation::maxTimeSeekable(%p) - returning %f", this, m_cachedMaxTimeSeekable);
+ return m_cachedMaxTimeSeekable;
+}
+
+float MediaPlayerPrivateAVFoundation::maxTimeLoaded() const
+{
+ if (!metaDataAvailable())
+ return 0;
+
+ if (!m_cachedMaxTimeLoaded)
+ m_cachedMaxTimeLoaded = platformMaxTimeLoaded();
+
+ return m_cachedMaxTimeLoaded;
+}
+
+unsigned MediaPlayerPrivateAVFoundation::bytesLoaded() const
+{
+ float dur = duration();
+ if (!dur)
+ return 0;
+ unsigned loaded = totalBytes() * maxTimeLoaded() / dur;
+ LOG(Media, "MediaPlayerPrivateAVFoundation::bytesLoaded(%p) - returning %i", this, loaded);
+ return loaded;
+}
+
+bool MediaPlayerPrivateAVFoundation::isReadyForVideoSetup() const
+{
+ return m_isAllowedToRender && m_readyState >= MediaPlayer::HaveMetadata && m_player->visible();
+}
+
+void MediaPlayerPrivateAVFoundation::prepareForRendering()
+{
+ if (m_isAllowedToRender)
+ return;
+ m_isAllowedToRender = true;
+
+ setUpVideoRendering();
+
+ if (currentRenderingMode() == MediaRenderingToLayer || preferredRenderingMode() == MediaRenderingToLayer)
+ m_player->mediaPlayerClient()->mediaPlayerRenderingModeChanged(m_player);
+}
+
+bool MediaPlayerPrivateAVFoundation::supportsFullscreen() const
+{
+#if ENABLE(FULLSCREEN_API)
+ return true;
+#else
+ // FIXME: WebVideoFullscreenController assumes a QTKit/QuickTime media engine
+ return false;
+#endif
+}
+
+void MediaPlayerPrivateAVFoundation::updateStates()
+{
+ MediaPlayer::NetworkState oldNetworkState = m_networkState;
+ MediaPlayer::ReadyState oldReadyState = m_readyState;
+
+ LOG(Media, "MediaPlayerPrivateAVFoundation::updateStates(%p) - entering with networkState = %i, readyState = %i",
+ this, static_cast<int>(m_networkState), static_cast<int>(m_readyState));
+
+ if (m_loadingMetadata)
+ m_networkState = MediaPlayer::Loading;
+ else {
+ // -loadValuesAsynchronouslyForKeys:completionHandler: has invoked its handler; test status of keys and determine state.
+ AVAssetStatus avAssetStatus = assetStatus();
+ ItemStatus itemStatus = playerItemStatus();
+
+ m_assetIsPlayable = (avAssetStatus == MediaPlayerAVAssetStatusPlayable);
+ if (m_readyState < MediaPlayer::HaveMetadata && avAssetStatus > MediaPlayerAVAssetStatusLoading) {
+ if (m_assetIsPlayable) {
+ if (itemStatus == MediaPlayerAVPlayerItemStatusUnknown) {
+ if (avAssetStatus == MediaPlayerAVAssetStatusFailed || m_preload > MediaPlayer::MetaData) {
+ // We may have a playable asset that doesn't support inspection prior to playback; go ahead
+ // and create the AVPlayerItem now. When the AVPlayerItem becomes ready to play, we will
+ // have access to its metadata. Or we may have been asked to become ready to play immediately.
+ m_networkState = MediaPlayer::Loading;
+ prepareToPlay();
+ } else
+ m_networkState = MediaPlayer::Idle;
+ }
+ if (avAssetStatus == MediaPlayerAVAssetStatusLoaded)
+ m_readyState = MediaPlayer::HaveMetadata;
+ } else {
+ // FIX ME: fetch the error associated with the @"playable" key to distinguish between format
+ // and network errors.
+ m_networkState = MediaPlayer::FormatError;
+ }
+ }
+
+ if (avAssetStatus >= MediaPlayerAVAssetStatusLoaded && itemStatus > MediaPlayerAVPlayerItemStatusUnknown) {
+ if (seeking())
+ m_readyState = m_readyState >= MediaPlayer::HaveMetadata ? MediaPlayer::HaveMetadata : MediaPlayer::HaveNothing;
+ else {
+ float maxLoaded = maxTimeLoaded();
+ switch (itemStatus) {
+ case MediaPlayerAVPlayerItemStatusUnknown:
+ break;
+ case MediaPlayerAVPlayerItemStatusFailed:
+ m_networkState = MediaPlayer::DecodeError;
+ break;
+ case MediaPlayerAVPlayerItemStatusPlaybackLikelyToKeepUp:
+ m_readyState = MediaPlayer::HaveEnoughData;
+ break;
+ case MediaPlayerAVPlayerItemStatusReadyToPlay:
+ case MediaPlayerAVPlayerItemStatusPlaybackBufferEmpty:
+ case MediaPlayerAVPlayerItemStatusPlaybackBufferFull:
+ if (maxLoaded > currentTime())
+ m_readyState = MediaPlayer::HaveFutureData;
+ else
+ m_readyState = MediaPlayer::HaveCurrentData;
+ break;
+ }
+
+ if (itemStatus >= MediaPlayerAVPlayerItemStatusReadyToPlay)
+ m_networkState = (maxLoaded == duration()) ? MediaPlayer::Loaded : MediaPlayer::Loading;
+ }
+ }
+ }
+
+ if (isReadyForVideoSetup() && currentRenderingMode() != preferredRenderingMode())
+ setUpVideoRendering();
+
+ if (m_networkState != oldNetworkState)
+ m_player->networkStateChanged();
+
+ if (m_readyState != oldReadyState)
+ m_player->readyStateChanged();
+
+ LOG(Media, "MediaPlayerPrivateAVFoundation::updateStates(%p) - exiting with networkState = %i, readyState = %i",
+ this, static_cast<int>(m_networkState), static_cast<int>(m_readyState));
+}
+
+void MediaPlayerPrivateAVFoundation::setSize(const IntSize&)
+{
+}
+
+void MediaPlayerPrivateAVFoundation::setVisible(bool visible)
+{
+ if (m_visible == visible)
+ return;
+
+ m_visible = visible;
+ if (visible)
+ setUpVideoRendering();
+ else
+ tearDownVideoRendering();
+}
+
+bool MediaPlayerPrivateAVFoundation::hasAvailableVideoFrame() const
+{
+ if (currentRenderingMode() == MediaRenderingToLayer)
+ return videoLayerIsReadyToDisplay();
+
+ // When using the software renderer we hope someone will signal that a frame is available so we might as well
+ // wait until we know that a frame has been drawn.
+ return m_videoFrameHasDrawn;
+}
+
+void MediaPlayerPrivateAVFoundation::acceleratedRenderingStateChanged()
+{
+ // Set up or change the rendering path if necessary.
+ setUpVideoRendering();
+}
+
+void MediaPlayerPrivateAVFoundation::metadataLoaded()
+{
+ m_loadingMetadata = false;
+ updateStates();
+}
+
+void MediaPlayerPrivateAVFoundation::loadStateChanged()
+{
+ if (m_ignoreLoadStateChanges)
+ return;
+ updateStates();
+}
+
+void MediaPlayerPrivateAVFoundation::rateChanged()
+{
+ updateStates();
+ m_player->rateChanged();
+}
+
+void MediaPlayerPrivateAVFoundation::loadedTimeRangesChanged()
+{
+ m_cachedLoadedTimeRanges = 0;
+ m_cachedMaxTimeLoaded = 0;
+ updateStates();
+
+ // For some media files, reported duration is estimated and updated as media is loaded
+ // so report duration changed when the estimate is upated.
+ float dur = duration();
+ if (dur != m_reportedDuration) {
+ if (m_reportedDuration != invalidTime)
+ m_player->durationChanged();
+ m_reportedDuration = dur;
+ }
+}
+
+void MediaPlayerPrivateAVFoundation::seekableTimeRangesChanged()
+{
+ m_cachedMaxTimeSeekable = 0;
+}
+
+void MediaPlayerPrivateAVFoundation::timeChanged(double time)
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundation::timeChanged(%p) - time = %f", this, time);
+
+ if (m_seekTo == invalidTime)
+ return;
+
+ // AVFoundation may call our observer more than once during a seek, and we can't currently tell
+ // if we will be able to seek to an exact time, so assume that we are done seeking if we are
+ // "close enough" to the seek time.
+ const double smallSeekDelta = 1.0 / 100;
+
+ float currentRate = rate();
+ if ((currentRate > 0 && time >= m_seekTo) || (currentRate < 0 && time <= m_seekTo) || (abs(m_seekTo - time) <= smallSeekDelta)) {
+ m_seekTo = invalidTime;
+ updateStates();
+ m_player->timeChanged();
+ }
+}
+
+void MediaPlayerPrivateAVFoundation::didEnd()
+{
+ // Hang onto the current time and use it as duration from now on since we are definitely at
+ // the end of the movie. Do this because the initial duration is sometimes an estimate.
+ float now = currentTime();
+ if (now > 0)
+ m_cachedDuration = now;
+
+ updateStates();
+ m_player->timeChanged();
+}
+
+void MediaPlayerPrivateAVFoundation::repaint()
+{
+ m_videoFrameHasDrawn = true;
+ m_player->repaint();
+}
+
+MediaPlayer::MovieLoadType MediaPlayerPrivateAVFoundation::movieLoadType() const
+{
+ if (!metaDataAvailable() || assetStatus() == MediaPlayerAVAssetStatusUnknown)
+ return MediaPlayer::Unknown;
+
+ if (isinf(duration()))
+ return MediaPlayer::LiveStream;
+
+ return MediaPlayer::Download;
+}
+
+void MediaPlayerPrivateAVFoundation::setPreload(MediaPlayer::Preload preload)
+{
+ m_preload = preload;
+ if (m_delayingLoad && m_preload != MediaPlayer::None)
+ resumeLoad();
+}
+
+void MediaPlayerPrivateAVFoundation::setDelayCallbacks(bool delay)
+{
+ MutexLocker lock(m_queueMutex);
+ if (delay)
+ ++m_delayCallbacks;
+ else {
+ ASSERT(m_delayCallbacks);
+ --m_delayCallbacks;
+ }
+}
+
+void MediaPlayerPrivateAVFoundation::mainThreadCallback(void* context)
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundation::mainThreadCallback(%p)", context);
+ MediaPlayerPrivateAVFoundation* player = static_cast<MediaPlayerPrivateAVFoundation*>(context);
+ player->clearMainThreadPendingFlag();
+ player->dispatchNotification();
+}
+
+void MediaPlayerPrivateAVFoundation::clearMainThreadPendingFlag()
+{
+ MutexLocker lock(m_queueMutex);
+ m_mainThreadCallPending = false;
+}
+
+void MediaPlayerPrivateAVFoundation::scheduleMainThreadNotification(Notification::Type type, double time)
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundation::scheduleMainThreadNotification(%p) - notification %d", this, static_cast<int>(type));
+ m_queueMutex.lock();
+
+ // It is important to always process the properties in the order that we are notified,
+ // so always go through the queue because notifications happen on different threads.
+ m_queuedNotifications.append(Notification(type, time));
+
+ bool delayDispatch = m_delayCallbacks || !isMainThread();
+ if (delayDispatch && !m_mainThreadCallPending) {
+ m_mainThreadCallPending = true;
+ callOnMainThread(mainThreadCallback, this);
+ }
+
+ m_queueMutex.unlock();
+
+ if (delayDispatch) {
+ LOG(Media, "MediaPlayerPrivateAVFoundation::scheduleMainThreadNotification(%p) - early return", this);
+ return;
+ }
+
+ dispatchNotification();
+}
+
+void MediaPlayerPrivateAVFoundation::dispatchNotification()
+{
+ ASSERT(isMainThread());
+
+ Notification notification = Notification();
+ {
+ MutexLocker lock(m_queueMutex);
+
+ if (m_queuedNotifications.isEmpty())
+ return;
+
+ if (!m_delayCallbacks) {
+ // Only dispatch one notification callback per invocation because they can cause recursion.
+ notification = m_queuedNotifications.first();
+ m_queuedNotifications.remove(0);
+ }
+
+ if (!m_queuedNotifications.isEmpty() && !m_mainThreadCallPending)
+ callOnMainThread(mainThreadCallback, this);
+
+ if (!notification.isValid())
+ return;
+ }
+
+ LOG(Media, "MediaPlayerPrivateAVFoundation::dispatchNotification(%p) - dispatching %d", this, static_cast<int>(notification.type()));
+
+ switch (notification.type()) {
+ case Notification::ItemDidPlayToEndTime:
+ didEnd();
+ break;
+ case Notification::ItemTracksChanged:
+ tracksChanged();
+ break;
+ case Notification::ItemStatusChanged:
+ loadStateChanged();
+ break;
+ case Notification::ItemSeekableTimeRangesChanged:
+ seekableTimeRangesChanged();
+ loadStateChanged();
+ break;
+ case Notification::ItemLoadedTimeRangesChanged:
+ loadedTimeRangesChanged();
+ loadStateChanged();
+ break;
+ case Notification::ItemPresentationSizeChanged:
+ sizeChanged();
+ break;
+ case Notification::ItemIsPlaybackLikelyToKeepUpChanged:
+ loadStateChanged();
+ break;
+ case Notification::ItemIsPlaybackBufferEmptyChanged:
+ loadStateChanged();
+ break;
+ case Notification::ItemIsPlaybackBufferFullChanged:
+ loadStateChanged();
+ break;
+ case Notification::PlayerRateChanged:
+ rateChanged();
+ break;
+ case Notification::PlayerTimeChanged:
+ timeChanged(notification.time());
+ break;
+ case Notification::AssetMetadataLoaded:
+ metadataLoaded();
+ break;
+ case Notification::AssetPlayabilityKnown:
+ playabilityKnown();
+ break;
+ case Notification::None:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h
new file mode 100644
index 0000000..a768ab4
--- /dev/null
+++ b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MediaPlayerPrivateAVFoundation_h
+#define MediaPlayerPrivateAVFoundation_h
+
+#if ENABLE(VIDEO) && USE(AVFOUNDATION)
+
+#include "FloatSize.h"
+#include "MediaPlayerPrivate.h"
+#include "Timer.h"
+#include <wtf/RetainPtr.h>
+
+namespace WebCore {
+
+class ApplicationCacheResource;
+
+class MediaPlayerPrivateAVFoundation : public MediaPlayerPrivateInterface {
+public:
+
+ virtual void repaint();
+ virtual void metadataLoaded();
+ virtual void loadStateChanged();
+ virtual void playabilityKnown();
+ virtual void rateChanged();
+ virtual void loadedTimeRangesChanged();
+ virtual void seekableTimeRangesChanged();
+ virtual void timeChanged(double);
+ virtual void didEnd();
+
+ class Notification {
+ public:
+ enum Type {
+ None,
+ ItemDidPlayToEndTime,
+ ItemTracksChanged,
+ ItemStatusChanged,
+ ItemSeekableTimeRangesChanged,
+ ItemLoadedTimeRangesChanged,
+ ItemPresentationSizeChanged,
+ ItemIsPlaybackLikelyToKeepUpChanged,
+ ItemIsPlaybackBufferEmptyChanged,
+ ItemIsPlaybackBufferFullChanged,
+ AssetMetadataLoaded,
+ AssetPlayabilityKnown,
+ PlayerRateChanged,
+ PlayerTimeChanged
+ };
+
+ Notification()
+ : m_type(None)
+ , m_time(0)
+ {
+ }
+
+ Notification(Type type, double time)
+ : m_type(type)
+ , m_time(time)
+ {
+ }
+
+ Type type() { return m_type; }
+ bool isValid() { return m_type != None; }
+ double time() { return m_time; }
+
+ private:
+ Type m_type;
+ double m_time;
+ };
+
+ void scheduleMainThreadNotification(Notification::Type, double time = 0);
+ void dispatchNotification();
+ void clearMainThreadPendingFlag();
+
+protected:
+ MediaPlayerPrivateAVFoundation(MediaPlayer*);
+ virtual ~MediaPlayerPrivateAVFoundation();
+
+ // MediaPlayerPrivatePrivateInterface overrides.
+ virtual void load(const String& url);
+ virtual void cancelLoad() = 0;
+
+ virtual void prepareToPlay();
+ virtual PlatformMedia platformMedia() const = 0;
+
+ virtual void play() = 0;
+ virtual void pause() = 0;
+
+ virtual IntSize naturalSize() const;
+ virtual bool hasVideo() const { return m_cachedHasVideo; }
+ virtual bool hasAudio() const { return m_cachedHasAudio; }
+ virtual void setVisible(bool);
+ virtual float duration() const;
+ virtual float currentTime() const = 0;
+ virtual void seek(float);
+ virtual bool seeking() const;
+ virtual void setRate(float);
+ virtual bool paused() const;
+ virtual void setVolume(float) = 0;
+ virtual bool hasClosedCaptions() const { return m_cachedHasCaptions; }
+ virtual void setClosedCaptionsVisible(bool) = 0;
+ virtual MediaPlayer::NetworkState networkState() const { return m_networkState; }
+ virtual MediaPlayer::ReadyState readyState() const { return m_readyState; }
+ virtual float maxTimeSeekable() const;
+ virtual PassRefPtr<TimeRanges> buffered() const;
+ virtual unsigned bytesLoaded() const;
+ virtual void setSize(const IntSize&);
+ virtual void paint(GraphicsContext*, const IntRect&);
+ virtual void paintCurrentFrameInContext(GraphicsContext*, const IntRect&) = 0;
+ virtual void setPreload(MediaPlayer::Preload);
+ virtual bool hasAvailableVideoFrame() const;
+#if USE(ACCELERATED_COMPOSITING)
+ virtual PlatformLayer* platformLayer() const { return 0; }
+ virtual bool supportsAcceleratedRendering() const = 0;
+ virtual void acceleratedRenderingStateChanged();
+#endif
+ virtual bool hasSingleSecurityOrigin() const { return true; }
+ virtual MediaPlayer::MovieLoadType movieLoadType() const;
+ virtual void prepareForRendering();
+ virtual float mediaTimeForTimeValue(float) const = 0;
+
+ virtual bool supportsFullscreen() const;
+
+ // Required interfaces for concrete derived classes.
+ virtual void createAVPlayerForURL(const String& url) = 0;
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ virtual void createAVPlayerForCacheResource(ApplicationCacheResource*) = 0;
+#endif
+
+ enum ItemStatus {
+ MediaPlayerAVPlayerItemStatusUnknown,
+ MediaPlayerAVPlayerItemStatusFailed,
+ MediaPlayerAVPlayerItemStatusReadyToPlay,
+ MediaPlayerAVPlayerItemStatusPlaybackBufferEmpty,
+ MediaPlayerAVPlayerItemStatusPlaybackBufferFull,
+ MediaPlayerAVPlayerItemStatusPlaybackLikelyToKeepUp,
+ };
+ virtual ItemStatus playerItemStatus() const = 0;
+
+ enum AVAssetStatus {
+ MediaPlayerAVAssetStatusUnknown,
+ MediaPlayerAVAssetStatusLoading,
+ MediaPlayerAVAssetStatusFailed,
+ MediaPlayerAVAssetStatusCancelled,
+ MediaPlayerAVAssetStatusLoaded,
+ MediaPlayerAVAssetStatusPlayable,
+ };
+ virtual AVAssetStatus assetStatus() const = 0;
+
+ virtual void checkPlayability() = 0;
+ virtual float rate() const = 0;
+ virtual void seekToTime(float time) = 0;
+ virtual unsigned totalBytes() const = 0;
+ virtual PassRefPtr<TimeRanges> platformBufferedTimeRanges() const = 0;
+ virtual float platformMaxTimeSeekable() const = 0;
+ virtual float platformMaxTimeLoaded() const = 0;
+ virtual float platformDuration() const = 0;
+
+ virtual void beginLoadingMetadata() = 0;
+ virtual void tracksChanged() = 0;
+ virtual void sizeChanged() = 0;
+
+ virtual void createContextVideoRenderer() = 0;
+ virtual void destroyContextVideoRenderer() = 0;
+
+ virtual void createVideoLayer() = 0;
+ virtual void destroyVideoLayer() = 0;
+ virtual bool videoLayerIsReadyToDisplay() const = 0;
+
+ virtual bool hasContextRenderer() const = 0;
+ virtual bool hasLayerRenderer() const = 0;
+
+protected:
+ void resumeLoad();
+ void updateStates();
+
+ void setHasVideo(bool b) { m_cachedHasVideo = b; };
+ void setHasAudio(bool b) { m_cachedHasAudio = b; }
+ void setHasClosedCaptions(bool b) { m_cachedHasCaptions = b; }
+ void setDelayCallbacks(bool);
+ void setIgnoreLoadStateChanges(bool delay) { m_ignoreLoadStateChanges = delay; }
+ void setNaturalSize(IntSize);
+
+ enum MediaRenderingMode { MediaRenderingNone, MediaRenderingToContext, MediaRenderingToLayer };
+ MediaRenderingMode currentRenderingMode() const;
+ MediaRenderingMode preferredRenderingMode() const;
+
+ bool metaDataAvailable() const { return m_readyState >= MediaPlayer::HaveMetadata; }
+ float requestedRate() const { return m_requestedRate; }
+ float maxTimeLoaded() const;
+ bool isReadyForVideoSetup() const;
+ virtual void setUpVideoRendering();
+ virtual void tearDownVideoRendering();
+ bool hasSetUpVideoRendering() const;
+
+ static void mainThreadCallback(void*);
+
+private:
+
+ MediaPlayer* m_player;
+
+ Vector<Notification> m_queuedNotifications;
+ Mutex m_queueMutex;
+ bool m_mainThreadCallPending;
+
+ mutable RefPtr<TimeRanges> m_cachedLoadedTimeRanges;
+
+ MediaPlayer::NetworkState m_networkState;
+ MediaPlayer::ReadyState m_readyState;
+
+ String m_assetURL;
+ MediaPlayer::Preload m_preload;
+ FloatSize m_scaleFactor;
+
+ IntSize m_cachedNaturalSize;
+ mutable float m_cachedMaxTimeLoaded;
+ mutable float m_cachedMaxTimeSeekable;
+ mutable float m_cachedDuration;
+ float m_reportedDuration;
+
+ float m_seekTo;
+ float m_requestedRate;
+ int m_delayCallbacks;
+ bool m_havePreparedToPlay;
+ bool m_assetIsPlayable;
+ bool m_visible;
+ bool m_videoFrameHasDrawn;
+ bool m_loadingMetadata;
+ bool m_delayingLoad;
+ bool m_isAllowedToRender;
+ bool m_cachedHasAudio;
+ bool m_cachedHasVideo;
+ bool m_cachedHasCaptions;
+ bool m_ignoreLoadStateChanges;
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.h b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.h
new file mode 100644
index 0000000..cc00c15
--- /dev/null
+++ b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MediaPlayerPrivateAVFoundationObjC_h
+#define MediaPlayerPrivateAVFoundationObjC_h
+
+#if ENABLE(VIDEO) && USE(AVFOUNDATION)
+
+#include "MediaPlayerPrivateAVFoundation.h"
+
+#ifdef __OBJC__
+@class AVAsset;
+@class AVPlayer;
+@class AVPlayerItem;
+@class AVPlayerLayer;
+@class AVAssetImageGenerator;
+@class WebCoreAVFMovieObserver;
+#else
+class AVAsset;
+class AVPlayer;
+class AVPlayerItem;
+class AVPlayerLayer;
+class AVAssetImageGenerator;
+class WebCoreAVFMovieObserver;
+typedef struct objc_object *id;
+#endif
+
+namespace WebCore {
+
+class ApplicationCacheResource;
+
+class MediaPlayerPrivateAVFoundationObjC : public MediaPlayerPrivateAVFoundation {
+public:
+
+ static void registerMediaEngine(MediaEngineRegistrar);
+
+ void setAsset(id);
+ virtual void tracksChanged();
+
+private:
+ MediaPlayerPrivateAVFoundationObjC(MediaPlayer*);
+ ~MediaPlayerPrivateAVFoundationObjC();
+
+ // engine support
+ static MediaPlayerPrivateInterface* create(MediaPlayer* player);
+ static void getSupportedTypes(HashSet<String>& types);
+ static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs);
+ static bool isAvailable();
+
+ virtual void cancelLoad();
+
+ virtual PlatformMedia platformMedia() const;
+
+ virtual void play();
+ virtual void pause();
+ virtual float currentTime() const;
+ virtual void setVolume(float);
+ virtual void setClosedCaptionsVisible(bool);
+ virtual void paint(GraphicsContext*, const IntRect&);
+ virtual void paintCurrentFrameInContext(GraphicsContext*, const IntRect&);
+ virtual PlatformLayer* platformLayer() const;
+ virtual bool supportsAcceleratedRendering() const { return true; }
+ virtual float mediaTimeForTimeValue(float) const;
+
+ virtual void createAVPlayer();
+ virtual void createAVPlayerForURL(const String& url);
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ virtual void createAVPlayerForCacheResource(ApplicationCacheResource*);
+#endif
+ virtual MediaPlayerPrivateAVFoundation::ItemStatus playerItemStatus() const;
+ virtual MediaPlayerPrivateAVFoundation::AVAssetStatus assetStatus() const;
+
+ virtual void checkPlayability();
+ virtual float rate() const;
+ virtual void seekToTime(float time);
+ virtual unsigned totalBytes() const;
+ virtual PassRefPtr<TimeRanges> platformBufferedTimeRanges() const;
+ virtual float platformMaxTimeSeekable() const;
+ virtual float platformDuration() const;
+ virtual float platformMaxTimeLoaded() const;
+ virtual void beginLoadingMetadata();
+ virtual void sizeChanged();
+
+ virtual void createContextVideoRenderer();
+ virtual void destroyContextVideoRenderer();
+
+ virtual void createVideoLayer();
+ virtual void destroyVideoLayer();
+ virtual bool videoLayerIsReadyToDisplay() const;
+
+ virtual bool hasContextRenderer() const;
+ virtual bool hasLayerRenderer() const;
+
+ RetainPtr<CGImageRef> createImageForTimeInRect(float, const IntRect&);
+
+ MediaPlayer* m_player;
+ RetainPtr<AVAsset> m_avAsset;
+ RetainPtr<AVPlayer> m_avPlayer;
+ RetainPtr<AVPlayerItem> m_avPlayerItem;
+ RetainPtr<AVPlayerLayer> m_videoLayer;
+ RetainPtr<WebCoreAVFMovieObserver> m_objcObserver;
+ RetainPtr<AVAssetImageGenerator> m_imageGenerator;
+ id m_timeObserver;
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.mm b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.mm
new file mode 100644
index 0000000..55eb433
--- /dev/null
+++ b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.mm
@@ -0,0 +1,811 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+
+#if ENABLE(VIDEO) && USE(AVFOUNDATION)
+
+#import "MediaPlayerPrivateAVFoundationObjC.h"
+
+#import "ApplicationCacheResource.h"
+#import "BlockExceptions.h"
+#import "FloatConversion.h"
+#import "FrameView.h"
+#import "FloatConversion.h"
+#import "GraphicsContext.h"
+#import "KURL.h"
+#import "Logging.h"
+#import "SoftLinking.h"
+#import "TimeRanges.h"
+#import "WebCoreSystemInterface.h"
+#import <objc/objc-runtime.h>
+#import <wtf/UnusedParam.h>
+
+#import <CoreMedia/CoreMedia.h>
+#import <AVFoundation/AVFoundation.h>
+
+SOFT_LINK_FRAMEWORK(AVFoundation)
+SOFT_LINK_FRAMEWORK(CoreMedia)
+
+SOFT_LINK(CoreMedia, CMTimeCompare, int32_t, (CMTime time1, CMTime time2), (time1, time2))
+SOFT_LINK(CoreMedia, CMTimeMakeWithSeconds, CMTime, (Float64 seconds, int32_t preferredTimeScale), (seconds, preferredTimeScale))
+SOFT_LINK(CoreMedia, CMTimeGetSeconds, Float64, (CMTime time), (time))
+SOFT_LINK(CoreMedia, CMTimeRangeGetEnd, CMTime, (CMTimeRange range), (range))
+
+SOFT_LINK_CLASS(AVFoundation, AVPlayer)
+SOFT_LINK_CLASS(AVFoundation, AVPlayerItem)
+SOFT_LINK_CLASS(AVFoundation, AVPlayerLayer)
+SOFT_LINK_CLASS(AVFoundation, AVURLAsset)
+SOFT_LINK_CLASS(AVFoundation, AVAssetImageGenerator)
+
+SOFT_LINK_POINTER(AVFoundation, AVMediaCharacteristicVisual, NSString *)
+SOFT_LINK_POINTER(AVFoundation, AVMediaCharacteristicAudible, NSString *)
+SOFT_LINK_POINTER(AVFoundation, AVMediaTypeClosedCaption, NSString *)
+SOFT_LINK_POINTER(AVFoundation, AVPlayerItemDidPlayToEndTimeNotification, NSString *)
+SOFT_LINK_POINTER(AVFoundation, AVAssetImageGeneratorApertureModeCleanAperture, NSString *)
+
+SOFT_LINK_CONSTANT(CoreMedia, kCMTimeZero, CMTime)
+
+#define AVPlayer getAVPlayerClass()
+#define AVPlayerItem getAVPlayerItemClass()
+#define AVPlayerLayer getAVPlayerLayerClass()
+#define AVURLAsset getAVURLAssetClass()
+#define AVAssetImageGenerator getAVAssetImageGeneratorClass()
+
+#define AVMediaCharacteristicVisual getAVMediaCharacteristicVisual()
+#define AVMediaCharacteristicAudible getAVMediaCharacteristicAudible()
+#define AVMediaTypeClosedCaption getAVMediaTypeClosedCaption()
+#define AVPlayerItemDidPlayToEndTimeNotification getAVPlayerItemDidPlayToEndTimeNotification()
+#define AVAssetImageGeneratorApertureModeCleanAperture getAVAssetImageGeneratorApertureModeCleanAperture()
+
+#define kCMTimeZero getkCMTimeZero()
+
+using namespace WebCore;
+using namespace std;
+
+enum MediaPlayerAVFoundationObservationContext {
+ MediaPlayerAVFoundationObservationContextPlayerItem,
+ MediaPlayerAVFoundationObservationContextPlayer
+};
+
+@interface WebCoreAVFMovieObserver : NSObject
+{
+ MediaPlayerPrivateAVFoundationObjC* m_callback;
+ int m_delayCallbacks;
+}
+-(id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback;
+-(void)disconnect;
+-(void)playableKnown;
+-(void)metadataLoaded;
+-(void)timeChanged:(double)time;
+-(void)didEnd:(NSNotification *)notification;
+-(void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary *)change context:(MediaPlayerAVFoundationObservationContext)context;
+@end
+
+namespace WebCore {
+
+static NSArray *assetMetadataKeyNames();
+static NSArray *itemKVOProperties();
+
+#if !LOG_DISABLED
+static const char *boolString(bool val)
+{
+ return val ? "true" : "false";
+}
+#endif
+
+static const float invalidTime = -1.0f;
+
+MediaPlayerPrivateInterface* MediaPlayerPrivateAVFoundationObjC::create(MediaPlayer* player)
+{
+ return new MediaPlayerPrivateAVFoundationObjC(player);
+}
+
+void MediaPlayerPrivateAVFoundationObjC::registerMediaEngine(MediaEngineRegistrar registrar)
+{
+ if (isAvailable())
+ registrar(create, getSupportedTypes, supportsType, 0, 0, 0);
+}
+
+MediaPlayerPrivateAVFoundationObjC::MediaPlayerPrivateAVFoundationObjC(MediaPlayer* player)
+ : MediaPlayerPrivateAVFoundation(player)
+ , m_objcObserver(AdoptNS, [[WebCoreAVFMovieObserver alloc] initWithCallback:this])
+ , m_timeObserver(0)
+{
+}
+
+MediaPlayerPrivateAVFoundationObjC::~MediaPlayerPrivateAVFoundationObjC()
+{
+ cancelLoad();
+ [m_objcObserver.get() disconnect];
+}
+
+void MediaPlayerPrivateAVFoundationObjC::cancelLoad()
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::cancelLoad(%p)", this);
+ tearDownVideoRendering();
+
+ [[NSNotificationCenter defaultCenter] removeObserver:m_objcObserver.get()];
+
+ // Tell our observer to do nothing when our cancellation of pending loading calls its completion handler.
+ setIgnoreLoadStateChanges(true);
+ if (m_avAsset) {
+ [m_avAsset.get() cancelLoading];
+ m_avAsset = nil;
+ }
+ if (m_avPlayerItem) {
+ for (NSString *keyName in itemKVOProperties())
+ [m_avPlayerItem.get() removeObserver:m_objcObserver.get() forKeyPath:keyName];
+
+ m_avPlayerItem = nil;
+ }
+ if (m_avPlayer) {
+ if (m_timeObserver)
+ [m_avPlayer.get() removeTimeObserver:m_timeObserver];
+ [m_avPlayer.get() removeObserver:m_objcObserver.get() forKeyPath:@"rate"];
+ m_avPlayer = nil;
+ }
+ setIgnoreLoadStateChanges(false);
+}
+
+bool MediaPlayerPrivateAVFoundationObjC::hasLayerRenderer() const
+{
+ return m_videoLayer;
+}
+
+bool MediaPlayerPrivateAVFoundationObjC::hasContextRenderer() const
+{
+ return m_imageGenerator;
+}
+
+void MediaPlayerPrivateAVFoundationObjC::createContextVideoRenderer()
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createContextVideoRenderer(%p)", this);
+
+ if (!m_avAsset || m_imageGenerator)
+ return;
+
+ m_imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:m_avAsset.get()];
+
+ [m_imageGenerator.get() setApertureMode:AVAssetImageGeneratorApertureModeCleanAperture];
+ [m_imageGenerator.get() setAppliesPreferredTrackTransform:YES];
+
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createImageGenerator(%p) - returning %p", this, m_imageGenerator.get());
+}
+
+void MediaPlayerPrivateAVFoundationObjC::destroyContextVideoRenderer()
+{
+ if (!m_imageGenerator)
+ return;
+
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::destroyContextVideoRenderer(%p) - destroying", this, m_imageGenerator.get());
+
+ m_imageGenerator = 0;
+}
+
+void MediaPlayerPrivateAVFoundationObjC::createVideoLayer()
+{
+ if (!m_avPlayer)
+ return;
+
+ if (!m_videoLayer) {
+ m_videoLayer.adoptNS([[AVPlayerLayer alloc] init]);
+ [m_videoLayer.get() setPlayer:m_avPlayer.get()];
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createVideoLayer(%p) - returning", this, m_videoLayer.get());
+ }
+}
+
+void MediaPlayerPrivateAVFoundationObjC::destroyVideoLayer()
+{
+ if (!m_videoLayer)
+ return;
+
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::destroyVideoLayer(%p) - destroying", this, m_videoLayer.get());
+
+ [m_videoLayer.get() setPlayer:nil];
+
+ m_videoLayer = 0;
+}
+
+bool MediaPlayerPrivateAVFoundationObjC::videoLayerIsReadyToDisplay() const
+{
+ return (m_videoLayer && [m_videoLayer.get() isReadyForDisplay]);
+}
+
+void MediaPlayerPrivateAVFoundationObjC::createAVPlayerForURL(const String& url)
+{
+ setDelayCallbacks(true);
+
+ if (!m_avAsset) {
+ NSURL *cocoaURL = KURL(ParsedURLString, url);
+ m_avAsset.adoptNS([[AVURLAsset alloc] initWithURL:cocoaURL options:nil]);
+ }
+
+ createAVPlayer();
+}
+
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+void MediaPlayerPrivateAVFoundationObjC::createAVPlayerForCacheResource(ApplicationCacheResource* resource)
+{
+ // AVFoundation can't open arbitrary data pointers, so if this ApplicationCacheResource doesn't
+ // have a valid local path, just open the resource's original URL.
+ if (resource->path().isEmpty()) {
+ createAVPlayerForURL(resource->url());
+ return;
+ }
+
+ setDelayCallbacks(true);
+
+ if (!m_avAsset) {
+ NSURL* localURL = [NSURL fileURLWithPath:resource->path()];
+ m_avAsset.adoptNS([[AVURLAsset alloc] initWithURL:localURL options:nil]);
+ }
+
+ createAVPlayer();
+}
+#endif
+
+void MediaPlayerPrivateAVFoundationObjC::createAVPlayer()
+{
+ if (!m_avPlayer) {
+ m_avPlayer.adoptNS([[AVPlayer alloc] init]);
+
+ [m_avPlayer.get() addObserver:m_objcObserver.get() forKeyPath:@"rate" options:nil context:(void *)MediaPlayerAVFoundationObservationContextPlayer];
+
+ // Add a time observer, ask to be called infrequently because we don't really want periodic callbacks but
+ // our observer will also be called whenever a seek happens.
+ const double veryLongInterval = 60*60*60*24*30;
+ WebCoreAVFMovieObserver *observer = m_objcObserver.get();
+ m_timeObserver = [m_avPlayer.get() addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(veryLongInterval, 10) queue:nil usingBlock:^(CMTime time){
+ [observer timeChanged:CMTimeGetSeconds(time)];
+ }];
+ }
+
+ if (!m_avPlayerItem) {
+ // Create the player item so we can media data.
+ m_avPlayerItem.adoptNS([[AVPlayerItem alloc] initWithAsset:m_avAsset.get()]);
+
+ [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()selector:@selector(didEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:m_avPlayerItem.get()];
+
+ for (NSString *keyName in itemKVOProperties())
+ [m_avPlayerItem.get() addObserver:m_objcObserver.get() forKeyPath:keyName options:nil context:(void *)MediaPlayerAVFoundationObservationContextPlayerItem];
+
+ [m_avPlayer.get() replaceCurrentItemWithPlayerItem:m_avPlayerItem.get()];
+ }
+
+ setDelayCallbacks(false);
+}
+
+void MediaPlayerPrivateAVFoundationObjC::checkPlayability()
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::checkPlayability(%p)", this);
+
+ [m_avAsset.get() loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:@"playable"] completionHandler:^{
+ [m_objcObserver.get() playableKnown];
+ }];
+}
+
+void MediaPlayerPrivateAVFoundationObjC::beginLoadingMetadata()
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::playabilityKnown(%p) - requesting metadata loading", this);
+ [m_avAsset.get() loadValuesAsynchronouslyForKeys:[assetMetadataKeyNames() retain] completionHandler:^{
+ [m_objcObserver.get() metadataLoaded];
+ }];
+}
+
+MediaPlayerPrivateAVFoundation::ItemStatus MediaPlayerPrivateAVFoundationObjC::playerItemStatus() const
+{
+ if (!m_avPlayerItem)
+ return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusUnknown;
+
+ AVPlayerItemStatus status = [m_avPlayerItem.get() status];
+ if (status == AVPlayerItemStatusUnknown)
+ return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusUnknown;
+ if (status == AVPlayerItemStatusFailed)
+ return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusFailed;
+ if ([m_avPlayerItem.get() isPlaybackLikelyToKeepUp])
+ return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusPlaybackLikelyToKeepUp;
+ if ([m_avPlayerItem.get() isPlaybackBufferFull])
+ return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusPlaybackBufferFull;
+ if ([m_avPlayerItem.get() isPlaybackBufferEmpty])
+ return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusPlaybackBufferEmpty;
+
+ return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusReadyToPlay;
+}
+
+PlatformMedia MediaPlayerPrivateAVFoundationObjC::platformMedia() const
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::platformMedia(%p)", this);
+ PlatformMedia pm;
+ pm.type = PlatformMedia::AVFoundationMediaPlayerType;
+ pm.media.avfMediaPlayer = m_avPlayer.get();
+ return pm;
+}
+
+PlatformLayer* MediaPlayerPrivateAVFoundationObjC::platformLayer() const
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::platformLayer(%p)", this);
+ return m_videoLayer.get();
+}
+
+void MediaPlayerPrivateAVFoundationObjC::play()
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::play(%p)", this);
+ if (!metaDataAvailable())
+ return;
+
+ setDelayCallbacks(true);
+ [m_avPlayer.get() setRate:requestedRate()];
+ setDelayCallbacks(false);
+}
+
+void MediaPlayerPrivateAVFoundationObjC::pause()
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::pause(%p)", this);
+ if (!metaDataAvailable())
+ return;
+
+ setDelayCallbacks(true);
+ [m_avPlayer.get() setRate:nil];
+ setDelayCallbacks(false);
+}
+
+float MediaPlayerPrivateAVFoundationObjC::platformDuration() const
+{
+ if (!metaDataAvailable() || !m_avPlayerItem)
+ return 0;
+
+ float duration;
+ CMTime cmDuration = [m_avPlayerItem.get() duration];
+ if (CMTIME_IS_NUMERIC(cmDuration))
+ duration = narrowPrecisionToFloat(CMTimeGetSeconds(cmDuration));
+ else if (CMTIME_IS_INDEFINITE(cmDuration))
+ duration = numeric_limits<float>::infinity();
+ else {
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::duration(%p) - invalid duration, returning 0", this);
+ return 0;
+ }
+
+ return duration;
+}
+
+float MediaPlayerPrivateAVFoundationObjC::currentTime() const
+{
+ if (!metaDataAvailable() || !m_avPlayerItem)
+ return 0;
+
+ CMTime itemTime = [m_avPlayerItem.get() currentTime];
+ if (CMTIME_IS_NUMERIC(itemTime))
+ return narrowPrecisionToFloat(CMTimeGetSeconds(itemTime));
+
+ return 0;
+}
+
+void MediaPlayerPrivateAVFoundationObjC::seekToTime(float time)
+{
+ // setCurrentTime generates several event callbacks, update afterwards.
+ setDelayCallbacks(true);
+
+ float now = currentTime();
+ if (time != now)
+ [m_avPlayerItem.get() seekToTime:CMTimeMakeWithSeconds(time, 600) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
+ else {
+ // Force a call to the "time changed" notifier manually because a seek to the current time is a noop
+ // so the seek will never seem to complete.
+ [m_objcObserver.get() timeChanged:now];
+ }
+
+ setDelayCallbacks(false);
+}
+
+void MediaPlayerPrivateAVFoundationObjC::setVolume(float volume)
+{
+ if (!metaDataAvailable())
+ return;
+
+ [m_avPlayer.get() setVolume:volume];
+}
+
+void MediaPlayerPrivateAVFoundationObjC::setClosedCaptionsVisible(bool closedCaptionsVisible)
+{
+ if (!metaDataAvailable())
+ return;
+
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::setClosedCaptionsVisible(%p) - setting to %s", this, boolString(closedCaptionsVisible));
+ [m_avPlayer.get() setClosedCaptionDisplayEnabled:closedCaptionsVisible];
+}
+
+float MediaPlayerPrivateAVFoundationObjC::rate() const
+{
+ if (!metaDataAvailable())
+ return 0;
+
+ return [m_avPlayer.get() rate];
+}
+
+PassRefPtr<TimeRanges> MediaPlayerPrivateAVFoundationObjC::platformBufferedTimeRanges() const
+{
+ RefPtr<TimeRanges> timeRanges = TimeRanges::create();
+
+ if (!m_avPlayerItem)
+ return timeRanges.release();
+
+ NSArray *loadedRanges = [m_avPlayerItem.get() loadedTimeRanges];
+ for (NSValue *thisRangeValue in loadedRanges) {
+ CMTimeRange timeRange = [thisRangeValue CMTimeRangeValue];
+ if (CMTIMERANGE_IS_VALID(timeRange) && !CMTIMERANGE_IS_EMPTY(timeRange)) {
+ float rangeStart = narrowPrecisionToFloat(CMTimeGetSeconds(timeRange.start));
+ float rangeEnd = narrowPrecisionToFloat(CMTimeGetSeconds(CMTimeRangeGetEnd(timeRange)));
+ timeRanges->add(rangeStart, rangeEnd);
+ }
+ }
+ return timeRanges.release();
+}
+
+float MediaPlayerPrivateAVFoundationObjC::platformMaxTimeSeekable() const
+{
+ NSArray *seekableRanges = [m_avPlayerItem.get() seekableTimeRanges];
+ if (!seekableRanges)
+ return 0;
+
+ float maxTimeSeekable = 0;
+ for (NSValue *thisRangeValue in seekableRanges) {
+ CMTimeRange timeRange = [thisRangeValue CMTimeRangeValue];
+ if (!CMTIMERANGE_IS_VALID(timeRange) || CMTIMERANGE_IS_EMPTY(timeRange))
+ continue;
+
+ float endOfRange = narrowPrecisionToFloat(CMTimeGetSeconds(CMTimeRangeGetEnd(timeRange)));
+ if (maxTimeSeekable < endOfRange)
+ maxTimeSeekable = endOfRange;
+ }
+ return maxTimeSeekable;
+}
+
+float MediaPlayerPrivateAVFoundationObjC::platformMaxTimeLoaded() const
+{
+ NSArray *loadedRanges = [m_avPlayerItem.get() loadedTimeRanges];
+ if (!loadedRanges)
+ return 0;
+
+ float maxTimeLoaded = 0;
+ for (NSValue *thisRangeValue in loadedRanges) {
+ CMTimeRange timeRange = [thisRangeValue CMTimeRangeValue];
+ if (!CMTIMERANGE_IS_VALID(timeRange) || CMTIMERANGE_IS_EMPTY(timeRange))
+ continue;
+
+ float endOfRange = narrowPrecisionToFloat(CMTimeGetSeconds(CMTimeRangeGetEnd(timeRange)));
+ if (maxTimeLoaded < endOfRange)
+ maxTimeLoaded = endOfRange;
+ }
+
+ return maxTimeLoaded;
+}
+
+unsigned MediaPlayerPrivateAVFoundationObjC::totalBytes() const
+{
+ if (!metaDataAvailable())
+ return 0;
+
+ long long totalMediaSize = 0;
+ NSArray *tracks = [m_avAsset.get() tracks];
+ for (AVAssetTrack *thisTrack in tracks)
+ totalMediaSize += [thisTrack totalSampleDataLength];
+
+ return static_cast<unsigned>(totalMediaSize);
+}
+
+void MediaPlayerPrivateAVFoundationObjC::setAsset(id asset)
+{
+ m_avAsset = asset;
+}
+
+MediaPlayerPrivateAVFoundation::AVAssetStatus MediaPlayerPrivateAVFoundationObjC::assetStatus() const
+{
+ if (!m_avAsset)
+ return MediaPlayerAVAssetStatusUnknown;
+
+ for (NSString *keyName in assetMetadataKeyNames()) {
+ AVKeyValueStatus keyStatus = [m_avAsset.get() statusOfValueForKey:keyName error:nil];
+ if (keyStatus < AVKeyValueStatusLoaded)
+ return MediaPlayerAVAssetStatusLoading;// At least one key is not loaded yet.
+
+ if (keyStatus == AVKeyValueStatusFailed)
+ return MediaPlayerAVAssetStatusFailed; // At least one key could not be loaded.
+ if (keyStatus == AVKeyValueStatusCancelled)
+ return MediaPlayerAVAssetStatusCancelled; // Loading of at least one key was cancelled.
+ }
+
+ if ([[m_avAsset.get() valueForKey:@"playable"] boolValue])
+ return MediaPlayerAVAssetStatusPlayable;
+
+ return MediaPlayerAVAssetStatusLoaded;
+}
+
+void MediaPlayerPrivateAVFoundationObjC::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& rect)
+{
+ if (!metaDataAvailable() || context->paintingDisabled())
+ return;
+
+ paint(context, rect);
+}
+
+void MediaPlayerPrivateAVFoundationObjC::paint(GraphicsContext* context, const IntRect& rect)
+{
+ if (!metaDataAvailable() || context->paintingDisabled())
+ return;
+
+ setDelayCallbacks(true);
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
+ RetainPtr<CGImageRef> image = createImageForTimeInRect(currentTime(), rect);
+ if (image) {
+ context->save();
+ context->translate(rect.x(), rect.y() + rect.height());
+ context->scale(FloatSize(1.0f, -1.0f));
+ context->setImageInterpolationQuality(InterpolationLow);
+ IntRect paintRect(IntPoint(0, 0), IntSize(rect.width(), rect.height()));
+ CGContextDrawImage(context->platformContext(), CGRectMake(0, 0, paintRect.width(), paintRect.height()), image.get());
+ context->restore();
+ image = 0;
+ }
+
+ END_BLOCK_OBJC_EXCEPTIONS;
+ setDelayCallbacks(false);
+
+ MediaPlayerPrivateAVFoundation::paint(context, rect);
+}
+
+static HashSet<String> mimeTypeCache()
+{
+ DEFINE_STATIC_LOCAL(HashSet<String>, cache, ());
+ static bool typeListInitialized = false;
+
+ if (typeListInitialized)
+ return cache;
+ typeListInitialized = true;
+
+ NSArray *types = [AVURLAsset audiovisualMIMETypes];
+ for (NSString *mimeType in types)
+ cache.add(mimeType);
+
+ return cache;
+}
+
+RetainPtr<CGImageRef> MediaPlayerPrivateAVFoundationObjC::createImageForTimeInRect(float time, const IntRect& rect)
+{
+ if (!m_imageGenerator)
+ createContextVideoRenderer();
+ ASSERT(m_imageGenerator);
+
+#if !LOG_DISABLED
+ double start = WTF::currentTime();
+#endif
+
+ [m_imageGenerator.get() setMaximumSize:CGSize(rect.size())];
+ CGImageRef image = [m_imageGenerator.get() copyCGImageAtTime:CMTimeMakeWithSeconds(time, 600) actualTime:nil error:nil];
+
+#if !LOG_DISABLED
+ double duration = WTF::currentTime() - start;
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createImageForTimeInRect(%p) - creating image took %.4f", this, narrowPrecisionToFloat(duration));
+#endif
+
+ return image;
+}
+
+void MediaPlayerPrivateAVFoundationObjC::getSupportedTypes(HashSet<String>& supportedTypes)
+{
+ supportedTypes = mimeTypeCache();
+}
+
+MediaPlayer::SupportsType MediaPlayerPrivateAVFoundationObjC::supportsType(const String& type, const String& codecs)
+{
+ // Only return "IsSupported" if there is no codecs parameter for now as there is no way to ask if it supports an
+ // extended MIME type until rdar://6220037 is fixed.
+ if (mimeTypeCache().contains(type))
+ return codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported;
+
+ return MediaPlayer::IsNotSupported;
+}
+
+bool MediaPlayerPrivateAVFoundationObjC::isAvailable()
+{
+ return true;
+}
+
+float MediaPlayerPrivateAVFoundationObjC::mediaTimeForTimeValue(float timeValue) const
+{
+ if (!metaDataAvailable())
+ return timeValue;
+
+ // FIXME - impossible to implement until rdar://8721510 is fixed.
+ return timeValue;
+}
+
+void MediaPlayerPrivateAVFoundationObjC::tracksChanged()
+{
+ // This is called whenever the tracks collection changes so cache hasVideo and hasAudio since we get
+ // asked about those fairly fequently.
+ setHasVideo([[m_avAsset.get() tracksWithMediaCharacteristic:AVMediaCharacteristicVisual] count]);
+ setHasAudio([[m_avAsset.get() tracksWithMediaCharacteristic:AVMediaCharacteristicAudible] count]);
+ setHasClosedCaptions([[m_avAsset.get() tracksWithMediaType:AVMediaTypeClosedCaption] count]);
+
+ sizeChanged();
+}
+
+void MediaPlayerPrivateAVFoundationObjC::sizeChanged()
+{
+ NSArray *tracks = [m_avAsset.get() tracks];
+
+ // Some assets don't report track properties until they are completely ready to play, but we
+ // want to report a size as early as possible so use presentationSize when an asset has no tracks.
+ if (![tracks count]) {
+ setNaturalSize(IntSize([m_avPlayerItem.get() presentationSize]));
+ return;
+ }
+
+ // AVAsset's 'naturalSize' property only considers the movie's first video track, so we need to compute
+ // the union of all visual track rects.
+ CGRect trackUnionRect = CGRectZero;
+ for (AVAssetTrack *track in tracks) {
+ CGSize trackSize = [track naturalSize];
+ CGRect trackRect = CGRectMake(0, 0, trackSize.width, trackSize.height);
+ trackUnionRect = CGRectUnion(trackUnionRect, CGRectApplyAffineTransform(trackRect, [track preferredTransform]));
+ }
+
+ // The movie is always displayed at 0,0 so move the track rect to the origin before using width and height.
+ trackUnionRect = CGRectOffset(trackUnionRect, trackUnionRect.origin.x, trackUnionRect.origin.y);
+
+ // Also look at the asset's preferred transform so we account for a movie matrix.
+ CGSize naturalSize = CGSizeApplyAffineTransform(trackUnionRect.size, [m_avAsset.get() preferredTransform]);
+
+ // Cache the natural size (setNaturalSize will notify the player if it has changed).
+ setNaturalSize(IntSize(naturalSize));
+}
+
+NSArray* assetMetadataKeyNames()
+{
+ static NSArray* keys;
+ if (!keys) {
+ keys = [[NSArray alloc] initWithObjects:@"duration",
+ @"naturalSize",
+ @"preferredTransform",
+ @"preferredVolume",
+ @"preferredRate",
+ @"playable",
+ @"tracks",
+ nil];
+ }
+ return keys;
+}
+
+NSArray* itemKVOProperties()
+{
+ static NSArray* keys;
+ if (!keys) {
+ keys = [[NSArray alloc] initWithObjects:@"presentationSize",
+ @"status",
+ @"asset",
+ @"tracks",
+ @"seekableTimeRanges",
+ @"loadedTimeRanges",
+ @"playbackLikelyToKeepUp",
+ @"playbackBufferFull",
+ @"playbackBufferEmpty",
+ nil];
+ }
+ return keys;
+}
+
+} // namespace WebCore
+
+@implementation WebCoreAVFMovieObserver
+
+- (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback
+{
+ m_callback = callback;
+ return [super init];
+}
+
+- (void)disconnect
+{
+ [NSObject cancelPreviousPerformRequestsWithTarget:self];
+ m_callback = 0;
+}
+
+- (void)metadataLoaded
+{
+ if (!m_callback)
+ return;
+
+ m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::AssetMetadataLoaded);
+}
+
+- (void)playableKnown
+{
+ if (!m_callback)
+ return;
+
+ m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::AssetPlayabilityKnown);
+}
+
+- (void)timeChanged:(double)time
+{
+ if (!m_callback)
+ return;
+
+ m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::PlayerTimeChanged, time);
+}
+
+- (void)didEnd:(NSNotification *)unusedNotification
+{
+ UNUSED_PARAM(unusedNotification);
+ if (!m_callback)
+ return;
+ m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemDidPlayToEndTime);
+}
+
+- (void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary *)change context:(MediaPlayerAVFoundationObservationContext)context
+{
+ UNUSED_PARAM(change);
+
+ LOG(Media, "WebCoreAVFMovieObserver:observeValueForKeyPath(%p) - keyPath = %s", self, [keyPath UTF8String]);
+
+ if (!m_callback)
+ return;
+
+ if (context == MediaPlayerAVFoundationObservationContextPlayerItem) {
+ // A value changed for an AVPlayerItem
+ if ([keyPath isEqualToString:@"status"])
+ m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemStatusChanged);
+ else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"])
+ m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemIsPlaybackLikelyToKeepUpChanged);
+ else if ([keyPath isEqualToString:@"playbackBufferEmpty"])
+ m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemIsPlaybackBufferEmptyChanged);
+ else if ([keyPath isEqualToString:@"playbackBufferFull"])
+ m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemIsPlaybackBufferFullChanged);
+ else if ([keyPath isEqualToString:@"asset"])
+ m_callback->setAsset([object asset]);
+ else if ([keyPath isEqualToString:@"loadedTimeRanges"])
+ m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemLoadedTimeRangesChanged);
+ else if ([keyPath isEqualToString:@"seekableTimeRanges"])
+ m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemSeekableTimeRangesChanged);
+ else if ([keyPath isEqualToString:@"tracks"])
+ m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemTracksChanged);
+ else if ([keyPath isEqualToString:@"presentationSize"])
+ m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemPresentationSizeChanged);
+
+ return;
+ }
+
+ if (context == MediaPlayerAVFoundationObservationContextPlayer) {
+ // A value changed for an AVPlayer.
+ if ([keyPath isEqualToString:@"rate"])
+ m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::PlayerRateChanged);
+}
+}
+
+@end
+
+#endif
diff --git a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
index e9663a6..427c7bf 100644
--- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
+++ b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
@@ -550,11 +550,17 @@ void GraphicsLayerCA::setNeedsDisplay()
setNeedsDisplayInRect(hugeRect);
}
-void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& rect)
+void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& r)
{
if (!drawsContent())
return;
+ FloatRect rect(r);
+ FloatRect layerBounds(FloatPoint(), m_size);
+ rect.intersect(layerBounds);
+ if (rect.isEmpty())
+ return;
+
const size_t maxDirtyRects = 32;
for (size_t i = 0; i < m_dirtyRects.size(); ++i) {
@@ -1601,9 +1607,11 @@ bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValue
TransformOperation::OperationType transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : functionList[animationIndex];
RefPtr<PlatformCAAnimation> caAnimation;
-#if defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD)
+#if defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD) || PLATFORM(WIN)
// CA applies animations in reverse order (<rdar://problem/7095638>) so we need the last one we add (per property)
// to be non-additive.
+ // FIXME: This fix has not been added to QuartzCore on Windows yet (<rdar://problem/9112233>) so we expect the
+ // reversed animation behavior
bool additive = animationIndex < (numAnimations - 1);
#else
bool additive = animationIndex > 0;
diff --git a/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h b/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h
index a8528fd..8b5a460 100644
--- a/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h
+++ b/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h
@@ -38,11 +38,10 @@
#if PLATFORM(MAC)
#ifdef __OBJC__
@class CAPropertyAnimation;
-typedef CAPropertyAnimation* PlatformAnimationRef;
#else
-typedef void* CAPropertyAnimation; // So the m_animation declaration works
-typedef void* PlatformAnimationRef;
+class CAPropertyAnimation;
#endif
+typedef CAPropertyAnimation* PlatformAnimationRef;
#elif PLATFORM(WIN)
typedef struct _CACFAnimation* CACFAnimationRef;
typedef CACFAnimationRef PlatformAnimationRef;
diff --git a/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp b/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp
index f2e1950..75f4a10 100644
--- a/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp
+++ b/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp
@@ -307,13 +307,14 @@ void CACFLayerTreeHost::contextDidChange()
void CACFLayerTreeHost::notifyAnimationsStarted()
{
+ // Send currentTime to the pending animations. This function is called by CACF in a callback
+ // which occurs after the drawInContext calls. So currentTime is very close to the time
+ // the animations actually start
double currentTime = WTF::currentTime();
- double time = currentTime + lastCommitTime() - CACurrentMediaTime();
- ASSERT(time <= currentTime);
HashSet<RefPtr<PlatformCALayer> >::iterator end = m_pendingAnimatedLayers.end();
for (HashSet<RefPtr<PlatformCALayer> >::iterator it = m_pendingAnimatedLayers.begin(); it != end; ++it)
- (*it)->animationStarted(time);
+ (*it)->animationStarted(currentTime);
m_pendingAnimatedLayers.clear();
}
diff --git a/Source/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp b/Source/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp
index b0588d6..0f90ce4 100644
--- a/Source/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp
@@ -34,6 +34,7 @@
#include "GraphicsContext.h"
#include "OwnPtrCairo.h"
#include "Path.h"
+#include "PlatformContextCairo.h"
#include "Timer.h"
#include <cairo.h>
@@ -88,7 +89,7 @@ PlatformContext ContextShadow::beginShadowLayer(GraphicsContext* context, const
adjustBlurDistance(context);
double x1, x2, y1, y2;
- cairo_clip_extents(context->platformContext(), &x1, &y1, &x2, &y2);
+ cairo_clip_extents(context->platformContext()->cr(), &x1, &y1, &x2, &y2);
IntRect layerRect = calculateLayerBoundingRect(context, layerArea, IntRect(x1, y1, x2 - x1, y2 - y1));
// Don't paint if we are totally outside the clip region.
@@ -120,7 +121,7 @@ void ContextShadow::endShadowLayer(GraphicsContext* context)
cairo_surface_mark_dirty(m_layerImage);
}
- cairo_t* cr = context->platformContext();
+ cairo_t* cr = context->platformContext()->cr();
cairo_save(cr);
setSourceRGBAFromColor(cr, m_color);
cairo_mask_surface(cr, m_layerImage, m_layerOrigin.x(), m_layerOrigin.y());
@@ -198,7 +199,7 @@ void ContextShadow::drawRectShadow(GraphicsContext* context, const IntRect& rect
int internalShadowHeight = radiusTwice + max(topLeftRadius.height(), topRightRadius.height()) +
max(bottomLeftRadius.height(), bottomRightRadius.height());
- cairo_t* cr = context->platformContext();
+ cairo_t* cr = context->platformContext()->cr();
// drawShadowedRect still does not work with rotations.
// https://bugs.webkit.org/show_bug.cgi?id=45042
diff --git a/Source/WebCore/platform/graphics/cairo/FontCairo.cpp b/Source/WebCore/platform/graphics/cairo/FontCairo.cpp
index 2d79499..58a7fd2 100644
--- a/Source/WebCore/platform/graphics/cairo/FontCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/FontCairo.cpp
@@ -36,6 +36,7 @@
#include "GlyphBuffer.h"
#include "Gradient.h"
#include "GraphicsContext.h"
+#include "PlatformContextCairo.h"
#include "ImageBuffer.h"
#include "Pattern.h"
#include "SimpleFontData.h"
@@ -64,7 +65,7 @@ static void drawGlyphsToContext(cairo_t* context, const SimpleFontData* font, Gl
}
}
-static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context, const FloatPoint& point, const SimpleFontData* font, GlyphBufferGlyph* glyphs, int numGlyphs)
+static void drawGlyphsShadow(GraphicsContext* graphicsContext, const FloatPoint& point, const SimpleFontData* font, GlyphBufferGlyph* glyphs, int numGlyphs)
{
ContextShadow* shadow = graphicsContext->contextShadow();
ASSERT(shadow);
@@ -74,6 +75,7 @@ static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context,
if (!shadow->mustUseContextShadow(graphicsContext)) {
// Optimize non-blurry shadows, by just drawing text without the ContextShadow.
+ cairo_t* context = graphicsContext->platformContext()->cr();
cairo_save(context);
cairo_translate(context, shadow->m_offset.width(), shadow->m_offset.height());
setSourceRGBAFromColor(context, shadow->m_color);
@@ -106,9 +108,10 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
offset += glyphBuffer.advanceAt(from + i);
}
- cairo_t* cr = context->platformContext();
- drawGlyphsShadow(context, cr, point, font, glyphs, numGlyphs);
+ PlatformContextCairo* platformContext = context->platformContext();
+ drawGlyphsShadow(context, point, font, glyphs, numGlyphs);
+ cairo_t* cr = platformContext->cr();
cairo_save(cr);
prepareContextForGlyphDrawing(cr, font, point);
if (context->textDrawingMode() & TextModeFill) {
diff --git a/Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h
index 5807102..f8f3c99 100644
--- a/Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h
+++ b/Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h
@@ -25,6 +25,7 @@
#include "FontOrientation.h"
#include "FontRenderingMode.h"
#include "FontWidthVariant.h"
+#include "TextOrientation.h"
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
@@ -41,7 +42,7 @@ struct FontCustomPlatformData {
public:
FontCustomPlatformData(FT_Face, SharedBuffer*);
~FontCustomPlatformData();
- FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
static bool supportsFormat(const String&);
private:
diff --git a/Source/WebCore/platform/graphics/cairo/GradientCairo.cpp b/Source/WebCore/platform/graphics/cairo/GradientCairo.cpp
index 4e6ed07..225046a 100644
--- a/Source/WebCore/platform/graphics/cairo/GradientCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/GradientCairo.cpp
@@ -29,6 +29,7 @@
#include "CSSParser.h"
#include "GraphicsContext.h"
+#include "PlatformContextCairo.h"
#include <cairo.h>
namespace WebCore {
@@ -87,7 +88,7 @@ void Gradient::setPlatformGradientSpaceTransform(const AffineTransform& gradient
void Gradient::fill(GraphicsContext* context, const FloatRect& rect)
{
- cairo_t* cr = context->platformContext();
+ cairo_t* cr = context->platformContext()->cr();
context->save();
cairo_set_source(cr, platformGradient());
diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index e69a7a5..0fc94df 100644
--- a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -47,6 +47,7 @@
#include "NotImplemented.h"
#include "Path.h"
#include "Pattern.h"
+#include "PlatformContextCairo.h"
#include "RefPtrCairo.h"
#include "SimpleFontData.h"
#include <cairo.h>
@@ -148,7 +149,7 @@ static inline void drawPathShadow(GraphicsContext* context, PathDrawingStyle dra
return;
// Calculate the extents of the rendered solid paths.
- cairo_t* cairoContext = context->platformContext();
+ cairo_t* cairoContext = context->platformContext()->cr();
OwnPtr<cairo_path_t> path(cairo_copy_path(cairoContext));
FloatRect solidFigureExtents;
@@ -199,12 +200,18 @@ static void strokeCurrentCairoPath(GraphicsContext* context, cairo_t* cairoCont
cairo_new_path(cairoContext);
}
-void GraphicsContext::platformInit(PlatformGraphicsContext* cr)
+GraphicsContext::GraphicsContext(cairo_t* cr)
{
- m_data = new GraphicsContextPlatformPrivate;
- m_data->cr = cairo_reference(cr);
- m_data->syncContext(cr);
- setPaintingDisabled(!cr);
+ m_data = new GraphicsContextPlatformPrivate(new PlatformContextCairo(cr));
+}
+
+void GraphicsContext::platformInit(PlatformContextCairo* platformContext)
+{
+ m_data = new GraphicsContextPlatformPrivate(platformContext);
+ if (platformContext)
+ m_data->syncContext(platformContext->cr());
+ else
+ setPaintingDisabled(true);
}
void GraphicsContext::platformDestroy()
@@ -214,20 +221,20 @@ void GraphicsContext::platformDestroy()
AffineTransform GraphicsContext::getCTM() const
{
- cairo_t* cr = platformContext();
+ cairo_t* cr = platformContext()->cr();
cairo_matrix_t m;
cairo_get_matrix(cr, &m);
return AffineTransform(m.xx, m.yx, m.xy, m.yy, m.x0, m.y0);
}
-cairo_t* GraphicsContext::platformContext() const
+PlatformContextCairo* GraphicsContext::platformContext() const
{
- return m_data->cr;
+ return m_data->platformContext;
}
void GraphicsContext::savePlatformState()
{
- cairo_save(m_data->cr);
+ cairo_save(platformContext()->cr());
m_data->save();
m_data->shadowStack.append(m_data->shadow);
m_data->maskImageStack.append(ImageMaskInformation());
@@ -235,7 +242,8 @@ void GraphicsContext::savePlatformState()
void GraphicsContext::restorePlatformState()
{
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
+
const ImageMaskInformation& maskInformation = m_data->maskImageStack.last();
if (maskInformation.isValid()) {
const FloatRect& maskRect = maskInformation.maskRect();
@@ -251,7 +259,7 @@ void GraphicsContext::restorePlatformState()
m_data->shadowStack.removeLast();
}
- cairo_restore(m_data->cr);
+ cairo_restore(cr);
m_data->restore();
}
@@ -261,7 +269,7 @@ void GraphicsContext::drawRect(const IntRect& rect)
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_save(cr);
if (fillColor().alpha())
@@ -289,7 +297,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
if (style == NoStroke)
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_save(cr);
float width = strokeThickness();
@@ -376,7 +384,7 @@ void GraphicsContext::drawEllipse(const IntRect& rect)
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_save(cr);
float yRadius = .5 * rect.height();
float xRadius = .5 * rect.width();
@@ -415,7 +423,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
float fa = startAngle;
float falen = fa + angleSpan;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_save(cr);
if (w != h)
@@ -492,7 +500,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
if (npoints <= 1)
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_save(cr);
cairo_set_antialias(cr, shouldAntialias ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE);
@@ -522,7 +530,7 @@ void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* poin
if (numPoints <= 1)
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_new_path(cr);
cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
@@ -542,7 +550,7 @@ void GraphicsContext::fillPath(const Path& path)
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
setPathOnCairoContext(cr, path.platformPath()->context());
fillCurrentCairoPath(this, cr);
}
@@ -552,7 +560,7 @@ void GraphicsContext::strokePath(const Path& path)
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
setPathOnCairoContext(cr, path.platformPath()->context());
strokeCurrentCairoPath(this, cr);
}
@@ -562,7 +570,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_save(cr);
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
fillCurrentCairoPath(this, cr);
@@ -578,7 +586,7 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS
m_data->shadow.drawRectShadow(this, enclosingIntRect(rect));
if (color.alpha())
- fillRectSourceOver(m_data->cr, rect, color);
+ fillRectSourceOver(platformContext()->cr(), rect, color);
}
void GraphicsContext::clip(const FloatRect& rect)
@@ -586,7 +594,7 @@ void GraphicsContext::clip(const FloatRect& rect)
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
@@ -600,7 +608,7 @@ void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
setPathOnCairoContext(cr, path.platformPath()->context());
cairo_set_fill_rule(cr, clipRule == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
cairo_clip(cr);
@@ -638,7 +646,7 @@ void GraphicsContext::drawFocusRing(const Path& path, int width, int /* offset *
adjustFocusRingColor(ringColor);
adjustFocusRingLineWidth(width);
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_save(cr);
appendWebCorePathToCairoContext(cr, path);
setSourceRGBAFromColor(cr, ringColor);
@@ -655,7 +663,7 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int
unsigned rectCount = rects.size();
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_save(cr);
cairo_push_group(cr);
cairo_new_path(cr);
@@ -732,7 +740,7 @@ void GraphicsContext::drawLineForTextChecking(const FloatPoint& origin, float wi
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_save(cr);
switch (style) {
@@ -762,7 +770,7 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
FloatRect result;
double x = frect.x();
double y = frect.y();
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_user_to_device(cr, &x, &y);
x = round(x);
y = round(y);
@@ -799,7 +807,7 @@ void GraphicsContext::translate(float x, float y)
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_translate(cr, x, y);
m_data->translate(x, y);
}
@@ -821,7 +829,7 @@ void GraphicsContext::setPlatformStrokeThickness(float strokeThickness)
if (paintingDisabled())
return;
- cairo_set_line_width(m_data->cr, strokeThickness);
+ cairo_set_line_width(platformContext()->cr(), strokeThickness);
}
void GraphicsContext::setPlatformStrokeStyle(StrokeStyle strokeStyle)
@@ -835,16 +843,16 @@ void GraphicsContext::setPlatformStrokeStyle(StrokeStyle strokeStyle)
switch (strokeStyle) {
case NoStroke:
// FIXME: is it the right way to emulate NoStroke?
- cairo_set_line_width(m_data->cr, 0);
+ cairo_set_line_width(platformContext()->cr(), 0);
break;
case SolidStroke:
- cairo_set_dash(m_data->cr, 0, 0, 0);
+ cairo_set_dash(platformContext()->cr(), 0, 0, 0);
break;
case DottedStroke:
- cairo_set_dash(m_data->cr, dotPattern, 2, 0);
+ cairo_set_dash(platformContext()->cr(), dotPattern, 2, 0);
break;
case DashedStroke:
- cairo_set_dash(m_data->cr, dashPattern, 2, 0);
+ cairo_set_dash(platformContext()->cr(), dashPattern, 2, 0);
break;
}
}
@@ -859,7 +867,7 @@ void GraphicsContext::concatCTM(const AffineTransform& transform)
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
const cairo_matrix_t matrix = cairo_matrix_t(transform);
cairo_transform(cr, &matrix);
m_data->concatCTM(transform);
@@ -870,7 +878,7 @@ void GraphicsContext::setCTM(const AffineTransform& transform)
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
const cairo_matrix_t matrix = cairo_matrix_t(transform);
cairo_set_matrix(cr, &matrix);
m_data->setCTM(transform);
@@ -881,7 +889,7 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
clip(rect);
Path p;
@@ -928,7 +936,7 @@ void GraphicsContext::beginTransparencyLayer(float opacity)
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_push_group(cr);
m_data->layers.append(opacity);
m_data->beginTransparencyLayer();
@@ -939,7 +947,7 @@ void GraphicsContext::endTransparencyLayer()
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_pop_group_to_source(cr);
cairo_paint_with_alpha(cr, m_data->layers.last());
@@ -952,7 +960,7 @@ void GraphicsContext::clearRect(const FloatRect& rect)
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_save(cr);
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
@@ -966,7 +974,7 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float width)
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_save(cr);
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
cairo_set_line_width(cr, width);
@@ -991,12 +999,12 @@ void GraphicsContext::setLineCap(LineCap lineCap)
cairoCap = CAIRO_LINE_CAP_SQUARE;
break;
}
- cairo_set_line_cap(m_data->cr, cairoCap);
+ cairo_set_line_cap(platformContext()->cr(), cairoCap);
}
void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
{
- cairo_set_dash(m_data->cr, dashes.data(), dashes.size(), dashOffset);
+ cairo_set_dash(platformContext()->cr(), dashes.data(), dashes.size(), dashOffset);
}
void GraphicsContext::setLineJoin(LineJoin lineJoin)
@@ -1016,7 +1024,7 @@ void GraphicsContext::setLineJoin(LineJoin lineJoin)
cairoJoin = CAIRO_LINE_JOIN_BEVEL;
break;
}
- cairo_set_line_join(m_data->cr, cairoJoin);
+ cairo_set_line_join(platformContext()->cr(), cairoJoin);
}
void GraphicsContext::setMiterLimit(float miter)
@@ -1024,7 +1032,7 @@ void GraphicsContext::setMiterLimit(float miter)
if (paintingDisabled())
return;
- cairo_set_miter_limit(m_data->cr, miter);
+ cairo_set_miter_limit(platformContext()->cr(), miter);
}
void GraphicsContext::setAlpha(float alpha)
@@ -1042,7 +1050,7 @@ void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op)
if (paintingDisabled())
return;
- cairo_set_operator(m_data->cr, toCairoOperator(op));
+ cairo_set_operator(platformContext()->cr(), toCairoOperator(op));
}
void GraphicsContext::clip(const Path& path)
@@ -1050,7 +1058,7 @@ void GraphicsContext::clip(const Path& path)
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
OwnPtr<cairo_path_t> p(cairo_copy_path(path.platformPath()->context()));
cairo_append_path(cr, p.get());
cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
@@ -1070,7 +1078,7 @@ void GraphicsContext::clipOut(const Path& path)
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
double x1, y1, x2, y2;
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1);
@@ -1087,7 +1095,7 @@ void GraphicsContext::rotate(float radians)
if (paintingDisabled())
return;
- cairo_rotate(m_data->cr, radians);
+ cairo_rotate(platformContext()->cr(), radians);
m_data->rotate(radians);
}
@@ -1096,7 +1104,7 @@ void GraphicsContext::scale(const FloatSize& size)
if (paintingDisabled())
return;
- cairo_scale(m_data->cr, size.width(), size.height());
+ cairo_scale(platformContext()->cr(), size.width(), size.height());
m_data->scale(size);
}
@@ -1105,7 +1113,7 @@ void GraphicsContext::clipOut(const IntRect& r)
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
double x1, y1, x2, y2;
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1);
@@ -1132,7 +1140,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft,
if (hasShadow())
m_data->shadow.drawRectShadow(this, r, topLeft, topRight, bottomLeft, bottomRight);
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_save(cr);
Path path;
path.addRoundedRect(r, topLeft, topRight, bottomLeft, bottomRight);
@@ -1170,7 +1178,7 @@ void GraphicsContext::setPlatformShouldAntialias(bool enable)
// When true, use the default Cairo backend antialias mode (usually this
// enables standard 'grayscale' antialiasing); false to explicitly disable
// antialiasing. This is the same strategy as used in drawConvexPolygon().
- cairo_set_antialias(m_data->cr, enable ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE);
+ cairo_set_antialias(platformContext()->cr(), enable ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE);
}
void GraphicsContext::setImageInterpolationQuality(InterpolationQuality)
@@ -1196,7 +1204,7 @@ void GraphicsContext::pushImageMask(cairo_surface_t* surface, const FloatRect& r
// We want to allow the clipped elements to composite with the surface as it
// is now, but they are isolated in another group. To make this work, we're
// going to blit the current surface contents onto the new group once we push it.
- cairo_t* cr = m_data->cr;
+ cairo_t* cr = platformContext()->cr();
cairo_surface_t* currentTarget = cairo_get_target(cr);
cairo_surface_flush(currentTarget);
diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h b/Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
index 924f69a..2bc290b 100644
--- a/Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
+++ b/Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
@@ -31,6 +31,7 @@
#include "GraphicsContext.h"
#include "ContextShadow.h"
+#include "PlatformContextCairo.h"
#include "RefPtrCairo.h"
#include <cairo.h>
#include <math.h>
@@ -67,8 +68,8 @@ private:
class GraphicsContextPlatformPrivate {
public:
- GraphicsContextPlatformPrivate()
- : cr(0)
+ GraphicsContextPlatformPrivate(PlatformContextCairo* newPlatformContext)
+ : platformContext(newPlatformContext)
#if PLATFORM(GTK)
, expose(0)
#elif PLATFORM(WIN)
@@ -82,7 +83,6 @@ public:
~GraphicsContextPlatformPrivate()
{
- cairo_destroy(cr);
}
#if PLATFORM(WIN)
@@ -99,7 +99,7 @@ public:
void setCTM(const AffineTransform&);
void beginTransparencyLayer() { m_transparencyCount++; }
void endTransparencyLayer() { m_transparencyCount--; }
- void syncContext(PlatformGraphicsContext* cr);
+ void syncContext(cairo_t* cr);
#else
// On everything else, we do nothing.
void save() {}
@@ -114,12 +114,11 @@ public:
void setCTM(const AffineTransform&) {}
void beginTransparencyLayer() {}
void endTransparencyLayer() {}
- void syncContext(PlatformGraphicsContext* cr) {}
+ void syncContext(cairo_t* cr) {}
#endif
- cairo_t* cr;
+ PlatformContextCairo* platformContext;
Vector<float> layers;
-
ContextShadow shadow;
Vector<ContextShadow> shadowStack;
Vector<ImageMaskInformation> maskImageStack;
@@ -133,6 +132,23 @@ public:
#endif
};
+// This is a specialized private section for the Cairo GraphicsContext, which knows how
+// to clean up the heap allocated PlatformContextCairo that we must use for the top-level
+// GraphicsContext.
+class GraphicsContextPlatformPrivateToplevel : public GraphicsContextPlatformPrivate {
+public:
+ GraphicsContextPlatformPrivateToplevel(PlatformContextCairo* platformContext)
+ : GraphicsContextPlatformPrivate(platformContext)
+ {
+ }
+
+ ~GraphicsContextPlatformPrivateToplevel()
+ {
+ delete platformContext;
+ }
+};
+
+
} // namespace WebCore
#endif // GraphicsContextPlatformPrivateCairo_h
diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
index 9ee8a94..1d5d492 100644
--- a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
@@ -37,7 +37,9 @@
#include "MIMETypeRegistry.h"
#include "NotImplemented.h"
#include "Pattern.h"
+#include "PlatformContextCairo.h"
#include "PlatformString.h"
+#include "RefPtrCairo.h"
#include <cairo.h>
#include <wtf/Vector.h>
@@ -66,6 +68,7 @@ namespace WebCore {
ImageBufferData::ImageBufferData(const IntSize& size)
: m_surface(0)
+ , m_platformContext(0)
{
}
@@ -80,9 +83,9 @@ ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode, bool& s
if (cairo_surface_status(m_data.m_surface) != CAIRO_STATUS_SUCCESS)
return; // create will notice we didn't set m_initialized and fail.
- cairo_t* cr = cairo_create(m_data.m_surface);
- m_context.set(new GraphicsContext(cr));
- cairo_destroy(cr); // The context is now owned by the GraphicsContext.
+ RefPtr<cairo_t> cr = adoptRef(cairo_create(m_data.m_surface));
+ m_data.m_platformContext.setCr(cr.get());
+ m_context.set(new GraphicsContext(&m_data.m_platformContext));
success = true;
}
@@ -301,7 +304,7 @@ static cairo_status_t writeFunction(void* closure, const unsigned char* data, un
String ImageBuffer::toDataURL(const String& mimeType, const double*) const
{
- cairo_surface_t* image = cairo_get_target(context()->platformContext());
+ cairo_surface_t* image = cairo_get_target(context()->platformContext()->cr());
if (!image)
return "data:,";
diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferData.h b/Source/WebCore/platform/graphics/cairo/ImageBufferData.h
index 49f15df..42867d1 100644
--- a/Source/WebCore/platform/graphics/cairo/ImageBufferData.h
+++ b/Source/WebCore/platform/graphics/cairo/ImageBufferData.h
@@ -26,7 +26,9 @@
#ifndef ImageBufferData_h
#define ImageBufferData_h
-#include "cairo.h"
+#include "PlatformContextCairo.h"
+
+typedef struct _cairo_surface cairo_surface_t;
namespace WebCore {
@@ -37,6 +39,7 @@ public:
ImageBufferData(const IntSize&);
cairo_surface_t* m_surface;
+ PlatformContextCairo m_platformContext;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp
index e51d65a..d3a52ce 100644
--- a/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp
@@ -36,6 +36,7 @@
#include "ContextShadow.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
+#include "PlatformContextCairo.h"
#include "ImageBuffer.h"
#include "ImageObserver.h"
#include "RefPtrCairo.h"
@@ -114,7 +115,7 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo
IntSize selfSize = size();
- cairo_t* cr = context->platformContext();
+ cairo_t* cr = context->platformContext()->cr();
context->save();
// Set the compositing operation.
@@ -169,8 +170,7 @@ void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, con
if (!image) // If it's too early we won't have an image yet.
return;
- cairo_t* cr = context->platformContext();
-
+ cairo_t* cr = context->platformContext()->cr();
drawPatternToCairoContext(cr, image, size(), tileRect, patternTransform, phase, toCairoOperator(op), destRect);
if (imageObserver())
diff --git a/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp b/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp
index 94f6809..1594e7b 100644
--- a/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp
@@ -20,7 +20,7 @@
#include "config.h"
#include "OwnPtrCairo.h"
-#if defined(USE_FREETYPE)
+#if USE(FREETYPE)
#include <cairo-ft.h>
#include <fontconfig/fcfreetype.h>
#endif
@@ -29,7 +29,7 @@
namespace WTF {
-#if defined(USE_FREETYPE)
+#if USE(FREETYPE)
template <> void deleteOwnedPtr<FcObjectSet>(FcObjectSet* ptr)
{
if (ptr)
diff --git a/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h b/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h
index 035d80e..e1dd370 100644
--- a/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h
+++ b/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h
@@ -22,7 +22,7 @@
#include "OwnPtr.h"
-#if defined(USE_FREETYPE)
+#if USE(FREETYPE)
typedef struct _FcObjectSet FcObjectSet;
typedef struct _FcFontSet FcFontSet;
#endif
@@ -31,7 +31,7 @@ typedef struct cairo_path cairo_path_t;
namespace WTF {
-#if defined(USE_FREETYPE)
+#if USE(FREETYPE)
template <> void deleteOwnedPtr<FcObjectSet>(FcObjectSet*);
template <> void deleteOwnedPtr<FcFontSet>(FcFontSet*);
#endif
diff --git a/Source/WebCore/platform/graphics/cairo/PathCairo.cpp b/Source/WebCore/platform/graphics/cairo/PathCairo.cpp
index 7a09a52..533df10 100644
--- a/Source/WebCore/platform/graphics/cairo/PathCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/PathCairo.cpp
@@ -281,7 +281,7 @@ FloatRect Path::boundingRect() const
return FloatRect(x0, y0, x1 - x0, y1 - y0);
}
-FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
+FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const
{
cairo_t* cr = platformPath()->context();
if (applier) {
diff --git a/Source/WebCore/platform/mac/WebCoreKeyGenerator.h b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp
index c9260e1..ba75162 100644
--- a/Source/WebCore/platform/mac/WebCoreKeyGenerator.h
+++ b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2011 Igalia S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,10 +23,16 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-@interface WebCoreKeyGenerator : NSObject
+#include "config.h"
+#include "PlatformContextCairo.h"
-+ (WebCoreKeyGenerator *)sharedGenerator;
-- (NSArray *)strengthMenuItemTitles;
-- (NSString *)signedPublicKeyAndChallengeStringWithStrengthIndex:(unsigned)index challenge:(NSString *)challenge pageURL:(NSURL *)pageURL;
+#include <cairo.h>
-@end
+namespace WebCore {
+
+PlatformContextCairo::PlatformContextCairo(cairo_t* cr)
+ : m_cr(cr)
+{
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/mac/SSLKeyGeneratorMac.mm b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h
index dd76b59..c6cceda 100644
--- a/Source/WebCore/platform/mac/SSLKeyGeneratorMac.mm
+++ b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Igalia S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,27 +23,30 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#import "config.h"
-#import "SSLKeyGenerator.h"
+#ifndef PlatformContextCairo_h
+#define PlatformContextCairo_h
-#import "KURL.h"
-#import "WebCoreKeyGenerator.h"
+#include "ContextShadow.h"
+#include "RefPtrCairo.h"
namespace WebCore {
-void getSupportedKeySizes(Vector<String>& supportedKeySizes)
-{
- NSEnumerator *enumerator = [[[WebCoreKeyGenerator sharedGenerator] strengthMenuItemTitles] objectEnumerator];
- NSString *string;
- while ((string = [enumerator nextObject]) != nil)
- supportedKeySizes.append(string);
-}
-
-String signedPublicKeyAndChallengeString(unsigned keySizeIndex, const String& challengeString, const KURL& url)
-{
- return [[WebCoreKeyGenerator sharedGenerator] signedPublicKeyAndChallengeStringWithStrengthIndex:keySizeIndex
- challenge:challengeString
- pageURL:url];
-}
-
-}
+// Much like PlatformContextSkia in the Skia port, this class holds information that
+// would normally be private to GraphicsContext, except that we want to allow access
+// to it in Font and Image code. This allows us to separate the concerns of Cairo-specific
+// code from the platform-independent GraphicsContext.
+
+class PlatformContextCairo {
+ WTF_MAKE_NONCOPYABLE(PlatformContextCairo);
+public:
+ PlatformContextCairo(cairo_t*);
+ cairo_t* cr() { return m_cr.get(); }
+ void setCr(cairo_t* cr) { m_cr = cr; }
+
+private:
+ RefPtr<cairo_t> m_cr;
+};
+
+} // namespace WebCore
+
+#endif // PlatformContextCairo_h
diff --git a/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp b/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp
index c8b242c..1792002 100644
--- a/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp
@@ -21,7 +21,7 @@
#include <cairo.h>
-#if defined(USE_FREETYPE)
+#if USE(FREETYPE)
#include <cairo-ft.h>
#include <fontconfig/fcfreetype.h>
#endif
@@ -88,7 +88,7 @@ template<> void derefIfNotNull(cairo_pattern_t* ptr)
cairo_pattern_destroy(ptr);
}
-#if defined(USE_FREETYPE)
+#if USE(FREETYPE)
template<> void refIfNotNull(FcPattern* ptr)
{
if (LIKELY(ptr != 0))
diff --git a/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h b/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h
index 204d1e3..540f9dc 100644
--- a/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h
+++ b/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h
@@ -28,7 +28,7 @@ typedef struct _cairo_font_face cairo_font_face_t;
typedef struct _cairo_scaled_font cairo_scaled_font_t;
typedef struct _cairo_pattern cairo_pattern_t;
-#if defined(USE_FREETYPE)
+#if USE(FREETYPE)
typedef struct _FcPattern FcPattern;
#endif
@@ -49,7 +49,7 @@ template<> void derefIfNotNull(cairo_scaled_font_t* ptr);
template<> void refIfNotNull(cairo_pattern_t*);
template<> void derefIfNotNull(cairo_pattern_t*);
-#if defined(USE_FREETYPE)
+#if USE(FREETYPE)
template<> void refIfNotNull(FcPattern* ptr);
template<> void derefIfNotNull(FcPattern* ptr);
#endif
diff --git a/Source/WebCore/platform/graphics/cg/FontPlatformData.h b/Source/WebCore/platform/graphics/cg/FontPlatformData.h
deleted file mode 100644
index e21b444..0000000
--- a/Source/WebCore/platform/graphics/cg/FontPlatformData.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * This file is part of the internal font implementation. It should not be included by anyone other than
- * FontMac.cpp, FontWin.cpp and Font.cpp.
- *
- * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef FontPlatformData_h
-#define FontPlatformData_h
-
-#include "FontOrientation.h"
-#include "RefCountedGDIHandle.h"
-#include "StringImpl.h"
-#include <wtf/Forward.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefCounted.h>
-#include <wtf/RetainPtr.h>
-
-typedef struct HFONT__* HFONT;
-typedef struct CGFont* CGFontRef;
-
-namespace WebCore {
-
-class FontDescription;
-
-class FontPlatformData {
-public:
- FontPlatformData()
- : m_size(0)
- , m_syntheticBold(false)
- , m_syntheticOblique(false)
- , m_useGDI(false)
- {
- }
-
- FontPlatformData(HFONT, float size, bool bold, bool oblique, bool useGDI);
- FontPlatformData(float size, bool bold, bool oblique);
-
- FontPlatformData(HFONT, CGFontRef, float size, bool bold, bool oblique, bool useGDI);
- ~FontPlatformData();
-
- FontPlatformData(WTF::HashTableDeletedValueType) : m_font(WTF::HashTableDeletedValue) { }
- bool isHashTableDeletedValue() const { return m_font.isHashTableDeletedValue(); }
-
- HFONT hfont() const { return m_font->handle(); }
- CGFontRef cgFont() const { return m_cgFont.get(); }
-
- float size() const { return m_size; }
- void setSize(float size) { m_size = size; }
- bool syntheticBold() const { return m_syntheticBold; }
- bool syntheticOblique() const { return m_syntheticOblique; }
- bool useGDI() const { return m_useGDI; }
-
- FontOrientation orientation() const { return Horizontal; } // FIXME: Implement.
-
- unsigned hash() const
- {
- return m_font->hash();
- }
-
- bool operator==(const FontPlatformData& other) const
- {
- return m_font == other.m_font
- && m_cgFont == other.m_cgFont
- && m_size == other.m_size
- && m_syntheticBold == other.m_syntheticBold
- && m_syntheticOblique == other.m_syntheticOblique
- && m_useGDI == other.m_useGDI;
- }
-
-#ifndef NDEBUG
- String description() const;
-#endif
-
-private:
- void platformDataInit(HFONT, float size, HDC, WCHAR* faceName);
-
- RefPtr<RefCountedGDIHandle<HFONT> > m_font;
- RetainPtr<CGFontRef> m_cgFont;
-
- float m_size;
- bool m_syntheticBold;
- bool m_syntheticOblique;
- bool m_useGDI;
-};
-
-} // namespace WebCore
-
-#endif
diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index dbcab45..7799137 100644
--- a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -695,7 +695,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
if (m_state.fillPattern)
applyFillPattern();
- bool drawOwnShadow = hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet.
+ bool drawOwnShadow = !isAcceleratedContext() && hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet.
if (drawOwnShadow) {
float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur;
// Turn off CG shadows.
@@ -724,7 +724,7 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS
if (oldFillColor != color || oldColorSpace != colorSpace)
setCGFillColor(context, color, colorSpace);
- bool drawOwnShadow = hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet.
+ bool drawOwnShadow = !isAcceleratedContext() && hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet.
if (drawOwnShadow) {
float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur;
// Turn off CG shadows.
@@ -759,7 +759,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
Path path;
path.addRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight);
- bool drawOwnShadow = hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet.
+ bool drawOwnShadow = !isAcceleratedContext() && hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet.
if (drawOwnShadow) {
float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur;
@@ -803,7 +803,7 @@ void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const Rounded
setFillColor(color, colorSpace);
// fillRectWithRoundedHole() assumes that the edges of rect are clipped out, so we only care about shadows cast around inside the hole.
- bool drawOwnShadow = hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms;
+ bool drawOwnShadow = !isAcceleratedContext() && hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms;
if (drawOwnShadow) {
float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur;
@@ -929,8 +929,7 @@ void GraphicsContext::setPlatformShadow(const FloatSize& offset, float blur, con
CGFloat smallEigenvalue = narrowPrecisionToCGFloat(sqrt(0.5 * ((A + D) - sqrt(4 * B * C + (A - D) * (A - D)))));
- // Extreme "blur" values can make text drawing crash or take crazy long times, so clamp
- blurRadius = min(blur * smallEigenvalue, narrowPrecisionToCGFloat(1000.0));
+ blurRadius = blur * smallEigenvalue;
CGSize offsetInBaseSpace = CGSizeApplyAffineTransform(offset, userToBaseCTM);
@@ -938,6 +937,9 @@ void GraphicsContext::setPlatformShadow(const FloatSize& offset, float blur, con
yOffset = offsetInBaseSpace.height;
}
+ // Extreme "blur" values can make text drawing crash or take crazy long times, so clamp
+ blurRadius = min(blurRadius, narrowPrecisionToCGFloat(1000.0));
+
// Work around <rdar://problem/5539388> by ensuring that the offsets will get truncated
// to the desired integer.
static const CGFloat extraShadowOffset = narrowPrecisionToCGFloat(1.0 / 128);
@@ -1343,14 +1345,30 @@ void GraphicsContext::setAllowsFontSmoothing(bool allowsFontSmoothing)
#endif
}
-void GraphicsContext::setIsCALayerContext(bool)
+void GraphicsContext::setIsCALayerContext(bool isLayerContext)
{
- m_data->m_isCALayerContext = true;
+ if (isLayerContext)
+ m_data->m_contextFlags |= IsLayerCGContext;
+ else
+ m_data->m_contextFlags &= ~IsLayerCGContext;
}
bool GraphicsContext::isCALayerContext() const
{
- return m_data->m_isCALayerContext;
+ return m_data->m_contextFlags & IsLayerCGContext;
+}
+
+void GraphicsContext::setIsAcceleratedContext(bool isAccelerated)
+{
+ if (isAccelerated)
+ m_data->m_contextFlags |= IsAcceleratedCGContext;
+ else
+ m_data->m_contextFlags &= ~IsAcceleratedCGContext;
+}
+
+bool GraphicsContext::isAcceleratedContext() const
+{
+ return m_data->m_contextFlags & IsAcceleratedCGContext;
}
void GraphicsContext::setPlatformTextDrawingMode(TextDrawingModeFlags mode)
diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h b/Source/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
index f9255df..722f5a0 100644
--- a/Source/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
+++ b/Source/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
@@ -31,9 +31,16 @@
namespace WebCore {
+enum GraphicsContextCGFlag {
+ IsLayerCGContext = 1 << 0,
+ IsAcceleratedCGContext = 1 << 1
+};
+
+typedef unsigned GraphicsContextCGFlags;
+
class GraphicsContextPlatformPrivate {
public:
- GraphicsContextPlatformPrivate(CGContextRef cgContext, bool isLayerContext = false)
+ GraphicsContextPlatformPrivate(CGContextRef cgContext, GraphicsContextCGFlags flags = 0)
: m_cgContext(cgContext)
#if PLATFORM(WIN)
, m_hdc(0)
@@ -41,7 +48,7 @@ public:
, m_shouldIncludeChildWindows(false)
#endif
, m_userToDeviceTransformKnownToBeIdentity(false)
- , m_isCALayerContext(isLayerContext)
+ , m_contextFlags(flags)
{
}
@@ -87,7 +94,7 @@ public:
RetainPtr<CGContextRef> m_cgContext;
bool m_userToDeviceTransformKnownToBeIdentity;
- bool m_isCALayerContext;
+ GraphicsContextCGFlags m_contextFlags;
};
}
diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
index 7c8e313..3c8f959 100644
--- a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -32,6 +32,7 @@
#include "BitmapImage.h"
#include "GraphicsContext.h"
#include "GraphicsContextCG.h"
+#include "ImageData.h"
#include "MIMETypeRegistry.h"
#include <ApplicationServices/ApplicationServices.h>
#include <wtf/Assertions.h>
@@ -498,21 +499,8 @@ static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType)
#endif
}
-String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
+static String CGImageToDataURL(CGImageRef image, const String& mimeType, const double* quality)
{
- ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
-
- RetainPtr<CGImageRef> image;
- if (!m_accelerateRendering)
- image.adoptCF(CGBitmapContextCreateImage(context()->platformContext()));
-#if USE(IOSURFACE_CANVAS_BACKING_STORE)
- else
- image.adoptCF(wkIOSurfaceContextCreateImage(context()->platformContext()));
-#endif
-
- if (!image)
- return "data:,";
-
RetainPtr<CFMutableDataRef> data(AdoptCF, CFDataCreateMutable(kCFAllocatorDefault, 0));
if (!data)
return "data:,";
@@ -533,7 +521,7 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
imageProperties.adoptCF(CFDictionaryCreate(0, &key, &value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
}
- CGImageDestinationAddImage(destination.get(), image.get(), imageProperties.get());
+ CGImageDestinationAddImage(destination.get(), image, imageProperties.get());
CGImageDestinationFinalize(destination.get());
Vector<char> out;
@@ -541,4 +529,46 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
return makeString("data:", mimeType, ";base64,", out);
}
+
+String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
+{
+ ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
+
+ RetainPtr<CGImageRef> image;
+ if (!m_accelerateRendering)
+ image.adoptCF(CGBitmapContextCreateImage(context()->platformContext()));
+#if USE(IOSURFACE_CANVAS_BACKING_STORE)
+ else
+ image.adoptCF(wkIOSurfaceContextCreateImage(context()->platformContext()));
+#endif
+
+ if (!image)
+ return "data:,";
+
+ return CGImageToDataURL(image.get(), mimeType, quality);
+}
+
+String ImageDataToDataURL(const ImageData& source, const String& mimeType, const double* quality)
+{
+ ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
+
+ RetainPtr<CGImageRef> image;
+ RetainPtr<CGDataProviderRef> dataProvider;
+
+ dataProvider.adoptCF(CGDataProviderCreateWithData(0, source.data()->data()->data(),
+ 4 * source.width() * source.height(), 0));
+
+ if (!dataProvider)
+ return "data:,";
+
+ image.adoptCF(CGImageCreate(source.width(), source.height(), 8, 32, 4 * source.width(),
+ CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrderDefault | kCGImageAlphaLast,
+ dataProvider.get(), 0, false, kCGRenderingIntentDefault));
+
+
+ if (!image)
+ return "data:,";
+
+ return CGImageToDataURL(image.get(), mimeType, quality);
+}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/cg/PathCG.cpp b/Source/WebCore/platform/graphics/cg/PathCG.cpp
index d6a1e6e..b8fc7d4 100644
--- a/Source/WebCore/platform/graphics/cg/PathCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/PathCG.cpp
@@ -166,7 +166,7 @@ FloatRect Path::boundingRect() const
return CGPathGetBoundingBox(m_path);
}
-FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
+FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const
{
CGContextRef context = scratchContext();
diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
index ad961aa..4cb119a 100644
--- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
@@ -56,7 +56,7 @@ Canvas2DLayerChromium::~Canvas2DLayerChromium()
layerRendererContext()->deleteTexture(m_textureId);
}
-void Canvas2DLayerChromium::updateContentsIfDirty()
+void Canvas2DLayerChromium::updateCompositorResources()
{
if (!m_contentsDirty || !m_drawingBuffer)
return;
diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
index a14cb98..81b118c 100644
--- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
@@ -46,7 +46,7 @@ public:
static PassRefPtr<Canvas2DLayerChromium> create(DrawingBuffer*, GraphicsLayerChromium* owner);
virtual ~Canvas2DLayerChromium();
virtual bool drawsContent() const { return true; }
- virtual void updateContentsIfDirty();
+ virtual void updateCompositorResources();
void setTextureChanged();
unsigned textureId() const;
@@ -55,8 +55,6 @@ public:
private:
explicit Canvas2DLayerChromium(DrawingBuffer*, GraphicsLayerChromium* owner);
DrawingBuffer* m_drawingBuffer;
-
- static unsigned m_shaderProgramId;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp
index 0264868..f306207 100644
--- a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp
@@ -40,8 +40,6 @@
namespace WebCore {
-unsigned CanvasLayerChromium::m_shaderProgramId = 0;
-
CanvasLayerChromium::CanvasLayerChromium(GraphicsLayerChromium* owner)
: LayerChromium(owner)
, m_textureChanged(true)
@@ -54,22 +52,18 @@ CanvasLayerChromium::~CanvasLayerChromium()
{
}
-void CanvasLayerChromium::draw()
+PassRefPtr<CCLayerImpl> CanvasLayerChromium::createCCLayerImpl()
{
- ASSERT(layerRenderer());
- const CanvasLayerChromium::Program* program = layerRenderer()->canvasLayerProgram();
- ASSERT(program && program->initialized());
- GraphicsContext3D* context = layerRendererContext();
- GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
- GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId));
- GC3Denum sfactor = m_premultipliedAlpha ? GraphicsContext3D::ONE : GraphicsContext3D::SRC_ALPHA;
- GLC(context, context->blendFunc(sfactor, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
- layerRenderer()->useShader(program->program());
- GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
- drawTexturedQuad(context, layerRenderer()->projectionMatrix(), ccLayerImpl()->drawTransform(),
- bounds().width(), bounds().height(), ccLayerImpl()->drawOpacity(),
- program->vertexShader().matrixLocation(),
- program->fragmentShader().alphaLocation());
+ return CCCanvasLayerImpl::create(this);
+}
+
+void CanvasLayerChromium::pushPropertiesTo(CCLayerImpl* layer)
+{
+ LayerChromium::pushPropertiesTo(layer);
+
+ CCCanvasLayerImpl* canvasLayer = static_cast<CCCanvasLayerImpl*>(layer);
+ canvasLayer->setTextureId(m_textureId);
+ canvasLayer->setPremultipliedAlpha(m_premultipliedAlpha);
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h
index ed3a06f..cb2ccc9 100644
--- a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h
@@ -43,9 +43,9 @@ class CanvasLayerChromium : public LayerChromium {
public:
virtual ~CanvasLayerChromium();
- virtual void draw();
+ virtual PassRefPtr<CCLayerImpl> createCCLayerImpl();
- typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program;
+ virtual void pushPropertiesTo(CCLayerImpl*);
protected:
explicit CanvasLayerChromium(GraphicsLayerChromium* owner);
@@ -55,9 +55,6 @@ protected:
bool m_textureChanged;
unsigned m_textureId;
bool m_premultipliedAlpha;
-
-private:
- static unsigned m_shaderProgramId;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
index 78f93d5..4ea9c92 100644
--- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
@@ -66,7 +66,7 @@ void ContentLayerChromium::cleanupResources()
m_contentsTexture.clear();
}
-bool ContentLayerChromium::requiresClippedUpdateRect() const
+bool ContentLayerChromium::requiresClippedUpdateRect()
{
// To avoid allocating excessively large textures, switch into "large layer mode" if
// one of the layer's dimensions is larger than 2000 pixels or the size of
@@ -77,7 +77,7 @@ bool ContentLayerChromium::requiresClippedUpdateRect() const
|| !layerRenderer()->checkTextureSize(bounds()));
}
-void ContentLayerChromium::updateContentsIfDirty()
+void ContentLayerChromium::paintContentsIfDirty()
{
RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());
if (!backing || backing->paintingGoesToWindow())
@@ -93,34 +93,25 @@ void ContentLayerChromium::updateContentsIfDirty()
// FIXME: Remove this test when tiled layers are implemented.
if (requiresClippedUpdateRect()) {
- // A layer with 3D transforms could require an arbitrarily large number
- // of texels to be repainted, so ignore these layers until tiling is
- // implemented.
- if (!ccLayerImpl()->drawTransform().isIdentityOrTranslation()) {
- m_skipsDraw = true;
- return;
- }
-
// Calculate the region of this layer that is currently visible.
const IntRect clipRect = ccLayerImpl()->targetRenderSurface()->contentRect();
TransformationMatrix layerOriginTransform = ccLayerImpl()->drawTransform();
layerOriginTransform.translate3d(-0.5 * bounds().width(), -0.5 * bounds().height(), 0);
- // For now we apply the large layer treatment only for layers that are either untransformed
- // or are purely translated. Their matrix is expected to be invertible.
- ASSERT(layerOriginTransform.isInvertible());
-
+ // We compute the visible portion of the layer by back-mapping the current RenderSurface
+ // content area to the layer. To do that, we invert the drawing matrix of the layer
+ // and project the content area rectangle to it. If the layer transform is not invertible
+ // then we skip rendering the layer.
+ if (!layerOriginTransform.isInvertible()) {
+ m_skipsDraw = true;
+ return;
+ }
TransformationMatrix targetToLayerMatrix = layerOriginTransform.inverse();
- IntRect visibleRectInLayerCoords = targetToLayerMatrix.mapRect(clipRect);
+ FloatQuad mappedClipToLayer = targetToLayerMatrix.projectQuad(FloatRect(clipRect));
+ IntRect visibleRectInLayerCoords = mappedClipToLayer.enclosingBoundingBox();
visibleRectInLayerCoords.intersect(IntRect(0, 0, bounds().width(), bounds().height()));
- // For normal layers, the center of the texture corresponds with the center of the layer.
- // In large layers the center of the texture is the center of the visible region so we have
- // to keep track of the offset in order to render correctly.
- IntRect visibleRectInSurfaceCoords = layerOriginTransform.mapRect(visibleRectInLayerCoords);
- m_layerCenterInSurfaceCoords = FloatRect(visibleRectInSurfaceCoords).center();
-
// If this is still too large to render, then skip the layer completely.
if (!layerRenderer()->checkTextureSize(visibleRectInLayerCoords.size())) {
m_skipsDraw = true;
@@ -256,9 +247,14 @@ void ContentLayerChromium::draw()
GLC(context, context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
if (requiresClippedUpdateRect()) {
- float m43 = ccLayerImpl()->drawTransform().m43();
- TransformationMatrix transform;
- transform.translate3d(m_layerCenterInSurfaceCoords.x(), m_layerCenterInSurfaceCoords.y(), m43);
+ // Compute the offset between the layer's center point and the center of the visible portion
+ // of the layer.
+ FloatPoint visibleRectCenterOffset = FloatRect(m_visibleRectInLayerCoords).center();
+ visibleRectCenterOffset.move(-0.5 * bounds().width(), -0.5 * bounds().height());
+
+ TransformationMatrix transform = ccLayerImpl()->drawTransform();
+ transform.translate(visibleRectCenterOffset.x(), visibleRectCenterOffset.y());
+
drawTexturedQuad(context, layerRenderer()->projectionMatrix(),
transform, m_visibleRectInLayerCoords.width(),
m_visibleRectInLayerCoords.height(), ccLayerImpl()->drawOpacity(),
@@ -273,6 +269,11 @@ void ContentLayerChromium::draw()
unreserveContentsTexture();
}
+void ContentLayerChromium::updateCompositorResources()
+{
+ updateTextureIfNeeded();
+}
+
void ContentLayerChromium::unreserveContentsTexture()
{
if (!m_skipsDraw && m_contentsTexture)
@@ -281,8 +282,6 @@ void ContentLayerChromium::unreserveContentsTexture()
void ContentLayerChromium::bindContentsTexture()
{
- updateTextureIfNeeded();
-
if (!m_skipsDraw && m_contentsTexture)
m_contentsTexture->bindTexture();
}
diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h
index 6f070c2..cf296ab 100644
--- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h
@@ -50,7 +50,8 @@ public:
virtual ~ContentLayerChromium();
- virtual void updateContentsIfDirty();
+ virtual void paintContentsIfDirty();
+ virtual void updateCompositorResources();
virtual void unreserveContentsTexture();
virtual void bindContentsTexture();
@@ -63,7 +64,7 @@ protected:
explicit ContentLayerChromium(GraphicsLayerChromium* owner);
virtual void cleanupResources();
- bool requiresClippedUpdateRect() const;
+ bool requiresClippedUpdateRect();
void resizeUploadBuffer(const IntSize&);
virtual const char* layerTypeAsString() const { return "ContentLayer"; }
@@ -82,7 +83,6 @@ private:
PlatformCanvas m_canvas;
IntRect m_visibleRectInLayerCoords;
- FloatPoint m_layerCenterInSurfaceCoords;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm
index 227fbe4..b442d53 100644
--- a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm
+++ b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm
@@ -29,7 +29,7 @@
#import "config.h"
#import "CrossProcessFontLoading.h"
-#import "../graphics/cocoa/FontPlatformData.h"
+#import "../graphics/FontPlatformData.h"
#import "PlatformBridge.h"
#import <AppKit/NSFont.h>
#import <wtf/HashMap.h>
diff --git a/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
index d956841..e559edb 100644
--- a/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
@@ -46,10 +46,6 @@
namespace WebCore {
-#if ENABLE(SKIA_GPU)
-extern GrContext* GetGlobalGrContext();
-#endif
-
struct DrawingBufferInternal {
unsigned offscreenColorTexture;
#if USE(ACCELERATED_COMPOSITING)
@@ -91,6 +87,9 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
, m_multisampleFBO(0)
, m_multisampleColorBuffer(0)
, m_internal(new DrawingBufferInternal)
+#if ENABLE(SKIA_GPU)
+ , m_grContext(0)
+#endif
{
if (!m_context->getExtensions()->supports("GL_CHROMIUM_copy_texture_to_parent_texture")) {
m_context.clear();
@@ -137,7 +136,8 @@ void DrawingBuffer::publishToPlatformLayer()
// would insert a fence into the child command stream that the compositor could wait for.
m_context->makeContextCurrent();
#if ENABLE(SKIA_GPU)
- GetGlobalGrContext()->flush(false);
+ if (m_grContext)
+ m_grContext->flush(0);
#endif
static_cast<Extensions3DChromium*>(m_context->getExtensions())->copyTextureToParentTextureCHROMIUM(m_colorBuffer, parentTexture);
m_context->flush();
@@ -166,4 +166,13 @@ Platform3DObject DrawingBuffer::platformColorBuffer() const
return m_colorBuffer;
}
+#if ENABLE(SKIA_GPU)
+void DrawingBuffer::setGrContext(GrContext* context)
+{
+ // We just take a ptr without referencing it, as we require that we never outlive
+ // the SharedGraphicsContext3D object that is giving us the context.
+ m_grContext = context;
+}
+#endif
+
}
diff --git a/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
index bbe6d62..598ae86 100644
--- a/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
@@ -153,7 +153,8 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
fontDescription.computedSize(),
(style & SkTypeface::kBold) && !tf->isBold(),
(style & SkTypeface::kItalic) && !tf->isItalic(),
- fontDescription.orientation());
+ fontDescription.orientation(),
+ fontDescription.textOrientation());
tf->unref();
return result;
}
diff --git a/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
index e57a84c..3c254dc 100644
--- a/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
@@ -196,7 +196,7 @@ class TransparencyAwareGlyphPainter : public TransparencyAwareFontPainter {
// left of m_point. We express it this way so that if we're using the Skia
// drawing path we can use floating-point positioning, even though we have
// to use integer positioning in the GDI path.
- bool drawGlyphs(int numGlyphs, const WORD* glyphs, const int* advances, int startAdvance) const;
+ bool drawGlyphs(int numGlyphs, const WORD* glyphs, const int* advances, float startAdvance) const;
private:
virtual IntRect estimateTextBounds();
@@ -256,11 +256,11 @@ IntRect TransparencyAwareGlyphPainter::estimateTextBounds()
bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs,
const WORD* glyphs,
const int* advances,
- int startAdvance) const
+ float startAdvance) const
{
if (!m_useGDI) {
SkPoint origin = m_point;
- origin.fX += startAdvance;
+ origin.fX += SkFloatToScalar(startAdvance);
return paintSkiaText(m_graphicsContext, m_font->platformData().hfont(),
numGlyphs, glyphs, advances, 0, &origin);
}
@@ -400,17 +400,25 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext,
Vector<WORD, kMaxBufferLength> glyphs;
Vector<int, kMaxBufferLength> advances;
int glyphIndex = 0; // The starting glyph of the current chunk.
- int curAdvance = 0; // How far from the left the current chunk is.
+
+ // In order to round all offsets to the correct pixel boundary, this code keeps track of the absolute position
+ // of each glyph in floating point units and rounds to integer advances at the last possible moment.
+
+ float horizontalOffset = point.x(); // The floating point offset of the left side of the current glyph.
+ int lastHorizontalOffsetRounded = lroundf(horizontalOffset); // The rounded offset of the left side of the last glyph rendered.
while (glyphIndex < numGlyphs) {
// How many chars will be in this chunk?
int curLen = std::min(kMaxBufferLength, numGlyphs - glyphIndex);
glyphs.resize(curLen);
advances.resize(curLen);
- int curWidth = 0;
+ float currentWidth = 0;
for (int i = 0; i < curLen; ++i, ++glyphIndex) {
glyphs[i] = glyphBuffer.glyphAt(from + glyphIndex);
- advances[i] = static_cast<int>(glyphBuffer.advanceAt(from + glyphIndex));
+ horizontalOffset += glyphBuffer.advanceAt(from + glyphIndex);
+ advances[i] = lroundf(horizontalOffset) - lastHorizontalOffsetRounded;
+ lastHorizontalOffsetRounded += advances[i];
+ currentWidth += glyphBuffer.advanceAt(from + glyphIndex);
// Bug 26088 - very large positive or negative runs can fail to
// render so we clamp the size here. In the specs, negative
@@ -420,15 +428,14 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext,
// -32830, so we give ourselves a little breathing room.
const int maxNegativeRun = -32768;
const int maxPositiveRun = 32768;
- if ((curWidth + advances[i] < maxNegativeRun) || (curWidth + advances[i] > maxPositiveRun))
+ if ((currentWidth + advances[i] < maxNegativeRun) || (currentWidth + advances[i] > maxPositiveRun))
advances[i] = 0;
- curWidth += advances[i];
}
// Actually draw the glyphs (with retry on failure).
bool success = false;
for (int executions = 0; executions < 2; ++executions) {
- success = painter.drawGlyphs(curLen, &glyphs[0], &advances[0], curAdvance);
+ success = painter.drawGlyphs(curLen, &glyphs[0], &advances[0], horizontalOffset - point.x() - currentWidth);
if (!success && executions == 0) {
// Ask the browser to load the font for us and retry.
PlatformBridge::ensureFontLoaded(font->platformData().hfont());
@@ -439,8 +446,6 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext,
if (!success)
LOG_ERROR("Unable to draw the glyphs after second attempt");
-
- curAdvance += curWidth;
}
}
@@ -509,8 +514,7 @@ void Font::drawComplexText(GraphicsContext* graphicsContext,
// Uniscribe counts the coordinates from the upper left, while WebKit uses
// the baseline, so we have to subtract off the ascent.
- state.draw(graphicsContext, hdc, static_cast<int>(point.x()),
- static_cast<int>(point.y() - fontMetrics().ascent()), from, to);
+ state.draw(graphicsContext, hdc, lroundf(point.x()), lroundf(point.y() - fontMetrics().ascent()), from, to);
context->canvas()->endPlatformPaint();
}
diff --git a/Source/WebCore/platform/graphics/chromium/FontLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontLinux.cpp
index 823dbc9..3c4a494 100644
--- a/Source/WebCore/platform/graphics/chromium/FontLinux.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontLinux.cpp
@@ -98,7 +98,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
SkPoint* vPosBegin = storage2.get();
SkPoint* vPosEnd = storage3.get();
- bool isVertical = font->orientation() == Vertical;
+ bool isVertical = font->platformData().orientation() == Vertical;
for (int i = 0; i < numGlyphs; i++) {
SkScalar myWidth = SkFloatToScalar(adv[i].width());
pos[i].set(x, y);
diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h b/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h
index b6ebb2e..84edebc 100644
--- a/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h
+++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h
@@ -71,6 +71,7 @@ public:
float size() const { return m_size; }
FontOrientation orientation() const { return Horizontal; } // FIXME: Implement.
+ void setOrientation(FontOrientation) { } // FIXME: Implement.
unsigned hash() const
{
@@ -105,7 +106,7 @@ private:
HFONT hfont() const { return m_hfont; }
unsigned hash() const
{
- return WTF::StringHasher::createBlobHash<sizeof(HFONT)>(&m_hfont);
+ return StringHasher::hashMemory<sizeof(HFONT)>(&m_hfont);
}
bool operator==(const RefCountedHFONT& other) const
diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
index 6f9009f..c3edfac 100644
--- a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
@@ -76,13 +76,14 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src)
, m_fakeBold(src.m_fakeBold)
, m_fakeItalic(src.m_fakeItalic)
, m_orientation(src.m_orientation)
+ , m_textOrientation(src.m_textOrientation)
, m_style(src.m_style)
, m_harfbuzzFace(src.m_harfbuzzFace)
{
SkSafeRef(m_typeface);
}
-FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation)
+FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation, TextOrientation textOrientation)
: m_typeface(tf)
, m_family(family)
, m_textSize(textSize)
@@ -90,6 +91,7 @@ FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float tex
, m_fakeBold(fakeBold)
, m_fakeItalic(fakeItalic)
, m_orientation(orientation)
+ , m_textOrientation(textOrientation)
{
SkSafeRef(m_typeface);
querySystemForRenderStyle();
@@ -102,6 +104,8 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize)
, m_emSizeInFontUnits(src.m_emSizeInFontUnits)
, m_fakeBold(src.m_fakeBold)
, m_fakeItalic(src.m_fakeItalic)
+ , m_orientation(src.m_orientation)
+ , m_textOrientation(src.m_textOrientation)
, m_harfbuzzFace(src.m_harfbuzzFace)
{
SkSafeRef(m_typeface);
@@ -134,6 +138,7 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src)
m_fakeItalic = src.m_fakeItalic;
m_harfbuzzFace = src.m_harfbuzzFace;
m_orientation = src.m_orientation;
+ m_textOrientation = src.m_textOrientation;
m_style = src.m_style;
m_emSizeInFontUnits = src.m_emSizeInFontUnits;
@@ -199,13 +204,14 @@ bool FontPlatformData::operator==(const FontPlatformData& a) const
&& m_fakeBold == a.m_fakeBold
&& m_fakeItalic == a.m_fakeItalic
&& m_orientation == a.m_orientation
+ && m_textOrientation == a.m_textOrientation
&& m_style == a.m_style;
}
unsigned FontPlatformData::hash() const
{
unsigned h = SkTypeface::UniqueID(m_typeface);
- h ^= 0x01010101 * ((static_cast<int>(m_orientation) << 2) | (static_cast<int>(m_fakeBold) << 1) | static_cast<int>(m_fakeItalic));
+ h ^= 0x01010101 * ((static_cast<int>(m_textOrientation) << 3) | (static_cast<int>(m_orientation) << 2) | (static_cast<int>(m_fakeBold) << 1) | static_cast<int>(m_fakeItalic));
// This memcpy is to avoid a reinterpret_cast that breaks strict-aliasing
// rules. Memcpy is generally optimized enough so that performance doesn't
diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
index d9ebb61..541aa86 100644
--- a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
+++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
@@ -33,6 +33,7 @@
#include "FontOrientation.h"
#include "FontRenderStyle.h"
+#include "TextOrientation.h"
#include <wtf/Forward.h>
#include <wtf/RefPtr.h>
#include <wtf/text/CString.h>
@@ -66,6 +67,8 @@ public:
, m_emSizeInFontUnits(0)
, m_fakeBold(false)
, m_fakeItalic(false)
+ , m_orientation(Horizontal)
+ , m_textOrientation(TextOrientationVerticalRight)
{ }
FontPlatformData()
@@ -75,6 +78,7 @@ public:
, m_fakeBold(false)
, m_fakeItalic(false)
, m_orientation(Horizontal)
+ , m_textOrientation(TextOrientationVerticalRight)
{ }
FontPlatformData(float textSize, bool fakeBold, bool fakeItalic)
@@ -84,10 +88,11 @@ public:
, m_fakeBold(fakeBold)
, m_fakeItalic(fakeItalic)
, m_orientation(Horizontal)
+ , m_textOrientation(TextOrientationVerticalRight)
{ }
FontPlatformData(const FontPlatformData&);
- FontPlatformData(SkTypeface*, const char* name, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation = Horizontal);
+ FontPlatformData(SkTypeface*, const char* name, float textSize, bool fakeBold, bool fakeItalic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight);
FontPlatformData(const FontPlatformData& src, float textSize);
~FontPlatformData();
@@ -113,7 +118,8 @@ public:
int emSizeInFontUnits() const;
FontOrientation orientation() const { return m_orientation; }
-
+ void setOrientation(FontOrientation orientation) { m_orientation = orientation; }
+
bool operator==(const FontPlatformData&) const;
FontPlatformData& operator=(const FontPlatformData&);
bool isHashTableDeletedValue() const { return m_typeface == hashTableDeletedFontValue(); }
@@ -161,6 +167,7 @@ private:
bool m_fakeBold;
bool m_fakeItalic;
FontOrientation m_orientation;
+ TextOrientation m_textOrientation;
FontRenderStyle m_style;
mutable RefPtr<RefCountedHarfbuzzFace> m_harfbuzzFace;
diff --git a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
index 2ff6b8b..cc5a060 100644
--- a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
+++ b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
@@ -62,29 +62,51 @@ typedef void (GLAPIENTRY *TESSCB)();
typedef WTF::Vector<float> FloatVector;
typedef WTF::Vector<double> DoubleVector;
+struct PathAndTransform {
+ PathAndTransform(const Path& p, const AffineTransform& t)
+ : path(p)
+ , transform(t)
+ {
+ }
+ Path path;
+ AffineTransform transform;
+};
+
struct GLES2Canvas::State {
State()
: m_fillColor(0, 0, 0, 255)
+ , m_shadowColor(0, 0, 0, 0)
, m_alpha(1.0f)
, m_compositeOp(CompositeSourceOver)
- , m_clippingEnabled(false)
+ , m_numClippingPaths(0)
+ , m_shadowOffset(0, 0)
+ , m_shadowBlur(0)
+ , m_shadowsIgnoreTransforms(false)
{
}
State(const State& other)
: m_fillColor(other.m_fillColor)
+ , m_shadowColor(other.m_shadowColor)
, m_alpha(other.m_alpha)
, m_compositeOp(other.m_compositeOp)
, m_ctm(other.m_ctm)
, m_clippingPaths() // Don't copy; clipping paths are tracked per-state.
- , m_clippingEnabled(other.m_clippingEnabled)
+ , m_numClippingPaths(other.m_numClippingPaths)
+ , m_shadowOffset(other.m_shadowOffset)
+ , m_shadowBlur(other.m_shadowBlur)
+ , m_shadowsIgnoreTransforms(other.m_shadowsIgnoreTransforms)
{
}
Color m_fillColor;
+ Color m_shadowColor;
float m_alpha;
CompositeOperator m_compositeOp;
AffineTransform m_ctm;
- WTF::Vector<Path> m_clippingPaths;
- bool m_clippingEnabled;
+ WTF::Vector<PathAndTransform> m_clippingPaths;
+ int m_numClippingPaths;
+ FloatSize m_shadowOffset;
+ float m_shadowBlur;
+ bool m_shadowsIgnoreTransforms;
// Helper function for applying the state's alpha value to the given input
// color to produce a new output color. The logic is the same as
@@ -100,7 +122,11 @@ struct GLES2Canvas::State {
int a = (c.alpha() * s) >> 8;
return Color(c.red(), c.green(), c.blue(), a);
}
-
+ bool shadowActive() const
+ {
+ return m_shadowColor.alpha() > 0 && (m_shadowBlur || m_shadowOffset.width() || m_shadowOffset.height());
+ }
+ bool clippingEnabled() { return m_numClippingPaths > 0; }
};
static inline FloatPoint operator*(const FloatPoint& f, float scale)
@@ -193,12 +219,8 @@ void GLES2Canvas::bindFramebuffer()
void GLES2Canvas::clearRect(const FloatRect& rect)
{
bindFramebuffer();
- if (m_state->m_ctm.isIdentity() && !m_state->m_clippingEnabled) {
- m_context->scissor(rect.x(), m_size.height() - rect.height() - rect.y(), rect.width(), rect.height());
- m_context->enable(GraphicsContext3D::SCISSOR_TEST);
- m_context->clearColor(Color(RGBA32(0)));
- m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
- m_context->disable(GraphicsContext3D::SCISSOR_TEST);
+ if (m_state->m_ctm.isIdentity() && !m_state->clippingEnabled()) {
+ scissorClear(rect.x(), rect.y(), rect.width(), rect.height());
} else {
save();
setCompositeOperation(CompositeClear);
@@ -207,35 +229,66 @@ void GLES2Canvas::clearRect(const FloatRect& rect)
}
}
+void GLES2Canvas::scissorClear(float x, float y, float width, float height)
+{
+ int intX = static_cast<int>(x + 0.5f);
+ int intY = static_cast<int>(y + 0.5f);
+ int intWidth = static_cast<int>(x + width + 0.5f) - intX;
+ int intHeight = static_cast<int>(y + height + 0.5f) - intY;
+ m_context->scissor(intX, m_size.height() - intHeight - intY, intWidth, intHeight);
+ m_context->enable(GraphicsContext3D::SCISSOR_TEST);
+ m_context->clearColor(Color(RGBA32(0)));
+ m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
+ m_context->disable(GraphicsContext3D::SCISSOR_TEST);
+}
+
void GLES2Canvas::fillPath(const Path& path)
{
+ if (m_state->shadowActive()) {
+ beginShadowDraw();
+ fillPathInternal(path, m_state->m_shadowColor);
+ endShadowDraw(path.boundingRect());
+ }
+
+ bindFramebuffer();
m_context->applyCompositeOperator(m_state->m_compositeOp);
- applyClipping(m_state->m_clippingEnabled);
- fillPath(path, m_state->applyAlpha(m_state->m_fillColor));
+ applyClipping(m_state->clippingEnabled());
+
+ fillPathInternal(path, m_state->applyAlpha(m_state->m_fillColor));
}
void GLES2Canvas::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
{
+ if (m_state->shadowActive()) {
+ beginShadowDraw();
+ fillRectInternal(rect, m_state->m_shadowColor);
+ endShadowDraw(rect);
+ }
+
+ bindFramebuffer();
m_context->applyCompositeOperator(m_state->m_compositeOp);
- applyClipping(m_state->m_clippingEnabled);
- m_context->useQuadVertices();
+ applyClipping(m_state->clippingEnabled());
+
+ fillRectInternal(rect, color);
+}
+
+void GLES2Canvas::fillRect(const FloatRect& rect)
+{
+ fillRect(rect, m_state->applyAlpha(m_state->m_fillColor), ColorSpaceDeviceRGB);
+}
+void GLES2Canvas::fillRectInternal(const FloatRect& rect, const Color& color)
+{
AffineTransform matrix(m_flipMatrix);
matrix *= m_state->m_ctm;
matrix.translate(rect.x(), rect.y());
matrix.scale(rect.width(), rect.height());
+ m_context->useQuadVertices();
m_context->useFillSolidProgram(matrix, color);
-
- bindFramebuffer();
m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4);
}
-void GLES2Canvas::fillRect(const FloatRect& rect)
-{
- fillRect(rect, m_state->applyAlpha(m_state->m_fillColor), ColorSpaceDeviceRGB);
-}
-
void GLES2Canvas::setFillColor(const Color& color, ColorSpace colorSpace)
{
m_state->m_fillColor = color;
@@ -246,6 +299,26 @@ void GLES2Canvas::setAlpha(float alpha)
m_state->m_alpha = alpha;
}
+void GLES2Canvas::setShadowColor(const Color& color, ColorSpace)
+{
+ m_state->m_shadowColor = color;
+}
+
+void GLES2Canvas::setShadowOffset(const FloatSize& offset)
+{
+ m_state->m_shadowOffset = offset;
+}
+
+void GLES2Canvas::setShadowBlur(float shadowBlur)
+{
+ m_state->m_shadowBlur = shadowBlur;
+}
+
+void GLES2Canvas::setShadowsIgnoreTransforms(bool shadowsIgnoreTransforms)
+{
+ m_state->m_shadowsIgnoreTransforms = shadowsIgnoreTransforms;
+}
+
void GLES2Canvas::translate(float x, float y)
{
m_state->m_ctm.translate(x, y);
@@ -275,12 +348,12 @@ void GLES2Canvas::clipPath(const Path& path)
{
bindFramebuffer();
checkGLError("bindFramebuffer");
- beginStencilDraw();
+ beginStencilDraw(GraphicsContext3D::INCR);
// Red is used so we can see it if it ends up in the color buffer.
Color red(255, 0, 0, 255);
- fillPath(path, red);
- m_state->m_clippingPaths.append(path);
- m_state->m_clippingEnabled = true;
+ fillPathInternal(path, red);
+ m_state->m_clippingPaths.append(PathAndTransform(path, m_state->m_ctm));
+ m_state->m_numClippingPaths++;
}
void GLES2Canvas::clipOut(const Path& path)
@@ -297,53 +370,48 @@ void GLES2Canvas::save()
void GLES2Canvas::restore()
{
ASSERT(!m_stateStack.isEmpty());
- bool hadClippingPaths = !m_state->m_clippingPaths.isEmpty();
- m_stateStack.removeLast();
- m_state = &m_stateStack.last();
- if (hadClippingPaths) {
- m_context->clear(GraphicsContext3D::STENCIL_BUFFER_BIT);
- beginStencilDraw();
- StateVector::const_iterator iter;
- for (iter = m_stateStack.begin(); iter < m_stateStack.end(); ++iter) {
- const State& state = *iter;
- const Vector<Path>& clippingPaths = state.m_clippingPaths;
- Vector<Path>::const_iterator pathIter;
- for (pathIter = clippingPaths.begin(); pathIter < clippingPaths.end(); ++pathIter) {
- // Red is used so we can see it if it ends up in the color buffer.
- Color red(255, 0, 0, 255);
- fillPath(*pathIter, red);
- }
+ const Vector<PathAndTransform>& clippingPaths = m_state->m_clippingPaths;
+ if (!clippingPaths.isEmpty()) {
+ beginStencilDraw(GraphicsContext3D::DECR);
+ WTF::Vector<PathAndTransform>::const_iterator pathIter;
+ for (pathIter = clippingPaths.begin(); pathIter < clippingPaths.end(); ++pathIter) {
+ m_state->m_ctm = pathIter->transform;
+ // Red is used so we can see it if it ends up in the color buffer.
+ Color red(255, 0, 0, 255);
+ fillPathInternal(pathIter->path, red);
}
}
+ m_stateStack.removeLast();
+ m_state = &m_stateStack.last();
}
void GLES2Canvas::drawTexturedRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp)
{
+ bindFramebuffer();
m_context->applyCompositeOperator(compositeOp);
applyClipping(false);
- m_context->useQuadVertices();
m_context->setActiveTexture(GraphicsContext3D::TEXTURE0);
m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, texture);
- drawQuad(textureSize, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha);
+ drawTexturedQuad(textureSize, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha);
}
void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp)
{
- drawTexturedRect(texture, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha, colorSpace, compositeOp, m_state->m_clippingEnabled);
+ drawTexturedRect(texture, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha, colorSpace, compositeOp, m_state->clippingEnabled());
}
void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha, ColorSpace colorSpace, CompositeOperator compositeOp, bool clip)
{
+ bindFramebuffer();
m_context->applyCompositeOperator(compositeOp);
applyClipping(clip);
const TilingData& tiles = texture->tiles();
IntRect tileIdxRect = tiles.overlappedTileIndices(srcRect);
- m_context->useQuadVertices();
m_context->setActiveTexture(GraphicsContext3D::TEXTURE0);
for (int y = tileIdxRect.y(); y <= tileIdxRect.maxY(); y++) {
@@ -367,13 +435,18 @@ void GLES2Canvas::drawTexturedRectTile(Texture* texture, int tile, const FloatRe
IntRect tileBoundsWithBorder = tiles.tileBoundsWithBorder(tile);
- drawQuad(tileBoundsWithBorder.size(), srcRectClippedInTileSpace, dstRectIntersected, transform, alpha);
+ drawTexturedQuad(tileBoundsWithBorder.size(), srcRectClippedInTileSpace, dstRectIntersected, transform, alpha);
}
-void GLES2Canvas::drawQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha)
+void GLES2Canvas::convolveRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, float imageIncrement[2], const float* kernel, int kernelWidth)
{
+ m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, texture);
+ m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
+ m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
+ m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST);
+ m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST);
+
AffineTransform matrix(m_flipMatrix);
- matrix *= transform;
matrix.translate(dstRect.x(), dstRect.y());
matrix.scale(dstRect.width(), dstRect.height());
@@ -382,13 +455,79 @@ void GLES2Canvas::drawQuad(const IntSize& textureSize, const FloatRect& srcRect,
texMatrix.translate(srcRect.x(), srcRect.y());
texMatrix.scale(srcRect.width(), srcRect.height());
- bindFramebuffer();
+ m_context->useQuadVertices();
+ m_context->useConvolutionProgram(matrix, texMatrix, kernel, kernelWidth, imageIncrement);
+ m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4);
+ checkGLError("glDrawArrays");
+}
+static float gauss(float x, float sigma)
+{
+ return exp(- (x * x) / (2.0f * sigma * sigma));
+}
+
+static void buildKernel(float sigma, float* kernel, int kernelWidth)
+{
+ float halfWidth = (kernelWidth - 1.0f) / 2.0f;
+ float sum = 0.0f;
+ for (int i = 0; i < kernelWidth; ++i) {
+ kernel[i] = gauss(i - halfWidth, sigma);
+ sum += kernel[i];
+ }
+ // Normalize the kernel
+ float scale = 1.0f / sum;
+ for (int i = 0; i < kernelWidth; ++i)
+ kernel[i] *= scale;
+}
+
+void GLES2Canvas::drawTexturedQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha)
+{
+ AffineTransform matrix(m_flipMatrix);
+ matrix *= transform;
+ matrix.translate(dstRect.x(), dstRect.y());
+ matrix.scale(dstRect.width(), dstRect.height());
+
+ AffineTransform texMatrix;
+ texMatrix.scale(1.0f / textureSize.width(), 1.0f / textureSize.height());
+ texMatrix.translate(srcRect.x(), srcRect.y());
+ texMatrix.scale(srcRect.width(), srcRect.height());
+
+ m_context->useQuadVertices();
m_context->useTextureProgram(matrix, texMatrix, alpha);
m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4);
checkGLError("glDrawArrays");
}
+void GLES2Canvas::drawTexturedQuadMitchell(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha)
+{
+ static const float mitchellCoefficients[16] = {
+ 0.0f / 18.0f, 1.0f / 18.0f, 16.0f / 18.0f, 1.0f / 18.0f,
+ 0.0f / 18.0f, 9.0f / 18.0f, 0.0f / 18.0f, -9.0f / 18.0f,
+ -6.0f / 18.0f, 27.0f / 18.0f, -36.0f / 18.0f, 15.0f / 18.0f,
+ 7.0f / 18.0f, -21.0f / 18.0f, 21.0f / 18.0f, -7.0f / 18.0f,
+ };
+
+ AffineTransform matrix(m_flipMatrix);
+ matrix *= transform;
+ matrix.translate(dstRect.x(), dstRect.y());
+ matrix.scale(dstRect.width(), dstRect.height());
+
+ float imageIncrement[2] = { 1.0f / textureSize.width(), 1.0f / textureSize.height() };
+
+ AffineTransform texMatrix;
+ texMatrix.scale(imageIncrement[0], imageIncrement[1]);
+ texMatrix.translate(srcRect.x(), srcRect.y());
+ texMatrix.scale(srcRect.width(), srcRect.height());
+
+ m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST);
+ m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST);
+
+ m_context->useQuadVertices();
+ m_context->useBicubicProgram(matrix, texMatrix, mitchellCoefficients, imageIncrement, alpha);
+ m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4);
+ checkGLError("glDrawArrays");
+}
+
void GLES2Canvas::setCompositeOperation(CompositeOperator op)
{
m_state->m_compositeOp = op;
@@ -554,12 +693,9 @@ void GLES2Canvas::createVertexBufferFromPath(const Path& path, int* count, unsig
*count = indices.size();
}
-void GLES2Canvas::fillPath(const Path& path, const Color& color)
+void GLES2Canvas::fillPathInternal(const Path& path, const Color& color)
{
if (SharedGraphicsContext3D::useLoopBlinnForPathRendering()) {
- bindFramebuffer();
- m_context->applyCompositeOperator(m_state->m_compositeOp);
-
m_pathCache.clear();
LoopBlinnPathProcessor processor;
processor.process(path, m_pathCache);
@@ -590,18 +726,18 @@ void GLES2Canvas::fillPath(const Path& path, const Color& color)
int count;
unsigned vertexBuffer, indexBuffer;
createVertexBufferFromPath(path, &count, &vertexBuffer, &indexBuffer);
+
+ AffineTransform matrix(m_flipMatrix);
+ matrix *= m_state->m_ctm;
+
m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, vertexBuffer);
checkGLError("bindBuffer");
m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, indexBuffer);
checkGLError("bindBuffer");
- AffineTransform matrix(m_flipMatrix);
- matrix *= m_state->m_ctm;
-
m_context->useFillSolidProgram(matrix, color);
checkGLError("useFillSolidProgram");
- bindFramebuffer();
m_context->graphicsContext3D()->drawElements(GraphicsContext3D::TRIANGLES, count, GraphicsContext3D::UNSIGNED_SHORT, 0);
checkGLError("drawArrays");
@@ -613,7 +749,141 @@ void GLES2Canvas::fillPath(const Path& path, const Color& color)
}
}
-void GLES2Canvas::beginStencilDraw()
+FloatRect GLES2Canvas::flipRect(const FloatRect& rect)
+{
+ FloatRect flippedRect(rect);
+ flippedRect.setY(m_size.height() - rect.y());
+ flippedRect.setHeight(-rect.height());
+ return flippedRect;
+}
+
+void GLES2Canvas::clearBorders(const FloatRect& rect, int width)
+{
+ scissorClear(rect.x(), rect.y() - width, rect.width() + width, width);
+ scissorClear(rect.maxX(), rect.y(), width, rect.height() + width);
+ scissorClear(rect.x() - width, rect.maxY(), rect.width() + width, width);
+ scissorClear(rect.x() - width, rect.y() - width, width, rect.height() + width);
+}
+
+void GLES2Canvas::beginShadowDraw()
+{
+ float offsetX = m_state->m_shadowOffset.width();
+ float offsetY = m_state->m_shadowOffset.height();
+ save();
+ if (m_state->m_shadowsIgnoreTransforms) {
+ AffineTransform newCTM;
+ newCTM.translate(offsetX, -offsetY);
+ newCTM *= m_state->m_ctm;
+ m_state->m_ctm = newCTM;
+ } else
+ m_state->m_ctm.translate(offsetX, offsetY);
+
+ if (m_state->m_shadowBlur > 0) {
+ // Draw hard shadow to offscreen buffer 0.
+ DrawingBuffer* dstBuffer = m_context->getOffscreenBuffer(0, m_size);
+ dstBuffer->bind();
+ m_context->applyCompositeOperator(CompositeCopy);
+ applyClipping(false);
+ m_context->clearColor(Color(RGBA32(0)));
+ m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
+ } else {
+ bindFramebuffer();
+ m_context->applyCompositeOperator(m_state->m_compositeOp);
+ applyClipping(m_state->clippingEnabled());
+ }
+}
+
+void GLES2Canvas::endShadowDraw(const FloatRect& boundingBox)
+{
+ if (m_state->m_shadowBlur > 0) {
+ // Buffer 0 contains the primitive drawn with a hard shadow.
+ DrawingBuffer* srcBuffer = m_context->getOffscreenBuffer(0, m_size);
+ DrawingBuffer* dstBuffer = m_context->getOffscreenBuffer(1, m_size);
+
+ float sigma = m_state->m_shadowBlur * 0.333333f;
+ FloatRect shadowBoundingBox(m_state->m_ctm.mapRect(boundingBox));
+ FloatRect rect(FloatPoint(0, 0), m_size);
+ FloatRect srcRect(shadowBoundingBox);
+
+ int scaleFactor = 1;
+ while (sigma > cMaxSigma) {
+ srcRect.scale(0.5f);
+ scaleFactor *= 2;
+ sigma *= 0.5f;
+ }
+ srcRect = enclosingIntRect(srcRect);
+ srcRect.scale(scaleFactor);
+ for (int i = 1; i < scaleFactor; i *= 2) {
+ dstBuffer->bind();
+ m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, srcBuffer->colorBuffer());
+ m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
+ m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
+ m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
+ m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
+ FloatRect dstRect(srcRect);
+ dstRect.scale(0.5f);
+ // Clear out 1 pixel border for linear filtering.
+ clearBorders(dstRect, 1);
+ drawTexturedQuad(srcBuffer->size(), flipRect(srcRect), dstRect, AffineTransform(), 1.0);
+ srcRect = dstRect;
+ std::swap(srcBuffer, dstBuffer);
+ }
+
+ int halfWidth = static_cast<int>(sigma * 3.0f);
+ int kernelWidth = halfWidth * 2 + 1;
+ OwnArrayPtr<float> kernel = adoptArrayPtr(new float[kernelWidth]);
+ buildKernel(sigma, kernel.get(), kernelWidth);
+
+ if (scaleFactor > 1) {
+ scissorClear(srcRect.maxX(), srcRect.y(), kernelWidth, srcRect.height());
+ scissorClear(srcRect.x() - kernelWidth, srcRect.y(), kernelWidth, srcRect.height());
+ }
+
+ // Blur in X offscreen.
+ dstBuffer->bind();
+ srcRect.inflateX(halfWidth);
+ srcRect.intersect(rect);
+ float imageIncrementX[2] = {1.0f / srcBuffer->size().width(), 0.0f};
+ convolveRect(srcBuffer->colorBuffer(), srcBuffer->size(), flipRect(srcRect), srcRect, imageIncrementX, kernel.get(), kernelWidth);
+
+ if (scaleFactor > 1) {
+ scissorClear(srcRect.x(), srcRect.maxY(), srcRect.width(), kernelWidth);
+ scissorClear(srcRect.x(), srcRect.y() - kernelWidth, srcRect.width(), kernelWidth);
+ }
+ srcRect.inflateY(halfWidth);
+ srcRect.intersect(rect);
+ std::swap(srcBuffer, dstBuffer);
+
+ float imageIncrementY[2] = {0.0f, 1.0f / srcBuffer->size().height()};
+ if (scaleFactor > 1) {
+ // Blur in Y offscreen.
+ dstBuffer->bind();
+ convolveRect(srcBuffer->colorBuffer(), srcBuffer->size(), flipRect(srcRect), srcRect, imageIncrementY, kernel.get(), kernelWidth);
+ // Clear out 2 pixel border for bicubic filtering.
+ clearBorders(srcRect, 2);
+ std::swap(srcBuffer, dstBuffer);
+
+ // Upsample srcBuffer -> main framebuffer using bicubic filtering.
+ bindFramebuffer();
+ m_context->applyCompositeOperator(m_state->m_compositeOp);
+ applyClipping(m_state->clippingEnabled());
+ m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, srcBuffer->colorBuffer());
+ FloatRect dstRect = srcRect;
+ dstRect.scale(scaleFactor);
+ drawTexturedQuadMitchell(srcBuffer->size(), flipRect(srcRect), dstRect, AffineTransform(), 1.0);
+ } else {
+ // Blur in Y directly to framebuffer.
+ bindFramebuffer();
+ m_context->applyCompositeOperator(m_state->m_compositeOp);
+ applyClipping(m_state->clippingEnabled());
+
+ convolveRect(srcBuffer->colorBuffer(), srcBuffer->size(), flipRect(srcRect), srcRect, imageIncrementY, kernel.get(), kernelWidth);
+ }
+ }
+ restore();
+}
+
+void GLES2Canvas::beginStencilDraw(unsigned op)
{
// Turn on stencil test.
m_context->enableStencil(true);
@@ -624,9 +894,7 @@ void GLES2Canvas::beginStencilDraw()
checkGLError("stencilFunc");
// All writes incremement the stencil buffer.
- m_context->graphicsContext3D()->stencilOp(GraphicsContext3D::INCR,
- GraphicsContext3D::INCR,
- GraphicsContext3D::INCR);
+ m_context->graphicsContext3D()->stencilOp(op, op, op);
checkGLError("stencilOp");
}
@@ -635,7 +903,7 @@ void GLES2Canvas::applyClipping(bool enable)
m_context->enableStencil(enable);
if (enable) {
// Enable drawing only where stencil is non-zero.
- m_context->graphicsContext3D()->stencilFunc(GraphicsContext3D::EQUAL, m_state->m_clippingPaths.size() % 256, 1);
+ m_context->graphicsContext3D()->stencilFunc(GraphicsContext3D::EQUAL, m_state->m_numClippingPaths, -1);
checkGLError("stencilFunc");
// Keep all stencil values the same.
m_context->graphicsContext3D()->stencilOp(GraphicsContext3D::KEEP,
diff --git a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h
index 8887a16..f6a8bcf 100644
--- a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h
+++ b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h
@@ -64,6 +64,10 @@ public:
void clearRect(const FloatRect&);
void setFillColor(const Color&, ColorSpace);
void setAlpha(float alpha);
+ void setShadowColor(const Color&, ColorSpace);
+ void setShadowOffset(const FloatSize&);
+ void setShadowBlur(float);
+ void setShadowsIgnoreTransforms(bool);
void setCompositeOperation(CompositeOperator);
void translate(float x, float y);
void rotate(float angleInRadians);
@@ -96,12 +100,21 @@ public:
DrawingBuffer* drawingBuffer() const { return m_drawingBuffer; }
private:
+ void scissorClear(float x, float y, float width, float height);
void drawTexturedRectTile(Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha);
- void drawQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha);
+ void drawTexturedQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha);
+ void drawTexturedQuadMitchell(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha);
+ void convolveRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, float imageIncrement[2], const float* kernel, int kernelWidth);
+
void applyCompositeOperator(CompositeOperator);
void createVertexBufferFromPath(const Path&, int* count, unsigned* vertexBuffer, unsigned* indexBuffer);
- void fillPath(const Path&, const Color&);
- void beginStencilDraw();
+ void fillPathInternal(const Path&, const Color&);
+ void fillRectInternal(const FloatRect&, const Color&);
+ FloatRect flipRect(const FloatRect&);
+ void clearBorders(const FloatRect&, int width);
+ void beginShadowDraw();
+ void endShadowDraw(const FloatRect& boundingBox);
+ void beginStencilDraw(unsigned op);
void applyClipping(bool enable);
void checkGLError(const char* header);
diff --git a/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp
index ee2b5ab..cfc1754 100644
--- a/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp
@@ -36,8 +36,8 @@
#include "GlyphPageTreeNode.h"
#include "PlatformBridge.h"
#include "SimpleFontData.h"
+#include "SystemInfo.h"
#include "UniscribeHelperTextRun.h"
-#include "WindowsVersion.h"
namespace WebCore {
@@ -134,7 +134,7 @@ static bool fillBMPGlyphs(unsigned offset,
bool haveGlyphs = false;
int invalidGlyph = 0xFFFF;
const DWORD cffTableTag = 0x20464643; // 4-byte identifier for OpenType CFF table ('CFF ').
- if (!isVistaOrNewer() && !(tm.tmPitchAndFamily & TMPF_TRUETYPE) && (GetFontData(dc, cffTableTag, 0, 0, 0) == GDI_ERROR))
+ if ((windowsVersion() < WindowsVista) && !(tm.tmPitchAndFamily & TMPF_TRUETYPE) && (GetFontData(dc, cffTableTag, 0, 0, 0) == GDI_ERROR))
invalidGlyph = 0x1F;
Glyph spaceGlyph = 0; // Glyph for a space. Lazily filled.
diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
index 7c42366..60c1332 100644
--- a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
@@ -60,7 +60,7 @@ void ImageLayerChromium::setContents(Image* contents)
setNeedsDisplay();
}
-void ImageLayerChromium::updateContentsIfDirty()
+void ImageLayerChromium::paintContentsIfDirty()
{
ASSERT(layerRenderer());
@@ -68,7 +68,7 @@ void ImageLayerChromium::updateContentsIfDirty()
if (requiresClippedUpdateRect()) {
// Use the base version of updateContents which draws a subset of the
// image to a bitmap, as the pixel contents can't be uploaded directly.
- ContentLayerChromium::updateContentsIfDirty();
+ ContentLayerChromium::paintContentsIfDirty();
return;
}
diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h
index cc9064d..6addabc 100644
--- a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h
@@ -50,7 +50,7 @@ class ImageLayerChromium : public ContentLayerChromium {
public:
static PassRefPtr<ImageLayerChromium> create(GraphicsLayerChromium* owner = 0);
- virtual void updateContentsIfDirty();
+ virtual void paintContentsIfDirty();
virtual bool drawsContent() const { return m_contents; }
void setContents(Image* image);
diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
index 95b7386..bc28239 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
@@ -62,6 +62,7 @@ LayerChromium::LayerChromium(GraphicsLayerChromium* owner)
: m_owner(owner)
, m_contentsDirty(false)
, m_maskLayer(0)
+ , m_ccLayerImpl(0)
, m_superlayer(0)
#ifndef NDEBUG
, m_debugID(s_nextLayerDebugID++)
@@ -77,7 +78,7 @@ LayerChromium::LayerChromium(GraphicsLayerChromium* owner)
, m_opaque(true)
, m_geometryFlipped(false)
, m_needsDisplayOnBoundsChange(false)
- , m_ccLayerImpl(CCLayerImpl::create(this))
+ , m_doubleSided(true)
, m_replicaLayer(0)
{
}
@@ -94,7 +95,8 @@ LayerChromium::~LayerChromium()
void LayerChromium::cleanupResources()
{
- m_ccLayerImpl->cleanupResources();
+ if (m_ccLayerImpl)
+ m_ccLayerImpl->cleanupResources();
}
void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer)
@@ -105,8 +107,7 @@ void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer)
cleanupResources();
setNeedsDisplay();
}
-
- m_ccLayerImpl->setLayerRenderer(renderer);
+ m_layerRenderer = renderer;
}
void LayerChromium::setNeedsCommit()
@@ -188,7 +189,7 @@ void LayerChromium::setBounds(const IntSize& size)
bool firstResize = !bounds().width() && !bounds().height() && size.width() && size.height();
- m_ccLayerImpl->setBounds(size);
+ m_bounds = size;
if (firstResize)
setNeedsDisplay(FloatRect(0, 0, bounds().width(), bounds().height()));
@@ -240,7 +241,6 @@ LayerChromium* LayerChromium::superlayer() const
void LayerChromium::setName(const String& name)
{
m_name = name;
- m_ccLayerImpl->setName(name);
}
void LayerChromium::setNeedsDisplay(const FloatRect& dirtyRect)
@@ -288,6 +288,29 @@ void LayerChromium::toGLMatrix(float* flattened, const TransformationMatrix& m)
flattened[15] = m.m44();
}
+void LayerChromium::pushPropertiesTo(CCLayerImpl* layer)
+{
+ layer->setAnchorPoint(m_anchorPoint);
+ layer->setAnchorPointZ(m_anchorPointZ);
+ layer->setBounds(m_bounds);
+ layer->setDebugBorderColor(m_debugBorderColor);
+ layer->setDebugBorderWidth(m_debugBorderWidth);
+ layer->setDoubleSided(m_doubleSided);
+ layer->setLayerRenderer(m_layerRenderer.get());
+ layer->setMasksToBounds(m_masksToBounds);
+ layer->setName(m_name);
+ layer->setOpacity(m_opacity);
+ layer->setPosition(m_position);
+ layer->setPreserves3D(preserves3D());
+ layer->setSublayerTransform(m_sublayerTransform);
+ layer->setTransform(m_transform);
+
+ if (maskLayer())
+ maskLayer()->pushPropertiesTo(layer->maskLayer());
+ if (replicaLayer())
+ replicaLayer()->pushPropertiesTo(layer->replicaLayer());
+}
+
GraphicsContext3D* LayerChromium::layerRendererContext() const
{
ASSERT(layerRenderer());
@@ -316,31 +339,6 @@ void LayerChromium::drawTexturedQuad(GraphicsContext3D* context, const Transform
GLC(context, context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0));
}
-
-
-// Returns true if any of the layer's descendants has drawable content.
-bool LayerChromium::descendantsDrawContent()
-{
- const Vector<RefPtr<LayerChromium> >& sublayers = getSublayers();
- for (size_t i = 0; i < sublayers.size(); ++i)
- if (sublayers[i]->descendantsDrawContentRecursive())
- return true;
- return false;
-}
-
-// Returns true if either this layer or one of its descendants has drawable content.
-bool LayerChromium::descendantsDrawContentRecursive()
-{
- if (drawsContent())
- return true;
-
- const Vector<RefPtr<LayerChromium> >& sublayers = getSublayers();
- for (size_t i = 0; i < sublayers.size(); ++i)
- if (sublayers[i]->descendantsDrawContentRecursive())
- return true;
- return false;
-}
-
String LayerChromium::layerTreeAsText() const
{
TextStream ts;
@@ -359,7 +357,8 @@ void LayerChromium::dumpLayer(TextStream& ts, int indent) const
writeIndent(ts, indent);
ts << layerTypeAsString() << "(" << m_name << ")\n";
dumpLayerProperties(ts, indent+2);
- m_ccLayerImpl->dumpLayerProperties(ts, indent+2);
+ if (m_ccLayerImpl)
+ m_ccLayerImpl->dumpLayerProperties(ts, indent+2);
if (m_replicaLayer) {
writeIndent(ts, indent+2);
ts << "Replica:\n";
@@ -385,48 +384,38 @@ void LayerChromium::dumpLayerProperties(TextStream& ts, int indent) const
}
-// Begin calls that forward to the CCLayerImpl.
-// ==============================================
-// These exists just for debugging (via drawDebugBorder()).
-void LayerChromium::setBorderColor(const Color& color)
+PassRefPtr<CCLayerImpl> LayerChromium::createCCLayerImpl()
{
- m_ccLayerImpl->setDebugBorderColor(color);
- setNeedsCommit();
+ return CCLayerImpl::create(this);
}
-Color LayerChromium::borderColor() const
+void LayerChromium::createCCLayerImplIfNeeded()
{
- return m_ccLayerImpl->debugBorderColor();
+ if (!m_ccLayerImpl)
+ m_ccLayerImpl = createCCLayerImpl();
}
-void LayerChromium::setBorderWidth(float width)
+CCLayerImpl* LayerChromium::ccLayerImpl()
{
- m_ccLayerImpl->setDebugBorderWidth(width);
- setNeedsCommit();
+ return m_ccLayerImpl.get();
}
-float LayerChromium::borderWidth() const
-{
- return m_ccLayerImpl->debugBorderWidth();
-}
-
-LayerRendererChromium* LayerChromium::layerRenderer() const
+void LayerChromium::setBorderColor(const Color& color)
{
- return m_ccLayerImpl->layerRenderer();
+ m_debugBorderColor = color;
+ setNeedsCommit();
}
-void LayerChromium::setDoubleSided(bool doubleSided)
+void LayerChromium::setBorderWidth(float width)
{
- m_ccLayerImpl->setDoubleSided(doubleSided);
+ m_debugBorderWidth = width;
setNeedsCommit();
}
-const IntSize& LayerChromium::bounds() const
+LayerRendererChromium* LayerChromium::layerRenderer() const
{
- return m_ccLayerImpl->bounds();
+ return m_layerRenderer.get();
}
-// ==============================================
-// End calls that forward to the CCLayerImpl.
}
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerChromium.h
index 29a2165..428ce61 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.h
@@ -89,6 +89,9 @@ public:
void setBackgroundColor(const Color& color) { m_backgroundColor = color; setNeedsCommit(); }
Color backgroundColor() const { return m_backgroundColor; }
+ void setBounds(const IntSize&);
+ const IntSize& bounds() const { return m_bounds; }
+
void setClearsContext(bool clears) { m_clearsContext = clears; setNeedsCommit(); }
bool clearsContext() const { return m_clearsContext; }
@@ -133,6 +136,9 @@ public:
void setTransform(const TransformationMatrix& transform) { m_transform = transform; setNeedsCommit(); }
const TransformationMatrix& transform() const { return m_transform; }
+ bool doubleSided() const { return m_doubleSided; }
+ void setDoubleSided(bool doubleSided) { m_doubleSided = doubleSided; setNeedsCommit(); }
+
// FIXME: This setting is currently ignored.
void setGeometryFlipped(bool flipped) { m_geometryFlipped = flipped; setNeedsCommit(); }
bool geometryFlipped() const { return m_geometryFlipped; }
@@ -143,9 +149,6 @@ public:
// in the LayerRendererChromium.
virtual void setLayerRenderer(LayerRendererChromium*);
- // Returns true if any of the layer's descendants has content to draw.
- bool descendantsDrawContent();
-
void setOwner(GraphicsLayerChromium* owner) { m_owner = owner; }
void setReplicaLayer(LayerChromium* layer) { m_replicaLayer = layer; }
@@ -153,14 +156,14 @@ public:
// These methods typically need to be overwritten by derived classes.
virtual bool drawsContent() const { return false; }
- virtual void updateContentsIfDirty() { }
+ virtual void paintContentsIfDirty() { }
+ virtual void updateCompositorResources() { }
virtual void unreserveContentsTexture() { }
virtual void bindContentsTexture() { }
virtual void draw() { }
// These exists just for debugging (via drawDebugBorder()).
void setBorderColor(const Color&);
- Color borderColor() const;
#ifndef NDEBUG
int debugID() const { return m_debugID; }
@@ -170,21 +173,19 @@ public:
String layerTreeAsText() const;
void setBorderWidth(float);
- float borderWidth() const;
// Everything from here down in the public section will move to CCLayerImpl.
-
- CCLayerImpl* ccLayerImpl() const { return m_ccLayerImpl.get(); }
+ CCLayerImpl* ccLayerImpl();
+ void createCCLayerImplIfNeeded();
static void drawTexturedQuad(GraphicsContext3D*, const TransformationMatrix& projectionMatrix, const TransformationMatrix& layerMatrix,
float width, float height, float opacity,
int matrixLocation, int alphaLocation);
+ virtual void pushPropertiesTo(CCLayerImpl*);
+
// Begin calls that forward to the CCLayerImpl.
LayerRendererChromium* layerRenderer() const;
- void setDoubleSided(bool);
- void setBounds(const IntSize&);
- const IntSize& bounds() const;
// End calls that forward to the CCLayerImpl.
typedef ProgramBinding<VertexShaderPos, FragmentShaderColor> BorderProgram;
@@ -217,6 +218,11 @@ protected:
static const unsigned s_positionAttribLocation;
static const unsigned s_texCoordAttribLocation;
+ // Constructs a CCLayerImpl of the correct runtime type for this LayerChromium type.
+ virtual PassRefPtr<CCLayerImpl> createCCLayerImpl();
+
+ // For now, the LayerChromium directly owns its CCLayerImpl.
+ RefPtr<CCLayerImpl> m_ccLayerImpl;
private:
void setNeedsCommit();
@@ -233,19 +239,22 @@ private:
// This should only be called from removeFromSuperlayer.
void removeSublayer(LayerChromium*);
- bool descendantsDrawContentRecursive();
-
Vector<RefPtr<LayerChromium> > m_sublayers;
LayerChromium* m_superlayer;
+ RefPtr<LayerRendererChromium> m_layerRenderer;
+
#ifndef NDEBUG
int m_debugID;
#endif
// Layer properties.
+ IntSize m_bounds;
FloatPoint m_position;
FloatPoint m_anchorPoint;
Color m_backgroundColor;
+ Color m_debugBorderColor;
+ float m_debugBorderWidth;
float m_opacity;
float m_zPosition;
float m_anchorPointZ;
@@ -255,13 +264,12 @@ private:
bool m_opaque;
bool m_geometryFlipped;
bool m_needsDisplayOnBoundsChange;
+ bool m_doubleSided;
TransformationMatrix m_transform;
TransformationMatrix m_sublayerTransform;
FloatRect m_frame;
- // For now, the LayerChromium directly owns its CCLayerImpl.
- RefPtr<CCLayerImpl> m_ccLayerImpl;
// Replica layer used for reflections.
LayerChromium* m_replicaLayer;
diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
index e7b299f..fc15abd 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
@@ -36,6 +36,7 @@
#include "cc/CCLayerImpl.h"
#include "Canvas2DLayerChromium.h"
+#include "FloatQuad.h"
#include "GeometryBinding.h"
#include "GraphicsContext3D.h"
#include "LayerChromium.h"
@@ -43,6 +44,7 @@
#include "NotImplemented.h"
#include "TextStream.h"
#include "TextureManager.h"
+#include "TraceEvent.h"
#include "WebGLLayerChromium.h"
#include "cc/CCLayerImpl.h"
#if USE(SKIA)
@@ -91,21 +93,23 @@ bool LayerRendererChromium::compareLayerZ(const CCLayerImpl* a, const CCLayerImp
return a->drawDepth() < b->drawDepth();
}
-PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassRefPtr<GraphicsContext3D> context)
+PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<TilePaintInterface> contentPaint, PassOwnPtr<TilePaintInterface> scrollbarPaint)
{
if (!context)
return 0;
- RefPtr<LayerRendererChromium> layerRenderer(adoptRef(new LayerRendererChromium(context)));
+ RefPtr<LayerRendererChromium> layerRenderer(adoptRef(new LayerRendererChromium(context, contentPaint, scrollbarPaint)));
if (!layerRenderer->hardwareCompositing())
return 0;
return layerRenderer.release();
}
-LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> context)
- : m_rootLayer(0)
- , m_scrollPosition(IntPoint(-1, -1))
+LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<TilePaintInterface> contentPaint, PassOwnPtr<TilePaintInterface> scrollbarPaint)
+ : m_viewportScrollPosition(IntPoint(-1, -1))
+ , m_rootLayer(0)
+ , m_rootLayerContentPaint(contentPaint)
+ , m_rootLayerScrollbarPaint(scrollbarPaint)
, m_currentShader(0)
, m_currentRenderSurface(0)
, m_offscreenFramebufferId(0)
@@ -114,8 +118,8 @@ LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> conte
, m_defaultRenderSurface(0)
{
m_hardwareCompositing = initializeSharedObjects();
- m_rootLayerTiler = LayerTilerChromium::create(this, IntSize(256, 256), LayerTilerChromium::NoBorderTexels);
- ASSERT(m_rootLayerTiler);
+ m_rootLayerContentTiler = LayerTilerChromium::create(this, IntSize(256, 256), LayerTilerChromium::NoBorderTexels);
+ ASSERT(m_rootLayerContentTiler);
m_headsUpDisplay = CCHeadsUpDisplay::create(this);
}
@@ -146,129 +150,149 @@ void LayerRendererChromium::useShader(unsigned programId)
}
}
-IntRect LayerRendererChromium::verticalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect)
+IntRect LayerRendererChromium::verticalScrollbarRect() const
{
- IntRect verticalScrollbar(IntPoint(contentRect.maxX(), contentRect.y()), IntSize(visibleRect.width() - contentRect.width(), visibleRect.height()));
+ IntRect verticalScrollbar(IntPoint(m_viewportContentRect.maxX(), m_viewportContentRect.y()), IntSize(m_viewportVisibleRect.width() - m_viewportContentRect.width(), m_viewportVisibleRect.height()));
return verticalScrollbar;
}
-IntRect LayerRendererChromium::horizontalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect)
+IntRect LayerRendererChromium::horizontalScrollbarRect() const
{
- IntRect horizontalScrollbar(IntPoint(contentRect.x(), contentRect.maxY()), IntSize(visibleRect.width(), visibleRect.height() - contentRect.height()));
+ IntRect horizontalScrollbar(IntPoint(m_viewportContentRect.x(), m_viewportContentRect.maxY()), IntSize(m_viewportVisibleRect.width(), m_viewportVisibleRect.height() - m_viewportContentRect.height()));
return horizontalScrollbar;
}
-void LayerRendererChromium::invalidateRootLayerRect(const IntRect& dirtyRect, const IntRect& visibleRect, const IntRect& contentRect)
+void LayerRendererChromium::invalidateRootLayerRect(const IntRect& dirtyRect)
{
- m_rootLayerTiler->invalidateRect(dirtyRect);
+ m_rootLayerContentTiler->invalidateRect(dirtyRect);
+
+ // Scrollbars never need to render beyond the fold, so clip to the viewport.
+ IntRect visibleDirtyRect = dirtyRect;
+ visibleDirtyRect.intersect(m_viewportVisibleRect);
+
if (m_horizontalScrollbarTiler) {
- IntRect scrollbar = horizontalScrollbarRect(visibleRect, contentRect);
- if (dirtyRect.intersects(scrollbar)) {
+ IntRect scrollbar = horizontalScrollbarRect();
+ if (visibleDirtyRect.intersects(scrollbar)) {
m_horizontalScrollbarTiler->setLayerPosition(scrollbar.location());
- m_horizontalScrollbarTiler->invalidateRect(dirtyRect);
+ m_horizontalScrollbarTiler->invalidateRect(visibleDirtyRect);
}
}
if (m_verticalScrollbarTiler) {
- IntRect scrollbar = verticalScrollbarRect(visibleRect, contentRect);
- if (dirtyRect.intersects(scrollbar)) {
+ IntRect scrollbar = verticalScrollbarRect();
+ if (visibleDirtyRect.intersects(scrollbar)) {
m_verticalScrollbarTiler->setLayerPosition(scrollbar.location());
- m_verticalScrollbarTiler->invalidateRect(dirtyRect);
+ m_verticalScrollbarTiler->invalidateRect(visibleDirtyRect);
}
}
}
-void LayerRendererChromium::updateRootLayerContents(TilePaintInterface& tilePaint, const IntRect& visibleRect)
+void LayerRendererChromium::updateRootLayerContents()
{
- m_rootLayerTiler->update(tilePaint, visibleRect);
+ TRACE_EVENT("LayerRendererChromium::updateRootLayerContents", this, 0);
+ m_rootLayerContentTiler->update(*m_rootLayerContentPaint, m_viewportVisibleRect);
}
-void LayerRendererChromium::updateRootLayerScrollbars(TilePaintInterface& scrollbarPaint, const IntRect& visibleRect, const IntRect& contentRect)
+void LayerRendererChromium::updateRootLayerScrollbars()
{
- if (visibleRect.width() > contentRect.width()) {
- IntRect verticalScrollbar = verticalScrollbarRect(visibleRect, contentRect);
+ TRACE_EVENT("LayerRendererChromium::updateRootLayerScrollbars", this, 0);
+ if (m_viewportVisibleRect.width() > m_viewportContentRect.width()) {
+ IntRect verticalScrollbar = verticalScrollbarRect();
IntSize tileSize = verticalScrollbar.size().shrunkTo(IntSize(m_maxTextureSize, m_maxTextureSize));
if (!m_verticalScrollbarTiler)
m_verticalScrollbarTiler = LayerTilerChromium::create(this, tileSize, LayerTilerChromium::NoBorderTexels);
else
m_verticalScrollbarTiler->setTileSize(tileSize);
m_verticalScrollbarTiler->setLayerPosition(verticalScrollbar.location());
- m_verticalScrollbarTiler->update(scrollbarPaint, visibleRect);
+ m_verticalScrollbarTiler->update(*m_rootLayerScrollbarPaint, m_viewportVisibleRect);
} else
m_verticalScrollbarTiler.clear();
- if (visibleRect.height() > contentRect.height()) {
- IntRect horizontalScrollbar = horizontalScrollbarRect(visibleRect, contentRect);
+ if (m_viewportVisibleRect.height() > m_viewportContentRect.height()) {
+ IntRect horizontalScrollbar = horizontalScrollbarRect();
IntSize tileSize = horizontalScrollbar.size().shrunkTo(IntSize(m_maxTextureSize, m_maxTextureSize));
if (!m_horizontalScrollbarTiler)
m_horizontalScrollbarTiler = LayerTilerChromium::create(this, tileSize, LayerTilerChromium::NoBorderTexels);
else
m_horizontalScrollbarTiler->setTileSize(tileSize);
m_horizontalScrollbarTiler->setLayerPosition(horizontalScrollbar.location());
- m_horizontalScrollbarTiler->update(scrollbarPaint, visibleRect);
+ m_horizontalScrollbarTiler->update(*m_rootLayerScrollbarPaint, m_viewportVisibleRect);
} else
m_horizontalScrollbarTiler.clear();
}
void LayerRendererChromium::drawRootLayer()
{
- m_rootLayerTiler->draw(m_visibleRect);
+ m_rootLayerContentTiler->draw(m_viewportVisibleRect);
if (m_verticalScrollbarTiler)
- m_verticalScrollbarTiler->draw(m_visibleRect);
+ m_verticalScrollbarTiler->draw(m_viewportVisibleRect);
if (m_horizontalScrollbarTiler)
- m_horizontalScrollbarTiler->draw(m_visibleRect);
+ m_horizontalScrollbarTiler->draw(m_viewportVisibleRect);
+}
+
+void LayerRendererChromium::setViewport(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition)
+{
+ bool visibleRectChanged = m_viewportVisibleRect.size() != visibleRect.size();
+
+ m_viewportVisibleRect = visibleRect;
+ m_viewportContentRect = contentRect;
+ m_viewportScrollPosition = scrollPosition;
+
+ if (visibleRectChanged) {
+ // Reset the current render surface to force an update of the viewport and
+ // projection matrix next time useRenderSurface is called.
+ m_currentRenderSurface = 0;
+
+ m_rootLayerContentTiler->invalidateEntireLayer();
+ if (m_horizontalScrollbarTiler)
+ m_horizontalScrollbarTiler->invalidateEntireLayer();
+ if (m_verticalScrollbarTiler)
+ m_verticalScrollbarTiler->invalidateEntireLayer();
+ }
}
-void LayerRendererChromium::updateAndDrawLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition,
- TilePaintInterface& tilePaint, TilePaintInterface& scrollbarPaint)
+void LayerRendererChromium::updateAndDrawLayers()
{
ASSERT(m_hardwareCompositing);
if (!m_rootLayer)
return;
- updateRootLayerContents(tilePaint, visibleRect);
+ updateRootLayerContents();
+
// Recheck that we still have a root layer. This may become null if
// compositing gets turned off during a paint operation.
if (!m_rootLayer)
return;
- updateRootLayerScrollbars(scrollbarPaint, visibleRect, contentRect);
+ updateRootLayerScrollbars();
Vector<CCLayerImpl*> renderSurfaceLayerList;
- updateLayers(visibleRect, contentRect, scrollPosition, renderSurfaceLayerList);
+ updateLayers(renderSurfaceLayerList);
drawLayers(renderSurfaceLayerList);
+
+ if (isCompositingOffscreen())
+ copyOffscreenTextureToDisplay();
}
-void LayerRendererChromium::updateLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition,
- Vector<CCLayerImpl*>& renderSurfaceLayerList)
+void LayerRendererChromium::updateLayers(Vector<CCLayerImpl*>& renderSurfaceLayerList)
{
+ TRACE_EVENT("LayerRendererChromium::updateLayers", this, 0);
+ m_rootLayer->createCCLayerImplIfNeeded();
CCLayerImpl* rootDrawLayer = m_rootLayer->ccLayerImpl();
if (!rootDrawLayer->renderSurface())
rootDrawLayer->createRenderSurface();
ASSERT(rootDrawLayer->renderSurface());
- // If the size of the visible area has changed then allocate a new texture
- // to store the contents of the root layer and adjust the projection matrix
- // and viewport.
-
- rootDrawLayer->renderSurface()->m_contentRect = IntRect(IntPoint(0, 0), visibleRect.size());
+ rootDrawLayer->renderSurface()->m_contentRect = IntRect(IntPoint(0, 0), m_viewportVisibleRect.size());
- if (visibleRect.size() != m_visibleRect.size()) {
- // Reset the current render surface to force an update of the viewport and
- // projection matrix next time useRenderSurface is called.
- m_currentRenderSurface = 0;
- }
- m_visibleRect = visibleRect;
-
- m_scrollPosition = scrollPosition;
// Scissor out the scrollbars to avoid rendering on top of them.
- IntRect rootScissorRect(contentRect);
+ IntRect rootScissorRect(m_viewportContentRect);
// The scissorRect should not include the scroll offset.
- rootScissorRect.move(-m_scrollPosition.x(), -m_scrollPosition.y());
+ rootScissorRect.move(-m_viewportScrollPosition.x(), -m_viewportScrollPosition.y());
rootDrawLayer->setScissorRect(rootScissorRect);
m_defaultRenderSurface = rootDrawLayer->renderSurface();
@@ -283,16 +307,19 @@ void LayerRendererChromium::updateLayers(const IntRect& visibleRect, const IntRe
// concept of a large content layer.
updatePropertiesAndRenderSurfaces(m_rootLayer.get(), identityMatrix, renderSurfaceLayerList, m_defaultRenderSurface->m_layerList);
- updateContentsRecursive(m_rootLayer.get());
+ paintContentsRecursive(m_rootLayer.get());
+
+ updateCompositorResourcesRecursive(m_rootLayer.get());
}
void LayerRendererChromium::drawLayers(const Vector<CCLayerImpl*>& renderSurfaceLayerList)
{
+ TRACE_EVENT("LayerRendererChromium::drawLayers", this, 0);
CCLayerImpl* rootDrawLayer = m_rootLayer->ccLayerImpl();
makeContextCurrent();
// The GL viewport covers the entire visible area, including the scrollbars.
- GLC(m_context.get(), m_context->viewport(0, 0, m_visibleRect.width(), m_visibleRect.height()));
+ GLC(m_context.get(), m_context->viewport(0, 0, m_viewportVisibleRect.width(), m_viewportVisibleRect.height()));
// Bind the common vertex attributes used for drawing all the layers.
m_sharedGeometry->prepareForDraw();
@@ -363,11 +390,13 @@ void LayerRendererChromium::drawLayers(const Vector<CCLayerImpl*>& renderSurface
void LayerRendererChromium::finish()
{
+ TRACE_EVENT("LayerRendererChromium::finish", this, 0);
m_context->finish();
}
void LayerRendererChromium::present()
{
+ TRACE_EVENT("LayerRendererChromium::present", this, 0);
// We're done! Time to swapbuffers!
// Note that currently this has the same effect as swapBuffers; we should
@@ -382,7 +411,7 @@ void LayerRendererChromium::setRootLayer(PassRefPtr<LayerChromium> layer)
m_rootLayer = layer;
if (m_rootLayer)
m_rootLayer->setLayerRenderer(this);
- m_rootLayerTiler->invalidateEntireLayer();
+ m_rootLayerContentTiler->invalidateEntireLayer();
if (m_horizontalScrollbarTiler)
m_horizontalScrollbarTiler->invalidateEntireLayer();
if (m_verticalScrollbarTiler)
@@ -391,7 +420,7 @@ void LayerRendererChromium::setRootLayer(PassRefPtr<LayerChromium> layer)
void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect)
{
- ASSERT(rect.maxX() <= visibleRectSize().width() && rect.maxY() <= visibleRectSize().height());
+ ASSERT(rect.maxX() <= m_viewportVisibleRect.width() && rect.maxY() <= m_viewportVisibleRect.height());
if (!pixels)
return;
@@ -446,8 +475,29 @@ bool LayerRendererChromium::isLayerVisible(LayerChromium* layer, const Transform
// necessary transformations, scissor rectangles, render surfaces, etc.
void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* layer, const TransformationMatrix& parentMatrix, Vector<CCLayerImpl*>& renderSurfaceLayerList, Vector<CCLayerImpl*>& layerList)
{
+ // Make sure we have CCLayerImpls for this subtree.
+ layer->createCCLayerImplIfNeeded();
layer->setLayerRenderer(this);
+ if (layer->maskLayer()) {
+ layer->maskLayer()->createCCLayerImplIfNeeded();
+ layer->maskLayer()->setLayerRenderer(this);
+ }
+ if (layer->replicaLayer()) {
+ layer->replicaLayer()->createCCLayerImplIfNeeded();
+ layer->replicaLayer()->setLayerRenderer(this);
+ }
+ if (layer->replicaLayer() && layer->replicaLayer()->maskLayer()) {
+ layer->replicaLayer()->maskLayer()->createCCLayerImplIfNeeded();
+ layer->replicaLayer()->maskLayer()->setLayerRenderer(this);
+ }
+
CCLayerImpl* drawLayer = layer->ccLayerImpl();
+ // Currently we're calling pushPropertiesTo() twice - once here and once in updateCompositorResourcesRecursive().
+ // We should only call pushPropertiesTo() in commit, but because we rely on the draw layer state to update
+ // RenderSurfaces and we rely on RenderSurfaces being up to date in order to paint contents we have
+ // to update the draw layers twice.
+ // FIXME: Remove this call once layer updates no longer depend on render surfaces.
+ layer->pushPropertiesTo(drawLayer);
// Compute the new matrix transformation that will be applied to this layer and
// all its sublayers. It's important to remember that the layer's position
@@ -467,9 +517,9 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
// Where: P is the projection matrix
// M is the layer's matrix computed above
// S is the scale adjustment (to scale up to the layer size)
- IntSize bounds = layer->bounds();
- FloatPoint anchorPoint = layer->anchorPoint();
- FloatPoint position = layer->position();
+ IntSize bounds = drawLayer->bounds();
+ FloatPoint anchorPoint = drawLayer->anchorPoint();
+ FloatPoint position = drawLayer->position();
// Offset between anchor point and the center of the quad.
float centerOffsetX = (0.5 - anchorPoint.x()) * bounds.width();
@@ -477,16 +527,16 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
TransformationMatrix layerLocalTransform;
// LT = Tr[l]
- layerLocalTransform.translate3d(position.x(), position.y(), layer->anchorPointZ());
+ layerLocalTransform.translate3d(position.x(), position.y(), drawLayer->anchorPointZ());
// LT = Tr[l] * M[l]
- layerLocalTransform.multiply(layer->transform());
+ layerLocalTransform.multiply(drawLayer->transform());
// LT = Tr[l] * M[l] * Tr[c]
- layerLocalTransform.translate3d(centerOffsetX, centerOffsetY, -layer->anchorPointZ());
+ layerLocalTransform.translate3d(centerOffsetX, centerOffsetY, -drawLayer->anchorPointZ());
TransformationMatrix combinedTransform = parentMatrix;
combinedTransform = combinedTransform.multiply(layerLocalTransform);
- FloatRect layerRect(-0.5 * layer->bounds().width(), -0.5 * layer->bounds().height(), layer->bounds().width(), layer->bounds().height());
+ FloatRect layerRect(-0.5 * drawLayer->bounds().width(), -0.5 * drawLayer->bounds().height(), drawLayer->bounds().width(), drawLayer->bounds().height());
IntRect transformedLayerRect;
// The layer and its descendants render on a new RenderSurface if any of
@@ -498,12 +548,11 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
// If a layer preserves-3d then we don't create a RenderSurface for it to avoid flattening
// out its children. The opacity value of the children layers is multiplied by the opacity
// of their parent.
- bool useSurfaceForClipping = layer->masksToBounds() && !isScaleOrTranslation(combinedTransform);
- bool useSurfaceForOpacity = layer->opacity() != 1 && !layer->preserves3D();
- bool useSurfaceForMasking = layer->maskDrawLayer();
- bool useSurfaceForReflection = layer->replicaLayer();
- if (((useSurfaceForClipping || useSurfaceForOpacity) && layer->descendantsDrawContent())
- || useSurfaceForMasking || useSurfaceForReflection) {
+ bool useSurfaceForClipping = drawLayer->masksToBounds() && !isScaleOrTranslation(combinedTransform);
+ bool useSurfaceForOpacity = drawLayer->opacity() != 1 && !drawLayer->preserves3D();
+ bool useSurfaceForMasking = drawLayer->maskLayer();
+ bool useSurfaceForReflection = drawLayer->replicaLayer();
+ if (useSurfaceForMasking || useSurfaceForReflection || ((useSurfaceForClipping || useSurfaceForOpacity) && drawLayer->descendantsDrawsContent())) {
RenderSurfaceChromium* renderSurface = drawLayer->renderSurface();
if (!renderSurface)
renderSurface = drawLayer->createRenderSurface();
@@ -516,15 +565,15 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
transformedLayerRect = IntRect(0, 0, bounds.width(), bounds.height());
// Layer's opacity will be applied when drawing the render surface.
- renderSurface->m_drawOpacity = layer->opacity();
- if (layer->superlayer() && layer->superlayer()->preserves3D())
+ renderSurface->m_drawOpacity = drawLayer->opacity();
+ if (drawLayer->superlayer() && drawLayer->superlayer()->preserves3D())
renderSurface->m_drawOpacity *= drawLayer->superlayer()->drawOpacity();
drawLayer->setDrawOpacity(1);
TransformationMatrix layerOriginTransform = combinedTransform;
layerOriginTransform.translate3d(-0.5 * bounds.width(), -0.5 * bounds.height(), 0);
renderSurface->m_originTransform = layerOriginTransform;
- if (layerOriginTransform.isInvertible() && layer->superlayer()) {
+ if (layerOriginTransform.isInvertible() && drawLayer->superlayer()) {
TransformationMatrix parentToLayer = layerOriginTransform.inverse();
drawLayer->setScissorRect(parentToLayer.mapRect(drawLayer->superlayer()->scissorRect()));
@@ -538,17 +587,14 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
renderSurface->m_layerList.clear();
- if (layer->maskDrawLayer()) {
- renderSurface->m_maskLayer = layer->maskDrawLayer();
- layer->maskDrawLayer()->setLayerRenderer(this);
- layer->maskDrawLayer()->setTargetRenderSurface(renderSurface);
+ if (drawLayer->maskLayer()) {
+ renderSurface->m_maskLayer = drawLayer->maskLayer();
+ drawLayer->maskLayer()->setTargetRenderSurface(renderSurface);
} else
renderSurface->m_maskLayer = 0;
- if (layer->replicaLayer() && layer->replicaLayer()->maskDrawLayer()) {
- layer->replicaLayer()->maskDrawLayer()->setLayerRenderer(this);
- layer->replicaLayer()->maskDrawLayer()->setTargetRenderSurface(renderSurface);
- }
+ if (drawLayer->replicaLayer() && drawLayer->replicaLayer()->maskLayer())
+ drawLayer->replicaLayer()->maskLayer()->setTargetRenderSurface(renderSurface);
renderSurfaceLayerList.append(drawLayer);
} else {
@@ -556,10 +602,10 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
drawLayer->setDrawTransform(combinedTransform);
transformedLayerRect = enclosingIntRect(drawLayer->drawTransform().mapRect(layerRect));
- drawLayer->setDrawOpacity(layer->opacity());
+ drawLayer->setDrawOpacity(drawLayer->opacity());
- if (layer->superlayer()) {
- if (layer->superlayer()->preserves3D())
+ if (drawLayer->superlayer()) {
+ if (drawLayer->superlayer()->preserves3D())
drawLayer->setDrawOpacity(drawLayer->drawOpacity() * drawLayer->superlayer()->drawOpacity());
// Layers inherit the scissor rect from their superlayer.
@@ -571,7 +617,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
if (layer != m_rootLayer)
drawLayer->clearRenderSurface();
- if (layer->masksToBounds()) {
+ if (drawLayer->masksToBounds()) {
IntRect scissor = drawLayer->scissorRect();
scissor.intersect(transformedLayerRect);
drawLayer->setScissorRect(scissor);
@@ -581,7 +627,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
if (drawLayer->renderSurface())
drawLayer->setTargetRenderSurface(drawLayer->renderSurface());
else {
- ASSERT(layer->superlayer());
+ ASSERT(drawLayer->superlayer());
drawLayer->setTargetRenderSurface(drawLayer->superlayer()->targetRenderSurface());
}
@@ -595,7 +641,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
TransformationMatrix sublayerMatrix = drawLayer->drawTransform();
// Flatten to 2D if the layer doesn't preserve 3D.
- if (!layer->preserves3D()) {
+ if (!drawLayer->preserves3D()) {
sublayerMatrix.setM13(0);
sublayerMatrix.setM23(0);
sublayerMatrix.setM31(0);
@@ -606,7 +652,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
}
// Apply the sublayer transform at the center of the layer.
- sublayerMatrix.multiply(layer->sublayerTransform());
+ sublayerMatrix.multiply(drawLayer->sublayerTransform());
// The origin of the sublayers is the top left corner of the layer, not the
// center. The matrix passed down to the sublayers is therefore:
@@ -619,6 +665,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers();
for (size_t i = 0; i < sublayers.size(); ++i) {
+ sublayers[i]->createCCLayerImplIfNeeded();
CCLayerImpl* sublayer = sublayers[i]->ccLayerImpl();
updatePropertiesAndRenderSurfaces(sublayers[i].get(), sublayerMatrix, renderSurfaceLayerList, descendants);
@@ -635,7 +682,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
}
}
- if (layer->masksToBounds() || useSurfaceForMasking) {
+ if (drawLayer->masksToBounds() || useSurfaceForMasking) {
IntRect drawableContentRect = drawLayer->drawableContentRect();
drawableContentRect.intersect(transformedLayerRect);
drawLayer->setDrawableContentRect(drawableContentRect);
@@ -651,7 +698,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
// Don't clip if the layer is reflected as the reflection shouldn't be
// clipped.
- if (!layer->replicaLayer()) {
+ if (!drawLayer->replicaLayer()) {
renderSurface->m_contentRect.intersect(drawLayer->scissorRect());
FloatPoint clippedSurfaceCenter = renderSurface->contentRectCenter();
centerOffsetDueToClipping = clippedSurfaceCenter - surfaceCenter;
@@ -675,10 +722,10 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
// Compute the transformation matrix used to draw the replica of the render
// surface.
- if (layer->replicaLayer()) {
+ if (drawLayer->replicaLayer()) {
renderSurface->m_replicaDrawTransform = renderSurface->m_originTransform;
- renderSurface->m_replicaDrawTransform.translate3d(layer->replicaLayer()->position().x(), layer->replicaLayer()->position().y(), 0);
- renderSurface->m_replicaDrawTransform.multiply(layer->replicaLayer()->transform());
+ renderSurface->m_replicaDrawTransform.translate3d(drawLayer->replicaLayer()->position().x(), drawLayer->replicaLayer()->position().y(), 0);
+ renderSurface->m_replicaDrawTransform.multiply(drawLayer->replicaLayer()->transform());
renderSurface->m_replicaDrawTransform.translate3d(surfaceCenter.x() - anchorPoint.x() * bounds.width(), surfaceCenter.y() - anchorPoint.y() * bounds.height(), 0);
}
}
@@ -686,8 +733,8 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
// Compute the depth value of the center of the layer which will be used when
// sorting the layers for the preserves-3d property.
const TransformationMatrix& layerDrawMatrix = drawLayer->renderSurface() ? drawLayer->renderSurface()->m_drawTransform : drawLayer->drawTransform();
- if (layer->superlayer()) {
- if (!layer->superlayer()->preserves3D())
+ if (drawLayer->superlayer()) {
+ if (!drawLayer->superlayer()->preserves3D())
drawLayer->setDrawDepth(drawLayer->superlayer()->drawDepth());
else
drawLayer->setDrawDepth(layerDrawMatrix.m43());
@@ -697,24 +744,50 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
// If preserves-3d then sort all the descendants by the Z coordinate of their
// center. If the preserves-3d property is also set on the superlayer then
// skip the sorting as the superlayer will sort all the descendants anyway.
- if (layer->preserves3D() && (!layer->superlayer() || !layer->superlayer()->preserves3D()))
+ if (drawLayer->preserves3D() && (!drawLayer->superlayer() || !drawLayer->superlayer()->preserves3D()))
std::stable_sort(&descendants.at(thisLayerIndex), descendants.end(), compareLayerZ);
}
-void LayerRendererChromium::updateContentsRecursive(LayerChromium* layer)
+void LayerRendererChromium::paintContentsRecursive(LayerChromium* layer)
{
const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers();
for (size_t i = 0; i < sublayers.size(); ++i)
- updateContentsRecursive(sublayers[i].get());
+ paintContentsRecursive(sublayers[i].get());
+
+ if (layer->bounds().isEmpty())
+ return;
if (layer->drawsContent())
- layer->updateContentsIfDirty();
+ layer->paintContentsIfDirty();
if (layer->maskLayer() && layer->maskLayer()->drawsContent())
- layer->maskLayer()->updateContentsIfDirty();
+ layer->maskLayer()->paintContentsIfDirty();
if (layer->replicaLayer() && layer->replicaLayer()->drawsContent())
- layer->replicaLayer()->updateContentsIfDirty();
+ layer->replicaLayer()->paintContentsIfDirty();
if (layer->replicaLayer() && layer->replicaLayer()->maskLayer() && layer->replicaLayer()->maskLayer()->drawsContent())
- layer->replicaLayer()->maskLayer()->updateContentsIfDirty();
+ layer->replicaLayer()->maskLayer()->paintContentsIfDirty();
+}
+
+void LayerRendererChromium::updateCompositorResourcesRecursive(LayerChromium* layer)
+{
+ const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers();
+ for (size_t i = 0; i < sublayers.size(); ++i)
+ updateCompositorResourcesRecursive(sublayers[i].get());
+
+ if (layer->bounds().isEmpty())
+ return;
+
+ CCLayerImpl* drawLayer = layer->ccLayerImpl();
+
+ if (drawLayer->drawsContent())
+ drawLayer->updateCompositorResources();
+ if (drawLayer->maskLayer() && drawLayer->maskLayer()->drawsContent())
+ drawLayer->maskLayer()->updateCompositorResources();
+ if (drawLayer->replicaLayer() && drawLayer->replicaLayer()->drawsContent())
+ drawLayer->replicaLayer()->updateCompositorResources();
+ if (drawLayer->replicaLayer() && drawLayer->replicaLayer()->maskLayer() && drawLayer->replicaLayer()->maskLayer()->drawsContent())
+ drawLayer->replicaLayer()->maskLayer()->updateCompositorResources();
+
+ layer->pushPropertiesTo(drawLayer);
}
void LayerRendererChromium::setCompositeOffscreen(bool compositeOffscreen)
@@ -788,22 +861,38 @@ void LayerRendererChromium::drawLayer(CCLayerImpl* layer, RenderSurfaceChromium*
return;
}
- if (layer->bounds().isEmpty())
+ if (layer->bounds().isEmpty()) {
+ layer->unreserveContentsTexture();
return;
+ }
setScissorToRect(layer->scissorRect());
// Check if the layer falls within the visible bounds of the page.
IntRect layerRect = layer->getDrawRect();
bool isLayerVisible = layer->scissorRect().intersects(layerRect);
- if (!isLayerVisible)
+ if (!isLayerVisible) {
+ layer->unreserveContentsTexture();
return;
+ }
// FIXME: Need to take into account the commulative render surface transforms all the way from
// the default render surface in order to determine visibility.
- TransformationMatrix combinedDrawMatrix = (layer->renderSurface() ? layer->renderSurface()->drawTransform().multiply(layer->drawTransform()) : layer->drawTransform());
- if (!layer->doubleSided() && combinedDrawMatrix.m33() < 0)
- return;
+ TransformationMatrix combinedDrawMatrix = (layer->targetRenderSurface() ? layer->targetRenderSurface()->drawTransform().multiply(layer->drawTransform()) : layer->drawTransform());
+
+ if (!layer->doubleSided()) {
+ FloatRect layerRect(FloatPoint(0, 0), FloatSize(layer->bounds()));
+ FloatQuad mappedLayer = combinedDrawMatrix.mapQuad(FloatQuad(layerRect));
+ FloatSize horizontalDir = mappedLayer.p2() - mappedLayer.p1();
+ FloatSize verticalDir = mappedLayer.p4() - mappedLayer.p1();
+ FloatPoint3D xAxis(horizontalDir.width(), horizontalDir.height(), 0);
+ FloatPoint3D yAxis(verticalDir.width(), verticalDir.height(), 0);
+ FloatPoint3D zAxis = xAxis.cross(yAxis);
+ if (zAxis.z() < 0) {
+ layer->unreserveContentsTexture();
+ return;
+ }
+ }
if (layer->drawsContent())
layer->draw();
@@ -880,10 +969,10 @@ bool LayerRendererChromium::initializeSharedObjects()
m_sharedGeometry = adoptPtr(new GeometryBinding(m_context.get()));
m_borderProgram = adoptPtr(new LayerChromium::BorderProgram(m_context.get()));
m_contentLayerProgram = adoptPtr(new ContentLayerChromium::Program(m_context.get()));
- m_canvasLayerProgram = adoptPtr(new CanvasLayerChromium::Program(m_context.get()));
- m_videoLayerRGBAProgram = adoptPtr(new VideoLayerChromium::RGBAProgram(m_context.get()));
- m_videoLayerYUVProgram = adoptPtr(new VideoLayerChromium::YUVProgram(m_context.get()));
- m_pluginLayerProgram = adoptPtr(new PluginLayerChromium::Program(m_context.get()));
+ m_canvasLayerProgram = adoptPtr(new CCCanvasLayerImpl::Program(m_context.get()));
+ m_videoLayerRGBAProgram = adoptPtr(new CCVideoLayerImpl::RGBAProgram(m_context.get()));
+ m_videoLayerYUVProgram = adoptPtr(new CCVideoLayerImpl::YUVProgram(m_context.get()));
+ m_pluginLayerProgram = adoptPtr(new CCPluginLayerImpl::Program(m_context.get()));
m_renderSurfaceProgram = adoptPtr(new RenderSurfaceChromium::Program(m_context.get()));
m_renderSurfaceMaskProgram = adoptPtr(new RenderSurfaceChromium::MaskProgram(m_context.get()));
m_tilerProgram = adoptPtr(new LayerTilerChromium::Program(m_context.get()));
@@ -920,7 +1009,7 @@ void LayerRendererChromium::cleanupSharedObjects()
GLC(m_context.get(), m_context->deleteFramebuffer(m_offscreenFramebufferId));
// Clear tilers before the texture manager, as they have references to textures.
- m_rootLayerTiler.clear();
+ m_rootLayerContentTiler.clear();
m_horizontalScrollbarTiler.clear();
m_verticalScrollbarTiler.clear();
diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h
index 7e8850a..667ede2 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h
@@ -34,16 +34,17 @@
#if USE(ACCELERATED_COMPOSITING)
-#include "CanvasLayerChromium.h"
#include "ContentLayerChromium.h"
#include "IntRect.h"
#include "LayerChromium.h"
#include "LayerTilerChromium.h"
-#include "PluginLayerChromium.h"
#include "RenderSurfaceChromium.h"
#include "SkBitmap.h"
#include "VideoLayerChromium.h"
+#include "cc/CCCanvasLayerImpl.h"
#include "cc/CCHeadsUpDisplay.h"
+#include "cc/CCPluginLayerImpl.h"
+#include "cc/CCVideoLayerImpl.h"
#include <wtf/HashMap.h>
#include <wtf/Noncopyable.h>
#include <wtf/PassOwnPtr.h>
@@ -66,17 +67,18 @@ class CCHeadsUpDisplay;
// Class that handles drawing of composited render layers using GL.
class LayerRendererChromium : public RefCounted<LayerRendererChromium> {
public:
- static PassRefPtr<LayerRendererChromium> create(PassRefPtr<GraphicsContext3D> graphicsContext3D);
+ static PassRefPtr<LayerRendererChromium> create(PassRefPtr<GraphicsContext3D>, PassOwnPtr<TilePaintInterface> contentPaint, PassOwnPtr<TilePaintInterface> scrollbarPaint);
~LayerRendererChromium();
GraphicsContext3D* context();
- void invalidateRootLayerRect(const IntRect& dirtyRect, const IntRect& visibleRect, const IntRect& contentRect);
+ void invalidateRootLayerRect(const IntRect& dirtyRect);
+
+ void setViewport(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition);
// updates and draws the current layers onto the backbuffer
- void updateAndDrawLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition,
- TilePaintInterface&, TilePaintInterface& scrollbarPaint);
+ void updateAndDrawLayers();
// waits for rendering to finish
void finish();
@@ -84,7 +86,7 @@ public:
// puts backbuffer onscreen
void present();
- IntSize visibleRectSize() const { return m_visibleRect.size(); }
+ IntSize viewportSize() const { return m_viewportVisibleRect.size(); }
void setRootLayer(PassRefPtr<LayerChromium> layer);
LayerChromium* rootLayer() { return m_rootLayer.get(); }
@@ -94,8 +96,6 @@ public:
void setCompositeOffscreen(bool);
bool isCompositingOffscreen() const { return m_compositeOffscreen; }
- LayerTexture* getOffscreenLayerTexture();
- void copyOffscreenTextureToDisplay();
unsigned createLayerTexture();
void deleteLayerTexture(unsigned);
@@ -111,13 +111,13 @@ public:
const GeometryBinding* sharedGeometry() const { return m_sharedGeometry.get(); }
const LayerChromium::BorderProgram* borderProgram() const { return m_borderProgram.get(); }
const ContentLayerChromium::Program* contentLayerProgram() const { return m_contentLayerProgram.get(); }
- const CanvasLayerChromium::Program* canvasLayerProgram() const { return m_canvasLayerProgram.get(); }
- const VideoLayerChromium::RGBAProgram* videoLayerRGBAProgram() const { return m_videoLayerRGBAProgram.get(); }
- const VideoLayerChromium::YUVProgram* videoLayerYUVProgram() const { return m_videoLayerYUVProgram.get(); }
- const PluginLayerChromium::Program* pluginLayerProgram() const { return m_pluginLayerProgram.get(); }
const RenderSurfaceChromium::Program* renderSurfaceProgram() const { return m_renderSurfaceProgram.get(); }
const RenderSurfaceChromium::MaskProgram* renderSurfaceMaskProgram() const { return m_renderSurfaceMaskProgram.get(); }
const LayerTilerChromium::Program* tilerProgram() const { return m_tilerProgram.get(); }
+ const CCCanvasLayerImpl::Program* canvasLayerProgram() const { return m_canvasLayerProgram.get(); }
+ const CCPluginLayerImpl::Program* pluginLayerProgram() const { return m_pluginLayerProgram.get(); }
+ const CCVideoLayerImpl::RGBAProgram* videoLayerRGBAProgram() const { return m_videoLayerRGBAProgram.get(); }
+ const CCVideoLayerImpl::YUVProgram* videoLayerYUVProgram() const { return m_videoLayerYUVProgram.get(); }
void resizeOnscreenContent(const IntSize&);
@@ -132,19 +132,21 @@ public:
String layerTreeAsText() const;
private:
- explicit LayerRendererChromium(PassRefPtr<GraphicsContext3D> graphicsContext3D);
+ explicit LayerRendererChromium(PassRefPtr<GraphicsContext3D>, PassOwnPtr<TilePaintInterface> contentPaint, PassOwnPtr<TilePaintInterface> scrollbarPaint);
- void updateLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition,
- Vector<CCLayerImpl*>& renderSurfaceLayerList);
- void updateRootLayerContents(TilePaintInterface&, const IntRect& visibleRect);
- void updateRootLayerScrollbars(TilePaintInterface& scrollbarPaint, const IntRect& visibleRect, const IntRect& contentRect);
+ void updateLayers(Vector<CCLayerImpl*>& renderSurfaceLayerList);
+ void updateRootLayerContents();
+ void updateRootLayerScrollbars();
void updatePropertiesAndRenderSurfaces(LayerChromium*, const TransformationMatrix& parentMatrix, Vector<CCLayerImpl*>& renderSurfaceLayerList, Vector<CCLayerImpl*>& layerList);
- void updateContentsRecursive(LayerChromium*);
+ void paintContentsRecursive(LayerChromium*);
+ void updateCompositorResourcesRecursive(LayerChromium*);
void drawLayers(const Vector<CCLayerImpl*>& renderSurfaceLayerList);
void drawLayer(CCLayerImpl*, RenderSurfaceChromium*);
void drawRootLayer();
+ LayerTexture* getOffscreenLayerTexture();
+ void copyOffscreenTextureToDisplay();
bool isLayerVisible(LayerChromium*, const TransformationMatrix&, const IntRect& visibleRect);
@@ -161,19 +163,22 @@ private:
bool initializeSharedObjects();
void cleanupSharedObjects();
- static IntRect verticalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect);
- static IntRect horizontalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect);
+ IntRect verticalScrollbarRect() const;
+ IntRect horizontalScrollbarRect() const;
- IntRect m_visibleRect;
+ IntRect m_viewportVisibleRect;
+ IntRect m_viewportContentRect;
+ IntPoint m_viewportScrollPosition;
TransformationMatrix m_projectionMatrix;
RefPtr<LayerChromium> m_rootLayer;
- OwnPtr<LayerTilerChromium> m_rootLayerTiler;
+ OwnPtr<TilePaintInterface> m_rootLayerContentPaint;
+ OwnPtr<TilePaintInterface> m_rootLayerScrollbarPaint;
+ OwnPtr<LayerTilerChromium> m_rootLayerContentTiler;
OwnPtr<LayerTilerChromium> m_horizontalScrollbarTiler;
OwnPtr<LayerTilerChromium> m_verticalScrollbarTiler;
- IntPoint m_scrollPosition;
bool m_hardwareCompositing;
unsigned m_currentShader;
@@ -202,13 +207,13 @@ private:
OwnPtr<GeometryBinding> m_sharedGeometry;
OwnPtr<LayerChromium::BorderProgram> m_borderProgram;
OwnPtr<ContentLayerChromium::Program> m_contentLayerProgram;
- OwnPtr<CanvasLayerChromium::Program> m_canvasLayerProgram;
- OwnPtr<VideoLayerChromium::RGBAProgram> m_videoLayerRGBAProgram;
- OwnPtr<VideoLayerChromium::YUVProgram> m_videoLayerYUVProgram;
- OwnPtr<PluginLayerChromium::Program> m_pluginLayerProgram;
OwnPtr<RenderSurfaceChromium::Program> m_renderSurfaceProgram;
OwnPtr<RenderSurfaceChromium::MaskProgram> m_renderSurfaceMaskProgram;
OwnPtr<LayerTilerChromium::Program> m_tilerProgram;
+ OwnPtr<CCCanvasLayerImpl::Program> m_canvasLayerProgram;
+ OwnPtr<CCVideoLayerImpl::RGBAProgram> m_videoLayerRGBAProgram;
+ OwnPtr<CCVideoLayerImpl::YUVProgram> m_videoLayerYUVProgram;
+ OwnPtr<CCPluginLayerImpl::Program> m_pluginLayerProgram;
OwnPtr<TextureManager> m_textureManager;
diff --git a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp
index 86592a6..bc37201 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp
@@ -34,6 +34,7 @@
#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h"
#include "LayerTexture.h"
+#include "TraceEvent.h"
#include <wtf/PassOwnArrayPtr.h>
@@ -84,58 +85,50 @@ void LayerTilerChromium::reset()
{
m_tiles.clear();
m_unusedTiles.clear();
-
m_tilingData.setTotalSize(0, 0);
- m_lastUpdateLayerRect = IntRect();
}
LayerTilerChromium::Tile* LayerTilerChromium::createTile(int i, int j)
{
- const int index = tileIndex(i, j);
- ASSERT(!m_tiles[index]);
+ ASSERT(!tileAt(i, j));
+ RefPtr<Tile> tile;
if (m_unusedTiles.size() > 0) {
- m_tiles[index] = m_unusedTiles.last().release();
+ tile = m_unusedTiles.last().release();
m_unusedTiles.removeLast();
+ ASSERT(tile->refCount() == 1);
} else {
GraphicsContext3D* context = layerRendererContext();
TextureManager* manager = layerRenderer()->textureManager();
- OwnPtr<Tile> tile = adoptPtr(new Tile(LayerTexture::create(context, manager)));
- m_tiles[index] = tile.release();
+ tile = adoptRef(new Tile(LayerTexture::create(context, manager)));
}
+ m_tiles.add(make_pair(i, j), tile);
+
+ tile->moveTo(i, j);
+ tile->m_dirtyLayerRect = tileLayerRect(tile.get());
- m_tiles[index]->m_dirtyLayerRect = tileLayerRect(i, j);
- return m_tiles[index].get();
+ return tile.get();
}
-void LayerTilerChromium::invalidateTiles(const IntRect& oldLayerRect, const IntRect& newLayerRect)
+void LayerTilerChromium::invalidateTiles(const IntRect& contentRect)
{
if (!m_tiles.size())
return;
- IntRect oldContentRect = layerRectToContentRect(oldLayerRect);
- int oldLeft, oldTop, oldRight, oldBottom;
- contentRectToTileIndices(oldContentRect, oldLeft, oldTop, oldRight, oldBottom);
-
- IntRect newContentRect = layerRectToContentRect(newLayerRect);
- int newLeft, newTop, newRight, newBottom;
- contentRectToTileIndices(newContentRect, newLeft, newTop, newRight, newBottom);
-
- // Iterating through just the old tile indices is an optimization to avoid
- // iterating through the entire m_tiles array.
- for (int j = oldTop; j <= oldBottom; ++j) {
- for (int i = oldLeft; i <= oldRight; ++i) {
- if (i >= newLeft && i <= newRight && j >= newTop && j <= newBottom)
- continue;
-
- const int index = tileIndex(i, j);
- if (m_tiles[index])
- m_unusedTiles.append(m_tiles[index].release());
- }
+ Vector<TileMapKey> removeKeys;
+ for (TileMap::iterator iter = m_tiles.begin(); iter != m_tiles.end(); ++iter) {
+ Tile* tile = iter->second.get();
+ IntRect tileRect = tileContentRect(tile);
+ if (tileRect.intersects(contentRect))
+ continue;
+ removeKeys.append(iter->first);
}
+
+ for (size_t i = 0; i < removeKeys.size(); ++i)
+ m_unusedTiles.append(m_tiles.take(removeKeys[i]));
}
-void LayerTilerChromium::contentRectToTileIndices(const IntRect& contentRect, int &left, int &top, int &right, int &bottom) const
+void LayerTilerChromium::contentRectToTileIndices(const IntRect& contentRect, int& left, int& top, int& right, int& bottom) const
{
const IntRect layerRect = contentRectToLayerRect(contentRect);
@@ -163,36 +156,28 @@ IntRect LayerTilerChromium::layerRectToContentRect(const IntRect& layerRect) con
return contentRect;
}
-int LayerTilerChromium::tileIndex(int i, int j) const
+LayerTilerChromium::Tile* LayerTilerChromium::tileAt(int i, int j) const
{
- return m_tilingData.tileIndex(i, j);
+ Tile* tile = m_tiles.get(make_pair(i, j)).get();
+ ASSERT(!tile || tile->refCount() == 1);
+ return tile;
}
-IntRect LayerTilerChromium::tileContentRect(int i, int j) const
+IntRect LayerTilerChromium::tileContentRect(const Tile* tile) const
{
- IntRect contentRect = tileLayerRect(i, j);
+ IntRect contentRect = tileLayerRect(tile);
contentRect.move(m_layerPosition.x(), m_layerPosition.y());
return contentRect;
}
-IntRect LayerTilerChromium::tileLayerRect(int i, int j) const
+IntRect LayerTilerChromium::tileLayerRect(const Tile* tile) const
{
- const int index = m_tilingData.tileIndex(i, j);
+ const int index = m_tilingData.tileIndex(tile->i(), tile->j());
IntRect layerRect = m_tilingData.tileBoundsWithBorder(index);
layerRect.setSize(m_tileSize);
return layerRect;
}
-IntSize LayerTilerChromium::layerSize() const
-{
- return IntSize(m_tilingData.totalSizeX(), m_tilingData.totalSizeY());
-}
-
-IntSize LayerTilerChromium::layerTileSize() const
-{
- return IntSize(m_tilingData.numTilesX(), m_tilingData.numTilesY());
-}
-
void LayerTilerChromium::invalidateRect(const IntRect& contentRect)
{
if (contentRect.isEmpty())
@@ -202,16 +187,16 @@ void LayerTilerChromium::invalidateRect(const IntRect& contentRect)
// Dirty rects are always in layer space, as the layer could be repositioned
// after invalidation.
- IntRect layerRect = contentRectToLayerRect(contentRect);
+ const IntRect layerRect = contentRectToLayerRect(contentRect);
int left, top, right, bottom;
contentRectToTileIndices(contentRect, left, top, right, bottom);
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
- Tile* tile = m_tiles[tileIndex(i, j)].get();
+ Tile* tile = tileAt(i, j);
if (!tile)
continue;
- IntRect bound = tileLayerRect(i, j);
+ IntRect bound = tileLayerRect(tile);
bound.intersect(layerRect);
tile->m_dirtyLayerRect.unite(bound);
}
@@ -220,14 +205,13 @@ void LayerTilerChromium::invalidateRect(const IntRect& contentRect)
void LayerTilerChromium::invalidateEntireLayer()
{
- for (size_t i = 0; i < m_tiles.size(); ++i) {
- if (m_tiles[i])
- m_unusedTiles.append(m_tiles[i].release());
+ for (TileMap::iterator iter = m_tiles.begin(); iter != m_tiles.end(); ++iter) {
+ ASSERT(iter->second->refCount() == 1);
+ m_unusedTiles.append(iter->second.release());
}
m_tiles.clear();
m_tilingData.setTotalSize(0, 0);
- m_lastUpdateLayerRect = IntRect();
}
void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& contentRect)
@@ -237,10 +221,7 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont
// Invalidate old tiles that were previously used but aren't in use this
// frame so that they can get reused for new tiles.
- IntRect layerRect = contentRectToLayerRect(contentRect);
- invalidateTiles(m_lastUpdateLayerRect, layerRect);
- m_lastUpdateLayerRect = layerRect;
-
+ invalidateTiles(contentRect);
growLayerToContain(contentRect);
// Create tiles as needed, expanding a dirty rect to contain all
@@ -250,11 +231,11 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont
contentRectToTileIndices(contentRect, left, top, right, bottom);
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
- Tile* tile = m_tiles[tileIndex(i, j)].get();
+ Tile* tile = tileAt(i, j);
if (!tile)
tile = createTile(i, j);
if (!tile->texture()->isValid(m_tileSize, GraphicsContext3D::RGBA))
- tile->m_dirtyLayerRect = tileLayerRect(i, j);
+ tile->m_dirtyLayerRect = tileLayerRect(tile);
dirtyLayerRect.unite(tile->m_dirtyLayerRect);
}
}
@@ -267,10 +248,16 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont
m_canvas.resize(paintRect.size());
PlatformCanvas::Painter canvasPainter(&m_canvas);
canvasPainter.context()->translate(-paintRect.x(), -paintRect.y());
- painter.paint(*canvasPainter.context(), paintRect);
+ {
+ TRACE_EVENT("LayerTilerChromium::update::paint", this, 0);
+ painter.paint(*canvasPainter.context(), paintRect);
+ }
PlatformCanvas::AutoLocker locker(&m_canvas);
- updateFromPixels(paintRect, locker.pixels());
+ {
+ TRACE_EVENT("LayerTilerChromium::updateFromPixels", this, 0);
+ updateFromPixels(paintRect, locker.pixels());
+ }
}
void LayerTilerChromium::updateFromPixels(const IntRect& paintRect, const uint8_t* paintPixels)
@@ -285,14 +272,14 @@ void LayerTilerChromium::updateFromPixels(const IntRect& paintRect, const uint8_
contentRectToTileIndices(paintRect, left, top, right, bottom);
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
- Tile* tile = m_tiles[tileIndex(i, j)].get();
+ Tile* tile = tileAt(i, j);
if (!tile)
CRASH();
if (!tile->dirty())
continue;
// Calculate page-space rectangle to copy from.
- IntRect sourceRect = tileContentRect(i, j);
+ IntRect sourceRect = tileContentRect(tile);
const IntPoint anchor = sourceRect.location();
sourceRect.intersect(layerRectToContentRect(tile->m_dirtyLayerRect));
if (sourceRect.isEmpty())
@@ -366,8 +353,7 @@ void LayerTilerChromium::draw(const IntRect& contentRect)
contentRectToTileIndices(contentRect, left, top, right, bottom);
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
- const int index = tileIndex(i, j);
- Tile* tile = m_tiles[index].get();
+ Tile* tile = tileAt(i, j);
ASSERT(tile);
tile->texture()->bindTexture();
@@ -376,11 +362,11 @@ void LayerTilerChromium::draw(const IntRect& contentRect)
// Don't use tileContentRect here, as that contains the full
// rect with border texels which shouldn't be drawn.
- IntRect tileRect = m_tilingData.tileBounds(index);
+ IntRect tileRect = m_tilingData.tileBounds(m_tilingData.tileIndex(tile->i(), tile->j()));
tileRect.move(m_layerPosition.x(), m_layerPosition.y());
tileMatrix.translate3d(tileRect.x() - contentRect.x() + tileRect.width() / 2.0, tileRect.y() - contentRect.y() + tileRect.height() / 2.0, 0);
- IntPoint texOffset = m_tilingData.textureOffset(i, j);
+ IntPoint texOffset = m_tilingData.textureOffset(tile->i(), tile->j());
float tileWidth = static_cast<float>(m_tileSize.width());
float tileHeight = static_cast<float>(m_tileSize.height());
float texTranslateX = texOffset.x() / tileWidth;
@@ -395,37 +381,15 @@ void LayerTilerChromium::draw(const IntRect& contentRect)
}
}
-void LayerTilerChromium::resizeLayer(const IntSize& size)
-{
- if (layerSize() == size)
- return;
-
- const IntSize oldTileSize = layerTileSize();
- m_tilingData.setTotalSize(size.width(), size.height());
- const IntSize newTileSize = layerTileSize();
-
- if (oldTileSize == newTileSize)
- return;
-
- if (newTileSize.height() && (newTileSize.width() > INT_MAX / newTileSize.height()))
- CRASH();
-
- Vector<OwnPtr<Tile> > newTiles;
- newTiles.resize(newTileSize.width() * newTileSize.height());
- for (int j = 0; j < oldTileSize.height(); ++j)
- for (int i = 0; i < oldTileSize.width(); ++i)
- newTiles[i + j * newTileSize.width()].swap(m_tiles[i + j * oldTileSize.width()]);
- m_tiles.swap(newTiles);
-}
-
void LayerTilerChromium::growLayerToContain(const IntRect& contentRect)
{
// Grow the tile array to contain this content rect.
IntRect layerRect = contentRectToLayerRect(contentRect);
IntSize rectSize = IntSize(layerRect.maxX(), layerRect.maxY());
- IntSize newSize = rectSize.expandedTo(layerSize());
- resizeLayer(newSize);
+ IntSize oldLayerSize(m_tilingData.totalSizeX(), m_tilingData.totalSizeY());
+ IntSize newSize = rectSize.expandedTo(oldLayerSize);
+ m_tilingData.setTotalSize(newSize.width(), newSize.height());
}
void LayerTilerChromium::drawTexturedQuad(GraphicsContext3D* context, const TransformationMatrix& projectionMatrix, const TransformationMatrix& drawMatrix,
diff --git a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h
index bdb35a5..2f356e4 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h
@@ -33,7 +33,9 @@
#include "LayerTexture.h"
#include "PlatformCanvas.h"
#include "TilingData.h"
+#include <wtf/HashTraits.h>
#include <wtf/OwnArrayPtr.h>
+#include <wtf/RefCounted.h>
namespace WebCore {
@@ -70,20 +72,26 @@ public:
private:
LayerTilerChromium(LayerRendererChromium*, const IntSize& tileSize, BorderTexelOption);
- class Tile {
+ class Tile : public RefCounted<Tile> {
WTF_MAKE_NONCOPYABLE(Tile);
public:
- explicit Tile(PassOwnPtr<LayerTexture> tex) : m_tex(tex) {}
+ explicit Tile(PassOwnPtr<LayerTexture> tex) : m_tex(tex), m_i(-1), m_j(-1) {}
LayerTexture* texture() { return m_tex.get(); }
bool dirty() const { return !m_dirtyLayerRect.isEmpty(); }
void clearDirty() { m_dirtyLayerRect = IntRect(); }
+ int i() const { return m_i; }
+ int j() const { return m_j; }
+ void moveTo(int i, int j) { m_i = i; m_j = j; }
+
// Layer-space dirty rectangle that needs to be repainted.
IntRect m_dirtyLayerRect;
private:
OwnPtr<LayerTexture> m_tex;
+ int m_i;
+ int m_j;
};
void drawTexturedQuad(GraphicsContext3D*, const TransformationMatrix& projectionMatrix, const TransformationMatrix& drawMatrix,
@@ -92,40 +100,45 @@ private:
float texScaleX, float texScaleY,
const LayerTilerChromium::Program*);
- void resizeLayer(const IntSize& size);
// Grow layer size to contain this rectangle.
void growLayerToContain(const IntRect& contentRect);
LayerRendererChromium* layerRenderer() const { return m_layerRenderer; }
GraphicsContext3D* layerRendererContext() const;
Tile* createTile(int i, int j);
- // Invalidate any tiles which do not intersect with the newLayerRect.
- void invalidateTiles(const IntRect& oldLayerRect, const IntRect& newLayerRect);
+ // Invalidate any tiles which do not intersect with the contentRect
+ void invalidateTiles(const IntRect& contentRect);
void reset();
void contentRectToTileIndices(const IntRect& contentRect, int &left, int &top, int &right, int &bottom) const;
IntRect contentRectToLayerRect(const IntRect& contentRect) const;
IntRect layerRectToContentRect(const IntRect& layerRect) const;
- // Returns the index into m_tiles for a given tile location.
- int tileIndex(int i, int j) const;
- // Returns the bounds in content space for a given tile location.
- IntRect tileContentRect(int i, int j) const;
- // Returns the bounds in layer space for a given tile location.
- IntRect tileLayerRect(int i, int j) const;
-
- IntSize layerSize() const;
- IntSize layerTileSize() const;
+ Tile* tileAt(int, int) const;
+ IntRect tileContentRect(const Tile*) const;
+ IntRect tileLayerRect(const Tile*) const;
IntSize m_tileSize;
- IntRect m_lastUpdateLayerRect;
IntPoint m_layerPosition;
bool m_skipsDraw;
- // Logical 2D array of tiles (dimensions of m_layerTileSize)
- Vector<OwnPtr<Tile> > m_tiles;
- // Linear array of unused tiles.
- Vector<OwnPtr<Tile> > m_unusedTiles;
+ // Default hash key traits for integers disallow 0 and -1 as a key, so
+ // use a custom hash trait which disallows -1 and -2 instead.
+ typedef std::pair<int, int> TileMapKey;
+ struct TileMapKeyTraits : HashTraits<TileMapKey> {
+ static const bool emptyValueIsZero = false;
+ static const bool needsDestruction = false;
+ static TileMapKey emptyValue() { return std::make_pair(-1, -1); }
+ static void constructDeletedValue(TileMapKey& slot) { slot = std::make_pair(-2, -2); }
+ static bool isDeletedValue(TileMapKey value) { return value.first == -2 && value.second == -2; }
+ };
+ // FIXME: The mapped value in TileMap should really be an OwnPtr, as the
+ // refcount of a Tile should never be more than 1. However, HashMap
+ // doesn't easily support OwnPtr as a value.
+ typedef HashMap<TileMapKey, RefPtr<Tile>, DefaultHash<TileMapKey>::Hash, TileMapKeyTraits> TileMap;
+ TileMap m_tiles;
+ // Tightly packed set of unused tiles.
+ Vector<RefPtr<Tile> > m_unusedTiles;
PlatformCanvas m_canvas;
diff --git a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp
index 5d595ad..3667fbb 100644
--- a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp
@@ -29,10 +29,10 @@
#include "PluginLayerChromium.h"
-#include "cc/CCLayerImpl.h"
#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h"
-#include <GLES2/gl2.h>
+#include "cc/CCLayerImpl.h"
+#include "cc/CCPluginLayerImpl.h"
namespace WebCore {
@@ -43,40 +43,26 @@ PassRefPtr<PluginLayerChromium> PluginLayerChromium::create(GraphicsLayerChromiu
PluginLayerChromium::PluginLayerChromium(GraphicsLayerChromium* owner)
: LayerChromium(owner)
+ , m_textureId(0)
{
}
-void PluginLayerChromium::setTextureId(unsigned id)
+PassRefPtr<CCLayerImpl> PluginLayerChromium::createCCLayerImpl()
{
- m_textureId = id;
+ return CCPluginLayerImpl::create(this);
}
-void PluginLayerChromium::updateContentsIfDirty()
+void PluginLayerChromium::setTextureId(unsigned id)
{
+ m_textureId = id;
}
-void PluginLayerChromium::draw()
+void PluginLayerChromium::pushPropertiesTo(CCLayerImpl* layer)
{
- ASSERT(layerRenderer());
- const PluginLayerChromium::Program* program = layerRenderer()->pluginLayerProgram();
- ASSERT(program && program->initialized());
- GraphicsContext3D* context = layerRendererContext();
- GLC(context, context->activeTexture(GL_TEXTURE0));
- GLC(context, context->bindTexture(GL_TEXTURE_2D, m_textureId));
-
- // FIXME: setting the texture parameters every time is redundant. Move this code somewhere
- // where it will only happen once per texture.
- GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
- GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
- GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
- GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
-
- layerRenderer()->useShader(program->program());
- GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
- drawTexturedQuad(context, layerRenderer()->projectionMatrix(), ccLayerImpl()->drawTransform(),
- bounds().width(), bounds().height(), ccLayerImpl()->drawOpacity(),
- program->vertexShader().matrixLocation(),
- program->fragmentShader().alphaLocation());
+ LayerChromium::pushPropertiesTo(layer);
+
+ CCPluginLayerImpl* pluginLayer = static_cast<CCPluginLayerImpl*>(layer);
+ pluginLayer->setTextureId(m_textureId);
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h
index 8d66f5f..852dc2e 100644
--- a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h
@@ -38,18 +38,19 @@ class PluginLayerChromium : public LayerChromium {
public:
static PassRefPtr<PluginLayerChromium> create(GraphicsLayerChromium* owner = 0);
virtual bool drawsContent() const { return true; }
- virtual void updateContentsIfDirty();
- virtual void draw();
-
+
+ virtual PassRefPtr<CCLayerImpl> createCCLayerImpl();
+
void setTextureId(unsigned textureId);
-
- typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program;
+ unsigned textureId() const { return m_textureId; }
+
+ virtual void pushPropertiesTo(CCLayerImpl*);
protected:
virtual const char* layerTypeAsString() const { return "PluginLayer"; }
private:
- PluginLayerChromium(GraphicsLayerChromium* owner);
+ explicit PluginLayerChromium(GraphicsLayerChromium* owner);
unsigned m_textureId;
};
diff --git a/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp b/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp
index 49b3462..b7f447b 100644
--- a/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp
@@ -248,7 +248,7 @@ FragmentShaderYUVVideo::FragmentShaderYUVVideo()
, m_vTextureLocation(-1)
, m_alphaLocation(-1)
, m_ccMatrixLocation(-1)
- , m_signAdjLocation(-1)
+ , m_yuvAdjLocation(-1)
{
}
@@ -259,10 +259,10 @@ bool FragmentShaderYUVVideo::init(GraphicsContext3D* context, unsigned program)
m_vTextureLocation = context->getUniformLocation(program, "v_texture");
m_alphaLocation = context->getUniformLocation(program, "alpha");
m_ccMatrixLocation = context->getUniformLocation(program, "cc_matrix");
- m_signAdjLocation = context->getUniformLocation(program, "adj");
+ m_yuvAdjLocation = context->getUniformLocation(program, "yuv_adj");
return m_yTextureLocation != -1 && m_uTextureLocation != -1 && m_vTextureLocation != -1
- && m_alphaLocation != -1 && m_ccMatrixLocation != -1 && m_signAdjLocation != -1;
+ && m_alphaLocation != -1 && m_ccMatrixLocation != -1 && m_yuvAdjLocation != -1;
}
String FragmentShaderYUVVideo::getShaderString() const
@@ -276,14 +276,15 @@ String FragmentShaderYUVVideo::getShaderString() const
uniform sampler2D u_texture;
uniform sampler2D v_texture;
uniform float alpha;
- uniform float adj;
+ uniform vec3 yuv_adj;
uniform mat3 cc_matrix;
void main()
{
- float y = texture2D(y_texture, y_texCoord).x;
- float u = texture2D(u_texture, uv_texCoord).x - adj;
- float v = texture2D(v_texture, uv_texCoord).x - adj;
- vec3 rgb = cc_matrix * vec3(y, u, v);
+ float y_raw = texture2D(y_texture, y_texCoord).x;
+ float u_unsigned = texture2D(u_texture, uv_texCoord).x;
+ float v_unsigned = texture2D(v_texture, uv_texCoord).x;
+ vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;
+ vec3 rgb = cc_matrix * yuv;
gl_FragColor = vec4(rgb, float(1)) * alpha;
}
);
diff --git a/Source/WebCore/platform/graphics/chromium/ShaderChromium.h b/Source/WebCore/platform/graphics/chromium/ShaderChromium.h
index 758c62b..3a3e175 100644
--- a/Source/WebCore/platform/graphics/chromium/ShaderChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/ShaderChromium.h
@@ -158,7 +158,7 @@ public:
int vTextureLocation() const { return m_vTextureLocation; }
int alphaLocation() const { return m_alphaLocation; }
int ccMatrixLocation() const { return m_ccMatrixLocation; }
- int signAdjLocation() const { return m_signAdjLocation; }
+ int yuvAdjLocation() const { return m_yuvAdjLocation; }
private:
int m_yTextureLocation;
@@ -166,7 +166,7 @@ private:
int m_vTextureLocation;
int m_alphaLocation;
int m_ccMatrixLocation;
- int m_signAdjLocation;
+ int m_yuvAdjLocation;
};
class FragmentShaderColor {
diff --git a/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp b/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
index 9423d1e..7cd47fe 100644
--- a/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
+++ b/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
@@ -113,13 +113,13 @@ void SimpleFontData::platformInit()
m_fontMetrics.setXHeight(xHeight);
m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));
- if (m_orientation == Vertical) {
+ if (platformData().orientation() == Vertical && !isTextOrientationFallback()) {
static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a');
static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G');
size_t vheaSize = SkFontHost::GetTableSize(fontID, vheaTag);
size_t vorgSize = SkFontHost::GetTableSize(fontID, vorgTag);
- if ((vheaSize <= 0) && (vorgSize <= 0))
- m_orientation = Horizontal;
+ if ((vheaSize > 0) || (vorgSize > 0))
+ m_hasVerticalGlyphs = true;
}
// In WebKit/WebCore/platform/graphics/SimpleFontData.cpp, m_spaceWidth is
diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
index 5d7a6e7..182e730 100644
--- a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
@@ -33,7 +33,6 @@
#if USE(ACCELERATED_COMPOSITING)
#include "VideoLayerChromium.h"
-#include "cc/CCLayerImpl.h"
#include "Extensions3DChromium.h"
#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h"
@@ -41,17 +40,11 @@
#include "RenderLayerBacking.h"
#include "VideoFrameChromium.h"
#include "VideoFrameProvider.h"
+#include "cc/CCLayerImpl.h"
+#include "cc/CCVideoLayerImpl.h"
namespace WebCore {
-// These values are magic numbers that are used in the transformation
-// from YUV to RGB color values.
-const float VideoLayerChromium::yuv2RGB[9] = {
- 1.f, 1.f, 1.f,
- 0.f, -.344f, 1.772f,
- 1.403f, -.714f, 0.f,
-};
-
PassRefPtr<VideoLayerChromium> VideoLayerChromium::create(GraphicsLayerChromium* owner,
VideoFrameProvider* provider)
{
@@ -71,23 +64,37 @@ VideoLayerChromium::VideoLayerChromium(GraphicsLayerChromium* owner, VideoFrameP
VideoLayerChromium::~VideoLayerChromium()
{
cleanupResources();
+ deleteTexturesInUse();
}
-void VideoLayerChromium::cleanupResources()
+PassRefPtr<CCLayerImpl> VideoLayerChromium::createCCLayerImpl()
+{
+ return CCVideoLayerImpl::create(this);
+}
+
+void VideoLayerChromium::deleteTexturesInUse()
{
- LayerChromium::cleanupResources();
- releaseCurrentFrame();
if (!layerRenderer())
return;
GraphicsContext3D* context = layerRendererContext();
for (unsigned plane = 0; plane < VideoFrameChromium::maxPlanes; plane++) {
- if (m_textures[plane])
- GLC(context, context->deleteTexture(m_textures[plane]));
+ Texture texture = m_textures[plane];
+ if (!texture.isEmpty && texture.ownedByLayerRenderer)
+ GLC(context, context->deleteTexture(texture.id));
}
}
-void VideoLayerChromium::updateContentsIfDirty()
+void VideoLayerChromium::cleanupResources()
+{
+ LayerChromium::cleanupResources();
+ if (m_currentFrame)
+ releaseCurrentFrame();
+ else
+ resetFrameParameters();
+}
+
+void VideoLayerChromium::updateCompositorResources()
{
if (!m_contentsDirty)
return;
@@ -116,6 +123,9 @@ void VideoLayerChromium::updateContentsIfDirty()
return;
}
+ // If the incoming frame is backed by a texture (i.e. decoded in hardware),
+ // then we do not need to allocate a texture via the layer renderer. Instead
+ // we save the texture data then exit.
if (frame->surfaceType() == VideoFrameChromium::TypeTexture) {
releaseCurrentFrame();
saveCurrentFrame(frame);
@@ -136,8 +146,9 @@ void VideoLayerChromium::updateContentsIfDirty()
// Update texture planes.
for (unsigned plane = 0; plane < frame->planes(); plane++) {
- ASSERT(frame->requiredTextureSize(plane) == m_textureSizes[plane]);
- updateTexture(context, m_textures[plane], frame->requiredTextureSize(plane), textureFormat, frame->data(plane));
+ Texture texture = m_textures[plane];
+ ASSERT(frame->requiredTextureSize(plane) == texture.size);
+ updateTexture(context, texture.id, texture.size, textureFormat, frame->data(plane));
}
m_dirtyRect.setSize(FloatSize());
@@ -146,7 +157,19 @@ void VideoLayerChromium::updateContentsIfDirty()
m_provider->putCurrentFrame(frame);
}
-unsigned VideoLayerChromium::determineTextureFormat(VideoFrameChromium* frame)
+void VideoLayerChromium::pushPropertiesTo(CCLayerImpl* layer)
+{
+ LayerChromium::pushPropertiesTo(layer);
+
+ CCVideoLayerImpl* videoLayer = static_cast<CCVideoLayerImpl*>(layer);
+ videoLayer->setSkipsDraw(m_skipsDraw);
+ videoLayer->setFrameFormat(m_frameFormat);
+ for (size_t i = 0; i < 3; ++i)
+ videoLayer->setTexture(i, m_textures[i]);
+}
+
+
+unsigned VideoLayerChromium::determineTextureFormat(const VideoFrameChromium* frame)
{
switch (frame->format()) {
case VideoFrameChromium::YV12:
@@ -160,56 +183,68 @@ unsigned VideoLayerChromium::determineTextureFormat(VideoFrameChromium* frame)
return GraphicsContext3D::INVALID_VALUE;
}
-bool VideoLayerChromium::allocateTexturesIfNeeded(GraphicsContext3D* context, VideoFrameChromium* frame, unsigned textureFormat)
+bool VideoLayerChromium::allocateTexturesIfNeeded(GraphicsContext3D* context, const VideoFrameChromium* frame, unsigned textureFormat)
{
ASSERT(context);
ASSERT(frame);
for (unsigned plane = 0; plane < frame->planes(); plane++) {
- IntSize planeTextureSize = frame->requiredTextureSize(plane);
+ IntSize requiredTextureSize = frame->requiredTextureSize(plane);
+ Texture texture = m_textures[plane];
// If the renderer cannot handle this large of a texture, return false.
// FIXME: Remove this test when tiled layers are implemented.
- if (!layerRenderer()->checkTextureSize(planeTextureSize))
+ if (!layerRenderer()->checkTextureSize(requiredTextureSize))
return false;
- if (!m_textures[plane])
- m_textures[plane] = layerRenderer()->createLayerTexture();
-
- if (!planeTextureSize.isZero() && planeTextureSize != m_textureSizes[plane]) {
- allocateTexture(context, m_textures[plane], planeTextureSize, textureFormat);
- m_textureSizes[plane] = planeTextureSize;
- int frameWidth = frame->width(plane);
- int frameHeight = frame->height(plane);
- // When there are dead pixels at the edge of the texture, decrease
- // the frame width by 1 to prevent the rightmost pixels from
- // interpolating with the dead pixels.
- if (frame->hasPaddingBytes(plane))
- --frameWidth;
- m_frameSizes[plane] = IntSize(frameWidth, frameHeight);
+ if (texture.isEmpty) {
+ texture.id = layerRenderer()->createLayerTexture();
+ texture.ownedByLayerRenderer = true;
+ texture.isEmpty = false;
+ }
+
+ if (!requiredTextureSize.isZero() && requiredTextureSize != texture.size) {
+ allocateTexture(context, texture.id, requiredTextureSize, textureFormat);
+ texture.size = requiredTextureSize;
+ texture.visibleSize = computeVisibleSize(frame, plane);
}
+ m_textures[plane] = texture;
}
+ return true;
+}
+
+IntSize VideoLayerChromium::computeVisibleSize(const VideoFrameChromium* frame, unsigned plane)
+{
+ int visibleWidth = frame->width(plane);
+ int visibleHeight = frame->height(plane);
+ // When there are dead pixels at the edge of the texture, decrease
+ // the frame width by 1 to prevent the rightmost pixels from
+ // interpolating with the dead pixels.
+ if (frame->hasPaddingBytes(plane))
+ --visibleWidth;
+
// In YV12, every 2x2 square of Y values corresponds to one U and
// one V value. If we decrease the width of the UV plane, we must decrease the
// width of the Y texture by 2 for proper alignment. This must happen
// always, even if Y's texture does not have padding bytes.
- if (frame->format() == VideoFrameChromium::YV12) {
- int yPlaneOriginalWidth = frame->width(VideoFrameChromium::yPlane);
- if (frame->hasPaddingBytes(VideoFrameChromium::uPlane))
- m_frameSizes[VideoFrameChromium::yPlane].setWidth(yPlaneOriginalWidth - 2);
+ if (plane == VideoFrameChromium::yPlane && frame->format() == VideoFrameChromium::YV12) {
+ if (frame->hasPaddingBytes(VideoFrameChromium::uPlane)) {
+ int originalWidth = frame->width(plane);
+ visibleWidth = originalWidth - 2;
+ }
}
- return true;
+ return IntSize(visibleWidth, visibleHeight);
}
-void VideoLayerChromium::allocateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned textureFormat)
+void VideoLayerChromium::allocateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned textureFormat) const
{
GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
GLC(context, context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, textureFormat, dimensions.width(), dimensions.height(), 0, textureFormat, GraphicsContext3D::UNSIGNED_BYTE));
}
-void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned format, const void* data)
+void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned format, const void* data) const
{
ASSERT(context);
GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
@@ -225,33 +260,6 @@ void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned text
}
}
-void VideoLayerChromium::draw()
-{
- if (m_skipsDraw)
- return;
-
- ASSERT(layerRenderer());
- const RGBAProgram* rgbaProgram = layerRenderer()->videoLayerRGBAProgram();
- ASSERT(rgbaProgram && rgbaProgram->initialized());
- const YUVProgram* yuvProgram = layerRenderer()->videoLayerYUVProgram();
- ASSERT(yuvProgram && yuvProgram->initialized());
-
- switch (m_frameFormat) {
- case VideoFrameChromium::YV12:
- case VideoFrameChromium::YV16:
- drawYUV(yuvProgram);
- break;
- case VideoFrameChromium::RGBA:
- drawRGBA(rgbaProgram);
- break;
- default:
- // FIXME: Implement other paths.
- notImplemented();
- break;
- }
- releaseCurrentFrame();
-}
-
void VideoLayerChromium::releaseCurrentFrame()
{
if (!m_currentFrame)
@@ -262,86 +270,29 @@ void VideoLayerChromium::releaseCurrentFrame()
resetFrameParameters();
}
-void VideoLayerChromium::drawYUV(const VideoLayerChromium::YUVProgram* program)
-{
- GraphicsContext3D* context = layerRendererContext();
- GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE1));
- GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::yPlane]));
- GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE2));
- GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::uPlane]));
- GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE3));
- GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::vPlane]));
-
- layerRenderer()->useShader(program->program());
- unsigned yFrameWidth = m_frameSizes[VideoFrameChromium::yPlane].width();
- unsigned yTextureWidth = m_textureSizes[VideoFrameChromium::yPlane].width();
- // Arbitrarily take the u sizes because u and v dimensions are identical.
- unsigned uvFrameWidth = m_frameSizes[VideoFrameChromium::uPlane].width();
- unsigned uvTextureWidth = m_textureSizes[VideoFrameChromium::uPlane].width();
-
- float yWidthScaleFactor = static_cast<float>(yFrameWidth) / yTextureWidth;
- float uvWidthScaleFactor = static_cast<float>(uvFrameWidth) / uvTextureWidth;
- GLC(context, context->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor));
- GLC(context, context->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor));
-
- GLC(context, context->uniform1i(program->fragmentShader().yTextureLocation(), 1));
- GLC(context, context->uniform1i(program->fragmentShader().uTextureLocation(), 2));
- GLC(context, context->uniform1i(program->fragmentShader().vTextureLocation(), 3));
-
- // This value of 0.5 maps to 128. It is used in the YUV to RGB conversion
- // formula to turn unsigned u and v values to signed u and v values.
- // This is loaded as a uniform because certain drivers have problems
- // reading literal float values.
- GLC(context, context->uniform1f(program->fragmentShader().signAdjLocation(), 0.5));
-
- GLC(context, context->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1));
-
- drawTexturedQuad(context, layerRenderer()->projectionMatrix(), ccLayerImpl()->drawTransform(),
- bounds().width(), bounds().height(), ccLayerImpl()->drawOpacity(),
- program->vertexShader().matrixLocation(),
- program->fragmentShader().alphaLocation());
-
- // Reset active texture back to texture 0.
- GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
-}
-
-void VideoLayerChromium::drawRGBA(const VideoLayerChromium::RGBAProgram* program)
-{
- GraphicsContext3D* context = layerRendererContext();
- GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
- GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::rgbPlane]));
-
- layerRenderer()->useShader(program->program());
- unsigned frameWidth = m_frameSizes[VideoFrameChromium::rgbPlane].width();
- unsigned textureWidth = m_textureSizes[VideoFrameChromium::rgbPlane].width();
- float widthScaleFactor = static_cast<float>(frameWidth) / textureWidth;
- GLC(context, context->uniform4f(program->vertexShader().texTransformLocation(), 0, 0, widthScaleFactor, 1));
-
- GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
-
- drawTexturedQuad(context, layerRenderer()->projectionMatrix(), ccLayerImpl()->drawTransform(),
- bounds().width(), bounds().height(), ccLayerImpl()->drawOpacity(),
- program->vertexShader().matrixLocation(),
- program->fragmentShader().alphaLocation());
-}
-
void VideoLayerChromium::resetFrameParameters()
{
+ deleteTexturesInUse();
for (unsigned plane = 0; plane < VideoFrameChromium::maxPlanes; plane++) {
- m_textures[plane] = 0;
- m_textureSizes[plane] = IntSize();
- m_frameSizes[plane] = IntSize();
+ m_textures[plane].id = 0;
+ m_textures[plane].size = IntSize();
+ m_textures[plane].visibleSize = IntSize();
+ m_textures[plane].ownedByLayerRenderer = false;
+ m_textures[plane].isEmpty = true;
}
}
void VideoLayerChromium::saveCurrentFrame(VideoFrameChromium* frame)
{
ASSERT(!m_currentFrame);
+ deleteTexturesInUse();
m_currentFrame = frame;
for (unsigned plane = 0; plane < frame->planes(); plane++) {
- m_textures[plane] = frame->texture(plane);
- m_textureSizes[plane] = frame->requiredTextureSize(plane);
- m_frameSizes[plane] = m_textureSizes[plane];
+ m_textures[plane].id = frame->texture(plane);
+ m_textures[plane].size = frame->requiredTextureSize(plane);
+ m_textures[plane].visibleSize = computeVisibleSize(frame, plane);
+ m_textures[plane].ownedByLayerRenderer = false;
+ m_textures[plane].isEmpty = false;
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h
index 2170e13..ef08bd8 100644
--- a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h
@@ -42,19 +42,28 @@ namespace WebCore {
// A Layer that contains a Video element.
class VideoLayerChromium : public LayerChromium {
public:
+ struct Texture {
+ unsigned id;
+ IntSize size;
+ IntSize visibleSize;
+ bool ownedByLayerRenderer;
+ bool isEmpty;
+ };
+
static PassRefPtr<VideoLayerChromium> create(GraphicsLayerChromium* owner = 0,
VideoFrameProvider* = 0);
virtual ~VideoLayerChromium();
- virtual void updateContentsIfDirty();
+
+ virtual PassRefPtr<CCLayerImpl> createCCLayerImpl();
+
+ virtual void updateCompositorResources();
virtual bool drawsContent() const { return true; }
- virtual void draw();
// This function is called by VideoFrameProvider. When this method is called
// putCurrentFrame() must be called to return the frame currently held.
void releaseCurrentFrame();
- typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexFlipAlpha> RGBAProgram;
- typedef ProgramBinding<VertexShaderPosTexYUVStretch, FragmentShaderYUVVideo> YUVProgram;
+ virtual void pushPropertiesTo(CCLayerImpl*);
protected:
virtual void cleanupResources();
@@ -63,27 +72,27 @@ protected:
private:
VideoLayerChromium(GraphicsLayerChromium* owner, VideoFrameProvider*);
- static unsigned determineTextureFormat(VideoFrameChromium*);
- bool allocateTexturesIfNeeded(GraphicsContext3D*, VideoFrameChromium*, unsigned textureFormat);
- void updateYUVContents(GraphicsContext3D*, const VideoFrameChromium*);
- void updateRGBAContents(GraphicsContext3D*, const VideoFrameChromium*);
- void allocateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat);
- void updateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat, const void* data);
- void drawYUV(const YUVProgram*);
- void drawRGBA(const RGBAProgram*);
+ static unsigned determineTextureFormat(const VideoFrameChromium*);
+ static IntSize computeVisibleSize(const VideoFrameChromium*, unsigned plane);
+ void deleteTexturesInUse();
+
+ bool allocateTexturesIfNeeded(GraphicsContext3D*, const VideoFrameChromium*, unsigned textureFormat);
+ void allocateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat) const;
+
+ void updateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat, const void* data) const;
+
void resetFrameParameters();
void saveCurrentFrame(VideoFrameChromium*);
- static const float yuv2RGB[9];
-
bool m_skipsDraw;
VideoFrameChromium::Format m_frameFormat;
VideoFrameProvider* m_provider;
- VideoFrameChromium* m_currentFrame;
- unsigned m_textures[3];
- IntSize m_textureSizes[3];
- IntSize m_frameSizes[3];
+ Texture m_textures[3];
+
+ // This will be null for the entire duration of video playback if hardware
+ // decoding is not being used.
+ VideoFrameChromium* m_currentFrame;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
index e83d045..652e752 100644
--- a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
@@ -47,10 +47,11 @@ PassRefPtr<WebGLLayerChromium> WebGLLayerChromium::create(GraphicsLayerChromium*
WebGLLayerChromium::WebGLLayerChromium(GraphicsLayerChromium* owner)
: CanvasLayerChromium(owner)
, m_context(0)
+ , m_textureUpdated(false)
{
}
-void WebGLLayerChromium::updateContentsIfDirty()
+void WebGLLayerChromium::updateCompositorResources()
{
if (!m_contentsDirty)
return;
@@ -68,19 +69,28 @@ void WebGLLayerChromium::updateContentsIfDirty()
m_textureChanged = false;
}
// Update the contents of the texture used by the compositor.
- if (m_contentsDirty) {
+ if (m_contentsDirty && m_textureUpdated) {
m_context->prepareTexture();
+ m_context->markLayerComposited();
m_contentsDirty = false;
+ m_textureUpdated = false;
}
}
+void WebGLLayerChromium::setTextureUpdated()
+{
+ m_textureUpdated = true;
+}
+
void WebGLLayerChromium::setContext(const GraphicsContext3D* context)
{
m_context = const_cast<GraphicsContext3D*>(context);
unsigned int textureId = m_context->platformTexture();
- if (textureId != m_textureId)
+ if (textureId != m_textureId) {
m_textureChanged = true;
+ m_textureUpdated = true;
+ }
m_textureId = textureId;
m_premultipliedAlpha = m_context->getContextAttributes().premultipliedAlpha;
}
diff --git a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
index 70be876..33db730 100644
--- a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
@@ -45,7 +45,8 @@ class WebGLLayerChromium : public CanvasLayerChromium {
public:
static PassRefPtr<WebGLLayerChromium> create(GraphicsLayerChromium* owner = 0);
virtual bool drawsContent() const { return m_context; }
- virtual void updateContentsIfDirty();
+ virtual void updateCompositorResources();
+ void setTextureUpdated();
void setContext(const GraphicsContext3D* context);
@@ -55,6 +56,7 @@ protected:
private:
explicit WebGLLayerChromium(GraphicsLayerChromium* owner);
GraphicsContext3D* m_context;
+ bool m_textureUpdated;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp
new file mode 100644
index 0000000..649d049
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "cc/CCCanvasLayerImpl.h"
+
+#include "CanvasLayerChromium.h"
+#include "GraphicsContext3D.h"
+#include "LayerRendererChromium.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+CCCanvasLayerImpl::CCCanvasLayerImpl(LayerChromium* owner)
+ : CCLayerImpl(owner)
+ , m_textureId(0)
+ , m_premultipliedAlpha(true)
+{
+}
+
+CCCanvasLayerImpl::~CCCanvasLayerImpl()
+{
+}
+
+void CCCanvasLayerImpl::draw()
+{
+ ASSERT(layerRenderer());
+ const CCCanvasLayerImpl::Program* program = layerRenderer()->canvasLayerProgram();
+ ASSERT(program && program->initialized());
+ GraphicsContext3D* context = layerRenderer()->context();
+ GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
+ GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId));
+ GC3Denum sfactor = m_premultipliedAlpha ? GraphicsContext3D::ONE : GraphicsContext3D::SRC_ALPHA;
+ GLC(context, context->blendFunc(sfactor, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
+ layerRenderer()->useShader(program->program());
+ GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
+ LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(),
+ bounds().width(), bounds().height(), drawOpacity(),
+ program->vertexShader().matrixLocation(),
+ program->fragmentShader().alphaLocation());
+
+}
+
+
+void CCCanvasLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
+{
+ writeIndent(ts, indent);
+ ts << "canvas layer texture id: " << m_textureId << " premultiplied: " << m_premultipliedAlpha << "\n";
+ CCLayerImpl::dumpLayerProperties(ts, indent);
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h
new file mode 100644
index 0000000..8cbf8d1
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CCCanvasLayerImpl_h
+#define CCCanvasLayerImpl_h
+
+#include "ProgramBinding.h"
+#include "ShaderChromium.h"
+#include "cc/CCLayerImpl.h"
+
+namespace WebCore {
+
+class CCCanvasLayerImpl : public CCLayerImpl {
+public:
+ static PassRefPtr<CCCanvasLayerImpl> create(LayerChromium* owner)
+ {
+ return adoptRef(new CCCanvasLayerImpl(owner));
+ }
+ virtual ~CCCanvasLayerImpl();
+
+ typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program;
+
+ virtual void draw();
+
+ virtual void dumpLayerProperties(TextStream&, int indent) const;
+
+ void setTextureId(unsigned id) { m_textureId = id; }
+ void setPremultipliedAlpha(bool premultipliedAlpha) { m_premultipliedAlpha = premultipliedAlpha; }
+private:
+ explicit CCCanvasLayerImpl(LayerChromium*);
+
+ unsigned m_textureId;
+ bool m_premultipliedAlpha;
+};
+
+}
+
+#endif // CCCanvasLayerImpl_h
+
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp
index 604ef61..404944b 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp
@@ -66,8 +66,8 @@ void CCHeadsUpDisplay::draw()
// Use a fullscreen texture only if we need to...
IntSize hudSize;
if (m_showPlatformLayerTree) {
- hudSize.setWidth(min(2048, m_layerRenderer->visibleRectSize().width()));
- hudSize.setHeight(min(2048, m_layerRenderer->visibleRectSize().height()));
+ hudSize.setWidth(min(2048, m_layerRenderer->viewportSize().width()));
+ hudSize.setHeight(min(2048, m_layerRenderer->viewportSize().height()));
} else {
hudSize.setWidth(512);
hudSize.setHeight(128);
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h
index dbac22a..d56f8ab 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h
@@ -53,7 +53,7 @@ public:
void setShowPlatformLayerTree(bool enable) { m_showPlatformLayerTree = enable; }
bool showPlatformLayerTree() const { return m_showPlatformLayerTree; }
- bool enabled() const { return true || m_showPlatformLayerTree || m_showFPSCounter; }
+ bool enabled() const { return m_showPlatformLayerTree || m_showFPSCounter; }
void draw();
private:
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp
index a0ad0fb..9411e5a 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp
@@ -62,13 +62,18 @@ namespace WebCore {
CCLayerImpl::CCLayerImpl(LayerChromium* owner)
: m_owner(owner)
+ , m_anchorPoint(0.5, 0.5)
+ , m_anchorPointZ(0)
+ , m_doubleSided(true)
+ , m_masksToBounds(false)
+ , m_opacity(1.0)
+ , m_preserves3D(false)
#ifndef NDEBUG
, m_debugID(owner->debugID())
#endif
, m_targetRenderSurface(0)
, m_drawDepth(0)
, m_drawOpacity(0)
- , m_doubleSided(true)
, m_debugBorderColor(0, 0, 0, 0)
, m_debugBorderWidth(0)
, m_renderSurface(0)
@@ -107,7 +112,18 @@ RenderSurfaceChromium* CCLayerImpl::createRenderSurface()
return m_renderSurface.get();
}
-// These belong on CCLayerImpl, but should be subclased by each type and not defer to the LayerChromium subtypes.
+bool CCLayerImpl::descendantsDrawsContent()
+{
+ const Vector<RefPtr<LayerChromium> >& sublayers = m_owner->getSublayers();
+ for (size_t i = 0; i < sublayers.size(); ++i) {
+ sublayers[i]->createCCLayerImplIfNeeded();
+ if (sublayers[i]->ccLayerImpl()->drawsContent() || sublayers[i]->ccLayerImpl()->descendantsDrawsContent())
+ return true;
+ }
+ return false;
+}
+
+// These belong on CCLayerImpl, but should be overridden by each type and not defer to the LayerChromium subtypes.
bool CCLayerImpl::drawsContent() const
{
return m_owner->drawsContent();
@@ -118,6 +134,11 @@ void CCLayerImpl::draw()
return m_owner->draw();
}
+void CCLayerImpl::updateCompositorResources()
+{
+ return m_owner->updateCompositorResources();
+}
+
void CCLayerImpl::unreserveContentsTexture()
{
m_owner->unreserveContentsTexture();
@@ -167,7 +188,7 @@ void CCLayerImpl::drawDebugBorder()
GLC(context, context->drawElements(GraphicsContext3D::LINE_LOOP, 4, GraphicsContext3D::UNSIGNED_SHORT, 6 * sizeof(unsigned short)));
}
-static void writeIndent(TextStream& ts, int indent)
+void CCLayerImpl::writeIndent(TextStream& ts, int indent)
{
for (int i = 0; i != indent; ++i)
ts << " ";
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h
index 6892976..96c4f1b 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h
@@ -49,7 +49,7 @@ public:
return adoptRef(new CCLayerImpl(owner));
}
// When this class gets subclasses, remember to add 'virtual' here.
- ~CCLayerImpl();
+ virtual ~CCLayerImpl();
#ifndef NDEBUG
int debugID() const { return m_debugID; }
@@ -59,13 +59,43 @@ public:
CCLayerImpl* maskLayer() const;
CCLayerImpl* replicaLayer() const;
- void draw();
- bool drawsContent() const;
+ virtual void draw();
+ virtual void updateCompositorResources();
void unreserveContentsTexture();
void bindContentsTexture();
+ // Returns true if this layer has content to draw.
+ virtual bool drawsContent() const;
+
+ // Returns true if any of the layer's descendants has content to draw.
+ bool descendantsDrawsContent();
+
void cleanupResources();
+ void setAnchorPoint(const FloatPoint& anchorPoint) { m_anchorPoint = anchorPoint; }
+ const FloatPoint& anchorPoint() const { return m_anchorPoint; }
+
+ void setAnchorPointZ(float anchorPointZ) { m_anchorPointZ = anchorPointZ; }
+ float anchorPointZ() const { return m_anchorPointZ; }
+
+ void setMasksToBounds(bool masksToBounds) { m_masksToBounds = masksToBounds; }
+ bool masksToBounds() const { return m_masksToBounds; }
+
+ void setOpacity(float opacity) { m_opacity = opacity; }
+ float opacity() const { return m_opacity; }
+
+ void setPosition(const FloatPoint& position) { m_position = position; }
+ const FloatPoint& position() const { return m_position; }
+
+ void setPreserves3D(bool preserves3D) { m_preserves3D = preserves3D; }
+ bool preserves3D() const { return m_preserves3D; }
+
+ void setSublayerTransform(const TransformationMatrix& sublayerTransform) { m_sublayerTransform = sublayerTransform; }
+ const TransformationMatrix& sublayerTransform() const { return m_sublayerTransform; }
+
+ void setTransform(const TransformationMatrix& transform) { m_transform = transform; }
+ const TransformationMatrix& transform() const { return m_transform; }
+
void setName(const String& name) { m_name = name; }
const String& name() const { return m_name; }
@@ -108,11 +138,30 @@ public:
virtual void dumpLayerProperties(TextStream&, int indent) const;
-private:
+protected:
// For now, CCLayers are owned directly by a LayerChromium.
LayerChromium* m_owner;
explicit CCLayerImpl(LayerChromium*);
+ static void writeIndent(TextStream&, int indent);
+
+private:
+ // Properties synchronized from the associated LayerChromium.
+ FloatPoint m_anchorPoint;
+ float m_anchorPointZ;
+ IntSize m_bounds;
+
+ // Whether the "back" of this layer should draw.
+ bool m_doubleSided;
+
+ bool m_masksToBounds;
+ float m_opacity;
+ FloatPoint m_position;
+ bool m_preserves3D;
+ TransformationMatrix m_sublayerTransform;
+ TransformationMatrix m_transform;
+
+ // Properties owned exclusively by this CCLayerImpl.
// Debugging.
#ifndef NDEBUG
int m_debugID;
@@ -131,17 +180,12 @@ private:
float m_drawDepth;
float m_drawOpacity;
- // Whether the "back" of this layer should draw.
- bool m_doubleSided;
-
// Debug borders.
Color m_debugBorderColor;
float m_debugBorderWidth;
TransformationMatrix m_drawTransform;
- IntSize m_bounds;
-
// The scissor rectangle that should be used when this layer is drawn.
// Inherited by the parent layer and further restricted if this layer masks
// to bounds.
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp
new file mode 100644
index 0000000..4aef639
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "cc/CCPluginLayerImpl.h"
+
+#include "GraphicsContext3D.h"
+#include "LayerRendererChromium.h"
+#include "PluginLayerChromium.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+CCPluginLayerImpl::CCPluginLayerImpl(LayerChromium* owner)
+ : CCLayerImpl(owner)
+ , m_textureId(0)
+{
+}
+
+CCPluginLayerImpl::~CCPluginLayerImpl()
+{
+}
+
+void CCPluginLayerImpl::draw()
+{
+ ASSERT(layerRenderer());
+ const CCPluginLayerImpl::Program* program = layerRenderer()->pluginLayerProgram();
+ ASSERT(program && program->initialized());
+ GraphicsContext3D* context = layerRenderer()->context();
+ GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
+ GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId));
+
+ // FIXME: setting the texture parameters every time is redundant. Move this code somewhere
+ // where it will only happen once per texture.
+ GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
+ GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
+ GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
+ GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
+
+ layerRenderer()->useShader(program->program());
+ GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
+ LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(),
+ bounds().width(), bounds().height(), drawOpacity(),
+ program->vertexShader().matrixLocation(),
+ program->fragmentShader().alphaLocation());
+}
+
+
+void CCPluginLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
+{
+ writeIndent(ts, indent);
+ ts << "plugin layer texture id: " << m_textureId << "\n";
+ CCLayerImpl::dumpLayerProperties(ts, indent);
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h
new file mode 100644
index 0000000..65eb5b7
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CCPluginLayerImpl_h
+#define CCPluginLayerImpl_h
+
+#include "ProgramBinding.h"
+#include "ShaderChromium.h"
+#include "cc/CCLayerImpl.h"
+
+namespace WebCore {
+
+class CCPluginLayerImpl : public CCLayerImpl {
+public:
+ static PassRefPtr<CCPluginLayerImpl> create(LayerChromium* owner)
+ {
+ return adoptRef(new CCPluginLayerImpl(owner));
+ }
+ virtual ~CCPluginLayerImpl();
+
+ typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program;
+
+ virtual void draw();
+
+ virtual void dumpLayerProperties(TextStream&, int indent) const;
+
+ void setTextureId(unsigned id) { m_textureId = id; }
+
+private:
+ explicit CCPluginLayerImpl(LayerChromium*);
+
+ unsigned m_textureId;
+};
+
+}
+
+#endif // CCPluginLayerImpl_h
+
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp
new file mode 100644
index 0000000..eb3612b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "cc/CCVideoLayerImpl.h"
+
+#include "GraphicsContext3D.h"
+#include "LayerRendererChromium.h"
+#include "NotImplemented.h"
+#include "VideoLayerChromium.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+// These values are magic numbers that are used in the transformation
+// from YUV to RGB color values.
+// They are taken from the following webpage:
+// http://www.fourcc.org/fccyvrgb.php
+const float CCVideoLayerImpl::yuv2RGB[9] = {
+ 1.164f, 1.164f, 1.164f,
+ 0.f, -.391f, 2.018f,
+ 1.596f, -.813f, 0.f,
+};
+
+// These values map to 16, 128, and 128 respectively, and are computed
+// as a fraction over 256 (e.g. 16 / 256 = 0.0625).
+// They are used in the YUV to RGBA conversion formula:
+// Y - 16 : Gives 16 values of head and footroom for overshooting
+// U - 128 : Turns unsigned U into signed U [-128,127]
+// V - 128 : Turns unsigned V into signed V [-128,127]
+const float CCVideoLayerImpl::yuvAdjust[3] = {
+ -0.0625f,
+ -0.5f,
+ -0.5f,
+};
+
+CCVideoLayerImpl::CCVideoLayerImpl(LayerChromium* owner)
+ : CCLayerImpl(owner)
+{
+}
+
+CCVideoLayerImpl::~CCVideoLayerImpl()
+{
+ cleanupResources();
+}
+
+void CCVideoLayerImpl::setTexture(size_t i, VideoLayerChromium::Texture texture)
+{
+ ASSERT(i < 3);
+ m_textures[i] = texture;
+}
+
+void CCVideoLayerImpl::draw()
+{
+ if (m_skipsDraw)
+ return;
+
+ ASSERT(layerRenderer());
+ const RGBAProgram* rgbaProgram = layerRenderer()->videoLayerRGBAProgram();
+ ASSERT(rgbaProgram && rgbaProgram->initialized());
+ const YUVProgram* yuvProgram = layerRenderer()->videoLayerYUVProgram();
+ ASSERT(yuvProgram && yuvProgram->initialized());
+
+ switch (m_frameFormat) {
+ case VideoFrameChromium::YV12:
+ case VideoFrameChromium::YV16:
+ drawYUV(yuvProgram);
+ break;
+ case VideoFrameChromium::RGBA:
+ drawRGBA(rgbaProgram);
+ break;
+ default:
+ // FIXME: Implement other paths.
+ notImplemented();
+ break;
+ }
+}
+
+void CCVideoLayerImpl::drawYUV(const CCVideoLayerImpl::YUVProgram* program) const
+{
+ GraphicsContext3D* context = layerRenderer()->context();
+ VideoLayerChromium::Texture yTexture = m_textures[VideoFrameChromium::yPlane];
+ VideoLayerChromium::Texture uTexture = m_textures[VideoFrameChromium::uPlane];
+ VideoLayerChromium::Texture vTexture = m_textures[VideoFrameChromium::vPlane];
+
+ GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE1));
+ GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, yTexture.id));
+ GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE2));
+ GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, uTexture.id));
+ GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE3));
+ GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, vTexture.id));
+
+ layerRenderer()->useShader(program->program());
+
+ float yWidthScaleFactor = static_cast<float>(yTexture.visibleSize.width()) / yTexture.size.width();
+ // Arbitrarily take the u sizes because u and v dimensions are identical.
+ float uvWidthScaleFactor = static_cast<float>(uTexture.visibleSize.width()) / uTexture.size.width();
+ GLC(context, context->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor));
+ GLC(context, context->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor));
+
+ GLC(context, context->uniform1i(program->fragmentShader().yTextureLocation(), 1));
+ GLC(context, context->uniform1i(program->fragmentShader().uTextureLocation(), 2));
+ GLC(context, context->uniform1i(program->fragmentShader().vTextureLocation(), 3));
+
+ GLC(context, context->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1));
+ GLC(context, context->uniform3fv(program->fragmentShader().yuvAdjLocation(), const_cast<float*>(yuvAdjust), 1));
+
+ LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(),
+ bounds().width(), bounds().height(), drawOpacity(),
+ program->vertexShader().matrixLocation(),
+ program->fragmentShader().alphaLocation());
+
+ // Reset active texture back to texture 0.
+ GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
+}
+
+void CCVideoLayerImpl::drawRGBA(const CCVideoLayerImpl::RGBAProgram* program) const
+{
+ GraphicsContext3D* context = layerRenderer()->context();
+ VideoLayerChromium::Texture texture = m_textures[VideoFrameChromium::rgbPlane];
+
+ GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
+ GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, texture.id));
+
+ layerRenderer()->useShader(program->program());
+ float widthScaleFactor = static_cast<float>(texture.visibleSize.width()) / texture.size.width();
+ GLC(context, context->uniform4f(program->vertexShader().texTransformLocation(), 0, 0, widthScaleFactor, 1));
+
+ GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
+
+ LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(),
+ bounds().width(), bounds().height(), drawOpacity(),
+ program->vertexShader().matrixLocation(),
+ program->fragmentShader().alphaLocation());
+}
+
+
+void CCVideoLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
+{
+ writeIndent(ts, indent);
+ ts << "video layer\n";
+ CCLayerImpl::dumpLayerProperties(ts, indent);
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h
new file mode 100644
index 0000000..62f8778
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CCVideoLayerImpl_h
+#define CCVideoLayerImpl_h
+
+#include "ProgramBinding.h"
+#include "ShaderChromium.h"
+#include "VideoFrameChromium.h"
+#include "VideoLayerChromium.h"
+#include "cc/CCLayerImpl.h"
+
+namespace WebCore {
+
+class VideoFrameProvider;
+
+class CCVideoLayerImpl : public CCLayerImpl {
+public:
+ static PassRefPtr<CCVideoLayerImpl> create(LayerChromium* owner)
+ {
+ return adoptRef(new CCVideoLayerImpl(owner));
+ }
+ virtual ~CCVideoLayerImpl();
+
+ typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexFlipAlpha> RGBAProgram;
+ typedef ProgramBinding<VertexShaderPosTexYUVStretch, FragmentShaderYUVVideo> YUVProgram;
+
+ virtual void draw();
+
+ virtual void dumpLayerProperties(TextStream&, int indent) const;
+
+ void setSkipsDraw(bool skipsDraw) { m_skipsDraw = skipsDraw; }
+ void setFrameFormat(VideoFrameChromium::Format format) { m_frameFormat = format; }
+ void setTexture(size_t, VideoLayerChromium::Texture);
+
+private:
+ explicit CCVideoLayerImpl(LayerChromium*);
+
+ void drawYUV(const YUVProgram*) const;
+ void drawRGBA(const RGBAProgram*) const;
+
+ static const float yuv2RGB[9];
+ static const float yuvAdjust[3];
+
+ bool m_skipsDraw;
+ VideoFrameChromium::Format m_frameFormat;
+ VideoLayerChromium::Texture m_textures[3];
+};
+
+}
+
+#endif // CCVideoLayerImpl_h
+
diff --git a/Source/WebCore/platform/graphics/cocoa/FontPlatformData.h b/Source/WebCore/platform/graphics/cocoa/FontPlatformData.h
deleted file mode 100644
index ca38029..0000000
--- a/Source/WebCore/platform/graphics/cocoa/FontPlatformData.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * This file is part of the internal font implementation.
- * It should not be included by source files outside of it.
- *
- * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef FontPlatformData_h
-#define FontPlatformData_h
-
-#include "FontOrientation.h"
-#include "FontWidthVariant.h"
-#include <wtf/text/StringImpl.h>
-
-#ifdef __OBJC__
-@class NSFont;
-#else
-class NSFont;
-#endif
-
-typedef struct CGFont* CGFontRef;
-#ifndef BUILDING_ON_TIGER
-typedef const struct __CTFont* CTFontRef;
-#endif
-
-#include <CoreFoundation/CFBase.h>
-#include <objc/objc-auto.h>
-#include <wtf/Forward.h>
-#include <wtf/RetainPtr.h>
-
-#if PLATFORM(CHROMIUM) && OS(DARWIN)
-#include "CrossProcessFontLoading.h"
-#endif
-
-
-typedef UInt32 ATSUFontID;
-typedef UInt32 ATSFontRef;
-
-namespace WebCore {
-
-#ifndef BUILDING_ON_TIGER
-inline CTFontRef toCTFontRef(NSFont *nsFont) { return reinterpret_cast<CTFontRef>(nsFont); }
-#endif
-
-class FontPlatformData {
- public:
- FontPlatformData(float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation = Horizontal, FontWidthVariant widthVariant = RegularWidth)
- : m_syntheticBold(syntheticBold)
- , m_syntheticOblique(syntheticOblique)
- , m_orientation(orientation)
- , m_size(size)
- , m_widthVariant(widthVariant)
- , m_font(0)
-#ifdef BUILDING_ON_TIGER
- , m_cgFont(0)
-#endif
- , m_isColorBitmapFont(false)
- {
- }
-
- FontPlatformData(NSFont*, float size, bool syntheticBold = false, bool syntheticOblique = false, FontOrientation = Horizontal, FontWidthVariant = RegularWidth);
-
- FontPlatformData(CGFontRef cgFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation, FontWidthVariant widthVariant)
- : m_syntheticBold(syntheticBold)
- , m_syntheticOblique(syntheticOblique)
- , m_orientation(orientation)
- , m_size(size)
- , m_widthVariant(widthVariant)
- , m_font(0)
- , m_cgFont(cgFont)
- , m_isColorBitmapFont(false)
- {
- }
-
- FontPlatformData(const FontPlatformData&);
-
- ~FontPlatformData();
-
- FontPlatformData(WTF::HashTableDeletedValueType) : m_font(hashTableDeletedFontValue()) { }
- bool isHashTableDeletedValue() const { return m_font == hashTableDeletedFontValue(); }
-
- float size() const { return m_size; }
- bool syntheticBold() const { return m_syntheticBold; }
- bool syntheticOblique() const { return m_syntheticOblique; }
- FontOrientation orientation() const { return m_orientation; }
- FontWidthVariant widthVariant() const { return m_widthVariant; }
-
- bool m_syntheticBold;
- bool m_syntheticOblique;
- FontOrientation m_orientation;
-
- float m_size;
-
- FontWidthVariant m_widthVariant;
-
- unsigned hash() const
- {
- ASSERT(m_font != 0 || m_cgFont == 0);
- uintptr_t hashCodes[3] = { (uintptr_t)m_font, m_widthVariant, m_orientation << 2 | m_syntheticBold << 1 | m_syntheticOblique };
- return WTF::StringHasher::createBlobHash<sizeof(hashCodes)>(hashCodes);
- }
-
- const FontPlatformData& operator=(const FontPlatformData& f);
-
- bool operator==(const FontPlatformData& other) const
- {
- return m_font == other.m_font && m_syntheticBold == other.m_syntheticBold && m_syntheticOblique == other.m_syntheticOblique &&
- m_cgFont == other.m_cgFont && m_size == other.m_size && m_orientation == other.m_orientation && m_widthVariant == other.m_widthVariant;
- }
-
- NSFont *font() const { return m_font; }
- void setFont(NSFont *font);
-
- CTFontRef ctFont() const;
-
- bool roundsGlyphAdvances() const;
- bool allowsLigatures() const;
- bool isColorBitmapFont() const { return m_isColorBitmapFont; }
-
-#ifndef BUILDING_ON_TIGER
- CGFontRef cgFont() const { return m_cgFont.get(); }
-#else
- CGFontRef cgFont() const { return m_cgFont; }
-#endif
-
-#ifndef NDEBUG
- String description() const;
-#endif
-
-private:
- static NSFont *hashTableDeletedFontValue() { return reinterpret_cast<NSFont *>(-1); }
-
- // Load various data about the font specified by |nsFont| with the size fontSize into the following output paramters:
- // Note: Callers should always take into account that for the Chromium port, |outNSFont| isn't necessarily the same
- // font as |nsFont|. This because the sandbox may block loading of the original font.
- // * outNSFont - The font that was actually loaded, for the Chromium port this may be different than nsFont.
- // The caller is responsible for calling CFRelease() on this parameter when done with it.
- // * cgFont - CGFontRef representing the input font at the specified point size.
- void loadFont(NSFont* nsFont, float fontSize, NSFont*& outNSFont, CGFontRef& cgFont);
-
- NSFont *m_font;
-
-#ifndef BUILDING_ON_TIGER
- RetainPtr<CGFontRef> m_cgFont;
-#else
- CGFontRef m_cgFont; // It is not necessary to refcount this, since either an NSFont owns it or some CachedFont has it referenced.
-#endif
-
- mutable RetainPtr<CTFontRef> m_CTFont;
-
- bool m_isColorBitmapFont;
-
-#if PLATFORM(CHROMIUM) && OS(DARWIN)
- RefPtr<MemoryActivatedFont> m_inMemoryFont;
-#endif
-};
-
-} // namespace WebCore
-
-#endif
diff --git a/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm b/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm
index b40f698..6a17707 100644
--- a/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm
+++ b/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm
@@ -45,9 +45,12 @@ void FontPlatformData::loadFont(NSFont* nsFont, float, NSFont*& outNSFont, CGFon
}
#endif // PLATFORM(MAC)
-FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation, FontWidthVariant widthVariant)
+FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation,
+ TextOrientation textOrientation, FontWidthVariant widthVariant)
: m_syntheticBold(syntheticBold)
, m_syntheticOblique(syntheticOblique)
+ , m_orientation(orientation)
+ , m_textOrientation(textOrientation)
, m_size(size)
, m_widthVariant(widthVariant)
, m_font(nsFont)
@@ -64,8 +67,6 @@ FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool syntheticBol
CGFontRef cgFont = 0;
loadFont(nsFont, size, m_font, cgFont);
- m_orientation = orientation;
-
if (m_font)
CFRetain(m_font);
@@ -76,35 +77,26 @@ FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool syntheticBol
#endif
}
-FontPlatformData::FontPlatformData(const FontPlatformData& f)
+FontPlatformData:: ~FontPlatformData()
+{
+ if (m_font && m_font != reinterpret_cast<NSFont *>(-1))
+ CFRelease(m_font);
+}
+
+void FontPlatformData::platformDataInit(const FontPlatformData& f)
{
m_font = f.m_font && f.m_font != reinterpret_cast<NSFont *>(-1) ? const_cast<NSFont *>(static_cast<const NSFont *>(CFRetain(f.m_font))) : f.m_font;
- m_syntheticBold = f.m_syntheticBold;
- m_syntheticOblique = f.m_syntheticOblique;
- m_size = f.m_size;
- m_widthVariant = f.m_widthVariant;
m_cgFont = f.m_cgFont;
- m_isColorBitmapFont = f.m_isColorBitmapFont;
- m_orientation = f.m_orientation;
m_CTFont = f.m_CTFont;
+
#if PLATFORM(CHROMIUM) && OS(DARWIN)
m_inMemoryFont = f.m_inMemoryFont;
#endif
}
-FontPlatformData:: ~FontPlatformData()
+const FontPlatformData& FontPlatformData::platformDataAssign(const FontPlatformData& f)
{
- if (m_font && m_font != reinterpret_cast<NSFont *>(-1))
- CFRelease(m_font);
-}
-
-const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& f)
-{
- m_syntheticBold = f.m_syntheticBold;
- m_syntheticOblique = f.m_syntheticOblique;
- m_size = f.m_size;
- m_widthVariant = f.m_widthVariant;
m_cgFont = f.m_cgFont;
if (m_font == f.m_font)
return *this;
@@ -113,8 +105,6 @@ const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& f)
if (m_font && m_font != reinterpret_cast<NSFont *>(-1))
CFRelease(m_font);
m_font = f.m_font;
- m_isColorBitmapFont = f.m_isColorBitmapFont;
- m_orientation = f.m_orientation;
m_CTFont = f.m_CTFont;
#if PLATFORM(CHROMIUM) && OS(DARWIN)
m_inMemoryFont = f.m_inMemoryFont;
@@ -122,6 +112,12 @@ const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& f)
return *this;
}
+bool FontPlatformData::platformIsEqual(const FontPlatformData& other) const
+{
+ return m_font == other.m_font
+ && m_cgFont == other.m_cgFont;
+}
+
void FontPlatformData::setFont(NSFont *font)
{
ASSERT_ARG(font, font);
diff --git a/Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp b/Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp
index 841c8a3..b1cf96b 100644
--- a/Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp
+++ b/Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp
@@ -59,7 +59,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
cairo_font_face_destroy(m_fontFace);
}
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode)
{
return FontPlatformData(m_fontFace, size, bold, italic);
}
diff --git a/Source/WebCore/platform/graphics/freetype/FontPlatformData.h b/Source/WebCore/platform/graphics/freetype/FontPlatformData.h
index 2841b14..d1cb605 100644
--- a/Source/WebCore/platform/graphics/freetype/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/freetype/FontPlatformData.h
@@ -71,6 +71,7 @@ public:
bool hasCompatibleCharmap();
FontOrientation orientation() const { return Horizontal; } // FIXME: Implement.
+ void setOrientation(FontOrientation) { } // FIXME: Implement.
cairo_scaled_font_t* scaledFont() const { return m_scaledFont; }
diff --git a/Source/WebCore/platform/graphics/gpu/BicubicShader.cpp b/Source/WebCore/platform/graphics/gpu/BicubicShader.cpp
new file mode 100644
index 0000000..40c9843
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/BicubicShader.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(ACCELERATED_2D_CANVAS)
+
+#include "BicubicShader.h"
+
+#include "GraphicsContext3D.h"
+
+namespace WebCore {
+
+BicubicShader::BicubicShader(GraphicsContext3D* context, unsigned program)
+ : Shader(context, program)
+ , m_matrixLocation(context->getUniformLocation(program, "matrix"))
+ , m_texMatrixLocation(context->getUniformLocation(program, "texMatrix"))
+ , m_coefficientsLocation(context->getUniformLocation(program, "coefficients"))
+ , m_imageIncrementLocation(context->getUniformLocation(program, "imageIncrement"))
+ , m_imageLocation(context->getUniformLocation(program, "image"))
+ , m_alphaLocation(context->getUniformLocation(program, "alpha"))
+ , m_positionLocation(context->getAttribLocation(program, "position"))
+{
+}
+
+PassOwnPtr<BicubicShader> BicubicShader::create(GraphicsContext3D* context)
+{
+ static const char* vertexShaderSource =
+ "uniform mat3 matrix;\n"
+ "uniform mat3 texMatrix;\n"
+ "attribute vec3 position;\n"
+ "varying vec2 texCoord;\n"
+ "void main() {\n"
+ " texCoord = (texMatrix * position).xy;\n"
+ " gl_Position = vec4(matrix * position, 1.0);\n"
+ "}\n";
+ static const char* fragmentShaderSource =
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "uniform sampler2D image;\n"
+ "uniform vec2 imageIncrement;\n"
+ "uniform mat4 coefficients;\n"
+ "uniform float alpha;\n"
+ "varying vec2 texCoord;\n"
+ "vec4 cubicBlend(float t, vec4 c0, vec4 c1, vec4 c2, vec4 c3) {\n"
+ " vec4 ts = vec4(1.0, t, t * t, t * t * t);\n"
+ " vec4 result = coefficients * ts;\n"
+ " return result.w * c0 + result.z * c1 + result.y * c2 + result.x * c3;\n"
+ "}\n"
+ "void main() {\n"
+ " vec2 imageCoord = texCoord;\n"
+ " vec2 f = fract(imageCoord / imageIncrement) - vec2(0.5, 0.5);\n"
+ " vec4 t00 = texture2D(image, imageCoord + imageIncrement * vec2(-1, -1));\n"
+ " vec4 t10 = texture2D(image, imageCoord + imageIncrement * vec2( 0, -1));\n"
+ " vec4 t20 = texture2D(image, imageCoord + imageIncrement * vec2( 1, -1));\n"
+ " vec4 t30 = texture2D(image, imageCoord + imageIncrement * vec2( 2, -1));\n"
+ " vec4 t0 = cubicBlend(f.x, t00, t10, t20, t30);\n"
+ " vec4 t01 = texture2D(image, imageCoord + imageIncrement * vec2(-1, 0));\n"
+ " vec4 t11 = texture2D(image, imageCoord + imageIncrement * vec2( 0, 0));\n"
+ " vec4 t21 = texture2D(image, imageCoord + imageIncrement * vec2( 1, 0));\n"
+ " vec4 t31 = texture2D(image, imageCoord + imageIncrement * vec2( 2, 0));\n"
+ " vec4 t1 = cubicBlend(f.x, t01, t11, t21, t31);\n"
+ " vec4 t02 = texture2D(image, imageCoord + imageIncrement * vec2(-1, 1));\n"
+ " vec4 t12 = texture2D(image, imageCoord + imageIncrement * vec2( 0, 1));\n"
+ " vec4 t22 = texture2D(image, imageCoord + imageIncrement * vec2( 1, 1));\n"
+ " vec4 t32 = texture2D(image, imageCoord + imageIncrement * vec2( 2, 1));\n"
+ " vec4 t2 = cubicBlend(f.x, t02, t12, t22, t32);\n"
+ " vec4 t03 = texture2D(image, imageCoord + imageIncrement * vec2(-1, 2));\n"
+ " vec4 t13 = texture2D(image, imageCoord + imageIncrement * vec2( 0, 2));\n"
+ " vec4 t23 = texture2D(image, imageCoord + imageIncrement * vec2( 1, 2));\n"
+ " vec4 t33 = texture2D(image, imageCoord + imageIncrement * vec2( 2, 2));\n"
+ " vec4 t3 = cubicBlend(f.x, t03, t13, t23, t33);\n"
+ " gl_FragColor = cubicBlend(f.y, t0, t1, t2, t3);\n"
+ "}\n";
+
+ unsigned program = loadProgram(context, vertexShaderSource, fragmentShaderSource);
+ if (!program)
+ return 0;
+
+ return new BicubicShader(context, program);
+}
+
+void BicubicShader::use(const AffineTransform& transform, const AffineTransform& texTransform, const float coefficients[16], const float imageIncrement[2], float alpha)
+{
+ m_context->useProgram(m_program);
+ float matrix[9];
+ affineTo3x3(transform, matrix);
+ m_context->uniformMatrix3fv(m_matrixLocation, false /*transpose*/, matrix, 1 /*count*/);
+
+ float texMatrix[9];
+ affineTo3x3(texTransform, texMatrix);
+ m_context->uniformMatrix3fv(m_texMatrixLocation, false /*transpose*/, texMatrix, 1 /*count*/);
+ m_context->uniformMatrix4fv(m_coefficientsLocation, false /*transpose*/, const_cast<float *>(coefficients), 1 /*count*/);
+
+ m_context->uniform2f(m_imageIncrementLocation, imageIncrement[0], imageIncrement[1]);
+
+ // For now, we always use texture unit 0. If that ever changes, we should
+ // expose this parameter to the caller.
+ m_context->uniform1i(m_imageLocation, 0);
+ m_context->uniform1f(m_alphaLocation, alpha);
+
+ m_context->vertexAttribPointer(m_positionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0);
+
+ m_context->enableVertexAttribArray(m_positionLocation);
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/graphics/gpu/BicubicShader.h b/Source/WebCore/platform/graphics/gpu/BicubicShader.h
new file mode 100644
index 0000000..f7522f4
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/BicubicShader.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BicubicShader_h
+#define BicubicShader_h
+
+#include "Shader.h"
+
+namespace WebCore {
+
+class BicubicShader : public Shader {
+public:
+ static PassOwnPtr<BicubicShader> create(GraphicsContext3D*);
+
+ void use(const AffineTransform&, const AffineTransform& texTransform, const float coefficients[16], const float imageIncrement[2], float alpha);
+
+private:
+ BicubicShader(GraphicsContext3D*, unsigned program);
+
+ int m_matrixLocation;
+ int m_texMatrixLocation;
+ int m_coefficientsLocation;
+ int m_imageIncrementLocation;
+ int m_imageLocation;
+ int m_alphaLocation;
+ int m_positionLocation;
+};
+
+}
+
+#endif // BicubicShader_h
diff --git a/Source/WebCore/platform/graphics/gpu/ConvolutionShader.cpp b/Source/WebCore/platform/graphics/gpu/ConvolutionShader.cpp
new file mode 100644
index 0000000..f0b6bd9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/ConvolutionShader.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(ACCELERATED_2D_CANVAS)
+
+#include "ConvolutionShader.h"
+
+#include "GraphicsContext3D.h"
+#include "StringExtras.h"
+
+namespace WebCore {
+
+ConvolutionShader::ConvolutionShader(GraphicsContext3D* context, unsigned program, int kernelWidth)
+ : Shader(context, program)
+ , m_kernelWidth(kernelWidth)
+ , m_matrixLocation(context->getUniformLocation(program, "matrix"))
+ , m_texMatrixLocation(context->getUniformLocation(program, "texMatrix"))
+ , m_kernelLocation(context->getUniformLocation(program, "kernel"))
+ , m_imageLocation(context->getUniformLocation(program, "image"))
+ , m_imageIncrementLocation(context->getUniformLocation(program, "imageIncrement"))
+ , m_positionLocation(context->getAttribLocation(program, "position"))
+{
+}
+
+PassOwnPtr<ConvolutionShader> ConvolutionShader::create(GraphicsContext3D* context, int kernelWidth)
+{
+ static const char* vertexShaderRaw =
+ "#define KERNEL_WIDTH %d\n"
+ "uniform mat3 matrix;\n"
+ "uniform mat3 texMatrix;\n"
+ "uniform vec2 imageIncrement;\n"
+ "attribute vec3 position;\n"
+ "varying vec2 imageCoord;\n"
+ "void main() {\n"
+ " // Offset image coords by half of kernel width, in image texels\n"
+ " gl_Position = vec4(matrix * position, 1.0);\n"
+ " float scale = (float(KERNEL_WIDTH) - 1.0) / 2.0;\n"
+ " imageCoord = (texMatrix * position).xy - vec2(scale, scale) * imageIncrement;\n"
+ "}\n";
+ char vertexShaderSource[1024];
+ snprintf(vertexShaderSource, sizeof(vertexShaderSource), vertexShaderRaw, kernelWidth);
+ static const char* fragmentShaderRaw =
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "#define KERNEL_WIDTH %d\n"
+ "uniform sampler2D image;\n"
+ "uniform float kernel[KERNEL_WIDTH];\n"
+ "uniform vec2 imageIncrement;\n"
+ "varying vec2 imageCoord;\n"
+ "void main() {\n"
+ " vec2 coord = imageCoord;\n"
+ " vec4 sum = vec4(0, 0, 0, 0);\n"
+ " for (int i = 0; i < KERNEL_WIDTH; i++) {\n"
+ " sum += texture2D(image, coord) * kernel[i];\n"
+ " coord += imageIncrement;\n"
+ " }\n"
+ " gl_FragColor = sum;\n"
+ "}\n";
+ char fragmentShaderSource[1024];
+ snprintf(fragmentShaderSource, sizeof(fragmentShaderSource), fragmentShaderRaw, kernelWidth);
+
+ unsigned program = loadProgram(context, vertexShaderSource, fragmentShaderSource);
+ if (!program)
+ return 0;
+ return new ConvolutionShader(context, program, kernelWidth);
+}
+
+void ConvolutionShader::use(const AffineTransform& transform, const AffineTransform& texTransform, const float* kernel, int kernelWidth, float imageIncrement[2])
+{
+ m_context->useProgram(m_program);
+ float matrix[9];
+ affineTo3x3(transform, matrix);
+ m_context->uniformMatrix3fv(m_matrixLocation, false /*transpose*/, matrix, 1 /*count*/);
+
+ float texMatrix[9];
+ affineTo3x3(texTransform, texMatrix);
+ m_context->uniformMatrix3fv(m_texMatrixLocation, false /*transpose*/, texMatrix, 1 /*count*/);
+
+ m_context->uniform2f(m_imageIncrementLocation, imageIncrement[0], imageIncrement[1]);
+
+ // For now, we always use texture unit 0. If that ever changes, we should
+ // expose this parameter to the caller.
+ m_context->uniform1i(m_imageLocation, 0);
+ if (kernelWidth > m_kernelWidth)
+ kernelWidth = m_kernelWidth;
+ m_context->uniform1fv(m_kernelLocation, const_cast<float*>(kernel), kernelWidth);
+
+ m_context->vertexAttribPointer(m_positionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0);
+
+ m_context->enableVertexAttribArray(m_positionLocation);
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/graphics/gpu/ConvolutionShader.h b/Source/WebCore/platform/graphics/gpu/ConvolutionShader.h
new file mode 100644
index 0000000..533e0f5
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/ConvolutionShader.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ConvolutionShader_h
+#define ConvolutionShader_h
+
+#include "Shader.h"
+
+namespace WebCore {
+
+class ConvolutionShader : public Shader {
+public:
+ static PassOwnPtr<ConvolutionShader> create(GraphicsContext3D*, int kernelWidth);
+
+ void use(const AffineTransform&, const AffineTransform& texTransform, const float* kernel, int kernelWidth, float imageIncrement[2]);
+
+private:
+ ConvolutionShader(GraphicsContext3D*, unsigned program, int kernelWidth);
+
+ int m_kernelWidth;
+ int m_matrixLocation;
+ int m_texMatrixLocation;
+ int m_kernelLocation;
+ int m_imageLocation;
+ int m_imageIncrementLocation;
+ int m_positionLocation;
+};
+
+}
+
+#endif // ConvolutionShader_h
diff --git a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h
index 49ae114..606484e 100644
--- a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h
+++ b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h
@@ -42,6 +42,10 @@
#include <wtf/RetainPtr.h>
#endif
+#if ENABLE(SKIA_GPU)
+class GrContext;
+#endif
+
namespace WebCore {
#if PLATFORM(CHROMIUM)
@@ -59,6 +63,7 @@ public:
void reset(const IntSize&);
void bind();
IntSize size() const { return m_size; }
+ Platform3DObject colorBuffer() const { return m_colorBuffer; }
// Clear all resources from this object, as well as context. Called when context is destroyed
// to prevent invalid accesses to the resources.
@@ -94,6 +99,10 @@ public:
void setWillPublishCallback(PassOwnPtr<WillPublishCallback> callback) { m_callback = callback; }
#endif
+#if ENABLE(SKIA_GPU)
+ void setGrContext(GrContext* ctx);
+#endif
+
PassRefPtr<GraphicsContext3D> graphicsContext3D() const { return m_context; }
private:
@@ -130,6 +139,10 @@ private:
#if PLATFORM(MAC)
RetainPtr<WebGLLayer> m_platformLayer;
#endif
+
+#if ENABLE(SKIA_GPU)
+ GrContext* m_grContext;
+#endif
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/gpu/LoopBlinnPathProcessor.cpp b/Source/WebCore/platform/graphics/gpu/LoopBlinnPathProcessor.cpp
index 5439885..a96213c 100644
--- a/Source/WebCore/platform/graphics/gpu/LoopBlinnPathProcessor.cpp
+++ b/Source/WebCore/platform/graphics/gpu/LoopBlinnPathProcessor.cpp
@@ -42,6 +42,8 @@
#include <algorithm>
#include <wtf/Assertions.h>
#include <wtf/FastMalloc.h>
+#include <wtf/UnusedParam.h>
+
#if USE(SKIA)
#include "SkGeometry.h"
@@ -701,6 +703,7 @@ void LoopBlinnPathProcessor::buildContours(const Path& path)
}
} while (verb != SkPath::kDone_Verb);
#else // !USE(SKIA)
+ UNUSED_PARAM(path);
// Must port to your platform.
ASSERT_NOT_REACHED();
#endif
@@ -1145,6 +1148,8 @@ static void combineCallback(GLdouble coords[3], void* vertexData[4],
GLfloat weight[4], void** outData,
void* polygonData)
{
+ UNUSED_PARAM(vertexData);
+ UNUSED_PARAM(weight);
TessellationState* state = static_cast<TessellationState*>(polygonData);
GLdouble* outVertex = static_cast<GLdouble*>(fastMalloc(3 * sizeof(GLdouble)));
state->allocatedPointers.append(outVertex);
diff --git a/Source/WebCore/platform/graphics/gpu/PODRedBlackTree.h b/Source/WebCore/platform/graphics/gpu/PODRedBlackTree.h
index bd08988..7dd9ddd 100644
--- a/Source/WebCore/platform/graphics/gpu/PODRedBlackTree.h
+++ b/Source/WebCore/platform/graphics/gpu/PODRedBlackTree.h
@@ -257,7 +257,7 @@ private:
// properly update such summary information based only on the values
// in the left and right children. This method should return true if
// the node's summary information changed.
- virtual bool updateNode(Node* node) { return false; }
+ virtual bool updateNode(Node*) { return false; }
//----------------------------------------------------------------------
// Generic binary search tree operations
@@ -713,7 +713,7 @@ private:
}
#ifdef NDEBUG
- void logIfVerbose(const char* output) const { }
+ void logIfVerbose(const char*) const { }
#else
void logIfVerbose(const char* output) const
{
diff --git a/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp b/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
index ea8bc71..662d6a8 100644
--- a/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
+++ b/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
@@ -35,7 +35,10 @@
#include "SharedGraphicsContext3D.h"
#include "AffineTransform.h"
+#include "BicubicShader.h"
#include "Color.h"
+#include "ConvolutionShader.h"
+#include "DrawingBuffer.h"
#include "Extensions3D.h"
#include "FloatRect.h"
#include "IntSize.h"
@@ -43,6 +46,15 @@
#include "SolidFillShader.h"
#include "TexShader.h"
+#if ENABLE(SKIA_GPU)
+#include "GrContext.h"
+// Limit the number of textures we hold in the bitmap->texture cache.
+static const int maxTextureCacheCount = 512;
+// Limit the bytes allocated toward textures in the bitmap->texture cache.
+static const size_t maxTextureCacheBytes = 50 * 1024 * 1024;
+#endif
+
+#include <wtf/OwnArrayPtr.h>
#include <wtf/text/CString.h>
#include <wtf/text/WTFString.h>
@@ -65,16 +77,30 @@ PassRefPtr<SharedGraphicsContext3D> SharedGraphicsContext3D::create(HostWindow*
OwnPtr<TexShader> texShader = TexShader::create(context.get());
if (!texShader)
return 0;
- return adoptRef(new SharedGraphicsContext3D(context.release(), solidFillShader.release(), texShader.release()));
+ OwnPtr<BicubicShader> bicubicShader = BicubicShader::create(context.get());
+ if (!bicubicShader)
+ return 0;
+ OwnArrayPtr<OwnPtr<ConvolutionShader> > convolutionShaders = adoptArrayPtr(new OwnPtr<ConvolutionShader>[cMaxKernelWidth]);
+ for (int i = 0; i < cMaxKernelWidth; ++i) {
+ convolutionShaders[i] = ConvolutionShader::create(context.get(), i + 1);
+ if (!convolutionShaders[i])
+ return 0;
+ }
+ return adoptRef(new SharedGraphicsContext3D(context.release(), solidFillShader.release(), texShader.release(), bicubicShader.release(), convolutionShaders.release()));
}
-SharedGraphicsContext3D::SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<SolidFillShader> solidFillShader, PassOwnPtr<TexShader> texShader)
+SharedGraphicsContext3D::SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<SolidFillShader> solidFillShader, PassOwnPtr<TexShader> texShader, PassOwnPtr<BicubicShader> bicubicShader, PassOwnArrayPtr<OwnPtr<ConvolutionShader> > convolutionShaders)
: m_context(context)
, m_bgraSupported(false)
, m_quadVertices(0)
, m_solidFillShader(solidFillShader)
, m_texShader(texShader)
+ , m_bicubicShader(bicubicShader)
+ , m_convolutionShaders(convolutionShaders)
, m_oesStandardDerivativesSupported(false)
+#if ENABLE(SKIA_GPU)
+ , m_grContext(0)
+#endif
{
allContexts()->add(this);
Extensions3D* extensions = m_context->getExtensions();
@@ -92,6 +118,9 @@ SharedGraphicsContext3D::~SharedGraphicsContext3D()
{
m_context->deleteBuffer(m_quadVertices);
allContexts()->remove(this);
+#if ENABLE(SKIA_GPU)
+ GrSafeUnref(m_grContext);
+#endif
}
void SharedGraphicsContext3D::makeContextCurrent()
@@ -369,6 +398,17 @@ void SharedGraphicsContext3D::useTextureProgram(const AffineTransform& transform
m_texShader->use(transform, texTransform, 0, alpha);
}
+void SharedGraphicsContext3D::useBicubicProgram(const AffineTransform& transform, const AffineTransform& texTransform, const float coefficients[16], const float imageIncrement[2], float alpha)
+{
+ m_bicubicShader->use(transform, texTransform, coefficients, imageIncrement, alpha);
+}
+
+void SharedGraphicsContext3D::useConvolutionProgram(const AffineTransform& transform, const AffineTransform& texTransform, const float* kernel, int kernelWidth, float imageIncrement[2])
+{
+ ASSERT(kernelWidth >= 1 && kernelWidth <= cMaxKernelWidth);
+ m_convolutionShaders[kernelWidth - 1]->use(transform, texTransform, kernel, kernelWidth, imageIncrement);
+}
+
void SharedGraphicsContext3D::bindFramebuffer(Platform3DObject framebuffer)
{
m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, framebuffer);
@@ -411,6 +451,31 @@ void SharedGraphicsContext3D::useLoopBlinnExteriorProgram(unsigned vertexOffset,
m_loopBlinnExteriorShader->use(vertexOffset, klmOffset, transform, color);
}
+DrawingBuffer* SharedGraphicsContext3D::getOffscreenBuffer(unsigned index, const IntSize& size)
+{
+ if (index >= m_offscreenBuffers.size())
+ m_offscreenBuffers.resize(index + 1);
+
+ if (!m_offscreenBuffers[index])
+ m_offscreenBuffers[index] = m_context->createDrawingBuffer(size);
+
+ if (size.width() != m_offscreenBuffers[index]->size().width()
+ || size.height() != m_offscreenBuffers[index]->size().height())
+ m_offscreenBuffers[index]->reset(size);
+ return m_offscreenBuffers[index].get();
+}
+
+#if ENABLE(SKIA_GPU)
+GrContext* SharedGraphicsContext3D::grContext()
+{
+ if (!m_grContext) {
+ m_grContext = GrContext::CreateGLShaderContext();
+ m_grContext->setTextureCacheLimits(maxTextureCacheCount, maxTextureCacheBytes);
+ }
+ return m_grContext;
+}
+#endif
+
} // namespace WebCore
#endif
diff --git a/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h b/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h
index 707fd24..8fb3d50 100644
--- a/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h
+++ b/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h
@@ -38,14 +38,22 @@
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
+#include <wtf/OwnArrayPtr.h>
#include <wtf/OwnPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
+#if ENABLE(SKIA_GPU)
+class GrContext;
+#endif
+
namespace WebCore {
class AffineTransform;
+class BicubicShader;
class Color;
+class ConvolutionShader;
+class DrawingBuffer;
class FloatRect;
class HostWindow;
class IntSize;
@@ -101,6 +109,8 @@ public:
void useFillSolidProgram(const AffineTransform&, const Color&);
void useTextureProgram(const AffineTransform&, const AffineTransform&, float alpha);
+ void useBicubicProgram(const AffineTransform&, const AffineTransform&, const float coefficients[16], const float imageIncrement[2], float alpha);
+ void useConvolutionProgram(const AffineTransform&, const AffineTransform& texTransform, const float* kernel, int kernelWidth, float imageIncrement[2]);
void setActiveTexture(GC3Denum textureUnit);
void bindTexture(GC3Denum target, Platform3DObject texture);
@@ -127,9 +137,14 @@ public:
static bool useLoopBlinnForPathRendering();
void useLoopBlinnInteriorProgram(unsigned vertexOffset, const AffineTransform&, const Color&);
void useLoopBlinnExteriorProgram(unsigned vertexOffset, unsigned klmOffset, const AffineTransform&, const Color&);
+ DrawingBuffer* getOffscreenBuffer(unsigned index, const IntSize&);
+
+#if ENABLE(SKIA_GPU)
+ GrContext* grContext();
+#endif
private:
- SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D>, PassOwnPtr<SolidFillShader>, PassOwnPtr<TexShader>);
+ SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D>, PassOwnPtr<SolidFillShader>, PassOwnPtr<TexShader>, PassOwnPtr<BicubicShader>, PassOwnArrayPtr<OwnPtr<ConvolutionShader> >);
// Used to implement removeTexturesFor(), see the comment above.
static HashSet<SharedGraphicsContext3D*>* allContexts();
@@ -142,6 +157,8 @@ private:
OwnPtr<SolidFillShader> m_solidFillShader;
OwnPtr<TexShader> m_texShader;
+ OwnPtr<BicubicShader> m_bicubicShader;
+ OwnArrayPtr<OwnPtr<ConvolutionShader> > m_convolutionShaders;
TextureHashMap m_textures;
@@ -150,8 +167,17 @@ private:
OwnPtr<LoopBlinnSolidFillShader> m_loopBlinnInteriorShader;
OwnPtr<LoopBlinnSolidFillShader> m_loopBlinnExteriorShader;
bool m_oesStandardDerivativesSupported;
+
+ WTF::Vector<RefPtr<DrawingBuffer> > m_offscreenBuffers;
+
+#if ENABLE(SKIA_GPU)
+ GrContext* m_grContext;
+#endif
};
+const float cMaxSigma = 4.0f;
+const int cMaxKernelWidth = 25;
+
} // namespace WebCore
#endif // SharedGraphicsContext3D_h
diff --git a/Source/WebCore/platform/graphics/gpu/TilingData.cpp b/Source/WebCore/platform/graphics/gpu/TilingData.cpp
index dd540b3..1370543 100644
--- a/Source/WebCore/platform/graphics/gpu/TilingData.cpp
+++ b/Source/WebCore/platform/graphics/gpu/TilingData.cpp
@@ -66,7 +66,7 @@ void TilingData::setTotalSize(int totalSizeX, int totalSizeY)
void TilingData::setMaxTextureSize(int maxTextureSize)
{
- m_maxTextureSize = m_maxTextureSize;
+ m_maxTextureSize = maxTextureSize;
recomputeNumTiles();
}
diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
index 3763ef7..2fb4cef 100644
--- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
@@ -117,6 +117,13 @@ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpo
|| err->code == GST_RESOURCE_ERROR_NOT_FOUND)
error = MediaPlayer::FormatError;
else if (err->domain == GST_STREAM_ERROR) {
+ // Let the mediaPlayerClient handle the stream error, in
+ // this case the HTMLMediaElement will emit a stalled
+ // event.
+ if (err->code == GST_STREAM_ERROR_TYPE_NOT_FOUND) {
+ LOG_VERBOSE(Media, "Decode error, let the Media element emit a stalled event.");
+ break;
+ }
error = MediaPlayer::DecodeError;
attemptNextLocation = true;
} else if (err->domain == GST_RESOURCE_ERROR)
@@ -495,7 +502,7 @@ float MediaPlayerPrivateGStreamer::currentTime() const
return 0.0f;
if (m_seeking)
- return static_cast<float>(m_seekTime);
+ return m_seekTime;
return playbackPosition(m_playBin);
@@ -513,17 +520,28 @@ void MediaPlayerPrivateGStreamer::seek(float time)
if (m_errorOccured)
return;
- GstClockTime sec = (GstClockTime)(static_cast<float>(time * GST_SECOND));
- LOG_VERBOSE(Media, "Seek: %" GST_TIME_FORMAT, GST_TIME_ARGS(sec));
+ // Extract the integer part of the time (seconds) and the
+ // fractional part (microseconds). Attempt to round the
+ // microseconds so no floating point precision is lost and we can
+ // perform an accurate seek.
+ float seconds;
+ float microSeconds = modf(time, &seconds) * 1000000;
+ GTimeVal timeValue;
+ timeValue.tv_sec = static_cast<glong>(seconds);
+ timeValue.tv_usec = static_cast<glong>(roundf(microSeconds / 10000) * 10000);
+
+ GstClockTime clockTime = GST_TIMEVAL_TO_TIME(timeValue);
+ LOG_VERBOSE(Media, "Seek: %" GST_TIME_FORMAT, GST_TIME_ARGS(clockTime));
+
if (!gst_element_seek(m_playBin, m_player->rate(),
GST_FORMAT_TIME,
- (GstSeekFlags)(GST_SEEK_FLAG_FLUSH),
- GST_SEEK_TYPE_SET, sec,
+ (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
+ GST_SEEK_TYPE_SET, clockTime,
GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE))
LOG_VERBOSE(Media, "Seek to %f failed", time);
else {
m_seeking = true;
- m_seekTime = sec;
+ m_seekTime = time;
}
}
@@ -1046,15 +1064,9 @@ void MediaPlayerPrivateGStreamer::updateStates()
if (!m_isStreaming && !m_buffering)
return;
- // Resume playback if a seek was performed in a live pipeline
- // or during progressive download. That second use-case
- // happens when the seek is performed to a region of the media
- // that hasn't been downloaded yet.
if (m_seeking) {
shouldUpdateAfterSeek = true;
m_seeking = false;
- if (m_paused)
- gst_element_set_state(m_playBin, GST_STATE_PLAYING);
}
break;
case GST_STATE_CHANGE_FAILURE:
diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
index 11eb81b..8003887 100644
--- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
+++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
@@ -161,7 +161,7 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
GstElement* m_videoSinkBin;
GstElement* m_fpsSink;
GstElement* m_source;
- GstClockTime m_seekTime;
+ float m_seekTime;
bool m_changingRate;
float m_endTime;
bool m_isEndReached;
diff --git a/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
index 86e3e7a..66ea9ba 100644
--- a/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
@@ -352,7 +352,7 @@ static void webKitWebSrcStop(WebKitWebSrc* src, bool seeking)
}
priv->resourceHandle = 0;
- if (priv->frame)
+ if (priv->frame && !seeking)
priv->frame.release();
GST_OBJECT_LOCK(src);
diff --git a/Source/WebCore/platform/graphics/gtk/FontGtk.cpp b/Source/WebCore/platform/graphics/gtk/FontGtk.cpp
index 216fb56..d14b052 100644
--- a/Source/WebCore/platform/graphics/gtk/FontGtk.cpp
+++ b/Source/WebCore/platform/graphics/gtk/FontGtk.cpp
@@ -35,6 +35,7 @@
#include "CairoUtilities.h"
#include "ContextShadow.h"
+#include "PlatformContextCairo.h"
#include "GraphicsContext.h"
#include "NotImplemented.h"
#include "SimpleFontData.h"
@@ -44,7 +45,7 @@
#include <pango/pango.h>
#include <pango/pangocairo.h>
-#if defined(USE_FREETYPE)
+#if USE(FREETYPE)
#include <pango/pangofc-fontmap.h>
#endif
@@ -171,13 +172,13 @@ static gchar* convertUniCharToUTF8(const UChar* characters, gint length, int fro
static void setPangoAttributes(const Font* font, const TextRun& run, PangoLayout* layout)
{
-#if defined(USE_FREETYPE)
+#if USE(FREETYPE)
if (font->primaryFont()->platformData().m_pattern) {
PangoFontDescription* desc = pango_fc_font_description_from_pattern(font->primaryFont()->platformData().m_pattern.get(), FALSE);
pango_layout_set_font_description(layout, desc);
pango_font_description_free(desc);
}
-#elif defined(USE_PANGO)
+#elif USE(PANGO)
if (font->primaryFont()->platformData().m_font) {
PangoFontDescription* desc = pango_font_describe(font->primaryFont()->platformData().m_font);
pango_layout_set_font_description(layout, desc);
@@ -220,7 +221,7 @@ bool Font::canExpandAroundIdeographsInComplexText()
return false;
}
-static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context, const FloatPoint& point, PangoLayoutLine* layoutLine, PangoRegionType renderRegion)
+static void drawGlyphsShadow(GraphicsContext* graphicsContext, const FloatPoint& point, PangoLayoutLine* layoutLine, PangoRegionType renderRegion)
{
ContextShadow* shadow = graphicsContext->contextShadow();
ASSERT(shadow);
@@ -232,6 +233,7 @@ static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context,
// Optimize non-blurry shadows, by just drawing text without the ContextShadow.
if (!shadow->mustUseContextShadow(graphicsContext)) {
+ cairo_t* context = graphicsContext->platformContext()->cr();
cairo_save(context);
cairo_translate(context, totalOffset.x(), totalOffset.y());
@@ -255,6 +257,7 @@ static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context,
// because we don't want any bits and pieces of characters out of range to be
// drawn. Since ContextShadow expects a consistent transform, we have to undo the
// translation before calling endShadowLayer as well.
+ cairo_t* context = graphicsContext->platformContext()->cr();
cairo_save(context);
cairo_translate(context, totalOffset.x(), totalOffset.y());
gdk_cairo_region(context, renderRegion);
@@ -268,14 +271,14 @@ static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context,
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
{
-#if defined(USE_FREETYPE)
+#if USE(FREETYPE)
if (!primaryFont()->platformData().m_pattern) {
drawSimpleText(context, run, point, from, to);
return;
}
#endif
- cairo_t* cr = context->platformContext();
+ cairo_t* cr = context->platformContext()->cr();
PangoLayout* layout = pango_cairo_create_layout(cr);
setPangoAttributes(this, run, layout);
@@ -294,7 +297,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
int ranges[] = {start - utf8, end - utf8};
partialRegion = gdk_pango_layout_line_get_clip_region(layoutLine, 0, 0, ranges, 1);
- drawGlyphsShadow(context, cr, point, layoutLine, partialRegion);
+ drawGlyphsShadow(context, point, layoutLine, partialRegion);
cairo_save(cr);
cairo_translate(cr, point.x(), point.y());
@@ -348,7 +351,7 @@ static PangoLayout* getDefaultPangoLayout(const TextRun& run)
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* overflow) const
{
-#if defined(USE_FREETYPE)
+#if USE(FREETYPE)
if (!primaryFont()->platformData().m_pattern)
return floatWidthForSimpleText(run, 0, fallbackFonts, overflow);
#endif
@@ -373,7 +376,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool includePartialGlyphs) const
{
-#if defined(USE_FREETYPE)
+#if USE(FREETYPE)
if (!primaryFont()->platformData().m_pattern)
return offsetForPositionForSimpleText(run, xFloat, includePartialGlyphs);
#endif
@@ -401,7 +404,7 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool
FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
{
-#if defined(USE_FREETYPE)
+#if USE(FREETYPE)
if (!primaryFont()->platformData().m_pattern)
return selectionRectForSimpleText(run, point, h, from, to);
#endif
diff --git a/Source/WebCore/platform/graphics/gtk/IconGtk.cpp b/Source/WebCore/platform/graphics/gtk/IconGtk.cpp
index d56b52d..7fdc1f6 100644
--- a/Source/WebCore/platform/graphics/gtk/IconGtk.cpp
+++ b/Source/WebCore/platform/graphics/gtk/IconGtk.cpp
@@ -33,9 +33,9 @@
#include "GraphicsContext.h"
#include "MIMETypeRegistry.h"
#include "PassRefPtr.h"
-#include <wtf/text/CString.h>
-
+#include "PlatformContextCairo.h"
#include <gtk/gtk.h>
+#include <wtf/text/CString.h>
namespace WebCore {
@@ -117,7 +117,7 @@ void Icon::paint(GraphicsContext* context, const IntRect& rect)
return;
// TODO: Scale/clip the image if necessary.
- cairo_t* cr = context->platformContext();
+ cairo_t* cr = context->platformContext()->cr();
cairo_save(cr);
gdk_cairo_set_source_pixbuf(cr, m_icon, rect.x(), rect.y());
cairo_paint(cr);
diff --git a/Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp b/Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp
index 2aa016e..3da0f9b 100644
--- a/Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp
+++ b/Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp
@@ -54,7 +54,7 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
GError* error = 0;
gboolean success = FALSE;
if (type == "jpeg" && quality && *quality >= 0.0 && *quality <= 1.0) {
- String qualityString = String::format("%f", *quality);
+ String qualityString = String::format("%f", *quality * 100.0);
success = gdk_pixbuf_save_to_buffer(pixbuf.get(), &buffer.outPtr(), &bufferSize,
type.utf8().data(), &error, "quality", qualityString.utf8().data(), NULL);
} else {
diff --git a/Source/WebCore/platform/graphics/gtk/ImageGtk.cpp b/Source/WebCore/platform/graphics/gtk/ImageGtk.cpp
index 623ace6..9dd82a9 100644
--- a/Source/WebCore/platform/graphics/gtk/ImageGtk.cpp
+++ b/Source/WebCore/platform/graphics/gtk/ImageGtk.cpp
@@ -152,7 +152,10 @@ PassRefPtr<Image> Image::loadPlatformThemeIcon(const char* name, int size)
GdkPixbuf* BitmapImage::getGdkPixbuf()
{
- return cairoImageSurfaceToGdkPixbuf(frameAtIndex(currentFrame()));
+ cairo_surface_t* frame = frameAtIndex(currentFrame());
+ if (!frame)
+ return 0;
+ return cairoImageSurfaceToGdkPixbuf(frame);
}
}
diff --git a/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp
index 017b1e4..352de67 100644
--- a/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp
+++ b/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp
@@ -31,7 +31,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
{
}
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode)
{
return FontPlatformData(size, bold, italic);
}
diff --git a/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.h
index 7ffe89a..a319ce5 100644
--- a/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.h
+++ b/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.h
@@ -24,6 +24,7 @@
#include "FontOrientation.h"
#include "FontRenderingMode.h"
#include "FontWidthVariant.h"
+#include "TextOrientation.h"
#include <wtf/Forward.h>
namespace WebCore {
@@ -39,7 +40,7 @@ namespace WebCore {
static bool supportsFormat(const String&);
- FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
};
FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer*);
diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp
index 1a56664..07bc3ec 100644
--- a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp
+++ b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp
@@ -63,7 +63,8 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru
, m_glyphInCurrentRun(0)
, m_characterInCurrentGlyph(0)
, m_expansion(run.expansion())
- , m_afterExpansion(true)
+ , m_leadingExpansion(0)
+ , m_afterExpansion(!run.allowsLeadingExpansion())
, m_fallbackFonts(fallbackFonts)
, m_minGlyphBoundingBoxX(numeric_limits<float>::max())
, m_maxGlyphBoundingBoxX(numeric_limits<float>::min())
@@ -73,7 +74,7 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru
if (!m_expansion)
m_expansionPerOpportunity = 0;
else {
- bool isAfterExpansion = true;
+ bool isAfterExpansion = m_afterExpansion;
unsigned expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion);
if (isAfterExpansion && !m_run.allowsTrailingExpansion())
expansionOpportunityCount--;
@@ -86,12 +87,16 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru
collectComplexTextRuns();
adjustGlyphsAndAdvances();
+
+ m_runWidthSoFar = m_leadingExpansion;
}
int ComplexTextController::offsetForPosition(float h, bool includePartialGlyphs)
{
if (h >= m_totalWidth)
return m_run.ltr() ? m_end : 0;
+
+ h -= m_leadingExpansion;
if (h < 0)
return m_run.ltr() ? 0 : m_end;
@@ -472,16 +477,21 @@ void ComplexTextController::adjustGlyphsAndAdvances()
// Handle justification and word-spacing.
if (treatAsSpace || Font::isCJKIdeographOrSymbol(ch)) {
// Distribute the run's total expansion evenly over all expansion opportunities in the run.
- if (m_expansion && (!lastGlyph || m_run.allowsTrailingExpansion())) {
+ if (m_expansion) {
if (!treatAsSpace && !m_afterExpansion) {
// Take the expansion opportunity before this ideograph.
m_expansion -= m_expansionPerOpportunity;
m_totalWidth += m_expansionPerOpportunity;
- m_adjustedAdvances.last().width += m_expansionPerOpportunity;
+ if (m_adjustedAdvances.isEmpty())
+ m_leadingExpansion = m_expansionPerOpportunity;
+ else
+ m_adjustedAdvances.last().width += m_expansionPerOpportunity;
+ }
+ if (!lastGlyph || m_run.allowsTrailingExpansion()) {
+ m_expansion -= m_expansionPerOpportunity;
+ advance.width += m_expansionPerOpportunity;
+ m_afterExpansion = true;
}
- m_expansion -= m_expansionPerOpportunity;
- advance.width += m_expansionPerOpportunity;
- m_afterExpansion = true;
} else
m_afterExpansion = false;
diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextController.h b/Source/WebCore/platform/graphics/mac/ComplexTextController.h
index 7373bfe..44a7994 100644
--- a/Source/WebCore/platform/graphics/mac/ComplexTextController.h
+++ b/Source/WebCore/platform/graphics/mac/ComplexTextController.h
@@ -175,6 +175,7 @@ private:
unsigned m_characterInCurrentGlyph;
float m_expansion;
float m_expansionPerOpportunity;
+ float m_leadingExpansion;
bool m_afterExpansion;
HashSet<const SimpleFontData*>* m_fallbackFonts;
diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp
index b367fdf..d965ada 100644
--- a/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp
+++ b/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp
@@ -264,7 +264,7 @@ static void disableLigatures(const SimpleFontData* fontData, ATSUStyle atsuStyle
// Don't be too aggressive: if the font doesn't contain 'a', then assume that any ligatures it contains are
// in characters that always go through ATSUI, and therefore allow them. Geeza Pro is an example.
// See bugzilla 5166.
- if ((typesettingFeatures & Ligatures) || (fontData->orientation() == Horizontal && fontData->platformData().allowsLigatures()))
+ if ((typesettingFeatures & Ligatures) || (fontData->platformData().orientation() == Horizontal && fontData->platformData().allowsLigatures()))
return;
ATSUFontFeatureType featureTypes[] = { kLigaturesType };
diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp
index 239113f..d2fbaf5 100644
--- a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp
+++ b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp
@@ -144,17 +144,17 @@ void ComplexTextController::collectComplexTextRunsForCharactersCoreText(const UC
static CFDictionaryRef rtlTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, rtlOptionValues, WTF_ARRAY_LENGTH(optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
- ProviderInfo info = { cp, length, fontData->getCFStringAttributes(m_font.typesettingFeatures()) };
+ ProviderInfo info = { cp, length, fontData->getCFStringAttributes(m_font.typesettingFeatures(), fontData->platformData().orientation()) };
RetainPtr<CTTypesetterRef> typesetter(AdoptCF, wkCreateCTTypesetterWithUniCharProviderAndOptions(&provideStringAndAttributes, 0, &info, m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions));
#else
RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, cp, length, kCFAllocatorNull));
- RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(m_font.typesettingFeatures())));
+ RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(m_font.typesettingFeatures(), fontData->platformData().orientation())));
RetainPtr<CTTypesetterRef> typesetter(AdoptCF, CTTypesetterCreateWithAttributedStringAndOptions(attributedString.get(), m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions));
#endif
line.adoptCF(CTTypesetterCreateLine(typesetter.get(), CFRangeMake(0, 0)));
} else {
- ProviderInfo info = { cp, length, fontData->getCFStringAttributes(m_font.typesettingFeatures()) };
+ ProviderInfo info = { cp, length, fontData->getCFStringAttributes(m_font.typesettingFeatures(), fontData->platformData().orientation()) };
line.adoptCF(wkCreateCTLineWithUniCharProvider(&provideStringAndAttributes, 0, &info));
}
diff --git a/Source/WebCore/platform/graphics/mac/FontCacheMac.mm b/Source/WebCore/platform/graphics/mac/FontCacheMac.mm
index c254906..f7ae6b7 100644
--- a/Source/WebCore/platform/graphics/mac/FontCacheMac.mm
+++ b/Source/WebCore/platform/graphics/mac/FontCacheMac.mm
@@ -211,7 +211,7 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
bool syntheticBold = isAppKitFontWeightBold(weight) && !isAppKitFontWeightBold(actualWeight);
bool syntheticOblique = (traits & NSFontItalicTrait) && !(actualTraits & NSFontItalicTrait);
- return new FontPlatformData(platformFont, size, syntheticBold, syntheticOblique, fontDescription.orientation(), fontDescription.widthVariant());
+ return new FontPlatformData(platformFont, size, syntheticBold, syntheticOblique, fontDescription.orientation(), fontDescription.textOrientation(), fontDescription.widthVariant());
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp b/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp
index eed49a5..fe2a22c 100644
--- a/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp
+++ b/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp
@@ -111,8 +111,8 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
{
ComplexTextController controller(this, run, true, fallbackFonts);
if (glyphOverflow) {
- glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - fontMetrics().ascent());
- glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - fontMetrics().descent());
+ glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent()));
+ glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent()));
glyphOverflow->left = max<int>(0, ceilf(-controller.minGlyphBoundingBoxX()));
glyphOverflow->right = max<int>(0, ceilf(controller.maxGlyphBoundingBoxX() - controller.totalWidth()));
}
diff --git a/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
index f2bc33d..383adef 100644
--- a/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
+++ b/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
@@ -38,9 +38,9 @@ FontCustomPlatformData::~FontCustomPlatformData()
CGFontRelease(m_cgFont);
}
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation, FontWidthVariant widthVariant, FontRenderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation, TextOrientation textOrientation, FontWidthVariant widthVariant, FontRenderingMode)
{
- return FontPlatformData(m_cgFont, size, bold, italic, orientation, widthVariant);
+ return FontPlatformData(m_cgFont, size, bold, italic, orientation, textOrientation, widthVariant);
}
FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
diff --git a/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h
index c7ae1ca..c625304 100644
--- a/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h
+++ b/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h
@@ -24,6 +24,7 @@
#include "FontOrientation.h"
#include "FontRenderingMode.h"
#include "FontWidthVariant.h"
+#include "TextOrientation.h"
#include <CoreFoundation/CFBase.h>
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
@@ -48,7 +49,7 @@ public:
~FontCustomPlatformData();
- FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
static bool supportsFormat(const String&);
diff --git a/Source/WebCore/platform/graphics/mac/FontMac.mm b/Source/WebCore/platform/graphics/mac/FontMac.mm
index acd7562..4c28ead 100644
--- a/Source/WebCore/platform/graphics/mac/FontMac.mm
+++ b/Source/WebCore/platform/graphics/mac/FontMac.mm
@@ -52,28 +52,72 @@ bool Font::canExpandAroundIdeographsInComplexText()
return true;
}
-static void showGlyphsWithAdvances(const SimpleFontData* font, CGContextRef context, const CGGlyph* glyphs, const CGSize* advances, size_t count)
+// CTFontGetVerticalTranslationsForGlyphs is different on Snow Leopard. It returns values for a font-size of 1
+// without unitsPerEm applied. We have to apply a transform that scales up to the point size and that also
+// divides by unitsPerEm.
+static bool hasBrokenCTFontGetVerticalTranslationsForGlyphs()
{
+// Chromium runs the same binary on both Leopard and Snow Leopard, so the check has to happen at runtime.
+#if PLATFORM(CHROMIUM)
+ static bool isCached = false;
+ static bool result;
+
+ if (!isCached) {
+ SInt32 majorVersion = 0;
+ SInt32 minorVersion = 0;
+ Gestalt(gestaltSystemVersionMajor, &majorVersion);
+ Gestalt(gestaltSystemVersionMinor, &minorVersion);
+ result = majorVersion == 10 && minorVersion == 6;
+ isCached = true;
+ }
+ return result;
+#elif defined(BUILDING_ON_SNOW_LEOPARD)
+ return true;
+#else
+ return false;
+#endif
+}
+
+static void showGlyphsWithAdvances(const FloatPoint& point, const SimpleFontData* font, CGContextRef context, const CGGlyph* glyphs, const CGSize* advances, size_t count)
+{
+ CGContextSetTextPosition(context, point.x(), point.y());
+
const FontPlatformData& platformData = font->platformData();
if (!platformData.isColorBitmapFont()) {
CGAffineTransform savedMatrix;
- bool isVertical = font->orientation() == Vertical;
-
+ bool isVertical = font->platformData().orientation() == Vertical;
if (isVertical) {
CGAffineTransform rotateLeftTransform = CGAffineTransformMake(0, -1, 1, 0, 0, 0);
-
savedMatrix = CGContextGetTextMatrix(context);
CGAffineTransform runMatrix = CGAffineTransformConcat(savedMatrix, rotateLeftTransform);
- // Move start point to put glyphs into original region.
- runMatrix.tx = savedMatrix.tx + font->fontMetrics().ascent();
- runMatrix.ty = savedMatrix.ty + font->fontMetrics().descent();
CGContextSetTextMatrix(context, runMatrix);
- }
-
- CGContextShowGlyphsWithAdvances(context, glyphs, advances, count);
-
- if (isVertical)
+
+ CGAffineTransform translationsTransform;
+ if (hasBrokenCTFontGetVerticalTranslationsForGlyphs()) {
+ translationsTransform = CGAffineTransformMake(platformData.m_size, 0, 0, platformData.m_size, 0, 0);
+ translationsTransform = CGAffineTransformConcat(translationsTransform, rotateLeftTransform);
+ CGFloat unitsPerEm = CGFontGetUnitsPerEm(platformData.cgFont());
+ translationsTransform = CGAffineTransformConcat(translationsTransform, CGAffineTransformMakeScale(1 / unitsPerEm, 1 / unitsPerEm));
+ } else {
+ translationsTransform = rotateLeftTransform;
+ }
+ Vector<CGSize, 256> translations(count);
+ CTFontGetVerticalTranslationsForGlyphs(platformData.ctFont(), glyphs, translations.data(), count);
+
+ CGAffineTransform transform = CGAffineTransformInvert(CGContextGetTextMatrix(context));
+
+ CGPoint position = FloatPoint(point.x(), point.y() + font->fontMetrics().floatAscent(IdeographicBaseline) - font->fontMetrics().floatAscent());
+ Vector<CGPoint, 256> positions(count);
+ for (size_t i = 0; i < count; ++i) {
+ CGSize translation = CGSizeApplyAffineTransform(translations[i], translationsTransform);
+ positions[i] = CGPointApplyAffineTransform(CGPointMake(position.x - translation.width, position.y + translation.height), transform);
+ position.x += advances[i].width;
+ position.y += advances[i].height;
+ }
+ CGContextShowGlyphsAtPositions(context, glyphs, positions.data(), count);
CGContextSetTextMatrix(context, savedMatrix);
+ } else
+ CGContextShowGlyphsWithAdvances(context, glyphs, advances, count);
}
#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
else {
@@ -188,21 +232,15 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
float shadowTextX = point.x() + shadowOffset.width();
// If shadows are ignoring transforms, then we haven't applied the Y coordinate flip yet, so down is negative.
float shadowTextY = point.y() + shadowOffset.height() * (context->shadowsIgnoreTransforms() ? -1 : 1);
- CGContextSetTextPosition(cgContext, shadowTextX, shadowTextY);
- showGlyphsWithAdvances(font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
- if (font->syntheticBoldOffset()) {
- CGContextSetTextPosition(cgContext, shadowTextX + font->syntheticBoldOffset(), shadowTextY);
- showGlyphsWithAdvances(font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
- }
+ showGlyphsWithAdvances(FloatPoint(shadowTextX, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
+ if (font->syntheticBoldOffset())
+ showGlyphsWithAdvances(FloatPoint(shadowTextX + font->syntheticBoldOffset(), shadowTextY), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
context->setFillColor(fillColor, fillColorSpace);
}
- CGContextSetTextPosition(cgContext, point.x(), point.y());
- showGlyphsWithAdvances(font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
- if (font->syntheticBoldOffset()) {
- CGContextSetTextPosition(cgContext, point.x() + font->syntheticBoldOffset(), point.y());
- showGlyphsWithAdvances(font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
- }
+ showGlyphsWithAdvances(point, font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
+ if (font->syntheticBoldOffset())
+ showGlyphsWithAdvances(FloatPoint(point.x() + font->syntheticBoldOffset(), point.y()), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
if (hasSimpleShadow)
context->setShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
diff --git a/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp b/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
index fe2b33a..18d0dc5 100644
--- a/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
+++ b/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
@@ -39,7 +39,7 @@ namespace WebCore {
#ifndef BUILDING_ON_TIGER
static bool shouldUseCoreText(UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
- if (fontData->platformData().widthVariant() != RegularWidth || (fontData->orientation() == Vertical && !fontData->isBrokenIdeographFont())) {
+ if (fontData->platformData().widthVariant() != RegularWidth || fontData->hasVerticalGlyphs()) {
// Ideographs don't have a vertical variant or width variants.
for (unsigned i = 0; i < bufferLength; ++i) {
if (!Font::isCJKIdeograph(buffer[i]))
@@ -70,7 +70,7 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b
} else {
// We ask CoreText for possible vertical variant glyphs
RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull));
- RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(0)));
+ RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(0, fontData->hasVerticalGlyphs() ? Vertical : Horizontal)));
RetainPtr<CTLineRef> line(AdoptCF, CTLineCreateWithAttributedString(attributedString.get()));
CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
diff --git a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
index aaa250b..997c976 100644
--- a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
+++ b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
@@ -93,9 +93,14 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWi
, m_attrs(attrs)
, m_contextObj(0)
, m_texture(0)
+ , m_compositorTexture(0)
, m_fbo(0)
, m_depthStencilBuffer(0)
+ , m_layerComposited(false)
+ , m_internalColorFormat(0)
, m_boundFBO(0)
+ , m_activeTexture(0)
+ , m_boundTexture0(0)
, m_multisampleFBO(0)
, m_multisampleDepthStencilBuffer(0)
, m_multisampleColorBuffer(0)
@@ -166,6 +171,12 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWi
::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ ::glGenTextures(1, &m_compositorTexture);
+ ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture);
+ ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
::glBindTexture(GL_TEXTURE_2D, 0);
// create an FBO
@@ -215,6 +226,7 @@ GraphicsContext3D::~GraphicsContext3D()
if (m_contextObj) {
CGLSetCurrentContext(m_contextObj);
::glDeleteTextures(1, &m_texture);
+ ::glDeleteTextures(1, &m_compositorTexture);
if (m_attrs.antialias) {
::glDeleteRenderbuffersEXT(1, &m_multisampleColorBuffer);
if (m_attrs.stencil || m_attrs.depth)
diff --git a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
index 80bc94e..7bdc064 100644
--- a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
+++ b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
@@ -54,6 +54,8 @@ class WebCoreMovieObserver;
#endif
namespace WebCore {
+
+class ApplicationCacheResource;
class MediaPlayerPrivateQTKit : public MediaPlayerPrivateInterface {
public:
@@ -139,6 +141,7 @@ private:
void createQTMovie(const String& url);
void createQTMovie(NSURL *, NSDictionary *movieAttributes);
+ void createQTMovie(ApplicationCacheResource*);
enum MediaRenderingMode { MediaRenderingNone, MediaRenderingMovieView, MediaRenderingSoftwareRenderer, MediaRenderingMovieLayer };
MediaRenderingMode currentRenderingMode() const;
@@ -178,6 +181,8 @@ private:
virtual double maximumDurationToCacheMediaTime() const { return 5; }
virtual void setPrivateBrowsingMode(bool);
+
+ NSMutableDictionary* commonMovieAttributes();
MediaPlayer* m_player;
RetainPtr<QTMovie> m_qtMovie;
@@ -211,6 +216,7 @@ private:
double m_timeStartedPlaying;
double m_timeStoppedPlaying;
#endif
+ mutable FloatSize m_cachedNaturalSize;
};
}
diff --git a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
index ecb7d9f..400fdfb 100644
--- a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
+++ b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
@@ -29,11 +29,18 @@
#import "MediaPlayerPrivateQTKit.h"
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+#include "ApplicationCacheHost.h"
+#include "ApplicationCacheResource.h"
+#include "DocumentLoader.h"
+#endif
+
#ifdef BUILDING_ON_TIGER
#import "AutodrainedPool.h"
#endif
#import "BlockExceptions.h"
+#import "DocumentLoader.h"
#import "FrameView.h"
#import "GraphicsContext.h"
#import "KURL.h"
@@ -83,6 +90,7 @@ SOFT_LINK_POINTER(QTKit, QTMediaTypeText, NSString *)
SOFT_LINK_POINTER(QTKit, QTMediaTypeVideo, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieAskUnresolvedDataRefsAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieLoopsAttribute, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieDataAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieDataSizeAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieDidEndNotification, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieHasVideoAttribute, NSString *)
@@ -120,6 +128,7 @@ SOFT_LINK_POINTER(QTKit, QTMovieApertureModeAttribute, NSString *)
#define QTMediaTypeVideo getQTMediaTypeVideo()
#define QTMovieAskUnresolvedDataRefsAttribute getQTMovieAskUnresolvedDataRefsAttribute()
#define QTMovieLoopsAttribute getQTMovieLoopsAttribute()
+#define QTMovieDataAttribute getQTMovieDataAttribute()
#define QTMovieDataSizeAttribute getQTMovieDataSizeAttribute()
#define QTMovieDidEndNotification getQTMovieDidEndNotification()
#define QTMovieHasVideoAttribute getQTMovieHasVideoAttribute()
@@ -241,21 +250,26 @@ MediaPlayerPrivateQTKit::~MediaPlayerPrivateQTKit()
[m_objcObserver.get() disconnect];
}
-void MediaPlayerPrivateQTKit::createQTMovie(const String& url)
+NSMutableDictionary* MediaPlayerPrivateQTKit::commonMovieAttributes()
{
- NSURL *cocoaURL = KURL(ParsedURLString, url);
- NSMutableDictionary *movieAttributes = [NSMutableDictionary dictionaryWithObjectsAndKeys:
- cocoaURL, QTMovieURLAttribute,
- [NSNumber numberWithBool:m_player->preservesPitch()], QTMovieRateChangesPreservePitchAttribute,
- [NSNumber numberWithBool:YES], QTMoviePreventExternalURLLinksAttribute,
- [NSNumber numberWithBool:YES], QTSecurityPolicyNoCrossSiteAttribute,
- [NSNumber numberWithBool:NO], QTMovieAskUnresolvedDataRefsAttribute,
- [NSNumber numberWithBool:NO], QTMovieLoopsAttribute,
- [NSNumber numberWithBool:!m_privateBrowsing], @"QTMovieAllowPersistentCacheAttribute",
+ return [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithBool:m_player->preservesPitch()], QTMovieRateChangesPreservePitchAttribute,
+ [NSNumber numberWithBool:YES], QTMoviePreventExternalURLLinksAttribute,
+ [NSNumber numberWithBool:YES], QTSecurityPolicyNoCrossSiteAttribute,
+ [NSNumber numberWithBool:NO], QTMovieAskUnresolvedDataRefsAttribute,
+ [NSNumber numberWithBool:NO], QTMovieLoopsAttribute,
+ [NSNumber numberWithBool:!m_privateBrowsing], @"QTMovieAllowPersistentCacheAttribute",
#ifndef BUILDING_ON_TIGER
- QTMovieApertureModeClean, QTMovieApertureModeAttribute,
+ QTMovieApertureModeClean, QTMovieApertureModeAttribute,
#endif
- nil];
+ nil];
+}
+
+void MediaPlayerPrivateQTKit::createQTMovie(const String& url)
+{
+ NSURL *cocoaURL = KURL(ParsedURLString, url);
+ NSMutableDictionary *movieAttributes = commonMovieAttributes();
+ [movieAttributes setValue:cocoaURL forKey:QTMovieURLAttribute];
#if !defined(BUILDING_ON_LEOPARD)
CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings();
@@ -291,6 +305,33 @@ void MediaPlayerPrivateQTKit::createQTMovie(const String& url)
createQTMovie(cocoaURL, movieAttributes);
}
+void MediaPlayerPrivateQTKit::createQTMovie(ApplicationCacheResource* resource)
+{
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ ASSERT(resource);
+
+ NSMutableDictionary *movieAttributes = commonMovieAttributes();
+ [movieAttributes setObject:[NSNumber numberWithBool:YES] forKey:@"QTMovieOpenForPlaybackAttribute"];
+
+ // ApplicationCacheResources can supply either a data pointer, or a path to a locally cached
+ // flat file. We would prefer the path over the data, but QTKit can handle either:
+ String localPath = resource->path();
+ NSURL* cocoaURL = !localPath.isEmpty() ? [NSURL fileURLWithPath:localPath isDirectory:NO] : nil;
+ if (cocoaURL)
+ [movieAttributes setValue:cocoaURL forKey:QTMovieURLAttribute];
+ else {
+ NSData* movieData = resource->data()->createNSData();
+ [movieAttributes setValue:movieData forKey:QTMovieDataAttribute];
+ [movieData release];
+ }
+
+ createQTMovie(cocoaURL, movieAttributes);
+
+#else
+ ASSERT_NOT_REACHED();
+#endif
+}
+
static void disableComponentsOnce()
{
static bool sComponentsDisabled = false;
@@ -658,6 +699,14 @@ void MediaPlayerPrivateQTKit::loadInternal(const String& url)
[m_objcObserver.get() setDelayCallbacks:YES];
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : NULL;
+ ApplicationCacheHost* cacheHost = frame ? frame->loader()->documentLoader()->applicationCacheHost() : NULL;
+ ApplicationCacheResource* resource = NULL;
+ if (cacheHost && cacheHost->shouldLoadResourceFromApplicationCache(ResourceRequest(url), resource) && resource)
+ createQTMovie(resource);
+ else
+#endif
createQTMovie(url);
[m_objcObserver.get() loadStateChanged:nil];
@@ -827,8 +876,19 @@ IntSize MediaPlayerPrivateQTKit::naturalSize() const
// dimensions, aspect ratio, clean aperture, resolution, and so forth, as defined for the
// format used by the resource
- NSSize naturalSize = [[m_qtMovie.get() attributeForKey:QTMovieNaturalSizeAttribute] sizeValue];
- return IntSize(naturalSize.width * m_scaleFactor.width(), naturalSize.height * m_scaleFactor.height());
+ FloatSize naturalSize([[m_qtMovie.get() attributeForKey:QTMovieNaturalSizeAttribute] sizeValue]);
+ if (naturalSize.isEmpty() && m_isStreaming) {
+ // HTTP Live Streams will occasionally return {0,0} natural sizes while scrubbing.
+ // Work around this problem (<rdar://problem/9078563>) by returning the last valid
+ // cached natural size:
+ naturalSize = m_cachedNaturalSize;
+ } else {
+ // Unfortunately, due to another QTKit bug (<rdar://problem/9082071>) we won't get a sizeChanged
+ // event when this happens, so we must cache the last valid naturalSize here:
+ m_cachedNaturalSize = naturalSize;
+ }
+
+ return IntSize(naturalSize.width() * m_scaleFactor.width(), naturalSize.height() * m_scaleFactor.height());
}
bool MediaPlayerPrivateQTKit::hasVideo() const
diff --git a/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp b/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp
index 452bd54..832bb9d 100644
--- a/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp
+++ b/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp
@@ -39,15 +39,17 @@ using namespace std;
namespace WebCore {
-CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typesettingFeatures) const
+CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typesettingFeatures, FontOrientation orientation) const
{
unsigned key = typesettingFeatures + 1;
pair<HashMap<unsigned, RetainPtr<CFDictionaryRef> >::iterator, bool> addResult = m_CFStringAttributes.add(key, RetainPtr<CFDictionaryRef>());
RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.first->second;
if (!addResult.second)
return attributesDictionary.get();
+
+ bool treatLineAsVertical = orientation == Vertical;
- bool allowLigatures = (orientation() == Horizontal && platformData().allowsLigatures()) || (typesettingFeatures & Ligatures);
+ bool allowLigatures = (!treatLineAsVertical && platformData().allowsLigatures()) || (typesettingFeatures & Ligatures);
static const int ligaturesNotAllowedValue = 0;
static CFNumberRef ligaturesNotAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesNotAllowedValue);
@@ -60,13 +62,13 @@ CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typese
static CFNumberRef kerningAdjustment = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &kerningAdjustmentValue);
static const void* keysWithKerningDisabled[] = { kCTFontAttributeName, kCTKernAttributeName, kCTLigatureAttributeName, kCTVerticalFormsAttributeName };
const void* valuesWithKerningDisabled[] = { platformData().ctFont(), kerningAdjustment, allowLigatures
- ? ligaturesAllowed : ligaturesNotAllowed, orientation() == Vertical ? kCFBooleanTrue : kCFBooleanFalse };
+ ? ligaturesAllowed : ligaturesNotAllowed, treatLineAsVertical ? kCFBooleanTrue : kCFBooleanFalse };
attributesDictionary.adoptCF(CFDictionaryCreate(0, keysWithKerningDisabled, valuesWithKerningDisabled,
WTF_ARRAY_LENGTH(keysWithKerningDisabled), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
} else {
// By omitting the kCTKernAttributeName attribute, we get Core Text's standard kerning.
static const void* keysWithKerningEnabled[] = { kCTFontAttributeName, kCTLigatureAttributeName, kCTVerticalFormsAttributeName };
- const void* valuesWithKerningEnabled[] = { platformData().ctFont(), allowLigatures ? ligaturesAllowed : ligaturesNotAllowed, orientation() == Vertical ? kCFBooleanTrue : kCFBooleanFalse };
+ const void* valuesWithKerningEnabled[] = { platformData().ctFont(), allowLigatures ? ligaturesAllowed : ligaturesNotAllowed, treatLineAsVertical ? kCFBooleanTrue : kCFBooleanFalse };
attributesDictionary.adoptCF(CFDictionaryCreate(0, keysWithKerningEnabled, valuesWithKerningEnabled,
WTF_ARRAY_LENGTH(keysWithKerningEnabled), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
}
diff --git a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
index 3094498..cd34000 100644
--- a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
+++ b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
@@ -259,49 +259,32 @@ void SimpleFontData::platformInit()
descent = 3;
}
- if (m_orientation == Vertical) {
- // Ignore vertical orientation when the font doesn't support vertical metrics.
+ if (platformData().orientation() == Vertical && !isTextOrientationFallback()) {
// The check doesn't look neat but this is what AppKit does for vertical writing...
RetainPtr<CFArrayRef> tableTags(AdoptCF, CTFontCopyAvailableTables(m_platformData.ctFont(), kCTFontTableOptionExcludeSynthetic));
CFIndex numTables = CFArrayGetCount(tableTags.get());
- bool found = false;
for (CFIndex index = 0; index < numTables; ++index) {
CTFontTableTag tag = (CTFontTableTag)(uintptr_t)CFArrayGetValueAtIndex(tableTags.get(), index);
if (tag == kCTFontTableVhea || tag == kCTFontTableVORG) {
- found = true;
+ m_hasVerticalGlyphs = true;
break;
}
}
-
- if (found == false)
- m_orientation = Horizontal;
}
float xHeight;
- // Measure the actual character "x", because AppKit synthesizes X height rather than getting it from the font.
- // Unfortunately, NSFont will round this for us so we don't quite get the right value.
- GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
- NSGlyph xGlyph = glyphPageZero ? glyphPageZero->glyphDataForCharacter('x').glyph : 0;
- if (xGlyph) {
- CGRect xBox = platformBoundsForGlyph(xGlyph);
- // Use the maximum of either width or height because "x" is nearly square
- // and web pages that foolishly use this metric for width will be laid out
- // poorly if we return an accurate height. Classic case is Times 13 point,
- // which has an "x" that is 7x6 pixels.
- xHeight = static_cast<float>(max(CGRectGetMaxX(xBox), -CGRectGetMinY(xBox)));
- } else {
-#ifndef BUILDING_ON_TIGER
- xHeight = static_cast<float>(CGFontGetXHeight(m_platformData.cgFont())) / unitsPerEm;
-#else
- xHeight = m_platformData.font() ? [m_platformData.font() xHeight] : 0;
-#endif
- // CGFontGetXHeight() returns a wrong value for "Apple Symbols" font (a float close to 0, but not strictly 0).
- // The following code makes a guess for xHeight in that case.
- // The int cast is a workaround for the "almost" zero value returned by CGFontGetXHeight().
- if (!static_cast<int>(xHeight) && ascent)
- xHeight = 2 * ascent / 3;
- }
+ if (platformData().orientation() == Horizontal) {
+ // Measure the actual character "x", since it's possible for it to extend below the baseline, and we need the
+ // reported x-height to only include the portion of the glyph that is above the baseline.
+ GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
+ NSGlyph xGlyph = glyphPageZero ? glyphPageZero->glyphDataForCharacter('x').glyph : 0;
+ if (xGlyph)
+ xHeight = -CGRectGetMinY(platformBoundsForGlyph(xGlyph));
+ else
+ xHeight = scaleEmToUnits(CGFontGetXHeight(m_platformData.cgFont()), unitsPerEm) * pointSize;
+ } else
+ xHeight = verticalRightOrientationFontData()->fontMetrics().xHeight();
m_fontMetrics.setUnitsPerEm(unitsPerEm);
m_fontMetrics.setAscent(ascent);
@@ -474,17 +457,8 @@ void SimpleFontData::determinePitch()
FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const
{
FloatRect boundingBox;
-#ifndef BUILDING_ON_TIGER
- boundingBox = CTFontGetBoundingRectsForGlyphs(m_platformData.ctFont(),
- orientation() == Vertical ? kCTFontVerticalOrientation : kCTFontHorizontalOrientation, &glyph, 0, 1);
+ boundingBox = CTFontGetBoundingRectsForGlyphs(m_platformData.ctFont(), platformData().orientation() == Vertical ? kCTFontVerticalOrientation : kCTFontHorizontalOrientation, &glyph, 0, 1);
boundingBox.setY(-boundingBox.maxY());
-#else
- // FIXME: Custom fonts don't have NSFonts, so this function doesn't compute correct bounds for these on Tiger.
- if (!m_platformData.font())
- return boundingBox;
- boundingBox = [m_platformData.font() boundingRectForGlyph:glyph];
- boundingBox.setY(-boundingBox.maxY());
-#endif
if (m_syntheticBoldOffset)
boundingBox.setWidth(boundingBox.width() + m_syntheticBoldOffset);
@@ -494,7 +468,7 @@ FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
CGSize advance;
- if (orientation() == Horizontal || m_isBrokenIdeographFont) {
+ if (platformData().orientation() == Horizontal || m_isBrokenIdeographFallback) {
NSFont* font = platformData().font();
float pointSize = platformData().m_size;
CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize);
diff --git a/Source/WebCore/platform/graphics/mac/WebLayer.h b/Source/WebCore/platform/graphics/mac/WebLayer.h
index 30bf55b..2e9bea0 100644
--- a/Source/WebCore/platform/graphics/mac/WebLayer.h
+++ b/Source/WebCore/platform/graphics/mac/WebLayer.h
@@ -32,6 +32,7 @@
namespace WebCore {
class GraphicsLayer;
+ class PlatformCALayer;
class PlatformCALayerClient;
}
@@ -48,7 +49,7 @@ namespace WebCore {
@end
// Functions allows us to share implementation across WebTiledLayer and WebLayer
-void drawLayerContents(CGContextRef, CALayer *, WebCore::PlatformCALayerClient*);
+void drawLayerContents(CGContextRef, CALayer *, WebCore::PlatformCALayer*);
void setLayerNeedsDisplayInRect(CALayer *, WebCore::PlatformCALayerClient*, CGRect);
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/mac/WebLayer.mm b/Source/WebCore/platform/graphics/mac/WebLayer.mm
index 414a75f..c9705d0 100644
--- a/Source/WebCore/platform/graphics/mac/WebLayer.mm
+++ b/Source/WebCore/platform/graphics/mac/WebLayer.mm
@@ -40,8 +40,9 @@ using namespace WebCore;
@implementation WebLayer
-void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCALayerClient* layerContents)
+void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCALayer* platformLayer)
{
+ WebCore::PlatformCALayerClient* layerContents = platformLayer->owner();
if (!layerContents)
return;
@@ -62,6 +63,7 @@ void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCA
GraphicsContext graphicsContext(context);
graphicsContext.setIsCALayerContext(true);
+ graphicsContext.setIsAcceleratedContext(platformLayer->acceleratesDrawing());
if (!layerContents->platformCALayerContentsOpaque()) {
// Turn off font smoothing to improve the appearance of text rendered onto a transparent background.
@@ -167,7 +169,7 @@ void setLayerNeedsDisplayInRect(CALayer *layer, WebCore::PlatformCALayerClient*
{
PlatformCALayer* layer = PlatformCALayer::platformCALayer(self);
if (layer)
- drawLayerContents(context, self, layer->owner());
+ drawLayerContents(context, self, layer);
}
@end // implementation WebLayer
diff --git a/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm b/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm
index e9fa5b7..9bcdd54 100644
--- a/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm
+++ b/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm
@@ -83,7 +83,7 @@ using namespace WebCore;
{
PlatformCALayer* layer = PlatformCALayer::platformCALayer(self);
if (layer)
- drawLayerContents(context, self, layer->owner());
+ drawLayerContents(context, self, layer);
}
@end // implementation WebTiledLayer
diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
index c224e20..f831550 100644
--- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
+++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
@@ -38,6 +38,7 @@
#include "GraphicsContext.h"
#include "HTMLCanvasElement.h"
#include "ImageBuffer.h"
+#include "ImageData.h"
#include "Int32Array.h"
#include "NotImplemented.h"
#include "Uint8Array.h"
@@ -53,11 +54,12 @@ namespace WebCore {
void GraphicsContext3D::validateAttributes()
{
- const char* extensions = reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS));
+ Extensions3D* extensions = getExtensions();
if (m_attrs.stencil) {
- if (std::strstr(extensions, "GL_EXT_packed_depth_stencil")) {
- if (!m_attrs.depth)
- m_attrs.depth = true;
+ if (extensions->supports("GL_EXT_packed_depth_stencil")) {
+ extensions->ensureEnabled("GL_EXT_packed_depth_stencil");
+ // Force depth if stencil is true.
+ m_attrs.depth = true;
} else
m_attrs.stencil = false;
}
@@ -67,24 +69,16 @@ void GraphicsContext3D::validateAttributes()
const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR));
if (!std::strstr(vendor, "NVIDIA"))
isValidVendor = false;
- if (!isValidVendor || !std::strstr(extensions, "GL_EXT_framebuffer_multisample"))
+ if (!isValidVendor || !extensions->supports("GL_ANGLE_framebuffer_multisample"))
m_attrs.antialias = false;
+ else
+ extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample");
}
- // FIXME: instead of enforcing premultipliedAlpha = true, implement the
- // correct behavior when premultipliedAlpha = false is requested.
- m_attrs.premultipliedAlpha = true;
}
-void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* context)
+void GraphicsContext3D::readRenderingResults(unsigned char *pixels, int pixelsSize)
{
- HTMLCanvasElement* canvas = context->canvas();
- ImageBuffer* imageBuffer = canvas->buffer();
-
- int rowBytes = m_currentWidth * 4;
- int totalBytes = rowBytes * m_currentHeight;
-
- OwnArrayPtr<unsigned char> pixels = adoptArrayPtr(new unsigned char[totalBytes]);
- if (!pixels)
+ if (pixelsSize < m_currentWidth * m_currentHeight * 4)
return;
makeContextCurrent();
@@ -111,18 +105,62 @@ void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* co
mustRestorePackAlignment = true;
}
- ::glReadPixels(0, 0, m_currentWidth, m_currentHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels.get());
+ ::glReadPixels(0, 0, m_currentWidth, m_currentHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
if (mustRestorePackAlignment)
::glPixelStorei(GL_PACK_ALIGNMENT, packAlignment);
if (mustRestoreFBO)
::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO);
+}
+
+void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* context)
+{
+ HTMLCanvasElement* canvas = context->canvas();
+ ImageBuffer* imageBuffer = canvas->buffer();
+
+ int rowBytes = m_currentWidth * 4;
+ int totalBytes = rowBytes * m_currentHeight;
+
+ OwnArrayPtr<unsigned char> pixels = adoptArrayPtr(new unsigned char[totalBytes]);
+ if (!pixels)
+ return;
+
+ readRenderingResults(pixels.get(), totalBytes);
+
+ if (!m_attrs.premultipliedAlpha) {
+ for (int i = 0; i < totalBytes; i += 4) {
+ // Premultiply alpha
+ pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255);
+ pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255);
+ pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255);
+ }
+ }
paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight,
canvas->width(), canvas->height(), imageBuffer->context()->platformContext());
}
+PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData()
+{
+ // Reading premultiplied alpha would involve unpremultiplying, which is
+ // lossy
+ if (m_attrs.premultipliedAlpha)
+ return 0;
+
+ RefPtr<ImageData> imageData = ImageData::create(IntSize(m_currentWidth, m_currentHeight));
+ unsigned char* pixels = imageData->data()->data()->data();
+ int totalBytes = 4 * m_currentWidth * m_currentHeight;
+
+ readRenderingResults(pixels, totalBytes);
+
+ // Convert to RGBA
+ for (int i = 0; i < totalBytes; i += 4)
+ std::swap(pixels[i], pixels[i + 2]);
+
+ return imageData.release();
+}
+
void GraphicsContext3D::reshape(int width, int height)
{
if (!m_contextObj)
@@ -135,19 +173,23 @@ void GraphicsContext3D::reshape(int width, int height)
m_currentHeight = height;
makeContextCurrent();
-
- GLuint internalColorFormat, colorFormat, internalDepthStencilFormat = 0;
+ validateAttributes();
+
+ GLuint colorFormat, internalDepthStencilFormat = 0;
if (m_attrs.alpha) {
- internalColorFormat = GL_RGBA8;
+ m_internalColorFormat = GL_RGBA8;
colorFormat = GL_RGBA;
} else {
- internalColorFormat = GL_RGB8;
+ m_internalColorFormat = GL_RGB8;
colorFormat = GL_RGB;
}
if (m_attrs.stencil || m_attrs.depth) {
// We don't allow the logic where stencil is required and depth is not.
- // See GraphicsContext3D constructor.
- if (m_attrs.stencil && m_attrs.depth)
+ // See GraphicsContext3D::validateAttributes.
+
+ Extensions3D* extensions = getExtensions();
+ // Use a 24 bit depth buffer where we know we have it
+ if (extensions->supports("GL_EXT_packed_depth_stencil"))
internalDepthStencilFormat = GL_DEPTH24_STENCIL8_EXT;
else
internalDepthStencilFormat = GL_DEPTH_COMPONENT;
@@ -167,7 +209,7 @@ void GraphicsContext3D::reshape(int width, int height)
mustRestoreFBO = true;
}
::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleColorBuffer);
- ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, internalColorFormat, width, height);
+ ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, m_internalColorFormat, width, height);
::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_multisampleColorBuffer);
if (m_attrs.stencil || m_attrs.depth) {
::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer);
@@ -190,8 +232,10 @@ void GraphicsContext3D::reshape(int width, int height)
::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
}
::glBindTexture(GL_TEXTURE_2D, m_texture);
- ::glTexImage2D(GL_TEXTURE_2D, 0, internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0);
+ ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0);
::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0);
+ ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture);
+ ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0);
::glBindTexture(GL_TEXTURE_2D, 0);
if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth)) {
::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthStencilBuffer);
@@ -278,19 +322,29 @@ IntSize GraphicsContext3D::getInternalFramebufferSize()
void GraphicsContext3D::prepareTexture()
{
+ if (m_layerComposited)
+ return;
makeContextCurrent();
if (m_attrs.antialias) {
::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO);
::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo);
::glBlitFramebufferEXT(0, 0, m_currentWidth, m_currentHeight, 0, 0, m_currentWidth, m_currentHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
- ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO);
}
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
+ ::glActiveTexture(0);
+ ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture);
+ ::glCopyTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, 0, 0, m_currentWidth, m_currentHeight, 0);
+ ::glBindTexture(GL_TEXTURE_2D, m_boundTexture0);
+ ::glActiveTexture(m_activeTexture);
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO);
::glFinish();
+ m_layerComposited = true;
}
void GraphicsContext3D::activeTexture(GC3Denum texture)
{
makeContextCurrent();
+ m_activeTexture = texture;
::glActiveTexture(texture);
}
@@ -340,6 +394,8 @@ void GraphicsContext3D::bindRenderbuffer(GC3Denum target, Platform3DObject rende
void GraphicsContext3D::bindTexture(GC3Denum target, Platform3DObject texture)
{
makeContextCurrent();
+ if (m_activeTexture && target == GL_TEXTURE_2D)
+ m_boundTexture0 = texture;
::glBindTexture(target, texture);
}
@@ -1442,6 +1498,21 @@ void GraphicsContext3D::synthesizeGLError(GC3Denum error)
m_syntheticErrors.add(error);
}
+void GraphicsContext3D::markContextChanged()
+{
+ m_layerComposited = false;
+}
+
+void GraphicsContext3D::markLayerComposited()
+{
+ m_layerComposited = true;
+}
+
+bool GraphicsContext3D::layerComposited() const
+{
+ return m_layerComposited;
+}
+
Extensions3D* GraphicsContext3D::getExtensions()
{
if (!m_extensions)
diff --git a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp
index 2e2082d..9765937 100644
--- a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp
+++ b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp
@@ -21,11 +21,11 @@
#include "TextureMapperGL.h"
#include "GraphicsContext.h"
-#include "HashMap.h"
#include "Image.h"
-#include "PassRefPtr.h"
-#include "RefCounted.h"
#include "Timer.h"
+#include <wtf/HashMap.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
#if defined(TEXMAP_OPENGL_ES_2)
#include <GLES2/gl2.h>
diff --git a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.h b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.h
index 8035abf..92c5198 100644
--- a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.h
+++ b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.h
@@ -24,8 +24,8 @@
#include "FloatQuad.h"
#include "IntSize.h"
+#include "TextureMapper.h"
#include "TransformationMatrix.h"
-#include "texmap/TextureMapper.h"
namespace WebCore {
diff --git a/Source/WebCore/platform/graphics/openvg/PathOpenVG.cpp b/Source/WebCore/platform/graphics/openvg/PathOpenVG.cpp
index 39a4b06..95df242 100644
--- a/Source/WebCore/platform/graphics/openvg/PathOpenVG.cpp
+++ b/Source/WebCore/platform/graphics/openvg/PathOpenVG.cpp
@@ -169,7 +169,7 @@ FloatRect Path::boundingRect() const
return FloatRect(FloatPoint(minX, minY), FloatSize(width, height));
}
-FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
+FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const
{
notImplemented();
@@ -464,7 +464,7 @@ void Path::transform(const AffineTransform& transformation)
// functions and Path::apply() doesn't really work as long as we rely on VGPath
// as primary path storage.
-float Path::length()
+float Path::length() const
{
m_path->makeCompatibleContextCurrent();
VGfloat length = vgPathLength(m_path->vgPath(), 0, vgGetParameteri(m_path->vgPath(), VG_PATH_NUM_SEGMENTS));
@@ -472,7 +472,7 @@ float Path::length()
return length;
}
-FloatPoint Path::pointAtLength(float length, bool& ok)
+FloatPoint Path::pointAtLength(float length, bool& ok) const
{
VGfloat x = 0, y = 0;
m_path->makeCompatibleContextCurrent();
@@ -483,7 +483,7 @@ FloatPoint Path::pointAtLength(float length, bool& ok)
return FloatPoint(x, y);
}
-float Path::normalAngleAtLength(float length, bool& ok)
+float Path::normalAngleAtLength(float length, bool& ok) const
{
VGfloat tangentX, tangentY;
m_path->makeCompatibleContextCurrent();
diff --git a/Source/WebCore/platform/graphics/pango/FontCustomPlatformDataPango.cpp b/Source/WebCore/platform/graphics/pango/FontCustomPlatformDataPango.cpp
index f9d36d3..deff9f7 100644
--- a/Source/WebCore/platform/graphics/pango/FontCustomPlatformDataPango.cpp
+++ b/Source/WebCore/platform/graphics/pango/FontCustomPlatformDataPango.cpp
@@ -30,7 +30,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
{
}
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode)
{
return FontPlatformData(m_fontFace, size, bold, italic);
}
diff --git a/Source/WebCore/platform/graphics/pango/FontPlatformData.h b/Source/WebCore/platform/graphics/pango/FontPlatformData.h
index 2929a3f..180d23b 100644
--- a/Source/WebCore/platform/graphics/pango/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/pango/FontPlatformData.h
@@ -74,7 +74,7 @@ public:
unsigned hash() const
{
uintptr_t hashCodes[1] = { reinterpret_cast<uintptr_t>(m_scaledFont) };
- return WTF::StringHasher::createBlobHash<sizeof(hashCodes)>(hashCodes);
+ return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
}
bool operator==(const FontPlatformData&) const;
diff --git a/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp b/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp
index dcea72f..3adc93f 100644
--- a/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp
@@ -30,6 +30,7 @@
#include "Extensions3DQt.h"
#include "GraphicsContext3D.h"
+#include <QGLContext>
namespace WebCore {
diff --git a/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h
index e8441d2..3996d22 100644
--- a/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h
+++ b/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h
@@ -25,6 +25,7 @@
#include "FontOrientation.h"
#include "FontRenderingMode.h"
#include "FontWidthVariant.h"
+#include "TextOrientation.h"
#include <wtf/FastAllocBase.h>
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
@@ -43,7 +44,8 @@ public:
// for use with QFontDatabase::addApplicationFont/removeApplicationFont
int m_handle;
- FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight,
+ FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
static bool supportsFormat(const String&);
};
diff --git a/Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp b/Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp
index ec8747d..20f161a 100644
--- a/Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp
@@ -34,7 +34,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
QFontDatabase::removeApplicationFont(m_handle);
}
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode)
{
QFont font;
font.setFamily(QFontDatabase::applicationFontFamilies(m_handle)[0]);
diff --git a/Source/WebCore/platform/graphics/qt/FontPlatformData.h b/Source/WebCore/platform/graphics/qt/FontPlatformData.h
index 32e8a2d..4a92acf 100644
--- a/Source/WebCore/platform/graphics/qt/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/qt/FontPlatformData.h
@@ -141,6 +141,7 @@ public:
}
FontOrientation orientation() const { return Horizontal; } // FIXME: Implement.
+ void setOrientation(FontOrientation) { } // FIXME: Implement.
unsigned hash() const;
diff --git a/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp b/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
index 185ae85..95dabd5 100644
--- a/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
@@ -73,9 +73,7 @@ FontPlatformData::FontPlatformData(const FontDescription& description, const Ato
font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing);
const bool smallCaps = description.smallCaps();
font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase);
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
font.setStyleStrategy(QFont::ForceIntegerMetrics);
-#endif
m_data->bold = font.bold();
// WebKit allows font size zero but QFont does not. We will return
diff --git a/Source/WebCore/platform/graphics/qt/FontQt.cpp b/Source/WebCore/platform/graphics/qt/FontQt.cpp
index 646cd0e..3fe90a4 100644
--- a/Source/WebCore/platform/graphics/qt/FontQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/FontQt.cpp
@@ -169,21 +169,16 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
p->restore();
return;
}
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
int skipWidth = QFontMetrics(font).width(string, from, Qt::TextBypassShaping);
pt.setX(pt.x() + skipWidth);
string = fromRawDataWithoutRef(sanitized, from, to - from);
-#endif
}
p->setFont(font);
int flags = run.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
- // See QWebPagePrivate::QWebPagePrivate() where the default path is set to Complex for Qt 4.6 and earlier.
if (!isComplexText && !(ctx->textDrawingMode() & TextModeStroke))
flags |= Qt::TextBypassShaping;
-#endif
QPainterPath textStrokePath;
if (ctx->textDrawingMode() & TextModeStroke)
@@ -200,11 +195,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
p->restore();
} else {
QFontMetrics fm(font);
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string, -1, flags), fm.height());
-#else
- QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string), fm.height());
-#endif
QPainter* shadowPainter = ctxShadow->beginShadowLayer(ctx, boundingRect);
if (shadowPainter) {
// Since it will be blurred anyway, we don't care about render hints.
@@ -221,11 +212,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
p->translate(-ctxShadow->offset());
} else {
QFontMetrics fm(font);
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string, -1, flags), fm.height());
-#else
- QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string), fm.height());
-#endif
QPainter* shadowPainter = ctxShadow->beginShadowLayer(ctx, boundingRect);
if (shadowPainter) {
// Since it will be blurred anyway, we don't care about render hints.
@@ -250,11 +237,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
void Font::drawSimpleText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
{
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
drawTextCommon(ctx, run, point, from, to, font(), /* isComplexText = */false);
-#else
- Q_ASSERT(false);
-#endif
}
void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
@@ -295,7 +278,6 @@ float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer
if (!primaryFont()->platformData().size())
return 0;
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
if (!run.length())
return 0;
@@ -309,10 +291,6 @@ float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer
w -= m_wordSpacing;
return w + run.expansion();
-#else
- Q_ASSERT(false);
- return 0;
-#endif
}
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const
@@ -339,7 +317,6 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
int Font::offsetForPositionForSimpleText(const TextRun& run, float position, bool includePartialGlyphs) const
{
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
String sanitized = Font::normalizeSpaces(run.characters(), run.length());
QString string = fromRawDataWithoutRef(sanitized);
@@ -359,10 +336,6 @@ int Font::offsetForPositionForSimpleText(const TextRun& run, float position, boo
} while (++curPos < string.size());
return curPos;
-#else
- Q_ASSERT(false);
- return 0;
-#endif
}
int Font::offsetForPositionForComplexText(const TextRun& run, float position, bool) const
@@ -377,7 +350,6 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float position, bo
FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const
{
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
String sanitized = Font::normalizeSpaces(run.characters(), run.length());
QString wholeText = fromRawDataWithoutRef(sanitized);
QString selectedText = fromRawDataWithoutRef(sanitized, from, qMin(to - from, wholeText.length() - from));
@@ -386,10 +358,6 @@ FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint&
int width = QFontMetrics(font()).width(selectedText, -1, Qt::TextBypassShaping);
return FloatRect(pt.x() + startX, pt.y(), width, h);
-#else
- Q_ASSERT(false);
- return FloatRect();
-#endif
}
FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const
diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
index b849214..4daa4dc 100644
--- a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
@@ -27,10 +27,14 @@
#include "HTMLCanvasElement.h"
#include "HostWindow.h"
#include "ImageBuffer.h"
+#include "ImageData.h"
#include "NotImplemented.h"
#include "QWebPageClient.h"
+#include "qwebpage.h"
#include <QAbstractScrollArea>
+#include <QGraphicsObject>
#include <QGLContext>
+#include <QStyleOptionGraphicsItem>
#include <wtf/UnusedParam.h>
#include <wtf/text/CString.h>
@@ -42,6 +46,10 @@ namespace WebCore {
typedef char GLchar;
#endif
+#if !defined(GL_DEPTH24_STENCIL8)
+#define GL_DEPTH24_STENCIL8 0x88F0
+#endif
+
#if !defined(APIENTRY)
#define APIENTRY
#endif
@@ -145,13 +153,17 @@ typedef void (APIENTRY* glVertexAttrib4fType) (GLuint, const GLfloat, const GLfl
typedef void (APIENTRY* glVertexAttrib4fvType) (GLuint, const GLfloat*);
typedef void (APIENTRY* glVertexAttribPointerType) (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid*);
-class GraphicsContext3DInternal {
+class GraphicsContext3DInternal : public QGraphicsObject {
public:
GraphicsContext3DInternal(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow);
~GraphicsContext3DInternal();
- bool isContextValid() { return m_contextValid; }
- QGLWidget* getOwnerGLWidget(QWebPageClient* webPageClient);
+ bool isValid() { return m_valid; }
+
+ QGLWidget* getViewportGLWidget();
+ void reshape(int width, int height);
+ void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*);
+ QRectF boundingRect() const;
glActiveTextureType activeTexture;
glAttachShaderType attachShader;
@@ -247,11 +259,13 @@ public:
GraphicsContext3D::Attributes m_attrs;
HostWindow* m_hostWindow;
QGLWidget* m_glWidget;
+ QGLWidget* m_viewportGLWidget;
+ QRectF m_boundingRect;
GLuint m_texture;
- GLuint m_mainFbo;
+ GLuint m_canvasFbo;
GLuint m_currentFbo;
GLuint m_depthBuffer;
- QImage m_pixels;
+ bool m_layerComposited;
ListHashSet<unsigned int> m_syntheticErrors;
OwnPtr<Extensions3DQt> m_extensions;
@@ -259,7 +273,7 @@ public:
private:
void* getProcAddress(const String& proc);
- bool m_contextValid;
+ bool m_valid;
};
#if defined (QT_OPENGL_ES_2)
@@ -281,39 +295,37 @@ GraphicsContext3DInternal::GraphicsContext3DInternal(GraphicsContext3D::Attribut
: m_attrs(attrs)
, m_hostWindow(hostWindow)
, m_glWidget(0)
+ , m_viewportGLWidget(0)
, m_texture(0)
- , m_mainFbo(0)
+ , m_canvasFbo(0)
, m_currentFbo(0)
, m_depthBuffer(0)
- , m_contextValid(true)
+ , m_layerComposited(false)
+ , m_valid(true)
{
- QWebPageClient* webPageClient = hostWindow->platformPageClient();
- QGLWidget* ownerGLWidget = getOwnerGLWidget(webPageClient);
+ m_viewportGLWidget = getViewportGLWidget();
- if (ownerGLWidget)
- m_glWidget = new QGLWidget(0, ownerGLWidget);
- else {
- QGLFormat format;
- format.setDepth(true);
- format.setSampleBuffers(true);
- format.setStencil(false);
-
- m_glWidget = new QGLWidget(format);
- }
+ if (m_viewportGLWidget)
+ m_glWidget = new QGLWidget(0, m_viewportGLWidget);
+ else
+ m_glWidget = new QGLWidget();
if (!m_glWidget->isValid()) {
- LOG_ERROR("GraphicsContext3D: QGLWidget does not have a valid context");
- m_contextValid = false;
+ LOG_ERROR("GraphicsContext3D: QGLWidget initialization failed.");
+ m_valid = false;
return;
}
-
- QGLFormat format = m_glWidget->format();
- m_attrs.alpha = format.alpha();
- m_attrs.depth = format.depth();
- m_attrs.stencil = format.stencil();
+ // Geometry can be set to zero because m_glWidget is used only for its QGLContext.
+ m_glWidget->setGeometry(0, 0, 0, 0);
+
+#if defined(QT_OPENGL_ES_2)
+ m_attrs.stencil = false;
+#else
+ if (m_attrs.stencil)
+ m_attrs.depth = true;
+#endif
m_attrs.antialias = false;
- m_attrs.premultipliedAlpha = true;
m_glWidget->makeCurrent();
@@ -408,60 +420,165 @@ GraphicsContext3DInternal::GraphicsContext3DInternal(GraphicsContext3D::Attribut
vertexAttrib4fv = GET_PROC_ADDRESS(glVertexAttrib4fv);
vertexAttribPointer = GET_PROC_ADDRESS(glVertexAttribPointer);
- if (!m_contextValid) {
+ if (!m_valid) {
LOG_ERROR("GraphicsContext3D: All needed OpenGL extensions are not available");
- m_contextValid = false;
return;
}
+ // Create buffers for the canvas FBO.
+ genFramebuffers(/* count */ 1, &m_canvasFbo);
+
glGenTextures(1, &m_texture);
glBindTexture(GraphicsContext3D::TEXTURE_2D, m_texture);
glTexParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
glTexParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
glTexParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
glTexParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
- glTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0);
glBindTexture(GraphicsContext3D::TEXTURE_2D, 0);
- genFramebuffers(/* count */ 1, &m_mainFbo);
- m_currentFbo = m_mainFbo;
+ if (m_attrs.depth)
+ genRenderbuffers(/* count */ 1, &m_depthBuffer);
+
+ // Bind canvas FBO and set initial clear color to black.
+ m_currentFbo = m_canvasFbo;
+ bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_canvasFbo);
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+}
+
+GraphicsContext3DInternal::~GraphicsContext3DInternal()
+{
+ delete m_glWidget;
+ m_glWidget = 0;
+}
+
+QGLWidget* GraphicsContext3DInternal::getViewportGLWidget()
+{
+ QWebPageClient* webPageClient = m_hostWindow->platformPageClient();
+ if (!webPageClient)
+ return 0;
+
+ QAbstractScrollArea* scrollArea = qobject_cast<QAbstractScrollArea*>(webPageClient->ownerWidget());
+ if (scrollArea)
+ return qobject_cast<QGLWidget*>(scrollArea->viewport());
+
+ return 0;
+}
+
+static inline quint32 swapBgrToRgb(quint32 pixel)
+{
+ return ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00);
+}
+
+void GraphicsContext3DInternal::reshape(int width, int height)
+{
+ if (width == m_boundingRect.width() && height == m_boundingRect.height())
+ return;
+
+ m_boundingRect = QRectF(QPointF(0, 0), QSizeF(width, height));
+
+ m_glWidget->makeCurrent();
- bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_mainFbo);
+ // Create color buffer
+ glBindTexture(GraphicsContext3D::TEXTURE_2D, m_texture);
+ if (m_attrs.alpha)
+ glTexImage2D(GraphicsContext3D::TEXTURE_2D, /* level */ 0, GraphicsContext3D::RGBA, width, height, /* border */ 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, /* data */ 0);
+ else
+ glTexImage2D(GraphicsContext3D::TEXTURE_2D, /* level */ 0, GraphicsContext3D::RGB, width, height, /* border */ 0, GraphicsContext3D::RGB, GraphicsContext3D::UNSIGNED_BYTE, /* data */ 0);
+ glBindTexture(GraphicsContext3D::TEXTURE_2D, 0);
- genRenderbuffers(/* count */ 1, &m_depthBuffer);
- bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthBuffer);
+ if (m_attrs.depth) {
+ // Create depth and stencil buffers.
+ bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthBuffer);
#if defined(QT_OPENGL_ES_2)
- renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, /* width */ 1, /* height */ 1);
+ renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, width, height);
#else
- renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT, /* width */ 1, /* height */ 1);
+ if (m_attrs.stencil)
+ renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
+ else
+ renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT, width, height);
#endif
+ bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
+ }
- bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
-
+ // Construct canvas FBO.
+ bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_canvasFbo);
framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_texture, 0);
- framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer);
- glClearColor(/* red */ 0, /* green */ 0, /* blue */ 0, /* alpha */ 0);
+ if (m_attrs.depth)
+ framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer);
+#if !defined(QT_OPENGL_ES_2)
+ if (m_attrs.stencil)
+ framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer);
+#endif
- if (checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
- LOG_ERROR("GraphicsContext3D: Wasn't able to create the main framebuffer");
- m_contextValid = false;
+ GLenum status = checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER);
+ if (status != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
+ LOG_ERROR("GraphicsContext3D: Canvas FBO initialization failed.");
+ return;
}
-}
-GraphicsContext3DInternal::~GraphicsContext3DInternal()
-{
- delete m_glWidget;
- m_glWidget = 0;
+ int clearFlags = GraphicsContext3D::COLOR_BUFFER_BIT;
+ if (m_attrs.depth)
+ clearFlags |= GraphicsContext3D::DEPTH_BUFFER_BIT;
+ if (m_attrs.stencil)
+ clearFlags |= GraphicsContext3D::STENCIL_BUFFER_BIT;
+
+ glClear(clearFlags);
+ glFlush();
}
-QGLWidget* GraphicsContext3DInternal::getOwnerGLWidget(QWebPageClient* webPageClient)
+void GraphicsContext3DInternal::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
- QAbstractScrollArea* scrollArea = qobject_cast<QAbstractScrollArea*>(webPageClient->ownerWidget());
+ Q_UNUSED(widget);
- if (scrollArea)
- return qobject_cast<QGLWidget*>(scrollArea->viewport());
+ QRectF rect = option ? option->rect : boundingRect();
- return 0;
+ // Use direct texture mapping if WebGL canvas has a shared OpenGL context
+ // with browsers OpenGL context.
+ QGLWidget* viewportGLWidget = getViewportGLWidget();
+ if (viewportGLWidget && viewportGLWidget == m_viewportGLWidget && viewportGLWidget == painter->device()) {
+ viewportGLWidget->drawTexture(rect, m_texture);
+ return;
+ }
+
+ // Alternatively read pixels to a memory buffer.
+ QImage offscreenImage(rect.width(), rect.height(), QImage::Format_ARGB32);
+ quint32* imagePixels = reinterpret_cast<quint32*>(offscreenImage.bits());
+
+ m_glWidget->makeCurrent();
+ bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_canvasFbo);
+ glReadPixels(/* x */ 0, /* y */ 0, rect.width(), rect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, imagePixels);
+
+ bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_currentFbo);
+
+ // OpenGL gives us ABGR on 32 bits, and with the origin at the bottom left
+ // We need RGB32 or ARGB32_PM, with the origin at the top left.
+ quint32* pixelsSrc = imagePixels;
+ const int height = static_cast<int>(rect.height());
+ const int width = static_cast<int>(rect.width());
+ const int halfHeight = height / 2;
+ for (int row = 0; row < halfHeight; ++row) {
+ const int targetIdx = (height - 1 - row) * width;
+ quint32* pixelsDst = imagePixels + targetIdx;
+ for (int column = 0; column < width; ++column) {
+ quint32 tempPixel = *pixelsSrc;
+ *pixelsSrc = swapBgrToRgb(*pixelsDst);
+ *pixelsDst = swapBgrToRgb(tempPixel);
+ ++pixelsSrc;
+ ++pixelsDst;
+ }
+ }
+ if (static_cast<int>(height) % 2) {
+ for (int column = 0; column < width; ++column) {
+ *pixelsSrc = swapBgrToRgb(*pixelsSrc);
+ ++pixelsSrc;
+ }
+ }
+ painter->drawImage(/* x */ 0, /* y */ 0, offscreenImage);
+}
+
+QRectF GraphicsContext3DInternal::boundingRect() const
+{
+ return m_boundingRect;
}
void* GraphicsContext3DInternal::getProcAddress(const String& proc)
@@ -477,7 +594,7 @@ void* GraphicsContext3DInternal::getProcAddress(const String& proc)
}
LOG_ERROR("GraphicsContext3D: Did not find GL function %s", proc.utf8().data());
- m_contextValid = false;
+ m_valid = false;
return 0;
}
@@ -493,7 +610,7 @@ PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attri
GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, bool)
: m_internal(new GraphicsContext3DInternal(attrs, hostWindow))
{
- if (!m_internal->isContextValid())
+ if (!m_internal->isValid())
m_internal = 0;
}
@@ -511,6 +628,11 @@ Platform3DObject GraphicsContext3D::platformTexture() const
return m_internal->m_texture;
}
+PlatformLayer* GraphicsContext3D::platformLayer() const
+{
+ return m_internal.get();
+}
+
void GraphicsContext3D::makeContextCurrent()
{
m_internal->m_glWidget->makeCurrent();
@@ -522,62 +644,25 @@ void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* co
HTMLCanvasElement* canvas = context->canvas();
ImageBuffer* imageBuffer = canvas->buffer();
QPainter* painter = imageBuffer->context()->platformContext();
- paint(painter, QRect(QPoint(0, 0), QSize(m_currentWidth, m_currentHeight)));
+ m_internal->paint(painter, 0, 0);
}
-void GraphicsContext3D::paint(QPainter* painter, const QRect& rect) const
+PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData()
{
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
- QWebPageClient* webPageClient = m_internal->m_hostWindow->platformPageClient();
- QGLWidget* ownerGLWidget = m_internal->getOwnerGLWidget(webPageClient);
- if (ownerGLWidget) {
- ownerGLWidget->drawTexture(rect, m_internal->m_texture);
- return;
- }
-#endif
- m_internal->m_glWidget->makeCurrent();
- m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_mainFbo);
- glReadPixels(/* x */ 0, /* y */ 0, m_currentWidth, m_currentHeight, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, m_internal->m_pixels.bits());
- painter->drawImage(/* x */ 0, /* y */ 0, m_internal->m_pixels.rgbSwapped().transformed(QMatrix().rotate(180)));
- m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_currentFbo);
+ // FIXME: This needs to be implemented for proper non-premultiplied-alpha
+ // support.
+ return 0;
}
void GraphicsContext3D::reshape(int width, int height)
{
- if (((width == m_currentWidth) && (height == m_currentHeight)) || (!m_internal))
+ if (width == m_currentWidth && height == m_currentHeight || (!m_internal))
return;
-
+
m_currentWidth = width;
m_currentHeight = height;
- m_internal->m_pixels = QImage(m_currentWidth, m_currentHeight, QImage::Format_ARGB32);
-
- m_internal->m_glWidget->makeCurrent();
-
- glBindTexture(GraphicsContext3D::TEXTURE_2D, m_internal->m_texture);
- glTexImage2D(GraphicsContext3D::TEXTURE_2D, /* level */ 0, GraphicsContext3D::RGBA, width, height, /* border */ 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, /* data */ 0);
- glBindTexture(GraphicsContext3D::TEXTURE_2D, 0);
-
- m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_mainFbo);
- m_internal->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_internal->m_depthBuffer);
-#if defined(QT_OPENGL_ES_2)
- renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, width, height);
-#else
- renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT, width, height);
-#endif
- m_internal->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
-
- m_internal->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_internal->m_texture, 0);
- m_internal->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_internal->m_depthBuffer);
-
- GLenum status = m_internal->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER);
- if (status != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
- LOG_ERROR("GraphicsContext3D: Wasn't able to reshape the main framebuffer");
- notImplemented();
- }
-
- glClear(GraphicsContext3D::COLOR_BUFFER_BIT);
- glFlush();
+ m_internal->reshape(width, height);
}
IntSize GraphicsContext3D::getInternalFramebufferSize()
@@ -626,7 +711,7 @@ void GraphicsContext3D::bindBuffer(GC3Denum target, Platform3DObject buffer)
void GraphicsContext3D::bindFramebuffer(GC3Denum target, Platform3DObject buffer)
{
m_internal->m_glWidget->makeCurrent();
- m_internal->m_currentFbo = buffer ? buffer : m_internal->m_mainFbo;
+ m_internal->m_currentFbo = buffer ? buffer : m_internal->m_canvasFbo;
m_internal->bindFramebuffer(target, m_internal->m_currentFbo);
}
@@ -1064,6 +1149,23 @@ void GraphicsContext3D::releaseShaderCompiler()
void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
{
m_internal->m_glWidget->makeCurrent();
+#if !defined(QT_OPENGL_ES_2)
+ switch (internalformat) {
+ case DEPTH_STENCIL:
+ internalformat = GL_DEPTH24_STENCIL8;
+ break;
+ case DEPTH_COMPONENT16:
+ internalformat = DEPTH_COMPONENT;
+ break;
+ case RGBA4:
+ case RGB5_A1:
+ internalformat = RGBA;
+ break;
+ case RGB565:
+ internalformat = RGB;
+ break;
+ }
+#endif
m_internal->renderbufferStorage(target, internalformat, width, height);
}
@@ -1598,6 +1700,22 @@ void GraphicsContext3D::synthesizeGLError(GC3Denum error)
m_internal->m_syntheticErrors.add(error);
}
+void GraphicsContext3D::markLayerComposited()
+{
+ m_internal->m_layerComposited = true;
+}
+
+void GraphicsContext3D::markContextChanged()
+{
+ // FIXME: Any accelerated compositor needs to be told to re-read from here.
+ m_internal->m_layerComposited = false;
+}
+
+bool GraphicsContext3D::layerComposited() const
+{
+ return m_internal->m_layerComposited;
+}
+
Extensions3D* GraphicsContext3D::getExtensions()
{
if (!m_internal->m_extensions)
diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index 9742755..e3e0fa6 100644
--- a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -9,6 +9,7 @@
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
* Copyright (C) 2008 Dirk Schulze <vbs85@gmx.de>
* Copyright (C) 2010, 2011 Sencha, Inc.
+ * Copyright (C) 2011 Andreas Kling <kling@webkit.org>
*
* All rights reserved.
*
@@ -672,8 +673,6 @@ void GraphicsContext::fillRect(const FloatRect& rect)
ContextShadow* shadow = contextShadow();
if (m_state.fillPattern) {
- AffineTransform affine;
- QBrush brush(m_state.fillPattern->createPlatformPattern(affine));
QPixmap* image = m_state.fillPattern->tileImage()->nativeImageForCurrentFrame();
QPainter* shadowPainter = hasShadow() ? shadow->beginShadowLayer(this, normalizedRect) : 0;
if (shadowPainter) {
diff --git a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
index f3cfc47..1f77fc2 100644
--- a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
@@ -310,10 +310,6 @@ public:
}
} m_state;
-#if ENABLE(WEBGL)
- const GraphicsContext3D* m_gc3D;
-#endif
-
#ifndef QT_NO_ANIMATION
friend class AnimationQtBase;
#endif
@@ -340,9 +336,6 @@ GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer)
#if ENABLE(TILED_BACKING_STORE)
, m_tiledBackingStore(0)
#endif
-#if ENABLE(WEBGL)
- , m_gc3D(0)
-#endif
{
// We use graphics-view for compositing-only, not for interactivity.
setAcceptedMouseButtons(Qt::NoButton);
@@ -665,11 +658,6 @@ void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsIte
case MediaContentType:
// we don't need to paint anything: we have a QGraphicsItem from the media element
break;
-#if ENABLE(WEBGL)
- case Canvas3DContentType:
- m_gc3D->paint(painter, option->rect);
- break;
-#endif
}
}
@@ -808,16 +796,6 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform
setFlag(ItemHasNoContents, !m_layer->drawsContent());
break;
-
-#if ENABLE(WEBGL)
- case Canvas3DContentType:
- if (m_pendingContent.contentType != m_currentContent.contentType)
- update();
-
- setCacheMode(NoCache);
- setFlag(ItemHasNoContents, false);
- break;
-#endif
}
}
@@ -1268,23 +1246,6 @@ void GraphicsLayerQt::setContentsBackgroundColor(const Color& color)
GraphicsLayer::setContentsBackgroundColor(color);
}
-#if ENABLE(WEBGL)
-void GraphicsLayerQt::setContentsToGraphicsContext3D(const GraphicsContext3D* ctx)
-{
- if (ctx == m_impl->m_gc3D)
- return;
-
- m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::Canvas3DContentType;
- m_impl->m_gc3D = ctx;
- m_impl->notifyChange(GraphicsLayerQtImpl::ContentChange);
-}
-
-void GraphicsLayerQt::setGraphicsContext3DNeedsDisplay()
-{
- setNeedsDisplay();
-}
-#endif
-
void GraphicsLayerQt::setContentsToMedia(PlatformLayer* media)
{
if (media) {
@@ -1297,6 +1258,11 @@ void GraphicsLayerQt::setContentsToMedia(PlatformLayer* media)
GraphicsLayer::setContentsToMedia(media);
}
+void GraphicsLayerQt::setContentsToCanvas(PlatformLayer* canvas)
+{
+ setContentsToMedia(canvas);
+}
+
/* \reimp (GraphicsLayer.h)
*/
void GraphicsLayerQt::setContentsOrientation(CompositingCoordinatesOrientation orientation)
diff --git a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h
index 569bd8d..2af98fd 100644
--- a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h
+++ b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h
@@ -20,9 +20,6 @@
#ifndef GraphicsLayerQt_h
#define GraphicsLayerQt_h
-#if ENABLE(WEBGL)
-#include "GraphicsContext3D.h"
-#endif
#include "GraphicsLayer.h"
#include "GraphicsLayerClient.h"
@@ -78,11 +75,8 @@ public:
virtual void setContentsToImage(Image*);
virtual void setContentsNeedsDisplay();
virtual void setContentsToMedia(PlatformLayer*);
+ virtual void setContentsToCanvas(PlatformLayer*);
virtual void setContentsBackgroundColor(const Color&);
-#if ENABLE(WEBGL)
- virtual void setContentsToGraphicsContext3D(const GraphicsContext3D*);
- virtual void setGraphicsContext3DNeedsDisplay();
-#endif
virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation);
virtual void distributeOpacity(float);
virtual float accumulatedOpacity() const;
diff --git a/Source/WebCore/platform/graphics/qt/ImageBufferData.h b/Source/WebCore/platform/graphics/qt/ImageBufferData.h
index aa32253..602197e 100644
--- a/Source/WebCore/platform/graphics/qt/ImageBufferData.h
+++ b/Source/WebCore/platform/graphics/qt/ImageBufferData.h
@@ -42,6 +42,8 @@ class ImageBufferData {
public:
ImageBufferData(const IntSize&);
+ QImage toQImage() const;
+
QPixmap m_pixmap;
OwnPtr<QPainter> m_painter;
RefPtr<Image> m_image;
diff --git a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp
index 62f5c3e..f7d63ca 100644
--- a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp
@@ -80,6 +80,21 @@ ImageBufferData::ImageBufferData(const IntSize& size)
m_image = StillImage::createForRendering(&m_pixmap);
}
+QImage ImageBufferData::toQImage() const
+{
+ QPaintEngine* paintEngine = m_pixmap.paintEngine();
+ if (!paintEngine || paintEngine->type() != QPaintEngine::Raster)
+ return m_pixmap.toImage();
+
+ // QRasterPixmapData::toImage() will deep-copy the backing QImage if there's an active QPainter on it.
+ // For performance reasons, we don't want that here, so we temporarily redirect the paint engine.
+ QPaintDevice* currentPaintDevice = paintEngine->paintDevice();
+ paintEngine->setPaintDevice(0);
+ QImage image = m_pixmap.toImage();
+ paintEngine->setPaintDevice(currentPaintDevice);
+ return image;
+}
+
ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode, bool& success)
: m_data(size)
, m_size(size)
@@ -159,7 +174,7 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
if (isPainting)
m_data.m_painter->end();
- QImage image = m_data.m_pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
+ QImage image = m_data.toQImage().convertToFormat(QImage::Format_ARGB32);
ASSERT(!image.isNull());
uchar* bits = image.bits();
@@ -214,16 +229,12 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& i
int numRows = endy - originy;
// NOTE: For unmultiplied data, we undo the premultiplication below.
- QImage image = imageData.m_pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ QImage image = imageData.toQImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
ASSERT(!image.isNull());
const int bytesPerLine = image.bytesPerLine();
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
const uchar* bits = image.constBits();
-#else
- const uchar* bits = image.bits();
-#endif
quint32* destRows = reinterpret_cast_ptr<quint32*>(&data[desty * rect.width() * 4 + destx * 4]);
diff --git a/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
index 3540994..8cda231 100644
--- a/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
@@ -194,15 +194,7 @@ void ImageDecoderQt::internalReadImage(size_t frameIndex)
bool ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex)
{
- QPixmap pixmap;
-
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
- pixmap = QPixmap::fromImageReader(m_reader.get());
-#else
- QImage img;
- if (m_reader->read(&img))
- pixmap = QPixmap::fromImage(img);
-#endif
+ QPixmap pixmap = QPixmap::fromImageReader(m_reader.get());
if (pixmap.isNull()) {
frameCount();
diff --git a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
index 001d45b..bc43acf 100644
--- a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
@@ -74,7 +74,7 @@ void MediaPlayerPrivateQt::getSupportedTypes(HashSet<String> &supported)
for (int i = 0; i < types.size(); i++) {
QString mime = types.at(i);
- if (mime.startsWith("audio/") || mime.startsWith("video/"))
+ if (mime.startsWith(QString::fromLatin1("audio/")) || mime.startsWith(QString::fromLatin1("video/")))
supported.add(mime);
}
}
@@ -103,7 +103,6 @@ MediaPlayerPrivateQt::MediaPlayerPrivateQt(MediaPlayer* player)
, m_isVisible(false)
, m_isSeeking(false)
, m_composited(false)
- , m_queuedSeek(-1)
, m_preload(MediaPlayer::Auto)
, m_suppressNextPlaybackChanged(false)
{
@@ -195,7 +194,7 @@ void MediaPlayerPrivateQt::commitLoad(const String& url)
HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient());
// Construct the media content with a network request if the resource is http[s]
- if (scheme == "http" || scheme == "https") {
+ if (scheme == QString::fromLatin1("http") || scheme == QString::fromLatin1("https")) {
QNetworkRequest request = QNetworkRequest(rUrl);
// Grab the current document
@@ -220,7 +219,7 @@ void MediaPlayerPrivateQt::commitLoad(const String& url)
// Set the refferer, but not when requesting insecure content from a secure page
QUrl documentUrl = QUrl(QString(document->documentURI()));
- if (documentUrl.scheme().toLower() == "http" || scheme == "https")
+ if (documentUrl.scheme().toLower() == QString::fromLatin1("http") || scheme == QString::fromLatin1("https"))
request.setRawHeader("Referer", documentUrl.toEncoded());
// Set the user agent
@@ -296,32 +295,8 @@ void MediaPlayerPrivateQt::seek(float position)
if (m_mediaPlayerControl && !m_mediaPlayerControl->availablePlaybackRanges().contains(position * 1000))
return;
- if (m_isSeeking)
- return;
-
- if (position > duration())
- position = duration();
-
- // Seeking is most reliable when we're paused.
- // Webkit will try to pause before seeking, but due to the asynchronous nature
- // of the backend, the player may not actually be paused yet.
- // In this case, we should queue the seek and wait until pausing has completed
- // before attempting to seek.
- if (m_mediaPlayer->state() == QMediaPlayer::PlayingState) {
- m_mediaPlayer->pause();
- m_isSeeking = true;
- m_queuedSeek = static_cast<qint64>(position * 1000);
-
- // Set a timeout, so that in the event that we don't get a state changed
- // signal, we still attempt the seek.
- QTimer::singleShot(1000, this, SLOT(queuedSeekTimeout()));
- } else {
- m_isSeeking = true;
- m_mediaPlayer->setPosition(static_cast<qint64>(position * 1000));
-
- // Set a timeout, in case we don't get a position changed signal
- QTimer::singleShot(10000, this, SLOT(seekTimeout()));
- }
+ m_isSeeking = true;
+ m_mediaPlayer->setPosition(static_cast<qint64>(position * 1000));
}
bool MediaPlayerPrivateQt::seeking() const
@@ -443,13 +418,8 @@ void MediaPlayerPrivateQt::handleError(QMediaPlayer::Error)
updateStates();
}
-void MediaPlayerPrivateQt::stateChanged(QMediaPlayer::State state)
+void MediaPlayerPrivateQt::stateChanged(QMediaPlayer::State)
{
- if (state != QMediaPlayer::PlayingState && m_isSeeking && m_queuedSeek >= 0) {
- m_mediaPlayer->setPosition(m_queuedSeek);
- m_queuedSeek = -1;
- }
-
if (!m_suppressNextPlaybackChanged)
m_webCorePlayer->playbackStateChanged();
else
@@ -468,34 +438,12 @@ void MediaPlayerPrivateQt::nativeSizeChanged(const QSizeF& size)
m_webCorePlayer->sizeChanged();
}
-void MediaPlayerPrivateQt::queuedSeekTimeout()
-{
- // If we haven't heard anything, assume the player is now paused
- // and we can attempt the seek
- if (m_isSeeking && m_queuedSeek >= 0) {
- m_mediaPlayer->setPosition(m_queuedSeek);
- m_queuedSeek = -1;
-
- // Set a timeout, in case we don't get a position changed signal
- QTimer::singleShot(10000, this, SLOT(seekTimeout()));
- }
-}
-
-void MediaPlayerPrivateQt::seekTimeout()
-{
- // If we haven't heard anything, assume the seek succeeded
- if (m_isSeeking) {
- m_webCorePlayer->timeChanged();
- m_isSeeking = false;
- }
-}
-
void MediaPlayerPrivateQt::positionChanged(qint64)
{
// Only propagate this event if we are seeking
- if (m_isSeeking && m_queuedSeek == -1) {
- m_webCorePlayer->timeChanged();
+ if (m_isSeeking) {
m_isSeeking = false;
+ m_webCorePlayer->timeChanged();
}
}
@@ -649,7 +597,7 @@ void MediaPlayerPrivateQt::repaint()
#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
-class TextureMapperVideoLayerQt : public virtual TextureMapperVideoLayer {
+class TextureMapperVideoLayerQt : public virtual TextureMapperMediaLayer {
public:
TextureMapperVideoLayerQt(QGraphicsVideoItem* videoItem)
: m_videoItem(videoItem)
diff --git a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h
index 81cdd79..c6398c9 100644
--- a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h
+++ b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h
@@ -33,7 +33,7 @@ QT_END_NAMESPACE
namespace WebCore {
-class TextureMapperVideoLayer;
+class TextureMapperMediaLayer;
class MediaPlayerPrivateQt : public QObject, public MediaPlayerPrivateInterface {
@@ -120,8 +120,6 @@ private slots:
void handleError(QMediaPlayer::Error);
void stateChanged(QMediaPlayer::State);
void nativeSizeChanged(const QSizeF&);
- void queuedSeekTimeout();
- void seekTimeout();
void positionChanged(qint64);
void durationChanged(qint64);
void bufferStatusChanged(int);
@@ -141,7 +139,7 @@ private:
QGraphicsVideoItem* m_videoItem;
QGraphicsScene* m_videoScene;
#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
- OwnPtr<TextureMapperVideoLayer> m_platformLayer;
+ OwnPtr<TextureMapperMediaLayer> m_platformLayer;
#endif
mutable MediaPlayer::NetworkState m_networkState;
@@ -153,7 +151,6 @@ private:
bool m_isVisible;
bool m_isSeeking;
bool m_composited;
- qint64 m_queuedSeek;
MediaPlayer::Preload m_preload;
bool m_delayingLoad;
String m_mediaUrl;
diff --git a/Source/WebCore/platform/graphics/qt/PathQt.cpp b/Source/WebCore/platform/graphics/qt/PathQt.cpp
index ad482f7..ccc7f3d 100644
--- a/Source/WebCore/platform/graphics/qt/PathQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/PathQt.cpp
@@ -154,7 +154,7 @@ FloatRect Path::boundingRect() const
return m_path.boundingRect();
}
-FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
+FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const
{
GraphicsContext* context = scratchContext();
QPainterPathStroker stroke;
@@ -398,23 +398,15 @@ void Path::apply(void* info, PathApplierFunction function) const
void Path::transform(const AffineTransform& transform)
{
QTransform qTransform(transform);
-#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
- // Workaround for http://bugreports.qt.nokia.com/browse/QTBUG-11264
- // QTransform.map doesn't handle the MoveTo element because of the isEmpty issue
- if (m_path.isEmpty() && m_path.elementCount()) {
- QPointF point = qTransform.map(m_path.currentPosition());
- moveTo(point);
- } else
-#endif
- m_path = qTransform.map(m_path);
-}
-
-float Path::length()
+ m_path = qTransform.map(m_path);
+}
+
+float Path::length() const
{
return m_path.length();
}
-FloatPoint Path::pointAtLength(float length, bool& ok)
+FloatPoint Path::pointAtLength(float length, bool& ok) const
{
ok = (length >= 0 && length <= m_path.length());
@@ -424,7 +416,7 @@ FloatPoint Path::pointAtLength(float length, bool& ok)
return point;
}
-float Path::normalAngleAtLength(float length, bool& ok)
+float Path::normalAngleAtLength(float length, bool& ok) const
{
ok = (length >= 0 && length <= m_path.length());
diff --git a/Source/WebCore/platform/graphics/qt/TileQt.cpp b/Source/WebCore/platform/graphics/qt/TileQt.cpp
index 096ce14..8723cd4 100644
--- a/Source/WebCore/platform/graphics/qt/TileQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/TileQt.cpp
@@ -91,10 +91,10 @@ void Tile::invalidate(const IntRect& dirtyRect)
*m_dirtyRegion += tileDirtyRect;
}
-void Tile::updateBackBuffer()
+Vector<IntRect> Tile::updateBackBuffer()
{
if (m_buffer && !isDirty())
- return;
+ return Vector<IntRect>();
if (!m_backBuffer) {
if (!m_buffer) {
@@ -115,15 +115,19 @@ void Tile::updateBackBuffer()
GraphicsContext context(&painter);
context.translate(-m_rect.x(), -m_rect.y());
+ Vector<IntRect> updatedRects;
int size = dirtyRects.size();
for (int n = 0; n < size; ++n) {
context.save();
IntRect rect = dirtyRects[n];
+ updatedRects.append(rect);
context.clip(FloatRect(rect));
context.scale(FloatSize(m_backingStore->m_contentsScale, m_backingStore->m_contentsScale));
m_backingStore->m_client->tiledBackingStorePaint(&context, m_backingStore->mapToContents(rect));
context.restore();
}
+
+ return updatedRects;
}
void Tile::swapBackBufferToFront()
diff --git a/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp
index 0e68c21..cc695a5 100644
--- a/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp
+++ b/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp
@@ -65,7 +65,8 @@ FontCustomPlatformData::~FontCustomPlatformData()
#endif
}
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation, FontWidthVariant, FontRenderingMode mode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation,
+ TextOrientation textOrientation, FontWidthVariant, FontRenderingMode mode)
{
#if OS(WINDOWS)
ASSERT(m_fontReference);
@@ -102,7 +103,7 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b
return FontPlatformData(hfont, size);
#elif OS(LINUX) || OS(FREEBSD) || PLATFORM(BREWMP)
ASSERT(m_fontReference);
- return FontPlatformData(m_fontReference, "", size, bold && !m_fontReference->isBold(), italic && !m_fontReference->isItalic(), orientation);
+ return FontPlatformData(m_fontReference, "", size, bold && !m_fontReference->isBold(), italic && !m_fontReference->isItalic(), orientation, textOrientation);
#else
notImplemented();
return FontPlatformData();
diff --git a/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.h
index 2dee3ab..b68722b 100644
--- a/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.h
+++ b/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.h
@@ -35,6 +35,7 @@
#include "FontOrientation.h"
#include "FontRenderingMode.h"
#include "FontWidthVariant.h"
+#include "TextOrientation.h"
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
@@ -66,8 +67,8 @@ public:
~FontCustomPlatformData();
- FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth,
- FontRenderingMode = NormalRenderingMode);
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight,
+ FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
static bool supportsFormat(const String&);
diff --git a/Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp b/Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp
index 66e6839..f362fa3 100644
--- a/Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp
@@ -91,7 +91,7 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b
return false;
}
- if ((fontData->orientation() == Vertical) && (!fontData->isBrokenIdeographFont())) {
+ if (fontData->hasVerticalGlyphs()) {
bool lookVariants = false;
for (unsigned i = 0; i < bufferLength; ++i) {
if (!Font::isCJKIdeograph(buffer[i])) {
diff --git a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
index 00afd07..df680eb 100644
--- a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
@@ -1025,6 +1025,14 @@ void GraphicsContext::setPlatformShadow(const FloatSize& size,
if (paintingDisabled())
return;
+ if (platformContext()->useGPU()) {
+ GLES2Canvas* canvas = platformContext()->gpuCanvas();
+ canvas->setShadowOffset(size);
+ canvas->setShadowBlur(blurFloat);
+ canvas->setShadowColor(color, colorSpace);
+ canvas->setShadowsIgnoreTransforms(m_state.shadowsIgnoreTransforms);
+ }
+
// Detect when there's no effective shadow and clear the looper.
if (!size.width() && !size.height() && !blurFloat) {
platformContext()->setDrawLooper(0);
@@ -1035,14 +1043,15 @@ void GraphicsContext::setPlatformShadow(const FloatSize& size,
double height = size.height();
double blur = blurFloat;
- SkBlurDrawLooper::BlurFlags blurFlags = SkBlurDrawLooper::kNone_BlurFlag;
+ uint32_t blurFlags = SkBlurDrawLooper::kHighQuality_BlurFlag |
+ SkBlurDrawLooper::kOverrideColor_BlurFlag;
if (m_state.shadowsIgnoreTransforms) {
// Currently only the GraphicsContext associated with the
// CanvasRenderingContext for HTMLCanvasElement have shadows ignore
// Transforms. So with this flag set, we know this state is associated
// with a CanvasRenderingContext.
- blurFlags = SkBlurDrawLooper::kIgnoreTransform_BlurFlag;
+ blurFlags |= SkBlurDrawLooper::kIgnoreTransform_BlurFlag;
// CG uses natural orientation for Y axis, but the HTML5 canvas spec
// does not.
diff --git a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
index 2721523..b89c68d 100644
--- a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
@@ -341,6 +341,28 @@ void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& so
putImageData<Premultiplied>(source, sourceSize, sourceRect, destPoint, context()->platformContext()->canvas()->getDevice(), m_size);
}
+template <typename T>
+static String ImageToDataURL(T& source, const String& mimeType, const double* quality)
+{
+ Vector<unsigned char> encodedImage;
+ if (mimeType == "image/jpeg") {
+ int compressionQuality = JPEGImageEncoder::DefaultCompressionQuality;
+ if (quality && *quality >= 0.0 && *quality <= 1.0)
+ compressionQuality = static_cast<int>(*quality * 100 + 0.5);
+ if (!JPEGImageEncoder::encode(source, compressionQuality, &encodedImage))
+ return "data:,";
+ } else {
+ if (!PNGImageEncoder::encode(source, &encodedImage))
+ return "data:,";
+ ASSERT(mimeType == "image/png");
+ }
+
+ Vector<char> base64Data;
+ base64Encode(*reinterpret_cast<Vector<char>*>(&encodedImage), base64Data);
+
+ return makeString("data:", mimeType, ";base64,", base64Data);
+}
+
String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
{
ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
@@ -358,23 +380,13 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
if (!device->readPixels(bounds, &bitmap))
return "data:,";
}
-
- if (mimeType == "image/jpeg") {
- int compressionQuality = JPEGImageEncoder::DefaultCompressionQuality;
- if (quality && *quality >= 0.0 && *quality <= 1.0)
- compressionQuality = static_cast<int>(*quality * 100 + 0.5);
- if (!JPEGImageEncoder::encode(bitmap, compressionQuality, &encodedImage))
- return "data:,";
- } else {
- if (!PNGImageEncoder::encode(bitmap, &encodedImage))
- return "data:,";
- ASSERT(mimeType == "image/png");
- }
- Vector<char> base64Data;
- base64Encode(*reinterpret_cast<Vector<char>*>(&encodedImage), base64Data);
+ return ImageToDataURL(bitmap, mimeType, quality);
+}
- return makeString("data:", mimeType, ";base64,", base64Data);
+String ImageDataToDataURL(const ImageData& source, const String& mimeType, const double* quality)
+{
+ return ImageToDataURL(source, mimeType, quality);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp
index 91a4e4f..72bec29 100644
--- a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp
@@ -260,6 +260,7 @@ static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImag
paint.setXfermodeMode(compOp);
paint.setFilterBitmap(true);
paint.setAlpha(platformContext->getNormalizedAlpha());
+ paint.setLooper(platformContext->getDrawLooper());
skia::PlatformCanvas* canvas = platformContext->canvas();
diff --git a/Source/WebCore/platform/graphics/skia/PathSkia.cpp b/Source/WebCore/platform/graphics/skia/PathSkia.cpp
index 0344086..b037a0d 100644
--- a/Source/WebCore/platform/graphics/skia/PathSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/PathSkia.cpp
@@ -228,7 +228,7 @@ void Path::transform(const AffineTransform& xform)
m_path->transform(xform);
}
-FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
+FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const
{
GraphicsContext* scratch = scratchContext();
scratch->save();
diff --git a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
index eac5e4a..8e1937f 100644
--- a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
@@ -68,18 +68,6 @@
namespace WebCore {
-#if ENABLE(SKIA_GPU)
-GrContext* GetGlobalGrContext()
-{
- static GrContext* gGR;
- if (!gGR) {
- gGR = GrContext::CreateGLShaderContext();
- gGR->setTextureCacheLimits(512, 50 * 1024 * 1024);
- }
- return gGR;
-}
-#endif
-
extern bool isPathSkiaSafe(const SkMatrix& transform, const SkPath& path);
// State -----------------------------------------------------------------------
@@ -241,8 +229,14 @@ PlatformContextSkia::PlatformContextSkia(skia::PlatformCanvas* canvas)
PlatformContextSkia::~PlatformContextSkia()
{
#if ENABLE(ACCELERATED_2D_CANVAS)
- if (m_gpuCanvas)
+ if (m_gpuCanvas) {
+#if ENABLE(SKIA_GPU)
+ // make sure everything related to this platform context has been flushed
+ if (!m_useGPU)
+ m_gpuCanvas->context()->grContext()->flush(0);
+#endif
m_gpuCanvas->drawingBuffer()->setWillPublishCallback(0);
+ }
#endif
}
@@ -697,8 +691,7 @@ void PlatformContextSkia::applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths)
bool PlatformContextSkia::canAccelerate() const
{
- return !m_state->m_fillShader // Can't accelerate with a fill gradient or pattern.
- && !m_state->m_looper; // Can't accelerate with a shadow.
+ return !m_state->m_fillShader; // Can't accelerate with a fill gradient or pattern.
}
bool PlatformContextSkia::canvasClipApplied() const
@@ -741,8 +734,10 @@ void PlatformContextSkia::setSharedGraphicsContext3D(SharedGraphicsContext3D* co
context->makeContextCurrent();
m_gpuCanvas->bindFramebuffer();
- GrContext* gr = GetGlobalGrContext();
+ GrContext* gr = context->grContext();
gr->resetContext();
+ drawingBuffer->setGrContext(gr);
+
SkDeviceFactory* factory = new SkGpuDeviceFactory(gr, SkGpuDevice::Current3DApiRenderTarget());
SkDevice* device = factory->newDevice(m_canvas, SkBitmap::kARGB_8888_Config, drawingBuffer->size().width(), drawingBuffer->size().height(), false, false);
m_canvas->setDevice(device)->unref();
diff --git a/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp b/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp
index 54aa35e..b0cb0c7 100644
--- a/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp
+++ b/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp
@@ -380,6 +380,11 @@ bool paintSkiaText(GraphicsContext* context,
paint.reset();
platformContext->setupPaintForStroking(&paint, 0, 0);
paint.setFlags(SkPaint::kAntiAlias_Flag);
+#if ENABLE(SKIA_TEXT)
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ setupPaintForFont(hfont, &paint);
+#endif
+
if (didFill) {
// If there is a shadow and we filled above, there will already be
// a shadow. We don't want to draw it again or it will be too dark
@@ -390,7 +395,7 @@ bool paintSkiaText(GraphicsContext* context,
// thing would be to draw to a new layer and then draw that layer
// with a shadow. But this is a lot of extra work for something
// that isn't normally an issue.
- SkSafeUnref(paint.setLooper(0));
+ paint.setLooper(0);
}
if (!skiaDrawText(hfont, dc, platformContext->canvas(), *origin, &paint,
diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
index 4698239..760ba6c 100644
--- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
+++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
@@ -336,7 +336,7 @@ void GraphicsLayerTextureMapper::setContentsToMedia(PlatformLayer* media)
notifyChange(TextureMapperNode::ContentChange);
m_pendingContent.contentType = media ? TextureMapperNode::MediaContentType : TextureMapperNode::HTMLContentType;
if (media)
- m_pendingContent.media = static_cast<TextureMapperVideoLayer*>(media);
+ m_pendingContent.media = static_cast<TextureMapperMediaLayer*>(media);
else
m_pendingContent.media = 0;
}
@@ -366,13 +366,6 @@ void GraphicsLayerTextureMapper::syncCompositingState()
}
/* \reimp (GraphicsLayer.h)
- */
-NativeLayer GraphicsLayerTextureMapper::nativeLayer() const
-{
- return m_node.get();
-}
-
-/* \reimp (GraphicsLayer.h)
*/
PlatformLayer* GraphicsLayerTextureMapper::platformLayer() const
{
diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
index 47a27c6..dcf4938 100644
--- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
+++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
@@ -81,7 +81,6 @@ public:
virtual void syncCompositingState();
virtual void syncCompositingStateForThisLayerOnly();
virtual void setName(const String& name);
- virtual NativeLayer nativeLayer() const;
virtual PlatformLayer* platformLayer() const;
virtual bool addAnimation(const KeyframeValueList&, const IntSize& /*boxSize*/, const Animation*, const String& /*keyframesName*/, double /*timeOffset*/) { return false; }
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.h b/Source/WebCore/platform/graphics/texmap/TextureMapper.h
index 589fda1..8e46e3c 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapper.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.h
@@ -31,6 +31,7 @@
#include "IntRect.h"
#include "IntSize.h"
#include "TransformationMatrix.h"
+#include <wtf/UnusedParam.h>
/*
TextureMapper is a mechanism that enables hardware acceleration of CSS animations (accelerated compositing) without
@@ -68,7 +69,7 @@ public:
return beginPaint(IntRect(0, 0, size().width(), size().height()));
}
virtual void setContentsToImage(Image*) = 0;
- virtual bool save(const String& filename) { return false; }
+ virtual bool save(const String&) { return false; }
inline void lock() { ++m_lockCount; }
inline void unlock() { --m_lockCount; }
@@ -101,6 +102,7 @@ public:
virtual void bindSurface(BitmapTexture* surface) = 0;
virtual void paintToTarget(const BitmapTexture& texture, const IntSize&, const TransformationMatrix& matrix, float opacity, const IntRect& visibleRect)
{
+ UNUSED_PARAM(visibleRect);
drawTexture(texture, IntRect(0, 0, texture.contentSize().width(), texture.contentSize().height()), matrix, opacity, 0);
}
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h
index 9694043..c5decc1 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h
@@ -20,19 +20,19 @@
#ifndef TextureMapperNode_h
#define TextureMapperNode_h
-#include "CurrentTime.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
#include "GraphicsLayer.h"
-#include "HashMap.h"
#include "Image.h"
-#include "RefCounted.h"
#include "TextureMapper.h"
#include "TextureMapperPlatformLayer.h"
#include "Timer.h"
#include "TransformOperations.h"
#include "TranslateTransformOperation.h"
#include "UnitBezier.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/HashMap.h>
+#include <wtf/RefCounted.h>
namespace WebCore {
@@ -94,7 +94,7 @@ public:
ContentType contentType;
RefPtr<Image> image;
- TextureMapperVideoLayer* media;
+ TextureMapperMediaLayer* media;
ContentData()
: needsDisplay(false)
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h
index 2a38b90..d2d646a 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h
@@ -43,7 +43,7 @@ class TextureMapperPlatformLayer {
public:
enum Type {
ContentLayer,
- VideoLayer
+ MediaLayer
};
virtual Type layerType() const = 0;
@@ -66,13 +66,11 @@ public:
virtual Type layerType() const { return ContentLayer; }
};
-#if ENABLE(VIDEO)
-class TextureMapperVideoLayer : public TextureMapperPlatformLayer {
+class TextureMapperMediaLayer : public TextureMapperPlatformLayer {
public:
virtual void paint(GraphicsContext*) = 0;
- virtual Type layerType() const { return VideoLayer; }
+ virtual Type layerType() const { return MediaLayer; }
};
-#endif
}
diff --git a/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.cpp b/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.cpp
index a8ad131..b1ea99b 100644
--- a/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.cpp
+++ b/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.cpp
@@ -21,6 +21,7 @@
#include "config.h"
#include "TranslateTransformOperation.h"
+#include "FloatConversion.h"
namespace WebCore {
@@ -30,15 +31,15 @@ PassRefPtr<TransformOperation> TranslateTransformOperation::blend(const Transfor
return this;
if (blendToIdentity)
- return TranslateTransformOperation::create(Length(m_x.type()).blend(m_x, progress),
- Length(m_y.type()).blend(m_y, progress),
- Length(m_z.type()).blend(m_z, progress), m_type);
+ return TranslateTransformOperation::create(Length(m_x.type()).blend(m_x, narrowPrecisionToFloat(progress)),
+ Length(m_y.type()).blend(m_y, narrowPrecisionToFloat(progress)),
+ Length(m_z.type()).blend(m_z, narrowPrecisionToFloat(progress)), m_type);
const TranslateTransformOperation* fromOp = static_cast<const TranslateTransformOperation*>(from);
Length fromX = fromOp ? fromOp->m_x : Length(m_x.type());
Length fromY = fromOp ? fromOp->m_y : Length(m_y.type());
Length fromZ = fromOp ? fromOp->m_z : Length(m_z.type());
- return TranslateTransformOperation::create(m_x.blend(fromX, progress), m_y.blend(fromY, progress), m_z.blend(fromZ, progress), m_type);
+ return TranslateTransformOperation::create(m_x.blend(fromX, narrowPrecisionToFloat(progress)), m_y.blend(fromY, narrowPrecisionToFloat(progress)), m_z.blend(fromZ, narrowPrecisionToFloat(progress)), m_type);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/win/FontCacheWin.cpp b/Source/WebCore/platform/graphics/win/FontCacheWin.cpp
index e800245..5382ef7 100644
--- a/Source/WebCore/platform/graphics/win/FontCacheWin.cpp
+++ b/Source/WebCore/platform/graphics/win/FontCacheWin.cpp
@@ -584,7 +584,7 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
#if PLATFORM(CG)
bool fontCreationFailed = !result->cgFont();
#elif PLATFORM(CAIRO)
- bool fontCreationFailed = !result->fontFace();
+ bool fontCreationFailed = !result->scaledFont();
#endif
if (fontCreationFailed) {
diff --git a/Source/WebCore/platform/graphics/win/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
index 4aee6cd..8348acb 100644
--- a/Source/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
+++ b/Source/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
@@ -59,7 +59,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
}
}
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode renderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode renderingMode)
{
ASSERT(m_fontReference);
ASSERT(T2embedLibrary());
diff --git a/Source/WebCore/platform/graphics/win/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/win/FontCustomPlatformData.h
index abdb356..65388d8 100644
--- a/Source/WebCore/platform/graphics/win/FontCustomPlatformData.h
+++ b/Source/WebCore/platform/graphics/win/FontCustomPlatformData.h
@@ -25,6 +25,7 @@
#include "FontRenderingMode.h"
#include "FontWidthVariant.h"
#include "PlatformString.h"
+#include "TextOrientation.h"
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
@@ -46,7 +47,8 @@ public:
~FontCustomPlatformData();
- FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight,
+ FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
static bool supportsFormat(const String&);
diff --git a/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp b/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp
index fd30a6d..6f9bbf0 100644
--- a/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp
+++ b/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp
@@ -23,8 +23,11 @@
#include "SharedBuffer.h"
#include "FontPlatformData.h"
+
+#include <cairo-win32.h>
#include <wtf/RetainPtr.h>
+
namespace WebCore {
FontCustomPlatformData::~FontCustomPlatformData()
@@ -32,7 +35,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
cairo_font_face_destroy(m_fontFace);
}
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant)
{
return FontPlatformData(m_fontFace, size, bold, italic);
}
diff --git a/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h b/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h
index ea3ae38..bd90f18 100644
--- a/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h
+++ b/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h
@@ -42,7 +42,7 @@ public:
}
~FontCustomPlatformData();
- FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth);
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight, FontWidthVariant = RegularWidth);
static bool supportsFormat(const String&);
diff --git a/Source/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp b/Source/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp
index 9234229..287121b 100644
--- a/Source/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp
+++ b/Source/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp
@@ -115,11 +115,15 @@ void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR*
}
FontPlatformData::FontPlatformData(HFONT hfont, CGFontRef font, float size, bool bold, bool oblique, bool useGDI)
- : m_font(RefCountedGDIHandle<HFONT>::create(hfont))
+ : m_syntheticBold(bold)
+ , m_syntheticOblique(oblique)
+ , m_orientation(Horizontal)
+ , m_textOrientation(TextOrientationVerticalRight)
, m_size(size)
+ , m_widthVariant(RegularWidth)
+ , m_font(RefCountedGDIHandle<HFONT>::create(hfont))
, m_cgFont(font)
- , m_syntheticBold(bold)
- , m_syntheticOblique(oblique)
+ , m_isColorBitmapFont(false)
, m_useGDI(useGDI)
{
}
@@ -128,4 +132,27 @@ FontPlatformData::~FontPlatformData()
{
}
+void FontPlatformData::platformDataInit(const FontPlatformData& source)
+{
+ m_font = source.m_font;
+ m_cgFont = source.m_cgFont;
+ m_useGDI = source.m_useGDI;
+}
+
+const FontPlatformData& FontPlatformData::platformDataAssign(const FontPlatformData& other)
+{
+ m_font = other.m_font;
+ m_cgFont = other.m_cgFont;
+ m_useGDI = other.m_useGDI;
+
+ return *this;
+}
+
+bool FontPlatformData::platformIsEqual(const FontPlatformData& other) const
+{
+ return m_font == other.m_font
+ && m_cgFont == other.m_cgFont
+ && m_useGDI == other.m_useGDI;
+}
+
}
diff --git a/Source/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp b/Source/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp
index 0f5c365..e60b69b 100644
--- a/Source/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp
+++ b/Source/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp
@@ -4,7 +4,7 @@
*
* Copyright (C) 2006, 2007, 2008 Apple Inc.
* Copyright (C) 2007 Alp Toker
- * Copyright (C) 2008, 2010 Brent Fulgham
+ * Copyright (C) 2008, 2010, 2011 Brent Fulgham
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -40,7 +40,7 @@ namespace WebCore {
void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR* faceName)
{
- m_fontFace = cairo_win32_font_face_create_for_hfont(font);
+ cairo_font_face_t* fontFace = cairo_win32_font_face_create_for_hfont(font);
cairo_matrix_t sizeMatrix, ctm;
cairo_matrix_init_identity(&ctm);
@@ -52,14 +52,18 @@ void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR*
cairo_font_options_set_antialias(fontOptions, CAIRO_ANTIALIAS_SUBPIXEL);
}
- m_scaledFont = cairo_scaled_font_create(m_fontFace, &sizeMatrix, &ctm, fontOptions);
+ m_scaledFont = cairo_scaled_font_create(fontFace, &sizeMatrix, &ctm, fontOptions);
+ cairo_font_face_destroy(fontFace);
}
FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool oblique)
: m_font(0)
, m_size(size)
- , m_fontFace(fontFace)
+ , m_orientation(Horizontal)
+ , m_textOrientation(TextOrientationVerticalRight)
+ , m_widthVariant(RegularWidth)
, m_scaledFont(0)
+ , m_isColorBitmapFont(false)
, m_syntheticBold(bold)
, m_syntheticOblique(oblique)
, m_useGDI(false)
@@ -79,64 +83,39 @@ FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool
cairo_font_options_destroy(options);
}
-FontPlatformData::FontPlatformData(const FontPlatformData& source)
- : m_font(source.m_font)
- , m_size(source.m_size)
- , m_fontFace(0)
- , m_scaledFont(0)
- , m_syntheticBold(source.m_syntheticBold)
- , m_syntheticOblique(source.m_syntheticOblique)
- , m_useGDI(source.m_useGDI)
+FontPlatformData::~FontPlatformData()
{
- if (source.m_fontFace)
- m_fontFace = cairo_font_face_reference(source.m_fontFace);
-
- if (source.m_scaledFont)
- m_scaledFont = cairo_scaled_font_reference(source.m_scaledFont);
+ if (m_scaledFont && m_scaledFont != hashTableDeletedFontValue())
+ cairo_scaled_font_destroy(m_scaledFont);
}
-
-FontPlatformData::~FontPlatformData()
+void FontPlatformData::platformDataInit(const FontPlatformData& source)
{
- cairo_scaled_font_destroy(m_scaledFont);
- cairo_font_face_destroy(m_fontFace);
+ m_font = source.m_font;
+ m_useGDI = source.m_useGDI;
+ m_scaledFont = 0;
+
+ if (source.m_scaledFont)
+ m_scaledFont = cairo_scaled_font_reference(source.m_scaledFont);
}
-FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other)
+const FontPlatformData& FontPlatformData::platformDataAssign(const FontPlatformData& other)
{
- // Check for self-assignment.
- if (this == &other)
- return *this;
-
m_font = other.m_font;
- m_size = other.m_size;
- m_syntheticBold = other.m_syntheticBold;
- m_syntheticOblique = other.m_syntheticOblique;
m_useGDI = other.m_useGDI;
- if (other.m_fontFace)
- cairo_font_face_reference(other.m_fontFace);
- if (m_fontFace)
- cairo_font_face_destroy(m_fontFace);
- m_fontFace = other.m_fontFace;
-
- if (other.m_scaledFont)
- cairo_scaled_font_reference(other.m_scaledFont);
- if (m_scaledFont)
+ if (m_scaledFont && m_scaledFont != hashTableDeletedFontValue())
cairo_scaled_font_destroy(m_scaledFont);
- m_scaledFont = other.m_scaledFont;
+
+ m_scaledFont = cairo_scaled_font_reference(other.m_scaledFont);
return *this;
}
-bool FontPlatformData::operator==(const FontPlatformData& other) const
-{
+bool FontPlatformData::platformIsEqual(const FontPlatformData& other) const
+{
return m_font == other.m_font
- && m_fontFace == other.m_fontFace
&& m_scaledFont == other.m_scaledFont
- && m_size == other.m_size
- && m_syntheticBold == other.m_syntheticBold
- && m_syntheticOblique == other.m_syntheticOblique
&& m_useGDI == other.m_useGDI;
}
diff --git a/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp b/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
index 09ed4a6..301198d 100644
--- a/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
+++ b/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
@@ -38,12 +38,15 @@ namespace WebCore {
FontPlatformData::FontPlatformData(HFONT font, float size, bool bold, bool oblique, bool useGDI)
: m_font(RefCountedGDIHandle<HFONT>::create(font))
, m_size(size)
+ , m_orientation(Horizontal)
+ , m_textOrientation(TextOrientationVerticalRight)
+ , m_widthVariant(RegularWidth)
#if PLATFORM(CG)
, m_cgFont(0)
#elif PLATFORM(CAIRO)
- , m_fontFace(0)
, m_scaledFont(0)
#endif
+ , m_isColorBitmapFont(false)
, m_syntheticBold(bold)
, m_syntheticOblique(oblique)
, m_useGDI(useGDI)
@@ -71,20 +74,6 @@ FontPlatformData::FontPlatformData(HFONT font, float size, bool bold, bool obliq
ReleaseDC(0, hdc);
}
-FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
- : m_size(size)
-#if PLATFORM(CG)
- , m_cgFont(0)
-#elif PLATFORM(CAIRO)
- , m_fontFace(0)
- , m_scaledFont(0)
-#endif
- , m_syntheticBold(bold)
- , m_syntheticOblique(oblique)
- , m_useGDI(false)
-{
-}
-
#ifndef NDEBUG
String FontPlatformData::description() const
{
diff --git a/Source/WebCore/platform/graphics/win/FontWin.cpp b/Source/WebCore/platform/graphics/win/FontWin.cpp
index 47c44bc..9e31f56 100644
--- a/Source/WebCore/platform/graphics/win/FontWin.cpp
+++ b/Source/WebCore/platform/graphics/win/FontWin.cpp
@@ -127,8 +127,8 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
UniscribeController controller(this, run, fallbackFonts);
controller.advance(run.length());
if (glyphOverflow) {
- glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - fontMetrics().ascent());
- glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - fontMetrics().descent());
+ glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent()));
+ glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent()));
glyphOverflow->left = max<int>(0, ceilf(-controller.minGlyphBoundingBoxX()));
glyphOverflow->right = max<int>(0, ceilf(controller.maxGlyphBoundingBoxX() - controller.runWidthSoFar()));
}
diff --git a/Source/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp b/Source/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
index b2c702f..7ce7ee9 100644
--- a/Source/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
+++ b/Source/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
@@ -72,18 +72,15 @@ GraphicsContext::GraphicsContext(HDC dc, bool hasAlpha)
void GraphicsContext::platformInit(HDC dc, bool hasAlpha)
{
- m_data = new GraphicsContextPlatformPrivate;
-
- if (dc) {
- m_data->cr = createCairoContextWithHDC(dc, hasAlpha);
- m_data->m_hdc = dc;
- } else {
+ cairo_t* cr = 0;
+ if (dc)
+ cr = createCairoContextWithHDC(dc, hasAlpha);
+ else
setPaintingDisabled(true);
- m_data->cr = 0;
- m_data->m_hdc = 0;
- }
- if (m_data->cr) {
+ m_data = new GraphicsContextPlatformPrivateTopLevel(new PlatformContextCairo(cr));
+ m_data->m_hdc = dc;
+ if (platformContext()->cr()) {
// Make sure the context starts in sync with our state.
setPlatformFillColor(fillColor(), fillColorSpace());
setPlatformStrokeColor(strokeColor(), strokeColorSpace());
@@ -131,24 +128,25 @@ void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, boo
// Scale the target surface to the new image size, and flip it
// so that when we set the srcImage as the surface it will draw
// right-side-up.
- cairo_save(m_data->cr);
- cairo_translate(m_data->cr, dstRect.x(), dstRect.height() + dstRect.y());
- cairo_scale(m_data->cr, 1.0, -1.0);
- cairo_set_source_surface(m_data->cr, image, 0, 0);
+ cairo_t* cr = platformContext()->cr();
+ cairo_save(cr);
+ cairo_translate(cr, dstRect.x(), dstRect.height() + dstRect.y());
+ cairo_scale(cr, 1, -1);
+ cairo_set_source_surface(cr, image, 0, 0);
if (m_data->layers.size())
- cairo_paint_with_alpha(m_data->cr, m_data->layers.last());
+ cairo_paint_with_alpha(cr, m_data->layers.last());
else
- cairo_paint(m_data->cr);
+ cairo_paint(cr);
// Delete all our junk.
cairo_surface_destroy(image);
::DeleteDC(hdc);
::DeleteObject(bitmap);
- cairo_restore(m_data->cr);
+ cairo_restore(cr);
}
-void GraphicsContextPlatformPrivate::syncContext(PlatformGraphicsContext* cr)
+void GraphicsContextPlatformPrivate::syncContext(cairo_t* cr)
{
if (!cr)
return;
diff --git a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
index 40fe1d1..bac85f7 100644
--- a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
+++ b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
@@ -28,8 +28,11 @@
#if ENABLE(VIDEO)
#include "MediaPlayerPrivateQuickTimeVisualContext.h"
+#include "ApplicationCacheHost.h"
+#include "ApplicationCacheResource.h"
#include "Cookie.h"
#include "CookieJar.h"
+#include "DocumentLoader.h"
#include "Frame.h"
#include "FrameView.h"
#include "GraphicsContext.h"
@@ -369,7 +372,16 @@ void MediaPlayerPrivateQuickTimeVisualContext::loadInternal(const String& url)
setUpCookiesForQuickTime(url);
m_movie = adoptRef(new QTMovie(m_movieClient.get()));
- m_movie->load(url.characters(), url.length(), m_player->preservesPitch());
+
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : 0;
+ ApplicationCacheHost* cacheHost = frame ? frame->loader()->documentLoader()->applicationCacheHost() : 0;
+ ApplicationCacheResource* resource = 0;
+ if (cacheHost && cacheHost->shouldLoadResourceFromApplicationCache(ResourceRequest(url), resource) && resource && !resource->path().isEmpty())
+ m_movie->load(resource->path().characters(), resource->path().length(), m_player->preservesPitch());
+ else
+#endif
+ m_movie->load(url.characters(), url.length(), m_player->preservesPitch());
m_movie->setVolume(m_player->volume());
}
diff --git a/Source/WebCore/platform/graphics/win/QTMovie.cpp b/Source/WebCore/platform/graphics/win/QTMovie.cpp
index 05fbb86..6f9c668 100644
--- a/Source/WebCore/platform/graphics/win/QTMovie.cpp
+++ b/Source/WebCore/platform/graphics/win/QTMovie.cpp
@@ -442,6 +442,17 @@ void QTMovie::getNaturalSize(int& width, int& height)
height = (rect.bottom - rect.top) * m_private->m_heightScaleFactor;
}
+void QTMovie::loadPath(const UChar* url, int len, bool preservesPitch)
+{
+ CFStringRef urlStringRef = CFStringCreateWithCharacters(kCFAllocatorDefault, reinterpret_cast<const UniChar*>(url), len);
+ CFURLRef cfURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, urlStringRef, kCFURLWindowsPathStyle, false);
+
+ load(cfURL, preservesPitch);
+
+ CFRelease(cfURL);
+ CFRelease(urlStringRef);
+}
+
void QTMovie::load(const UChar* url, int len, bool preservesPitch)
{
CFStringRef urlStringRef = CFStringCreateWithCharacters(kCFAllocatorDefault, reinterpret_cast<const UniChar*>(url), len);
diff --git a/Source/WebCore/platform/graphics/win/QTMovie.h b/Source/WebCore/platform/graphics/win/QTMovie.h
index e97d16d..38b3473 100644
--- a/Source/WebCore/platform/graphics/win/QTMovie.h
+++ b/Source/WebCore/platform/graphics/win/QTMovie.h
@@ -70,6 +70,7 @@ public:
void addClient(QTMovieClient*);
void removeClient(QTMovieClient*);
+ void loadPath(const UChar* url, int len, bool preservesPitch);
void load(const UChar* url, int len, bool preservesPitch);
void load(CFURLRef, bool preservesPitch);
diff --git a/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp b/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
index 30a931e..12f1127 100644
--- a/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
+++ b/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
@@ -97,18 +97,14 @@ void SimpleFontData::platformInit()
m_fontMetrics.setLineGap(fLineGap);
m_fontMetrics.setLineSpacing(lroundf(fAscent) + lroundf(fDescent) + lroundf(fLineGap));
- // Measure the actual character "x", because AppKit synthesizes X height rather than getting it from the font.
- // Unfortunately, NSFont will round this for us so we don't quite get the right value.
GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
Glyph xGlyph = glyphPageZero ? glyphPageZero->glyphDataForCharacter('x').glyph : 0;
if (xGlyph) {
+ // Measure the actual character "x", since it's possible for it to extend below the baseline, and we need the
+ // reported x-height to only include the portion of the glyph that is above the baseline.
CGRect xBox;
CGFontGetGlyphBBoxes(font, &xGlyph, 1, &xBox);
- // Use the maximum of either width or height because "x" is nearly square
- // and web pages that foolishly use this metric for width will be laid out
- // poorly if we return an accurate height. Classic case is Times 13 point,
- // which has an "x" that is 7x6 pixels.
- m_fontMetrics.setXHeight(scaleEmToUnits(max(CGRectGetMaxX(xBox), CGRectGetMaxY(xBox)), unitsPerEm) * pointSize);
+ m_fontMetrics.setXHeight(scaleEmToUnits(CGRectGetMaxY(xBox), unitsPerEm) * pointSize);
} else {
int iXHeight = CGFontGetXHeight(font);
m_fontMetrics.setXHeight(scaleEmToUnits(iXHeight, unitsPerEm) * pointSize);
diff --git a/Source/WebCore/platform/graphics/win/cairo/FontPlatformData.h b/Source/WebCore/platform/graphics/win/cairo/FontPlatformData.h
deleted file mode 100644
index d8f538a..0000000
--- a/Source/WebCore/platform/graphics/win/cairo/FontPlatformData.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc.
- * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
- * Copyright (C) 2007 Holger Hans Peter Freyther
- * Copyright (C) 2007 Pioneer Research Center USA, Inc.
- * Copyright (C) 2010 Brent Fulgham <bfulgham@webkit.org>
- * All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef FontPlatformDataCairoWin_h
-#define FontPlatformDataCairoWin_h
-
-#include "FontOrientation.h"
-#include "GlyphBuffer.h"
-#include "RefCountedGDIHandle.h"
-#include "StringImpl.h"
-#include <cairo-win32.h>
-#include <cairo.h>
-#include <wtf/Forward.h>
-
-typedef struct HFONT__* HFONT;
-
-namespace WebCore {
-
-class FontDescription;
-
-class FontPlatformData {
-public:
- FontPlatformData(WTF::HashTableDeletedValueType)
- : m_fontFace(0)
- , m_useGDI(false)
- , m_font(WTF::HashTableDeletedValue)
- , m_size(0)
- , m_syntheticBold(false)
- , m_syntheticOblique(false)
- , m_scaledFont(0)
- { }
-
- FontPlatformData()
- : m_fontFace(0)
- , m_useGDI(false)
- , m_size(0)
- , m_syntheticBold(false)
- , m_syntheticOblique(false)
- , m_scaledFont(0)
- { }
-
- FontPlatformData(HFONT, float size, bool bold, bool oblique, bool useGDI);
- FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic);
- FontPlatformData(float size, bool bold, bool italic);
- FontPlatformData(const FontPlatformData&);
- ~FontPlatformData();
-
- HFONT hfont() const { return m_font->handle(); }
- bool useGDI() const { return m_useGDI; }
- cairo_font_face_t* fontFace() const { return m_fontFace; }
-
- bool isFixedPitch();
- float size() const { return m_size; }
- void setSize(float size) { m_size = size; }
- bool syntheticBold() const { return m_syntheticBold; }
- bool syntheticOblique() const { return m_syntheticOblique; }
-
- FontOrientation orientation() const { return Horizontal; } // FIXME: Implement.
-
- cairo_scaled_font_t* scaledFont() const { return m_scaledFont; }
-
- unsigned hash() const
- {
- return m_font->hash();
- }
-
- bool operator==(const FontPlatformData&) const;
- FontPlatformData& operator=(const FontPlatformData&);
- bool isHashTableDeletedValue() const
- {
- return m_font.isHashTableDeletedValue();
- }
-
-#ifndef NDEBUG
- String description() const;
-#endif
-
-private:
- void platformDataInit(HFONT, float size, HDC, WCHAR* faceName);
-
- RefPtr<RefCountedGDIHandle<HFONT> > m_font;
- cairo_font_face_t* m_fontFace;
- bool m_useGDI;
- float m_size;
- bool m_syntheticBold;
- bool m_syntheticOblique;
- cairo_scaled_font_t* m_scaledFont;
-};
-
-}
-
-#endif // FontPlatformDataCairoWin_h
diff --git a/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp
index fb97fe1..07a8756 100644
--- a/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp
+++ b/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp
@@ -45,7 +45,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
g_customFontCache->unregisterFont(m_name);
}
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode renderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode renderingMode)
{
FontDescription fontDesc;
fontDesc.setComputedSize(size);
diff --git a/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.h
index fe7ee94..12a86e9 100644
--- a/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.h
+++ b/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.h
@@ -24,6 +24,7 @@
#include "FontDescription.h"
#include "FontRenderingMode.h"
#include "FontWidthVariant.h"
+#include "TextOrientation.h"
#include "PlatformString.h"
#include <wtf/Noncopyable.h>
@@ -48,7 +49,7 @@ namespace WebCore {
~FontCustomPlatformData();
- FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
static bool supportsFormat(const String&);
diff --git a/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp b/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp
index d9d8a72..d767ac7 100644
--- a/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp
+++ b/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp
@@ -148,7 +148,7 @@ struct FixedSizeFontDataKeyHash {
font.m_weight,
// static_cast<unsigned>(font.m_italic);
};
- return WTF::StringHasher::createBlobHash<sizeof(hashCodes)>(hashCodes);
+ return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
}
static bool equal(const FixedSizeFontDataKey& a, const FixedSizeFontDataKey& b)
diff --git a/Source/WebCore/platform/graphics/wince/FontPlatformData.h b/Source/WebCore/platform/graphics/wince/FontPlatformData.h
index e73a7b2..9c3f733 100644
--- a/Source/WebCore/platform/graphics/wince/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/wince/FontPlatformData.h
@@ -79,6 +79,7 @@ namespace WebCore {
static LONG adjustedGDIFontWeight(LONG gdiFontWeight, const String& family);
FontOrientation orientation() const { return Horizontal; } // FIXME: Implement.
+ void setOrientation(FontOrientation) { } // FIXME: Implement.
#ifndef NDEBUG
String description() const;
diff --git a/Source/WebCore/platform/graphics/wince/PathWinCE.cpp b/Source/WebCore/platform/graphics/wince/PathWinCE.cpp
index fa4c8fb..9c9112b 100644
--- a/Source/WebCore/platform/graphics/wince/PathWinCE.cpp
+++ b/Source/WebCore/platform/graphics/wince/PathWinCE.cpp
@@ -133,7 +133,7 @@ void Path::transform(const AffineTransform& t)
m_path->transform(t);
}
-FloatRect Path::strokeBoundingRect(StrokeStyleApplier *)
+FloatRect Path::strokeBoundingRect(StrokeStyleApplier*) const
{
notImplemented();
return FloatRect();
diff --git a/Source/WebCore/platform/graphics/wx/FontPlatformData.h b/Source/WebCore/platform/graphics/wx/FontPlatformData.h
index 3ef0179..8a2c4a0 100644
--- a/Source/WebCore/platform/graphics/wx/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/wx/FontPlatformData.h
@@ -150,6 +150,7 @@ public:
bool allowsLigatures() const { return false; }
FontOrientation orientation() const { return Horizontal; } // FIXME: Implement.
+ void setOrientation(FontOrientation) { } // FIXME: Implement.
// We don't support this yet, so just return the default value for now.
FontWidthVariant widthVariant() const { return RegularWidth; }
diff --git a/Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp b/Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
index c125b7c..830cd05 100644
--- a/Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
+++ b/Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
@@ -126,10 +126,10 @@ unsigned FontPlatformData::computeHash() const
thisFont->GetStyle(),
thisFont->GetWeight(),
thisFont->GetUnderlined(),
- WTF::StringHasher::createHash(thisFont->GetFaceName().utf8_str().data())
+ StringHasher::computeHash(thisFont->GetFaceName().utf8_str().data())
};
- return WTF::StringHasher::createBlobHash<sizeof(hashCodes)>(hashCodes);
+ return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
}
FontPlatformData::~FontPlatformData()
diff --git a/Source/WebCore/platform/graphics/wx/PathWx.cpp b/Source/WebCore/platform/graphics/wx/PathWx.cpp
index f5355f2..a95cc1c 100644
--- a/Source/WebCore/platform/graphics/wx/PathWx.cpp
+++ b/Source/WebCore/platform/graphics/wx/PathWx.cpp
@@ -105,7 +105,7 @@ FloatRect Path::boundingRect() const
return FloatRect();
}
-FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
+FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const
{
notImplemented();
return FloatRect();
diff --git a/Source/WebCore/platform/gtk/FileSystemGtk.cpp b/Source/WebCore/platform/gtk/FileSystemGtk.cpp
index b3c4c9f..e2b1642 100644
--- a/Source/WebCore/platform/gtk/FileSystemGtk.cpp
+++ b/Source/WebCore/platform/gtk/FileSystemGtk.cpp
@@ -227,16 +227,16 @@ Vector<String> listDirectory(const String& path, const String& filter)
return entries;
}
-CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
+String openTemporaryFile(const String& prefix, PlatformFileHandle& handle)
{
- GOwnPtr<gchar> filename(g_strdup_printf("%s%s", prefix, createCanonicalUUIDString().utf8().data()));
+ GOwnPtr<gchar> filename(g_strdup_printf("%s%s", prefix.utf8().data(), createCanonicalUUIDString().utf8().data()));
GOwnPtr<gchar> tempPath(g_build_filename(g_get_tmp_dir(), filename.get(), NULL));
GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(tempPath.get()));
handle = g_file_create_readwrite(file.get(), G_FILE_CREATE_NONE, 0, 0);
if (!isHandleValid(handle))
- return CString();
- return tempPath.get();
+ return String();
+ return String::fromUTF8(tempPath.get());
}
PlatformFileHandle openFile(const String& path, FileOpenMode mode)
diff --git a/Source/WebCore/platform/gtk/LocalizedStringsGtk.cpp b/Source/WebCore/platform/gtk/LocalizedStringsGtk.cpp
index eab0ac6..02f6c47 100644
--- a/Source/WebCore/platform/gtk/LocalizedStringsGtk.cpp
+++ b/Source/WebCore/platform/gtk/LocalizedStringsGtk.cpp
@@ -259,7 +259,7 @@ String contextMenuItemTagSearchWeb()
return String::fromUTF8(_("_Search the Web"));
}
-String contextMenuItemTagLookUpInDictionary()
+String contextMenuItemTagLookUpInDictionary(const String&)
{
return String::fromUTF8(_("_Look Up in Dictionary"));
}
diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk.cpp b/Source/WebCore/platform/gtk/RenderThemeGtk.cpp
index 1e9f159..9b11c27 100644
--- a/Source/WebCore/platform/gtk/RenderThemeGtk.cpp
+++ b/Source/WebCore/platform/gtk/RenderThemeGtk.cpp
@@ -34,6 +34,7 @@
#include "HTMLNames.h"
#include "MediaControlElements.h"
#include "PaintInfo.h"
+#include "PlatformContextCairo.h"
#include "RenderBox.h"
#include "RenderObject.h"
#include "TimeRanges.h"
@@ -234,7 +235,7 @@ static void paintGdkPixbuf(GraphicsContext* context, const GdkPixbuf* icon, cons
icon = scaledIcon.get();
}
- cairo_t* cr = context->platformContext();
+ cairo_t* cr = context->platformContext()->cr();
cairo_save(cr);
gdk_cairo_set_source_pixbuf(cr, icon, iconRect.x(), iconRect.y());
cairo_paint(cr);
diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk.h b/Source/WebCore/platform/gtk/RenderThemeGtk.h
index f5e03a9..191a34b 100644
--- a/Source/WebCore/platform/gtk/RenderThemeGtk.h
+++ b/Source/WebCore/platform/gtk/RenderThemeGtk.h
@@ -214,6 +214,7 @@ private:
GtkWidget* gtkComboBoxButton() const;
GtkWidget* gtkComboBoxArrow() const;
GtkWidget* gtkComboBoxSeparator() const;
+ GtkWidget* gtkSpinButton() const;
GdkColormap* m_colormap;
mutable GtkWidget* m_gtkWindow;
@@ -232,6 +233,7 @@ private:
mutable GtkWidget* m_gtkComboBoxSeparator;
mutable GtkWidget* m_gtkVScrollbar;
mutable GtkWidget* m_gtkHScrollbar;
+ mutable GtkWidget* m_gtkSpinButton;
bool m_themePartsHaveRGBAColormap;
friend class WidgetRenderingContext;
#endif
diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk2.cpp b/Source/WebCore/platform/gtk/RenderThemeGtk2.cpp
index 534aa97..5149bea 100644
--- a/Source/WebCore/platform/gtk/RenderThemeGtk2.cpp
+++ b/Source/WebCore/platform/gtk/RenderThemeGtk2.cpp
@@ -46,6 +46,9 @@
namespace WebCore {
+// This is the default value defined by GTK+, where it was defined as MIN_ARROW_WIDTH in gtkspinbutton.c.
+static const int minSpinButtonArrowSize = 6;
+
// This is not a static method, because we want to avoid having GTK+ headers in RenderThemeGtk.h.
extern GtkTextDirection gtkTextDirection(TextDirection);
@@ -68,6 +71,7 @@ void RenderThemeGtk::platformInit()
m_gtkComboBoxSeparator = 0;
m_gtkVScrollbar = 0;
m_gtkHScrollbar = 0;
+ m_gtkSpinButton = 0;
m_colormap = gdk_screen_get_rgba_colormap(gdk_screen_get_default());
if (!m_colormap) {
@@ -117,6 +121,10 @@ void RenderThemeGtk::adjustRepaintRect(const RenderObject* renderObject, IntRect
adjustRectForFocus(part == CheckboxPart ? gtkCheckButton() : gtkRadioButton(), rect, true);
return;
}
+ case InnerSpinButtonPart:
+ // See paintInnerSpinButton for an explanation of why we expand the painting rect.
+ rect.inflateY(2);
+ rect.setWidth(rect.width() + 2);
default:
return;
}
@@ -566,13 +574,84 @@ bool RenderThemeGtk::paintProgressBar(RenderObject* renderObject, const PaintInf
}
#endif
-void RenderThemeGtk::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderThemeGtk::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
{
+ GtkStyle* gtkStyle = gtk_widget_get_style(gtkSpinButton());
+ const PangoFontDescription* fontDescription = gtkStyle->font_desc;
+ gint fontSize = pango_font_description_get_size(fontDescription);
+
+ // Force an odd arrow size here. GTK+ 3.x forces even in this case, but
+ // Nodoka-based themes look incorrect with an even arrow size.
+ int width = max(PANGO_PIXELS(fontSize), minSpinButtonArrowSize);
+ width += -((width % 2) - 1) + gtkStyle->xthickness;
+
+ style->setWidth(Length(width, Fixed));
+ style->setMinWidth(Length(width, Fixed));
}
-bool RenderThemeGtk::paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&)
+bool RenderThemeGtk::paintInnerSpinButton(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
- return true;
+ // We expand the painted area by 2 pixels on the top and bottom and 2 pixels on the right. This
+ // is because GTK+ themes want to draw over the text box borders, but WebCore renders the inner
+ // spin button inside the text box.
+ IntRect expandedRect(rect);
+ expandedRect.inflateY(2);
+ expandedRect.setWidth(rect.width() + 2);
+
+ WidgetRenderingContext widgetContext(paintInfo.context, expandedRect);
+ GtkWidget* widget = gtkSpinButton();
+ gtk_widget_set_direction(widget, gtkTextDirection(renderObject->style()->direction()));
+
+ IntRect fullSpinButtonRect(IntPoint(), expandedRect.size());
+ widgetContext.gtkPaintBox(fullSpinButtonRect, widget, GTK_STATE_NORMAL, GTK_SHADOW_IN, "spinbutton");
+
+ bool upPressed = isSpinUpButtonPartPressed(renderObject);
+ bool upHovered = isSpinUpButtonPartHovered(renderObject);
+ bool controlActive = isEnabled(renderObject) && !isReadOnlyControl(renderObject);
+ GtkShadowType shadowType = upPressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
+
+ GtkStateType stateType = GTK_STATE_INSENSITIVE;
+ if (controlActive) {
+ if (isPressed(renderObject) && upPressed)
+ stateType = GTK_STATE_ACTIVE;
+ else if (isHovered(renderObject) && upHovered)
+ stateType = GTK_STATE_PRELIGHT;
+ else
+ stateType = GTK_STATE_NORMAL;
+ }
+ IntRect topRect(IntPoint(), expandedRect.size());
+ topRect.setHeight(expandedRect.height() / 2);
+ widgetContext.gtkPaintBox(topRect, widget, stateType, shadowType, "spinbutton_up");
+
+ // The arrow size/position calculation here is based on the arbitrary gymnastics that happen
+ // in gtkspinbutton.c. It isn't pretty there and it isn't pretty here. This manages to make
+ // the button look native for many themes though.
+ IntRect arrowRect;
+ int arrowSize = (expandedRect.width() - 3) / 2;
+ arrowSize -= (arrowSize % 2) - 1; // Force odd.
+ arrowRect.setWidth(arrowSize);
+ arrowRect.setHeight(arrowSize);
+ arrowRect.move((expandedRect.width() - arrowRect.width()) / 2,
+ (topRect.height() - arrowRect.height()) / 2 + 1);
+ widgetContext.gtkPaintArrow(arrowRect, widget, stateType, shadowType, GTK_ARROW_UP, "spinbutton");
+
+ shadowType = isPressed(renderObject) && !upPressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
+ if (controlActive) {
+ if (isPressed(renderObject) && !upPressed)
+ stateType = GTK_STATE_ACTIVE;
+ else if (isHovered(renderObject) && !upHovered)
+ stateType = GTK_STATE_PRELIGHT;
+ else
+ stateType = GTK_STATE_NORMAL;
+ }
+ IntRect bottomRect(IntPoint(0, expandedRect.height() / 2), expandedRect.size());
+ bottomRect.setHeight(expandedRect.height() - bottomRect.y());
+ widgetContext.gtkPaintBox(bottomRect, widget, stateType, shadowType, "spinbutton_down");
+
+ arrowRect.setY(arrowRect.y() + bottomRect.y() - 1);
+ widgetContext.gtkPaintArrow(arrowRect, widget, stateType, shadowType, GTK_ARROW_DOWN, "spinbutton");
+
+ return false;
}
GRefPtr<GdkPixbuf> RenderThemeGtk::getStockIcon(GType widgetType, const char* iconName, gint direction, gint state, gint iconSize)
@@ -867,6 +946,15 @@ GtkWidget* RenderThemeGtk::gtkVScrollbar() const
return m_gtkVScrollbar;
}
+GtkWidget* RenderThemeGtk::gtkSpinButton() const
+{
+ if (m_gtkSpinButton)
+ return m_gtkSpinButton;
+ m_gtkSpinButton = gtk_spin_button_new_with_range(0, 10, 1);
+ setupWidgetAndAddToContainer(m_gtkSpinButton, gtkContainer());
+ return m_gtkSpinButton;
+}
+
} // namespace WebCore
#endif // GTK_API_VERSION_2
diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp b/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp
index 7fa0f04..527de1a 100644
--- a/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp
+++ b/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp
@@ -483,14 +483,14 @@ bool RenderThemeGtk::paintMenuList(RenderObject* renderObject, const PaintInfo&
gtk_style_context_get_style(arrowStyleContext, "arrow-scaling", &arrowScaling, NULL);
IntSize arrowSize(minArrowSize, innerRect.height());
- IntPoint arrowPosition = innerRect.location();
+ FloatPoint arrowPosition(innerRect.location());
if (direction == GTK_TEXT_DIR_LTR)
arrowPosition.move(innerRect.width() - arrowSize.width(), 0);
// GTK+ actually fetches the xalign and valign values from the widget, but since we
// don't have a widget here, we are just using the default xalign and valign values of 0.5.
gint extent = std::min(arrowSize.width(), arrowSize.height()) * arrowScaling;
- arrowPosition.move(std::floor((arrowSize.width() - extent) / 2), std::floor((arrowSize.height() - extent) / 2));
+ arrowPosition.move((arrowSize.width() - extent) / 2, (arrowSize.height() - extent) / 2);
gtk_style_context_set_state(arrowStyleContext, state);
gtk_render_arrow(arrowStyleContext, cairoContext, G_PI, arrowPosition.x(), arrowPosition.y(), extent);
diff --git a/Source/WebCore/platform/gtk/ScrollViewGtk.cpp b/Source/WebCore/platform/gtk/ScrollViewGtk.cpp
index c5f32f3..53cacf7 100644
--- a/Source/WebCore/platform/gtk/ScrollViewGtk.cpp
+++ b/Source/WebCore/platform/gtk/ScrollViewGtk.cpp
@@ -31,6 +31,8 @@
#include "config.h"
#include "ScrollView.h"
+#if USE(NATIVE_GTK_MAIN_FRAME_SCROLLBAR)
+
#include "ChromeClient.h"
#include "FloatRect.h"
#include "Frame.h"
@@ -44,7 +46,6 @@
#include "PlatformMouseEvent.h"
#include "PlatformWheelEvent.h"
#include "ScrollbarTheme.h"
-
#include <gtk/gtk.h>
using namespace std;
@@ -228,3 +229,5 @@ void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode v
}
}
+
+#endif // USE(NATIVE_GTK_MAIN_FRAME_SCROLLBAR)
diff --git a/Source/WebCore/platform/gtk/ScrollbarThemeGtk3.cpp b/Source/WebCore/platform/gtk/ScrollbarThemeGtk3.cpp
index d000063..b0b5146 100644
--- a/Source/WebCore/platform/gtk/ScrollbarThemeGtk3.cpp
+++ b/Source/WebCore/platform/gtk/ScrollbarThemeGtk3.cpp
@@ -135,40 +135,16 @@ void ScrollbarThemeGtk::paintButton(GraphicsContext* context, Scrollbar* scrollb
flags |= GTK_STATE_FLAG_INSENSITIVE;
gtk_style_context_set_state(m_context, static_cast<GtkStateFlags>(flags));
- guint sides = gtk_style_context_get_junction_sides(m_context);
- if (scrollbar->orientation() == VerticalScrollbar)
- sides &= ~(GTK_JUNCTION_TOP | GTK_JUNCTION_BOTTOM);
- else
- sides &= ~(GTK_JUNCTION_LEFT | GTK_JUNCTION_RIGHT);
-
- switch (part) {
- case BackButtonStartPart:
- sides |= (scrollbar->orientation() == VerticalScrollbar) ? GTK_JUNCTION_BOTTOM : GTK_JUNCTION_RIGHT;
- break;
- case BackButtonEndPart:
- case ForwardButtonEndPart:
- sides |= (scrollbar->orientation() == VerticalScrollbar) ?
- GTK_JUNCTION_TOP | GTK_JUNCTION_BOTTOM : GTK_JUNCTION_RIGHT | GTK_JUNCTION_LEFT;
- break;
- case ForwardButtonStartPart:
- sides |= (scrollbar->orientation() == VerticalScrollbar) ? GTK_JUNCTION_TOP : GTK_JUNCTION_LEFT;
- break;
- default:
- ASSERT_NOT_REACHED();
- }
- gtk_style_context_set_junction_sides(m_context, static_cast<GtkJunctionSides>(sides));
gtk_style_context_add_class(m_context, GTK_STYLE_CLASS_BUTTON);
-
gtk_render_background(m_context, context->platformContext(), rect.x(), rect.y(), rect.width(), rect.height());
gtk_render_frame(m_context, context->platformContext(), rect.x(), rect.y(), rect.width(), rect.height());
gfloat arrowScaling;
gtk_style_context_get_style(m_context, "arrow-scaling", &arrowScaling, NULL);
- IntSize arrowSize = rect.size();
- arrowSize.scale(arrowScaling);
- IntPoint arrowPoint(rect.x() + (rect.width() - arrowSize.width()) / 2,
- rect.y() + (rect.height() - arrowSize.height()) / 2);
+ double arrowSize = std::min(rect.width(), rect.height()) * arrowScaling;
+ FloatPoint arrowPoint(rect.x() + (rect.width() - arrowSize) / 2,
+ rect.y() + (rect.height() - arrowSize) / 2);
if (flags & GTK_STATE_FLAG_ACTIVE) {
gint arrowDisplacementX, arrowDisplacementY;
@@ -179,16 +155,14 @@ void ScrollbarThemeGtk::paintButton(GraphicsContext* context, Scrollbar* scrollb
arrowPoint.move(arrowDisplacementX, arrowDisplacementY);
}
- gdouble angle, size;
+ gdouble angle;
if (scrollbar->orientation() == VerticalScrollbar) {
- size = arrowSize.width();
angle = (part == ForwardButtonEndPart || part == ForwardButtonStartPart) ? G_PI : 0;
} else {
- size = arrowSize.height();
angle = (part == ForwardButtonEndPart || part == ForwardButtonStartPart) ? G_PI / 2 : 3 * (G_PI / 2);
}
- gtk_render_arrow(m_context, context->platformContext(), angle, arrowPoint.x(), arrowPoint.y(), size);
+ gtk_render_arrow(m_context, context->platformContext(), angle, arrowPoint.x(), arrowPoint.y(), arrowSize);
gtk_style_context_restore(m_context);
}
diff --git a/Source/WebCore/platform/gtk/WidgetGtk.cpp b/Source/WebCore/platform/gtk/WidgetGtk.cpp
index f251772..0ab3940 100644
--- a/Source/WebCore/platform/gtk/WidgetGtk.cpp
+++ b/Source/WebCore/platform/gtk/WidgetGtk.cpp
@@ -41,8 +41,6 @@
namespace WebCore {
-static GdkCursor* lastSetCursor;
-
Widget::Widget(PlatformWidget widget)
{
init(widget);
@@ -60,11 +58,6 @@ void Widget::setFocus(bool focused)
gtk_widget_grab_focus(platformWidget() ? platformWidget() : GTK_WIDGET(root()->hostWindow()->platformPageClient()));
}
-static GdkWindow* gdkWindow(PlatformWidget widget)
-{
- return widget ? gtk_widget_get_window(widget) : 0;
-}
-
void Widget::setCursor(const Cursor& cursor)
{
ScrollView* view = root();
diff --git a/Source/WebCore/platform/gtk/WidgetRenderingContext.cpp b/Source/WebCore/platform/gtk/WidgetRenderingContext.cpp
index 9e640f6..6f7389d 100644
--- a/Source/WebCore/platform/gtk/WidgetRenderingContext.cpp
+++ b/Source/WebCore/platform/gtk/WidgetRenderingContext.cpp
@@ -33,6 +33,7 @@
#include "GraphicsContext.h"
#include "GtkVersioning.h"
+#include "PlatformContextCairo.h"
#include "RefPtrCairo.h"
#include "RenderThemeGtk.h"
#include "Timer.h"
@@ -128,7 +129,7 @@ WidgetRenderingContext::~WidgetRenderingContext()
}
// FIXME: It's unclear if it is necessary to preserve the current source here.
- cairo_t* cairoContext = m_graphicsContext->platformContext();
+ cairo_t* cairoContext = m_graphicsContext->platformContext()->cr();
RefPtr<cairo_pattern_t> previousSource(cairo_get_source(cairoContext));
// The blit rectangle is the original target rectangle adjusted for any extra space.
diff --git a/Source/WebCore/platform/haiku/FileSystemHaiku.cpp b/Source/WebCore/platform/haiku/FileSystemHaiku.cpp
index b0d34f2..7985c54 100644
--- a/Source/WebCore/platform/haiku/FileSystemHaiku.cpp
+++ b/Source/WebCore/platform/haiku/FileSystemHaiku.cpp
@@ -56,11 +56,11 @@ String homeDirectoryPath()
return String(path.Path());
}
-CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
+String openTemporaryFile(const String&, PlatformFileHandle& handle)
{
notImplemented();
handle = invalidPlatformFileHandle;
- return CString();
+ return String();
}
void closeFile(PlatformFileHandle&)
diff --git a/Source/WebCore/platform/haiku/LocalizedStringsHaiku.cpp b/Source/WebCore/platform/haiku/LocalizedStringsHaiku.cpp
index 63b9b91..c1f3641 100644
--- a/Source/WebCore/platform/haiku/LocalizedStringsHaiku.cpp
+++ b/Source/WebCore/platform/haiku/LocalizedStringsHaiku.cpp
@@ -213,7 +213,7 @@ String contextMenuItemTagSearchWeb()
return "Search web";
}
-String contextMenuItemTagLookUpInDictionary()
+String contextMenuItemTagLookUpInDictionary(const String&)
{
return "Lookup in dictionary";
}
diff --git a/Source/WebCore/platform/image-decoders/ImageDecoder.h b/Source/WebCore/platform/image-decoders/ImageDecoder.h
index 2a307c5..801daf3 100644
--- a/Source/WebCore/platform/image-decoders/ImageDecoder.h
+++ b/Source/WebCore/platform/image-decoders/ImageDecoder.h
@@ -62,7 +62,7 @@ namespace WebCore {
DisposeNotSpecified, // Leave frame in framebuffer
DisposeKeep, // Leave frame in framebuffer
DisposeOverwriteBgcolor, // Clear frame to transparent
- DisposeOverwritePrevious, // Clear frame to previous framebuffer
+ DisposeOverwritePrevious // Clear frame to previous framebuffer
// contents
};
#if USE(SKIA) || PLATFORM(QT)
diff --git a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
index 8edfe36..8419a97 100644
--- a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
@@ -241,11 +241,11 @@ void PNGImageDecoder::headerAvailable()
{
png_structp png = m_reader->pngPtr();
png_infop info = m_reader->infoPtr();
- png_uint_32 width = png->width;
- png_uint_32 height = png->height;
+ 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 (png->width > cMaxPNGSize || png->height > cMaxPNGSize) {
+ if (width > cMaxPNGSize || height > cMaxPNGSize) {
longjmp(JMPBUF(png), 1);
return;
}
@@ -318,9 +318,14 @@ void PNGImageDecoder::headerAvailable()
m_reader->setHasAlpha(channels == 4);
if (m_reader->decodingSizeOnly()) {
- // If we only needed the size, halt the reader.
+ // If we only needed the size, halt the reader.
+#if defined(PNG_LIBPNG_VER_MAJOR) && defined(PNG_LIBPNG_VER_MINOR) && (PNG_LIBPNG_VER_MAJOR > 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 5))
+ // '0' argument to png_process_data_pause means: Do not cache unprocessed data.
+ m_reader->setReadOffset(m_reader->currentBufferSize() - png_process_data_pause(png, 0));
+#else
m_reader->setReadOffset(m_reader->currentBufferSize() - png->buffer_size);
png->buffer_size = 0;
+#endif
}
}
@@ -343,7 +348,7 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex,
// For PNGs, the frame always fills the entire image.
buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
- if (m_reader->pngPtr()->interlaced)
+ if (png_get_interlace_type(m_reader->pngPtr(), m_reader->infoPtr()) != PNG_INTERLACE_NONE)
m_reader->createInterlaceBuffer((m_reader->hasAlpha() ? 4 : 3) * size().width() * size().height());
}
diff --git a/Source/WebCore/platform/image-encoders/skia/JPEGImageEncoder.cpp b/Source/WebCore/platform/image-encoders/skia/JPEGImageEncoder.cpp
index be3c92a..f0ac601 100644
--- a/Source/WebCore/platform/image-encoders/skia/JPEGImageEncoder.cpp
+++ b/Source/WebCore/platform/image-encoders/skia/JPEGImageEncoder.cpp
@@ -31,6 +31,7 @@
#include "config.h"
#include "JPEGImageEncoder.h"
+#include "ImageData.h"
#include "IntSize.h"
#include "SkBitmap.h"
#include "SkColorPriv.h"
@@ -79,22 +80,29 @@ static void handleError(j_common_ptr common)
longjmp(*jumpBufferPtr, -1);
}
-static void preMultipliedBGRAtoRGB(const SkPMColor* input, unsigned int pixels, unsigned char* output)
+static void preMultipliedBGRAtoRGB(const void* pixels, unsigned int pixelCount, unsigned char* output)
{
- for (; pixels-- > 0; ++input) {
+ const SkPMColor* input = static_cast<const SkPMColor*>(pixels);
+ for (; pixelCount-- > 0; ++input) {
*output++ = SkGetPackedR32(*input);
*output++ = SkGetPackedG32(*input);
*output++ = SkGetPackedB32(*input);
}
}
-bool JPEGImageEncoder::encode(const SkBitmap& bitmap, int quality, Vector<unsigned char>* output)
+static void RGBAtoRGB(const unsigned char* input, unsigned int pixels, unsigned char* output)
{
- if (bitmap.config() != SkBitmap::kARGB_8888_Config)
- return false; // Only support ARGB 32 bpp skia bitmaps.
+ for (; pixels-- > 0; input += 4) {
+ *output++ = input[0];
+ *output++ = input[1];
+ *output++ = input[2];
+ }
+}
- SkAutoLockPixels bitmapLock(bitmap);
- IntSize imageSize(bitmap.width(), bitmap.height());
+static bool encodePixels(const IntSize& inputSize, unsigned char* inputPixels,
+ bool premultiplied, int quality, Vector<unsigned char>* output)
+{
+ IntSize imageSize(inputSize);
imageSize.clampNegativeToZero();
JPEGOutputBuffer destination;
destination.output = output;
@@ -126,12 +134,15 @@ bool JPEGImageEncoder::encode(const SkBitmap& bitmap, int quality, Vector<unsign
jpeg_set_quality(&cinfo, quality, TRUE);
jpeg_start_compress(&cinfo, TRUE);
- const SkPMColor* pixels = static_cast<SkPMColor*>(bitmap.getPixels());
+ unsigned char* pixels = inputPixels;
row.resize(cinfo.image_width * cinfo.input_components);
while (cinfo.next_scanline < cinfo.image_height) {
- preMultipliedBGRAtoRGB(pixels, cinfo.image_width, row.data());
+ if (premultiplied)
+ preMultipliedBGRAtoRGB(pixels, cinfo.image_width, row.data());
+ else
+ RGBAtoRGB(pixels, cinfo.image_width, row.data());
jpeg_write_scanlines(&cinfo, row.dataSlot(), 1);
- pixels += cinfo.image_width;
+ pixels += cinfo.image_width * 4;
}
jpeg_finish_compress(&cinfo);
@@ -139,4 +150,22 @@ bool JPEGImageEncoder::encode(const SkBitmap& bitmap, int quality, Vector<unsign
return true;
}
+bool JPEGImageEncoder::encode(const SkBitmap& bitmap, int quality, Vector<unsigned char>* output)
+{
+ if (bitmap.config() != SkBitmap::kARGB_8888_Config)
+ return false; // Only support ARGB 32 bpp skia bitmaps.
+
+ SkAutoLockPixels bitmapLock(bitmap);
+ IntSize imageSize(bitmap.width(), bitmap.height());
+
+ return encodePixels(imageSize, static_cast<unsigned char *>(bitmap.getPixels()),
+ true, quality, output);
+}
+
+bool JPEGImageEncoder::encode(const ImageData& imageData, int quality, Vector<unsigned char>* output)
+{
+ return encodePixels(imageData.size(), imageData.data()->data()->data(),
+ false, quality, output);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/image-encoders/skia/JPEGImageEncoder.h b/Source/WebCore/platform/image-encoders/skia/JPEGImageEncoder.h
index f2ac52d..122725d 100644
--- a/Source/WebCore/platform/image-encoders/skia/JPEGImageEncoder.h
+++ b/Source/WebCore/platform/image-encoders/skia/JPEGImageEncoder.h
@@ -31,16 +31,19 @@
#ifndef JPEGImageEncoder_h
#define JPEGImageEncoder_h
-#include "Vector.h"
+#include <wtf/Vector.h>
class SkBitmap;
namespace WebCore {
+class ImageData;
+
class JPEGImageEncoder {
public:
- // Encode the input bitmap with a compression quality in [0-100].
+ // Encode the input data with a compression quality in [0-100].
static bool encode(const SkBitmap&, int quality, Vector<unsigned char>*);
+ static bool encode(const ImageData&, int quality, Vector<unsigned char>*);
// For callers: provide a reasonable compression quality default.
enum Quality { DefaultCompressionQuality = 92 };
diff --git a/Source/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp b/Source/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp
index 78f737e..2fc758e 100644
--- a/Source/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp
+++ b/Source/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp
@@ -31,6 +31,7 @@
#include "config.h"
#include "PNGImageEncoder.h"
+#include "ImageData.h"
#include "IntSize.h"
#include "SkBitmap.h"
#include "SkColorPriv.h"
@@ -46,11 +47,12 @@ static void writeOutput(png_structp png, png_bytep data, png_size_t size)
static_cast<Vector<unsigned char>*>(png->io_ptr)->append(data, size);
}
-static void preMultipliedBGRAtoRGBA(const SkPMColor* input, int pixels, unsigned char* output)
+static void preMultipliedBGRAtoRGBA(const void* pixels, int pixelCount, unsigned char* output)
{
static const SkUnPreMultiply::Scale* scale = SkUnPreMultiply::GetScaleTable();
+ const SkPMColor* input = static_cast<const SkPMColor*>(pixels);
- for (; pixels-- > 0; ++input) {
+ for (; pixelCount-- > 0; ++input) {
const unsigned alpha = SkGetPackedA32(*input);
if ((alpha != 0) && (alpha != 255)) {
*output++ = SkUnPreMultiply::ApplyScale(scale[alpha], SkGetPackedR32(*input));
@@ -66,13 +68,10 @@ static void preMultipliedBGRAtoRGBA(const SkPMColor* input, int pixels, unsigned
}
}
-bool PNGImageEncoder::encode(const SkBitmap& bitmap, Vector<unsigned char>* output)
+static bool encodePixels(const IntSize& inputSize, unsigned char* inputPixels,
+ bool premultiplied, Vector<unsigned char>* output)
{
- if (bitmap.config() != SkBitmap::kARGB_8888_Config)
- return false; // Only support ARGB 32 bpp skia bitmaps.
-
- SkAutoLockPixels bitmapLock(bitmap);
- IntSize imageSize(bitmap.width(), bitmap.height());
+ IntSize imageSize(inputSize);
imageSize.clampNegativeToZero();
Vector<unsigned char> row;
@@ -100,12 +99,15 @@ bool PNGImageEncoder::encode(const SkBitmap& bitmap, Vector<unsigned char>* outp
8, PNG_COLOR_TYPE_RGB_ALPHA, 0, 0, 0);
png_write_info(png, info);
- const SkPMColor* pixels = static_cast<SkPMColor*>(bitmap.getPixels());
- row.resize(imageSize.width() * bitmap.bytesPerPixel());
+ unsigned char* pixels = inputPixels;
+ row.resize(imageSize.width() * sizeof(SkPMColor));
for (int y = 0; y < imageSize.height(); ++y) {
- preMultipliedBGRAtoRGBA(pixels, imageSize.width(), row.data());
- png_write_row(png, row.data());
- pixels += imageSize.width();
+ if (premultiplied) {
+ preMultipliedBGRAtoRGBA(pixels, imageSize.width(), row.data());
+ png_write_row(png, row.data());
+ } else
+ png_write_row(png, pixels);
+ pixels += imageSize.width() * 4;
}
png_write_end(png, info);
@@ -113,4 +115,19 @@ bool PNGImageEncoder::encode(const SkBitmap& bitmap, Vector<unsigned char>* outp
return true;
}
+bool PNGImageEncoder::encode(const SkBitmap& bitmap, Vector<unsigned char>* output)
+{
+ if (bitmap.config() != SkBitmap::kARGB_8888_Config)
+ return false; // Only support ARGB 32 bpp skia bitmaps.
+
+ SkAutoLockPixels bitmapLock(bitmap);
+ IntSize imageSize(bitmap.width(), bitmap.height());
+ return encodePixels(imageSize, static_cast<unsigned char*>(bitmap.getPixels()), true, output);
+}
+
+bool PNGImageEncoder::encode(const ImageData& bitmap, Vector<unsigned char>* output)
+{
+ return encodePixels(bitmap.size(), bitmap.data()->data()->data(), false, output);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/image-encoders/skia/PNGImageEncoder.h b/Source/WebCore/platform/image-encoders/skia/PNGImageEncoder.h
index b8dfec3..31edad3 100644
--- a/Source/WebCore/platform/image-encoders/skia/PNGImageEncoder.h
+++ b/Source/WebCore/platform/image-encoders/skia/PNGImageEncoder.h
@@ -31,16 +31,19 @@
#ifndef PNGImageEncoder_h
#define PNGImageEncoder_h
-#include "Vector.h"
+#include <wtf/Vector.h>
class SkBitmap;
namespace WebCore {
+class ImageData;
+
// Interface for encoding PNG data. This is a wrapper around libpng.
class PNGImageEncoder {
public:
static bool encode(const SkBitmap&, Vector<unsigned char>* output);
+ static bool encode(const ImageData&, Vector<unsigned char>* output);
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/mac/FileSystemMac.mm b/Source/WebCore/platform/mac/FileSystemMac.mm
index 8cdd382..a9cbcf4 100644
--- a/Source/WebCore/platform/mac/FileSystemMac.mm
+++ b/Source/WebCore/platform/mac/FileSystemMac.mm
@@ -41,28 +41,29 @@ String homeDirectoryPath()
return NSHomeDirectory();
}
-CString openTemporaryFile(const char* prefix, PlatformFileHandle& platformFileHandle)
+String openTemporaryFile(const String& prefix, PlatformFileHandle& platformFileHandle)
{
platformFileHandle = invalidPlatformFileHandle;
Vector<char> temporaryFilePath(PATH_MAX);
if (!confstr(_CS_DARWIN_USER_TEMP_DIR, temporaryFilePath.data(), temporaryFilePath.size()))
- return CString();
+ return String();
// Shrink the vector.
temporaryFilePath.shrink(strlen(temporaryFilePath.data()));
ASSERT(temporaryFilePath.last() == '/');
- // Append the file name.
- temporaryFilePath.append(prefix, strlen(prefix));
+ // Append the file name.
+ CString prefixUtf8 = prefix.utf8();
+ temporaryFilePath.append(prefixUtf8.data(), prefixUtf8.length());
temporaryFilePath.append("XXXXXX", 6);
temporaryFilePath.append('\0');
platformFileHandle = mkstemp(temporaryFilePath.data());
if (platformFileHandle == invalidPlatformFileHandle)
- return CString();
+ return String();
- return CString(temporaryFilePath.data());
+ return String::fromUTF8(temporaryFilePath.data());
}
bool canExcludeFromBackup()
diff --git a/Source/WebCore/platform/mac/HTMLConverter.h b/Source/WebCore/platform/mac/HTMLConverter.h
new file mode 100644
index 0000000..645c1d7
--- /dev/null
+++ b/Source/WebCore/platform/mac/HTMLConverter.h
@@ -0,0 +1,88 @@
+/*
+ * 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 "DOM.h"
+#import "DOMDocument.h"
+#import "DOMRange.h"
+
+namespace WebCore {
+class DocumentLoader;
+}
+
+@interface WebHTMLConverter : NSObject {
+ NSMutableAttributedString *_attrStr;
+ NSURL *_baseURL;
+ DOMDocument *_document;
+ DOMRange *_domRange;
+ NSMutableArray *_domStartAncestors;
+ WebCore::DocumentLoader *_dataSource;
+ NSString *_standardFontFamily;
+ CGFloat _textSizeMultiplier;
+ CGFloat _webViewTextSizeMultiplier;
+ CGFloat _defaultTabInterval;
+ CGFloat _defaultFontSize;
+ CGFloat _minimumFontSize;
+ NSMutableArray *_textLists;
+ NSMutableArray *_textBlocks;
+ NSMutableArray *_textTables;
+ NSMutableDictionary *_textTableFooters;
+ NSMutableArray *_textTableSpacings;
+ NSMutableArray *_textTablePaddings;
+ NSMutableArray *_textTableRows;
+ NSMutableArray *_textTableRowArrays;
+ NSMutableArray *_textTableRowBackgroundColors;
+ NSMutableDictionary *_computedStylesForElements;
+ NSMutableDictionary *_specifiedStylesForElements;
+ NSMutableDictionary *_stringsForNodes;
+ NSMutableDictionary *_floatsForNodes;
+ NSMutableDictionary *_colorsForNodes;
+ NSMutableDictionary *_attributesForElements;
+ NSMutableDictionary *_elementIsBlockLevel;
+ NSMutableDictionary *_fontCache;
+ NSMutableArray *_writingDirectionArray;
+ NSUInteger _domRangeStartIndex;
+ NSInteger _indexingLimit;
+ NSUInteger _thumbnailLimit;
+ NSInteger _errorCode;
+ NSInteger _quoteLevel;
+
+ struct {
+ unsigned int isSoft:1;
+ unsigned int reachedStart:1;
+ unsigned int reachedEnd:1;
+ unsigned int isIndexing:1;
+ unsigned int isTesting:1;
+ unsigned int hasTrailingNewline:1;
+ unsigned int pad:26;
+ } _flags;
+}
+
+- (id)init;
+- (id)initWithDOMRange:(DOMRange *)domRange;
+
+- (NSAttributedString *)attributedString;
+
+@end
+
diff --git a/Source/WebCore/platform/mac/HTMLConverter.mm b/Source/WebCore/platform/mac/HTMLConverter.mm
new file mode 100644
index 0000000..a4864c2
--- /dev/null
+++ b/Source/WebCore/platform/mac/HTMLConverter.mm
@@ -0,0 +1,1682 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 "HTMLConverter.h"
+
+#import "ArchiveResource.h"
+#import "Document.h"
+#import "DocumentLoader.h"
+#import "DOMDocumentInternal.h"
+#import "DOMElementInternal.h"
+#import "DOMHTMLTableCellElement.h"
+#import "DOMPrivate.h"
+#import "Element.h"
+#import "Frame.h"
+#import "HTMLNames.h"
+#import "HTMLParserIdioms.h"
+#import <wtf/ASCIICType.h>
+
+using namespace WebCore;
+using namespace HTMLNames;
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+// Additional control Unicode characters
+const unichar WebNextLineCharacter = 0x0085;
+
+@interface NSTextList (TextListPrivate)
++ (NSDictionary *)_standardMarkerAttributesForAttributes:(NSDictionary *)attrs;
+@end
+
+@interface NSTextAttachment (NSIgnoreOrientation)
+- (void)setIgnoresOrientation:(BOOL)flag;
+- (BOOL)ignoresOrientation;
+@end
+
+@interface NSURL (WebDataURL)
++ (NSURL *)_web_uniqueWebDataURL;
++ (NSURL *)_web_uniqueWebDataURLWithRelativeString:(NSString *)string;
++ (NSURL *)_web_URLWithString:(NSString *)string relativeToURL:(NSURL *)baseURL;
+- (NSString *)_web_suggestedFilenameWithMIMEType:(NSString *)MIMEType;
+@end
+
+@interface WebHTMLConverter(WebHTMLConverterPrivate)
+
+- (NSString *)_stringForNode:(DOMNode *)node property:(NSString *)key;
+- (NSColor *)_colorForNode:(DOMNode *)node property:(NSString *)key;
+- (BOOL)_getFloat:(CGFloat *)val forNode:(DOMNode *)node property:(NSString *)key;
+- (void)_traverseNode:(DOMNode *)node depth:(NSInteger)depth embedded:(BOOL)embedded;
+- (void)_traverseFooterNode:(DOMNode *)node depth:(NSInteger)depth;
+
+@end
+
+// Returns the font to be used if the NSFontAttributeName doesn't exist
+static NSFont *WebDefaultFont()
+{
+ static NSFont *defaultFont = nil;
+
+ if (defaultFont)
+ return defaultFont;
+
+ NSFont *font = [NSFont fontWithName:@"Helvetica" size:12];
+ if (!font)
+ font = [NSFont systemFontOfSize:12];
+
+ defaultFont = [font retain];
+
+ return defaultFont;
+}
+
+@implementation WebHTMLConverter
+
+static NSFont *_fontForNameAndSize(NSString *fontName, CGFloat size, NSMutableDictionary *cache)
+{
+ NSFontManager *fontManager = [NSFontManager sharedFontManager];
+ NSFont *font = [cache objectForKey:fontName];
+
+ if (font) {
+ font = [fontManager convertFont:font toSize:size];
+ return font;
+ }
+ font = [fontManager fontWithFamily:fontName traits:0 weight:0 size:size];
+ if (!font) {
+ NSArray *availableFamilyNames = [fontManager availableFontFamilies];
+ NSRange dividingRange, dividingSpaceRange = [fontName rangeOfString:@" " options:NSBackwardsSearch], dividingDashRange = [fontName rangeOfString:@"-" options:NSBackwardsSearch];
+ dividingRange = (0 < dividingSpaceRange.length && 0 < dividingDashRange.length) ? (dividingSpaceRange.location > dividingDashRange.location ? dividingSpaceRange : dividingDashRange) : (0 < dividingSpaceRange.length ? dividingSpaceRange : dividingDashRange);
+ while (0 < dividingRange.length) {
+ NSString *familyName = [fontName substringToIndex:dividingRange.location];
+ if ([availableFamilyNames containsObject:familyName]) {
+ NSArray *familyMemberArray;
+ NSString *faceName = [fontName substringFromIndex:(dividingRange.location + dividingRange.length)];
+ NSArray *familyMemberArrays = [fontManager availableMembersOfFontFamily:familyName];
+ NSEnumerator *familyMemberArraysEnum = [familyMemberArrays objectEnumerator];
+ while ((familyMemberArray = [familyMemberArraysEnum nextObject])) {
+ NSString *familyMemberFaceName = [familyMemberArray objectAtIndex:1];
+ if ([familyMemberFaceName compare:faceName options:NSCaseInsensitiveSearch] == NSOrderedSame) {
+ NSFontTraitMask traits = [[familyMemberArray objectAtIndex:3] integerValue];
+ NSInteger weight = [[familyMemberArray objectAtIndex:2] integerValue];
+ font = [fontManager fontWithFamily:familyName traits:traits weight:weight size:size];
+ break;
+ }
+ }
+ if (!font) {
+ if (0 < [familyMemberArrays count]) {
+ NSArray *familyMemberArray = [familyMemberArrays objectAtIndex:0];
+ NSFontTraitMask traits = [[familyMemberArray objectAtIndex:3] integerValue];
+ NSInteger weight = [[familyMemberArray objectAtIndex:2] integerValue];
+ font = [fontManager fontWithFamily:familyName traits:traits weight:weight size:size];
+ }
+ }
+ break;
+ } else {
+ dividingSpaceRange = [familyName rangeOfString:@" " options:NSBackwardsSearch];
+ dividingDashRange = [familyName rangeOfString:@"-" options:NSBackwardsSearch];
+ dividingRange = (0 < dividingSpaceRange.length && 0 < dividingDashRange.length) ? (dividingSpaceRange.location > dividingDashRange.location ? dividingSpaceRange : dividingDashRange) : (0 < dividingSpaceRange.length ? dividingSpaceRange : dividingDashRange);
+ }
+ }
+ }
+ if (!font) font = [NSFont fontWithName:@"Times" size:size];
+ if (!font) font = [NSFont userFontOfSize:size];
+ if (!font) font = [fontManager convertFont:WebDefaultFont() toSize:size];
+ if (!font) font = WebDefaultFont();
+ [cache setObject:font forKey:fontName];
+ return font;
+}
+
++ (NSParagraphStyle *)defaultParagraphStyle
+{
+ static NSMutableParagraphStyle *defaultParagraphStyle = nil;
+ if (!defaultParagraphStyle) {
+ defaultParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
+ [defaultParagraphStyle setDefaultTabInterval:36];
+ [defaultParagraphStyle setTabStops:[NSArray array]];
+ }
+ return defaultParagraphStyle;
+}
+
+- (NSArray *)_childrenForNode:(DOMNode *)node
+{
+ NSMutableArray *array = [NSMutableArray array];
+ DOMNode *child = [node firstChild];
+ while (child) {
+ [array addObject:child];
+ child = [child nextSibling];
+ }
+ return array;
+}
+
+- (DOMCSSStyleDeclaration *)_computedStyleForElement:(DOMElement *)element
+{
+ DOMDocument *document = [element ownerDocument];
+ DOMCSSStyleDeclaration *result = nil;
+ result = [_computedStylesForElements objectForKey:element];
+ if (result) {
+ if ([[NSNull null] isEqual:result]) result = nil;
+ } else {
+ result = [document getComputedStyle:element pseudoElement:@""] ;
+ [_computedStylesForElements setObject:(result ? (id)result : (id)[NSNull null]) forKey:element];
+ }
+ return result;
+}
+
+- (DOMCSSStyleDeclaration *)_specifiedStyleForElement:(DOMElement *)element
+{
+ DOMCSSStyleDeclaration *result = [_specifiedStylesForElements objectForKey:element];
+ if (result) {
+ if ([[NSNull null] isEqual:result]) result = nil;
+ } else {
+ result = [element style];
+ [_specifiedStylesForElements setObject:(result ? (id)result : (id)[NSNull null]) forKey:element];
+ }
+ return result;
+}
+
+- (NSString *)_computedStringForNode:(DOMNode *)node property:(NSString *)key
+{
+ NSString *result = nil;
+ BOOL inherit = YES;
+ DOMElement *element = (DOMElement *)node;
+ if (element && [element nodeType] == DOM_ELEMENT_NODE) {
+ DOMCSSStyleDeclaration *computedStyle, *specifiedStyle;
+ inherit = NO;
+ if (!result && (computedStyle = [self _computedStyleForElement:element])) {
+ DOMCSSPrimitiveValue *computedValue = (DOMCSSPrimitiveValue *)[computedStyle getPropertyCSSValue:key];
+ if (computedValue) {
+ unsigned short valueType = [computedValue cssValueType];
+ if (valueType == DOM_CSS_PRIMITIVE_VALUE) {
+ unsigned short primitiveType = [computedValue primitiveType];
+ if (primitiveType == DOM_CSS_STRING || primitiveType == DOM_CSS_URI || primitiveType == DOM_CSS_IDENT || primitiveType == DOM_CSS_ATTR) {
+ result = [computedValue getStringValue];
+ if (result && [result length] == 0) result = nil;
+ }
+ } else if (valueType == DOM_CSS_VALUE_LIST) {
+ result = [computedStyle getPropertyValue:key];
+ }
+ }
+ }
+ if (!result && (specifiedStyle = [self _specifiedStyleForElement:element])) {
+ DOMCSSPrimitiveValue *specifiedValue = (DOMCSSPrimitiveValue *)[specifiedStyle getPropertyCSSValue:key];
+ if (specifiedValue) {
+ unsigned short valueType = [specifiedValue cssValueType];
+ if (valueType == DOM_CSS_PRIMITIVE_VALUE) {
+ unsigned short primitiveType = [specifiedValue primitiveType];
+ if (primitiveType == DOM_CSS_STRING || primitiveType == DOM_CSS_URI || primitiveType == DOM_CSS_IDENT || primitiveType == DOM_CSS_ATTR) {
+ result = [specifiedValue getStringValue];
+ if (result && [result length] == 0) result = nil;
+ // ??? hack alert
+ if (!result) {
+ result = [specifiedStyle getPropertyValue:key];
+ }
+ }
+ } else if (valueType == DOM_CSS_INHERIT) {
+ inherit = YES;
+ } else if (valueType == DOM_CSS_VALUE_LIST) {
+ result = [specifiedStyle getPropertyValue:key];
+ }
+ }
+ }
+ if (!result) {
+ Element* coreElement = core(element);
+ if ([@"display" isEqualToString:key]) {
+ if (coreElement->hasTagName(headTag) || coreElement->hasTagName(scriptTag) || coreElement->hasTagName(appletTag) || coreElement->hasTagName(noframesTag))
+ result = @"none";
+ else if (coreElement->hasTagName(addressTag) || coreElement->hasTagName(blockquoteTag) || coreElement->hasTagName(bodyTag) || coreElement->hasTagName(centerTag)
+ || coreElement->hasTagName(ddTag) || coreElement->hasTagName(dirTag) || coreElement->hasTagName(divTag) || coreElement->hasTagName(dlTag)
+ || coreElement->hasTagName(dtTag) || coreElement->hasTagName(fieldsetTag) || coreElement->hasTagName(formTag) || coreElement->hasTagName(frameTag)
+ || coreElement->hasTagName(framesetTag) || coreElement->hasTagName(hrTag) || coreElement->hasTagName(htmlTag) || coreElement->hasTagName(h1Tag)
+ || coreElement->hasTagName(h2Tag) || coreElement->hasTagName(h3Tag) || coreElement->hasTagName(h4Tag) || coreElement->hasTagName(h5Tag)
+ || coreElement->hasTagName(h6Tag) || coreElement->hasTagName(iframeTag) || coreElement->hasTagName(menuTag) || coreElement->hasTagName(noscriptTag)
+ || coreElement->hasTagName(olTag) || coreElement->hasTagName(pTag) || coreElement->hasTagName(preTag) || coreElement->hasTagName(ulTag))
+ result = @"block";
+ else if (coreElement->hasTagName(liTag))
+ result = @"list-item";
+ else if (coreElement->hasTagName(tableTag))
+ result = @"table";
+ else if (coreElement->hasTagName(trTag))
+ result = @"table-row";
+ else if (coreElement->hasTagName(thTag) || coreElement->hasTagName(tdTag))
+ result = @"table-cell";
+ else if (coreElement->hasTagName(theadTag))
+ result = @"table-header-group";
+ else if (coreElement->hasTagName(tbodyTag))
+ result = @"table-row-group";
+ else if (coreElement->hasTagName(tfootTag))
+ result = @"table-footer-group";
+ else if (coreElement->hasTagName(colTag))
+ result = @"table-column";
+ else if (coreElement->hasTagName(colgroupTag))
+ result = @"table-column-group";
+ else if (coreElement->hasTagName(captionTag))
+ result = @"table-caption";
+ } else if ([@"white-space" isEqualToString:key]) {
+ if (coreElement->hasTagName(preTag))
+ result = @"pre";
+ else
+ inherit = YES;
+ } else if ([@"font-style" isEqualToString:key]) {
+ if (coreElement->hasTagName(iTag) || coreElement->hasTagName(citeTag) || coreElement->hasTagName(emTag) || coreElement->hasTagName(varTag) || coreElement->hasTagName(addressTag))
+ result = @"italic";
+ else
+ inherit = YES;
+ } else if ([@"font-weight" isEqualToString:key]) {
+ if (coreElement->hasTagName(bTag) || coreElement->hasTagName(strongTag) || coreElement->hasTagName(thTag))
+ result = @"bolder";
+ else
+ inherit = YES;
+ } else if ([@"text-decoration" isEqualToString:key]) {
+ if (coreElement->hasTagName(uTag) || coreElement->hasTagName(insTag))
+ result = @"underline";
+ else if (coreElement->hasTagName(sTag) || coreElement->hasTagName(strikeTag) || coreElement->hasTagName(delTag))
+ result = @"line-through";
+ else
+ inherit = YES; // ??? this is not strictly correct
+ } else if ([@"text-align" isEqualToString:key]) {
+ if (coreElement->hasTagName(centerTag) || coreElement->hasTagName(captionTag) || coreElement->hasTagName(thTag))
+ result = @"center";
+ else
+ inherit = YES;
+ } else if ([@"vertical-align" isEqualToString:key]) {
+ if (coreElement->hasTagName(supTag))
+ result = @"super";
+ else if (coreElement->hasTagName(subTag))
+ result = @"sub";
+ else if (coreElement->hasTagName(theadTag) || coreElement->hasTagName(tbodyTag) || coreElement->hasTagName(tfootTag))
+ result = @"middle";
+ else if (coreElement->hasTagName(trTag) || coreElement->hasTagName(thTag) || coreElement->hasTagName(tdTag))
+ inherit = YES;
+ } else if ([@"font-family" isEqualToString:key] || [@"font-variant" isEqualToString:key] || [@"font-effect" isEqualToString:key]
+ || [@"text-transform" isEqualToString:key] || [@"text-shadow" isEqualToString:key] || [@"visibility" isEqualToString:key]
+ || [@"border-collapse" isEqualToString:key] || [@"empty-cells" isEqualToString:key] || [@"word-spacing" isEqualToString:key]
+ || [@"list-style-type" isEqualToString:key] || [@"direction" isEqualToString:key]) {
+ inherit = YES;
+ }
+ }
+ }
+ if (!result && inherit) {
+ DOMNode *parentNode = [node parentNode];
+ if (parentNode) result = [self _stringForNode:parentNode property:key];
+ }
+ return result ? [result lowercaseString] : nil;
+}
+
+- (NSString *)_stringForNode:(DOMNode *)node property:(NSString *)key
+{
+ NSString *result = nil;
+ NSMutableDictionary *attributeDictionary = [_stringsForNodes objectForKey:node];
+ if (!attributeDictionary) {
+ attributeDictionary = [[NSMutableDictionary alloc] init];
+ [_stringsForNodes setObject:attributeDictionary forKey:node];
+ [attributeDictionary release];
+ }
+ result = [attributeDictionary objectForKey:key];
+ if (result) {
+ if ([@"" isEqualToString:result]) result = nil;
+ } else {
+ result = [self _computedStringForNode:node property:key];
+ [attributeDictionary setObject:(result ? result : @"") forKey:key];
+ }
+ return result;
+}
+
+static inline BOOL _getFloat(DOMCSSPrimitiveValue *primitiveValue, CGFloat *val)
+{
+ if (!val)
+ return NO;
+ switch ([primitiveValue primitiveType]) {
+ case DOM_CSS_PX:
+ *val = [primitiveValue getFloatValue:DOM_CSS_PX];
+ return YES;
+ case DOM_CSS_PT:
+ *val = 4 * [primitiveValue getFloatValue:DOM_CSS_PT] / 3;
+ return YES;
+ case DOM_CSS_PC:
+ *val = 16 * [primitiveValue getFloatValue:DOM_CSS_PC];
+ return YES;
+ case DOM_CSS_CM:
+ *val = 96 * [primitiveValue getFloatValue:DOM_CSS_CM] / (CGFloat)2.54;
+ return YES;
+ case DOM_CSS_MM:
+ *val = 96 * [primitiveValue getFloatValue:DOM_CSS_MM] / (CGFloat)25.4;
+ return YES;
+ case DOM_CSS_IN:
+ *val = 96 * [primitiveValue getFloatValue:DOM_CSS_IN];
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+- (BOOL)_getComputedFloat:(CGFloat *)val forNode:(DOMNode *)node property:(NSString *)key
+{
+ BOOL result = NO, inherit = YES;
+ CGFloat floatVal = 0;
+ DOMElement *element = (DOMElement *)node;
+ if (element && [element nodeType] == DOM_ELEMENT_NODE) {
+ DOMCSSStyleDeclaration *computedStyle, *specifiedStyle;
+ inherit = NO;
+ if (!result && (computedStyle = [self _computedStyleForElement:element])) {
+ DOMCSSPrimitiveValue *computedValue = (DOMCSSPrimitiveValue *)[computedStyle getPropertyCSSValue:key];
+ if (computedValue && [computedValue cssValueType] == DOM_CSS_PRIMITIVE_VALUE) {
+ result = _getFloat(computedValue, &floatVal);
+ }
+ }
+ if (!result && (specifiedStyle = [self _specifiedStyleForElement:element])) {
+ DOMCSSPrimitiveValue *specifiedValue = (DOMCSSPrimitiveValue *)[specifiedStyle getPropertyCSSValue:key];
+ if (specifiedValue) {
+ unsigned short valueType = [specifiedValue cssValueType];
+ if (valueType == DOM_CSS_PRIMITIVE_VALUE) {
+ result = _getFloat(specifiedValue, &floatVal);
+ } else if (valueType == DOM_CSS_INHERIT) {
+ inherit = YES;
+ }
+ }
+ }
+ if (!result) {
+ if ([@"text-indent" isEqualToString:key] || [@"letter-spacing" isEqualToString:key] || [@"word-spacing" isEqualToString:key]
+ || [@"line-height" isEqualToString:key] || [@"widows" isEqualToString:key] || [@"orphans" isEqualToString:key])
+ inherit = YES;
+ }
+ }
+ if (!result && inherit) {
+ DOMNode *parentNode = [node parentNode];
+ if (parentNode) result = [self _getFloat:&floatVal forNode:parentNode property:key];
+ }
+ if (result && val)
+ *val = floatVal;
+ return result;
+}
+
+- (BOOL)_getFloat:(CGFloat *)val forNode:(DOMNode *)node property:(NSString *)key
+{
+ BOOL result = NO;
+ CGFloat floatVal = 0;
+ NSNumber *floatNumber;
+ NSMutableDictionary *attributeDictionary = [_floatsForNodes objectForKey:node];
+ if (!attributeDictionary) {
+ attributeDictionary = [[NSMutableDictionary alloc] init];
+ [_floatsForNodes setObject:attributeDictionary forKey:node];
+ [attributeDictionary release];
+ }
+ floatNumber = [attributeDictionary objectForKey:key];
+ if (floatNumber) {
+ if (![[NSNull null] isEqual:floatNumber]) {
+ result = YES;
+ floatVal = [floatNumber floatValue];
+ }
+ } else {
+ result = [self _getComputedFloat:&floatVal forNode:node property:key];
+ [attributeDictionary setObject:(result ? (id)[NSNumber numberWithDouble:floatVal] : (id)[NSNull null]) forKey:key];
+ }
+ if (result && val) *val = floatVal;
+ return result;
+}
+
+static inline NSColor *_colorForRGBColor(DOMRGBColor *domRGBColor, BOOL ignoreBlack)
+{
+ NSColor *color = [domRGBColor _color];
+ NSColorSpace *colorSpace = [color colorSpace];
+ const CGFloat ColorEpsilon = 1 / (2 * (CGFloat)255.0);
+
+ if (color) {
+ if ([colorSpace isEqual:[NSColorSpace genericGrayColorSpace]] || [colorSpace isEqual:[NSColorSpace deviceGrayColorSpace]]) {
+ CGFloat white, alpha;
+ [color getWhite:&white alpha:&alpha];
+ if (white < ColorEpsilon && (ignoreBlack || alpha < ColorEpsilon)) color = nil;
+ } else {
+ NSColor *rgbColor = nil;
+ if ([colorSpace isEqual:[NSColorSpace genericRGBColorSpace]] || [colorSpace isEqual:[NSColorSpace deviceRGBColorSpace]]) rgbColor = color;
+ if (!rgbColor) rgbColor = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ if (rgbColor) {
+ CGFloat red, green, blue, alpha;
+ [rgbColor getRed:&red green:&green blue:&blue alpha:&alpha];
+ if (red < ColorEpsilon && green < ColorEpsilon && blue < ColorEpsilon && (ignoreBlack || alpha < ColorEpsilon)) color = nil;
+ }
+ }
+ }
+ return color;
+}
+
+static inline NSShadow *_shadowForShadowStyle(NSString *shadowStyle)
+{
+ NSShadow *shadow = nil;
+ NSUInteger shadowStyleLength = [shadowStyle length];
+ NSRange openParenRange = [shadowStyle rangeOfString:@"("], closeParenRange = [shadowStyle rangeOfString:@")"], firstRange = NSMakeRange(NSNotFound, 0), secondRange = NSMakeRange(NSNotFound, 0), thirdRange = NSMakeRange(NSNotFound, 0), spaceRange;
+ if (openParenRange.length > 0 && closeParenRange.length > 0 && NSMaxRange(openParenRange) < closeParenRange.location) {
+ NSArray *components = [[shadowStyle substringWithRange:NSMakeRange(NSMaxRange(openParenRange), closeParenRange.location - NSMaxRange(openParenRange))] componentsSeparatedByString:@","];
+ if ([components count] >= 3) {
+ CGFloat red = [[components objectAtIndex:0] floatValue] / 255, green = [[components objectAtIndex:1] floatValue] / 255, blue = [[components objectAtIndex:2] floatValue] / 255, alpha = ([components count] >= 4) ? [[components objectAtIndex:3] floatValue] / 255 : 1;
+ NSColor *shadowColor = [NSColor colorWithCalibratedRed:red green:green blue:blue alpha:alpha];
+ NSSize shadowOffset;
+ CGFloat shadowBlurRadius;
+ firstRange = [shadowStyle rangeOfString:@"px"];
+ if (firstRange.length > 0 && NSMaxRange(firstRange) < shadowStyleLength) secondRange = [shadowStyle rangeOfString:@"px" options:0 range:NSMakeRange(NSMaxRange(firstRange), shadowStyleLength - NSMaxRange(firstRange))];
+ if (secondRange.length > 0 && NSMaxRange(secondRange) < shadowStyleLength) thirdRange = [shadowStyle rangeOfString:@"px" options:0 range:NSMakeRange(NSMaxRange(secondRange), shadowStyleLength - NSMaxRange(secondRange))];
+ if (firstRange.location > 0 && firstRange.length > 0 && secondRange.length > 0 && thirdRange.length > 0) {
+ spaceRange = [shadowStyle rangeOfString:@" " options:NSBackwardsSearch range:NSMakeRange(0, firstRange.location)];
+ if (spaceRange.length == 0) spaceRange = NSMakeRange(0, 0);
+ shadowOffset.width = [[shadowStyle substringWithRange:NSMakeRange(NSMaxRange(spaceRange), firstRange.location - NSMaxRange(spaceRange))] floatValue];
+ spaceRange = [shadowStyle rangeOfString:@" " options:NSBackwardsSearch range:NSMakeRange(0, secondRange.location)];
+ if (spaceRange.length == 0) spaceRange = NSMakeRange(0, 0);
+ shadowOffset.height = -[[shadowStyle substringWithRange:NSMakeRange(NSMaxRange(spaceRange), secondRange.location - NSMaxRange(spaceRange))] floatValue];
+ spaceRange = [shadowStyle rangeOfString:@" " options:NSBackwardsSearch range:NSMakeRange(0, thirdRange.location)];
+ if (spaceRange.length == 0) spaceRange = NSMakeRange(0, 0);
+ shadowBlurRadius = [[shadowStyle substringWithRange:NSMakeRange(NSMaxRange(spaceRange), thirdRange.location - NSMaxRange(spaceRange))] floatValue];
+ shadow = [[[NSShadow alloc] init] autorelease];
+ [shadow setShadowColor:shadowColor];
+ [shadow setShadowOffset:shadowOffset];
+ [shadow setShadowBlurRadius:shadowBlurRadius];
+ }
+ }
+ }
+ return shadow;
+}
+
+- (BOOL)_elementIsBlockLevel:(DOMElement *)element
+{
+ BOOL isBlockLevel = NO;
+ NSNumber *val = nil;
+ val = [_elementIsBlockLevel objectForKey:element];
+ if (val) {
+ isBlockLevel = [val boolValue];
+ } else {
+ NSString *displayVal = [self _stringForNode:element property:@"display"], *floatVal = [self _stringForNode:element property:@"float"];
+ if (floatVal && ([@"left" isEqualToString:floatVal] || [@"right" isEqualToString:floatVal])) {
+ isBlockLevel = YES;
+ } else if (displayVal) {
+ isBlockLevel = ([@"block" isEqualToString:displayVal] || [@"list-item" isEqualToString:displayVal] || [displayVal hasPrefix:@"table"]);
+ }
+ [_elementIsBlockLevel setObject:[NSNumber numberWithBool:isBlockLevel] forKey:element];
+ }
+ return isBlockLevel;
+}
+
+- (BOOL)_elementHasOwnBackgroundColor:(DOMElement *)element
+{
+ // In the text system, text blocks (table elements) and documents (body elements) have their own background colors, which should not be inherited
+ if ([self _elementIsBlockLevel:element]) {
+ Element* coreElement = core(element);
+ NSString *displayVal = [self _stringForNode:element property:@"display"];
+ if (coreElement->hasTagName(htmlTag) || coreElement->hasTagName(bodyTag) || [displayVal hasPrefix:@"table"])
+ return YES;
+ }
+ return NO;
+}
+
+- (DOMElement *)_blockLevelElementForNode:(DOMNode *)node
+{
+ DOMElement *element = (DOMElement *)node;
+ while (element && [element nodeType] != DOM_ELEMENT_NODE)
+ element = (DOMElement *)[element parentNode];
+ if (element && ![self _elementIsBlockLevel:element])
+ element = [self _blockLevelElementForNode:[element parentNode]];
+ return element;
+}
+
+- (NSColor *)_computedColorForNode:(DOMNode *)node property:(NSString *)key
+{
+ NSColor *result = nil;
+ BOOL inherit = YES, haveResult = NO, isColor = [@"color" isEqualToString:key], isBackgroundColor = [@"background-color" isEqualToString:key];
+ DOMElement *element = (DOMElement *)node;
+ if (element && [element nodeType] == DOM_ELEMENT_NODE) {
+ DOMCSSStyleDeclaration *computedStyle, *specifiedStyle;
+ inherit = NO;
+ if (!haveResult && (computedStyle = [self _computedStyleForElement:element])) {
+ DOMCSSPrimitiveValue *computedValue = (DOMCSSPrimitiveValue *)[computedStyle getPropertyCSSValue:key];
+ if (computedValue && [computedValue cssValueType] == DOM_CSS_PRIMITIVE_VALUE && [computedValue primitiveType] == DOM_CSS_RGBCOLOR) {
+ result = _colorForRGBColor([computedValue getRGBColorValue], isColor);
+ haveResult = YES;
+ }
+ }
+ if (!haveResult && (specifiedStyle = [self _specifiedStyleForElement:element])) {
+ DOMCSSPrimitiveValue *specifiedValue = (DOMCSSPrimitiveValue *)[specifiedStyle getPropertyCSSValue:key];
+ if (specifiedValue) {
+ unsigned short valueType = [specifiedValue cssValueType];
+ if (valueType == DOM_CSS_PRIMITIVE_VALUE && [specifiedValue primitiveType] == DOM_CSS_RGBCOLOR) {
+ result = _colorForRGBColor([specifiedValue getRGBColorValue], isColor);
+ haveResult = YES;
+ } else if (valueType == DOM_CSS_INHERIT) {
+ inherit = YES;
+ }
+ }
+ }
+ if (!result) {
+ if ((isColor && !haveResult) || (isBackgroundColor && ![self _elementHasOwnBackgroundColor:element])) inherit = YES;
+ }
+ }
+ if (!result && inherit) {
+ DOMNode *parentNode = [node parentNode];
+ if (parentNode && !(isBackgroundColor && [parentNode nodeType] == DOM_ELEMENT_NODE && [self _elementHasOwnBackgroundColor:(DOMElement *)parentNode])) {
+ result = [self _colorForNode:parentNode property:key];
+ }
+ }
+ return result;
+}
+
+- (NSColor *)_colorForNode:(DOMNode *)node property:(NSString *)key
+{
+ NSColor *result = nil;
+ NSMutableDictionary *attributeDictionary = [_colorsForNodes objectForKey:node];
+ if (!attributeDictionary) {
+ attributeDictionary = [[NSMutableDictionary alloc] init];
+ [_colorsForNodes setObject:attributeDictionary forKey:node];
+ [attributeDictionary release];
+ }
+ result = [attributeDictionary objectForKey:key];
+ if (result) {
+ if ([[NSColor clearColor] isEqual:result]) result = nil;
+ } else {
+ result = [self _computedColorForNode:node property:key];
+ [attributeDictionary setObject:(result ? result : [NSColor clearColor]) forKey:key];
+ }
+ return result;
+}
+
+- (NSDictionary *)_computedAttributesForElement:(DOMElement *)element
+{
+ DOMElement *blockElement = [self _blockLevelElementForNode:element];
+ NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
+ NSFontManager *fontManager = [NSFontManager sharedFontManager];
+ NSString *fontEffect = [self _stringForNode:element property:@"font-effect"], *textDecoration = [self _stringForNode:element property:@"text-decoration"], *verticalAlign = [self _stringForNode:element property:@"vertical-align"], *textShadow = [self _stringForNode:element property:@"text-shadow"];
+ CGFloat fontSize = 0, baselineOffset = 0, kerning = 0;
+ NSFont *font = nil, *actualFont = [element _font];
+ NSColor *foregroundColor = [self _colorForNode:element property:@"color"], *backgroundColor = [self _colorForNode:element property:@"background-color"];
+
+ if (![self _getFloat:&fontSize forNode:element property:@"font-size"] || fontSize <= 0.0) fontSize = _defaultFontSize;
+ fontSize *= _textSizeMultiplier;
+ if (fontSize < _minimumFontSize) fontSize = _minimumFontSize;
+ if (fabs(floor(2.0 * fontSize + 0.5) / 2.0 - fontSize) < 0.05) {
+ fontSize = (CGFloat)floor(2.0 * fontSize + 0.5) / 2;
+ } else if (fabs(floor(10.0 * fontSize + 0.5) / 10.0 - fontSize) < 0.005) {
+ fontSize = (CGFloat)floor(10.0 * fontSize + 0.5) / 10;
+ }
+ if (fontSize <= 0.0) fontSize = 12;
+
+ if (actualFont) font = [fontManager convertFont:actualFont toSize:fontSize];
+ if (!font) {
+ NSString *fontName = [[self _stringForNode:element property:@"font-family"] capitalizedString], *fontStyle = [self _stringForNode:element property:@"font-style"], *fontWeight = [self _stringForNode:element property:@"font-weight"], *fontVariant = [self _stringForNode:element property:@"font-variant"];
+
+ if (!fontName) fontName = _standardFontFamily;
+ if (fontName) font = _fontForNameAndSize(fontName, fontSize, _fontCache);
+ if (!font) font = [NSFont fontWithName:@"Times" size:fontSize];
+ if ([@"italic" isEqualToString:fontStyle] || [@"oblique" isEqualToString:fontStyle]) {
+ NSFont *originalFont = font;
+ font = [fontManager convertFont:font toHaveTrait:NSItalicFontMask];
+ if (!font) font = originalFont;
+ }
+ if ([fontWeight hasPrefix:@"bold"] || [fontWeight integerValue] >= 700) {
+ // ??? handle weight properly using NSFontManager
+ NSFont *originalFont = font;
+ font = [fontManager convertFont:font toHaveTrait:NSBoldFontMask];
+ if (!font) font = originalFont;
+ }
+ if ([@"small-caps" isEqualToString:fontVariant]) {
+ // ??? synthesize small-caps if [font isEqual:originalFont]
+ NSFont *originalFont = font;
+ font = [fontManager convertFont:font toHaveTrait:NSSmallCapsFontMask];
+ if (!font) font = originalFont;
+ }
+ }
+ if (font) [attrs setObject:font forKey:NSFontAttributeName];
+ if (foregroundColor) [attrs setObject:foregroundColor forKey:NSForegroundColorAttributeName];
+ if (backgroundColor && ![self _elementHasOwnBackgroundColor:element]) [attrs setObject:backgroundColor forKey:NSBackgroundColorAttributeName];
+ if (fontEffect) {
+ if ([fontEffect rangeOfString:@"outline"].location != NSNotFound) [attrs setObject:[NSNumber numberWithDouble:3.0] forKey:NSStrokeWidthAttributeName];
+ if ([fontEffect rangeOfString:@"emboss"].location != NSNotFound) [attrs setObject:[[[NSShadow alloc] init] autorelease] forKey:NSShadowAttributeName];
+ }
+ if (textDecoration && [textDecoration length] > 4) {
+ if ([textDecoration rangeOfString:@"underline"].location != NSNotFound) [attrs setObject:[NSNumber numberWithInteger:NSUnderlineStyleSingle] forKey:NSUnderlineStyleAttributeName];
+ if ([textDecoration rangeOfString:@"line-through"].location != NSNotFound) [attrs setObject:[NSNumber numberWithInteger:NSUnderlineStyleSingle] forKey:NSStrikethroughStyleAttributeName];
+ }
+ if (verticalAlign) {
+ if ([verticalAlign rangeOfString:@"super"].location != NSNotFound) [attrs setObject:[NSNumber numberWithInteger:1] forKey:NSSuperscriptAttributeName];
+ if ([verticalAlign rangeOfString:@"sub"].location != NSNotFound) [attrs setObject:[NSNumber numberWithInteger:-1] forKey:NSSuperscriptAttributeName];
+ }
+ if ([self _getFloat:&baselineOffset forNode:element property:@"vertical-align"]) [attrs setObject:[NSNumber numberWithDouble:baselineOffset] forKey:NSBaselineOffsetAttributeName];
+ if ([self _getFloat:&kerning forNode:element property:@"letter-spacing"]) [attrs setObject:[NSNumber numberWithDouble:kerning] forKey:NSKernAttributeName];
+ if (textShadow && [textShadow length] > 4) {
+ NSShadow *shadow = _shadowForShadowStyle(textShadow);
+ if (shadow) [attrs setObject:shadow forKey:NSShadowAttributeName];
+ }
+ if (element != blockElement && [_writingDirectionArray count] > 0) [attrs setObject:[NSArray arrayWithArray:_writingDirectionArray] forKey:NSWritingDirectionAttributeName];
+
+ if (blockElement) {
+ NSMutableParagraphStyle *paragraphStyle = [[[self class] defaultParagraphStyle] mutableCopy];
+ NSString *blockTag = [blockElement tagName];
+ BOOL isParagraph = ([@"P" isEqualToString:blockTag] || [@"LI" isEqualToString:blockTag] || ([blockTag hasPrefix:@"H"] && 2 == [blockTag length]));
+ NSString *textAlign = [self _stringForNode:blockElement property:@"text-align"], *direction = [self _stringForNode:blockElement property:@"direction"];
+ CGFloat leftMargin = 0, rightMargin = 0, bottomMargin = 0, textIndent = 0, lineHeight = 0;
+ if (textAlign) {
+ // WebKit can return -khtml-left, -khtml-right, -khtml-center
+ if ([textAlign hasSuffix:@"left"]) [paragraphStyle setAlignment:NSLeftTextAlignment];
+ else if ([textAlign hasSuffix:@"right"]) [paragraphStyle setAlignment:NSRightTextAlignment];
+ else if ([textAlign hasSuffix:@"center"]) [paragraphStyle setAlignment:NSCenterTextAlignment];
+ else if ([textAlign hasSuffix:@"justify"]) [paragraphStyle setAlignment:NSJustifiedTextAlignment];
+ }
+ if (direction) {
+ if ([direction isEqualToString:@"ltr"]) [paragraphStyle setBaseWritingDirection:NSWritingDirectionLeftToRight];
+ else if ([direction isEqualToString:@"rtl"]) [paragraphStyle setBaseWritingDirection:NSWritingDirectionRightToLeft];
+ }
+ if ([blockTag hasPrefix:@"H"] && 2 == [blockTag length]) {
+ NSInteger headerLevel = [blockTag characterAtIndex:1] - '0';
+ if (1 <= headerLevel && headerLevel <= 6) [paragraphStyle setHeaderLevel:headerLevel];
+ }
+ if (isParagraph) {
+ //if ([self _getFloat:&topMargin forNode:blockElement property:@"margin-top"] && topMargin > 0.0) [paragraphStyle setParagraphSpacingBefore:topMargin];
+ if ([self _getFloat:&leftMargin forNode:blockElement property:@"margin-left"] && leftMargin > 0.0) [paragraphStyle setHeadIndent:leftMargin];
+ if ([self _getFloat:&textIndent forNode:blockElement property:@"text-indent"]) [paragraphStyle setFirstLineHeadIndent:[paragraphStyle headIndent] + textIndent];
+ if ([self _getFloat:&rightMargin forNode:blockElement property:@"margin-right"] && rightMargin > 0.0) [paragraphStyle setTailIndent:-rightMargin];
+ if ([self _getFloat:&bottomMargin forNode:blockElement property:@"margin-bottom"] && bottomMargin > 0.0) [paragraphStyle setParagraphSpacing:bottomMargin];
+ }
+ if (_webViewTextSizeMultiplier > 0.0 && [self _getFloat:&lineHeight forNode:element property:@"line-height"] && lineHeight > 0.0) {
+ [paragraphStyle setMinimumLineHeight:lineHeight / _webViewTextSizeMultiplier];
+ }
+ if ([_textLists count] > 0) [paragraphStyle setTextLists:_textLists];
+ if ([_textBlocks count] > 0) [paragraphStyle setTextBlocks:_textBlocks];
+ [attrs setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
+ [paragraphStyle release];
+ }
+ return attrs;
+}
+
+- (NSDictionary *)_attributesForElement:(DOMElement *)element
+{
+ NSDictionary *result;
+ if (element) {
+ result = [_attributesForElements objectForKey:element];
+ if (!result) {
+ result = [self _computedAttributesForElement:element];
+ [_attributesForElements setObject:result forKey:element];
+ }
+ } else {
+ result = [NSDictionary dictionary];
+ }
+ return result;
+
+}
+
+- (void)_newParagraphForElement:(DOMElement *)element tag:(NSString *)tag allowEmpty:(BOOL)flag suppressTrailingSpace:(BOOL)suppress
+{
+ NSUInteger textLength = [_attrStr length];
+ unichar lastChar = (textLength > 0) ? [[_attrStr string] characterAtIndex:textLength - 1] : '\n';
+ NSRange rangeToReplace = (suppress && _flags.isSoft && (lastChar == ' ' || lastChar == NSLineSeparatorCharacter)) ? NSMakeRange(textLength - 1, 1) : NSMakeRange(textLength, 0);
+ BOOL needBreak = (flag || lastChar != '\n');
+ if (needBreak) {
+ NSString *string = (([@"BODY" isEqualToString:tag] || [@"HTML" isEqualToString:tag]) ? @"" : @"\n");
+ [_writingDirectionArray removeAllObjects];
+ [_attrStr replaceCharactersInRange:rangeToReplace withString:string];
+ if (rangeToReplace.location < _domRangeStartIndex) _domRangeStartIndex += [string length] - rangeToReplace.length;
+ rangeToReplace.length = [string length];
+ if (!_flags.isIndexing) {
+ NSDictionary *attrs = [self _attributesForElement:element];
+ if (!_flags.isTesting && rangeToReplace.length > 0) [_attrStr setAttributes:attrs range:rangeToReplace];
+ }
+ _flags.isSoft = YES;
+ }
+}
+
+- (void)_newLineForElement:(DOMElement *)element
+{
+ unichar c = NSLineSeparatorCharacter;
+ NSString *string = [[NSString alloc] initWithCharacters:&c length:1];
+ NSUInteger textLength = [_attrStr length];
+ NSRange rangeToReplace = NSMakeRange(textLength, 0);
+ [_attrStr replaceCharactersInRange:rangeToReplace withString:string];
+ rangeToReplace.length = [string length];
+ if (rangeToReplace.location < _domRangeStartIndex) _domRangeStartIndex += rangeToReplace.length;
+ if (!_flags.isIndexing) {
+ NSDictionary *attrs = [self _attributesForElement:element];
+ if (!_flags.isTesting && rangeToReplace.length > 0) [_attrStr setAttributes:attrs range:rangeToReplace];
+ }
+ [string release];
+ _flags.isSoft = YES;
+}
+
+- (void)_newTabForElement:(DOMElement *)element
+{
+ NSString *string = @"\t";
+ NSUInteger textLength = [_attrStr length];
+ unichar lastChar = (textLength > 0) ? [[_attrStr string] characterAtIndex:textLength - 1] : '\n';
+ NSRange rangeToReplace = (_flags.isSoft && lastChar == ' ') ? NSMakeRange(textLength - 1, 1) : NSMakeRange(textLength, 0);
+ [_attrStr replaceCharactersInRange:rangeToReplace withString:string];
+ rangeToReplace.length = [string length];
+ if (rangeToReplace.location < _domRangeStartIndex) _domRangeStartIndex += rangeToReplace.length;
+ if (!_flags.isIndexing) {
+ NSDictionary *attrs = [self _attributesForElement:element];
+ if (!_flags.isTesting && rangeToReplace.length > 0) [_attrStr setAttributes:attrs range:rangeToReplace];
+ }
+ [string release];
+ _flags.isSoft = YES;
+}
+
+static NSFileWrapper *fileWrapperForURL(DocumentLoader *dataSource, NSURL *URL)
+{
+ if ([URL isFileURL]) {
+ NSString *path = [[URL path] stringByResolvingSymlinksInPath];
+ return [[[NSFileWrapper alloc] initWithPath:path] autorelease];
+ }
+
+ RefPtr<ArchiveResource> resource = dataSource->subresource(URL);
+ if (resource) {
+ NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:[resource->data()->createNSData() autorelease]] autorelease];
+ NSString *filename = resource->response().suggestedFilename();
+ if (!filename || ![filename length]) {
+ NSURL *URL = resource->url();
+ filename = [URL _web_suggestedFilenameWithMIMEType:resource->mimeType()];
+ }
+ [wrapper setPreferredFilename:filename];
+ return wrapper;
+ }
+
+ NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
+
+ NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
+ [request release];
+
+ if (cachedResponse) {
+ NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:[cachedResponse data]] autorelease];
+ [wrapper setPreferredFilename:[[cachedResponse response] suggestedFilename]];
+ return wrapper;
+ }
+
+ return nil;
+}
+
+- (BOOL)_addAttachmentForElement:(DOMElement *)element URL:(NSURL *)url needsParagraph:(BOOL)needsParagraph usePlaceholder:(BOOL)flag
+{
+ BOOL retval = NO, notFound = NO;
+ NSFileWrapper *fileWrapper = nil;
+ static NSImage *missingImage = nil;
+ Frame* frame = core([element ownerDocument])->frame();
+ DocumentLoader *dataSource = frame->loader()->frameHasLoaded() ? frame->loader()->documentLoader() : 0;
+ BOOL ignoreOrientation = YES;
+
+ if (_flags.isIndexing) return NO;
+ if ([url isFileURL]) {
+ NSString *path = [[url path] stringByStandardizingPath];
+ if (path) fileWrapper = [[[NSFileWrapper alloc] initWithPath:path] autorelease];
+ }
+ if (!fileWrapper) {
+ RefPtr<ArchiveResource> resource = dataSource->subresource(url);
+ if (!resource) resource = dataSource->subresource(url);
+ if (flag && resource && [@"text/html" isEqual:resource->mimeType()]) notFound = YES;
+ if (resource && !notFound) {
+ fileWrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:[resource->data()->createNSData() autorelease]] autorelease];
+ [fileWrapper setPreferredFilename:[url _web_suggestedFilenameWithMIMEType:resource->mimeType()]];
+ }
+ }
+ if (!fileWrapper && !notFound) {
+ fileWrapper = fileWrapperForURL(dataSource, url);
+ if (flag && fileWrapper && [[[[fileWrapper preferredFilename] pathExtension] lowercaseString] hasPrefix:@"htm"]) notFound = YES;
+ if (notFound) fileWrapper = nil;
+ }
+ if (!fileWrapper && !notFound) {
+ fileWrapper = fileWrapperForURL(_dataSource, url);
+ if (flag && fileWrapper && [[[[fileWrapper preferredFilename] pathExtension] lowercaseString] hasPrefix:@"htm"]) notFound = YES;
+ if (notFound) fileWrapper = nil;
+ }
+ if (fileWrapper || flag) {
+ NSUInteger textLength = [_attrStr length];
+ NSTextAttachment *attachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper];
+ NSTextAttachmentCell *cell;
+ NSString *string = [[NSString alloc] initWithFormat:(needsParagraph ? @"%C\n" : @"%C"), NSAttachmentCharacter];
+ NSRange rangeToReplace = NSMakeRange(textLength, 0);
+ NSDictionary *attrs;
+ if (fileWrapper) {
+ if (ignoreOrientation) [attachment setIgnoresOrientation:YES];
+ } else {
+ cell = [[NSTextAttachmentCell alloc] initImageCell:missingImage];
+ [attachment setAttachmentCell:cell];
+ [cell release];
+ }
+ [_attrStr replaceCharactersInRange:rangeToReplace withString:string];
+ rangeToReplace.length = [string length];
+ if (rangeToReplace.location < _domRangeStartIndex) _domRangeStartIndex += rangeToReplace.length;
+ attrs = [self _attributesForElement:element];
+ if (!_flags.isTesting && rangeToReplace.length > 0) {
+ [_attrStr setAttributes:attrs range:rangeToReplace];
+ rangeToReplace.length = 1;
+ [_attrStr addAttribute:NSAttachmentAttributeName value:attachment range:rangeToReplace];
+ }
+ [string release];
+ [attachment release];
+ _flags.isSoft = NO;
+ retval = YES;
+ }
+ return retval;
+}
+
+- (void)_addQuoteForElement:(DOMElement *)element opening:(BOOL)opening level:(NSInteger)level
+{
+ unichar c = ((level % 2) == 0) ? (opening ? 0x201c : 0x201d) : (opening ? 0x2018 : 0x2019);
+ NSString *string = [[NSString alloc] initWithCharacters:&c length:1];
+ NSUInteger textLength = [_attrStr length];
+ NSRange rangeToReplace = NSMakeRange(textLength, 0);
+ [_attrStr replaceCharactersInRange:rangeToReplace withString:string];
+ rangeToReplace.length = [string length];
+ if (rangeToReplace.location < _domRangeStartIndex) _domRangeStartIndex += rangeToReplace.length;
+ if (!_flags.isIndexing) {
+ NSDictionary *attrs = [self _attributesForElement:element];
+ if (!_flags.isTesting && rangeToReplace.length > 0) [_attrStr setAttributes:attrs range:rangeToReplace];
+ }
+ [string release];
+ _flags.isSoft = NO;
+}
+
+- (void)_addValue:(NSString *)value forElement:(DOMElement *)element
+{
+ NSUInteger textLength = [_attrStr length], valueLength = [value length];
+ NSRange rangeToReplace = NSMakeRange(textLength, 0);
+ if (valueLength > 0) {
+ [_attrStr replaceCharactersInRange:rangeToReplace withString:value];
+ rangeToReplace.length = valueLength;
+ if (rangeToReplace.location < _domRangeStartIndex) _domRangeStartIndex += rangeToReplace.length;
+ if (!_flags.isIndexing) {
+ NSDictionary *attrs = [self _attributesForElement:element];
+ if (!_flags.isTesting && rangeToReplace.length > 0) [_attrStr setAttributes:attrs range:rangeToReplace];
+ }
+ _flags.isSoft = NO;
+ }
+}
+
+- (void)_fillInBlock:(NSTextBlock *)block forElement:(DOMElement *)element backgroundColor:(NSColor *)backgroundColor extraMargin:(CGFloat)extraMargin extraPadding:(CGFloat)extraPadding isTable:(BOOL)isTable
+{
+ CGFloat val = 0;
+ NSColor *color = nil;
+ BOOL isTableCellElement = [element isKindOfClass:[DOMHTMLTableCellElement class]];
+ NSString *width = isTableCellElement ? [(DOMHTMLTableCellElement *)element width] : [element getAttribute:@"width"];
+
+ if ((width && [width length] > 0) || !isTable) {
+ if ([self _getFloat:&val forNode:element property:@"width"]) [block setValue:val type:NSTextBlockAbsoluteValueType forDimension:NSTextBlockWidth];
+ }
+
+ if ([self _getFloat:&val forNode:element property:@"min-width"]) [block setValue:val type:NSTextBlockAbsoluteValueType forDimension:NSTextBlockMinimumWidth];
+ if ([self _getFloat:&val forNode:element property:@"max-width"]) [block setValue:val type:NSTextBlockAbsoluteValueType forDimension:NSTextBlockMaximumWidth];
+ if ([self _getFloat:&val forNode:element property:@"min-height"]) [block setValue:val type:NSTextBlockAbsoluteValueType forDimension:NSTextBlockMinimumHeight];
+ if ([self _getFloat:&val forNode:element property:@"max-height"]) [block setValue:val type:NSTextBlockAbsoluteValueType forDimension:NSTextBlockMaximumHeight];
+
+ if ([self _getFloat:&val forNode:element property:@"padding-left"]) [block setWidth:val + extraPadding type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockPadding edge:NSMinXEdge]; else [block setWidth:extraPadding type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockPadding edge:NSMinXEdge];
+ if ([self _getFloat:&val forNode:element property:@"padding-top"]) [block setWidth:val + extraPadding type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockPadding edge:NSMinYEdge]; else [block setWidth:extraPadding type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockPadding edge:NSMinYEdge];
+ if ([self _getFloat:&val forNode:element property:@"padding-right"]) [block setWidth:val + extraPadding type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockPadding edge:NSMaxXEdge]; else [block setWidth:extraPadding type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockPadding edge:NSMaxXEdge];
+ if ([self _getFloat:&val forNode:element property:@"padding-bottom"]) [block setWidth:val + extraPadding type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockPadding edge:NSMaxYEdge]; else [block setWidth:extraPadding type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockPadding edge:NSMaxYEdge];
+
+ if ([self _getFloat:&val forNode:element property:@"border-left-width"]) [block setWidth:val type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockBorder edge:NSMinXEdge];
+ if ([self _getFloat:&val forNode:element property:@"border-top-width"]) [block setWidth:val type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockBorder edge:NSMinYEdge];
+ if ([self _getFloat:&val forNode:element property:@"border-right-width"]) [block setWidth:val type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockBorder edge:NSMaxXEdge];
+ if ([self _getFloat:&val forNode:element property:@"border-bottom-width"]) [block setWidth:val type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockBorder edge:NSMaxYEdge];
+
+ if ([self _getFloat:&val forNode:element property:@"margin-left"]) [block setWidth:val + extraMargin type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockMargin edge:NSMinXEdge]; else [block setWidth:extraMargin type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockMargin edge:NSMinXEdge];
+ if ([self _getFloat:&val forNode:element property:@"margin-top"]) [block setWidth:val + extraMargin type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockMargin edge:NSMinYEdge]; else [block setWidth:extraMargin type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockMargin edge:NSMinYEdge];
+ if ([self _getFloat:&val forNode:element property:@"margin-right"]) [block setWidth:val + extraMargin type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockMargin edge:NSMaxXEdge]; else [block setWidth:extraMargin type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockMargin edge:NSMaxXEdge];
+ if ([self _getFloat:&val forNode:element property:@"margin-bottom"]) [block setWidth:val + extraMargin type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockMargin edge:NSMaxYEdge]; else [block setWidth:extraMargin type:NSTextBlockAbsoluteValueType forLayer:NSTextBlockMargin edge:NSMaxYEdge];
+
+ if ((color = [self _colorForNode:element property:@"background-color"])) [block setBackgroundColor:color];
+ if (!color && backgroundColor) [block setBackgroundColor:backgroundColor];
+ if ((color = [self _colorForNode:element property:@"border-left-color"])) [block setBorderColor:color forEdge:NSMinXEdge];
+ if ((color = [self _colorForNode:element property:@"border-top-color"])) [block setBorderColor:color forEdge:NSMinYEdge];
+ if ((color = [self _colorForNode:element property:@"border-right-color"])) [block setBorderColor:color forEdge:NSMaxXEdge];
+ if ((color = [self _colorForNode:element property:@"border-bottom-color"])) [block setBorderColor:color forEdge:NSMaxYEdge];
+}
+
+static inline BOOL read2DigitNumber(const char **pp, int8_t *outval)
+{
+ BOOL result = NO;
+ char c1 = *(*pp)++, c2;
+ if (isASCIIDigit(c1)) {
+ c2 = *(*pp)++;
+ if (isASCIIDigit(c2)) {
+ *outval = 10 * (c1 - '0') + (c2 - '0');
+ result = YES;
+ }
+ }
+ return result;
+}
+
+static inline NSDate *_dateForString(NSString *string)
+{
+ CFGregorianDate date;
+ const char *p = [string UTF8String];
+ int8_t secval = 0;
+ BOOL wellFormed = YES;
+
+ date.year = 0;
+ while (*p && isASCIIDigit(*p)) date.year = 10 * date.year + *p++ - '0';
+ if (*p++ != '-') wellFormed = NO;
+ if (!wellFormed || !read2DigitNumber(&p, &date.month) || *p++ != '-') wellFormed = NO;
+ if (!wellFormed || !read2DigitNumber(&p, &date.day) || *p++ != 'T') wellFormed = NO;
+ if (!wellFormed || !read2DigitNumber(&p, &date.hour) || *p++ != ':') wellFormed = NO;
+ if (!wellFormed || !read2DigitNumber(&p, &date.minute) || *p++ != ':') wellFormed = NO;
+ if (!wellFormed || !read2DigitNumber(&p, &secval) || *p++ != 'Z') wellFormed = NO;
+ if (wellFormed) date.second = secval;
+ return wellFormed ? [(NSDate *)CFDateCreate(NULL, CFGregorianDateGetAbsoluteTime(date, NULL)) autorelease] : nil;
+}
+
+static NSInteger _colCompare(id block1, id block2, void *)
+{
+ NSInteger col1 = [(NSTextTableBlock *)block1 startingColumn], col2 = [(NSTextTableBlock *)block2 startingColumn];
+ return ((col1 < col2) ? NSOrderedAscending : ((col1 == col2) ? NSOrderedSame : NSOrderedDescending));
+}
+
+- (BOOL)_enterElement:(DOMElement *)element tag:(NSString *)tag display:(NSString *)displayVal
+{
+ if (!displayVal || !([@"none" isEqualToString:displayVal] || [@"table-column" isEqualToString:displayVal] || [@"table-column-group" isEqualToString:displayVal])) {
+ if ([self _elementIsBlockLevel:element] && ![@"BR" isEqualToString:tag] && !([@"table-cell" isEqualToString:displayVal] && [_textTables count] == 0)
+ && !([_textLists count] > 0 && [@"block" isEqualToString:displayVal] && ![@"LI" isEqualToString:tag] && ![@"UL" isEqualToString:tag] && ![@"OL" isEqualToString:tag]))
+ [self _newParagraphForElement:element tag:tag allowEmpty:NO suppressTrailingSpace:YES];
+ return YES;
+ }
+ return NO;
+}
+
+- (void)_addTableForElement:(DOMElement *)tableElement
+{
+ NSTextTable *table = [[NSTextTable alloc] init];
+ CGFloat cellSpacingVal = 1, cellPaddingVal = 1;
+ [table setNumberOfColumns:1];
+ [table setLayoutAlgorithm:NSTextTableAutomaticLayoutAlgorithm];
+ [table setCollapsesBorders:NO];
+ [table setHidesEmptyCells:NO];
+ if (tableElement) {
+ NSString *borderCollapse = [self _stringForNode:tableElement property:@"border-collapse"], *emptyCells = [self _stringForNode:tableElement property:@"empty-cells"], *tableLayout = [self _stringForNode:tableElement property:@"table-layout"];
+ if ([tableElement respondsToSelector:@selector(cellSpacing)]) {
+ NSString *cellSpacing = [(DOMHTMLTableElement *)tableElement cellSpacing];
+ if (cellSpacing && [cellSpacing length] > 0 && ![cellSpacing hasSuffix:@"%"]) cellSpacingVal = [cellSpacing floatValue];
+ }
+ if ([tableElement respondsToSelector:@selector(cellPadding)]) {
+ NSString *cellPadding = [(DOMHTMLTableElement *)tableElement cellPadding];
+ if (cellPadding && [cellPadding length] > 0 && ![cellPadding hasSuffix:@"%"]) cellPaddingVal = [cellPadding floatValue];
+ }
+ [self _fillInBlock:table forElement:tableElement backgroundColor:nil extraMargin:0 extraPadding:0 isTable:YES];
+ if ([@"collapse" isEqualToString:borderCollapse]) {
+ [table setCollapsesBorders:YES];
+ cellSpacingVal = 0;
+ }
+ if ([@"hide" isEqualToString:emptyCells]) [table setHidesEmptyCells:YES];
+ if ([@"fixed" isEqualToString:tableLayout]) [table setLayoutAlgorithm:NSTextTableFixedLayoutAlgorithm];
+ }
+ [_textTables addObject:table];
+ [_textTableSpacings addObject:[NSNumber numberWithDouble:cellSpacingVal]];
+ [_textTablePaddings addObject:[NSNumber numberWithDouble:cellPaddingVal]];
+ [_textTableRows addObject:[NSNumber numberWithInteger:0]];
+ [_textTableRowArrays addObject:[NSMutableArray array]];
+ [table release];
+}
+
+- (void)_addTableCellForElement:(DOMElement *)tableCellElement
+{
+ NSTextTable *table = [_textTables lastObject];
+ NSInteger rowNumber = [[_textTableRows lastObject] integerValue], columnNumber = 0, rowSpan = 1, colSpan = 1;
+ NSMutableArray *rowArray = [_textTableRowArrays lastObject];
+ NSUInteger i, count = [rowArray count];
+ NSColor *color = ([_textTableRowBackgroundColors count] > 0) ? [_textTableRowBackgroundColors lastObject] : nil;
+ NSTextTableBlock *block, *previousBlock;
+ CGFloat cellSpacingVal = [[_textTableSpacings lastObject] floatValue];
+ if ([color isEqual:[NSColor clearColor]]) color = nil;
+ for (i = 0; i < count; i++) {
+ previousBlock = [rowArray objectAtIndex:i];
+ if (columnNumber >= [previousBlock startingColumn] && columnNumber < [previousBlock startingColumn] + [previousBlock columnSpan]) columnNumber = [previousBlock startingColumn] + [previousBlock columnSpan];
+ }
+ if (tableCellElement) {
+ if ([tableCellElement respondsToSelector:@selector(rowSpan)]) {
+ rowSpan = [(DOMHTMLTableCellElement *)tableCellElement rowSpan];
+ if (rowSpan < 1) rowSpan = 1;
+ }
+ if ([tableCellElement respondsToSelector:@selector(colSpan)]) {
+ colSpan = [(DOMHTMLTableCellElement *)tableCellElement colSpan];
+ if (colSpan < 1) colSpan = 1;
+ }
+ }
+ block = [[NSTextTableBlock alloc] initWithTable:table startingRow:rowNumber rowSpan:rowSpan startingColumn:columnNumber columnSpan:colSpan];
+ if (tableCellElement) {
+ NSString *verticalAlign = [self _stringForNode:tableCellElement property:@"vertical-align"];
+ [self _fillInBlock:block forElement:tableCellElement backgroundColor:color extraMargin:cellSpacingVal / 2 extraPadding:0 isTable:NO];
+ if ([@"middle" isEqualToString:verticalAlign]) [block setVerticalAlignment:NSTextBlockMiddleAlignment];
+ else if ([@"bottom" isEqualToString:verticalAlign]) [block setVerticalAlignment:NSTextBlockBottomAlignment];
+ else if ([@"baseline" isEqualToString:verticalAlign]) [block setVerticalAlignment:NSTextBlockBaselineAlignment];
+ else if ([@"top" isEqualToString:verticalAlign]) [block setVerticalAlignment:NSTextBlockTopAlignment];
+ }
+ [_textBlocks addObject:block];
+ [rowArray addObject:block];
+ [rowArray sortUsingFunction:_colCompare context:NULL];
+ [block release];
+}
+
+- (BOOL)_processElement:(DOMElement *)element tag:(NSString *)tag display:(NSString *)displayVal depth:(NSInteger)depth
+{
+ BOOL retval = YES, isBlockLevel = [self _elementIsBlockLevel:element];
+ if (isBlockLevel) {
+ [_writingDirectionArray removeAllObjects];
+ } else {
+ NSString *bidi = [self _stringForNode:element property:@"unicode-bidi"];
+ if (bidi && [bidi isEqualToString:@"embed"]) {
+ NSUInteger val = NSTextWritingDirectionEmbedding;
+ NSString *direction = [self _stringForNode:element property:@"direction"];
+ if ([direction isEqualToString:@"rtl"]) val |= NSWritingDirectionRightToLeft;
+ [_writingDirectionArray addObject:[NSNumber numberWithUnsignedInteger:val]];
+ } else if (bidi && [bidi isEqualToString:@"bidi-override"]) {
+ NSUInteger val = NSTextWritingDirectionOverride;
+ NSString *direction = [self _stringForNode:element property:@"direction"];
+ if ([direction isEqualToString:@"rtl"]) val |= NSWritingDirectionRightToLeft;
+ [_writingDirectionArray addObject:[NSNumber numberWithUnsignedInteger:val]];
+ }
+ }
+ if ([@"table" isEqualToString:displayVal] || ([_textTables count] == 0 && [@"table-row-group" isEqualToString:displayVal])) {
+ DOMElement *tableElement = element;
+ if ([@"table-row-group" isEqualToString:displayVal]) {
+ // If we are starting in medias res, the first thing we see may be the tbody, so go up to the table
+ tableElement = [self _blockLevelElementForNode:[element parentNode]];
+ if (![@"table" isEqualToString:[self _stringForNode:tableElement property:@"display"]]) tableElement = element;
+ }
+ while ([_textTables count] > [_textBlocks count]) {
+ [self _addTableCellForElement:nil];
+ }
+ [self _addTableForElement:tableElement];
+ } else if ([@"table-footer-group" isEqualToString:displayVal] && [_textTables count] > 0) {
+ [_textTableFooters setObject:element forKey:[NSValue valueWithNonretainedObject:[_textTables lastObject]]];
+ retval = NO;
+ } else if ([@"table-row" isEqualToString:displayVal] && [_textTables count] > 0) {
+ NSColor *color = [self _colorForNode:element property:@"background-color"];
+ if (!color) color = [NSColor clearColor];
+ [_textTableRowBackgroundColors addObject:color];
+ } else if ([@"table-cell" isEqualToString:displayVal]) {
+ while ([_textTables count] < [_textBlocks count] + 1) {
+ [self _addTableForElement:nil];
+ }
+ [self _addTableCellForElement:element];
+ } else if ([@"IMG" isEqualToString:tag]) {
+ NSString *urlString = [element getAttribute:@"src"];
+ if (urlString && [urlString length] > 0) {
+ NSURL *url = core([element ownerDocument])->completeURL(stripLeadingAndTrailingHTMLSpaces(urlString));
+ if (!url) url = [NSURL _web_URLWithString:[urlString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] relativeToURL:_baseURL];
+ if (url) [self _addAttachmentForElement:element URL:url needsParagraph:isBlockLevel usePlaceholder:YES];
+ }
+ retval = NO;
+ } else if ([@"OBJECT" isEqualToString:tag]) {
+ NSString *baseString = [element getAttribute:@"codebase"], *urlString = [element getAttribute:@"data"], *declareString = [element getAttribute:@"declare"];
+ if (urlString && [urlString length] > 0 && ![@"true" isEqualToString:declareString]) {
+ NSURL *baseURL = nil, *url = nil;
+ if (baseString && [baseString length] > 0) {
+ baseURL = core([element ownerDocument])->completeURL(stripLeadingAndTrailingHTMLSpaces(baseString));
+ if (!baseURL) baseURL = [NSURL _web_URLWithString:[baseString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] relativeToURL:_baseURL];
+ }
+ if (baseURL) url = [NSURL _web_URLWithString:[urlString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] relativeToURL:baseURL];
+ if (!url) url =core([element ownerDocument])->completeURL(stripLeadingAndTrailingHTMLSpaces(urlString));
+ if (!url) url = [NSURL _web_URLWithString:[urlString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] relativeToURL:_baseURL];
+ if (url) retval = ![self _addAttachmentForElement:element URL:url needsParagraph:isBlockLevel usePlaceholder:NO];
+ }
+ } else if ([@"FRAME" isEqualToString:tag]) {
+ if ([element respondsToSelector:@selector(contentDocument)]) {
+ DOMDocument *contentDocument = [(DOMHTMLFrameElement *)element contentDocument];
+ if (contentDocument) [self _traverseNode:contentDocument depth:depth + 1 embedded:YES];
+ }
+ retval = NO;
+ } else if ([@"IFRAME" isEqualToString:tag]) {
+ if ([element respondsToSelector:@selector(contentDocument)]) {
+ DOMDocument *contentDocument = [(DOMHTMLIFrameElement *)element contentDocument];
+ if (contentDocument) {
+ [self _traverseNode:contentDocument depth:depth + 1 embedded:YES];
+ retval = NO;
+ }
+ }
+ } else if ([@"BR" isEqualToString:tag]) {
+ DOMElement *blockElement = [self _blockLevelElementForNode:[element parentNode]];
+ NSString *breakClass = [element getAttribute:@"class"], *blockTag = [blockElement tagName];
+ BOOL isExtraBreak = [@"Apple-interchange-newline" isEqualToString:breakClass], blockElementIsParagraph = ([@"P" isEqualToString:blockTag] || [@"LI" isEqualToString:blockTag] || ([blockTag hasPrefix:@"H"] && 2 == [blockTag length]));
+ if (isExtraBreak) {
+ _flags.hasTrailingNewline = YES;
+ } else {
+ if (blockElement && blockElementIsParagraph) {
+ [self _newLineForElement:element];
+ } else {
+ [self _newParagraphForElement:element tag:tag allowEmpty:YES suppressTrailingSpace:NO];
+ }
+ }
+ } else if ([@"UL" isEqualToString:tag]) {
+ NSTextList *list;
+ NSString *listStyleType = [self _stringForNode:element property:@"list-style-type"];
+ if (!listStyleType || [listStyleType length] == 0) listStyleType = @"disc";
+ list = [[NSTextList alloc] initWithMarkerFormat:[NSString stringWithFormat:@"{%@}", listStyleType] options:0];
+ [_textLists addObject:list];
+ [list release];
+ } else if ([@"OL" isEqualToString:tag]) {
+ NSTextList *list;
+ NSString *listStyleType = [self _stringForNode:element property:@"list-style-type"];
+ if (!listStyleType || [listStyleType length] == 0) listStyleType = @"decimal";
+ list = [[NSTextList alloc] initWithMarkerFormat:[NSString stringWithFormat:@"{%@}.", listStyleType] options:0];
+ if ([element respondsToSelector:@selector(start)]) {
+ NSInteger startingItemNumber = [(DOMHTMLOListElement *)element start];
+ [list setStartingItemNumber:startingItemNumber];
+ }
+ [_textLists addObject:list];
+ [list release];
+ } else if ([@"Q" isEqualToString:tag]) {
+ [self _addQuoteForElement:element opening:YES level:_quoteLevel++];
+ } else if ([@"INPUT" isEqualToString:tag]) {
+ if ([element respondsToSelector:@selector(type)] && [element respondsToSelector:@selector(value)] && [@"text" compare:[(DOMHTMLInputElement *)element type] options:NSCaseInsensitiveSearch] == NSOrderedSame) {
+ NSString *value = [(DOMHTMLInputElement *)element value];
+ if (value && [value length] > 0) [self _addValue:value forElement:element];
+ }
+ } else if ([@"TEXTAREA" isEqualToString:tag]) {
+ if ([element respondsToSelector:@selector(value)]) {
+ NSString *value = [(DOMHTMLTextAreaElement *)element value];
+ if (value && [value length] > 0) [self _addValue:value forElement:element];
+ }
+ retval = NO;
+ }
+ return retval;
+}
+
+- (void)_addMarkersToList:(NSTextList *)list range:(NSRange)range
+{
+ NSInteger itemNum = [list startingItemNumber];
+ NSString *string = [_attrStr string], *stringToInsert;
+ NSDictionary *attrsToInsert = nil;
+ NSFont *font;
+ NSParagraphStyle *paragraphStyle;
+ NSMutableParagraphStyle *newStyle;
+ NSTextTab *tab = nil, *tabToRemove;
+ NSRange paragraphRange, styleRange;
+ NSUInteger textLength = [_attrStr length], listIndex, idx, insertLength, i, count;
+ NSArray *textLists;
+ CGFloat markerLocation, listLocation, pointSize;
+
+ if (range.length == 0 || range.location >= textLength) return;
+ if (NSMaxRange(range) > textLength) range.length = textLength - range.location;
+ paragraphStyle = [_attrStr attribute:NSParagraphStyleAttributeName atIndex:range.location effectiveRange:NULL];
+ if (paragraphStyle) {
+ textLists = [paragraphStyle textLists];
+ listIndex = [textLists indexOfObject:list];
+ if (textLists && listIndex != NSNotFound) {
+ for (idx = range.location; idx < NSMaxRange(range);) {
+ paragraphRange = [string paragraphRangeForRange:NSMakeRange(idx, 0)];
+ paragraphStyle = [_attrStr attribute:NSParagraphStyleAttributeName atIndex:idx effectiveRange:&styleRange];
+ font = [_attrStr attribute:NSFontAttributeName atIndex:idx effectiveRange:NULL];
+ pointSize = font ? [font pointSize] : 12;
+ if ([[paragraphStyle textLists] count] == listIndex + 1) {
+ stringToInsert = [NSString stringWithFormat:@"\t%@\t", [list markerForItemNumber:itemNum++]];
+ insertLength = [stringToInsert length];
+ if (!_flags.isIndexing && !_flags.isTesting) attrsToInsert = [NSTextList _standardMarkerAttributesForAttributes:[_attrStr attributesAtIndex:paragraphRange.location effectiveRange:NULL]];
+ [_attrStr replaceCharactersInRange:NSMakeRange(paragraphRange.location, 0) withString:stringToInsert];
+ if (!_flags.isIndexing && !_flags.isTesting) [_attrStr setAttributes:attrsToInsert range:NSMakeRange(paragraphRange.location, insertLength)];
+ range.length += insertLength;
+ paragraphRange.length += insertLength;
+ if (paragraphRange.location < _domRangeStartIndex) _domRangeStartIndex += insertLength;
+
+ newStyle = [paragraphStyle mutableCopy];
+ listLocation = (listIndex + 1) * 36;
+ markerLocation = listLocation - 25;
+ [newStyle setFirstLineHeadIndent:0];
+ [newStyle setHeadIndent:listLocation];
+ while ((count = [[newStyle tabStops] count]) > 0) {
+ for (i = 0, tabToRemove = nil; !tabToRemove && i < count; i++) {
+ tab = [[newStyle tabStops] objectAtIndex:i];
+ if ([tab location] <= listLocation) tabToRemove = tab;
+ }
+ if (tabToRemove) [newStyle removeTabStop:tab]; else break;
+ }
+ tab = [[NSTextTab alloc] initWithType:NSLeftTabStopType location:markerLocation];
+ [newStyle addTabStop:tab];
+ [tab release];
+ tab = [[NSTextTab alloc] initWithTextAlignment:NSNaturalTextAlignment location:listLocation options:nil];
+ [newStyle addTabStop:tab];
+ [tab release];
+ if (!_flags.isIndexing && !_flags.isTesting) [_attrStr addAttribute:NSParagraphStyleAttributeName value:newStyle range:paragraphRange];
+ [newStyle release];
+
+ idx = NSMaxRange(paragraphRange);
+ } else {
+ // skip any deeper-nested lists
+ idx = NSMaxRange(styleRange);
+ }
+ }
+ }
+ }
+}
+
+- (void)_exitElement:(DOMElement *)element tag:(NSString *)tag display:(NSString *)displayVal depth:(NSInteger)depth startIndex:(NSUInteger)startIndex
+{
+ NSRange range = NSMakeRange(startIndex, [_attrStr length] - startIndex);
+ if (range.length > 0 && [@"A" isEqualToString:tag]) {
+ NSString *urlString = [element getAttribute:@"href"], *strippedString = [urlString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
+ if (urlString && [urlString length] > 0 && strippedString && [strippedString length] > 0 && ![strippedString hasPrefix:@"#"]) {
+ NSURL *url = core([element ownerDocument])->completeURL(stripLeadingAndTrailingHTMLSpaces(urlString));
+ if (!url) url = core([element ownerDocument])->completeURL(stripLeadingAndTrailingHTMLSpaces(strippedString));
+ if (!url) url = [NSURL _web_URLWithString:strippedString relativeToURL:_baseURL];
+ if (!_flags.isIndexing && !_flags.isTesting) [_attrStr addAttribute:NSLinkAttributeName value:url ? (id)url : (id)urlString range:range];
+ }
+ }
+ if (!_flags.reachedEnd && [self _elementIsBlockLevel:element]) {
+ [_writingDirectionArray removeAllObjects];
+ if ([@"table-cell" isEqualToString:displayVal] && [_textBlocks count] == 0) {
+ [self _newTabForElement:element];
+ } else if ([_textLists count] > 0 && [@"block" isEqualToString:displayVal] && ![@"LI" isEqualToString:tag] && ![@"UL" isEqualToString:tag] && ![@"OL" isEqualToString:tag]) {
+ [self _newLineForElement:element];
+ } else {
+ [self _newParagraphForElement:element tag:tag allowEmpty:(range.length == 0) suppressTrailingSpace:YES];
+ }
+ } else if ([_writingDirectionArray count] > 0) {
+ NSString *bidi = [self _stringForNode:element property:@"unicode-bidi"];
+ if (bidi && ([bidi isEqualToString:@"embed"] || [bidi isEqualToString:@"bidi-override"])) {
+ [_writingDirectionArray removeLastObject];
+ }
+ }
+ range = NSMakeRange(startIndex, [_attrStr length] - startIndex);
+ if ([@"table" isEqualToString:displayVal] && [_textTables count] > 0) {
+ NSValue *key = [NSValue valueWithNonretainedObject:[_textTables lastObject]];
+ DOMNode *footer = [_textTableFooters objectForKey:key];
+ while ([_textTables count] < [_textBlocks count] + 1) {
+ [_textBlocks removeLastObject];
+ }
+ if (footer) {
+ [self _traverseFooterNode:footer depth:depth + 1];
+ [_textTableFooters removeObjectForKey:key];
+ }
+ [_textTables removeLastObject];
+ [_textTableSpacings removeLastObject];
+ [_textTablePaddings removeLastObject];
+ [_textTableRows removeLastObject];
+ [_textTableRowArrays removeLastObject];
+ } else if ([@"table-row" isEqualToString:displayVal] && [_textTables count] > 0) {
+ NSTextTable *table = [_textTables lastObject];
+ NSTextTableBlock *block;
+ NSMutableArray *rowArray = [_textTableRowArrays lastObject], *previousRowArray;
+ NSUInteger i, count;
+ NSInteger numberOfColumns = [table numberOfColumns];
+ NSInteger openColumn;
+ NSInteger rowNumber = [[_textTableRows lastObject] integerValue];
+ do {
+ rowNumber++;
+ previousRowArray = rowArray;
+ rowArray = [NSMutableArray array];
+ count = [previousRowArray count];
+ for (i = 0; i < count; i++) {
+ block = [previousRowArray objectAtIndex:i];
+ if ([block startingColumn] + [block columnSpan] > numberOfColumns) numberOfColumns = [block startingColumn] + [block columnSpan];
+ if ([block startingRow] + [block rowSpan] > rowNumber) [rowArray addObject:block];
+ }
+ count = [rowArray count];
+ openColumn = 0;
+ for (i = 0; i < count; i++) {
+ block = [rowArray objectAtIndex:i];
+ if (openColumn >= [block startingColumn] && openColumn < [block startingColumn] + [block columnSpan]) openColumn = [block startingColumn] + [block columnSpan];
+ }
+ } while (openColumn >= numberOfColumns);
+ if ((NSUInteger)numberOfColumns > [table numberOfColumns]) [table setNumberOfColumns:numberOfColumns];
+ [_textTableRows removeLastObject];
+ [_textTableRows addObject:[NSNumber numberWithInteger:rowNumber]];
+ [_textTableRowArrays removeLastObject];
+ [_textTableRowArrays addObject:rowArray];
+ if ([_textTableRowBackgroundColors count] > 0) [_textTableRowBackgroundColors removeLastObject];
+ } else if ([@"table-cell" isEqualToString:displayVal] && [_textBlocks count] > 0) {
+ while ([_textTables count] > [_textBlocks count]) {
+ [_textTables removeLastObject];
+ [_textTableSpacings removeLastObject];
+ [_textTablePaddings removeLastObject];
+ [_textTableRows removeLastObject];
+ [_textTableRowArrays removeLastObject];
+ }
+ [_textBlocks removeLastObject];
+ } else if (([@"UL" isEqualToString:tag] || [@"OL" isEqualToString:tag]) && [_textLists count] > 0) {
+ NSTextList *list = [_textLists lastObject];
+ [self _addMarkersToList:list range:range];
+ [_textLists removeLastObject];
+ } else if ([@"Q" isEqualToString:tag]) {
+ [self _addQuoteForElement:element opening:NO level:--_quoteLevel];
+ } else if ([@"SPAN" isEqualToString:tag]) {
+ NSString *className = [element getAttribute:@"class"];
+ NSMutableString *mutableString;
+ NSUInteger i, count = 0;
+ unichar c;
+ if ([@"Apple-converted-space" isEqualToString:className]) {
+ mutableString = [_attrStr mutableString];
+ for (i = range.location; i < NSMaxRange(range); i++) {
+ c = [mutableString characterAtIndex:i];
+ if (0xa0 == c) [mutableString replaceCharactersInRange:NSMakeRange(i, 1) withString:@" "];
+ }
+ } else if ([@"Apple-converted-tab" isEqualToString:className]) {
+ mutableString = [_attrStr mutableString];
+ for (i = range.location; i < NSMaxRange(range); i++) {
+ NSRange rangeToReplace = NSMakeRange(NSNotFound, 0);
+ c = [mutableString characterAtIndex:i];
+ if (' ' == c || 0xa0 == c) {
+ count++;
+ if (count >= 4 || i + 1 >= NSMaxRange(range)) rangeToReplace = NSMakeRange(i + 1 - count, count);
+ } else {
+ if (count > 0) rangeToReplace = NSMakeRange(i - count, count);
+ }
+ if (rangeToReplace.length > 0) {
+ [mutableString replaceCharactersInRange:rangeToReplace withString:@"\t"];
+ range.length -= (rangeToReplace.length - 1);
+ i -= (rangeToReplace.length - 1);
+ if (NSMaxRange(rangeToReplace) <= _domRangeStartIndex) {
+ _domRangeStartIndex -= (rangeToReplace.length - 1);
+ } else if (rangeToReplace.location < _domRangeStartIndex) {
+ _domRangeStartIndex = rangeToReplace.location;
+ }
+ count = 0;
+ }
+ }
+ }
+ }
+}
+
+- (void)_processText:(DOMCharacterData *)text
+{
+ NSString *instr = [text data], *outstr = instr, *whitespaceVal, *transformVal;
+ NSUInteger textLength = [_attrStr length], startOffset = 0, endOffset = [instr length];
+ unichar lastChar = (textLength > 0) ? [[_attrStr string] characterAtIndex:textLength - 1] : '\n';
+ BOOL wasSpace = NO, wasLeading = YES, suppressLeadingSpace = ((_flags.isSoft && lastChar == ' ') || lastChar == '\n' || lastChar == '\r' || lastChar == '\t' || lastChar == NSParagraphSeparatorCharacter || lastChar == NSLineSeparatorCharacter || lastChar == NSFormFeedCharacter || lastChar == WebNextLineCharacter);
+ NSRange rangeToReplace = NSMakeRange(textLength, 0);
+ CFMutableStringRef mutstr = NULL;
+ whitespaceVal = [self _stringForNode:text property:@"white-space"];
+ transformVal = [self _stringForNode:text property:@"text-transform"];
+
+ if (_domRange) {
+ if (text == [_domRange startContainer]) {
+ startOffset = (NSUInteger)[_domRange startOffset];
+ _domRangeStartIndex = [_attrStr length];
+ _flags.reachedStart = YES;
+ }
+ if (text == [_domRange endContainer]) {
+ endOffset = (NSUInteger)[_domRange endOffset];
+ _flags.reachedEnd = YES;
+ }
+ if ((startOffset > 0 || endOffset < [instr length]) && endOffset >= startOffset) {
+ instr = [instr substringWithRange:NSMakeRange(startOffset, endOffset - startOffset)];
+ outstr = instr;
+ }
+ }
+ if ([whitespaceVal hasPrefix:@"pre"]) {
+ if (textLength > 0 && [instr length] > 0 && _flags.isSoft) {
+ unichar c = [instr characterAtIndex:0];
+ if (c == '\n' || c == '\r' || c == NSParagraphSeparatorCharacter || c == NSLineSeparatorCharacter || c == NSFormFeedCharacter || c == WebNextLineCharacter) rangeToReplace = NSMakeRange(textLength - 1, 1);
+ }
+ } else {
+ CFStringInlineBuffer inlineBuffer;
+ const unsigned int TextBufferSize = 255;
+
+ unichar buffer[TextBufferSize + 1];
+ NSUInteger i, count = [instr length], idx = 0;
+
+ mutstr = CFStringCreateMutable(NULL, 0);
+ CFStringInitInlineBuffer((CFStringRef)instr, &inlineBuffer, CFRangeMake(0, count));
+ for (i = 0; i < count; i++) {
+ unichar c = CFStringGetCharacterFromInlineBuffer(&inlineBuffer, i);
+ if (c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == 0xc || c == 0x200b) {
+ wasSpace = (!wasLeading || !suppressLeadingSpace);
+ } else {
+ if (wasSpace) buffer[idx++] = ' ';
+ buffer[idx++] = c;
+ if (idx >= TextBufferSize) {
+ CFStringAppendCharacters(mutstr, buffer, idx);
+ idx = 0;
+ }
+ wasSpace = wasLeading = NO;
+ }
+ }
+ if (wasSpace) buffer[idx++] = ' ';
+ if (idx > 0) CFStringAppendCharacters(mutstr, buffer, idx);
+ outstr = (NSString *)mutstr;
+ }
+ if ([outstr length] > 0) {
+ if ([@"capitalize" isEqualToString:transformVal]) {
+ outstr = [outstr capitalizedString];
+ } else if ([@"uppercase" isEqualToString:transformVal]) {
+ outstr = [outstr uppercaseString];
+ } else if ([@"lowercase" isEqualToString:transformVal]) {
+ outstr = [outstr lowercaseString];
+ }
+ [_attrStr replaceCharactersInRange:rangeToReplace withString:outstr];
+ rangeToReplace.length = [outstr length];
+ if (!_flags.isIndexing) {
+ NSDictionary *attrs;
+ DOMElement *element = (DOMElement *)text;
+ while (element && [element nodeType] != DOM_ELEMENT_NODE) element = (DOMElement *)[element parentNode];
+ attrs = [self _attributesForElement:element];
+ if (!_flags.isTesting && rangeToReplace.length > 0) [_attrStr setAttributes:attrs range:rangeToReplace];
+ }
+ _flags.isSoft = wasSpace;
+ }
+ if (mutstr) CFRelease(mutstr);
+}
+
+- (void)_traverseNode:(DOMNode *)node depth:(NSInteger)depth embedded:(BOOL)embedded
+{
+ unsigned short nodeType;
+ NSArray *childNodes;
+ NSUInteger i, count, startOffset, endOffset;
+ BOOL isStart = NO, isEnd = NO;
+
+ if (_flags.reachedEnd) return;
+ if (_domRange && !_flags.reachedStart && _domStartAncestors && ![_domStartAncestors containsObject:node]) return;
+
+ nodeType = [node nodeType];
+ childNodes = [self _childrenForNode:node];
+ count = [childNodes count];
+ startOffset = 0;
+ endOffset = count;
+
+ if (_domRange) {
+ if (node == [_domRange startContainer]) {
+ startOffset = (NSUInteger)[_domRange startOffset];
+ isStart = YES;
+ _flags.reachedStart = YES;
+ }
+ if (node == [_domRange endContainer]) {
+ endOffset = (NSUInteger)[_domRange endOffset];
+ isEnd = YES;
+ }
+ }
+
+ if (nodeType == DOM_DOCUMENT_NODE || nodeType == DOM_DOCUMENT_FRAGMENT_NODE) {
+ for (i = 0; i < count; i++) {
+ if (isStart && i == startOffset) _domRangeStartIndex = [_attrStr length];
+ if ((!isStart || startOffset <= i) && (!isEnd || endOffset > i)) [self _traverseNode:[childNodes objectAtIndex:i] depth:depth + 1 embedded:embedded];
+ if (isEnd && i + 1 >= endOffset) _flags.reachedEnd = YES;
+ if (_thumbnailLimit > 0 && [_attrStr length] >= _thumbnailLimit) _flags.reachedEnd = YES;
+ if (_flags.reachedEnd) break;
+ }
+ } else if (nodeType == DOM_ELEMENT_NODE) {
+ DOMElement *element = (DOMElement *)node;
+ NSString *tag = [element tagName], *displayVal = [self _stringForNode:element property:@"display"], *floatVal = [self _stringForNode:element property:@"float"];
+ BOOL isBlockLevel = NO;
+ if (floatVal && ([@"left" isEqualToString:floatVal] || [@"right" isEqualToString:floatVal])) {
+ isBlockLevel = YES;
+ } else if (displayVal) {
+ isBlockLevel = ([@"block" isEqualToString:displayVal] || [@"list-item" isEqualToString:displayVal] || [displayVal hasPrefix:@"table"]);
+ }
+ [_elementIsBlockLevel setObject:[NSNumber numberWithBool:isBlockLevel] forKey:element];
+ if ([self _enterElement:element tag:tag display:displayVal]) {
+ NSUInteger startIndex = [_attrStr length];
+ if ([self _processElement:element tag:tag display:displayVal depth:depth]) {
+ for (i = 0; i < count; i++) {
+ if (isStart && i == startOffset) _domRangeStartIndex = [_attrStr length];
+ if ((!isStart || startOffset <= i) && (!isEnd || endOffset > i)) [self _traverseNode:[childNodes objectAtIndex:i] depth:depth + 1 embedded:embedded];
+ if (isEnd && i + 1 >= endOffset) _flags.reachedEnd = YES;
+ if (_flags.reachedEnd) break;
+ }
+ [self _exitElement:element tag:tag display:displayVal depth:depth startIndex:startIndex];
+ }
+ }
+ } else if (nodeType == DOM_TEXT_NODE || nodeType == DOM_CDATA_SECTION_NODE) {
+ [self _processText:(DOMCharacterData *)node];
+ }
+
+ if (isEnd) _flags.reachedEnd = YES;
+}
+
+- (void)_traverseFooterNode:(DOMNode *)node depth:(NSInteger)depth
+{
+ DOMElement *element = (DOMElement *)node;
+ NSArray *childNodes = [self _childrenForNode:node];
+ NSString *tag = @"TBODY", *displayVal = @"table-row-group";
+ NSUInteger i, count = [childNodes count], startOffset = 0, endOffset = count;
+ BOOL isStart = NO, isEnd = NO;
+
+ if (_flags.reachedEnd) return;
+ if (_domRange && !_flags.reachedStart && _domStartAncestors && ![_domStartAncestors containsObject:node]) return;
+ if (_domRange) {
+ if (node == [_domRange startContainer]) {
+ startOffset = (NSUInteger)[_domRange startOffset];
+ isStart = YES;
+ _flags.reachedStart = YES;
+ }
+ if (node == [_domRange endContainer]) {
+ endOffset = (NSUInteger)[_domRange endOffset];
+ isEnd = YES;
+ }
+ }
+ if ([self _enterElement:element tag:tag display:displayVal]) {
+ NSUInteger startIndex = [_attrStr length];
+ if ([self _processElement:element tag:tag display:displayVal depth:depth]) {
+ for (i = 0; i < count; i++) {
+ if (isStart && i == startOffset) _domRangeStartIndex = [_attrStr length];
+ if ((!isStart || startOffset <= i) && (!isEnd || endOffset > i)) [self _traverseNode:[childNodes objectAtIndex:i] depth:depth + 1 embedded:YES];
+ if (isEnd && i + 1 >= endOffset) _flags.reachedEnd = YES;
+ if (_flags.reachedEnd) break;
+ }
+ [self _exitElement:element tag:tag display:displayVal depth:depth startIndex:startIndex];
+ }
+ }
+ if (isEnd) _flags.reachedEnd = YES;
+}
+
+- (void)_adjustTrailingNewline
+{
+ NSUInteger textLength = [_attrStr length];
+ unichar lastChar = (textLength > 0) ? [[_attrStr string] characterAtIndex:textLength - 1] : 0;
+ BOOL alreadyHasTrailingNewline = (lastChar == '\n' || lastChar == '\r' || lastChar == NSParagraphSeparatorCharacter || lastChar == NSLineSeparatorCharacter || lastChar == WebNextLineCharacter);
+ if (_flags.hasTrailingNewline && !alreadyHasTrailingNewline)
+ [_attrStr replaceCharactersInRange:NSMakeRange(textLength, 0) withString:@"\n"];
+}
+
+- (void)_loadFromDOMRange
+{
+ if (-1 == _errorCode) {
+ DOMNode *commonAncestorContainer = [_domRange commonAncestorContainer], *ancestorContainer = [_domRange startContainer];
+
+ _domStartAncestors = [[NSMutableArray alloc] init];
+ while (ancestorContainer) {
+ [_domStartAncestors addObject:ancestorContainer];
+ if (ancestorContainer == commonAncestorContainer) break;
+ ancestorContainer = [ancestorContainer parentNode];
+ }
+ _document = [commonAncestorContainer ownerDocument];
+ _dataSource = (DocumentLoader *)core(_document)->frame()->loader()->documentLoader();
+ if (_textSizeMultiplier <= 0.0) _textSizeMultiplier = 1;
+ if (_defaultFontSize <= 0.0) _defaultFontSize = 12;
+ if (_minimumFontSize < 1.0) _minimumFontSize = 1;
+ if (_document && _dataSource) {
+ _domRangeStartIndex = 0;
+ _errorCode = 0;
+ [self _traverseNode:commonAncestorContainer depth:0 embedded:NO];
+ if (_domRangeStartIndex > 0 && _domRangeStartIndex <= [_attrStr length]) [_attrStr deleteCharactersInRange:NSMakeRange(0, _domRangeStartIndex)];
+ }
+ }
+}
+
+- (void)dealloc
+{
+ [_attrStr release];
+ [_domRange release];
+ [_domStartAncestors release];
+ [_standardFontFamily release];
+ [_textLists release];
+ [_textBlocks release];
+ [_textTables release];
+ [_textTableFooters release];
+ [_textTableSpacings release];
+ [_textTablePaddings release];
+ [_textTableRows release];
+ [_textTableRowArrays release];
+ [_textTableRowBackgroundColors release];
+ [_computedStylesForElements release];
+ [_specifiedStylesForElements release];
+ [_stringsForNodes release];
+ [_floatsForNodes release];
+ [_colorsForNodes release];
+ [_attributesForElements release];
+ [_elementIsBlockLevel release];
+ [_fontCache release];
+ [_writingDirectionArray release];
+ [super dealloc];
+}
+
+- (id)init
+{
+ self = [super init];
+ if (!self) return nil;
+
+ _attrStr = [[NSMutableAttributedString alloc] init];
+
+ _textLists = [[NSMutableArray alloc] init];
+ _textBlocks = [[NSMutableArray alloc] init];
+ _textTables = [[NSMutableArray alloc] init];
+ _textTableFooters = [[NSMutableDictionary alloc] init];
+ _textTableSpacings = [[NSMutableArray alloc] init];
+ _textTablePaddings = [[NSMutableArray alloc] init];
+ _textTableRows = [[NSMutableArray alloc] init];
+ _textTableRowArrays = [[NSMutableArray alloc] init];
+ _textTableRowBackgroundColors = [[NSMutableArray alloc] init];
+ _computedStylesForElements = [[NSMutableDictionary alloc] init];
+ _specifiedStylesForElements = [[NSMutableDictionary alloc] init];
+ _stringsForNodes = [[NSMutableDictionary alloc] init];
+ _floatsForNodes = [[NSMutableDictionary alloc] init];
+ _colorsForNodes = [[NSMutableDictionary alloc] init];
+ _attributesForElements = [[NSMutableDictionary alloc] init];
+ _elementIsBlockLevel = [[NSMutableDictionary alloc] init];
+ _fontCache = [[NSMutableDictionary alloc] init];
+ _writingDirectionArray = [[NSMutableArray alloc] init];
+
+ _textSizeMultiplier = 1;
+ _webViewTextSizeMultiplier = 0;
+ _defaultTabInterval = 36;
+ _defaultFontSize = 12;
+ _minimumFontSize = 1;
+ _errorCode = -1;
+ _indexingLimit = 0;
+ _thumbnailLimit = 0;
+
+ _flags.isIndexing = (_indexingLimit > 0);
+ _flags.isTesting = 0;
+
+ return self;
+}
+
+- (id)initWithDOMRange:(DOMRange *)domRange
+{
+ self = [self init];
+ if (!self) return nil;
+ _domRange = [domRange retain];
+ return self;
+}
+
+- (NSAttributedString *)attributedString
+{
+ [self _loadFromDOMRange];
+ return (0 == _errorCode) ? [[_attrStr retain] autorelease] : nil;
+}
+
+@end
+#endif
diff --git a/Source/WebCore/platform/mac/LoggingMac.mm b/Source/WebCore/platform/mac/LoggingMac.mm
index ee2f39e..168d0cc 100644
--- a/Source/WebCore/platform/mac/LoggingMac.mm
+++ b/Source/WebCore/platform/mac/LoggingMac.mm
@@ -23,6 +23,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "config.h"
+
#include "Logging.h"
namespace WebCore {
diff --git a/Source/WebCore/platform/mac/PasteboardMac.mm b/Source/WebCore/platform/mac/PasteboardMac.mm
index 8c6610a..da06606 100644
--- a/Source/WebCore/platform/mac/PasteboardMac.mm
+++ b/Source/WebCore/platform/mac/PasteboardMac.mm
@@ -38,6 +38,10 @@
#import "FrameLoaderClient.h"
#import "HitTestResult.h"
#import "HTMLAnchorElement.h"
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+#import "HTMLConverter.h"
+#endif
+#import "htmlediting.h"
#import "HTMLNames.h"
#import "Image.h"
#import "KURL.h"
@@ -144,9 +148,30 @@ void Pasteboard::writeSelection(NSPasteboard* pasteboard, NSArray* pasteboardTyp
Pasteboard::generalPasteboard(); // Initializes pasteboard types.
ASSERT(selectedRange);
+ // If the selection is at the beginning of content inside an anchor tag
+ // we move the selection start to include the anchor.
+ // This way the attributed string will contain the url attribute as well.
+ // See <rdar://problem/9084267>.
+ ExceptionCode ec;
+ Node* commonAncestor = selectedRange->commonAncestorContainer(ec);
+ ASSERT(commonAncestor);
+ Node* enclosingAnchor = enclosingNodeWithTag(firstPositionInNode(commonAncestor), HTMLNames::aTag);
+ if (enclosingAnchor && comparePositions(firstPositionInOrBeforeNode(selectedRange->startPosition().anchorNode()), selectedRange->startPosition()) >= 0)
+ selectedRange->setStart(enclosingAnchor, 0, ec);
+
// Using different API for WebKit and WebKit2.
- // FIXME - We need to have a way to create the NSAttributedString for WebKit2 that doesn't require accessing the WebFrame.
- NSAttributedString *attributedString = (frame->view()->platformWidget()) ? [[[NSAttributedString alloc] _initWithDOMRange:kit(selectedRange)] autorelease] : [[[NSAttributedString alloc] initWithString:selectedRange->text()] autorelease];
+ NSAttributedString *attributedString = nil;
+ if (frame->view()->platformWidget())
+ attributedString = [[[NSAttributedString alloc] _initWithDOMRange:kit(selectedRange)] autorelease];
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ else {
+ // In WebKit2 we are using a different way to create the NSAttributedString from the DOMrange that doesn't require access to the WebView.
+ RetainPtr<WebHTMLConverter> converter = [[WebHTMLConverter alloc] initWithDOMRange:kit(selectedRange)];
+ if (converter)
+ attributedString = [converter.get() attributedString];
+ }
+#endif
+
#ifdef BUILDING_ON_TIGER
// 4930197: Mail overrides [WebHTMLView pasteboardTypesForSelection] in order to add another type to the pasteboard
// after WebKit does. On Tiger we must call this function so that Mail code will be executed, meaning that
diff --git a/Source/WebCore/platform/mac/PlatformScreenMac.mm b/Source/WebCore/platform/mac/PlatformScreenMac.mm
index 5dbfcf4..916fc9f 100644
--- a/Source/WebCore/platform/mac/PlatformScreenMac.mm
+++ b/Source/WebCore/platform/mac/PlatformScreenMac.mm
@@ -76,12 +76,21 @@ 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 userRect = rect;
userRect.setY(NSMaxY([screenForWindow(destination) frame]) - (userRect.y() + userRect.height())); // flip
if (destination)
- userRect.scale(1 / [destination userSpaceScaleFactor]); // scale down
+ userRect.scale(1 / windowScaleFactor(destination)); // scale down
return userRect;
}
@@ -89,7 +98,7 @@ NSRect toDeviceSpace(const FloatRect& rect, NSWindow *source)
{
FloatRect deviceRect = rect;
if (source)
- deviceRect.scale([source userSpaceScaleFactor]); // scale up
+ deviceRect.scale(windowScaleFactor(source)); // scale up
deviceRect.setY(NSMaxY([screenForWindow(source) frame]) - (deviceRect.y() + deviceRect.height())); // flip
return deviceRect;
}
diff --git a/Source/WebCore/platform/mac/SSLKeyGeneratorMac.cpp b/Source/WebCore/platform/mac/SSLKeyGeneratorMac.cpp
new file mode 100644
index 0000000..0a1a4d8
--- /dev/null
+++ b/Source/WebCore/platform/mac/SSLKeyGeneratorMac.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2003, 2005, 2008, 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 "SSLKeyGenerator.h"
+
+#include "KURL.h"
+#include "LocalizedStrings.h"
+#include "WebCoreSystemInterface.h"
+#include <wtf/RetainPtr.h>
+
+namespace WebCore {
+
+void getSupportedKeySizes(Vector<String>& supportedKeySizes)
+{
+ ASSERT(supportedKeySizes.isEmpty());
+ supportedKeySizes.append(keygenMenuItem2048());
+ supportedKeySizes.append(keygenMenuItem1024());
+ supportedKeySizes.append(keygenMenuItem512());
+}
+
+String signedPublicKeyAndChallengeString(unsigned keySizeIndex, const String& challengeString, const KURL& url)
+{
+ // This switch statement must always be synced with the UI strings returned by getSupportedKeySizes.
+ UInt32 keySize;
+ switch (keySizeIndex) {
+ case 0:
+ keySize = 2048;
+ break;
+ case 1:
+ keySize = 1024;
+ break;
+ case 2:
+ keySize = 512;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ return String();
+ }
+
+ RetainPtr<CFStringRef> challengeStringCF(AdoptCF, challengeString.createCFString());
+ RetainPtr<CFStringRef> keyDescription(AdoptCF, keygenKeychainItemName(url.host()).createCFString());
+ RetainPtr<CFStringRef> result(AdoptCF, wkSignedPublicKeyAndChallengeString(keySize, challengeStringCF.get(), keyDescription.get()));
+
+ return result.get();
+}
+
+}
diff --git a/Source/WebCore/platform/mac/ScrollAnimatorMac.h b/Source/WebCore/platform/mac/ScrollAnimatorMac.h
index 2bafbf5..f7b6332 100644
--- a/Source/WebCore/platform/mac/ScrollAnimatorMac.h
+++ b/Source/WebCore/platform/mac/ScrollAnimatorMac.h
@@ -30,7 +30,6 @@
#include "FloatPoint.h"
#include "FloatSize.h"
-#include "HeaderDetection.h"
#include "ScrollAnimator.h"
#include "Timer.h"
#include "WebCoreSystemInterface.h"
@@ -67,6 +66,8 @@ public:
#endif
#endif
+ virtual void cancelAnimations();
+
void immediateScrollToPoint(const FloatPoint& newPosition);
void immediateScrollByDeltaX(float deltaX);
void immediateScrollByDeltaY(float deltaY);
@@ -74,14 +75,25 @@ public:
void setIsDrawingIntoLayer(bool b) { m_drawingIntoLayer = b; }
bool isDrawingIntoLayer() const { return m_drawingIntoLayer; }
+ bool haveScrolledSincePageLoad() const { return m_haveScrolledSincePageLoad; }
+
+#if USE(WK_SCROLLBAR_PAINTER)
+ bool scrollbarPaintTimerIsActive() const;
+ void startScrollbarPaintTimer();
+ void stopScrollbarPaintTimer();
+#endif
+
private:
RetainPtr<id> m_scrollAnimationHelper;
RetainPtr<ScrollAnimationHelperDelegate> m_scrollAnimationHelperDelegate;
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
RetainPtr<WKScrollbarPainterControllerRef> m_scrollbarPainterController;
RetainPtr<ScrollbarPainterControllerDelegate> m_scrollbarPainterControllerDelegate;
RetainPtr<id> m_scrollbarPainterDelegate;
+
+ void initialScrollbarPaintTimerFired(Timer<ScrollAnimatorMac>*);
+ Timer<ScrollAnimatorMac> m_initialScrollbarPaintTimer;
#endif
virtual void notityPositionChanged();
@@ -131,6 +143,7 @@ private:
Timer<ScrollAnimatorMac> m_snapRubberBandTimer;
#endif
bool m_drawingIntoLayer;
+ bool m_haveScrolledSincePageLoad;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm b/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
index 67c0904..5725880 100644
--- a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
+++ b/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
@@ -141,7 +141,7 @@ static NSSize abs(NSSize size)
@end
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
@interface ScrollbarPainterControllerDelegate : NSObject
{
@@ -240,6 +240,13 @@ static NSSize abs(NSSize size)
verticalScrollbar->controlSize(),
false);
macTheme->setNewPainterForScrollbar(verticalScrollbar, newVerticalPainter);
+ wkSetPainterForPainterController(painterController, newVerticalPainter, false);
+
+ // 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
+ // and length are properly updated.
+ int thickness = macTheme->scrollbarThickness(verticalScrollbar->controlSize());
+ verticalScrollbar->setFrameRect(WebCore::IntRect(0, 0, thickness, thickness));
}
WKScrollbarPainterRef oldHorizontalPainter = wkHorizontalScrollbarPainterForController(painterController);
@@ -250,9 +257,19 @@ static NSSize abs(NSSize size)
horizontalScrollbar->controlSize(),
true);
macTheme->setNewPainterForScrollbar(horizontalScrollbar, newHorizontalPainter);
+ wkSetPainterForPainterController(painterController, newHorizontalPainter, true);
+
+ // 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
+ // and length are properly updated.
+ int thickness = macTheme->scrollbarThickness(horizontalScrollbar->controlSize());
+ horizontalScrollbar->setFrameRect(WebCore::IntRect(0, 0, thickness, thickness));
}
wkSetScrollbarPainterControllerStyle(painterController, newRecommendedScrollerStyle);
+
+ // The different scrollbar styles affect layout, so we must re-layout everything.
+ _animator->scrollableArea()->scrollbarStyleChanged();
}
@end
@@ -329,6 +346,7 @@ static NSSize abs(NSSize size)
RetainPtr<ScrollbarPartAnimation> _horizontalTrackAnimation;
}
- (id)initWithScrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator;
+- (void)cancelAnimations;
@end
@implementation ScrollbarPainterDelegate
@@ -343,6 +361,14 @@ static NSSize abs(NSSize size)
return self;
}
+- (void)cancelAnimations
+{
+ [_verticalKnobAnimation.get() stopAnimation];
+ [_horizontalKnobAnimation.get() stopAnimation];
+ [_verticalTrackAnimation.get() stopAnimation];
+ [_horizontalTrackAnimation.get() stopAnimation];
+}
+
- (NSRect)convertRectToBacking:(NSRect)aRect
{
return aRect;
@@ -367,12 +393,29 @@ static NSSize abs(NSSize size)
- (void)setUpAnimation:(RetainPtr<ScrollbarPartAnimation>&)scrollbarPartAnimation scrollerPainter:(WKScrollbarPainterRef)scrollerPainter part:(WebCore::ScrollbarPart)part animateAlphaTo:(CGFloat)newAlpha duration:(NSTimeInterval)duration
{
+ // If the user has scrolled the page, then the scrollbars must be animated here.
+ // This overrides the early returns.
+ bool mustAnimate = _animator->haveScrolledSincePageLoad();
+
+ if (_animator->scrollbarPaintTimerIsActive() && !mustAnimate)
+ return;
+
+ if (_animator->scrollableArea()->shouldSuspendScrollAnimations() && !mustAnimate) {
+ _animator->startScrollbarPaintTimer();
+ return;
+ }
+
+ // At this point, we are definitely going to animate now, so stop the timer.
+ _animator->stopScrollbarPaintTimer();
+
// If we are currently animating, stop
if (scrollbarPartAnimation) {
[scrollbarPartAnimation.get() stopAnimation];
scrollbarPartAnimation = nil;
}
-
+
+ [NSAnimationContext beginGrouping];
+ [[NSAnimationContext currentContext] setDuration:duration];
scrollbarPartAnimation.adoptNS([[ScrollbarPartAnimation alloc] initWithScrollbarPainter:scrollerPainter
part:part
scrollAnimator:_animator
@@ -380,6 +423,7 @@ static NSSize abs(NSSize size)
duration:duration]);
[scrollbarPartAnimation.get() setAnimationBlockingMode:NSAnimationNonblocking];
[scrollbarPartAnimation.get() startAnimation];
+ [NSAnimationContext endGrouping];
}
- (void)scrollerImp:(id)scrollerImp animateKnobAlphaTo:(CGFloat)newKnobAlpha duration:(NSTimeInterval)duration
@@ -388,9 +432,6 @@ static NSSize abs(NSSize size)
return;
WKScrollbarPainterRef scrollerPainter = (WKScrollbarPainterRef)scrollerImp;
- if (newKnobAlpha == wkScrollbarPainterKnobAlpha(scrollerPainter))
- return;
-
if (wkScrollbarPainterIsHorizontal(scrollerPainter))
[self setUpAnimation:_horizontalKnobAnimation scrollerPainter:scrollerPainter part:WebCore::ThumbPart animateAlphaTo:newKnobAlpha duration:duration];
else
@@ -403,9 +444,6 @@ static NSSize abs(NSSize size)
return;
WKScrollbarPainterRef scrollerPainter = (WKScrollbarPainterRef)scrollerImp;
- if (newTrackAlpha == wkScrollbarPainterTrackAlpha(scrollerPainter))
- return;
-
if (wkScrollbarPainterIsHorizontal(scrollerPainter))
[self setUpAnimation:_horizontalTrackAnimation scrollerPainter:scrollerPainter part:WebCore::BackTrackPart animateAlphaTo:newTrackAlpha duration:duration];
else
@@ -414,20 +452,8 @@ static NSSize abs(NSSize size)
- (void)scrollerImp:(id)scrollerImp overlayScrollerStateChangedTo:(NSUInteger)newOverlayScrollerState
{
- if (!_animator)
- return;
-
- WKScrollbarPainterRef scrollbarPainter = (WKScrollbarPainterRef)scrollerImp;
- wkScrollbarPainterSetOverlayState(scrollbarPainter, newOverlayScrollerState);
-
- if (wkScrollbarPainterIsHorizontal(scrollbarPainter)) {
- WebCore::Scrollbar* horizontalScrollbar = _animator->scrollableArea()->horizontalScrollbar();
- _animator->scrollableArea()->invalidateScrollbarRect(horizontalScrollbar, WebCore::IntRect(0, 0, horizontalScrollbar->width(), horizontalScrollbar->height()));
- } else {
- WebCore::Scrollbar* verticalScrollbar = _animator->scrollableArea()->verticalScrollbar();
- _animator->scrollableArea()->invalidateScrollbarRect(verticalScrollbar, WebCore::IntRect(0, 0, verticalScrollbar->width(), verticalScrollbar->height()));
-
- }
+ UNUSED_PARAM(scrollerImp);
+ UNUSED_PARAM(newOverlayScrollerState);
}
- (void)scrollAnimatorDestroyed
@@ -440,7 +466,8 @@ static NSSize abs(NSSize size)
}
@end
-#endif // #if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+
+#endif // USE(WK_SCROLLBAR_PAINTER)
namespace WebCore {
@@ -451,6 +478,9 @@ PassOwnPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea
ScrollAnimatorMac::ScrollAnimatorMac(ScrollableArea* scrollableArea)
: ScrollAnimator(scrollableArea)
+#if USE(WK_SCROLLBAR_PAINTER)
+ , m_initialScrollbarPaintTimer(this, &ScrollAnimatorMac::initialScrollbarPaintTimerFired)
+#endif
#if ENABLE(RUBBER_BANDING)
, m_inScrollGesture(false)
, m_momentumScrollInProgress(false)
@@ -460,11 +490,12 @@ ScrollAnimatorMac::ScrollAnimatorMac(ScrollableArea* scrollableArea)
, m_snapRubberBandTimer(this, &ScrollAnimatorMac::snapRubberBandTimerFired)
#endif
, m_drawingIntoLayer(false)
+ , m_haveScrolledSincePageLoad(false)
{
m_scrollAnimationHelperDelegate.adoptNS([[ScrollAnimationHelperDelegate alloc] initWithScrollAnimator:this]);
m_scrollAnimationHelper.adoptNS([[NSClassFromString(@"NSScrollAnimationHelper") alloc] initWithDelegate:m_scrollAnimationHelperDelegate.get()]);
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
m_scrollbarPainterControllerDelegate.adoptNS([[ScrollbarPainterControllerDelegate alloc] initWithScrollAnimator:this]);
m_scrollbarPainterController = wkMakeScrollbarPainterController(m_scrollbarPainterControllerDelegate.get());
m_scrollbarPainterDelegate.adoptNS([[ScrollbarPainterDelegate alloc] initWithScrollAnimator:this]);
@@ -473,7 +504,7 @@ ScrollAnimatorMac::ScrollAnimatorMac(ScrollableArea* scrollableArea)
ScrollAnimatorMac::~ScrollAnimatorMac()
{
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
[m_scrollbarPainterControllerDelegate.get() scrollAnimatorDestroyed];
[(id)m_scrollbarPainterController.get() setDelegate:nil];
[m_scrollbarPainterDelegate.get() scrollAnimatorDestroyed];
@@ -483,6 +514,8 @@ ScrollAnimatorMac::~ScrollAnimatorMac()
bool ScrollAnimatorMac::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier)
{
+ m_haveScrolledSincePageLoad = true;
+
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"AppleScrollAnimationEnabled"])
return ScrollAnimator::scroll(orientation, granularity, step, multiplier);
@@ -561,7 +594,7 @@ void ScrollAnimatorMac::immediateScrollByDeltaY(float deltaY)
void ScrollAnimatorMac::notityPositionChanged()
{
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
wkContentAreaScrolled(m_scrollbarPainterController.get());
#endif
ScrollAnimator::notityPositionChanged();
@@ -569,70 +602,70 @@ void ScrollAnimatorMac::notityPositionChanged()
void ScrollAnimatorMac::contentAreaWillPaint() const
{
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
wkContentAreaWillPaint(m_scrollbarPainterController.get());
#endif
}
void ScrollAnimatorMac::mouseEnteredContentArea() const
{
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
wkMouseEnteredContentArea(m_scrollbarPainterController.get());
#endif
}
void ScrollAnimatorMac::mouseExitedContentArea() const
{
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
wkMouseExitedContentArea(m_scrollbarPainterController.get());
#endif
}
void ScrollAnimatorMac::mouseMovedInContentArea() const
{
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
wkMouseMovedInContentArea(m_scrollbarPainterController.get());
#endif
}
void ScrollAnimatorMac::willStartLiveResize()
{
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
wkWillStartLiveResize(m_scrollbarPainterController.get());
#endif
}
void ScrollAnimatorMac::contentsResized() const
{
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
wkContentAreaResized(m_scrollbarPainterController.get());
#endif
}
void ScrollAnimatorMac::willEndLiveResize()
{
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
wkWillEndLiveResize(m_scrollbarPainterController.get());
#endif
}
void ScrollAnimatorMac::contentAreaDidShow() const
{
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
wkContentAreaDidShow(m_scrollbarPainterController.get());
#endif
}
void ScrollAnimatorMac::contentAreaDidHide() const
{
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
wkContentAreaDidHide(m_scrollbarPainterController.get());
#endif
}
void ScrollAnimatorMac::didAddVerticalScrollbar(Scrollbar* scrollbar)
{
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
WKScrollbarPainterRef painter = static_cast<WebCore::ScrollbarThemeMac*>(WebCore::ScrollbarTheme::nativeTheme())->painterForScrollbar(scrollbar);
wkScrollbarPainterSetDelegate(painter, m_scrollbarPainterDelegate.get());
wkSetPainterForPainterController(m_scrollbarPainterController.get(), painter, false);
@@ -645,7 +678,7 @@ void ScrollAnimatorMac::didAddVerticalScrollbar(Scrollbar* scrollbar)
void ScrollAnimatorMac::willRemoveVerticalScrollbar(Scrollbar* scrollbar)
{
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
WKScrollbarPainterRef painter = static_cast<WebCore::ScrollbarThemeMac*>(WebCore::ScrollbarTheme::nativeTheme())->painterForScrollbar(scrollbar);
wkScrollbarPainterSetDelegate(painter, nil);
wkSetPainterForPainterController(m_scrollbarPainterController.get(), nil, false);
@@ -656,7 +689,7 @@ void ScrollAnimatorMac::willRemoveVerticalScrollbar(Scrollbar* scrollbar)
void ScrollAnimatorMac::didAddHorizontalScrollbar(Scrollbar* scrollbar)
{
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
WKScrollbarPainterRef painter = static_cast<WebCore::ScrollbarThemeMac*>(WebCore::ScrollbarTheme::nativeTheme())->painterForScrollbar(scrollbar);
wkScrollbarPainterSetDelegate(painter, m_scrollbarPainterDelegate.get());
wkSetPainterForPainterController(m_scrollbarPainterController.get(), painter, true);
@@ -669,7 +702,7 @@ void ScrollAnimatorMac::didAddHorizontalScrollbar(Scrollbar* scrollbar)
void ScrollAnimatorMac::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
{
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
WKScrollbarPainterRef painter = static_cast<WebCore::ScrollbarThemeMac*>(WebCore::ScrollbarTheme::nativeTheme())->painterForScrollbar(scrollbar);
wkScrollbarPainterSetDelegate(painter, nil);
wkSetPainterForPainterController(m_scrollbarPainterController.get(), nil, true);
@@ -678,6 +711,17 @@ void ScrollAnimatorMac::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
#endif
}
+void ScrollAnimatorMac::cancelAnimations()
+{
+ m_haveScrolledSincePageLoad = false;
+
+#if USE(WK_SCROLLBAR_PAINTER)
+ if (scrollbarPaintTimerIsActive())
+ stopScrollbarPaintTimer();
+ [m_scrollbarPainterDelegate.get() cancelAnimations];
+#endif
+}
+
#if ENABLE(RUBBER_BANDING)
static const float scrollVelocityZeroingTimeout = 0.10f;
@@ -720,6 +764,8 @@ static float scrollWheelMultiplier()
void ScrollAnimatorMac::handleWheelEvent(PlatformWheelEvent& wheelEvent)
{
+ m_haveScrolledSincePageLoad = true;
+
if (!wheelEvent.hasPreciseScrollingDeltas()) {
ScrollAnimator::handleWheelEvent(wheelEvent);
return;
@@ -751,18 +797,18 @@ bool ScrollAnimatorMac::pinnedInDirection(float deltaX, float deltaY)
if (fabsf(deltaY) >= fabsf(deltaX)) {
if (deltaY < 0) {
// We are trying to scroll up. Make sure we are not pinned to the top
- limitDelta.setHeight(m_scrollableArea->visibleContentRect().y());
+ limitDelta.setHeight(m_scrollableArea->visibleContentRect().y() + + m_scrollableArea->scrollOrigin().y());
} else {
// We are trying to scroll down. Make sure we are not pinned to the bottom
- limitDelta.setHeight(m_scrollableArea->contentsSize().height() - m_scrollableArea->visibleContentRect().maxY());
+ limitDelta.setHeight(m_scrollableArea->contentsSize().height() - (m_scrollableArea->visibleContentRect().maxY() + m_scrollableArea->scrollOrigin().y()));
}
} else if (deltaX != 0) {
if (deltaX < 0) {
// We are trying to scroll left. Make sure we are not pinned to the left
- limitDelta.setWidth(m_scrollableArea->visibleContentRect().x());
+ limitDelta.setWidth(m_scrollableArea->visibleContentRect().x() + m_scrollableArea->scrollOrigin().x());
} else {
// We are trying to scroll right. Make sure we are not pinned to the right
- limitDelta.setWidth(m_scrollableArea->contentsSize().width() - m_scrollableArea->visibleContentRect().maxX());
+ limitDelta.setWidth(m_scrollableArea->contentsSize().width() - (m_scrollableArea->visibleContentRect().maxX() + m_scrollableArea->scrollOrigin().x()));
}
}
@@ -793,6 +839,8 @@ bool ScrollAnimatorMac::allowsHorizontalStretching() const
void ScrollAnimatorMac::smoothScrollWithEvent(PlatformWheelEvent& wheelEvent)
{
+ m_haveScrolledSincePageLoad = true;
+
float deltaX = m_overflowScrollDelta.width();
float deltaY = m_overflowScrollDelta.height();
@@ -925,7 +973,7 @@ void ScrollAnimatorMac::smoothScrollWithEvent(PlatformWheelEvent& wheelEvent)
m_stretchScrollForce.setHeight(m_stretchScrollForce.height() + deltaY);
FloatSize dampedDelta(ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.width())), ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.height())));
- FloatPoint origOrigin = m_scrollableArea->visibleContentRect().location() - stretchAmount;
+ FloatPoint origOrigin = (m_scrollableArea->visibleContentRect().location() + m_scrollableArea->scrollOrigin()) - stretchAmount;
FloatPoint newOrigin = origOrigin + dampedDelta;
if (origOrigin != newOrigin) {
@@ -945,6 +993,7 @@ void ScrollAnimatorMac::smoothScrollWithEvent(PlatformWheelEvent& wheelEvent)
void ScrollAnimatorMac::beginScrollGesture()
{
+ m_haveScrolledSincePageLoad = true;
m_inScrollGesture = true;
m_momentumScrollInProgress = false;
m_ignoreMomentumScrolls = false;
@@ -1017,7 +1066,7 @@ void ScrollAnimatorMac::snapRubberBandTimerFired(Timer<ScrollAnimatorMac>*)
return;
}
- m_origOrigin = m_scrollableArea->visibleContentRect().location() - m_startStretch;
+ m_origOrigin = (m_scrollableArea->visibleContentRect().location() + m_scrollableArea->scrollOrigin()) - m_startStretch;
m_origVelocity = m_momentumVelocity;
// Just like normal scrolling, prefer vertical rubberbanding
@@ -1069,6 +1118,28 @@ void ScrollAnimatorMac::snapRubberBandTimerFired(Timer<ScrollAnimatorMac>*)
}
#endif
+#if USE(WK_SCROLLBAR_PAINTER)
+void ScrollAnimatorMac::startScrollbarPaintTimer()
+{
+ m_initialScrollbarPaintTimer.startOneShot(0.1);
+}
+
+bool ScrollAnimatorMac::scrollbarPaintTimerIsActive() const
+{
+ return m_initialScrollbarPaintTimer.isActive();
+}
+
+void ScrollAnimatorMac::stopScrollbarPaintTimer()
+{
+ m_initialScrollbarPaintTimer.stop();
+}
+
+void ScrollAnimatorMac::initialScrollbarPaintTimerFired(Timer<ScrollAnimatorMac>*)
+{
+ wkScrollbarPainterForceFlashScrollers(m_scrollbarPainterController.get());
+}
+#endif
+
} // namespace WebCore
#endif // ENABLE(SMOOTH_SCROLLING)
diff --git a/Source/WebCore/platform/mac/ScrollbarThemeMac.h b/Source/WebCore/platform/mac/ScrollbarThemeMac.h
index 844a088..bd56808 100644
--- a/Source/WebCore/platform/mac/ScrollbarThemeMac.h
+++ b/Source/WebCore/platform/mac/ScrollbarThemeMac.h
@@ -26,7 +26,6 @@
#ifndef ScrollbarThemeMac_h
#define ScrollbarThemeMac_h
-#include "HeaderDetection.h"
#include "ScrollbarThemeComposite.h"
#include "WebCoreSystemInterface.h"
@@ -52,7 +51,7 @@ public:
virtual void registerScrollbar(Scrollbar*);
virtual void unregisterScrollbar(Scrollbar*);
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
void setNewPainterForScrollbar(Scrollbar*, WKScrollbarPainterRef);
WKScrollbarPainterRef painterForScrollbar(Scrollbar*);
#endif
diff --git a/Source/WebCore/platform/mac/ScrollbarThemeMac.mm b/Source/WebCore/platform/mac/ScrollbarThemeMac.mm
index 5a3796d..5504f5c 100644
--- a/Source/WebCore/platform/mac/ScrollbarThemeMac.mm
+++ b/Source/WebCore/platform/mac/ScrollbarThemeMac.mm
@@ -169,7 +169,7 @@ void ScrollbarThemeMac::unregisterScrollbar(Scrollbar* scrollbar)
scrollbarMap()->remove(scrollbar);
}
-#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+#if USE(WK_SCROLLBAR_PAINTER)
void ScrollbarThemeMac::setNewPainterForScrollbar(Scrollbar* scrollbar, WKScrollbarPainterRef newPainter)
{
scrollbarMap()->set(scrollbar, newPainter);
@@ -440,7 +440,11 @@ bool ScrollbarThemeMac::paint(Scrollbar* scrollbar, GraphicsContext* context, co
overhang = scrollbar->currentPos() + scrollbar->visibleSize() - scrollbar->totalSize();
} else {
// Within the bounds of the scrollable area.
- value = scrollbar->currentPos() / scrollbar->maximum();
+ int maximum = scrollbar->maximum();
+ if (maximum > 0)
+ value = scrollbar->currentPos() / maximum;
+ else
+ value = 0;
}
ScrollAnimatorMac* scrollAnimator = static_cast<ScrollAnimatorMac*>(scrollbar->scrollableArea()->scrollAnimator());
diff --git a/Source/WebCore/platform/mac/ThemeMac.mm b/Source/WebCore/platform/mac/ThemeMac.mm
index e510ea7..918bc07 100644
--- a/Source/WebCore/platform/mac/ThemeMac.mm
+++ b/Source/WebCore/platform/mac/ThemeMac.mm
@@ -52,6 +52,11 @@ using namespace std;
return nil;
}
+- (BOOL)_automaticFocusRingDisabled
+{
+ return YES;
+}
+
- (NSRect)_focusRingVisibleRect
{
return [self visibleRect];
diff --git a/Source/WebCore/platform/mac/WebCoreObjCExtras.mm b/Source/WebCore/platform/mac/WebCoreObjCExtras.mm
index 05d3e01..5a2d564 100644
--- a/Source/WebCore/platform/mac/WebCoreObjCExtras.mm
+++ b/Source/WebCore/platform/mac/WebCoreObjCExtras.mm
@@ -26,6 +26,11 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+// This file intentionally calls objc_finalizeOnMainThread, which is deprecated.
+// According to http://gcc.gnu.org/onlinedocs/gcc-4.2.1/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas
+// we need to place this directive before any data or functions are defined.
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
#include "config.h"
#include "WebCoreObjCExtras.h"
diff --git a/Source/WebCore/platform/mac/WebCoreSystemInterface.h b/Source/WebCore/platform/mac/WebCoreSystemInterface.h
index df65ff2..308a551 100644
--- a/Source/WebCore/platform/mac/WebCoreSystemInterface.h
+++ b/Source/WebCore/platform/mac/WebCoreSystemInterface.h
@@ -86,6 +86,8 @@ class QTMovie;
class QTMovieView;
#endif
+typedef struct _CFURLResponse *CFURLResponseRef;
+
extern "C" {
// In alphabetical order.
@@ -115,6 +117,7 @@ extern BOOL (*wkGetGlyphTransformedAdvances)(CGFontRef, NSFont*, CGAffineTransfo
extern void (*wkDrawMediaSliderTrack)(int themeStyle, CGContextRef context, CGRect rect, float timeLoaded, float currentTime,
float duration, unsigned state);
extern void (*wkDrawMediaUIPart)(int part, int themeStyle, CGContextRef context, CGRect rect, unsigned state);
+extern CFStringRef (*wkSignedPublicKeyAndChallengeString)(unsigned keySize, CFStringRef challenge, CFStringRef keyDescription);
extern NSString* (*wkGetPreferredExtensionForMIMEType)(NSString*);
extern NSArray* (*wkGetExtensionsForMIMEType)(NSString*);
extern NSString* (*wkGetMIMETypeForExtension)(NSString*);
@@ -194,10 +197,13 @@ extern CGContextRef (*wkIOSurfaceContextCreate)(IOSurfaceRef surface, unsigned w
extern CGImageRef (*wkIOSurfaceContextCreateImage)(CGContextRef context);
typedef struct __WKScrollbarPainter *WKScrollbarPainterRef;
+typedef struct __WKScrollbarPainterController *WKScrollbarPainterControllerRef;
+
extern WKScrollbarPainterRef (*wkMakeScrollbarPainter)(int controlSize, bool isHorizontal);
extern WKScrollbarPainterRef (*wkMakeScrollbarReplacementPainter)(WKScrollbarPainterRef oldPainter, int newStyle, int controlSize, bool isHorizontal);
extern void (*wkScrollbarPainterSetDelegate)(WKScrollbarPainterRef, id scrollbarPainterDelegate);
extern void (*wkScrollbarPainterPaint)(WKScrollbarPainterRef, bool enabled, double value, CGFloat proportion, CGRect frameRect);
+extern void (*wkScrollbarPainterForceFlashScrollers)(WKScrollbarPainterControllerRef);
extern int (*wkScrollbarThickness)(int controlSize);
extern int (*wkScrollbarMinimumThumbLength)(WKScrollbarPainterRef);
extern int (*wkScrollbarMinimumTotalLengthNeededForThumb)(WKScrollbarPainterRef);
@@ -208,7 +214,6 @@ extern void (*wkSetScrollbarPainterTrackAlpha)(WKScrollbarPainterRef, CGFloat);
extern bool (*wkScrollbarPainterIsHorizontal)(WKScrollbarPainterRef);
extern void (*wkScrollbarPainterSetOverlayState)(WKScrollbarPainterRef, int overlayScrollerState);
-typedef struct __WKScrollbarPainterController *WKScrollbarPainterControllerRef;
extern WKScrollbarPainterControllerRef (*wkMakeScrollbarPainterController)(id painterControllerDelegate);
extern void (*wkSetPainterForPainterController)(WKScrollbarPainterControllerRef, WKScrollbarPainterRef, bool isHorizontal);
extern WKScrollbarPainterRef (*wkVerticalScrollbarPainterForController)(WKScrollbarPainterControllerRef);
@@ -244,12 +249,18 @@ extern CFURLStorageSessionRef (*wkCreatePrivateStorageSession)(CFStringRef);
extern NSURLRequest* (*wkCopyRequestWithStorageSession)(CFURLStorageSessionRef, NSURLRequest*);
typedef struct OpaqueCFHTTPCookieStorage* CFHTTPCookieStorageRef;
-extern CFHTTPCookieStorageRef (*wkCreatePrivateInMemoryHTTPCookieStorage)(CFURLStorageSessionRef);
+extern CFHTTPCookieStorageRef (*wkCopyHTTPCookieStorage)(CFURLStorageSessionRef);
extern unsigned (*wkGetHTTPCookieAcceptPolicy)(CFHTTPCookieStorageRef);
extern NSArray *(*wkHTTPCookiesForURL)(CFHTTPCookieStorageRef, NSURL *);
extern void (*wkSetHTTPCookiesForURL)(CFHTTPCookieStorageRef, NSArray *, NSURL *, NSURL *);
extern void (*wkDeleteHTTPCookie)(CFHTTPCookieStorageRef, NSHTTPCookie *);
+extern CFStringRef (*wkGetCFURLResponseMIMEType)(CFURLResponseRef);
+extern CFURLRef (*wkGetCFURLResponseURL)(CFURLResponseRef);
+extern CFHTTPMessageRef (*wkGetCFURLResponseHTTPResponse)(CFURLResponseRef);
+extern CFStringRef (*wkCopyCFURLResponseSuggestedFilename)(CFURLResponseRef);
+extern void (*wkSetCFURLResponseMIMEType)(CFURLResponseRef, CFStringRef mimeType);
+
}
#endif
diff --git a/Source/WebCore/platform/mac/WebCoreSystemInterface.mm b/Source/WebCore/platform/mac/WebCoreSystemInterface.mm
index 50ac236..ab059bd 100644
--- a/Source/WebCore/platform/mac/WebCoreSystemInterface.mm
+++ b/Source/WebCore/platform/mac/WebCoreSystemInterface.mm
@@ -48,6 +48,7 @@ void (*wkDrawMediaUIPart)(int part, int themeStyle, CGContextRef context, CGRect
void (*wkMeasureMediaUIPart)(int part, int themeStyle, CGRect *bounds, CGSize *naturalSize);
BOOL (*wkMediaControllerThemeAvailable)(int themeStyle);
NSString* (*wkGetPreferredExtensionForMIMEType)(NSString*);
+CFStringRef (*wkSignedPublicKeyAndChallengeString)(unsigned keySize, CFStringRef challenge, CFStringRef keyDescription);
NSArray* (*wkGetExtensionsForMIMEType)(NSString*);
NSString* (*wkGetMIMETypeForExtension)(NSString*);
NSTimeInterval (*wkGetNSURLResponseCalculatedExpiration)(NSURLResponse *response);
@@ -132,6 +133,7 @@ WKScrollbarPainterRef (*wkMakeScrollbarPainter)(int controlSize, bool isHorizont
WKScrollbarPainterRef (*wkMakeScrollbarReplacementPainter)(WKScrollbarPainterRef oldPainter, int newStyle, int controlSize, bool isHorizontal);
void (*wkScrollbarPainterSetDelegate)(WKScrollbarPainterRef, id scrollbarPainterDelegate);
void (*wkScrollbarPainterPaint)(WKScrollbarPainterRef, bool enabled, double value, CGFloat proportion, CGRect frameRect);
+void (*wkScrollbarPainterForceFlashScrollers)(WKScrollbarPainterControllerRef);
int (*wkScrollbarThickness)(int controlSize);
int (*wkScrollbarMinimumThumbLength)(WKScrollbarPainterRef);
int (*wkScrollbarMinimumTotalLengthNeededForThumb)(WKScrollbarPainterRef);
@@ -174,8 +176,14 @@ AXUIElementRef (*wkCreateAXUIElementRef)(id element);
CFURLStorageSessionRef (*wkCreatePrivateStorageSession)(CFStringRef);
NSURLRequest* (*wkCopyRequestWithStorageSession)(CFURLStorageSessionRef, NSURLRequest*);
-CFHTTPCookieStorageRef (*wkCreatePrivateInMemoryHTTPCookieStorage)(CFURLStorageSessionRef);
+CFHTTPCookieStorageRef (*wkCopyHTTPCookieStorage)(CFURLStorageSessionRef);
unsigned (*wkGetHTTPCookieAcceptPolicy)(CFHTTPCookieStorageRef);
NSArray *(*wkHTTPCookiesForURL)(CFHTTPCookieStorageRef, NSURL *);
void (*wkSetHTTPCookiesForURL)(CFHTTPCookieStorageRef, NSArray *, NSURL *, NSURL *);
void (*wkDeleteHTTPCookie)(CFHTTPCookieStorageRef, NSHTTPCookie *);
+
+CFStringRef (*wkGetCFURLResponseMIMEType)(CFURLResponseRef);
+CFURLRef (*wkGetCFURLResponseURL)(CFURLResponseRef);
+CFHTTPMessageRef (*wkGetCFURLResponseHTTPResponse)(CFURLResponseRef);
+CFStringRef (*wkCopyCFURLResponseSuggestedFilename)(CFURLResponseRef);
+void (*wkSetCFURLResponseMIMEType)(CFURLResponseRef, CFStringRef mimeType);
diff --git a/Source/WebCore/platform/mac/WidgetMac.mm b/Source/WebCore/platform/mac/WidgetMac.mm
index 96bcde2..f75faaa 100644
--- a/Source/WebCore/platform/mac/WidgetMac.mm
+++ b/Source/WebCore/platform/mac/WidgetMac.mm
@@ -115,10 +115,15 @@ void Widget::setFocus(bool focused)
BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ // If there's no platformWidget, WK2 is running. The focus() method needs to be used
+ // to bring focus to the right view on the UIProcess side.
NSView *view = [platformWidget() _webcore_effectiveFirstResponder];
- if (Page* page = frame->page())
- page->chrome()->focusNSView(view);
-
+ if (Page* page = frame->page()) {
+ if (!platformWidget())
+ page->chrome()->focus();
+ else
+ page->chrome()->focusNSView(view);
+ }
END_BLOCK_OBJC_EXCEPTIONS;
}
diff --git a/Source/WebCore/platform/mock/GeolocationClientMock.cpp b/Source/WebCore/platform/mock/GeolocationClientMock.cpp
index 5255b34..d067c8a 100644
--- a/Source/WebCore/platform/mock/GeolocationClientMock.cpp
+++ b/Source/WebCore/platform/mock/GeolocationClientMock.cpp
@@ -79,6 +79,11 @@ void GeolocationClientMock::setPermission(bool allowed)
asyncUpdatePermission();
}
+int GeolocationClientMock::numberOfPendingPermissionRequests() const
+{
+ return m_pendingPermission.size();
+}
+
void GeolocationClientMock::requestPermission(Geolocation* geolocation)
{
m_pendingPermission.add(geolocation);
diff --git a/Source/WebCore/platform/mock/GeolocationClientMock.h b/Source/WebCore/platform/mock/GeolocationClientMock.h
index df35316..b400166 100644
--- a/Source/WebCore/platform/mock/GeolocationClientMock.h
+++ b/Source/WebCore/platform/mock/GeolocationClientMock.h
@@ -59,6 +59,7 @@ public:
void setError(PassRefPtr<GeolocationError>);
void setPosition(PassRefPtr<GeolocationPosition>);
void setPermission(bool allowed);
+ int numberOfPendingPermissionRequests() const;
// GeolocationClient
virtual void geolocationDestroyed();
diff --git a/Source/WebCore/platform/network/BlobData.h b/Source/WebCore/platform/network/BlobData.h
index c1f5522..f919d64 100644
--- a/Source/WebCore/platform/network/BlobData.h
+++ b/Source/WebCore/platform/network/BlobData.h
@@ -34,11 +34,11 @@
#include "KURL.h"
#include "PlatformString.h"
#include <wtf/Forward.h>
-#include <wtf/ThreadSafeShared.h>
+#include <wtf/ThreadSafeRefCounted.h>
namespace WebCore {
-class RawData : public ThreadSafeShared<RawData> {
+class RawData : public ThreadSafeRefCounted<RawData> {
public:
static PassRefPtr<RawData> create()
{
diff --git a/Source/WebCore/platform/network/FormDataBuilder.cpp b/Source/WebCore/platform/network/FormDataBuilder.cpp
index e973f99..3174614 100644
--- a/Source/WebCore/platform/network/FormDataBuilder.cpp
+++ b/Source/WebCore/platform/network/FormDataBuilder.cpp
@@ -32,6 +32,7 @@
#include <limits>
#include <wtf/Assertions.h>
+#include <wtf/HexNumber.h>
#include <wtf/text/CString.h>
#include <wtf/RandomNumber.h>
@@ -192,8 +193,6 @@ void FormDataBuilder::addKeyValuePairAsFormData(Vector<char>& buffer, const CStr
void FormDataBuilder::encodeStringAsFormData(Vector<char>& buffer, const CString& string)
{
- static const char hexDigits[17] = "0123456789ABCDEF";
-
// Same safe characters as Netscape for compatibility.
static const char safeCharacters[] = "-._*";
@@ -210,8 +209,7 @@ void FormDataBuilder::encodeStringAsFormData(Vector<char>& buffer, const CString
append(buffer, "%0D%0A");
else if (c != '\r') {
append(buffer, '%');
- append(buffer, hexDigits[c >> 4]);
- append(buffer, hexDigits[c & 0xF]);
+ appendByteAsHex(c, buffer);
}
}
}
diff --git a/Source/WebCore/platform/network/ProtectionSpace.h b/Source/WebCore/platform/network/ProtectionSpace.h
index deb59d2..87758e1 100644
--- a/Source/WebCore/platform/network/ProtectionSpace.h
+++ b/Source/WebCore/platform/network/ProtectionSpace.h
@@ -49,7 +49,7 @@ enum ProtectionSpaceAuthenticationScheme {
ProtectionSpaceAuthenticationSchemeNegotiate = 6,
ProtectionSpaceAuthenticationSchemeClientCertificateRequested = 7,
ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested = 8,
- ProtectionSpaceAuthenticationSchemeUnknown = 100,
+ ProtectionSpaceAuthenticationSchemeUnknown = 100
};
class ProtectionSpace {
diff --git a/Source/WebCore/platform/network/ProtectionSpaceHash.h b/Source/WebCore/platform/network/ProtectionSpaceHash.h
index 9934321..40eb9b6 100644
--- a/Source/WebCore/platform/network/ProtectionSpaceHash.h
+++ b/Source/WebCore/platform/network/ProtectionSpaceHash.h
@@ -46,7 +46,7 @@ struct ProtectionSpaceHash {
// Ignore realm for proxies.
if (protectionSpace.isProxy())
codeCount -= sizeof(hashCodes[0]);
- return WTF::StringHasher::createBlobHash(hashCodes, codeCount);
+ return StringHasher::hashMemory(hashCodes, codeCount);
}
static bool equal(const ProtectionSpace& a, const ProtectionSpace& b) { return a == b; }
diff --git a/Source/WebCore/platform/network/ResourceErrorBase.cpp b/Source/WebCore/platform/network/ResourceErrorBase.cpp
index 42bc0de..e1d29e0 100644
--- a/Source/WebCore/platform/network/ResourceErrorBase.cpp
+++ b/Source/WebCore/platform/network/ResourceErrorBase.cpp
@@ -42,6 +42,7 @@ ResourceError ResourceErrorBase::copy() const
errorCopy.m_localizedDescription = m_localizedDescription.crossThreadString();
errorCopy.m_isNull = m_isNull;
errorCopy.m_isCancellation = m_isCancellation;
+ platformCopy(errorCopy);
return errorCopy;
}
diff --git a/Source/WebCore/platform/network/ResourceErrorBase.h b/Source/WebCore/platform/network/ResourceErrorBase.h
index a6b7c69..2d7be70 100644
--- a/Source/WebCore/platform/network/ResourceErrorBase.h
+++ b/Source/WebCore/platform/network/ResourceErrorBase.h
@@ -74,6 +74,9 @@ protected:
// The ResourceError subclass may "shadow" this method to lazily initialize platform specific fields
void platformLazyInit() {}
+ // The ResourceError subclass may "shadow" this method to copy platform specific fields
+ void platformCopy(ResourceError&) const {}
+
// The ResourceError subclass may "shadow" this method to compare platform specific fields
static bool platformCompare(const ResourceError&, const ResourceError&) { return true; }
diff --git a/Source/WebCore/platform/network/ResourceHandleClient.h b/Source/WebCore/platform/network/ResourceHandleClient.h
index d9350ee..e92b376 100644
--- a/Source/WebCore/platform/network/ResourceHandleClient.h
+++ b/Source/WebCore/platform/network/ResourceHandleClient.h
@@ -59,7 +59,7 @@ namespace WebCore {
enum CacheStoragePolicy {
StorageAllowed,
StorageAllowedInMemoryOnly,
- StorageNotAllowed,
+ StorageNotAllowed
};
class ResourceHandleClient {
@@ -78,6 +78,11 @@ namespace WebCore {
virtual void wasBlocked(ResourceHandle*) { }
virtual void cannotShowURL(ResourceHandle*) { }
+#if HAVE(CFNETWORK_DATA_ARRAY_CALLBACK)
+ virtual bool supportsDataArray() { return false; }
+ virtual void didReceiveDataArray(ResourceHandle*, CFArrayRef) { }
+#endif
+
virtual void willCacheResponse(ResourceHandle*, CacheStoragePolicy&) { }
virtual bool shouldUseCredentialStorage(ResourceHandle*) { return false; }
diff --git a/Source/WebCore/platform/network/ResourceRequestBase.h b/Source/WebCore/platform/network/ResourceRequestBase.h
index ec7e32a..31a1e69 100644
--- a/Source/WebCore/platform/network/ResourceRequestBase.h
+++ b/Source/WebCore/platform/network/ResourceRequestBase.h
@@ -41,7 +41,7 @@ namespace WebCore {
UseProtocolCachePolicy, // normal load
ReloadIgnoringCacheData, // reload
ReturnCacheDataElseLoad, // back/forward or encoding change - allow stale data
- ReturnCacheDataDontLoad, // results of a post - allow stale data and only use cache
+ ReturnCacheDataDontLoad // results of a post - allow stale data and only use cache
};
class ResourceRequest;
diff --git a/Source/WebCore/platform/network/cf/CookieStorageCFNet.cpp b/Source/WebCore/platform/network/cf/CookieStorageCFNet.cpp
index c2a5691..2eac3f6 100644
--- a/Source/WebCore/platform/network/cf/CookieStorageCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/CookieStorageCFNet.cpp
@@ -42,7 +42,7 @@
namespace WebCore {
-static RetainPtr<CFHTTPCookieStorageRef>& privateBrowsingCookieStorage()
+static RetainPtr<CFHTTPCookieStorageRef>& privateCookieStorage()
{
DEFINE_STATIC_LOCAL(RetainPtr<CFHTTPCookieStorageRef>, cookieStorage, ());
return cookieStorage;
@@ -52,16 +52,21 @@ CFHTTPCookieStorageRef currentCookieStorage()
{
ASSERT(isMainThread());
- if (CFHTTPCookieStorageRef privateCookieStorage = privateBrowsingCookieStorage().get())
- return privateCookieStorage;
+ if (CFHTTPCookieStorageRef cookieStorage = privateCookieStorage().get())
+ return cookieStorage;
return wkGetDefaultHTTPCookieStorage();
}
+CFHTTPCookieStorageRef privateBrowsingCookieStorage()
+{
+ return privateCookieStorage().get();
+}
+
void setCurrentCookieStorage(CFHTTPCookieStorageRef cookieStorage)
{
ASSERT(isMainThread());
- privateBrowsingCookieStorage().adoptCF(cookieStorage);
+ privateCookieStorage().adoptCF(cookieStorage);
}
void setCookieStoragePrivateBrowsingEnabled(bool enabled)
@@ -69,15 +74,21 @@ void setCookieStoragePrivateBrowsingEnabled(bool enabled)
ASSERT(isMainThread());
if (!enabled) {
- privateBrowsingCookieStorage() = nullptr;
+ privateCookieStorage() = nullptr;
return;
}
#if USE(CFURLSTORAGESESSIONS)
- privateBrowsingCookieStorage().adoptCF(wkCreatePrivateInMemoryHTTPCookieStorage(ResourceHandle::privateBrowsingStorageSession()));
-#else
- privateBrowsingCookieStorage().adoptCF(wkCreatePrivateInMemoryHTTPCookieStorage(0));
+ if (CFURLStorageSessionRef privateStorageSession = ResourceHandle::privateBrowsingStorageSession())
+ privateCookieStorage().adoptCF(wkCopyHTTPCookieStorage(privateStorageSession));
+ else
#endif
+ privateCookieStorage().adoptCF(wkCreateInMemoryHTTPCookieStorage());
+}
+
+CFHTTPCookieStorageRef defaultCookieStorage()
+{
+ return wkGetDefaultHTTPCookieStorage();
}
static void notifyCookiesChangedOnMainThread(void* context)
diff --git a/Source/WebCore/platform/network/cf/CookieStorageCFNet.h b/Source/WebCore/platform/network/cf/CookieStorageCFNet.h
index 0167587..d33c76e 100644
--- a/Source/WebCore/platform/network/cf/CookieStorageCFNet.h
+++ b/Source/WebCore/platform/network/cf/CookieStorageCFNet.h
@@ -33,6 +33,8 @@ typedef struct OpaqueCFHTTPCookieStorage* CFHTTPCookieStorageRef;
namespace WebCore {
CFHTTPCookieStorageRef currentCookieStorage();
+ CFHTTPCookieStorageRef defaultCookieStorage();
+ CFHTTPCookieStorageRef privateBrowsingCookieStorage();
// Needed for WebKit1 API only.
void setCurrentCookieStorage(CFHTTPCookieStorageRef cookieStorage);
diff --git a/Source/WebCore/platform/network/cf/LoaderRunLoopCF.h b/Source/WebCore/platform/network/cf/LoaderRunLoopCF.h
index e0d3ba4..272acf9 100644
--- a/Source/WebCore/platform/network/cf/LoaderRunLoopCF.h
+++ b/Source/WebCore/platform/network/cf/LoaderRunLoopCF.h
@@ -29,7 +29,7 @@
#if USE(CFNETWORK)
#if !PLATFORM(WIN)
-#error This code is not needed on platforms other than Windows, because main thread's CFRunLoop can be used.
+#error This code is not needed on platforms other than Windows, because the CFRunLoop from the main thread can be used.
#endif
typedef struct __CFRunLoop* CFRunLoopRef;
diff --git a/Source/WebCore/platform/network/cf/ResourceError.h b/Source/WebCore/platform/network/cf/ResourceError.h
index aae9a4a..d36903f 100644
--- a/Source/WebCore/platform/network/cf/ResourceError.h
+++ b/Source/WebCore/platform/network/cf/ResourceError.h
@@ -32,6 +32,7 @@
#if USE(CFNETWORK)
#include <CoreFoundation/CFStream.h>
#else
+
#ifdef __OBJC__
@class NSError;
#else
@@ -54,38 +55,38 @@ public:
{
}
-#if USE(CFNETWORK)
- ResourceError(CFStreamError error);
-
- ResourceError(CFErrorRef error)
- : m_dataIsUpToDate(false)
- , m_platformError(error)
- {
- m_isNull = !error;
- }
+ ResourceError(CFErrorRef error);
+ CFErrorRef cfError() const;
operator CFErrorRef() const;
+
+#if USE(CFNETWORK)
+#if PLATFORM(WIN)
+ ResourceError(const String& domain, int errorCode, const String& failingURL, const String& localizedDescription, CFDataRef certificate);
+ PCCERT_CONTEXT certificate() const;
+#endif
+ ResourceError(CFStreamError error);
+ CFStreamError cfStreamError() const;
operator CFStreamError() const;
#else
- ResourceError(NSError* error)
- : m_dataIsUpToDate(false)
- , m_platformError(error)
- {
- m_isNull = !error;
- }
-
- operator NSError*() const;
+ ResourceError(NSError *);
+ NSError *nsError() const;
+ operator NSError *() const;
#endif
private:
friend class ResourceErrorBase;
void platformLazyInit();
+ void platformCopy(ResourceError&) const;
static bool platformCompare(const ResourceError& a, const ResourceError& b);
bool m_dataIsUpToDate;
#if USE(CFNETWORK)
mutable RetainPtr<CFErrorRef> m_platformError;
+#if PLATFORM(WIN)
+ RetainPtr<CFDataRef> m_certificate;
+#endif
#else
mutable RetainPtr<NSError> m_platformError;
#endif
diff --git a/Source/WebCore/platform/network/cf/ResourceErrorCF.cpp b/Source/WebCore/platform/network/cf/ResourceErrorCF.cpp
index 1eba97e..556ad6e 100644
--- a/Source/WebCore/platform/network/cf/ResourceErrorCF.cpp
+++ b/Source/WebCore/platform/network/cf/ResourceErrorCF.cpp
@@ -24,44 +24,46 @@
*/
#include "config.h"
-#include "KURL.h"
#include "ResourceError.h"
#if USE(CFNETWORK)
-// FIXME: Once <rdar://problem/5050881> is fixed in open source we
-// can remove this extern "C"
-extern "C" {
-#include <CFNetwork/CFNetworkErrors.h>
-}
-
+#include "KURL.h"
#include <CoreFoundation/CFError.h>
+#include <CFNetwork/CFNetworkErrors.h>
+#if PLATFORM(WIN)
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
+#endif
#include <WTF/RetainPtr.h>
namespace WebCore {
-const CFStringRef failingURLStringKey = CFSTR("NSErrorFailingURLStringKey");
-const CFStringRef failingURLKey = CFSTR("NSErrorFailingURLKey");
+ResourceError::ResourceError(CFErrorRef cfError)
+ : m_dataIsUpToDate(false)
+ , m_platformError(cfError)
+{
+ m_isNull = !cfError;
+}
-// FIXME: Once <rdar://problem/5050841> is fixed we can remove this constructor.
-ResourceError::ResourceError(CFStreamError error)
- : m_dataIsUpToDate(true)
+#if PLATFORM(WIN)
+ResourceError::ResourceError(const String& domain, int errorCode, const String& failingURL, const String& localizedDescription, CFDataRef certificate)
+ : ResourceErrorBase(domain, errorCode, failingURL, localizedDescription)
+ , m_dataIsUpToDate(true)
+ , m_certificate(certificate)
{
- m_isNull = false;
- m_errorCode = error.error;
+}
- switch(error.domain) {
- case kCFStreamErrorDomainCustom:
- m_domain ="NSCustomErrorDomain";
- break;
- case kCFStreamErrorDomainPOSIX:
- m_domain = "NSPOSIXErrorDomain";
- break;
- case kCFStreamErrorDomainMacOSStatus:
- m_domain = "NSOSStatusErrorDomain";
- break;
- }
+PCCERT_CONTEXT ResourceError::certificate() const
+{
+ if (!m_certificate)
+ return 0;
+
+ return reinterpret_cast<PCCERT_CONTEXT>(CFDataGetBytePtr(m_certificate.get()));
}
+#endif // PLATFORM(WIN)
+
+const CFStringRef failingURLStringKey = CFSTR("NSErrorFailingURLStringKey");
+const CFStringRef failingURLKey = CFSTR("NSErrorFailingURLKey");
void ResourceError::platformLazyInit()
{
@@ -101,23 +103,34 @@ void ResourceError::platformLazyInit()
}
}
m_localizedDescription = (CFStringRef) CFDictionaryGetValue(userInfo.get(), kCFErrorLocalizedDescriptionKey);
+
+#if PLATFORM(WIN)
+ m_certificate = wkGetSSLPeerCertificateData(userInfo.get());
+#endif
}
m_dataIsUpToDate = true;
}
+void ResourceError::platformCopy(ResourceError& errorCopy) const
+{
+#if PLATFORM(WIN)
+ errorCopy.m_certificate = m_certificate;
+#endif
+}
+
bool ResourceError::platformCompare(const ResourceError& a, const ResourceError& b)
{
- return (CFErrorRef)a == (CFErrorRef)b;
+ return a.cfError() == b.cfError();
}
-ResourceError::operator CFErrorRef() const
+CFErrorRef ResourceError::cfError() const
{
if (m_isNull) {
ASSERT(!m_platformError);
return 0;
}
-
+
if (!m_platformError) {
RetainPtr<CFMutableDictionaryRef> userInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
@@ -133,6 +146,11 @@ ResourceError::operator CFErrorRef() const
CFDictionarySetValue(userInfo.get(), failingURLKey, url.get());
}
+#if PLATFORM(WIN)
+ if (m_certificate)
+ wkSetSSLPeerCertificateData(userInfo.get(), m_certificate.get());
+#endif
+
RetainPtr<CFStringRef> domainString(AdoptCF, m_domain.createCFString());
m_platformError.adoptCF(CFErrorCreate(0, domainString.get(), m_errorCode, userInfo.get()));
}
@@ -140,7 +158,32 @@ ResourceError::operator CFErrorRef() const
return m_platformError.get();
}
-ResourceError::operator CFStreamError() const
+ResourceError::operator CFErrorRef() const
+{
+ return cfError();
+}
+
+// FIXME: Once <rdar://problem/5050841> is fixed we can remove this constructor.
+ResourceError::ResourceError(CFStreamError error)
+ : m_dataIsUpToDate(true)
+{
+ m_isNull = false;
+ m_errorCode = error.error;
+
+ switch(error.domain) {
+ case kCFStreamErrorDomainCustom:
+ m_domain ="NSCustomErrorDomain";
+ break;
+ case kCFStreamErrorDomainPOSIX:
+ m_domain = "NSPOSIXErrorDomain";
+ break;
+ case kCFStreamErrorDomainMacOSStatus:
+ m_domain = "NSOSStatusErrorDomain";
+ break;
+ }
+}
+
+CFStreamError ResourceError::cfStreamError() const
{
lazyInit();
@@ -159,6 +202,11 @@ ResourceError::operator CFStreamError() const
return result;
}
+ResourceError::operator CFStreamError() const
+{
+ return cfStreamError();
+}
+
} // namespace WebCore
#endif // USE(CFNETWORK)
diff --git a/Source/WebCore/platform/network/cf/ResourceRequestCFNet.h b/Source/WebCore/platform/network/cf/ResourceRequestCFNet.h
index 09f4cea..271dcd2 100644
--- a/Source/WebCore/platform/network/cf/ResourceRequestCFNet.h
+++ b/Source/WebCore/platform/network/cf/ResourceRequestCFNet.h
@@ -50,6 +50,8 @@ inline ResourceLoadPriority mapHTTPPipeliningPriorityToResourceLoadPriority(int
return ResourceLoadPriorityMedium;
case 2:
return ResourceLoadPriorityHigh;
+ case 3:
+ return ResourceLoadPriorityUnresolved;
default:
ASSERT_NOT_REACHED();
return ResourceLoadPriorityLowest;
@@ -67,8 +69,7 @@ inline int mapResourceLoadPriorityToHTTPPipeliningPriority(ResourceLoadPriority
case ResourceLoadPriorityHigh:
return 2;
case ResourceLoadPriorityUnresolved:
- ASSERT_NOT_REACHED();
- return 0;
+ return 3;
}
ASSERT_NOT_REACHED();
diff --git a/Source/WebCore/platform/network/cf/ResourceResponse.h b/Source/WebCore/platform/network/cf/ResourceResponse.h
index 33b6ddc..0551ede 100644
--- a/Source/WebCore/platform/network/cf/ResourceResponse.h
+++ b/Source/WebCore/platform/network/cf/ResourceResponse.h
@@ -98,9 +98,9 @@ private:
static bool platformCompare(const ResourceResponse& a, const ResourceResponse& b);
#if USE(CFNETWORK)
- RetainPtr<CFURLResponseRef> m_cfResponse;
+ mutable RetainPtr<CFURLResponseRef> m_cfResponse;
#else
- RetainPtr<NSURLResponse> m_nsResponse;
+ mutable RetainPtr<NSURLResponse> m_nsResponse;
#endif
bool m_isUpToDate;
};
diff --git a/Source/WebCore/platform/network/cf/ResourceResponseCFNet.cpp b/Source/WebCore/platform/network/cf/ResourceResponseCFNet.cpp
index 167b079..d4a0b31 100644
--- a/Source/WebCore/platform/network/cf/ResourceResponseCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/ResourceResponseCFNet.cpp
@@ -43,7 +43,14 @@ using namespace std;
namespace WebCore {
CFURLResponseRef ResourceResponse::cfURLResponse() const
-{
+{
+ if (!m_cfResponse && !m_isNull) {
+ RetainPtr<CFURLRef> url(AdoptCF, m_url.createCFURL());
+ RetainPtr<CFStringRef> mimeType(AdoptCF, m_mimeType.createCFString());
+ RetainPtr<CFStringRef> textEncodingName(AdoptCF, m_textEncodingName.createCFString());
+ m_cfResponse.adoptCF(CFURLResponseCreate(0, url.get(), mimeType.get(), m_expectedContentLength, textEncodingName.get(), kCFURLCacheStorageAllowed));
+ }
+
return m_cfResponse.get();
}
diff --git a/Source/WebCore/platform/network/cf/SocketStreamHandle.h b/Source/WebCore/platform/network/cf/SocketStreamHandle.h
index 5c1c6ff..4adee70 100644
--- a/Source/WebCore/platform/network/cf/SocketStreamHandle.h
+++ b/Source/WebCore/platform/network/cf/SocketStreamHandle.h
@@ -44,14 +44,14 @@ class AuthenticationChallenge;
class Credential;
class SocketStreamHandleClient;
-class SocketStreamHandle : public RefCounted<SocketStreamHandle>, public SocketStreamHandleBase, public AuthenticationClient {
+class SocketStreamHandle : public ThreadSafeRefCounted<SocketStreamHandle>, public SocketStreamHandleBase, public AuthenticationClient {
public:
static PassRefPtr<SocketStreamHandle> create(const KURL& url, SocketStreamHandleClient* client) { return adoptRef(new SocketStreamHandle(url, client)); }
virtual ~SocketStreamHandle();
- using RefCounted<SocketStreamHandle>::ref;
- using RefCounted<SocketStreamHandle>::deref;
+ using ThreadSafeRefCounted<SocketStreamHandle>::ref;
+ using ThreadSafeRefCounted<SocketStreamHandle>::deref;
private:
virtual int platformSend(const char* data, int length);
diff --git a/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp b/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp
index d5b1743..ee06c68 100644
--- a/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp
@@ -117,7 +117,7 @@ CFStringRef SocketStreamHandle::copyPACExecutionDescription(void*)
struct MainThreadPACCallbackInfo {
MainThreadPACCallbackInfo(SocketStreamHandle* handle, CFArrayRef proxyList) : handle(handle), proxyList(proxyList) { }
- SocketStreamHandle* handle;
+ RefPtr<SocketStreamHandle> handle;
CFArrayRef proxyList;
};
@@ -436,7 +436,7 @@ CFStringRef SocketStreamHandle::copyCFStreamDescription(void* info)
struct MainThreadEventCallbackInfo {
MainThreadEventCallbackInfo(CFStreamEventType type, SocketStreamHandle* handle) : type(type), handle(handle) { }
CFStreamEventType type;
- SocketStreamHandle* handle;
+ RefPtr<SocketStreamHandle> handle;
};
void SocketStreamHandle::readStreamCallback(CFReadStreamRef stream, CFStreamEventType type, void* clientCallBackInfo)
diff --git a/Source/WebCore/platform/network/mac/CookieStorageMac.mm b/Source/WebCore/platform/network/mac/CookieStorageMac.mm
index db64aae..2696188 100644
--- a/Source/WebCore/platform/network/mac/CookieStorageMac.mm
+++ b/Source/WebCore/platform/network/mac/CookieStorageMac.mm
@@ -92,7 +92,7 @@ void setCookieStoragePrivateBrowsingEnabled(bool enabled)
return;
if (enabled && ResourceHandle::privateBrowsingStorageSession()) {
- privateBrowsingCookieStorage().adoptCF(wkCreatePrivateInMemoryHTTPCookieStorage(ResourceHandle::privateBrowsingStorageSession()));
+ privateBrowsingCookieStorage().adoptCF(wkCopyHTTPCookieStorage(ResourceHandle::privateBrowsingStorageSession()));
// FIXME: When Private Browsing is enabled, the Private Browsing Cookie Storage should be
// observed for changes, not the default Cookie Storage.
@@ -116,7 +116,10 @@ void startObservingCookieChanges()
void stopObservingCookieChanges()
{
- ASSERT(cookieStorageAdapter);
+ // cookieStorageAdapter can be nil here, if the WebProcess crashed and was restarted between
+ // when startObservingCookieChanges was called, and stopObservingCookieChanges is currently being called.
+ if (!cookieStorageAdapter)
+ return;
[cookieStorageAdapter stopListeningForCookieChangeNotifications];
}
diff --git a/Source/WebCore/platform/network/mac/FormDataStreamMac.mm b/Source/WebCore/platform/network/mac/FormDataStreamMac.mm
index eb6f601..f094842 100644
--- a/Source/WebCore/platform/network/mac/FormDataStreamMac.mm
+++ b/Source/WebCore/platform/network/mac/FormDataStreamMac.mm
@@ -192,8 +192,8 @@ static bool advanceCurrentStream(FormStreamFields* form)
}
#if ENABLE(BLOB)
if (nextInput.m_fileStart > 0) {
- CFNumberRef position = CFNumberCreate(0, kCFNumberLongLongType, &nextInput.m_fileStart);
- CFReadStreamSetProperty(form->currentStream, kCFStreamPropertyFileCurrentOffset, position);
+ RetainPtr<CFNumberRef> position(AdoptCF, CFNumberCreate(0, kCFNumberLongLongType, &nextInput.m_fileStart));
+ CFReadStreamSetProperty(form->currentStream, kCFStreamPropertyFileCurrentOffset, position.get());
}
form->currentStreamRangeLength = nextInput.m_fileLength;
#endif
diff --git a/Source/WebCore/platform/network/mac/ResourceErrorMac.mm b/Source/WebCore/platform/network/mac/ResourceErrorMac.mm
index 275ca41..0bada1f 100644
--- a/Source/WebCore/platform/network/mac/ResourceErrorMac.mm
+++ b/Source/WebCore/platform/network/mac/ResourceErrorMac.mm
@@ -28,6 +28,7 @@
#import "BlockExceptions.h"
#import "KURL.h"
+#import <CoreFoundation/CFError.h>
#import <Foundation/Foundation.h>
@interface NSError (WebExtras)
@@ -36,6 +37,20 @@
namespace WebCore {
+ResourceError::ResourceError(NSError *nsError)
+ : m_dataIsUpToDate(false)
+ , m_platformError(nsError)
+{
+ m_isNull = !nsError;
+}
+
+ResourceError::ResourceError(CFErrorRef cfError)
+ : m_dataIsUpToDate(false)
+ , m_platformError((NSError *)cfError)
+{
+ m_isNull = !cfError;
+}
+
void ResourceError::platformLazyInit()
{
if (m_dataIsUpToDate)
@@ -59,10 +74,10 @@ void ResourceError::platformLazyInit()
bool ResourceError::platformCompare(const ResourceError& a, const ResourceError& b)
{
- return (NSError*)a == (NSError*)b;
+ return a.nsError() == b.nsError();
}
-ResourceError::operator NSError*() const
+NSError *ResourceError::nsError() const
{
if (m_isNull) {
ASSERT(!m_platformError);
@@ -87,4 +102,19 @@ ResourceError::operator NSError*() const
return m_platformError.get();
}
+ResourceError::operator NSError *() const
+{
+ return nsError();
+}
+
+CFErrorRef ResourceError::cfError() const
+{
+ return (CFErrorRef)nsError();
+}
+
+ResourceError::operator CFErrorRef() const
+{
+ return cfError();
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/mac/ResourceHandleMac.mm b/Source/WebCore/platform/network/mac/ResourceHandleMac.mm
index 96d561d..b2a89f0 100644
--- a/Source/WebCore/platform/network/mac/ResourceHandleMac.mm
+++ b/Source/WebCore/platform/network/mac/ResourceHandleMac.mm
@@ -886,7 +886,7 @@ String ResourceHandle::privateBrowsingStorageSessionIdentifierDefaultBase()
// Avoid MIME type sniffing if the response comes back as 304 Not Modified.
int statusCode = [r respondsToSelector:@selector(statusCode)] ? [(id)r statusCode] : 0;
if (statusCode != 304)
- [r adjustMIMETypeIfNecessary];
+ adjustMIMETypeIfNecessary([r _CFURLResponse]);
if ([m_handle->firstRequest().nsURLRequest() _propertyForKey:@"ForceHTMLMIMEType"])
[r _setMIMEType:@"text/html"];
@@ -910,9 +910,32 @@ String ResourceHandle::privateBrowsingStorageSessionIdentifierDefaultBase()
m_handle->client()->didReceiveResponse(m_handle, r);
}
+#if HAVE(CFNETWORK_DATA_ARRAY_CALLBACK)
+- (void)connection:(NSURLConnection *)connection didReceiveDataArray:(NSArray *)dataArray
+{
+ UNUSED_PARAM(connection);
+ LOG(Network, "Handle %p delegate connection:%p didReceiveDataArray:%p arraySize:%d", m_handle, connection, dataArray, [dataArray count]);
+
+ if (!dataArray)
+ return;
+
+ if (!m_handle || !m_handle->client())
+ return;
+
+ if (m_handle->client()->supportsDataArray())
+ m_handle->client()->didReceiveDataArray(m_handle, reinterpret_cast<CFArrayRef>(dataArray));
+ else {
+ for (NSData *data in dataArray)
+ m_handle->client()->didReceiveData(m_handle, static_cast<const char*>([data bytes]), [data length], static_cast<int>([data length]));
+ }
+ return;
+}
+#endif
+
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data lengthReceived:(long long)lengthReceived
{
UNUSED_PARAM(connection);
+ UNUSED_PARAM(lengthReceived);
LOG(Network, "Handle %p delegate connection:%p didReceiveData:%p lengthReceived:%lld", m_handle, connection, data, lengthReceived);
@@ -922,7 +945,10 @@ String ResourceHandle::privateBrowsingStorageSessionIdentifierDefaultBase()
// However, with today's computers and networking speeds, this won't happen in practice.
// Could be an issue with a giant local file.
CallbackGuard guard;
- m_handle->client()->didReceiveData(m_handle, (const char*)[data bytes], [data length], static_cast<int>(lengthReceived));
+ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=19793
+ // -1 means we do not provide any data about transfer size to inspector so it would use
+ // Content-Length headers or content size to show transfer size.
+ m_handle->client()->didReceiveData(m_handle, (const char*)[data bytes], [data length], -1);
}
- (void)connection:(NSURLConnection *)connection willStopBufferingData:(NSData *)data
diff --git a/Source/WebCore/platform/network/mac/WebCoreURLResponse.h b/Source/WebCore/platform/network/mac/WebCoreURLResponse.h
index 8d43a21..d766b96 100644
--- a/Source/WebCore/platform/network/mac/WebCoreURLResponse.h
+++ b/Source/WebCore/platform/network/mac/WebCoreURLResponse.h
@@ -26,10 +26,15 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-@interface NSURLResponse (WebCoreURLResponse)
--(void)adjustMIMETypeIfNecessary;
-@end
+typedef struct _CFURLResponse* CFURLResponseRef;
+#ifdef __OBJC__
@interface NSURLResponse (Details)
+- (CFURLResponseRef)_CFURLResponse;
- (void)_setMIMEType:(NSString *)type;
@end
+#endif
+
+namespace WebCore {
+void adjustMIMETypeIfNecessary(CFURLResponseRef);
+}
diff --git a/Source/WebCore/platform/network/mac/WebCoreURLResponse.mm b/Source/WebCore/platform/network/mac/WebCoreURLResponse.mm
index e287e5f..0960492 100644
--- a/Source/WebCore/platform/network/mac/WebCoreURLResponse.mm
+++ b/Source/WebCore/platform/network/mac/WebCoreURLResponse.mm
@@ -30,308 +30,429 @@
#import "WebCoreURLResponse.h"
#import "MIMETypeRegistry.h"
-#import <objc/objc-class.h>
+#import "WebCoreSystemInterface.h"
#import <wtf/Assertions.h>
#import <wtf/RetainPtr.h>
-#ifndef BUILDING_ON_TIGER
+namespace WebCore {
+
// <rdar://problem/5321972> Plain text document from HTTP server detected as application/octet-stream
// When we sniff a resource as application/octet-stream but the http response headers had "text/plain",
// we have a hard decision to make about which of the two generic MIME types to go with.
// When the URL's extension is a known binary type, we'll go with application/octet-stream.
// Otherwise, we'll trust the server.
-static NSSet *createBinaryExtensionsSet()
+static CFSetRef createBinaryExtensionsSet()
{
- return [[NSSet alloc] initWithObjects:
- @"3g2",
- @"3gp",
- @"ai",
- @"aif",
- @"aifc",
- @"aiff",
- @"au",
- @"avi",
- @"bcpio",
- @"bin",
- @"bmp",
- @"boz",
- @"bpk",
- @"bz",
- @"bz2",
- @"chm",
- @"class",
- @"com",
- @"cpio",
- @"dcr",
- @"dir",
- @"dist",
- @"distz",
- @"dll",
- @"dmg",
- @"dms",
- @"doc",
- @"dot",
- @"dump",
- @"dv",
- @"dvi",
- @"dxr",
- @"elc",
- @"eot",
- @"eps",
- @"exe",
- @"fgd",
- @"gif",
- @"gtar",
- @"h261",
- @"h263",
- @"h264",
- @"ico",
- @"ims",
- @"indd",
- @"iso",
- @"jp2",
- @"jpe",
- @"jpeg",
- @"jpg",
- @"jpgm",
- @"jpgv",
- @"jpm",
- @"kar",
- @"kmz",
- @"lha",
- @"lrm",
- @"lzh",
- @"m1v",
- @"m2a",
- @"m2v",
- @"m3a",
- @"m3u",
- @"m4a",
- @"m4p",
- @"m4v",
- @"mdb",
- @"mid",
- @"midi",
- @"mj2",
- @"mjp2",
- @"mov",
- @"movie",
- @"mp2",
- @"mp2a",
- @"mp3",
- @"mp4",
- @"mp4a",
- @"mp4s",
- @"mp4v",
- @"mpe",
- @"mpeg",
- @"mpg",
- @"mpg4",
- @"mpga",
- @"mpp",
- @"mpt",
- @"msi",
- @"ogg",
- @"otf",
- @"pct",
- @"pdf",
- @"pfa",
- @"pfb",
- @"pic",
- @"pict",
- @"pkg",
- @"png",
- @"pot",
- @"pps",
- @"ppt",
- @"ps",
- @"psd",
- @"qt",
- @"qti",
- @"qtif",
- @"qwd",
- @"qwt",
- @"qxb",
- @"qxd",
- @"qxl",
- @"qxp",
- @"qxt",
- @"ra",
- @"ram",
- @"rm",
- @"rmi",
- @"rmp",
- @"scpt",
- @"sit",
- @"sitx",
- @"snd",
- @"so",
- @"swf",
- @"tar",
- @"tif",
- @"tiff",
- @"ttf",
- @"wav",
- @"wcm",
- @"wdb",
- @"wks",
- @"wm",
- @"wma",
- @"wmd",
- @"wmf",
- @"wmv",
- @"wmx",
- @"wmz",
- @"wpd",
- @"wpl",
- @"wps",
- @"wvx",
- @"xla",
- @"xlc",
- @"xlm",
- @"xls",
- @"xlt",
- @"xlw",
- @"xps",
- @"zip",
- nil
- ];
+ CFStringRef extensions[] = {
+ CFSTR("3g2"),
+ CFSTR("3gp"),
+ CFSTR("ai"),
+ CFSTR("aif"),
+ CFSTR("aifc"),
+ CFSTR("aiff"),
+ CFSTR("au"),
+ CFSTR("avi"),
+ CFSTR("bcpio"),
+ CFSTR("bin"),
+ CFSTR("bmp"),
+ CFSTR("boz"),
+ CFSTR("bpk"),
+ CFSTR("bz"),
+ CFSTR("bz2"),
+ CFSTR("chm"),
+ CFSTR("class"),
+ CFSTR("com"),
+ CFSTR("cpio"),
+ CFSTR("dcr"),
+ CFSTR("dir"),
+ CFSTR("dist"),
+ CFSTR("distz"),
+ CFSTR("dll"),
+ CFSTR("dmg"),
+ CFSTR("dms"),
+ CFSTR("doc"),
+ CFSTR("dot"),
+ CFSTR("dump"),
+ CFSTR("dv"),
+ CFSTR("dvi"),
+ CFSTR("dxr"),
+ CFSTR("elc"),
+ CFSTR("eot"),
+ CFSTR("eps"),
+ CFSTR("exe"),
+ CFSTR("fgd"),
+ CFSTR("gif"),
+ CFSTR("gtar"),
+ CFSTR("h261"),
+ CFSTR("h263"),
+ CFSTR("h264"),
+ CFSTR("ico"),
+ CFSTR("ims"),
+ CFSTR("indd"),
+ CFSTR("iso"),
+ CFSTR("jp2"),
+ CFSTR("jpe"),
+ CFSTR("jpeg"),
+ CFSTR("jpg"),
+ CFSTR("jpgm"),
+ CFSTR("jpgv"),
+ CFSTR("jpm"),
+ CFSTR("kar"),
+ CFSTR("kmz"),
+ CFSTR("lha"),
+ CFSTR("lrm"),
+ CFSTR("lzh"),
+ CFSTR("m1v"),
+ CFSTR("m2a"),
+ CFSTR("m2v"),
+ CFSTR("m3a"),
+ CFSTR("m3u"),
+ CFSTR("m4a"),
+ CFSTR("m4p"),
+ CFSTR("m4v"),
+ CFSTR("mdb"),
+ CFSTR("mid"),
+ CFSTR("midi"),
+ CFSTR("mj2"),
+ CFSTR("mjp2"),
+ CFSTR("mov"),
+ CFSTR("movie"),
+ CFSTR("mp2"),
+ CFSTR("mp2a"),
+ CFSTR("mp3"),
+ CFSTR("mp4"),
+ CFSTR("mp4a"),
+ CFSTR("mp4s"),
+ CFSTR("mp4v"),
+ CFSTR("mpe"),
+ CFSTR("mpeg"),
+ CFSTR("mpg"),
+ CFSTR("mpg4"),
+ CFSTR("mpga"),
+ CFSTR("mpp"),
+ CFSTR("mpt"),
+ CFSTR("msi"),
+ CFSTR("ogg"),
+ CFSTR("otf"),
+ CFSTR("pct"),
+ CFSTR("pdf"),
+ CFSTR("pfa"),
+ CFSTR("pfb"),
+ CFSTR("pic"),
+ CFSTR("pict"),
+ CFSTR("pkg"),
+ CFSTR("png"),
+ CFSTR("pot"),
+ CFSTR("pps"),
+ CFSTR("ppt"),
+ CFSTR("ps"),
+ CFSTR("psd"),
+ CFSTR("qt"),
+ CFSTR("qti"),
+ CFSTR("qtif"),
+ CFSTR("qwd"),
+ CFSTR("qwt"),
+ CFSTR("qxb"),
+ CFSTR("qxd"),
+ CFSTR("qxl"),
+ CFSTR("qxp"),
+ CFSTR("qxt"),
+ CFSTR("ra"),
+ CFSTR("ram"),
+ CFSTR("rm"),
+ CFSTR("rmi"),
+ CFSTR("rmp"),
+ CFSTR("scpt"),
+ CFSTR("sit"),
+ CFSTR("sitx"),
+ CFSTR("snd"),
+ CFSTR("so"),
+ CFSTR("swf"),
+ CFSTR("tar"),
+ CFSTR("tif"),
+ CFSTR("tiff"),
+ CFSTR("ttf"),
+ CFSTR("wav"),
+ CFSTR("wcm"),
+ CFSTR("wdb"),
+ CFSTR("wks"),
+ CFSTR("wm"),
+ CFSTR("wma"),
+ CFSTR("wmd"),
+ CFSTR("wmf"),
+ CFSTR("wmv"),
+ CFSTR("wmx"),
+ CFSTR("wmz"),
+ CFSTR("wpd"),
+ CFSTR("wpl"),
+ CFSTR("wps"),
+ CFSTR("wvx"),
+ CFSTR("xla"),
+ CFSTR("xlc"),
+ CFSTR("xlm"),
+ CFSTR("xls"),
+ CFSTR("xlt"),
+ CFSTR("xlw"),
+ CFSTR("xps"),
+ CFSTR("zip")
+ };
+ return CFSetCreate(kCFAllocatorDefault, (const void **)&extensions, sizeof(extensions)/sizeof(CFStringRef), &kCFTypeSetCallBacks);
}
-#endif
// <rdar://problem/7007389> CoreTypes UTI map is missing 100+ file extensions that GateKeeper knew about
// When we disabled content sniffing for file URLs we caused problems with these 100+ extensions that CoreTypes
// doesn't know about.
// If CoreTypes is ever brought up to speed we can remove this table and associated code.
-static NSDictionary *createExtensionToMIMETypeMap()
+static CFDictionaryRef createExtensionToMIMETypeMap()
{
- return [[NSDictionary alloc] initWithObjectsAndKeys:
- @"application/postscript", @"ai",
- @"text/plain", @"asc",
- @"application/x-bcpio", @"bcpio",
- @"image/bmp", @"bmp",
- @"application/x-netcdf", @"cdf",
- @"application/octet-stream", @"class",
- @"application/x-gzip", @"cpgz",
- @"application/x-cpio", @"cpio",
- @"application/mac-compactpro", @"cpt",
- @"application/x-csh", @"csh",
- @"text/css", @"css",
- @"application/x-director", @"dcr",
- @"application/x-director", @"dir",
- @"application/x-diskcopy", @"dmg",
- @"application/octet-stream", @"dms",
- @"application/x-dvi", @"dvi",
- @"application/x-director", @"dxr",
- @"application/postscript", @"eps",
- @"text/x-setext", @"etx",
- @"application/andrew-inset", @"ez",
- @"application/vnd.fdf", @"fdf",
- @"application/octet-stream", @"fla",
- @"application/x-filemaker", @"fp",
- @"application/x-filemaker", @"fp2",
- @"application/x-filemaker", @"fp3",
- @"application/x-filemaker", @"fp4",
- @"application/x-filemaker", @"fp5",
- @"application/x-filemaker", @"fp6",
- @"application/x-hdf", @"hdf",
- @"x-conference/x-cooltalk", @"ice",
- @"image/x-icon", @"ico",
- @"text/calendar", @"ics",
- @"image/ief", @"ief",
- @"model/iges", @"iges",
- @"model/iges", @"igs",
- @"application/octet-stream", @"iso",
- @"text/html", @"jhtml",
- @"application/x-latex", @"latex",
- @"application/octet-stream", @"lha",
- @"application/octet-stream", @"lzh",
- @"audio/x-mpegurl", @"m3u",
- @"audio/x-m4p", @"m4p",
- @"image/x-macpaint", @"mac",
- @"application/x-troff-man", @"man",
- @"application/x-troff-me", @"me",
- @"model/mesh", @"mesh",
- @"application/vnd.mif", @"mif",
- @"video/x-sgi-movie", @"movie",
- @"audio/mpeg", @"mp2",
- @"audio/mpeg", @"mpga",
- @"application/x-troff-ms", @"ms",
- @"model/mesh", @"msh",
- @"video/vnd.mpegurl", @"mxu",
- @"application/x-netcdf", @"nc",
- @"application/oda", @"oda",
- @"image/x-portable-bitmap", @"pbm",
- @"image/x-pcx", @"pcx",
- @"chemical/x-pdb", @"pdb",
- @"image/x-portable-graymap", @"pgm",
- @"application/x-chess-pgn", @"pgn",
- @"audio/scpls", @"pls",
- @"image/x-portable-anymap", @"pnm",
- @"image/x-macpaint", @"pnt",
- @"image/x-macpaint", @"pntg",
- @"image/x-portable-pixmap", @"ppm",
- @"image/x-cmu-raster", @"ras",
- @"image/x-rgb", @"rgb",
- @"application/x-troff", @"roff",
- @"audio/x-pn-realaudio-plugin", @"rpm",
- @"text/richtext", @"rtx",
- @"text/sgml", @"sgm",
- @"text/sgml", @"sgml",
- @"application/x-sh", @"sh",
- @"application/x-shar", @"shar",
- @"model/mesh", @"silo",
- @"application/x-koan", @"skd",
- @"application/x-koan", @"skm",
- @"application/x-koan", @"skp",
- @"application/x-koan", @"skt",
- @"application/x-diskcopy", @"smi",
- @"application/octet-stream", @"so",
- @"application/x-futuresplash", @"spl",
- @"application/x-wais-source", @"src",
- @"application/x-sv4cpio", @"sv4cpio",
- @"application/x-sv4crc", @"sv4crc",
- @"application/x-shockwave-flash", @"swf",
- @"application/x-troff", @"t",
- @"image/x-targa", @"targa",
- @"application/x-tcl", @"tcl",
- @"application/x-tex", @"tex",
- @"application/x-texinfo", @"texi",
- @"application/x-texinfo", @"texinfo",
- @"application/x-gzip", @"tgz",
- @"application/x-bittorrent", @"torrent",
- @"application/x-troff", @"tr",
- @"text/tab-separated-values", @"tsv",
- @"application/x-ustar", @"ustar",
- @"application/x-cdlink", @"vcd",
- @"model/vrml", @"vrml",
- @"image/vnd.wap.wbmp", @"wbmp",
- @"application/vnd.wap.wbxml", @"wbxml",
- @"application/x-webarchive", @"webarchive",
- @"application/x-ms-wmd", @"wmd",
- @"text/vnd.wap.wml", @"wml",
- @"application/vnd.wap.wmlc", @"wmlc",
- @"text/vnd.wap.wmlscript", @"wmls",
- @"application/vnd.wap.wmlscriptc", @"wmlsc",
- @"model/vrml", @"wrl",
- @"application/vnd.adobe.xdp+xml", @"xdp",
- @"application/vnd.adobe.xfd+xml", @"xfd",
- @"application/vnd.adobe.xfdf", @"xfdf",
- @"image/x-xpixmap", @"xpm",
- @"text/xml", @"xsl",
- @"image/x-xwindowdump", @"xwd",
- @"chemical/x-xyz", @"xyz",
- @"application/x-compress", @"z",
- nil
- ];
+ CFStringRef keys[] = {
+ CFSTR("ai"),
+ CFSTR("asc"),
+ CFSTR("bcpio"),
+ CFSTR("bmp"),
+ CFSTR("cdf"),
+ CFSTR("class"),
+ CFSTR("cpgz"),
+ CFSTR("cpio"),
+ CFSTR("cpt"),
+ CFSTR("csh"),
+ CFSTR("css"),
+ CFSTR("dcr"),
+ CFSTR("dir"),
+ CFSTR("dmg"),
+ CFSTR("dms"),
+ CFSTR("dvi"),
+ CFSTR("dxr"),
+ CFSTR("eps"),
+ CFSTR("etx"),
+ CFSTR("ez"),
+ CFSTR("fdf"),
+ CFSTR("fla"),
+ CFSTR("fp"),
+ CFSTR("fp2"),
+ CFSTR("fp3"),
+ CFSTR("fp4"),
+ CFSTR("fp5"),
+ CFSTR("fp6"),
+ CFSTR("hdf"),
+ CFSTR("ice"),
+ CFSTR("ico"),
+ CFSTR("ics"),
+ CFSTR("ief"),
+ CFSTR("iges"),
+ CFSTR("igs"),
+ CFSTR("iso"),
+ CFSTR("jhtml"),
+ CFSTR("latex"),
+ CFSTR("lha"),
+ CFSTR("lzh"),
+ CFSTR("m3u"),
+ CFSTR("m4p"),
+ CFSTR("mac"),
+ CFSTR("man"),
+ CFSTR("me"),
+ CFSTR("mesh"),
+ CFSTR("mif"),
+ CFSTR("movie"),
+ CFSTR("mp2"),
+ CFSTR("mpga"),
+ CFSTR("ms"),
+ CFSTR("msh"),
+ CFSTR("mxu"),
+ CFSTR("nc"),
+ CFSTR("oda"),
+ CFSTR("pbm"),
+ CFSTR("pcx"),
+ CFSTR("pdb"),
+ CFSTR("pgm"),
+ CFSTR("pgn"),
+ CFSTR("pls"),
+ CFSTR("pnm"),
+ CFSTR("pnt"),
+ CFSTR("pntg"),
+ CFSTR("ppm"),
+ CFSTR("ras"),
+ CFSTR("rgb"),
+ CFSTR("roff"),
+ CFSTR("rpm"),
+ CFSTR("rtx"),
+ CFSTR("sgm"),
+ CFSTR("sgml"),
+ CFSTR("sh"),
+ CFSTR("shar"),
+ CFSTR("silo"),
+ CFSTR("skd"),
+ CFSTR("skm"),
+ CFSTR("skp"),
+ CFSTR("skt"),
+ CFSTR("smi"),
+ CFSTR("so"),
+ CFSTR("spl"),
+ CFSTR("src"),
+ CFSTR("sv4cpio"),
+ CFSTR("sv4crc"),
+ CFSTR("swf"),
+ CFSTR("t"),
+ CFSTR("targa"),
+ CFSTR("tcl"),
+ CFSTR("tex"),
+ CFSTR("texi"),
+ CFSTR("texinfo"),
+ CFSTR("tgz"),
+ CFSTR("torrent"),
+ CFSTR("tr"),
+ CFSTR("tsv"),
+ CFSTR("ustar"),
+ CFSTR("vcd"),
+ CFSTR("vrml"),
+ CFSTR("wbmp"),
+ CFSTR("wbxml"),
+ CFSTR("webarchive"),
+ CFSTR("wmd"),
+ CFSTR("wml"),
+ CFSTR("wmlc"),
+ CFSTR("wmls"),
+ CFSTR("wmlsc"),
+ CFSTR("wrl"),
+ CFSTR("xdp"),
+ CFSTR("xfd"),
+ CFSTR("xfdf"),
+ CFSTR("xpm"),
+ CFSTR("xsl"),
+ CFSTR("xwd"),
+ CFSTR("xyz"),
+ CFSTR("z")
+ };
+
+ CFStringRef values[] = {
+ CFSTR("application/postscript"),
+ CFSTR("text/plain"),
+ CFSTR("application/x-bcpio"),
+ CFSTR("image/bmp"),
+ CFSTR("application/x-netcdf"),
+ CFSTR("application/octet-stream"),
+ CFSTR("application/x-gzip"),
+ CFSTR("application/x-cpio"),
+ CFSTR("application/mac-compactpro"),
+ CFSTR("application/x-csh"),
+ CFSTR("text/css"),
+ CFSTR("application/x-director"),
+ CFSTR("application/x-director"),
+ CFSTR("application/x-diskcopy"),
+ CFSTR("application/octet-stream"),
+ CFSTR("application/x-dvi"),
+ CFSTR("application/x-director"),
+ CFSTR("application/postscript"),
+ CFSTR("text/x-setext"),
+ CFSTR("application/andrew-inset"),
+ CFSTR("application/vnd.fdf"),
+ CFSTR("application/octet-stream"),
+ CFSTR("application/x-filemaker"),
+ CFSTR("application/x-filemaker"),
+ CFSTR("application/x-filemaker"),
+ CFSTR("application/x-filemaker"),
+ CFSTR("application/x-filemaker"),
+ CFSTR("application/x-filemaker"),
+ CFSTR("application/x-hdf"),
+ CFSTR("x-conference/x-cooltalk"),
+ CFSTR("image/x-icon"),
+ CFSTR("text/calendar"),
+ CFSTR("image/ief"),
+ CFSTR("model/iges"),
+ CFSTR("model/iges"),
+ CFSTR("application/octet-stream"),
+ CFSTR("text/html"),
+ CFSTR("application/x-latex"),
+ CFSTR("application/octet-stream"),
+ CFSTR("application/octet-stream"),
+ CFSTR("audio/x-mpegurl"),
+ CFSTR("audio/x-m4p"),
+ CFSTR("image/x-macpaint"),
+ CFSTR("application/x-troff-man"),
+ CFSTR("application/x-troff-me"),
+ CFSTR("model/mesh"),
+ CFSTR("application/vnd.mif"),
+ CFSTR("video/x-sgi-movie"),
+ CFSTR("audio/mpeg"),
+ CFSTR("audio/mpeg"),
+ CFSTR("application/x-troff-ms"),
+ CFSTR("model/mesh"),
+ CFSTR("video/vnd.mpegurl"),
+ CFSTR("application/x-netcdf"),
+ CFSTR("application/oda"),
+ CFSTR("image/x-portable-bitmap"),
+ CFSTR("image/x-pcx"),
+ CFSTR("chemical/x-pdb"),
+ CFSTR("image/x-portable-graymap"),
+ CFSTR("application/x-chess-pgn"),
+ CFSTR("audio/scpls"),
+ CFSTR("image/x-portable-anymap"),
+ CFSTR("image/x-macpaint"),
+ CFSTR("image/x-macpaint"),
+ CFSTR("image/x-portable-pixmap"),
+ CFSTR("image/x-cmu-raster"),
+ CFSTR("image/x-rgb"),
+ CFSTR("application/x-troff"),
+ CFSTR("audio/x-pn-realaudio-plugin"),
+ CFSTR("text/richtext"),
+ CFSTR("text/sgml"),
+ CFSTR("text/sgml"),
+ CFSTR("application/x-sh"),
+ CFSTR("application/x-shar"),
+ CFSTR("model/mesh"),
+ CFSTR("application/x-koan"),
+ CFSTR("application/x-koan"),
+ CFSTR("application/x-koan"),
+ CFSTR("application/x-koan"),
+ CFSTR("application/x-diskcopy"),
+ CFSTR("application/octet-stream"),
+ CFSTR("application/x-futuresplash"),
+ CFSTR("application/x-wais-source"),
+ CFSTR("application/x-sv4cpio"),
+ CFSTR("application/x-sv4crc"),
+ CFSTR("application/x-shockwave-flash"),
+ CFSTR("application/x-troff"),
+ CFSTR("image/x-targa"),
+ CFSTR("application/x-tcl"),
+ CFSTR("application/x-tex"),
+ CFSTR("application/x-texinfo"),
+ CFSTR("application/x-texinfo"),
+ CFSTR("application/x-gzip"),
+ CFSTR("application/x-bittorrent"),
+ CFSTR("application/x-troff"),
+ CFSTR("text/tab-separated-values"),
+ CFSTR("application/x-ustar"),
+ CFSTR("application/x-cdlink"),
+ CFSTR("model/vrml"),
+ CFSTR("image/vnd.wap.wbmp"),
+ CFSTR("application/vnd.wap.wbxml"),
+ CFSTR("application/x-webarchive"),
+ CFSTR("application/x-ms-wmd"),
+ CFSTR("text/vnd.wap.wml"),
+ CFSTR("application/vnd.wap.wmlc"),
+ CFSTR("text/vnd.wap.wmlscript"),
+ CFSTR("application/vnd.wap.wmlscriptc"),
+ CFSTR("model/vrml"),
+ CFSTR("application/vnd.adobe.xdp+xml"),
+ CFSTR("application/vnd.adobe.xfd+xml"),
+ CFSTR("application/vnd.adobe.xfdf"),
+ CFSTR("image/x-xpixmap"),
+ CFSTR("text/xml"),
+ CFSTR("image/x-xwindowdump"),
+ CFSTR("chemical/x-xyz"),
+ CFSTR("application/x-compress")
+ };
+
+ ASSERT(sizeof(keys) == sizeof(values));
+ return CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys, (const void**)&values, sizeof(keys)/sizeof(CFStringRef), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
}
-static RetainPtr<NSString> mimeTypeFromUTITree(CFStringRef uti)
+static RetainPtr<CFStringRef> mimeTypeFromUTITree(CFStringRef uti)
{
// Check if this UTI has a MIME type.
RetainPtr<CFStringRef> mimeType(AdoptCF, UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType));
if (mimeType)
- return (NSString *)mimeType.get();
+ return mimeType.get();
// If not, walk the ancestory of this UTI via its "ConformsTo" tags and return the first MIME type we find.
RetainPtr<CFDictionaryRef> decl(AdoptCF, UTTypeCopyDeclaration(uti));
@@ -353,7 +474,7 @@ static RetainPtr<NSString> mimeTypeFromUTITree(CFStringRef uti)
if (CFGetTypeID(object) != CFStringGetTypeID())
continue;
- if (RetainPtr<NSString> mimeType = mimeTypeFromUTITree((CFStringRef)object))
+ if (RetainPtr<CFStringRef> mimeType = mimeTypeFromUTITree((CFStringRef)object))
return mimeType;
}
}
@@ -361,33 +482,29 @@ static RetainPtr<NSString> mimeTypeFromUTITree(CFStringRef uti)
return nil;
}
-@implementation NSURLResponse (WebCoreURLResponse)
-
--(void)adjustMIMETypeIfNecessary
+void adjustMIMETypeIfNecessary(CFURLResponseRef cfResponse)
{
- RetainPtr<NSString> result = [self MIMEType];
- RetainPtr<NSString> originalResult = result;
-
-#ifdef BUILDING_ON_TIGER
- // When content sniffing is disabled, Tiger's CFNetwork automatically returns application/octet-stream for certain
- // extensions even when scouring the UTI maps would end up with a better result, so we'll give a chance for that to happen.
- if ([[self URL] isFileURL] && [result.get() caseInsensitiveCompare:@"application/octet-stream"] == NSOrderedSame)
- result = nil;
-#endif
+ RetainPtr<CFStringRef> result = wkGetCFURLResponseMIMEType(cfResponse);
+ RetainPtr<CFStringRef> originalResult = result;
if (!result) {
- NSURL *url = [self URL];
- if ([url isFileURL]) {
- if (NSString *extension = [[url path] pathExtension]) {
+ CFURLRef url = wkGetCFURLResponseURL(cfResponse);
+ NSURL *nsURL = (NSURL *)url;
+ if ([nsURL isFileURL]) {
+ RetainPtr<CFStringRef> extension(AdoptCF, CFURLCopyPathExtension(url));
+ if (extension) {
// <rdar://problem/7007389> CoreTypes UTI map is missing 100+ file extensions that GateKeeper knew about
// When this radar is resolved, we can remove this file:// url specific code.
- static NSDictionary *extensionMap = createExtensionToMIMETypeMap();
- result = [extensionMap objectForKey:[extension lowercaseString]];
+ static CFDictionaryRef extensionMap = createExtensionToMIMETypeMap();
+ CFMutableStringRef mutableExtension = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, extension.get());
+ CFStringLowercase(mutableExtension, NULL);
+ extension.adoptCF(mutableExtension);
+ result = (CFStringRef) CFDictionaryGetValue(extensionMap, extension.get());
if (!result) {
// If the Gatekeeper-based map doesn't have a MIME type, we'll try to figure out what it should be by
// looking up the file extension in the UTI maps.
- RetainPtr<CFStringRef> uti(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)extension, 0));
+ RetainPtr<CFStringRef> uti(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extension.get(), 0));
result = mimeTypeFromUTITree(uti.get());
}
}
@@ -395,29 +512,33 @@ static RetainPtr<NSString> mimeTypeFromUTITree(CFStringRef uti)
}
if (!result) {
- static NSString *defaultMIMETypeString = [(NSString *)WebCore::defaultMIMEType() retain];
+ static CFStringRef defaultMIMETypeString = WebCore::defaultMIMEType().createCFString();
result = defaultMIMETypeString;
}
-#ifndef BUILDING_ON_TIGER
// <rdar://problem/5321972> Plain text document from HTTP server detected as application/octet-stream
// Make the best guess when deciding between "generic binary" and "generic text" using a table of known binary MIME types.
- if ([result.get() isEqualToString:@"application/octet-stream"] && [self respondsToSelector:@selector(allHeaderFields)] && [[[self performSelector:@selector(allHeaderFields)] objectForKey:@"Content-Type"] hasPrefix:@"text/plain"]) {
- static NSSet *binaryExtensions = createBinaryExtensionsSet();
- if (![binaryExtensions containsObject:[[[self suggestedFilename] pathExtension] lowercaseString]])
- result = @"text/plain";
+ if (CFStringCompare(result.get(), CFSTR("application/octet-stream"), 0) == kCFCompareEqualTo) {
+ CFHTTPMessageRef message = wkGetCFURLResponseHTTPResponse(cfResponse);
+ if (message) {
+ RetainPtr<CFStringRef> contentType(AdoptCF, CFHTTPMessageCopyHeaderFieldValue(message, CFSTR("Content-Type")));
+ if (contentType && CFStringHasPrefix(contentType.get(), CFSTR("text/plain"))) {
+ static CFSetRef binaryExtensions = createBinaryExtensionsSet();
+ RetainPtr<NSString> suggestedFilename(AdoptNS, (NSString *)wkCopyCFURLResponseSuggestedFilename(cfResponse));
+ if (!CFSetContainsValue(binaryExtensions, (CFStringRef) [[suggestedFilename.get() pathExtension] lowercaseString]))
+ result = CFSTR("text/plain");
+ }
+ }
}
-#endif
-
#ifdef BUILDING_ON_LEOPARD
// Workaround for <rdar://problem/5539824>
- if ([result.get() isEqualToString:@"text/xml"])
- result = @"application/xml";
+ if (CFStringCompare(result.get(), CFSTR("text/xml"), 0) == kCFCompareEqualTo)
+ result = CFSTR("application/xml");
#endif
if (result != originalResult)
- [self _setMIMEType:result.get()];
+ wkSetCFURLResponseMIMEType(cfResponse, result.get());
}
-@end
+}
diff --git a/Source/WebCore/platform/network/qt/DnsPrefetchHelper.h b/Source/WebCore/platform/network/qt/DnsPrefetchHelper.h
index 892a3fb..4fcd19c 100644
--- a/Source/WebCore/platform/network/qt/DnsPrefetchHelper.h
+++ b/Source/WebCore/platform/network/qt/DnsPrefetchHelper.h
@@ -32,7 +32,7 @@ namespace WebCore {
class DnsPrefetchHelper : public QObject {
Q_OBJECT
public:
- DnsPrefetchHelper() : QObject(), currentLookups(0) {};
+ DnsPrefetchHelper() : QObject(), currentLookups(0) { }
public slots:
void lookup(QString hostname)
@@ -42,26 +42,8 @@ namespace WebCore {
if (currentLookups >= 10)
return; // do not launch more than 10 lookups at the same time
-#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 3)
currentLookups++;
QHostInfo::lookupHost(hostname, this, SLOT(lookedUp(QHostInfo)));
-#else
- // This code is only needed for Qt versions that do not have
- // the small Qt DNS cache yet.
-
- QTime* entryTime = lookupCache.object(hostname);
- if (entryTime && entryTime->elapsed() > 300*1000) {
- // delete knowledge about lookup if it is already 300 seconds old
- lookupCache.remove(hostname);
- } else if (!entryTime) {
- // not in cache yet, can look it up
- QTime *tmpTime = new QTime();
- *tmpTime = QTime::currentTime();
- lookupCache.insert(hostname, tmpTime);
- currentLookups++;
- QHostInfo::lookupHost(hostname, this, SLOT(lookedUp(QHostInfo)));
- }
-#endif
}
void lookedUp(const QHostInfo&)
@@ -74,9 +56,6 @@ namespace WebCore {
}
protected:
-#if QT_VERSION < QT_VERSION_CHECK(4, 6, 3)
- QCache<QString, QTime> lookupCache; // 100 entries
-#endif
int currentLookups;
};
diff --git a/Source/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h b/Source/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h
index 766dc90..4b8252c 100644
--- a/Source/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h
+++ b/Source/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h
@@ -22,15 +22,9 @@
#include <QObject>
-#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
-namespace QtMobility {
-class QNetworkConfigurationManager;
-}
-#else
QT_BEGIN_NAMESPACE
class QNetworkConfigurationManager;
QT_END_NAMESPACE
-#endif
namespace WebCore {
@@ -46,11 +40,7 @@ public slots:
void networkAccessPermissionChanged(bool);
public:
-#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
- QtMobility::QNetworkConfigurationManager* m_configurationManager;
-#else
QNetworkConfigurationManager* m_configurationManager;
-#endif
bool m_online;
bool m_networkAccessAllowed;
NetworkStateNotifier* m_notifier;
diff --git a/Source/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp b/Source/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp
index f3e7023..ced52eb 100644
--- a/Source/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp
+++ b/Source/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp
@@ -25,10 +25,6 @@
#include "NetworkStateNotifierPrivate.h"
#include "qnetworkconfigmanager.h"
-#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
-using namespace QtMobility;
-#endif
-
namespace WebCore {
NetworkStateNotifierPrivate::NetworkStateNotifierPrivate(NetworkStateNotifier* notifier)
diff --git a/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp b/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
index 61fe96c..6e63145 100644
--- a/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
+++ b/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
@@ -41,21 +41,11 @@
#include <QDebug>
#include <QCoreApplication>
-// What type of connection should be used for the signals of the
-// QNetworkReply? This depends on if Qt has a bugfix for this or not.
-// It is fixed in Qt 4.6.3. See https://bugs.webkit.org/show_bug.cgi?id=32113
-// and https://bugs.webkit.org/show_bug.cgi?id=36755
-#if QT_VERSION > QT_VERSION_CHECK(4, 6, 2)
-#define SIGNAL_CONN Qt::DirectConnection
-#else
-#define SIGNAL_CONN Qt::QueuedConnection
-#endif
-
// In Qt 4.8, the attribute for sending a request synchronously will be made public,
// for now, use this hackish solution for setting the internal attribute.
const QNetworkRequest::Attribute gSynchronousNetworkRequestAttribute = static_cast<QNetworkRequest::Attribute>(QNetworkRequest::HttpPipeliningWasUsedAttribute + 7);
-static const int gMaxRecursionLimit = 10;
+static const int gMaxRedirections = 10;
namespace WebCore {
@@ -159,6 +149,86 @@ bool FormDataIODevice::isSequential() const
return true;
}
+QNetworkReplyWrapper::QNetworkReplyWrapper(QNetworkReply* reply, QObject* parent)
+ : QObject(parent)
+ , m_reply(reply)
+{
+ Q_ASSERT(m_reply);
+
+ connect(m_reply, SIGNAL(metaDataChanged()), this, SLOT(receiveMetaData()));
+ connect(m_reply, SIGNAL(readyRead()), this, SLOT(receiveMetaData()));
+ connect(m_reply, SIGNAL(finished()), this, SLOT(receiveMetaData()));
+}
+
+QNetworkReplyWrapper::~QNetworkReplyWrapper()
+{
+ if (m_reply)
+ m_reply->deleteLater();
+}
+
+QNetworkReply* QNetworkReplyWrapper::release()
+{
+ if (!m_reply)
+ return 0;
+
+ resetConnections();
+ QNetworkReply* reply = m_reply;
+ m_reply = 0;
+ reply->setParent(0);
+ return reply;
+}
+
+void QNetworkReplyWrapper::resetConnections()
+{
+ if (m_reply)
+ m_reply->disconnect(this);
+ QCoreApplication::removePostedEvents(this, QEvent::MetaCall);
+}
+
+void QNetworkReplyWrapper::receiveMetaData()
+{
+ // This slot is only used to receive the first signal from the QNetworkReply object.
+ resetConnections();
+
+ m_redirectionTargetUrl = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
+ if (m_redirectionTargetUrl.isValid()) {
+ emit metaDataChanged();
+ emit finished();
+ return;
+ }
+
+ WTF::String contentType = m_reply->header(QNetworkRequest::ContentTypeHeader).toString();
+ m_encoding = extractCharsetFromMediaType(contentType);
+ m_advertisedMimeType = extractMIMETypeFromMediaType(contentType);
+
+ bool hasData = m_reply->bytesAvailable();
+ bool isFinished = m_reply->isFinished();
+
+ if (!isFinished) {
+ // If not finished, connect to the slots that will be used from this point on.
+ connect(m_reply, SIGNAL(readyRead()), this, SIGNAL(readyRead()));
+ connect(m_reply, SIGNAL(finished()), this, SLOT(didReceiveFinished()));
+ }
+
+ emit metaDataChanged();
+
+ if (hasData)
+ emit readyRead();
+
+ if (isFinished) {
+ emit finished();
+ return;
+ }
+
+}
+
+void QNetworkReplyWrapper::didReceiveFinished()
+{
+ // Disconnecting will make sure that nothing will happen after emitting the finished signal.
+ resetConnections();
+ emit finished();
+}
+
String QNetworkReplyHandler::httpMethod() const
{
switch (m_method) {
@@ -172,30 +242,24 @@ String QNetworkReplyHandler::httpMethod() const
return "PUT";
case QNetworkAccessManager::DeleteOperation:
return "DELETE";
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
case QNetworkAccessManager::CustomOperation:
return m_resourceHandle->firstRequest().httpMethod();
-#endif
default:
ASSERT_NOT_REACHED();
return "GET";
}
}
-QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadMode loadMode)
+QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadType loadType, bool deferred)
: QObject(0)
- , m_reply(0)
+ , m_replyWrapper(0)
, m_resourceHandle(handle)
- , m_redirected(false)
- , m_responseSent(false)
- , m_responseContainsData(false)
- , m_loadMode(loadMode)
- , m_shouldStart(true)
- , m_shouldFinish(false)
- , m_shouldSendResponse(false)
- , m_shouldForwardData(false)
- , m_redirectionTries(gMaxRecursionLimit)
+ , m_loadType(loadType)
+ , m_deferred(deferred)
+ , m_redirectionTries(gMaxRedirections)
{
+ resetState();
+
const ResourceRequest &r = m_resourceHandle->firstRequest();
if (r.httpMethod() == "GET")
@@ -208,13 +272,8 @@ QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadMode load
m_method = QNetworkAccessManager::PutOperation;
else if (r.httpMethod() == "DELETE")
m_method = QNetworkAccessManager::DeleteOperation;
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
else
m_method = QNetworkAccessManager::CustomOperation;
-#else
- else
- m_method = QNetworkAccessManager::UnknownOperation;
-#endif
QObject* originatingObject = 0;
if (m_resourceHandle->getInternal()->m_context)
@@ -222,40 +281,58 @@ QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadMode load
m_request = r.toNetworkRequest(originatingObject);
- if (m_loadMode == LoadSynchronously)
- m_request.setAttribute(gSynchronousNetworkRequestAttribute, true);
-
- if (m_loadMode == LoadNormal || m_loadMode == LoadSynchronously)
+ if (!m_deferred)
start();
+}
+
+void QNetworkReplyHandler::resetState()
+{
+ m_redirected = false;
+ m_responseSent = false;
+ m_responseContainsData = false;
+ m_hasStarted = false;
+ m_callFinishOnResume = false;
+ m_callSendResponseIfNeededOnResume = false;
+ m_callForwardDataOnResume = false;
+
+ if (m_replyWrapper) {
+ m_replyWrapper->deleteLater();
+ m_replyWrapper = 0;
+ }
+}
- if (m_loadMode == LoadSynchronously)
- m_loadMode = LoadNormal;
+void QNetworkReplyHandler::setLoadingDeferred(bool deferred)
+{
+ m_deferred = deferred;
+
+ if (!deferred)
+ resumeDeferredLoad();
}
-void QNetworkReplyHandler::setLoadMode(LoadMode mode)
+void QNetworkReplyHandler::resumeDeferredLoad()
{
- // https://bugs.webkit.org/show_bug.cgi?id=26556
- // We cannot call sendQueuedItems() from here, because the signal that
- // caused us to get into deferred mode, might not be processed yet.
- switch (mode) {
- case LoadNormal:
- m_loadMode = LoadResuming;
- emit processQueuedItems();
- break;
- case LoadDeferred:
- m_loadMode = LoadDeferred;
- break;
- case LoadResuming:
- Q_ASSERT(0); // should never happen
- break;
- };
+ if (!m_hasStarted) {
+ ASSERT(!m_callSendResponseIfNeededOnResume);
+ ASSERT(!m_callForwardDataOnResume);
+ ASSERT(!m_callFinishOnResume);
+ start();
+ return;
+ }
+
+ if (m_callSendResponseIfNeededOnResume)
+ sendResponseIfNeeded();
+
+ if (m_callForwardDataOnResume)
+ forwardData();
+
+ if (m_callFinishOnResume)
+ finish();
}
void QNetworkReplyHandler::abort()
{
m_resourceHandle = 0;
- if (m_reply) {
- QNetworkReply* reply = release();
+ if (QNetworkReply* reply = release()) {
reply->abort();
reply->deleteLater();
}
@@ -264,20 +341,16 @@ void QNetworkReplyHandler::abort()
QNetworkReply* QNetworkReplyHandler::release()
{
- QNetworkReply* reply = m_reply;
- if (m_reply) {
- disconnect(m_reply, 0, this, 0);
- // We have queued connections to the QNetworkReply. Make sure any
- // posted meta call events that were the result of a signal emission
- // don't reach the slots in our instance.
- QCoreApplication::removePostedEvents(this, QEvent::MetaCall);
- m_reply->setParent(0);
- m_reply = 0;
- }
+ if (!m_replyWrapper)
+ return 0;
+
+ QNetworkReply* reply = m_replyWrapper->release();
+ m_replyWrapper->deleteLater();
+ m_replyWrapper = 0;
return reply;
}
-static bool ignoreHttpError(QNetworkReply* reply, bool receivedData)
+static bool shouldIgnoreHttpError(QNetworkReply* reply, bool receivedData)
{
int httpStatusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
@@ -292,66 +365,73 @@ static bool ignoreHttpError(QNetworkReply* reply, bool receivedData)
void QNetworkReplyHandler::finish()
{
- m_shouldFinish = (m_loadMode != LoadNormal);
- if (m_shouldFinish)
+ ASSERT(m_hasStarted);
+
+ m_callFinishOnResume = m_deferred;
+ if (m_deferred)
return;
- if (!m_reply)
+ if (!m_replyWrapper || !m_replyWrapper->reply())
return;
+
sendResponseIfNeeded();
- if (!m_resourceHandle)
+ if (wasAborted())
return;
+
ResourceHandleClient* client = m_resourceHandle->client();
if (!client) {
- m_reply->deleteLater();
- m_reply = 0;
+ m_replyWrapper->deleteLater();
+ m_replyWrapper = 0;
return;
}
- if (!m_redirected) {
- if (!m_reply->error() || ignoreHttpError(m_reply, m_responseContainsData))
- client->didFinishLoading(m_resourceHandle, 0);
- else {
- QUrl url = m_reply->url();
- int httpStatusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
-
- if (httpStatusCode) {
- ResourceError error("HTTP", httpStatusCode, url.toString(), m_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString());
- client->didFail(m_resourceHandle, error);
- } else {
- ResourceError error("QtNetwork", m_reply->error(), url.toString(), m_reply->errorString());
- client->didFail(m_resourceHandle, error);
- }
- }
- if (m_reply) {
- m_reply->deleteLater();
- m_reply = 0;
- }
- } else {
- if (m_reply) {
- m_reply->deleteLater();
- m_reply = 0;
- }
+ if (m_redirected) {
resetState();
start();
+ return;
+ }
+
+ if (!m_replyWrapper->reply()->error() || shouldIgnoreHttpError(m_replyWrapper->reply(), m_responseContainsData))
+ client->didFinishLoading(m_resourceHandle, 0);
+ else {
+ QUrl url = m_replyWrapper->reply()->url();
+ int httpStatusCode = m_replyWrapper->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+
+ if (httpStatusCode) {
+ ResourceError error("HTTP", httpStatusCode, url.toString(), m_replyWrapper->reply()->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString());
+ client->didFail(m_resourceHandle, error);
+ } else {
+ ResourceError error("QtNetwork", m_replyWrapper->reply()->error(), url.toString(), m_replyWrapper->reply()->errorString());
+ client->didFail(m_resourceHandle, error);
+ }
+ }
+
+ if (m_replyWrapper) {
+ m_replyWrapper->deleteLater();
+ m_replyWrapper = 0;
}
}
void QNetworkReplyHandler::sendResponseIfNeeded()
{
- m_shouldSendResponse = (m_loadMode != LoadNormal);
- if (m_shouldSendResponse)
+ ASSERT(m_hasStarted);
+
+ m_callSendResponseIfNeededOnResume = m_deferred;
+ if (m_deferred)
return;
- if (!m_reply)
+ if (!m_replyWrapper || !m_replyWrapper->reply())
return;
- if (m_reply->error() && !ignoreHttpError(m_reply, m_responseContainsData))
+ if (m_replyWrapper->reply()->error() && !shouldIgnoreHttpError(m_replyWrapper->reply(), m_responseContainsData))
return;
- if (m_responseSent || !m_resourceHandle)
+ if (wasAborted())
+ return;
+
+ if (m_responseSent)
return;
m_responseSent = true;
@@ -359,18 +439,18 @@ void QNetworkReplyHandler::sendResponseIfNeeded()
if (!client)
return;
- WTF::String contentType = m_reply->header(QNetworkRequest::ContentTypeHeader).toString();
+ WTF::String contentType = m_replyWrapper->reply()->header(QNetworkRequest::ContentTypeHeader).toString();
WTF::String encoding = extractCharsetFromMediaType(contentType);
WTF::String mimeType = extractMIMETypeFromMediaType(contentType);
if (mimeType.isEmpty()) {
// let's try to guess from the extension
- mimeType = MIMETypeRegistry::getMIMETypeForPath(m_reply->url().path());
+ mimeType = MIMETypeRegistry::getMIMETypeForPath(m_replyWrapper->reply()->url().path());
}
- KURL url(m_reply->url());
+ KURL url(m_replyWrapper->reply()->url());
ResourceResponse response(url, mimeType.lower(),
- m_reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(),
+ m_replyWrapper->reply()->header(QNetworkRequest::ContentLengthHeader).toLongLong(),
encoding, String());
if (url.isLocalFile()) {
@@ -379,10 +459,10 @@ void QNetworkReplyHandler::sendResponseIfNeeded()
}
// The status code is equal to 0 for protocols not in the HTTP family.
- int statusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ int statusCode = m_replyWrapper->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (url.protocolInHTTPFamily()) {
- String suggestedFilename = filenameFromHTTPContentDisposition(QString::fromAscii(m_reply->rawHeader("Content-Disposition")));
+ String suggestedFilename = filenameFromHTTPContentDisposition(QString::fromLatin1(m_replyWrapper->reply()->rawHeader("Content-Disposition")));
if (!suggestedFilename.isEmpty())
response.setSuggestedFilename(suggestedFilename);
@@ -390,70 +470,79 @@ void QNetworkReplyHandler::sendResponseIfNeeded()
response.setSuggestedFilename(url.lastPathComponent());
response.setHTTPStatusCode(statusCode);
- response.setHTTPStatusText(m_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray().constData());
+ response.setHTTPStatusText(m_replyWrapper->reply()->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray().constData());
// Add remaining headers.
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
- foreach (const QNetworkReply::RawHeaderPair& pair, m_reply->rawHeaderPairs())
- response.setHTTPHeaderField(QString::fromAscii(pair.first), QString::fromAscii(pair.second));
-#else
- foreach (const QByteArray& headerName, m_reply->rawHeaderList())
- response.setHTTPHeaderField(QString::fromAscii(headerName), QString::fromAscii(m_reply->rawHeader(headerName)));
-#endif
+ foreach (const QNetworkReply::RawHeaderPair& pair, m_replyWrapper->reply()->rawHeaderPairs())
+ response.setHTTPHeaderField(QString::fromLatin1(pair.first), QString::fromLatin1(pair.second));
}
- QUrl redirection = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
+ QUrl redirection = m_replyWrapper->reply()->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
if (redirection.isValid()) {
- QUrl newUrl = m_reply->url().resolved(redirection);
+ redirect(response, redirection);
+ return;
+ }
- m_redirectionTries--;
- if (m_redirectionTries == 0) { // 10 or more redirections to the same url is considered infinite recursion
- ResourceError error(newUrl.host(), 400 /*bad request*/,
- newUrl.toString(),
- QCoreApplication::translate("QWebPage", "Redirection limit reached"));
- client->didFail(m_resourceHandle, error);
- return;
- }
- m_redirected = true;
+ client->didReceiveResponse(m_resourceHandle, response);
+}
+void QNetworkReplyHandler::redirect(ResourceResponse& response, const QUrl& redirection)
+{
+ QUrl newUrl = m_replyWrapper->reply()->url().resolved(redirection);
- // Status Code 301 (Moved Permanently), 302 (Moved Temporarily), 303 (See Other):
- // - If original request is POST convert to GET and redirect automatically
- // Status Code 307 (Temporary Redirect) and all other redirect status codes:
- // - Use the HTTP method from the previous request
- if ((statusCode >= 301 && statusCode <= 303) && m_resourceHandle->firstRequest().httpMethod() == "POST")
- m_method = QNetworkAccessManager::GetOperation;
+ ResourceHandleClient* client = m_resourceHandle->client();
+ ASSERT(client);
+
+ int statusCode = m_replyWrapper->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
- ResourceRequest newRequest = m_resourceHandle->firstRequest();
- newRequest.setHTTPMethod(httpMethod());
- newRequest.setURL(newUrl);
+ m_redirectionTries--;
+ if (!m_redirectionTries) {
+ ResourceError error(newUrl.host(), 400 /*bad request*/,
+ newUrl.toString(),
+ QCoreApplication::translate("QWebPage", "Redirection limit reached"));
+ client->didFail(m_resourceHandle, error);
+ return;
+ }
+ m_redirected = true;
- // Should not set Referer after a redirect from a secure resource to non-secure one.
- if (!newRequest.url().protocolIs("https") && protocolIs(newRequest.httpReferrer(), "https"))
- newRequest.clearHTTPReferrer();
+ // Status Code 301 (Moved Permanently), 302 (Moved Temporarily), 303 (See Other):
+ // - If original request is POST convert to GET and redirect automatically
+ // Status Code 307 (Temporary Redirect) and all other redirect status codes:
+ // - Use the HTTP method from the previous request
+ if ((statusCode >= 301 && statusCode <= 303) && m_resourceHandle->firstRequest().httpMethod() == "POST")
+ m_method = QNetworkAccessManager::GetOperation;
- client->willSendRequest(m_resourceHandle, newRequest, response);
- if (!m_resourceHandle) // network error did cancel the request
- return;
+ ResourceRequest newRequest = m_resourceHandle->firstRequest();
+ newRequest.setHTTPMethod(httpMethod());
+ newRequest.setURL(newUrl);
- QObject* originatingObject = 0;
- if (m_resourceHandle->getInternal()->m_context)
- originatingObject = m_resourceHandle->getInternal()->m_context->originatingObject();
+ // Should not set Referer after a redirect from a secure resource to non-secure one.
+ if (!newRequest.url().protocolIs("https") && protocolIs(newRequest.httpReferrer(), "https"))
+ newRequest.clearHTTPReferrer();
- m_request = newRequest.toNetworkRequest(originatingObject);
+ client->willSendRequest(m_resourceHandle, newRequest, response);
+ if (wasAborted()) // Network error cancelled the request.
return;
- }
- client->didReceiveResponse(m_resourceHandle, response);
+ QObject* originatingObject = 0;
+ if (m_resourceHandle->getInternal()->m_context)
+ originatingObject = m_resourceHandle->getInternal()->m_context->originatingObject();
+
+ m_request = newRequest.toNetworkRequest(originatingObject);
}
void QNetworkReplyHandler::forwardData()
{
- m_shouldForwardData = (m_loadMode != LoadNormal);
- if (m_shouldForwardData)
+ ASSERT(m_hasStarted);
+
+ m_callForwardDataOnResume = m_deferred;
+ if (m_deferred)
return;
- if (m_reply->bytesAvailable())
+ if (!m_replyWrapper || !m_replyWrapper->reply())
+ return;
+
+ if (m_replyWrapper->reply()->bytesAvailable())
m_responseContainsData = true;
sendResponseIfNeeded();
@@ -462,22 +551,25 @@ void QNetworkReplyHandler::forwardData()
if (m_redirected)
return;
- if (!m_resourceHandle)
+ if (wasAborted())
return;
- QByteArray data = m_reply->read(m_reply->bytesAvailable());
+ QByteArray data = m_replyWrapper->reply()->read(m_replyWrapper->reply()->bytesAvailable());
ResourceHandleClient* client = m_resourceHandle->client();
if (!client)
return;
+ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=19793
+ // -1 means we do not provide any data about transfer size to inspector so it would use
+ // Content-Length headers or content size to show transfer size.
if (!data.isEmpty())
- client->didReceiveData(m_resourceHandle, data.constData(), data.length(), data.length() /*FixMe*/);
+ client->didReceiveData(m_resourceHandle, data.constData(), data.length(), -1);
}
void QNetworkReplyHandler::uploadProgress(qint64 bytesSent, qint64 bytesTotal)
{
- if (!m_resourceHandle)
+ if (wasAborted())
return;
ResourceHandleClient* client = m_resourceHandle->client();
@@ -487,9 +579,10 @@ void QNetworkReplyHandler::uploadProgress(qint64 bytesSent, qint64 bytesTotal)
client->didSendData(m_resourceHandle, bytesSent, bytesTotal);
}
-void QNetworkReplyHandler::start()
+QNetworkReply* QNetworkReplyHandler::sendNetworkRequest()
{
- m_shouldStart = false;
+ if (m_loadType == SynchronousLoad)
+ m_request.setAttribute(gSynchronousNetworkRequestAttribute, true);
ResourceHandleInternal* d = m_resourceHandle->getInternal();
@@ -498,7 +591,7 @@ void QNetworkReplyHandler::start()
manager = d->m_context->networkAccessManager();
if (!manager)
- return;
+ return 0;
const QUrl url = m_request.url();
const QString scheme = url.scheme();
@@ -511,108 +604,61 @@ void QNetworkReplyHandler::start()
switch (m_method) {
case QNetworkAccessManager::GetOperation:
- m_reply = manager->get(m_request);
- break;
+ return manager->get(m_request);
case QNetworkAccessManager::PostOperation: {
- FormDataIODevice* postDevice = new FormDataIODevice(d->m_firstRequest.httpBody());
+ FormDataIODevice* postDevice = new FormDataIODevice(d->m_firstRequest.httpBody());
// We may be uploading files so prevent QNR from buffering data
m_request.setHeader(QNetworkRequest::ContentLengthHeader, postDevice->getFormDataSize());
m_request.setAttribute(QNetworkRequest::DoNotBufferUploadDataAttribute, QVariant(true));
- m_reply = manager->post(m_request, postDevice);
- postDevice->setParent(m_reply);
- break;
+ QNetworkReply* result = manager->post(m_request, postDevice);
+ postDevice->setParent(result);
+ return result;
}
case QNetworkAccessManager::HeadOperation:
- m_reply = manager->head(m_request);
- break;
+ return manager->head(m_request);
case QNetworkAccessManager::PutOperation: {
- FormDataIODevice* putDevice = new FormDataIODevice(d->m_firstRequest.httpBody());
+ FormDataIODevice* putDevice = new FormDataIODevice(d->m_firstRequest.httpBody());
// We may be uploading files so prevent QNR from buffering data
m_request.setHeader(QNetworkRequest::ContentLengthHeader, putDevice->getFormDataSize());
m_request.setAttribute(QNetworkRequest::DoNotBufferUploadDataAttribute, QVariant(true));
- m_reply = manager->put(m_request, putDevice);
- putDevice->setParent(m_reply);
- break;
+ QNetworkReply* result = manager->put(m_request, putDevice);
+ putDevice->setParent(result);
+ return result;
}
case QNetworkAccessManager::DeleteOperation: {
- m_reply = manager->deleteResource(m_request);
- break;
+ return manager->deleteResource(m_request);
}
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
case QNetworkAccessManager::CustomOperation:
- m_reply = manager->sendCustomRequest(m_request, m_resourceHandle->firstRequest().httpMethod().latin1().data());
- break;
-#endif
- case QNetworkAccessManager::UnknownOperation: {
- m_reply = 0;
- ResourceHandleClient* client = m_resourceHandle->client();
- if (client) {
- ResourceError error(url.host(), 400 /*bad request*/,
- url.toString(),
- QCoreApplication::translate("QWebPage", "Bad HTTP request"));
- client->didFail(m_resourceHandle, error);
- }
- return;
- }
- }
-
- m_reply->setParent(this);
-
- if (m_loadMode == LoadSynchronously && m_reply->isFinished()) {
- // If supported, a synchronous request will be finished at this point, no need to hook up the signals.
- return;
- }
-
- connect(m_reply, SIGNAL(finished()),
- this, SLOT(finish()), SIGNAL_CONN);
-
- // For http(s) we know that the headers are complete upon metaDataChanged() emission, so we
- // can send the response as early as possible
- if (scheme == QLatin1String("http") || scheme == QLatin1String("https"))
- connect(m_reply, SIGNAL(metaDataChanged()),
- this, SLOT(sendResponseIfNeeded()), SIGNAL_CONN);
-
- connect(m_reply, SIGNAL(readyRead()),
- this, SLOT(forwardData()), SIGNAL_CONN);
-
- if (m_resourceHandle->firstRequest().reportUploadProgress()) {
- connect(m_reply, SIGNAL(uploadProgress(qint64, qint64)),
- this, SLOT(uploadProgress(qint64, qint64)), SIGNAL_CONN);
+ return manager->sendCustomRequest(m_request, m_resourceHandle->firstRequest().httpMethod().latin1().data());
+ case QNetworkAccessManager::UnknownOperation:
+ ASSERT_NOT_REACHED();
+ return 0;
}
-
- // Make this a direct function call once we require 4.6.1+.
- connect(this, SIGNAL(processQueuedItems()),
- this, SLOT(sendQueuedItems()), SIGNAL_CONN);
+ return 0;
}
-void QNetworkReplyHandler::resetState()
+void QNetworkReplyHandler::start()
{
- m_redirected = false;
- m_responseSent = false;
- m_responseContainsData = false;
- m_shouldStart = true;
- m_shouldFinish = false;
- m_shouldSendResponse = false;
- m_shouldForwardData = false;
-}
+ ASSERT(!m_hasStarted);
+ m_hasStarted = true;
-void QNetworkReplyHandler::sendQueuedItems()
-{
- if (m_loadMode != LoadResuming)
+ QNetworkReply* reply = sendNetworkRequest();
+ if (!reply)
return;
- m_loadMode = LoadNormal;
- if (m_shouldStart)
- start();
+ m_replyWrapper = new QNetworkReplyWrapper(reply, this);
- if (m_shouldSendResponse)
- sendResponseIfNeeded();
+ if (m_loadType == SynchronousLoad && m_replyWrapper->reply()->isFinished()) {
+ // If supported, a synchronous request will be finished at this point, no need to hook up the signals.
+ return;
+ }
- if (m_shouldForwardData)
- forwardData();
+ connect(m_replyWrapper, SIGNAL(finished()), this, SLOT(finish()));
+ connect(m_replyWrapper, SIGNAL(metaDataChanged()), this, SLOT(sendResponseIfNeeded()));
+ connect(m_replyWrapper, SIGNAL(readyRead()), this, SLOT(forwardData()));
- if (m_shouldFinish)
- finish();
+ if (m_resourceHandle->firstRequest().reportUploadProgress())
+ connect(m_replyWrapper->reply(), SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(uploadProgress(qint64, qint64)));
}
}
diff --git a/Source/WebCore/platform/network/qt/QNetworkReplyHandler.h b/Source/WebCore/platform/network/qt/QNetworkReplyHandler.h
index 8c9bd08..61694d6 100644
--- a/Source/WebCore/platform/network/qt/QNetworkReplyHandler.h
+++ b/Source/WebCore/platform/network/qt/QNetworkReplyHandler.h
@@ -34,56 +34,90 @@ QT_END_NAMESPACE
namespace WebCore {
class ResourceHandle;
+class ResourceResponse;
+
+class QNetworkReplyWrapper : public QObject {
+ Q_OBJECT
+public:
+ QNetworkReplyWrapper(QNetworkReply*, QObject* parent = 0);
+ ~QNetworkReplyWrapper();
+
+ QNetworkReply* reply() const { return m_reply; }
+ QNetworkReply* release();
+
+ QUrl redirectionTargetUrl() const { return m_redirectionTargetUrl; }
+ QString encoding() const { return m_encoding; }
+ QString advertisedMimeType() const { return m_advertisedMimeType; }
+
+Q_SIGNALS:
+ void finished();
+ void metaDataChanged();
+ void readyRead();
+ void uploadProgress(qint64 bytesSent, qint64 bytesTotal);
+
+private Q_SLOTS:
+ void receiveMetaData();
+ void didReceiveFinished();
+
+private:
+ void resetConnections();
+
+ QNetworkReply* m_reply;
+ QUrl m_redirectionTargetUrl;
+
+ QString m_encoding;
+ QString m_advertisedMimeType;
+};
class QNetworkReplyHandler : public QObject
{
Q_OBJECT
public:
- enum LoadMode {
- LoadNormal,
- LoadDeferred,
- LoadResuming,
- LoadSynchronously
+ enum LoadType {
+ AsynchronousLoad,
+ SynchronousLoad
};
- QNetworkReplyHandler(ResourceHandle *handle, LoadMode);
- void setLoadMode(LoadMode);
+ QNetworkReplyHandler(ResourceHandle*, LoadType, bool deferred = false);
+ void setLoadingDeferred(bool);
- QNetworkReply* reply() const { return m_reply; }
+ QNetworkReply* reply() const { return m_replyWrapper ? m_replyWrapper->reply() : 0; }
void abort();
QNetworkReply* release();
-signals:
- void processQueuedItems();
-
public slots:
void finish();
void sendResponseIfNeeded();
void forwardData();
- void sendQueuedItems();
void uploadProgress(qint64 bytesSent, qint64 bytesTotal);
private:
void start();
void resetState();
String httpMethod() const;
+ void resumeDeferredLoad();
+ void redirect(ResourceResponse&, const QUrl&);
+ bool wasAborted() const { return !m_resourceHandle; }
+ QNetworkReply* sendNetworkRequest();
- QNetworkReply* m_reply;
+ QNetworkReplyWrapper* m_replyWrapper;
ResourceHandle* m_resourceHandle;
bool m_redirected;
bool m_responseSent;
bool m_responseContainsData;
- LoadMode m_loadMode;
+ LoadType m_loadType;
QNetworkAccessManager::Operation m_method;
QNetworkRequest m_request;
+ bool m_deferred;
+
// defer state holding
- bool m_shouldStart;
- bool m_shouldFinish;
- bool m_shouldSendResponse;
- bool m_shouldForwardData;
+ bool m_hasStarted;
+ bool m_callFinishOnResume;
+ bool m_callSendResponseIfNeededOnResume;
+ bool m_callForwardDataOnResume;
int m_redirectionTries;
};
diff --git a/Source/WebCore/platform/network/qt/ResourceHandleQt.cpp b/Source/WebCore/platform/network/qt/ResourceHandleQt.cpp
index cd17660..a6da432 100644
--- a/Source/WebCore/platform/network/qt/ResourceHandleQt.cpp
+++ b/Source/WebCore/platform/network/qt/ResourceHandleQt.cpp
@@ -42,9 +42,6 @@
#include "ResourceHandleInternal.h"
#include "SharedBuffer.h"
-// FIXME: WebCore including these headers from WebKit is a massive layering violation.
-#include "qwebframe_p.h"
-
#include <QAbstractNetworkCache>
#include <QCoreApplication>
#include <QUrl>
@@ -140,7 +137,7 @@ bool ResourceHandle::start(NetworkingContext* context)
getInternal()->m_context = context;
ResourceHandleInternal *d = getInternal();
- d->m_job = new QNetworkReplyHandler(this, QNetworkReplyHandler::LoadMode(d->m_defersLoading));
+ d->m_job = new QNetworkReplyHandler(this, QNetworkReplyHandler::AsynchronousLoad, d->m_defersLoading);
return true;
}
@@ -207,7 +204,7 @@ void ResourceHandle::loadResourceSynchronously(NetworkingContext* context, const
d->m_firstRequest.setURL(urlWithCredentials);
}
d->m_context = context;
- d->m_job = new QNetworkReplyHandler(handle.get(), QNetworkReplyHandler::LoadSynchronously);
+ d->m_job = new QNetworkReplyHandler(handle.get(), QNetworkReplyHandler::SynchronousLoad);
QNetworkReply* reply = d->m_job->reply();
// When using synchronous calls, we are finished when reaching this point.
@@ -225,8 +222,9 @@ void ResourceHandle::loadResourceSynchronously(NetworkingContext* context, const
void ResourceHandle::platformSetDefersLoading(bool defers)
{
- if (d->m_job)
- d->m_job->setLoadMode(QNetworkReplyHandler::LoadMode(defers));
+ if (!d->m_job)
+ return;
+ d->m_job->setLoadingDeferred(defers);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp b/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp
index 7e162ed..498c90a 100644
--- a/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp
+++ b/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp
@@ -83,13 +83,11 @@ QNetworkRequest ResourceRequest::toNetworkRequest(QObject* originatingFrame) con
break;
}
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
if (!allowCookies()) {
request.setAttribute(QNetworkRequest::CookieLoadControlAttribute, QNetworkRequest::Manual);
request.setAttribute(QNetworkRequest::CookieSaveControlAttribute, QNetworkRequest::Manual);
request.setAttribute(QNetworkRequest::AuthenticationReuseAttribute, QNetworkRequest::Manual);
}
-#endif
return request;
}
diff --git a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
index d410fa3..e5da0e3 100644
--- a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
+++ b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
@@ -364,7 +364,10 @@ static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data)
ASSERT(!d->m_response.isNull());
- client->didReceiveData(handle.get(), chunk->data, chunk->length, chunk->length);
+ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=19793
+ // -1 means we do not provide any data about transfer size to inspector so it would use
+ // Content-Length headers or content size to show transfer size.
+ client->didReceiveData(handle.get(), chunk->data, chunk->length, -1);
}
static SoupSession* createSoupSession()
diff --git a/Source/WebCore/platform/network/win/ResourceHandleWin.cpp b/Source/WebCore/platform/network/win/ResourceHandleWin.cpp
index f50540c..dc5adc8 100644
--- a/Source/WebCore/platform/network/win/ResourceHandleWin.cpp
+++ b/Source/WebCore/platform/network/win/ResourceHandleWin.cpp
@@ -242,8 +242,11 @@ bool ResourceHandle::onRequestComplete()
resourceHandleClient->didReceiveResponse(this, response);
}
+ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=19793
+ // -1 means we do not provide any data about transfer size to inspector so it would use
+ // Content-Length headers or content size to show transfer size.
if (ResourceHandleClient* resourceHandleClient = client())
- resourceHandleClient->didReceiveData(this, buffer, buffers.dwBufferLength, 0);
+ resourceHandleClient->didReceiveData(this, buffer, buffers.dwBufferLength, -1);
buffers.dwBufferLength = bufferSize;
}
@@ -385,8 +388,11 @@ void ResourceHandle::fileLoadTimer(Timer<ResourceHandle>*)
const int bufferSize = 8192;
char buffer[bufferSize];
result = ReadFile(fileHandle, &buffer, bufferSize, &bytesRead, 0);
+ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=19793
+ // -1 means we do not provide any data about transfer size to inspector so it would use
+ // Content-Length headers or content size to show transfer size.
if (result && bytesRead)
- client()->didReceiveData(this, buffer, bytesRead, 0);
+ client()->didReceiveData(this, buffer, bytesRead, -1);
// Check for end of file.
} while (result && bytesRead);
diff --git a/Source/WebCore/platform/posix/FileSystemPOSIX.cpp b/Source/WebCore/platform/posix/FileSystemPOSIX.cpp
index c035310..9ad5f3a 100644
--- a/Source/WebCore/platform/posix/FileSystemPOSIX.cpp
+++ b/Source/WebCore/platform/posix/FileSystemPOSIX.cpp
@@ -30,6 +30,7 @@
#include "FileSystem.h"
#include "PlatformString.h"
+<<<<<<< HEAD
#ifdef ANDROID_PLUGINS
#include <dirent.h>
#endif
@@ -38,6 +39,12 @@
#ifdef ANDROID_PLUGINS
#include <fnmatch.h>
#endif
+=======
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+>>>>>>> webkit.org at r82507
#include <libgen.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -235,10 +242,30 @@ String directoryName(const String& path)
return dirname(fsRep.mutableData());
}
-// OK to not implement listDirectory at the moment, because it's only used for plug-ins, and
-// all platforms that use the shared plug-in implementation have implementations. We'd need
-// to implement it if we wanted to use PluginDatabase.cpp on the Mac. Better to not implement
-// at all and get a link error in case this arises, rather than having a stub here, because
-// with a stub you learn about the problem at runtime instead of link time.
+#if !PLATFORM(EFL)
+Vector<String> listDirectory(const String& path, const String& filter)
+{
+ Vector<String> entries;
+ CString cpath = path.utf8();
+ CString cfilter = filter.utf8();
+ DIR* dir = opendir(cpath.data());
+ if (dir) {
+ struct dirent* dp;
+ while ((dp = readdir(dir))) {
+ const char* name = dp->d_name;
+ if (!strcmp(name, ".") || !strcmp(name, ".."))
+ continue;
+ if (fnmatch(cfilter.data(), name, 0))
+ continue;
+ char filePath[1024];
+ if (static_cast<int>(sizeof(filePath) - 1) < snprintf(filePath, sizeof(filePath), "%s/%s", cpath.data(), name))
+ continue; // buffer overflow
+ entries.append(filePath);
+ }
+ closedir(dir);
+ }
+ return entries;
+}
+#endif
} // namespace WebCore
diff --git a/Source/WebCore/platform/qt/CookieJarQt.cpp b/Source/WebCore/platform/qt/CookieJarQt.cpp
index db4a42a..3c4cd42 100644
--- a/Source/WebCore/platform/qt/CookieJarQt.cpp
+++ b/Source/WebCore/platform/qt/CookieJarQt.cpp
@@ -91,8 +91,7 @@ String cookies(const Document* document, const KURL& url)
foreach (QNetworkCookie networkCookie, cookies) {
if (networkCookie.isHttpOnly())
continue;
- resultCookies.append(QString::fromAscii(
- networkCookie.toRawForm(QNetworkCookie::NameAndValueOnly).constData()));
+ resultCookies.append(QString::fromLatin1(networkCookie.toRawForm(QNetworkCookie::NameAndValueOnly).constData()));
}
return resultCookies.join(QLatin1String("; "));
@@ -110,10 +109,8 @@ String cookieRequestHeaderFieldValue(const Document* document, const KURL &url)
return String();
QStringList resultCookies;
- foreach (QNetworkCookie networkCookie, cookies) {
- resultCookies.append(QString::fromAscii(
- networkCookie.toRawForm(QNetworkCookie::NameAndValueOnly).constData()));
- }
+ foreach (QNetworkCookie networkCookie, cookies)
+ resultCookies.append(QString::fromLatin1(networkCookie.toRawForm(QNetworkCookie::NameAndValueOnly).constData()));
return resultCookies.join(QLatin1String("; "));
}
diff --git a/Source/WebCore/platform/qt/FileSystemQt.cpp b/Source/WebCore/platform/qt/FileSystemQt.cpp
index d88a967..32644d1 100644
--- a/Source/WebCore/platform/qt/FileSystemQt.cpp
+++ b/Source/WebCore/platform/qt/FileSystemQt.cpp
@@ -114,19 +114,19 @@ Vector<String> listDirectory(const String& path, const String& filter)
return entries;
}
-CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
+String openTemporaryFile(const String& prefix, PlatformFileHandle& handle)
{
#ifndef QT_NO_TEMPORARYFILE
- QTemporaryFile* tempFile = new QTemporaryFile(QDir::tempPath() + QLatin1Char('/') + QLatin1String(prefix));
+ QTemporaryFile* tempFile = new QTemporaryFile(QDir::tempPath() + QLatin1Char('/') + QString(prefix));
tempFile->setAutoRemove(false);
QFile* temp = tempFile;
if (temp->open(QIODevice::ReadWrite)) {
handle = temp;
- return String(temp->fileName()).utf8();
+ return temp->fileName();
}
#endif
handle = invalidPlatformFileHandle;
- return CString();
+ return String();
}
PlatformFileHandle openFile(const String& path, FileOpenMode mode)
diff --git a/Source/WebCore/platform/qt/LanguageQt.cpp b/Source/WebCore/platform/qt/LanguageQt.cpp
index 71e554f..5a1d707 100644
--- a/Source/WebCore/platform/qt/LanguageQt.cpp
+++ b/Source/WebCore/platform/qt/LanguageQt.cpp
@@ -35,7 +35,7 @@ namespace WebCore {
String platformDefaultLanguage()
{
QLocale locale;
- return locale.name().replace("_", "-");
+ return locale.name().replace(QLatin1Char('_'), QLatin1Char('-'));
}
}
diff --git a/Source/WebCore/platform/qt/PasteboardQt.cpp b/Source/WebCore/platform/qt/PasteboardQt.cpp
index 6865fd7..850d68a 100644
--- a/Source/WebCore/platform/qt/PasteboardQt.cpp
+++ b/Source/WebCore/platform/qt/PasteboardQt.cpp
@@ -77,7 +77,7 @@ void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete,
QApplication::clipboard()->setMimeData(md, m_selectionMode ? QClipboard::Selection : QClipboard::Clipboard);
#endif
if (canSmartCopyOrDelete)
- md->setData("application/vnd.qtwebkit.smartpaste", QByteArray());
+ md->setData(QLatin1String("application/vnd.qtwebkit.smartpaste"), QByteArray());
}
bool Pasteboard::canSmartReplace()
diff --git a/Source/WebCore/platform/qt/RenderThemeQt.cpp b/Source/WebCore/platform/qt/RenderThemeQt.cpp
index ca8c6dd..cc654d5 100644
--- a/Source/WebCore/platform/qt/RenderThemeQt.cpp
+++ b/Source/WebCore/platform/qt/RenderThemeQt.cpp
@@ -1368,7 +1368,6 @@ bool RenderThemeQt::paintMediaSliderTrack(RenderObject* o, const PaintInfo& pain
paintMediaBackground(p.painter, r);
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
if (MediaPlayer* player = mediaElement->player()) {
// Get the buffered parts of the media
PassRefPtr<TimeRanges> buffered = player->buffered();
@@ -1386,7 +1385,6 @@ bool RenderThemeQt::paintMediaSliderTrack(RenderObject* o, const PaintInfo& pain
}
}
}
-#endif
return false;
}
diff --git a/Source/WebCore/platform/text/BidiContext.cpp b/Source/WebCore/platform/text/BidiContext.cpp
index fb6b8cf..f507514 100644
--- a/Source/WebCore/platform/text/BidiContext.cpp
+++ b/Source/WebCore/platform/text/BidiContext.cpp
@@ -21,48 +21,80 @@
#include "config.h"
#include "BidiContext.h"
+#include <wtf/Vector.h>
namespace WebCore {
using namespace WTF::Unicode;
-inline PassRefPtr<BidiContext> BidiContext::createUncached(unsigned char level, Direction direction, bool override, BidiContext* parent)
+inline PassRefPtr<BidiContext> BidiContext::createUncached(unsigned char level, Direction direction, bool override, BidiEmbeddingSource source, BidiContext* parent)
{
- return adoptRef(new BidiContext(level, direction, override, parent));
+ return adoptRef(new BidiContext(level, direction, override, source, parent));
}
-PassRefPtr<BidiContext> BidiContext::create(unsigned char level, Direction direction, bool override, BidiContext* parent)
+PassRefPtr<BidiContext> BidiContext::create(unsigned char level, Direction direction, bool override, BidiEmbeddingSource source, BidiContext* parent)
{
ASSERT(direction == (level % 2 ? RightToLeft : LeftToRight));
if (parent)
- return createUncached(level, direction, override, parent);
+ return createUncached(level, direction, override, source, parent);
ASSERT(level <= 1);
if (!level) {
if (!override) {
- static BidiContext* ltrContext = createUncached(0, LeftToRight, false, 0).releaseRef();
+ static BidiContext* ltrContext = createUncached(0, LeftToRight, false, FromStyleOrDOM, 0).releaseRef();
return ltrContext;
}
- static BidiContext* ltrOverrideContext = createUncached(0, LeftToRight, true, 0).releaseRef();
+ static BidiContext* ltrOverrideContext = createUncached(0, LeftToRight, true, FromStyleOrDOM, 0).releaseRef();
return ltrOverrideContext;
}
if (!override) {
- static BidiContext* rtlContext = createUncached(1, RightToLeft, false, 0).releaseRef();
+ static BidiContext* rtlContext = createUncached(1, RightToLeft, false, FromStyleOrDOM, 0).releaseRef();
return rtlContext;
}
- static BidiContext* rtlOverrideContext = createUncached(1, RightToLeft, true, 0).releaseRef();
+ static BidiContext* rtlOverrideContext = createUncached(1, RightToLeft, true, FromStyleOrDOM, 0).releaseRef();
return rtlOverrideContext;
}
+static inline PassRefPtr<BidiContext> copyContextAndRebaselineLevel(BidiContext* context, BidiContext* parent)
+{
+ ASSERT(context);
+ unsigned char newLevel = parent ? parent->level() : 0;
+ if (context->dir() == RightToLeft)
+ newLevel = nextGreaterOddLevel(newLevel);
+ else if (parent)
+ newLevel = nextGreaterEvenLevel(newLevel);
+
+ return BidiContext::create(newLevel, context->dir(), context->override(), context->source(), parent);
+}
+
+// The BidiContext stack must be immutable -- they're re-used for re-layout after
+// DOM modification/editing -- so we copy all the non-unicode contexts, and
+// recalculate their levels.
+PassRefPtr<BidiContext> BidiContext::copyStackRemovingUnicodeEmbeddingContexts()
+{
+ Vector<BidiContext*, 64> contexts;
+ for (BidiContext* iter = this; iter; iter = iter->parent()) {
+ if (iter->source() != FromUnicode)
+ contexts.append(iter);
+ }
+ ASSERT(contexts.size());
+
+ RefPtr<BidiContext> topContext = copyContextAndRebaselineLevel(contexts.last(), 0);
+ for (int i = contexts.size() - 1; i > 0; --i)
+ topContext = copyContextAndRebaselineLevel(contexts[i - 1], topContext.get());
+
+ return topContext.release();
+}
+
bool operator==(const BidiContext& c1, const BidiContext& c2)
{
if (&c1 == &c2)
return true;
- if (c1.level() != c2.level() || c1.override() != c2.override() || c1.dir() != c2.dir())
+ if (c1.level() != c2.level() || c1.override() != c2.override() || c1.dir() != c2.dir() || c1.source() != c2.source())
return false;
if (!c1.parent())
return !c2.parent();
diff --git a/Source/WebCore/platform/text/BidiContext.h b/Source/WebCore/platform/text/BidiContext.h
index b52815f..9f45d65 100644
--- a/Source/WebCore/platform/text/BidiContext.h
+++ b/Source/WebCore/platform/text/BidiContext.h
@@ -30,33 +30,52 @@
namespace WebCore {
+enum BidiEmbeddingSource {
+ FromStyleOrDOM,
+ FromUnicode
+};
+
// Used to keep track of explicit embeddings.
class BidiContext : public RefCounted<BidiContext> {
public:
- static PassRefPtr<BidiContext> create(unsigned char level, WTF::Unicode::Direction direction, bool override = false, BidiContext* parent = 0);
+ static PassRefPtr<BidiContext> create(unsigned char level, WTF::Unicode::Direction, bool override = false, BidiEmbeddingSource = FromStyleOrDOM, BidiContext* parent = 0);
BidiContext* parent() const { return m_parent.get(); }
unsigned char level() const { return m_level; }
WTF::Unicode::Direction dir() const { return static_cast<WTF::Unicode::Direction>(m_direction); }
bool override() const { return m_override; }
+ BidiEmbeddingSource source() const { return static_cast<BidiEmbeddingSource>(m_source); }
+ PassRefPtr<BidiContext> copyStackRemovingUnicodeEmbeddingContexts();
private:
- BidiContext(unsigned char level, WTF::Unicode::Direction direction, bool override, BidiContext* parent)
+ BidiContext(unsigned char level, WTF::Unicode::Direction direction, bool override, BidiEmbeddingSource source, BidiContext* parent)
: m_level(level)
, m_direction(direction)
, m_override(override)
+ , m_source(source)
, m_parent(parent)
{
}
- static PassRefPtr<BidiContext> createUncached(unsigned char level, WTF::Unicode::Direction, bool override, BidiContext* parent);
+ static PassRefPtr<BidiContext> createUncached(unsigned char level, WTF::Unicode::Direction, bool override, BidiEmbeddingSource, BidiContext* parent);
unsigned char m_level;
unsigned m_direction : 5; // Direction
bool m_override : 1;
+ unsigned m_source : 1; // BidiEmbeddingSource
RefPtr<BidiContext> m_parent;
};
+inline unsigned char nextGreaterOddLevel(unsigned char level)
+{
+ return (level + 1) | 1;
+}
+
+inline unsigned char nextGreaterEvenLevel(unsigned char level)
+{
+ return (level + 2) & ~1;
+}
+
bool operator==(const BidiContext&, const BidiContext&);
} // namespace WebCore
diff --git a/Source/WebCore/platform/text/BidiResolver.h b/Source/WebCore/platform/text/BidiResolver.h
index 07e9274..5b92ee2 100644
--- a/Source/WebCore/platform/text/BidiResolver.h
+++ b/Source/WebCore/platform/text/BidiResolver.h
@@ -75,6 +75,21 @@ struct BidiStatus {
RefPtr<BidiContext> context;
};
+class BidiEmbedding {
+public:
+ BidiEmbedding(WTF::Unicode::Direction direction, BidiEmbeddingSource source)
+ : m_direction(direction)
+ , m_source(source)
+ {
+ }
+
+ WTF::Unicode::Direction direction() const { return m_direction; }
+ BidiEmbeddingSource source() const { return m_source; }
+private:
+ WTF::Unicode::Direction m_direction;
+ BidiEmbeddingSource m_source;
+};
+
inline bool operator==(const BidiStatus& status1, const BidiStatus& status2)
{
return status1.eor == status2.eor && status1.last == status2.last && status1.lastStrong == status2.lastStrong && *(status1.context) == *(status2.context);
@@ -134,10 +149,10 @@ enum VisualDirectionOverride {
template <class Iterator, class Run> class BidiResolver {
WTF_MAKE_NONCOPYABLE(BidiResolver);
-public :
+public:
BidiResolver()
: m_direction(WTF::Unicode::OtherNeutral)
- , reachedEndOfLine(false)
+ , m_reachedEndOfLine(false)
, emptyRun(true)
, m_firstRun(0)
, m_lastRun(0)
@@ -146,10 +161,10 @@ public :
{
}
- const Iterator& position() const { return current; }
- void setPosition(const Iterator& position) { current = position; }
+ const Iterator& position() const { return m_current; }
+ void setPosition(const Iterator& position) { m_current = position; }
- void increment() { current.increment(); }
+ void increment() { m_current.increment(); }
BidiContext* context() const { return m_status.context.get(); }
void setContext(PassRefPtr<BidiContext> c) { m_status.context = c; }
@@ -166,7 +181,7 @@ public :
MidpointState<Iterator>& midpointState() { return m_midpointState; }
- void embed(WTF::Unicode::Direction);
+ void embed(WTF::Unicode::Direction, BidiEmbeddingSource);
bool commitExplicitEmbedding();
void createBidiRunsForLine(const Iterator& end, VisualDirectionOverride = NoVisualOverride, bool hardLineBreak = false);
@@ -188,14 +203,16 @@ protected:
void appendRun();
void reverseRuns(unsigned start, unsigned end);
- Iterator current;
- Iterator sor;
- Iterator eor;
- Iterator last;
+ Iterator m_current;
+ // sor and eor are "start of run" and "end of run" respectively and correpond
+ // to abreviations used in UBA spec: http://unicode.org/reports/tr9/#BD7
+ Iterator m_sor;
+ Iterator m_eor;
+ Iterator m_last;
BidiStatus m_status;
WTF::Unicode::Direction m_direction;
Iterator endOfLine;
- bool reachedEndOfLine;
+ bool m_reachedEndOfLine;
Iterator lastBeforeET;
bool emptyRun;
@@ -210,7 +227,10 @@ private:
void lowerExplicitEmbeddingLevel(WTF::Unicode::Direction from);
void checkDirectionInLowerRaiseEmbeddingLevel();
- Vector<WTF::Unicode::Direction, 8> m_currentExplicitEmbeddingSequence;
+ void updateStatusLastFromCurrentDirection(WTF::Unicode::Direction);
+ void reorderRunsFromLevels();
+
+ Vector<BidiEmbedding, 8> m_currentExplicitEmbeddingSequence;
};
template <class Iterator, class Run>
@@ -286,20 +306,20 @@ inline void BidiResolver<Iterator, Run>::moveRunToBeginning(Run* run)
template <class Iterator, class Run>
void BidiResolver<Iterator, Run>::appendRun()
{
- if (!emptyRun && !eor.atEnd()) {
- unsigned startOffset = sor.offset();
- unsigned endOffset = eor.offset();
+ if (!emptyRun && !m_eor.atEnd()) {
+ unsigned startOffset = m_sor.offset();
+ unsigned endOffset = m_eor.offset();
if (!endOfLine.atEnd() && endOffset >= endOfLine.offset()) {
- reachedEndOfLine = true;
+ m_reachedEndOfLine = true;
endOffset = endOfLine.offset();
}
if (endOffset >= startOffset)
addRun(new Run(startOffset, endOffset + 1, context(), m_direction));
- eor.increment();
- sor = eor;
+ m_eor.increment();
+ m_sor = m_eor;
}
m_direction = WTF::Unicode::OtherNeutral;
@@ -307,12 +327,12 @@ void BidiResolver<Iterator, Run>::appendRun()
}
template <class Iterator, class Run>
-void BidiResolver<Iterator, Run>::embed(WTF::Unicode::Direction d)
+void BidiResolver<Iterator, Run>::embed(WTF::Unicode::Direction dir, BidiEmbeddingSource source)
{
using namespace WTF::Unicode;
- ASSERT(d == PopDirectionalFormat || d == LeftToRightEmbedding || d == LeftToRightOverride || d == RightToLeftEmbedding || d == RightToLeftOverride);
- m_currentExplicitEmbeddingSequence.append(d);
+ ASSERT(dir == PopDirectionalFormat || dir == LeftToRightEmbedding || dir == LeftToRightOverride || dir == RightToLeftEmbedding || dir == RightToLeftOverride);
+ m_currentExplicitEmbeddingSequence.append(BidiEmbedding(dir, source));
}
template <class Iterator, class Run>
@@ -320,7 +340,7 @@ void BidiResolver<Iterator, Run>::checkDirectionInLowerRaiseEmbeddingLevel()
{
using namespace WTF::Unicode;
- ASSERT(m_status.eor != OtherNeutral || eor.atEnd());
+ ASSERT(m_status.eor != OtherNeutral || m_eor.atEnd());
ASSERT(m_status.last != NonSpacingMark
&& m_status.last != BoundaryNeutral
&& m_status.last != RightToLeftEmbedding
@@ -337,7 +357,7 @@ void BidiResolver<Iterator, Run>::lowerExplicitEmbeddingLevel(WTF::Unicode::Dire
{
using namespace WTF::Unicode;
- if (!emptyRun && eor != last) {
+ if (!emptyRun && m_eor != m_last) {
checkDirectionInLowerRaiseEmbeddingLevel();
// bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-bidi.eor run or extend it through bidi.last
if (from == LeftToRight) {
@@ -358,14 +378,14 @@ void BidiResolver<Iterator, Run>::lowerExplicitEmbeddingLevel(WTF::Unicode::Dire
appendRun();
m_direction = RightToLeft;
}
- eor = last;
+ m_eor = m_last;
}
appendRun();
emptyRun = true;
// sor for the new run is determined by the higher level (rule X10)
setLastDir(from);
setLastStrongDir(from);
- eor = Iterator();
+ m_eor = Iterator();
}
template <class Iterator, class Run>
@@ -373,7 +393,7 @@ void BidiResolver<Iterator, Run>::raiseExplicitEmbeddingLevel(WTF::Unicode::Dire
{
using namespace WTF::Unicode;
- if (!emptyRun && eor != last) {
+ if (!emptyRun && m_eor != m_last) {
checkDirectionInLowerRaiseEmbeddingLevel();
// bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-bidi.eor run or extend it through bidi.last
if (to == LeftToRight) {
@@ -396,13 +416,13 @@ void BidiResolver<Iterator, Run>::raiseExplicitEmbeddingLevel(WTF::Unicode::Dire
appendRun();
m_direction = RightToLeft;
}
- eor = last;
+ m_eor = m_last;
}
appendRun();
emptyRun = true;
setLastDir(to);
setLastStrongDir(to);
- eor = Iterator();
+ m_eor = Iterator();
}
template <class Iterator, class Run>
@@ -414,25 +434,20 @@ bool BidiResolver<Iterator, Run>::commitExplicitEmbedding()
RefPtr<BidiContext> toContext = context();
for (size_t i = 0; i < m_currentExplicitEmbeddingSequence.size(); ++i) {
- Direction embedding = m_currentExplicitEmbeddingSequence[i];
- if (embedding == PopDirectionalFormat) {
+ BidiEmbedding embedding = m_currentExplicitEmbeddingSequence[i];
+ if (embedding.direction() == PopDirectionalFormat) {
if (BidiContext* parentContext = toContext->parent())
toContext = parentContext;
} else {
- Direction direction = (embedding == RightToLeftEmbedding || embedding == RightToLeftOverride) ? RightToLeft : LeftToRight;
- bool override = embedding == LeftToRightOverride || embedding == RightToLeftOverride;
+ Direction direction = (embedding.direction() == RightToLeftEmbedding || embedding.direction() == RightToLeftOverride) ? RightToLeft : LeftToRight;
+ bool override = embedding.direction() == LeftToRightOverride || embedding.direction() == RightToLeftOverride;
unsigned char level = toContext->level();
- if (direction == RightToLeft) {
- // Go to the least greater odd integer
- level += 1;
- level |= 1;
- } else {
- // Go to the least greater even integer
- level += 2;
- level &= ~1;
- }
+ if (direction == RightToLeft)
+ level = nextGreaterOddLevel(level);
+ else
+ level = nextGreaterEvenLevel(level);
if (level < 61)
- toContext = BidiContext::create(level, direction, override, toContext.get());
+ toContext = BidiContext::create(level, direction, override, embedding.source(), toContext.get());
}
}
@@ -520,6 +535,85 @@ void BidiResolver<Iterator, Run>::reverseRuns(unsigned start, unsigned end)
}
template <class Iterator, class Run>
+inline void BidiResolver<Iterator, Run>::updateStatusLastFromCurrentDirection(WTF::Unicode::Direction dirCurrent)
+{
+ using namespace WTF::Unicode;
+ switch (dirCurrent) {
+ case EuropeanNumberTerminator:
+ if (m_status.last != EuropeanNumber)
+ m_status.last = EuropeanNumberTerminator;
+ break;
+ case EuropeanNumberSeparator:
+ case CommonNumberSeparator:
+ case SegmentSeparator:
+ case WhiteSpaceNeutral:
+ case OtherNeutral:
+ switch (m_status.last) {
+ case LeftToRight:
+ case RightToLeft:
+ case RightToLeftArabic:
+ case EuropeanNumber:
+ case ArabicNumber:
+ m_status.last = dirCurrent;
+ break;
+ default:
+ m_status.last = OtherNeutral;
+ }
+ break;
+ case NonSpacingMark:
+ case BoundaryNeutral:
+ case RightToLeftEmbedding:
+ case LeftToRightEmbedding:
+ case RightToLeftOverride:
+ case LeftToRightOverride:
+ case PopDirectionalFormat:
+ // ignore these
+ break;
+ case EuropeanNumber:
+ // fall through
+ default:
+ m_status.last = dirCurrent;
+ }
+}
+
+template <class Iterator, class Run>
+inline void BidiResolver<Iterator, Run>::reorderRunsFromLevels()
+{
+ unsigned char levelLow = 128;
+ unsigned char levelHigh = 0;
+ for (Run* run = firstRun(); run; run = run->next()) {
+ levelHigh = std::max(run->level(), levelHigh);
+ levelLow = std::min(run->level(), levelLow);
+ }
+
+ // This implements reordering of the line (L2 according to Bidi spec):
+ // http://unicode.org/reports/tr9/#L2
+ // L2. From the highest level found in the text to the lowest odd level on each line,
+ // reverse any contiguous sequence of characters that are at that level or higher.
+
+ // Reversing is only done up to the lowest odd level.
+ if (!(levelLow % 2))
+ levelLow++;
+
+ unsigned count = runCount() - 1;
+
+ while (levelHigh >= levelLow) {
+ unsigned i = 0;
+ Run* run = firstRun();
+ while (i < count) {
+ for (;i < count && run && run->level() < levelHigh; i++)
+ run = run->next();
+ unsigned start = i;
+ for (;i <= count && run && run->level() >= levelHigh; i++)
+ run = run->next();
+ unsigned end = i - 1;
+ reverseRuns(start, end);
+ }
+ levelHigh--;
+ }
+}
+
+template <class Iterator, class Run>
void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, VisualDirectionOverride override, bool hardLineBreak)
{
using namespace WTF::Unicode;
@@ -528,10 +622,10 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
if (override != NoVisualOverride) {
emptyRun = false;
- sor = current;
- eor = Iterator();
- while (current != end && !current.atEnd()) {
- eor = current;
+ m_sor = m_current;
+ m_eor = Iterator();
+ while (m_current != end && !m_current.atEnd()) {
+ m_eor = m_current;
increment();
}
m_direction = override == VisualLeftToRightOverride ? LeftToRight : RightToLeft;
@@ -544,29 +638,34 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
emptyRun = true;
- eor = Iterator();
+ m_eor = Iterator();
- last = current;
+ m_last = m_current;
bool pastEnd = false;
BidiResolver<Iterator, Run> stateAtEnd;
while (true) {
Direction dirCurrent;
- if (pastEnd && (hardLineBreak || current.atEnd())) {
+ if (pastEnd && (hardLineBreak || m_current.atEnd())) {
BidiContext* c = context();
- while (c->parent())
- c = c->parent();
- dirCurrent = c->dir();
if (hardLineBreak) {
// A deviation from the Unicode Bidi Algorithm in order to match
- // Mac OS X text and WinIE: a hard line break resets bidi state.
- stateAtEnd.setContext(c);
+ // WinIE and user expectations: hard line breaks reset bidi state
+ // coming from unicode bidi control characters, but not those from
+ // DOM nodes with specified directionality
+ stateAtEnd.setContext(c->copyStackRemovingUnicodeEmbeddingContexts());
+
+ dirCurrent = stateAtEnd.context()->dir();
stateAtEnd.setEorDir(dirCurrent);
stateAtEnd.setLastDir(dirCurrent);
stateAtEnd.setLastStrongDir(dirCurrent);
+ } else {
+ while (c->parent())
+ c = c->parent();
+ dirCurrent = c->dir();
}
} else {
- dirCurrent = current.direction();
+ dirCurrent = m_current.direction();
if (context()->override()
&& dirCurrent != RightToLeftEmbedding
&& dirCurrent != LeftToRightEmbedding
@@ -578,7 +677,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
dirCurrent = m_status.last;
}
- ASSERT(m_status.eor != OtherNeutral || eor.atEnd());
+ ASSERT(m_status.eor != OtherNeutral || m_eor.atEnd());
switch (dirCurrent) {
// embedding and overrides (X1-X9 in the Bidi specs)
@@ -587,7 +686,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
case RightToLeftOverride:
case LeftToRightOverride:
case PopDirectionalFormat:
- embed(dirCurrent);
+ embed(dirCurrent, FromUnicode);
commitExplicitEmbedding();
break;
@@ -618,7 +717,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
appendRun();
if (context()->dir() != LeftToRight) {
// the neutrals take the embedding direction, which is R
- eor = last;
+ m_eor = m_last;
m_direction = RightToLeft;
appendRun();
}
@@ -629,14 +728,14 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
appendRun();
if (context()->dir() != LeftToRight) {
// the neutrals take the embedding direction, which is R
- eor = last;
+ m_eor = m_last;
m_direction = RightToLeft;
appendRun();
}
} else if (m_status.lastStrong != LeftToRight) {
//last stuff takes embedding dir
if (context()->dir() == RightToLeft) {
- eor = last;
+ m_eor = m_last;
m_direction = RightToLeft;
}
appendRun();
@@ -644,7 +743,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
default:
break;
}
- eor = current;
+ m_eor = m_current;
m_status.eor = LeftToRight;
m_status.lastStrong = LeftToRight;
m_direction = LeftToRight;
@@ -669,19 +768,19 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
case OtherNeutral:
if (m_status.eor == EuropeanNumber) {
if (m_status.lastStrong == LeftToRight && context()->dir() == LeftToRight)
- eor = last;
+ m_eor = m_last;
appendRun();
} else if (m_status.eor == ArabicNumber)
appendRun();
else if (m_status.lastStrong == LeftToRight) {
if (context()->dir() == LeftToRight)
- eor = last;
+ m_eor = m_last;
appendRun();
}
default:
break;
}
- eor = current;
+ m_eor = m_current;
m_status.eor = RightToLeft;
m_status.lastStrong = dirCurrent;
m_direction = RightToLeft;
@@ -699,7 +798,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
case RightToLeft:
case RightToLeftArabic:
case ArabicNumber:
- eor = last;
+ m_eor = m_last;
appendRun();
m_direction = EuropeanNumber;
break;
@@ -719,7 +818,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
// Terminate the EN run.
appendRun();
// Make an R run.
- eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : last;
+ m_eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : m_last;
m_direction = RightToLeft;
appendRun();
// Begin a new EN run.
@@ -730,7 +829,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
appendRun();
if (m_status.lastStrong == RightToLeft || context()->dir() == RightToLeft) {
// Make an R run.
- eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : last;
+ m_eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : m_last;
m_direction = RightToLeft;
appendRun();
// Begin a new EN run.
@@ -738,7 +837,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
}
} else if (m_status.lastStrong == RightToLeft) {
// Extend the R run to include the neutrals.
- eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : last;
+ m_eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : m_last;
m_direction = RightToLeft;
appendRun();
// Begin a new EN run.
@@ -747,7 +846,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
default:
break;
}
- eor = current;
+ m_eor = m_current;
m_status.eor = EuropeanNumber;
if (m_direction == OtherNeutral)
m_direction = LeftToRight;
@@ -765,7 +864,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
case RightToLeft:
case RightToLeftArabic:
case EuropeanNumber:
- eor = last;
+ m_eor = m_last;
appendRun();
break;
case CommonNumberSeparator:
@@ -787,12 +886,12 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
m_direction = RightToLeft;
} else if (m_direction == OtherNeutral)
m_direction = m_status.lastStrong == LeftToRight ? LeftToRight : RightToLeft;
- eor = last;
+ m_eor = m_last;
appendRun();
default:
break;
}
- eor = current;
+ m_eor = m_current;
m_status.eor = ArabicNumber;
if (m_direction == OtherNeutral)
m_direction = ArabicNumber;
@@ -803,16 +902,16 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
case EuropeanNumberTerminator:
if (m_status.last == EuropeanNumber) {
dirCurrent = EuropeanNumber;
- eor = current;
+ m_eor = m_current;
m_status.eor = dirCurrent;
} else if (m_status.last != EuropeanNumberTerminator)
- lastBeforeET = emptyRun ? eor : last;
+ lastBeforeET = emptyRun ? m_eor : m_last;
break;
// boundary neutrals should be ignored
case BoundaryNeutral:
- if (eor == last)
- eor = current;
+ if (m_eor == m_last)
+ m_eor = m_current;
break;
// neutrals
case BlockSeparator:
@@ -829,9 +928,9 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
break;
}
- if (pastEnd && eor == current) {
- if (!reachedEndOfLine) {
- eor = endOfLine;
+ if (pastEnd && m_eor == m_current) {
+ if (!m_reachedEndOfLine) {
+ m_eor = endOfLine;
switch (m_status.eor) {
case LeftToRight:
case RightToLeft:
@@ -846,60 +945,23 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
}
appendRun();
}
- current = end;
+ m_current = end;
m_status = stateAtEnd.m_status;
- sor = stateAtEnd.sor;
- eor = stateAtEnd.eor;
- last = stateAtEnd.last;
- reachedEndOfLine = stateAtEnd.reachedEndOfLine;
+ m_sor = stateAtEnd.m_sor;
+ m_eor = stateAtEnd.m_eor;
+ m_last = stateAtEnd.m_last;
+ m_reachedEndOfLine = stateAtEnd.m_reachedEndOfLine;
lastBeforeET = stateAtEnd.lastBeforeET;
emptyRun = stateAtEnd.emptyRun;
m_direction = OtherNeutral;
break;
}
- // set m_status.last as needed.
- switch (dirCurrent) {
- case EuropeanNumberTerminator:
- if (m_status.last != EuropeanNumber)
- m_status.last = EuropeanNumberTerminator;
- break;
- case EuropeanNumberSeparator:
- case CommonNumberSeparator:
- case SegmentSeparator:
- case WhiteSpaceNeutral:
- case OtherNeutral:
- switch(m_status.last) {
- case LeftToRight:
- case RightToLeft:
- case RightToLeftArabic:
- case EuropeanNumber:
- case ArabicNumber:
- m_status.last = dirCurrent;
- break;
- default:
- m_status.last = OtherNeutral;
- }
- break;
- case NonSpacingMark:
- case BoundaryNeutral:
- case RightToLeftEmbedding:
- case LeftToRightEmbedding:
- case RightToLeftOverride:
- case LeftToRightOverride:
- case PopDirectionalFormat:
- // ignore these
- break;
- case EuropeanNumber:
- // fall through
- default:
- m_status.last = dirCurrent;
- }
-
- last = current;
+ updateStatusLastFromCurrentDirection(dirCurrent);
+ m_last = m_current;
if (emptyRun) {
- sor = current;
+ m_sor = m_current;
emptyRun = false;
}
@@ -907,12 +969,12 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
if (!m_currentExplicitEmbeddingSequence.isEmpty()) {
bool committed = commitExplicitEmbedding();
if (committed && pastEnd) {
- current = end;
+ m_current = end;
m_status = stateAtEnd.m_status;
- sor = stateAtEnd.sor;
- eor = stateAtEnd.eor;
- last = stateAtEnd.last;
- reachedEndOfLine = stateAtEnd.reachedEndOfLine;
+ m_sor = stateAtEnd.m_sor;
+ m_eor = stateAtEnd.m_eor;
+ m_last = stateAtEnd.m_last;
+ m_reachedEndOfLine = stateAtEnd.m_reachedEndOfLine;
lastBeforeET = stateAtEnd.lastBeforeET;
emptyRun = stateAtEnd.emptyRun;
m_direction = OtherNeutral;
@@ -920,64 +982,23 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
}
}
- if (!pastEnd && (current == end || current.atEnd())) {
+ if (!pastEnd && (m_current == end || m_current.atEnd())) {
if (emptyRun)
break;
stateAtEnd.m_status = m_status;
- stateAtEnd.sor = sor;
- stateAtEnd.eor = eor;
- stateAtEnd.last = last;
- stateAtEnd.reachedEndOfLine = reachedEndOfLine;
+ stateAtEnd.m_sor = m_sor;
+ stateAtEnd.m_eor = m_eor;
+ stateAtEnd.m_last = m_last;
+ stateAtEnd.m_reachedEndOfLine = m_reachedEndOfLine;
stateAtEnd.lastBeforeET = lastBeforeET;
stateAtEnd.emptyRun = emptyRun;
- endOfLine = last;
+ endOfLine = m_last;
pastEnd = true;
}
}
m_logicallyLastRun = m_lastRun;
-
- // reorder line according to run structure...
- // first find highest and lowest levels
- unsigned char levelLow = 128;
- unsigned char levelHigh = 0;
- Run* r = firstRun();
- while (r) {
- if (r->m_level > levelHigh)
- levelHigh = r->m_level;
- if (r->m_level < levelLow)
- levelLow = r->m_level;
- r = r->next();
- }
-
- // implements reordering of the line (L2 according to Bidi spec):
- // L2. From the highest level found in the text to the lowest odd level on each line,
- // reverse any contiguous sequence of characters that are at that level or higher.
-
- // reversing is only done up to the lowest odd level
- if (!(levelLow % 2))
- levelLow++;
-
- unsigned count = runCount() - 1;
-
- while (levelHigh >= levelLow) {
- unsigned i = 0;
- Run* currRun = firstRun();
- while (i < count) {
- while (i < count && currRun && currRun->m_level < levelHigh) {
- i++;
- currRun = currRun->next();
- }
- unsigned start = i;
- while (i <= count && currRun && currRun->m_level >= levelHigh) {
- i++;
- currRun = currRun->next();
- }
- unsigned end = i - 1;
- reverseRuns(start, end);
- }
- levelHigh--;
- }
+ reorderRunsFromLevels();
endOfLine = Iterator();
}
diff --git a/Source/WebCore/platform/text/LocalizedNumber.h b/Source/WebCore/platform/text/LocalizedNumber.h
index d70541f..01d2553 100644
--- a/Source/WebCore/platform/text/LocalizedNumber.h
+++ b/Source/WebCore/platform/text/LocalizedNumber.h
@@ -47,7 +47,9 @@ double parseLocalizedNumber(const String&);
// 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.
-String formatLocalizedNumber(double);
+// fractionDigits is the maximum length of the fractional parts of the
+// resultant string.
+String formatLocalizedNumber(double, unsigned fractionDigits);
} // namespace WebCore
diff --git a/Source/WebCore/platform/text/LocalizedNumberICU.cpp b/Source/WebCore/platform/text/LocalizedNumberICU.cpp
index 189151e..7c4b1cb 100644
--- a/Source/WebCore/platform/text/LocalizedNumberICU.cpp
+++ b/Source/WebCore/platform/text/LocalizedNumberICU.cpp
@@ -34,6 +34,7 @@
#include <limits>
#include <unicode/numfmt.h>
#include <unicode/parsepos.h>
+#include <wtf/MathExtras.h>
#include <wtf/PassOwnPtr.h>
using namespace std;
@@ -73,12 +74,13 @@ double parseLocalizedNumber(const String& numberString)
return U_SUCCESS(status) ? numericResult : numeric_limits<double>::quiet_NaN();
}
-String formatLocalizedNumber(double number)
+String formatLocalizedNumber(double number, unsigned fractionDigits)
{
NumberFormat* formatter = numberFormatter();
if (!formatter)
return String();
UnicodeString result;
+ formatter->setMaximumFractionDigits(clampToInteger(fractionDigits));
formatter->format(number, result);
return String(result.getBuffer(), result.length());
}
diff --git a/Source/WebCore/platform/text/LocalizedNumberNone.cpp b/Source/WebCore/platform/text/LocalizedNumberNone.cpp
index 729f2f1..c7a8ed2 100644
--- a/Source/WebCore/platform/text/LocalizedNumberNone.cpp
+++ b/Source/WebCore/platform/text/LocalizedNumberNone.cpp
@@ -42,7 +42,7 @@ double parseLocalizedNumber(const String&)
return numeric_limits<double>::quiet_NaN();
}
-String formatLocalizedNumber(double)
+String formatLocalizedNumber(double, unsigned)
{
return String();
}
diff --git a/Source/WebCore/platform/text/TextCheckerClient.h b/Source/WebCore/platform/text/TextCheckerClient.h
index acaa02c..8abbed4 100644
--- a/Source/WebCore/platform/text/TextCheckerClient.h
+++ b/Source/WebCore/platform/text/TextCheckerClient.h
@@ -28,6 +28,8 @@
#ifndef TextCheckerClient_h
#define TextCheckerClient_h
+#include "TextChecking.h"
+
#include <wtf/Forward.h>
#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>
@@ -70,7 +72,7 @@ public:
virtual void checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength) = 0;
virtual String getAutoCorrectSuggestionForMisspelledWord(const String& misspelledWord) = 0;
virtual void checkGrammarOfString(const UChar*, int length, Vector<GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength) = 0;
-#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+#if USE(UNIFIED_TEXT_CHECKING)
virtual void checkTextOfParagraph(const UChar* text, int length, uint64_t checkingTypes, Vector<TextCheckingResult>& results) = 0;
#endif
diff --git a/Source/WebCore/platform/chromium/WindowsVersion.h b/Source/WebCore/platform/text/TextChecking.h
index 3b2010a..022fb82 100644
--- a/Source/WebCore/platform/chromium/WindowsVersion.h
+++ b/Source/WebCore/platform/text/TextChecking.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, 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,13 +28,20 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef WindowsVersion_h
-#define WindowsVersion_h
+#ifndef TextChecking_h
+#define TextChecking_h
namespace WebCore {
- bool isVistaOrNewer();
-
-} // namespace WebCore
+#if !defined(BUILDING_ON_TIGER)
+#define WTF_USE_GRAMMAR_CHECKING 1
+#endif
+#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+#define WTF_USE_UNIFIED_TEXT_CHECKING 1
+#define WTF_USE_AUTOMATIC_TEXT_REPLACEMENT 1
#endif
+
+}
+
+#endif // TextChecking_h
diff --git a/Source/WebCore/platform/text/TextCodec.h b/Source/WebCore/platform/text/TextCodec.h
index 35229a3..0c2a38a 100644
--- a/Source/WebCore/platform/text/TextCodec.h
+++ b/Source/WebCore/platform/text/TextCodec.h
@@ -52,7 +52,7 @@ namespace WebCore {
// Encodes the character as en entity as above, but escaped
// non-alphanumeric characters. This is used in URLs.
// For example, U+6DE would be "%26%231758%3B".
- URLEncodedEntitiesForUnencodables,
+ URLEncodedEntitiesForUnencodables
};
typedef char UnencodableReplacementArray[32];
diff --git a/Source/WebCore/platform/text/TextCodecICU.cpp b/Source/WebCore/platform/text/TextCodecICU.cpp
index d07b50e..0d99196 100644
--- a/Source/WebCore/platform/text/TextCodecICU.cpp
+++ b/Source/WebCore/platform/text/TextCodecICU.cpp
@@ -149,13 +149,6 @@ void TextCodecICU::registerEncodingNames(EncodingNameRegistrar registrar)
registrar("x-windows-949", "windows-949");
registrar("x-uhc", "windows-949");
registrar("shift-jis", "Shift_JIS");
-#if !USE(BUILTIN_UTF8_CODEC)
- registrar("unicode11utf8", "UTF-8");
- registrar("unicode20utf8", "UTF-8");
- registrar("x-unicode20utf8", "UTF-8");
- registrar("utf8", "UTF-8");
- registrar("UTF-8", "UTF-8");
-#endif
// These aliases are present in modern versions of ICU, but use different codecs, and have no standard names.
// They are not present in ICU 3.2.
diff --git a/Source/WebCore/platform/text/TextEncodingRegistry.cpp b/Source/WebCore/platform/text/TextEncodingRegistry.cpp
index f604227..d6450b1 100644
--- a/Source/WebCore/platform/text/TextEncodingRegistry.cpp
+++ b/Source/WebCore/platform/text/TextEncodingRegistry.cpp
@@ -223,10 +223,8 @@ static void buildBaseTextCodecMaps()
TextCodecLatin1::registerEncodingNames(addToTextEncodingNameMap);
TextCodecLatin1::registerCodecs(addToTextCodecMap);
-#if USE(BUILTIN_UTF8_CODEC)
TextCodecUTF8::registerEncodingNames(addToTextEncodingNameMap);
TextCodecUTF8::registerCodecs(addToTextCodecMap);
-#endif
TextCodecUTF16::registerEncodingNames(addToTextEncodingNameMap);
TextCodecUTF16::registerCodecs(addToTextCodecMap);
diff --git a/Source/WebCore/platform/mac/WebCoreKeyGenerator.m b/Source/WebCore/platform/text/TextOrientation.h
index a1e780c..e229f1e 100644
--- a/Source/WebCore/platform/mac/WebCoreKeyGenerator.m
+++ b/Source/WebCore/platform/text/TextOrientation.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Apple Computer, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,41 +23,13 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#import "config.h"
-#import "WebCoreKeyGenerator.h"
+#ifndef TextOrientation_h
+#define TextOrientation_h
-#import <wtf/Assertions.h>
-#import <wtf/UnusedParam.h>
+namespace WebCore {
-static WebCoreKeyGenerator *sharedGenerator;
+enum TextOrientation { TextOrientationVerticalRight, TextOrientationUpright };
-@implementation WebCoreKeyGenerator
-
-+ (WebCoreKeyGenerator *)sharedGenerator
-{
- return sharedGenerator;
-}
-
-- init
-{
- ASSERT(!sharedGenerator);
- [super init];
- sharedGenerator = [self retain];
- return self;
-}
-
-- (NSArray *)strengthMenuItemTitles
-{
- return nil;
-}
-
-- (NSString *)signedPublicKeyAndChallengeStringWithStrengthIndex:(unsigned)unusedIndex challenge:(NSString *)unusedChallenge pageURL:(NSURL *)unusedPageURL
-{
- UNUSED_PARAM(unusedIndex);
- UNUSED_PARAM(unusedChallenge);
- UNUSED_PARAM(unusedPageURL);
-
- return nil;
}
-@end
+#endif
diff --git a/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm b/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm
index 8cfe200..826f707 100644
--- a/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm
+++ b/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm
@@ -65,10 +65,12 @@ double parseLocalizedNumber(const String& numberString)
return [number doubleValue];
}
-String formatLocalizedNumber(double inputNumber)
+String formatLocalizedNumber(double inputNumber, unsigned fractionDigits)
{
RetainPtr<NSNumber> number(AdoptNS, [[NSNumber alloc] initWithDouble:inputNumber]);
- return String([numberFormatter() stringFromNumber:number.get()]);
+ RetainPtr<NSNumberFormatter> formatter = numberFormatter();
+ [formatter.get() setMaximumFractionDigits:fractionDigits];
+ return String([formatter.get() stringFromNumber:number.get()]);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/text/qt/TextBreakIteratorQt.cpp b/Source/WebCore/platform/text/qt/TextBreakIteratorQt.cpp
index 3fae657..1fe400c 100644
--- a/Source/WebCore/platform/text/qt/TextBreakIteratorQt.cpp
+++ b/Source/WebCore/platform/text/qt/TextBreakIteratorQt.cpp
@@ -22,6 +22,7 @@
#include "TextBreakIterator.h"
#include <QtCore/qtextboundaryfinder.h>
+#include <algorithm>
#include <qdebug.h>
// #define DEBUG_TEXT_ITERATORS
@@ -89,7 +90,7 @@ const char* currentTextBreakLocaleID()
TextBreakIterator* lineBreakIterator = 0;
if (staticLineBreakIterator) {
setUpIterator(*staticLineBreakIterator, QTextBoundaryFinder::Line, string, length);
- swap(staticLineBreakIterator, lineBreakIterator);
+ std::swap(staticLineBreakIterator, lineBreakIterator);
}
if (!lineBreakIterator && string && length)
diff --git a/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp b/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp
index 513992d..33d8ccd 100644
--- a/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp
+++ b/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp
@@ -130,7 +130,7 @@ static bool getWebLocData(const DragDataMap* dataObject, String& url, String* ti
if (!dataObject->contains(cfHDropFormat()->cfFormat))
return false;
- wcscpy(filename, dataObject->get(cfHDropFormat()->cfFormat)[0].characters());
+ wcscpy(filename, dataObject->get(cfHDropFormat()->cfFormat)[0].charactersWithNullTermination());
if (_wcsicmp(PathFindExtensionW(filename), L".url"))
return false;
diff --git a/Source/WebCore/platform/win/CursorWin.cpp b/Source/WebCore/platform/win/CursorWin.cpp
index 0036388..3a8cc09 100644
--- a/Source/WebCore/platform/win/CursorWin.cpp
+++ b/Source/WebCore/platform/win/CursorWin.cpp
@@ -30,6 +30,7 @@
#include "BitmapInfo.h"
#include "Image.h"
#include "IntPoint.h"
+#include "SystemInfo.h"
#include <wtf/OwnPtr.h>
@@ -39,20 +40,12 @@
namespace WebCore {
-static inline bool supportsAlphaCursors()
-{
- OSVERSIONINFO osinfo = {0};
- osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx(&osinfo);
- return osinfo.dwMajorVersion > 5 || (osinfo.dwMajorVersion == 5 && osinfo.dwMinorVersion > 0);
-}
-
static PassRefPtr<SharedCursor> createSharedCursor(Image* img, const IntPoint& hotSpot)
{
RefPtr<SharedCursor> impl;
IntPoint effectiveHotSpot = determineHotSpot(img, hotSpot);
- static bool doAlpha = supportsAlphaCursors();
+ static bool doAlpha = windowsVersion() >= WindowsXP;
BitmapInfo cursorImage = BitmapInfo::create(IntSize(img->width(), img->height()));
HDC dc = GetDC(0);
diff --git a/Source/WebCore/platform/win/FileSystemWin.cpp b/Source/WebCore/platform/win/FileSystemWin.cpp
index 5ee3b8e..03a2eaf 100644
--- a/Source/WebCore/platform/win/FileSystemWin.cpp
+++ b/Source/WebCore/platform/win/FileSystemWin.cpp
@@ -31,9 +31,11 @@
#include "FileSystem.h"
#include "NotImplemented.h"
+#include "PathWalker.h"
#include "PlatformString.h"
#include <wtf/HashMap.h>
#include <wtf/text/CString.h>
+#include <wtf/text/StringConcatenate.h>
#include <windows.h>
#include <winbase.h>
@@ -184,18 +186,18 @@ static String cachedStorageDirectory(DWORD pathIdentifier)
return directory;
}
-CString openTemporaryFile(const char*, PlatformFileHandle& handle)
+String openTemporaryFile(const String&, PlatformFileHandle& handle)
{
handle = INVALID_HANDLE_VALUE;
char tempPath[MAX_PATH];
int tempPathLength = ::GetTempPathA(WTF_ARRAY_LENGTH(tempPath), tempPath);
if (tempPathLength <= 0 || tempPathLength > WTF_ARRAY_LENGTH(tempPath))
- return CString();
+ return String();
HCRYPTPROV hCryptProv = 0;
if (!CryptAcquireContext(&hCryptProv, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
- return CString();
+ return String();
char proposedPath[MAX_PATH];
while (1) {
@@ -226,9 +228,28 @@ CString openTemporaryFile(const char*, PlatformFileHandle& handle)
CryptReleaseContext(hCryptProv, 0);
if (!isHandleValid(handle))
- return CString();
+ return String();
- return proposedPath;
+ return String::fromUTF8(proposedPath);
+}
+
+PlatformFileHandle openFile(const String& path, FileOpenMode mode)
+{
+ DWORD desiredAccess = 0;
+ DWORD creationDisposition = 0;
+ switch (mode) {
+ case OpenForRead:
+ desiredAccess = GENERIC_READ;
+ creationDisposition = OPEN_EXISTING;
+ case OpenForWrite:
+ desiredAccess = GENERIC_WRITE;
+ creationDisposition = CREATE_ALWAYS;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+
+ String destination = path;
+ return CreateFile(destination.charactersWithNullTermination(), desiredAccess, 0, 0, creationDisposition, FILE_ATTRIBUTE_NORMAL, 0);
}
void closeFile(PlatformFileHandle& handle)
@@ -297,10 +318,21 @@ bool safeCreateFile(const String& path, CFDataRef data)
return true;
}
-Vector<String> listDirectory(const String& path, const String& filter)
+Vector<String> listDirectory(const String& directory, const String& filter)
{
Vector<String> entries;
- notImplemented();
+
+ PathWalker walker(directory, filter);
+ if (!walker.isValid())
+ return entries;
+
+ do {
+ if (walker.data().dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ continue;
+
+ entries.append(makeString(directory, "\\", reinterpret_cast<const UChar*>(walker.data().cFileName)));
+ } while (walker.step());
+
return entries;
}
diff --git a/Source/WebCore/platform/win/LocalizedStringsWin.cpp b/Source/WebCore/platform/win/LocalizedStringsWin.cpp
new file mode 100644
index 0000000..67de0fc
--- /dev/null
+++ b/Source/WebCore/platform/win/LocalizedStringsWin.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 "LocalizedStrings.h"
+
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+String localizedString(const char* key)
+{
+ // FIXME: <rdar://problem/9119405> Win: WebKit2 needs to be made localizable
+ return String::fromUTF8(key, strlen(key));
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/win/PathWalker.cpp b/Source/WebCore/platform/win/PathWalker.cpp
new file mode 100644
index 0000000..cb4fccb
--- /dev/null
+++ b/Source/WebCore/platform/win/PathWalker.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 "PathWalker.h"
+
+#include <wtf/text/StringConcatenate.h>
+
+namespace WebCore {
+
+PathWalker::PathWalker(const String& directory, const String& pattern)
+{
+ String path = makeString(directory, "\\", pattern);
+ m_handle = ::FindFirstFileW(path.charactersWithNullTermination(), &m_data);
+}
+
+PathWalker::~PathWalker()
+{
+ if (!isValid())
+ return;
+ ::FindClose(m_handle);
+}
+
+bool PathWalker::step()
+{
+ return ::FindNextFileW(m_handle, &m_data);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/win/PathWalker.h b/Source/WebCore/platform/win/PathWalker.h
new file mode 100644
index 0000000..219c837
--- /dev/null
+++ b/Source/WebCore/platform/win/PathWalker.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 <Windows.h>
+#include <wtf/Noncopyable.h>
+
+namespace WTF {
+ class String;
+}
+
+namespace WebCore {
+
+class PathWalker {
+ WTF_MAKE_NONCOPYABLE(PathWalker);
+public:
+ PathWalker(const WTF::String& directory, const WTF::String& pattern);
+ ~PathWalker();
+
+ bool isValid() const { return m_handle != INVALID_HANDLE_VALUE; }
+ const WIN32_FIND_DATAW& data() const { return m_data; }
+
+ bool step();
+
+private:
+ HANDLE m_handle;
+ WIN32_FIND_DATAW m_data;
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/win/SSLKeyGeneratorWin.cpp b/Source/WebCore/platform/win/SSLKeyGeneratorWin.cpp
index 50aee8e..b10961b 100644
--- a/Source/WebCore/platform/win/SSLKeyGeneratorWin.cpp
+++ b/Source/WebCore/platform/win/SSLKeyGeneratorWin.cpp
@@ -30,6 +30,7 @@ namespace WebCore {
void WebCore::getSupportedKeySizes(Vector<String>& v)
{
+ // FIXME: Strings should be localizable.
v.append("High Grade");
v.append("Medium Grade");
}
diff --git a/Source/WebCore/platform/win/ScrollbarThemeWin.cpp b/Source/WebCore/platform/win/ScrollbarThemeWin.cpp
index ff3aaa4..576cd92 100644
--- a/Source/WebCore/platform/win/ScrollbarThemeWin.cpp
+++ b/Source/WebCore/platform/win/ScrollbarThemeWin.cpp
@@ -100,7 +100,7 @@ ScrollbarThemeWin::ScrollbarThemeWin()
if (!initialized) {
initialized = true;
checkAndInitScrollbarTheme();
- runningVista = isRunningOnVistaOrLater();
+ runningVista = (windowsVersion() >= WindowsVista);
}
}
diff --git a/Source/WebCore/platform/win/SystemInfo.cpp b/Source/WebCore/platform/win/SystemInfo.cpp
index f2fe62b..878a6cc 100644
--- a/Source/WebCore/platform/win/SystemInfo.cpp
+++ b/Source/WebCore/platform/win/SystemInfo.cpp
@@ -27,30 +27,155 @@
#include "SystemInfo.h"
#include <windows.h>
+#include <wtf/text/StringConcatenate.h>
namespace WebCore {
-bool isRunningOnVistaOrLater()
+WindowsVersion windowsVersion(int* major, int* minor)
{
+ static bool initialized = false;
+ static WindowsVersion version;
+ static int majorVersion, minorVersion;
+
+ if (!initialized) {
+ initialized = true;
+#if OS(WINCE)
+ OSVERSIONINFO versionInfo;
+#else
+ OSVERSIONINFOEX versionInfo;
+#endif
+ ZeroMemory(&versionInfo, sizeof(versionInfo));
+ versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
+ GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&versionInfo));
+ majorVersion = versionInfo.dwMajorVersion;
+ minorVersion = versionInfo.dwMinorVersion;
+
#if OS(WINCE)
- return false;
+ if (majorVersion >= 1 && majorVersion <= 7)
+ version = static_cast<WindowsVersion>(WindowsCE1 + (majorVersion - 1));
+ else
+ version = (majorVersion < 1) ? WindowsCE1 : WindowsCE7;
#else
- static bool isVistaOrLater;
- static bool initialized;
+ if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32s)
+ version = Windows3_1;
+ else if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
+ if (!minorVersion)
+ version = Windows95;
+ else
+ version = (minorVersion == 10) ? Windows98 : WindowsME;
+ } else {
+ if (majorVersion == 5) {
+ if (!minorVersion)
+ version = Windows2000;
+ else
+ version = (minorVersion == 1) ? WindowsXP : WindowsServer2003;
+ } else if (majorVersion >= 6) {
+ if (versionInfo.wProductType == VER_NT_WORKSTATION)
+ version = (majorVersion == 6 && !minorVersion) ? WindowsVista : Windows7;
+ else
+ version = WindowsServer2008;
+ } else
+ version = (majorVersion == 4) ? WindowsNT4 : WindowsNT3;
+ }
+#endif
+ }
- if (initialized)
- return isVistaOrLater;
+ if (major)
+ *major = majorVersion;
+ if (minor)
+ *minor = minorVersion;
+ return version;
+}
+
+static String osVersionForUAString()
+{
+ int major, minor;
+ WindowsVersion version = windowsVersion(&major, &minor);
+ switch (version) {
+ case WindowsCE1:
+ case WindowsCE2:
+ case WindowsCE3:
+ return "Windows CE";
+ case WindowsCE4:
+ return "Windows CE .NET";
+ case Windows3_1:
+ return "Windows 3.1";
+ case Windows95:
+ return "Windows 95";
+ case Windows98:
+ return "Windows 98";
+ case WindowsME:
+ return "Windows 98; Win 9x 4.90";
+ case WindowsNT4:
+ return "WinNT4.0";
+ }
- initialized = true;
+ const char* familyName = (version >= WindowsNT3) ? "Windows NT " : "Windows CE ";
+ return makeString(familyName, String::number(major), '.', String::number(minor));
+}
- OSVERSIONINFOEX vi = {0};
- vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
- GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&vi));
+#if !OS(WINCE)
+static bool isWOW64()
+{
+ static bool initialized = false;
+ static bool wow64 = false;
- isVistaOrLater = vi.dwMajorVersion >= 6;
+ if (!initialized) {
+ initialized = true;
+ HMODULE kernel32Module = GetModuleHandleA("kernel32.dll");
+ if (!kernel32Module)
+ return wow64;
+ typedef BOOL (WINAPI* IsWow64ProcessFunc)(HANDLE, PBOOL);
+ IsWow64ProcessFunc isWOW64Process = reinterpret_cast<IsWow64ProcessFunc>(GetProcAddress(kernel32Module, "IsWow64Process"));
+ if (isWOW64Process) {
+ BOOL result = FALSE;
+ wow64 = isWOW64Process(GetCurrentProcess(), &result) && result;
+ }
+ }
- return isVistaOrLater;
+ return wow64;
+}
+
+static WORD processorArchitecture()
+{
+ static bool initialized = false;
+ static WORD architecture = PROCESSOR_ARCHITECTURE_INTEL;
+
+ if (!initialized) {
+ initialized = true;
+ HMODULE kernel32Module = GetModuleHandleA("kernel32.dll");
+ if (!kernel32Module)
+ return architecture;
+ typedef VOID (WINAPI* GetNativeSystemInfoFunc)(LPSYSTEM_INFO);
+ GetNativeSystemInfoFunc getNativeSystemInfo = reinterpret_cast<GetNativeSystemInfoFunc>(GetProcAddress(kernel32Module, "GetNativeSystemInfo"));
+ if (getNativeSystemInfo) {
+ SYSTEM_INFO systemInfo;
+ ZeroMemory(&systemInfo, sizeof(systemInfo));
+ getNativeSystemInfo(&systemInfo);
+ architecture = systemInfo.wProcessorArchitecture;
+ }
+ }
+
+ return architecture;
+}
#endif
+
+static String architectureTokenForUAString()
+{
+#if !OS(WINCE)
+ if (isWOW64())
+ return "; WOW64";
+ if (processorArchitecture() == PROCESSOR_ARCHITECTURE_AMD64)
+ return "; Win64; x64";
+ if (processorArchitecture() == PROCESSOR_ARCHITECTURE_IA64)
+ return "; Win64; IA64";
+#endif
+ return String();
+}
+
+String windowsVersionForUAString()
+{
+ return makeString(osVersionForUAString(), architectureTokenForUAString());
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/win/SystemInfo.h b/Source/WebCore/platform/win/SystemInfo.h
index 9f2c2a0..2631ace 100644
--- a/Source/WebCore/platform/win/SystemInfo.h
+++ b/Source/WebCore/platform/win/SystemInfo.h
@@ -26,9 +26,44 @@
#ifndef SystemInfo_h
#define SystemInfo_h
+#include <wtf/text/WTFString.h>
+
namespace WebCore {
-bool isRunningOnVistaOrLater();
+// NOTE: Keep these in order so callers can do things like
+// "if (windowsVersion() >= WindowsVista) ...". It's OK to change or add values,
+// though.
+enum WindowsVersion {
+ // CE-based versions
+ WindowsCE1 = 0,
+ WindowsCE2,
+ WindowsCE3,
+ WindowsCE4,
+ WindowsCE5,
+ WindowsCE6,
+ WindowsCE7,
+ // 3.x-based versions
+ Windows3_1,
+ // 9x-based versions
+ Windows95,
+ Windows98,
+ WindowsME,
+ // NT-based versions
+ WindowsNT3,
+ WindowsNT4,
+ Windows2000,
+ WindowsXP,
+ WindowsServer2003,
+ WindowsVista,
+ WindowsServer2008,
+ Windows7,
+};
+
+// If supplied, |major| and |minor| are set to the OSVERSIONINFO::dwMajorVersion
+// and dwMinorVersion field values, respectively.
+WindowsVersion windowsVersion(int* major = 0, int* minor = 0);
+
+String windowsVersionForUAString();
} // namespace WebCore
diff --git a/Source/WebCore/platform/wince/FileSystemWinCE.cpp b/Source/WebCore/platform/wince/FileSystemWinCE.cpp
index 49acf12..3e28a01 100644
--- a/Source/WebCore/platform/wince/FileSystemWinCE.cpp
+++ b/Source/WebCore/platform/wince/FileSystemWinCE.cpp
@@ -187,18 +187,18 @@ String directoryName(const String& path)
return path.left(pos);
}
-CString openTemporaryFile(const char*, PlatformFileHandle& handle)
+String openTemporaryFile(const String&, PlatformFileHandle& handle)
{
handle = INVALID_HANDLE_VALUE;
wchar_t tempPath[MAX_PATH];
int tempPathLength = ::GetTempPath(WTF_ARRAY_LENGTH(tempPath), tempPath);
if (tempPathLength <= 0 || tempPathLength > WTF_ARRAY_LENGTH(tempPath))
- return CString();
+ return String();
HCRYPTPROV hCryptProv = 0;
if (!CryptAcquireContext(&hCryptProv, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
- return CString();
+ return String();
String proposedPath;
while (1) {
@@ -229,9 +229,28 @@ CString openTemporaryFile(const char*, PlatformFileHandle& handle)
CryptReleaseContext(hCryptProv, 0);
if (!isHandleValid(handle))
- return CString();
+ return String();
+
+ return proposedPath;
+}
+
+PlatformFileHandle openFile(const String& path, FileOpenMode mode)
+{
+ DWORD desiredAccess = 0;
+ DWORD creationDisposition = 0;
+ switch (mode) {
+ case OpenForRead:
+ desiredAccess = GENERIC_READ;
+ creationDisposition = OPEN_EXISTING;
+ case OpenForWrite:
+ desiredAccess = GENERIC_WRITE;
+ creationDisposition = CREATE_ALWAYS;
+ default:
+ ASSERT_NOT_REACHED();
+ }
- return proposedPath.latin1();
+ String destination = path;
+ return CreateFile(destination.charactersWithNullTermination(), desiredAccess, 0, 0, creationDisposition, FILE_ATTRIBUTE_NORMAL, 0);
}
void closeFile(PlatformFileHandle& handle)
diff --git a/Source/WebCore/platform/wx/FileSystemWx.cpp b/Source/WebCore/platform/wx/FileSystemWx.cpp
index bfcaf88..3c2b453 100644
--- a/Source/WebCore/platform/wx/FileSystemWx.cpp
+++ b/Source/WebCore/platform/wx/FileSystemWx.cpp
@@ -107,11 +107,11 @@ String directoryName(const String& path)
return wxFileName(path).GetPath();
}
-CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
+String openTemporaryFile(const String&, PlatformFileHandle& handle)
{
notImplemented();
handle = invalidPlatformFileHandle;
- return CString();
+ return String();
}
void closeFile(PlatformFileHandle&)
diff --git a/Source/WebCore/platform/wx/LocalizedStringsWx.cpp b/Source/WebCore/platform/wx/LocalizedStringsWx.cpp
index 835c3cd..8ec791e 100644
--- a/Source/WebCore/platform/wx/LocalizedStringsWx.cpp
+++ b/Source/WebCore/platform/wx/LocalizedStringsWx.cpp
@@ -212,7 +212,7 @@ String contextMenuItemTagSearchWeb()
return String("Search Web");
}
-String contextMenuItemTagLookUpInDictionary()
+String contextMenuItemTagLookUpInDictionary(const String&)
{
return String("Look Up in Dictionary");
}