summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform')
-rw-r--r--Source/WebCore/platform/AsyncFileSystem.cpp4
-rw-r--r--Source/WebCore/platform/AsyncFileSystem.h10
-rw-r--r--Source/WebCore/platform/ContextMenuItem.h3
-rw-r--r--Source/WebCore/platform/DragData.h16
-rw-r--r--Source/WebCore/platform/DragImage.cpp7
-rw-r--r--Source/WebCore/platform/DragImage.h1
-rw-r--r--Source/WebCore/platform/FileChooser.cpp8
-rw-r--r--Source/WebCore/platform/FileChooser.h1
-rw-r--r--Source/WebCore/platform/FileSystem.cpp16
-rw-r--r--Source/WebCore/platform/FileSystem.h43
-rw-r--r--Source/WebCore/platform/KURL.cpp115
-rw-r--r--Source/WebCore/platform/KURL.h6
-rw-r--r--Source/WebCore/platform/KURLGoogle.cpp87
-rw-r--r--Source/WebCore/platform/KURLGooglePrivate.h20
-rw-r--r--Source/WebCore/platform/Length.cpp13
-rw-r--r--Source/WebCore/platform/Length.h5
-rw-r--r--Source/WebCore/platform/LinkHash.cpp2
-rw-r--r--Source/WebCore/platform/LocalizationStrategy.h3
-rw-r--r--Source/WebCore/platform/LocalizedStrings.cpp7
-rw-r--r--Source/WebCore/platform/LocalizedStrings.h3
-rw-r--r--Source/WebCore/platform/MIMETypeRegistry.cpp18
-rw-r--r--Source/WebCore/platform/MIMETypeRegistry.h3
-rw-r--r--Source/WebCore/platform/PlatformGestureEvent.h66
-rw-r--r--Source/WebCore/platform/PlatformWheelEvent.h6
-rw-r--r--Source/WebCore/platform/PopupMenuStyle.h7
-rw-r--r--Source/WebCore/platform/SchemeRegistry.cpp38
-rw-r--r--Source/WebCore/platform/SchemeRegistry.h5
-rw-r--r--Source/WebCore/platform/ScrollAnimator.cpp41
-rw-r--r--Source/WebCore/platform/ScrollAnimator.h30
-rw-r--r--Source/WebCore/platform/ScrollView.cpp177
-rw-r--r--Source/WebCore/platform/ScrollView.h28
-rw-r--r--Source/WebCore/platform/ScrollableArea.cpp63
-rw-r--r--Source/WebCore/platform/ScrollableArea.h38
-rw-r--r--Source/WebCore/platform/Scrollbar.cpp20
-rw-r--r--Source/WebCore/platform/ScrollbarThemeComposite.cpp20
-rw-r--r--Source/WebCore/platform/URLString.h52
-rw-r--r--Source/WebCore/platform/android/TemporaryLinkStubs.cpp12
-rw-r--r--Source/WebCore/platform/audio/FFTFrame.h39
-rw-r--r--Source/WebCore/platform/audio/FFTFrameStub.cpp6
-rw-r--r--Source/WebCore/platform/audio/chromium/AudioBusChromium.cpp2
-rw-r--r--Source/WebCore/platform/audio/fftw/FFTFrameFFTW.cpp301
-rw-r--r--Source/WebCore/platform/audio/mac/FFTFrameMac.cpp4
-rw-r--r--Source/WebCore/platform/audio/mkl/FFTFrameMKL.cpp4
-rw-r--r--Source/WebCore/platform/brew/MIMETypeRegistryBrew.cpp4
-rw-r--r--Source/WebCore/platform/brew/SystemTimeBrew.cpp11
-rw-r--r--Source/WebCore/platform/cf/BinaryPropertyList.cpp2
-rw-r--r--Source/WebCore/platform/cf/FileSystemCF.cpp17
-rw-r--r--Source/WebCore/platform/chromium/ChromiumDataObject.cpp4
-rw-r--r--Source/WebCore/platform/chromium/ChromiumDataObject.h2
-rw-r--r--Source/WebCore/platform/chromium/ClipboardChromium.cpp2
-rw-r--r--Source/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp11
-rw-r--r--Source/WebCore/platform/chromium/PlatformBridge.h7
-rw-r--r--Source/WebCore/platform/chromium/PopupMenuChromium.cpp119
-rw-r--r--Source/WebCore/platform/chromium/PopupMenuChromium.h23
-rw-r--r--Source/WebCore/platform/chromium/ReadableDataObject.cpp19
-rw-r--r--Source/WebCore/platform/chromium/ReadableDataObject.h7
-rw-r--r--Source/WebCore/platform/chromium/ScrollbarThemeChromium.cpp2
-rw-r--r--Source/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm4
-rw-r--r--Source/WebCore/platform/efl/MIMETypeRegistryEfl.cpp5
-rw-r--r--Source/WebCore/platform/efl/RenderThemeEfl.cpp79
-rw-r--r--Source/WebCore/platform/efl/RenderThemeEfl.h17
-rw-r--r--Source/WebCore/platform/efl/SystemTimeEfl.cpp9
-rw-r--r--Source/WebCore/platform/efl/TemporaryLinkStubs.cpp6
-rw-r--r--Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp8
-rw-r--r--Source/WebCore/platform/graphics/ContextShadow.h2
-rw-r--r--Source/WebCore/platform/graphics/Extensions3D.h5
-rw-r--r--Source/WebCore/platform/graphics/FloatQuad.h6
-rw-r--r--Source/WebCore/platform/graphics/FloatRect.cpp20
-rw-r--r--Source/WebCore/platform/graphics/FloatRect.h10
-rw-r--r--Source/WebCore/platform/graphics/Font.cpp74
-rw-r--r--Source/WebCore/platform/graphics/Font.h25
-rw-r--r--Source/WebCore/platform/graphics/FontCache.cpp11
-rw-r--r--Source/WebCore/platform/graphics/FontDescription.h9
-rw-r--r--Source/WebCore/platform/graphics/FontFastPath.cpp13
-rw-r--r--Source/WebCore/platform/graphics/FontMetrics.h122
-rw-r--r--Source/WebCore/platform/graphics/FontWidthVariant.h35
-rw-r--r--Source/WebCore/platform/graphics/GlyphBuffer.h17
-rw-r--r--Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp2
-rw-r--r--Source/WebCore/platform/graphics/GraphicsContext.cpp52
-rw-r--r--Source/WebCore/platform/graphics/GraphicsContext.h23
-rw-r--r--Source/WebCore/platform/graphics/GraphicsContext3D.cpp4
-rw-r--r--Source/WebCore/platform/graphics/GraphicsContext3D.h16
-rw-r--r--Source/WebCore/platform/graphics/Icon.h7
-rw-r--r--Source/WebCore/platform/graphics/IntRect.cpp16
-rw-r--r--Source/WebCore/platform/graphics/IntRect.h26
-rw-r--r--Source/WebCore/platform/graphics/IntRectHash.h59
-rw-r--r--Source/WebCore/platform/graphics/IntSizeHash.h16
-rw-r--r--Source/WebCore/platform/graphics/MediaPlayer.cpp20
-rw-r--r--Source/WebCore/platform/graphics/MediaPlayer.h5
-rw-r--r--Source/WebCore/platform/graphics/MediaPlayerPrivate.h4
-rw-r--r--Source/WebCore/platform/graphics/ShadowBlur.cpp733
-rw-r--r--Source/WebCore/platform/graphics/ShadowBlur.h105
-rw-r--r--Source/WebCore/platform/graphics/SimpleFontData.cpp38
-rw-r--r--Source/WebCore/platform/graphics/SimpleFontData.h16
-rw-r--r--Source/WebCore/platform/graphics/StringTruncator.cpp2
-rw-r--r--Source/WebCore/platform/graphics/TextRun.h23
-rw-r--r--Source/WebCore/platform/graphics/TiledBackingStore.cpp20
-rw-r--r--Source/WebCore/platform/graphics/WidthIterator.cpp74
-rw-r--r--Source/WebCore/platform/graphics/WidthIterator.h7
-rw-r--r--Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp4
-rw-r--r--Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h8
-rw-r--r--Source/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm55
-rw-r--r--Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp401
-rw-r--r--Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.h58
-rw-r--r--Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHostClient.h43
-rw-r--r--Source/WebCore/platform/graphics/ca/win/LegacyCACFLayerTreeHost.cpp401
-rw-r--r--Source/WebCore/platform/graphics/ca/win/LegacyCACFLayerTreeHost.h82
-rw-r--r--Source/WebCore/platform/graphics/ca/win/PlatformCAAnimationWin.cpp51
-rw-r--r--Source/WebCore/platform/graphics/ca/win/WKCACFViewLayerTreeHost.cpp160
-rw-r--r--Source/WebCore/platform/graphics/ca/win/WKCACFViewLayerTreeHost.h65
-rw-r--r--Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp4
-rw-r--r--Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h3
-rw-r--r--Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp12
-rw-r--r--Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp41
-rw-r--r--Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp123
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp14
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageCG.cpp4
-rw-r--r--Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp38
-rw-r--r--Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.h4
-rw-r--r--Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp17
-rw-r--r--Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h3
-rw-r--r--Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp15
-rw-r--r--Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h4
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp37
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp29
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontLinux.cpp19
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp16
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h5
-rw-r--r--Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp24
-rw-r--r--Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp21
-rw-r--r--Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h3
-rw-r--r--Source/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp4
-rw-r--r--Source/WebCore/platform/graphics/chromium/IconChromium.cpp (renamed from Source/WebCore/platform/graphics/chromium/IconChromiumWin.cpp)23
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerChromium.cpp9
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerChromium.h13
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp83
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerTexture.cpp1
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp37
-rw-r--r--Source/WebCore/platform/graphics/chromium/PlatformIcon.h6
-rw-r--r--Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp126
-rw-r--r--Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h19
-rw-r--r--Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp24
-rw-r--r--Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp34
-rw-r--r--Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp6
-rw-r--r--Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp10
-rw-r--r--Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp18
-rw-r--r--Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h2
-rw-r--r--Source/WebCore/platform/graphics/cocoa/FontPlatformData.h16
-rw-r--r--Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm52
-rw-r--r--Source/WebCore/platform/graphics/efl/FontEfl.cpp5
-rw-r--r--Source/WebCore/platform/graphics/filters/DistantLightSource.cpp80
-rw-r--r--Source/WebCore/platform/graphics/filters/DistantLightSource.h2
-rw-r--r--Source/WebCore/platform/graphics/filters/FEDiffuseLighting.cpp25
-rw-r--r--Source/WebCore/platform/graphics/filters/FEDiffuseLighting.h10
-rw-r--r--Source/WebCore/platform/graphics/filters/FilterEffect.cpp16
-rw-r--r--Source/WebCore/platform/graphics/filters/FilterEffect.h1
-rw-r--r--Source/WebCore/platform/graphics/filters/LightSource.cpp149
-rw-r--r--Source/WebCore/platform/graphics/filters/LightSource.h11
-rw-r--r--Source/WebCore/platform/graphics/filters/PointLightSource.cpp91
-rw-r--r--Source/WebCore/platform/graphics/filters/PointLightSource.h3
-rw-r--r--Source/WebCore/platform/graphics/filters/SpotLightSource.cpp198
-rw-r--r--Source/WebCore/platform/graphics/filters/SpotLightSource.h8
-rw-r--r--Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp2
-rw-r--r--Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp21
-rw-r--r--Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp16
-rw-r--r--Source/WebCore/platform/graphics/gpu/LoopBlinnPathCache.cpp86
-rw-r--r--Source/WebCore/platform/graphics/gpu/LoopBlinnPathCache.h123
-rw-r--r--Source/WebCore/platform/graphics/gpu/LoopBlinnPathProcessor.cpp1228
-rw-r--r--Source/WebCore/platform/graphics/gpu/LoopBlinnPathProcessor.h126
-rw-r--r--Source/WebCore/platform/graphics/gpu/LoopBlinnShader.cpp59
-rw-r--r--Source/WebCore/platform/graphics/gpu/LoopBlinnShader.h58
-rw-r--r--Source/WebCore/platform/graphics/gpu/LoopBlinnSolidFillShader.cpp62
-rw-r--r--Source/WebCore/platform/graphics/gpu/LoopBlinnSolidFillShader.h52
-rw-r--r--Source/WebCore/platform/graphics/gpu/Shader.cpp169
-rw-r--r--Source/WebCore/platform/graphics/gpu/Shader.h27
-rw-r--r--Source/WebCore/platform/graphics/gpu/SolidFillShader.cpp20
-rw-r--r--Source/WebCore/platform/graphics/gpu/TexShader.cpp25
-rw-r--r--Source/WebCore/platform/graphics/gpu/Texture.cpp2
-rw-r--r--Source/WebCore/platform/graphics/gpu/TilingData.cpp8
-rw-r--r--Source/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm2
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp17
-rw-r--r--Source/WebCore/platform/graphics/gtk/FontGtk.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/haiku/FontHaiku.cpp5
-rw-r--r--Source/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp10
-rw-r--r--Source/WebCore/platform/graphics/mac/ComplexTextController.cpp82
-rw-r--r--Source/WebCore/platform/graphics/mac/ComplexTextController.h15
-rw-r--r--Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp3
-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.mm9
-rw-r--r--Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp4
-rw-r--r--Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm8
-rw-r--r--Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm2
-rw-r--r--Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm63
-rw-r--r--Source/WebCore/platform/graphics/mac/WebGLLayer.mm4
-rw-r--r--Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp8
-rw-r--r--Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp28
-rw-r--r--Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp4
-rw-r--r--Source/WebCore/platform/graphics/pango/FontCustomPlatformDataPango.cpp2
-rw-r--r--Source/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp22
-rw-r--r--Source/WebCore/platform/graphics/qt/ContextShadowQt.cpp5
-rw-r--r--Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp4
-rw-r--r--Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h3
-rw-r--r--Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp2
-rw-r--r--Source/WebCore/platform/graphics/qt/FontQt.cpp37
-rw-r--r--Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp30
-rw-r--r--Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp30
-rw-r--r--Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp16
-rw-r--r--Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h4
-rw-r--r--Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp14
-rw-r--r--Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp2
-rw-r--r--Source/WebCore/platform/graphics/qt/ImageQt.cpp23
-rw-r--r--Source/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp2
-rw-r--r--Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp19
-rw-r--r--Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h2
-rw-r--r--Source/WebCore/platform/graphics/qt/PathQt.cpp21
-rw-r--r--Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp22
-rw-r--r--Source/WebCore/platform/graphics/qt/TransparencyLayer.h3
-rw-r--r--Source/WebCore/platform/graphics/skia/FloatRectSkia.cpp2
-rw-r--r--Source/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp13
-rw-r--r--Source/WebCore/platform/graphics/skia/FontCustomPlatformData.h3
-rw-r--r--Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp4
-rw-r--r--Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp32
-rw-r--r--Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp121
-rw-r--r--Source/WebCore/platform/graphics/skia/IntRectSkia.cpp4
-rw-r--r--Source/WebCore/platform/graphics/skia/PathSkia.cpp20
-rw-r--r--Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp79
-rw-r--r--Source/WebCore/platform/graphics/skia/PlatformContextSkia.h8
-rw-r--r--Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h4
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp12
-rw-r--r--Source/WebCore/platform/graphics/transforms/AffineTransform.cpp14
-rw-r--r--Source/WebCore/platform/graphics/transforms/AffineTransform.h6
-rw-r--r--Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h2
-rw-r--r--Source/WebCore/platform/graphics/transforms/MatrixTransformOperation.h2
-rw-r--r--Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.cpp25
-rw-r--r--Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h14
-rw-r--r--Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp48
-rw-r--r--Source/WebCore/platform/graphics/transforms/TransformationMatrix.h18
-rw-r--r--Source/WebCore/platform/graphics/win/FontCGWin.cpp10
-rw-r--r--Source/WebCore/platform/graphics/win/FontCustomPlatformData.cpp13
-rw-r--r--Source/WebCore/platform/graphics/win/FontCustomPlatformData.h3
-rw-r--r--Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp2
-rw-r--r--Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h2
-rw-r--r--Source/WebCore/platform/graphics/win/FontWin.cpp9
-rw-r--r--Source/WebCore/platform/graphics/win/GraphicsContextWin.cpp2
-rw-r--r--Source/WebCore/platform/graphics/win/IconWin.cpp11
-rw-r--r--Source/WebCore/platform/graphics/win/IntRectWin.cpp2
-rw-r--r--Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp21
-rw-r--r--Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.h13
-rw-r--r--Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp2
-rw-r--r--Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp2
-rw-r--r--Source/WebCore/platform/graphics/win/QTMovie.cpp108
-rw-r--r--Source/WebCore/platform/graphics/win/QTMovieGWorld.cpp8
-rw-r--r--Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp41
-rw-r--r--Source/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp21
-rw-r--r--Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp32
-rw-r--r--Source/WebCore/platform/graphics/win/UniscribeController.cpp6
-rw-r--r--Source/WebCore/platform/graphics/win/WKCAImageQueue.cpp4
-rw-r--r--Source/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp12
-rw-r--r--Source/WebCore/platform/graphics/wince/FontCustomPlatformData.h3
-rw-r--r--Source/WebCore/platform/graphics/wince/FontWinCE.cpp8
-rw-r--r--Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp41
-rw-r--r--Source/WebCore/platform/graphics/wince/PlatformPathWinCE.cpp10
-rw-r--r--Source/WebCore/platform/graphics/wince/SharedBitmap.cpp10
-rw-r--r--Source/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp17
-rw-r--r--Source/WebCore/platform/graphics/wx/FontCustomPlatformData.cpp2
-rw-r--r--Source/WebCore/platform/graphics/wx/FontCustomPlatformData.h4
-rw-r--r--Source/WebCore/platform/graphics/wx/FontPlatformData.h4
-rw-r--r--Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp2
-rw-r--r--Source/WebCore/platform/graphics/wx/FontWx.cpp10
-rw-r--r--Source/WebCore/platform/graphics/wx/GraphicsContextWx.cpp4
-rw-r--r--Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp12
-rw-r--r--Source/WebCore/platform/gtk/GtkVersioning.h5
-rw-r--r--Source/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp5
-rw-r--r--Source/WebCore/platform/gtk/RenderThemeGtk.cpp112
-rw-r--r--Source/WebCore/platform/gtk/RenderThemeGtk.h16
-rw-r--r--Source/WebCore/platform/gtk/RenderThemeGtk2.cpp80
-rw-r--r--Source/WebCore/platform/gtk/RenderThemeGtk3.cpp115
-rw-r--r--Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp7
-rw-r--r--Source/WebCore/platform/gtk/ScrollbarThemeGtk2.cpp184
-rw-r--r--Source/WebCore/platform/gtk/WidgetRenderingContext.cpp24
-rw-r--r--Source/WebCore/platform/gtk/WidgetRenderingContext.h7
-rw-r--r--Source/WebCore/platform/gtk/gtk2drawing.c552
-rw-r--r--Source/WebCore/platform/gtk/gtkdrawing.h217
-rw-r--r--Source/WebCore/platform/haiku/MIMETypeRegistryHaiku.cpp4
-rw-r--r--Source/WebCore/platform/image-decoders/ImageDecoder.cpp94
-rw-r--r--Source/WebCore/platform/image-decoders/ImageDecoder.h159
-rw-r--r--Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp4
-rw-r--r--Source/WebCore/platform/image-decoders/cg/ImageDecoderCG.cpp2
-rw-r--r--Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp24
-rw-r--r--Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp8
-rw-r--r--Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h1
-rw-r--r--Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp2
-rw-r--r--Source/WebCore/platform/image-decoders/qt/ImageFrameQt.cpp9
-rw-r--r--Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp9
-rw-r--r--Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp2
-rw-r--r--Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h1
-rw-r--r--Source/WebCore/platform/mac/DragImageMac.mm210
-rw-r--r--Source/WebCore/platform/mac/EmptyProtocolDefinitions.h5
-rw-r--r--Source/WebCore/platform/mac/FileSystemMac.mm25
-rw-r--r--Source/WebCore/platform/mac/MIMETypeRegistryMac.mm3
-rw-r--r--Source/WebCore/platform/mac/PasteboardMac.mm3
-rw-r--r--Source/WebCore/platform/mac/PopupMenuMac.mm25
-rw-r--r--Source/WebCore/platform/mac/ScrollAnimatorMac.h79
-rw-r--r--Source/WebCore/platform/mac/ScrollAnimatorMac.mm923
-rw-r--r--Source/WebCore/platform/mac/ScrollViewMac.mm4
-rw-r--r--Source/WebCore/platform/mac/ScrollbarThemeMac.h7
-rw-r--r--Source/WebCore/platform/mac/ScrollbarThemeMac.mm126
-rw-r--r--Source/WebCore/platform/mac/WebCoreSystemInterface.h43
-rw-r--r--Source/WebCore/platform/mac/WebCoreSystemInterface.mm43
-rw-r--r--Source/WebCore/platform/mac/WheelEventMac.mm3
-rw-r--r--Source/WebCore/platform/mac/WidgetMac.mm4
-rw-r--r--Source/WebCore/platform/network/BlobRegistryImpl.cpp4
-rw-r--r--Source/WebCore/platform/network/BlobResourceHandle.cpp50
-rw-r--r--Source/WebCore/platform/network/BlobResourceHandle.h3
-rw-r--r--Source/WebCore/platform/network/FormData.cpp22
-rw-r--r--Source/WebCore/platform/network/FormDataBuilder.cpp5
-rw-r--r--Source/WebCore/platform/network/ProtectionSpaceHash.h6
-rw-r--r--Source/WebCore/platform/network/ResourceHandle.h4
-rw-r--r--Source/WebCore/platform/network/ResourceHandleInternal.h13
-rw-r--r--Source/WebCore/platform/network/ResourceRequestBase.cpp22
-rw-r--r--Source/WebCore/platform/network/ResourceRequestBase.h18
-rw-r--r--Source/WebCore/platform/network/cf/DNSCFNet.cpp1
-rw-r--r--Source/WebCore/platform/network/cf/DownloadBundle.h43
-rw-r--r--Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp13
-rw-r--r--Source/WebCore/platform/network/cf/LoaderRunLoopCF.cpp1
-rw-r--r--Source/WebCore/platform/network/cf/LoaderRunLoopCF.h2
-rw-r--r--Source/WebCore/platform/network/cf/ProxyServerCFNet.cpp4
-rw-r--r--Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp7
-rw-r--r--Source/WebCore/platform/network/cf/ResourceRequestCFNet.cpp49
-rw-r--r--Source/WebCore/platform/network/cf/ResourceRequestCFNet.h47
-rw-r--r--Source/WebCore/platform/network/cf/SocketStreamHandle.h1
-rw-r--r--Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp1
-rw-r--r--Source/WebCore/platform/network/chromium/ResourceRequest.cpp2
-rw-r--r--Source/WebCore/platform/network/chromium/ResourceRequest.h10
-rw-r--r--Source/WebCore/platform/network/chromium/ResourceResponse.cpp4
-rw-r--r--Source/WebCore/platform/network/chromium/ResourceResponse.h15
-rw-r--r--Source/WebCore/platform/network/mac/AuthenticationMac.mm15
-rw-r--r--Source/WebCore/platform/network/mac/FormDataStreamMac.mm4
-rw-r--r--Source/WebCore/platform/network/mac/ResourceHandleMac.mm7
-rw-r--r--Source/WebCore/platform/network/mac/ResourceRequestMac.mm22
-rw-r--r--Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.cpp20
-rw-r--r--Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.h4
-rw-r--r--Source/WebCore/platform/network/soup/CookieJarSoup.cpp8
-rw-r--r--Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp375
-rw-r--r--Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp6
-rw-r--r--Source/WebCore/platform/network/soup/SocketStreamHandle.h2
-rw-r--r--Source/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp35
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-directory-input-stream.c200
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-directory-input-stream.h62
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-http-input-stream.c922
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-http-input-stream.h77
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-request-data.c170
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-request-data.h52
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-request-file.c331
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-request-file.h54
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-request-http.c356
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-request-http.h54
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-request.c312
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-request.h100
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-requester.c188
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-requester.h81
-rw-r--r--Source/WebCore/platform/network/soup/cache/webkit/soup-cache-private.h42
-rw-r--r--Source/WebCore/platform/network/soup/cache/webkit/soup-cache.c1677
-rw-r--r--Source/WebCore/platform/network/soup/cache/webkit/soup-cache.h106
-rw-r--r--Source/WebCore/platform/network/win/DownloadBundleWin.cpp196
-rw-r--r--Source/WebCore/platform/qt/ClipboardQt.h80
-rw-r--r--Source/WebCore/platform/qt/CookieJarQt.cpp8
-rw-r--r--Source/WebCore/platform/qt/DragDataQt.cpp3
-rw-r--r--Source/WebCore/platform/qt/MIMETypeRegistryQt.cpp5
-rw-r--r--Source/WebCore/platform/qt/RenderThemeQt.cpp27
-rw-r--r--Source/WebCore/platform/qt/ScrollbarQt.cpp5
-rw-r--r--Source/WebCore/platform/sql/SQLiteStatement.cpp40
-rw-r--r--Source/WebCore/platform/sql/SQLiteStatement.h2
-rw-r--r--Source/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumPosix.cpp1081
-rw-r--r--Source/WebCore/platform/text/Base64.cpp6
-rw-r--r--Source/WebCore/platform/text/Base64.h29
-rw-r--r--Source/WebCore/platform/text/BidiResolver.h10
-rw-r--r--Source/WebCore/platform/text/CharacterNames.h90
-rw-r--r--Source/WebCore/platform/text/LocalizedNumber.h (renamed from Source/WebCore/platform/graphics/chromium/IconChromiumMac.cpp)45
-rw-r--r--Source/WebCore/platform/text/LocalizedNumberNone.cpp (renamed from Source/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp)27
-rw-r--r--Source/WebCore/platform/text/RegularExpression.cpp91
-rw-r--r--Source/WebCore/platform/text/SegmentedString.cpp15
-rw-r--r--Source/WebCore/platform/text/SegmentedString.h12
-rw-r--r--Source/WebCore/platform/text/TextCodecICU.cpp2
-rw-r--r--Source/WebCore/platform/text/TextCodecUTF16.cpp2
-rw-r--r--Source/WebCore/platform/text/TextCodecUTF8.cpp276
-rw-r--r--Source/WebCore/platform/text/TextCodecUTF8.h52
-rw-r--r--Source/WebCore/platform/text/TextEncodingRegistry.cpp15
-rw-r--r--Source/WebCore/platform/text/mac/TextCodecMac.cpp4
-rw-r--r--Source/WebCore/platform/text/transcoder/FontTranscoder.cpp2
-rw-r--r--Source/WebCore/platform/win/BString.cpp11
-rw-r--r--Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp277
-rw-r--r--Source/WebCore/platform/win/ClipboardUtilitiesWin.h11
-rw-r--r--Source/WebCore/platform/win/ClipboardWin.cpp128
-rw-r--r--Source/WebCore/platform/win/ClipboardWin.h7
-rw-r--r--Source/WebCore/platform/win/ContextMenuWin.cpp3
-rw-r--r--Source/WebCore/platform/win/CursorWin.cpp4
-rw-r--r--Source/WebCore/platform/win/DragDataWin.cpp145
-rw-r--r--Source/WebCore/platform/win/DragImageWin.cpp147
-rw-r--r--Source/WebCore/platform/win/FileChooserWin.cpp3
-rw-r--r--Source/WebCore/platform/win/LoggingWin.cpp2
-rw-r--r--Source/WebCore/platform/win/MIMETypeRegistryWin.cpp4
-rw-r--r--Source/WebCore/platform/win/PopupMenuWin.cpp19
-rw-r--r--Source/WebCore/platform/win/PopupMenuWin.h2
-rw-r--r--Source/WebCore/platform/win/SystemTimeWin.cpp11
-rw-r--r--Source/WebCore/platform/win/WCDataObject.cpp14
-rw-r--r--Source/WebCore/platform/win/WCDataObject.h6
-rw-r--r--Source/WebCore/platform/wince/DragDataWinCE.cpp5
-rw-r--r--Source/WebCore/platform/wince/KeygenWinCE.cpp5
-rw-r--r--Source/WebCore/platform/wince/MIMETypeRegistryWinCE.cpp4
-rw-r--r--Source/WebCore/platform/wx/MimeTypeRegistryWx.cpp5
-rw-r--r--Source/WebCore/platform/wx/RenderThemeWx.cpp1
-rw-r--r--Source/WebCore/platform/wx/SystemTimeWx.cpp10
419 files changed, 11646 insertions, 9771 deletions
diff --git a/Source/WebCore/platform/AsyncFileSystem.cpp b/Source/WebCore/platform/AsyncFileSystem.cpp
index b85a487..b1a3fe2 100644
--- a/Source/WebCore/platform/AsyncFileSystem.cpp
+++ b/Source/WebCore/platform/AsyncFileSystem.cpp
@@ -46,7 +46,7 @@ bool AsyncFileSystem::isAvailable()
return false;
}
-PassOwnPtr<AsyncFileSystem> AsyncFileSystem::create(const String&)
+PassOwnPtr<AsyncFileSystem> AsyncFileSystem::create(Type, const String&)
{
notImplemented();
return 0;
@@ -68,7 +68,7 @@ void AsyncFileSystem::openFileSystem(const String& basePath, const String& stora
rootPath += typeString;
rootPath.append(PlatformFilePathSeparator);
- callbacks->didOpenFileSystem(name, AsyncFileSystem::create(rootPath));
+ callbacks->didOpenFileSystem(name, AsyncFileSystem::create(type, rootPath));
}
#endif
diff --git a/Source/WebCore/platform/AsyncFileSystem.h b/Source/WebCore/platform/AsyncFileSystem.h
index c34a644..f5207ce 100644
--- a/Source/WebCore/platform/AsyncFileSystem.h
+++ b/Source/WebCore/platform/AsyncFileSystem.h
@@ -65,7 +65,7 @@ public:
virtual bool waitForOperationToComplete() { return false; }
// Creates and returns a new platform-specific AsyncFileSystem instance if the platform has its own implementation.
- static PassOwnPtr<AsyncFileSystem> create(const String& rootPath);
+ static PassOwnPtr<AsyncFileSystem> create(Type, const String& rootPath);
// Opens a new file system. The create parameter specifies whether or not to create the path if it does not already exists.
static void openFileSystem(const String& basePath, const String& storageIdentifier, Type, bool create, PassOwnPtr<AsyncFileSystemCallbacks>);
@@ -132,12 +132,16 @@ public:
// Getter for this file system's root path.
String root() const { return m_platformRootPath; }
+ Type type() const { return m_type; }
+
protected:
- AsyncFileSystem(const String& platformRootPath)
- : m_platformRootPath(platformRootPath)
+ AsyncFileSystem(Type type, const String& platformRootPath)
+ : m_type(type)
+ , m_platformRootPath(platformRootPath)
{
}
+ Type m_type;
String m_platformRootPath;
};
diff --git a/Source/WebCore/platform/ContextMenuItem.h b/Source/WebCore/platform/ContextMenuItem.h
index 6e84131..6595711 100644
--- a/Source/WebCore/platform/ContextMenuItem.h
+++ b/Source/WebCore/platform/ContextMenuItem.h
@@ -65,6 +65,9 @@ namespace WebCore {
ContextMenuItemTagOpenImageInNewWindow,
ContextMenuItemTagDownloadImageToDisk,
ContextMenuItemTagCopyImageToClipboard,
+#if PLATFORM(QT)
+ ContextMenuItemTagCopyImageUrlToClipboard,
+#endif
ContextMenuItemTagOpenFrameInNewWindow,
ContextMenuItemTagCopy,
ContextMenuItemTagGoBack,
diff --git a/Source/WebCore/platform/DragData.h b/Source/WebCore/platform/DragData.h
index 42d0d3a..b89748e 100644
--- a/Source/WebCore/platform/DragData.h
+++ b/Source/WebCore/platform/DragData.h
@@ -31,6 +31,7 @@
#include "IntPoint.h"
#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
#include <wtf/Vector.h>
#if PLATFORM(MAC)
@@ -51,6 +52,7 @@ QT_END_NAMESPACE
typedef const QMimeData* DragDataRef;
#elif PLATFORM(WIN)
typedef struct IDataObject* DragDataRef;
+#include <wtf/text/WTFString.h>
#elif PLATFORM(WX)
typedef class wxDataObject* DragDataRef;
#elif PLATFORM(GTK)
@@ -84,7 +86,11 @@ enum DragApplicationFlags {
DragApplicationHasAttachedSheet = 4,
DragApplicationIsCopyKeyDown = 8
};
-
+
+#if PLATFORM(WIN)
+typedef HashMap<UINT, Vector<String> > DragDataMap;
+#endif
+
class DragData {
public:
enum FilenameConversionPolicy { DoNotConvertFilenames, ConvertFilenames };
@@ -92,7 +98,10 @@ public:
// clientPosition is taken to be the position of the drag event within the target window, with (0,0) at the top left
DragData(DragDataRef, const IntPoint& clientPosition, const IntPoint& globalPosition, DragOperation, DragApplicationFlags = DragApplicationNone);
DragData(const String& dragStorageName, const IntPoint& clientPosition, const IntPoint& globalPosition, DragOperation, DragApplicationFlags = DragApplicationNone);
-
+#if PLATFORM(WIN)
+ DragData(const DragDataMap&, const IntPoint& clientPosition, const IntPoint& globalPosition, DragOperation sourceOperationMask, DragApplicationFlags = DragApplicationNone);
+ const DragDataMap& dragDataMap();
+#endif
const IntPoint& clientPosition() const { return m_clientPosition; }
const IntPoint& globalPosition() const { return m_globalPosition; }
DragApplicationFlags flags() { return m_applicationFlags; }
@@ -119,6 +128,9 @@ private:
#if PLATFORM(MAC)
RetainPtr<NSPasteboard> m_pasteboard;
#endif
+#if PLATFORM(WIN)
+ DragDataMap m_dragDataMap;
+#endif
};
}
diff --git a/Source/WebCore/platform/DragImage.cpp b/Source/WebCore/platform/DragImage.cpp
index 5fcafc1..64aaa0e 100644
--- a/Source/WebCore/platform/DragImage.cpp
+++ b/Source/WebCore/platform/DragImage.cpp
@@ -73,6 +73,13 @@ DragImageRef createDragImageForSelection(Frame* frame)
return image;
}
+#if !PLATFORM(MAC) && (!PLATFORM(WIN) || OS(WINCE))
+DragImageRef createDragImageForLink(KURL&, const String&, Frame*)
+{
+ return 0;
+}
+#endif
+
} // namespace WebCore
#endif // ENABLE(DRAG_SUPPORT)
diff --git a/Source/WebCore/platform/DragImage.h b/Source/WebCore/platform/DragImage.h
index a371821..fcb980a 100644
--- a/Source/WebCore/platform/DragImage.h
+++ b/Source/WebCore/platform/DragImage.h
@@ -96,6 +96,7 @@ namespace WebCore {
DragImageRef createDragImageFromImage(Image*);
DragImageRef createDragImageForSelection(Frame*);
DragImageRef createDragImageIconForCachedImage(CachedImage*);
+ DragImageRef createDragImageForLink(KURL&, const String& label, Frame*);
void deleteDragImage(DragImageRef);
}
diff --git a/Source/WebCore/platform/FileChooser.cpp b/Source/WebCore/platform/FileChooser.cpp
index 90dd567..7e6d4ae 100644
--- a/Source/WebCore/platform/FileChooser.cpp
+++ b/Source/WebCore/platform/FileChooser.cpp
@@ -42,13 +42,19 @@ inline FileChooser::FileChooser(FileChooserClient* client, const Vector<String>&
, m_isInitializing(true)
{
m_filenames = initialFilenames;
+}
+
+void FileChooser::initialize()
+{
loadIcon();
m_isInitializing = false;
}
PassRefPtr<FileChooser> FileChooser::create(FileChooserClient* client, const Vector<String>& initialFilenames)
{
- return adoptRef(new FileChooser(client, initialFilenames));
+ RefPtr<FileChooser> chooser(adoptRef(new FileChooser(client, initialFilenames)));
+ chooser->initialize();
+ return chooser;
}
FileChooser::~FileChooser()
diff --git a/Source/WebCore/platform/FileChooser.h b/Source/WebCore/platform/FileChooser.h
index fa25406..ac5e0e6 100644
--- a/Source/WebCore/platform/FileChooser.h
+++ b/Source/WebCore/platform/FileChooser.h
@@ -81,6 +81,7 @@ public:
private:
FileChooser(FileChooserClient*, const Vector<String>& initialFilenames);
+ void initialize();
void loadIcon();
FileChooserClient* m_client;
diff --git a/Source/WebCore/platform/FileSystem.cpp b/Source/WebCore/platform/FileSystem.cpp
index 511f8aa..0f69b7f 100644
--- a/Source/WebCore/platform/FileSystem.cpp
+++ b/Source/WebCore/platform/FileSystem.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 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
@@ -101,4 +101,18 @@ String encodeForFileName(const String& inputStr)
return String(buffer.data(), p - buffer.data());
}
+#if !PLATFORM(MAC)
+
+bool canExcludeFromBackup()
+{
+ return false;
+}
+
+bool excludeFromBackup(const String&)
+{
+ return false;
+}
+
+#endif
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/FileSystem.h b/Source/WebCore/platform/FileSystem.h
index 4f088e1..d923fe6 100644
--- a/Source/WebCore/platform/FileSystem.h
+++ b/Source/WebCore/platform/FileSystem.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved.
* Copyright (C) 2008 Collabora, Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,6 +30,15 @@
#ifndef FileSystem_h
#define FileSystem_h
+#include "PlatformString.h"
+#include <time.h>
+#include <wtf/Forward.h>
+#include <wtf/Vector.h>
+
+#if PLATFORM(CF)
+#include <wtf/RetainPtr.h>
+#endif
+
#if PLATFORM(QT)
#include <QFile>
#include <QLibrary>
@@ -39,15 +48,9 @@
#endif
#if PLATFORM(CF) || (PLATFORM(QT) && defined(Q_WS_MAC))
-#include <CoreFoundation/CFBundle.h>
-#endif
-
-#include "PlatformString.h"
-#include <time.h>
-#include <wtf/Forward.h>
-#include <wtf/Vector.h>
-
+typedef struct __CFBundle* CFBundleRef;
typedef const struct __CFData* CFDataRef;
+#endif
#if OS(WINDOWS)
// These are to avoid including <winbase.h> in a header for Chromium
@@ -122,8 +125,6 @@ const PlatformFileHandle invalidPlatformFileHandle = reinterpret_cast<HANDLE>(-1
#elif PLATFORM(BREWMP)
typedef IFile* PlatformFileHandle;
const PlatformFileHandle invalidPlatformFileHandle = 0;
-typedef void* PlatformModule;
-typedef unsigned PlatformModuleVersion;
#elif PLATFORM(GTK)
typedef GFileIOStream* PlatformFileHandle;
const PlatformFileHandle invalidPlatformFileHandle = 0;
@@ -161,6 +162,9 @@ String homeDirectoryPath();
String pathGetFileName(const String&);
String directoryName(const String&);
+bool canExcludeFromBackup(); // Returns true if any file can ever be excluded from backup.
+bool excludeFromBackup(const String&); // Returns true if successful.
+
Vector<String> listDirectory(const String& path, const String& filter = String());
CString fileSystemRepresentation(const String&);
@@ -179,17 +183,18 @@ int writeToFile(PlatformFileHandle, const char* data, int length);
// Returns number of bytes actually written if successful, -1 otherwise.
int readFromFile(PlatformFileHandle, char* data, int length);
-// Methods for dealing with loadable modules
+// Functions for working with loadable modules.
bool unloadModule(PlatformModule);
// Encode a string for use within a file name.
String encodeForFileName(const String&);
-#if PLATFORM(WIN)
-String localUserSpecificStorageDirectory();
-String roamingUserSpecificStorageDirectory();
+#if PLATFORM(CF)
+RetainPtr<CFURLRef> pathAsURL(const String&);
+#endif
-bool safeCreateFile(const String&, CFDataRef);
+#if PLATFORM(CHROMIUM)
+String pathGetDisplayFileName(const String&);
#endif
#if PLATFORM(GTK)
@@ -198,8 +203,10 @@ String filenameForDisplay(const String&);
CString applicationDirectoryPath();
#endif
-#if PLATFORM(CHROMIUM)
-String pathGetDisplayFileName(const String&);
+#if PLATFORM(WIN) && !OS(WINCE)
+String localUserSpecificStorageDirectory();
+String roamingUserSpecificStorageDirectory();
+bool safeCreateFile(const String&, CFDataRef);
#endif
} // namespace WebCore
diff --git a/Source/WebCore/platform/KURL.cpp b/Source/WebCore/platform/KURL.cpp
index 60049df..f6a66ef 100644
--- a/Source/WebCore/platform/KURL.cpp
+++ b/Source/WebCore/platform/KURL.cpp
@@ -322,6 +322,12 @@ KURL::KURL(ParsedURLStringTag, const String& url)
ASSERT(url == m_string);
}
+KURL::KURL(ParsedURLStringTag, const URLString& url)
+{
+ parse(url.string());
+ ASSERT(url.string() == m_string);
+}
+
KURL::KURL(const KURL& base, const String& relative)
{
init(base, relative, UTF8Encoding());
@@ -921,11 +927,11 @@ String decodeURLEscapeSequences(const String& str, const TextEncoding& encoding)
&& isASCIIHexDigit(str[encodedRunEnd + 1])
&& isASCIIHexDigit(str[encodedRunEnd + 2]))
encodedRunEnd += 3;
+ searchPosition = encodedRunEnd;
if (encodedRunEnd == encodedRunPosition) {
++searchPosition;
continue;
}
- searchPosition = encodedRunEnd;
// Decode the %-escapes into bytes.
unsigned runLength = (encodedRunEnd - encodedRunPosition) / 3;
@@ -962,6 +968,14 @@ bool KURL::isLocalFile() const
return protocolIs("file");
}
+// Caution: This function does not bounds check.
+static void appendEscapedChar(char*& buffer, unsigned char c)
+{
+ *buffer++ = '%';
+ *buffer++ = hexDigits[c >> 4];
+ *buffer++ = hexDigits[c & 0xF];
+}
+
static void appendEscapingBadChars(char*& buffer, const char* strStart, size_t length)
{
char* p = buffer;
@@ -971,16 +985,37 @@ static void appendEscapingBadChars(char*& buffer, const char* strStart, size_t l
while (str < strEnd) {
unsigned char c = *str++;
if (isBadChar(c)) {
- if (c == '%' || c == '?') {
+ if (c == '%' || c == '?')
*p++ = c;
- } else if (c != 0x09 && c != 0x0a && c != 0x0d) {
- *p++ = '%';
- *p++ = hexDigits[c >> 4];
- *p++ = hexDigits[c & 0xF];
- }
- } else {
+ else if (c != 0x09 && c != 0x0a && c != 0x0d)
+ appendEscapedChar(p, c);
+ } else
*p++ = c;
+ }
+
+ buffer = p;
+}
+
+static void escapeAndAppendFragment(char*& buffer, const char* strStart, size_t length)
+{
+ char* p = buffer;
+
+ const char* str = strStart;
+ const char* strEnd = strStart + length;
+ while (str < strEnd) {
+ unsigned char c = *str++;
+ // Strip CR, LF and Tab from fragments, per:
+ // https://bugs.webkit.org/show_bug.cgi?id=8770
+ if (c == 0x09 || c == 0x0a || c == 0x0d)
+ continue;
+
+ // Chrome and IE allow non-ascii characters in fragments, however doing
+ // so would hit an ASSERT in checkEncodedString, so for now we don't.
+ if (c < 0x20 || c >= 127) {
+ appendEscapedChar(p, c);
+ continue;
}
+ *p++ = c;
}
buffer = p;
@@ -1021,11 +1056,6 @@ static int copyPathRemovingDots(char* dst, const char* src, int srcStart, int sr
baseStringPos += 3;
if (dst > bufferPathStart + 1)
dst--;
- // Note that these two while blocks differ subtly.
- // The first helps to remove multiple adjoining slashes as we rewind.
- // The +1 to bufferPathStart in the first while block prevents eating a leading slash
- while (dst > bufferPathStart + 1 && dst[-1] == '/')
- dst--;
while (dst > bufferPathStart && dst[-1] != '/')
dst--;
continue;
@@ -1070,6 +1100,38 @@ void KURL::parse(const String& string)
parse(buffer.data(), &string);
}
+static inline bool equal(const char* a, size_t lenA, const char* b, size_t lenB)
+{
+ if (lenA != lenB)
+ return false;
+ return !strncmp(a, b, lenA);
+}
+
+// List of default schemes is taken from google-url:
+// http://code.google.com/p/google-url/source/browse/trunk/src/url_canon_stdurl.cc#120
+static inline bool isDefaultPortForScheme(const char* port, size_t portLength, const char* scheme, size_t schemeLength)
+{
+ // This switch is theoretically a performance optimization. It came over when
+ // the code was moved from google-url, but may be removed later.
+ switch (schemeLength) {
+ case 2:
+ return equal("ws", 2, scheme, schemeLength) && equal("80", 2, port, portLength);
+ case 3:
+ if (equal("ftp", 3, scheme, schemeLength))
+ return equal("21", 2, port, portLength);
+ if (equal("wss", 3, scheme, schemeLength))
+ return equal("443", 3, port, portLength);
+ break;
+ case 4:
+ return equal("http", 4, scheme, schemeLength) && equal("80", 2, port, portLength);
+ case 5:
+ return equal("https", 5, scheme, schemeLength) && equal("443", 3, port, portLength);
+ case 6:
+ return equal("gopher", 6, scheme, schemeLength) && equal("70", 2, port, portLength);
+ }
+ return false;
+}
+
void KURL::parse(const char* url, const String* originalString)
{
if (!url || url[0] == '\0') {
@@ -1246,7 +1308,7 @@ void KURL::parse(const char* url, const String* originalString)
// copy in the scheme
const char *schemeEndPtr = url + schemeEnd;
while (strPtr < schemeEndPtr)
- *p++ = *strPtr++;
+ *p++ = toASCIILower(*strPtr++);
m_schemeEnd = p - buffer.data();
bool hostIsLocalHost = portEnd - userStart == 9
@@ -1305,13 +1367,16 @@ void KURL::parse(const char* url, const String* originalString)
}
m_hostEnd = p - buffer.data();
- // copy in the port
+ // Copy in the port if the URL has one (and it's not default).
if (hostEnd != portStart) {
- *p++ = ':';
- strPtr = url + portStart;
- const char *portEndPtr = url + portEnd;
- while (strPtr < portEndPtr)
- *p++ = *strPtr++;
+ const char* portStr = url + portStart;
+ size_t portLength = portEnd - portStart;
+ if (portLength && !isDefaultPortForScheme(portStr, portLength, buffer.data(), m_schemeEnd)) {
+ *p++ = ':';
+ const char* portEndPtr = url + portEnd;
+ while (portStr < portEndPtr)
+ *p++ = *portStr++;
+ }
}
m_portEnd = p - buffer.data();
} else
@@ -1349,7 +1414,7 @@ void KURL::parse(const char* url, const String* originalString)
// add fragment, escaping bad characters
if (fragmentEnd != queryEnd) {
*p++ = '#';
- appendEscapingBadChars(p, url + fragmentStart, fragmentEnd - fragmentStart);
+ escapeAndAppendFragment(p, url + fragmentStart, fragmentEnd - fragmentStart);
}
m_fragmentEnd = p - buffer.data();
@@ -1415,11 +1480,9 @@ String encodeWithURLEscapeSequences(const String& notEncodedString)
const char* strEnd = str + asUTF8.length();
while (str < strEnd) {
unsigned char c = *str++;
- if (isBadChar(c)) {
- *p++ = '%';
- *p++ = hexDigits[c >> 4];
- *p++ = hexDigits[c & 0xF];
- } else
+ if (isBadChar(c))
+ appendEscapedChar(p, c);
+ else
*p++ = c;
}
diff --git a/Source/WebCore/platform/KURL.h b/Source/WebCore/platform/KURL.h
index cbf0d8b..521e7ca 100644
--- a/Source/WebCore/platform/KURL.h
+++ b/Source/WebCore/platform/KURL.h
@@ -27,6 +27,7 @@
#define KURL_h
#include "PlatformString.h"
+#include "URLString.h"
#include <wtf/HashMap.h>
#if PLATFORM(CF)
@@ -74,6 +75,7 @@ public:
// It is usually best to avoid repeatedly parsing a string, unless memory saving outweigh the possible slow-downs.
KURL(ParsedURLStringTag, const char*);
KURL(ParsedURLStringTag, const String&);
+ KURL(ParsedURLStringTag, const URLString&);
// Resolves the relative URL with the given base URL. If provided, the
// TextEncoding is used to encode non-ASCII characers. The base URL can be
@@ -117,11 +119,13 @@ public:
bool canSetHostOrPort() const { return isHierarchical(); }
bool canSetPathname() const { return isHierarchical(); }
-
+
#if USE(GOOGLEURL)
const String& string() const { return m_url.string(); }
+ URLString urlString() const { return URLString(m_url.string()); }
#else
const String& string() const { return m_string; }
+ URLString urlString() const { return URLString(m_string); }
#endif
String protocol() const;
diff --git a/Source/WebCore/platform/KURLGoogle.cpp b/Source/WebCore/platform/KURLGoogle.cpp
index 6d63734..0697b33 100644
--- a/Source/WebCore/platform/KURLGoogle.cpp
+++ b/Source/WebCore/platform/KURLGoogle.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2007, 2008, 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2008, 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 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
@@ -63,8 +63,7 @@ static const int invalidPortNumber = 0xFFFF;
// canonicalizer.
class KURLCharsetConverter : public url_canon::CharsetConverter {
public:
- // The encoding parameter may be NULL, but in this case the object must not
- // be called.
+ // The encoding parameter may be 0, but in this case the object must not be called.
KURLCharsetConverter(const TextEncoding* encoding)
: m_encoding(encoding)
{
@@ -96,8 +95,8 @@ static inline void assertProtocolIsGood(const char* protocol)
}
// Returns the characters for the given string, or a pointer to a static empty
-// string if the input string is NULL. This will always ensure we have a non-
-// NULL character pointer since ReplaceComponents has special meaning for NULL.
+// string if the input string is null. This will always ensure we have a non-
+// null character pointer since ReplaceComponents has special meaning for null.
static inline const url_parse::UTF16Char* CharactersOrEmpty(const String& str)
{
static const url_parse::UTF16Char zero = 0;
@@ -194,15 +193,15 @@ void KURLGooglePrivate::init(const KURL& base,
init(base, relative.characters(), relative.length(), queryEncoding);
}
-// Note: code mostly duplicated below.
-void KURLGooglePrivate::init(const KURL& base, const char* rel, int relLength,
+template <typename CHAR>
+void KURLGooglePrivate::init(const KURL& base, const CHAR* rel, int relLength,
const TextEncoding* queryEncoding)
{
- // As a performance optimization, we do not use the charset converter if
- // encoding is UTF-8 or other Unicode encodings. Note that this is
- // per HTML5 2.5.3 (resolving URL). The URL canonicalizer will be
- // more efficient with no charset converter object because it
- // can do UTF-8 internally with no extra copies.
+ // As a performance optimization, we do not use the charset converter
+ // if encoding is UTF-8 or other Unicode encodings. Note that this is
+ // per HTML5 2.5.3 (resolving URL). The URL canonicalizer will be more
+ // efficient with no charset converter object because it can do UTF-8
+ // internally with no extra copies.
// We feel free to make the charset converter object every time since it's
// just a wrapper around a reference.
@@ -233,37 +232,11 @@ void KURLGooglePrivate::init(const KURL& base, const char* rel, int relLength,
else
setAscii(CString(output.data(), output.length()));
} else {
- // WebCore expects resolved URLs to be empty rather than NULL.
+ // WebCore expects resolved URLs to be empty rather than null.
setUtf8(CString("", 0));
}
}
-// Note: code mostly duplicated above. See FIXMEs and comments there.
-void KURLGooglePrivate::init(const KURL& base, const UChar* rel, int relLength,
- const TextEncoding* queryEncoding)
-{
- KURLCharsetConverter charsetConverterObject(queryEncoding);
- KURLCharsetConverter* charsetConverter =
- (!queryEncoding || isUnicodeEncoding(queryEncoding)) ? 0 :
- &charsetConverterObject;
-
- url_canon::RawCanonOutputT<char> output;
- const CString& baseStr = base.m_url.utf8String();
- m_isValid = url_util::ResolveRelative(baseStr.data(), baseStr.length(),
- base.m_url.m_parsed, rel, relLength,
- charsetConverter,
- &output, &m_parsed);
-
-
- if (m_isValid || output.length()) {
- if (m_parsed.ref.is_nonempty())
- setUtf8(CString(output.data(), output.length()));
- else
- setAscii(CString(output.data(), output.length()));
- } else
- setUtf8(CString("", 0));
-}
-
void KURLGooglePrivate::initProtocolInHTTPFamily()
{
if (!m_isValid) {
@@ -295,8 +268,8 @@ void KURLGooglePrivate::copyTo(KURLGooglePrivate* dest) const
String KURLGooglePrivate::componentString(const url_parse::Component& comp) const
{
if (!m_isValid || comp.len <= 0) {
- // KURL returns a NULL string if the URL is itself a NULL string, and an
- // empty string for other nonexistant entities.
+ // KURL returns a null string if the URL is itself a null string, and an
+ // empty string for other nonexistent entities.
if (utf8String().isNull())
return String();
return String("", 0);
@@ -330,9 +303,9 @@ void KURLGooglePrivate::replaceComponents(const Replacements& replacements)
const String& KURLGooglePrivate::string() const
{
if (!m_stringIsValid) {
- // Must special case the NULL case, since constructing the
- // string like we do below will generate an empty rather than
- // a NULL string.
+ // Handle the null case separately. Otherwise, constructing
+ // the string like we do below would generate the empty string,
+ // not the null string.
if (m_utf8.isNull())
m_string = String();
else if (m_utf8IsASCII)
@@ -346,17 +319,17 @@ const String& KURLGooglePrivate::string() const
// KURL ------------------------------------------------------------------------
-// Creates with NULL-terminated string input representing an absolute URL.
+// Creates with null-terminated string input representing an absolute URL.
// WebCore generally calls this only with hardcoded strings, so the input is
-// ASCII. We treat is as UTF-8 just in case.
+// ASCII. We treat it as UTF-8 just in case.
KURL::KURL(ParsedURLStringTag, const char *url)
{
- // FIXME The Mac code checks for beginning with a slash and converting to a
+ // FIXME The Mac code checks for beginning with a slash and converts it to
// file: URL. We will want to add this as well once we can compile on a
// system like that.
m_url.init(KURL(), url, strlen(url), 0);
- // The one-argument constructors should never generate a NULL string.
+ // The one-argument constructors should never generate a null string.
// This is a funny quirk of KURL.cpp (probably a bug) which we preserve.
if (m_url.utf8String().isNull())
m_url.setAscii(CString("", 0));
@@ -365,7 +338,7 @@ KURL::KURL(ParsedURLStringTag, const char *url)
// Initializes with a string representing an absolute URL. No encoding
// information is specified. This generally happens when a KURL is converted
// to a string and then converted back. In this case, the URL is already
-// canonical and in proper escaped form so needs no encoding. We treat it was
+// canonical and in proper escaped form so needs no encoding. We treat it as
// UTF-8 just in case.
KURL::KURL(ParsedURLStringTag, const String& url)
{
@@ -533,8 +506,8 @@ String KURL::user() const
String KURL::fragmentIdentifier() const
{
// Empty but present refs ("foo.com/bar#") should result in the empty
- // string, which m_url.componentString will produce. Nonexistant refs should be
- // the NULL string.
+ // string, which m_url.componentString will produce. Nonexistent refs
+ // should be the null string.
if (!m_url.m_parsed.ref.is_valid())
return String();
@@ -745,7 +718,7 @@ void KURL::setQuery(const String& query)
{
KURLGooglePrivate::Replacements replacements;
if (query.isNull()) {
- // KURL.cpp sets to NULL to clear any query.
+ // KURL.cpp sets to null to clear any query.
replacements.ClearQuery();
} else if (query.length() > 0 && query[0] == '?') {
// WebCore expects the query string to begin with a question mark, but
@@ -946,7 +919,7 @@ String decodeURLEscapeSequences(const String& str)
}
// In KURL.cpp's implementation, this is called by every component getter.
-// It will unescape every character, including NULL. This is scary, and may
+// It will unescape every character, including '\0'. This is scary, and may
// cause security holes. We never call this function for components, and
// just return the ASCII versions instead.
//
@@ -1005,10 +978,10 @@ bool KURL::isLocalFile() const
// will automatically do the correct escaping, this function does not have to
// do any work.
//
-// There is a possibility that a future called may use this function in other
+// There is a possibility that a future caller may use this function in other
// ways, and may expect to get a valid URL string. The dangerous thing we want
-// to protect against here is accidentally getting NULLs in a string that is
-// not supposed to have NULLs. Therefore, we escape NULLs here to prevent this.
+// to protect against here is accidentally getting '\0' characters in a string
+// that is not supposed to have them. Therefore, we escape these characters.
String encodeWithURLEscapeSequences(const String& notEncodedString)
{
CString utf8 = UTF8Encoding().encode(
@@ -1115,7 +1088,7 @@ bool protocolIs(const String& url, const char* protocol)
// Check the scheme like GURL does.
return url_util::FindAndCompareScheme(url.characters(), url.length(),
- protocol, NULL);
+ protocol, 0);
}
inline bool KURL::protocolIs(const String& string, const char* protocol)
diff --git a/Source/WebCore/platform/KURLGooglePrivate.h b/Source/WebCore/platform/KURLGooglePrivate.h
index c71e56b..c74a6b4 100644
--- a/Source/WebCore/platform/KURLGooglePrivate.h
+++ b/Source/WebCore/platform/KURLGooglePrivate.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
+ * Copyright (c) 2008, 2009, 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
@@ -41,7 +41,7 @@ namespace WebCore {
class KURL;
class TextEncoding;
- // Wraps the internals related to using Google-URL as the bnackend for KURL.
+ // Wraps the internals related to using Google-URL as the backend for KURL.
// This maintains the state and has auxiliary functions so that we don't need
// to uglify KURL.h while allowing Google-URL to be evaluated.
class KURLGooglePrivate {
@@ -49,19 +49,17 @@ namespace WebCore {
KURLGooglePrivate();
KURLGooglePrivate(const url_parse::Parsed&, bool isValid);
- // Initializes the object. This will call through to one of the backend
- // initializers below depending on whether the string's internal
- // representation is 8 or 16 bit.
+ // Initializes the object. This will call through the backend initializer
+ // below.
void init(const KURL& base, const String& relative,
const TextEncoding* queryEncoding);
- // Backend initializers. The query encoding parameters are optional and can
- // be NULL (this implies UTF-8). These initializers require that the object
- // has just been created and the strings are NULL. Do not call on an
+ // Backend initializer. The query encoding parameters are optional and can
+ // be 0 (this implies UTF-8). This initializer requires that the object
+ // has just been created and the strings are null. Do not call on an
// already-constructed object.
- void init(const KURL& base, const char* rel, int relLength,
- const TextEncoding* queryEncoding);
- void init(const KURL& base, const UChar* rel, int relLength,
+ template <typename CHAR>
+ void init(const KURL& base, const CHAR* rel, int relLength,
const TextEncoding* queryEncoding);
// Does a deep copy to the given output object.
diff --git a/Source/WebCore/platform/Length.cpp b/Source/WebCore/platform/Length.cpp
index e2fd9b8..323705a 100644
--- a/Source/WebCore/platform/Length.cpp
+++ b/Source/WebCore/platform/Length.cpp
@@ -28,6 +28,7 @@
#include "PlatformString.h"
#include <wtf/ASCIICType.h>
#include <wtf/Assertions.h>
+#include <wtf/OwnArrayPtr.h>
#include <wtf/text/StringBuffer.h>
using namespace WTF;
@@ -83,7 +84,7 @@ static int countCharacter(const UChar* data, unsigned length, UChar character)
return count;
}
-Length* newCoordsArray(const String& string, int& len)
+PassOwnArrayPtr<Length> newCoordsArray(const String& string, int& len)
{
unsigned length = string.length();
const UChar* data = string.characters();
@@ -100,7 +101,7 @@ Length* newCoordsArray(const String& string, int& len)
str = str->simplifyWhiteSpace();
len = countCharacter(str->characters(), str->length(), ' ') + 1;
- Length* r = new Length[len];
+ OwnArrayPtr<Length> r = adoptArrayPtr(new Length[len]);
int i = 0;
unsigned pos = 0;
@@ -114,10 +115,10 @@ Length* newCoordsArray(const String& string, int& len)
ASSERT(i == len - 1);
- return r;
+ return r.release();
}
-Length* newLengthArray(const String& string, int& len)
+PassOwnArrayPtr<Length> newLengthArray(const String& string, int& len)
{
RefPtr<StringImpl> str = string.impl()->simplifyWhiteSpace();
if (!str->length()) {
@@ -126,7 +127,7 @@ Length* newLengthArray(const String& string, int& len)
}
len = countCharacter(str->characters(), str->length(), ',') + 1;
- Length* r = new Length[len];
+ OwnArrayPtr<Length> r = adoptArrayPtr(new Length[len]);
int i = 0;
unsigned pos = 0;
@@ -145,7 +146,7 @@ Length* newLengthArray(const String& string, int& len)
else
len--;
- return r;
+ return r.release();
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/Length.h b/Source/WebCore/platform/Length.h
index 9da71c7..1571944 100644
--- a/Source/WebCore/platform/Length.h
+++ b/Source/WebCore/platform/Length.h
@@ -25,6 +25,7 @@
#include <wtf/FastAllocBase.h>
#include <wtf/Forward.h>
#include <wtf/MathExtras.h>
+#include <wtf/PassOwnArrayPtr.h>
namespace WebCore {
@@ -193,8 +194,8 @@ private:
int m_value;
};
-Length* newCoordsArray(const String&, int& len);
-Length* newLengthArray(const String&, int& len);
+PassOwnArrayPtr<Length> newCoordsArray(const String&, int& len);
+PassOwnArrayPtr<Length> newLengthArray(const String&, int& len);
} // namespace WebCore
diff --git a/Source/WebCore/platform/LinkHash.cpp b/Source/WebCore/platform/LinkHash.cpp
index ac3aa3c..a2acad1 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(StringImpl::computeHash(url, length));
+ return AlreadyHashed::avoidDeletedValue(WTF::StringHasher::createHash(url, length));
}
LinkHash visitedLinkHash(const UChar* url, unsigned length)
diff --git a/Source/WebCore/platform/LocalizationStrategy.h b/Source/WebCore/platform/LocalizationStrategy.h
index 5596c81..3ed84d9 100644
--- a/Source/WebCore/platform/LocalizationStrategy.h
+++ b/Source/WebCore/platform/LocalizationStrategy.h
@@ -55,6 +55,9 @@ public:
virtual String contextMenuItemTagOpenImageInNewWindow() = 0;
virtual String contextMenuItemTagDownloadImageToDisk() = 0;
virtual String contextMenuItemTagCopyImageToClipboard() = 0;
+#if PLATFORM(QT)
+ virtual String contextMenuItemTagCopyImageUrlToClipboard() = 0;
+#endif
virtual String contextMenuItemTagOpenFrameInNewWindow() = 0;
virtual String contextMenuItemTagCopy() = 0;
virtual String contextMenuItemTagGoBack() = 0;
diff --git a/Source/WebCore/platform/LocalizedStrings.cpp b/Source/WebCore/platform/LocalizedStrings.cpp
index f342c6d..77144a9 100644
--- a/Source/WebCore/platform/LocalizedStrings.cpp
+++ b/Source/WebCore/platform/LocalizedStrings.cpp
@@ -104,6 +104,13 @@ String contextMenuItemTagCopyImageToClipboard()
return platformStrategies()->localizationStrategy()->contextMenuItemTagCopyImageToClipboard();
}
+#if PLATFORM(QT)
+String contextMenuItemTagCopyImageUrlToClipboard()
+{
+ return platformStrategies()->localizationStrategy()->contextMenuItemTagCopyImageUrlToClipboard();
+}
+#endif
+
String contextMenuItemTagOpenFrameInNewWindow()
{
return platformStrategies()->localizationStrategy()->contextMenuItemTagOpenFrameInNewWindow();
diff --git a/Source/WebCore/platform/LocalizedStrings.h b/Source/WebCore/platform/LocalizedStrings.h
index da0fe86..812300f 100644
--- a/Source/WebCore/platform/LocalizedStrings.h
+++ b/Source/WebCore/platform/LocalizedStrings.h
@@ -51,6 +51,9 @@ namespace WebCore {
String contextMenuItemTagOpenImageInNewWindow();
String contextMenuItemTagDownloadImageToDisk();
String contextMenuItemTagCopyImageToClipboard();
+#if PLATFORM(QT)
+ String contextMenuItemTagCopyImageUrlToClipboard();
+#endif
String contextMenuItemTagOpenFrameInNewWindow();
String contextMenuItemTagCopy();
String contextMenuItemTagGoBack();
diff --git a/Source/WebCore/platform/MIMETypeRegistry.cpp b/Source/WebCore/platform/MIMETypeRegistry.cpp
index 0f4cc0e..8017c90 100644
--- a/Source/WebCore/platform/MIMETypeRegistry.cpp
+++ b/Source/WebCore/platform/MIMETypeRegistry.cpp
@@ -27,9 +27,12 @@
#include "config.h"
#include "MIMETypeRegistry.h"
+<<<<<<< HEAD
#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size
#include "ArchiveFactory.h"
#endif
+=======
+>>>>>>> webkit.org at r78450
#include "MediaPlayer.h"
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
@@ -46,6 +49,10 @@
#include <qimagewriter.h>
#endif
+#if ENABLE(WEB_ARCHIVE)
+#include "ArchiveFactory.h"
+#endif
+
namespace WebCore {
static HashSet<String>* supportedImageResourceMIMETypes;
@@ -249,7 +256,11 @@ static void initializeSupportedNonImageMimeTypes()
for (size_t i = 0; i < WTF_ARRAY_LENGTH(types); ++i)
supportedNonImageMIMETypes->add(types[i]);
+<<<<<<< HEAD
#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size
+=======
+#if ENABLE(WEB_ARCHIVE)
+>>>>>>> webkit.org at r78450
ArchiveFactory::registerKnownArchiveMIMETypes();
#endif
}
@@ -369,6 +380,13 @@ static MediaMIMETypeMap& mediaMIMETypeMap()
return mediaMIMETypeForExtensionMap;
}
+#if ENABLE(FILE_SYSTEM) && ENABLE(WORKERS)
+String MIMETypeRegistry::getMIMETypeForExtension(const String& extension)
+{
+ return getMIMETypeForExtensionThreadSafe(extension);
+}
+#endif
+
String MIMETypeRegistry::getMediaMIMETypeForExtension(const String& ext)
{
// Look in the system-specific registry first.
diff --git a/Source/WebCore/platform/MIMETypeRegistry.h b/Source/WebCore/platform/MIMETypeRegistry.h
index 64abea8..d069035 100644
--- a/Source/WebCore/platform/MIMETypeRegistry.h
+++ b/Source/WebCore/platform/MIMETypeRegistry.h
@@ -36,6 +36,9 @@ namespace WebCore {
class MIMETypeRegistry {
public:
static String getMIMETypeForExtension(const String& extension);
+#if ENABLE(FILE_SYSTEM) && ENABLE(WORKERS)
+ static String getMIMETypeForExtensionThreadSafe(const String& extension);
+#endif
static Vector<String> getExtensionsForMIMEType(const String& type);
static String getPreferredExtensionForMIMEType(const String& type);
static String getMediaMIMETypeForExtension(const String& extension);
diff --git a/Source/WebCore/platform/PlatformGestureEvent.h b/Source/WebCore/platform/PlatformGestureEvent.h
new file mode 100644
index 0000000..99157e1
--- /dev/null
+++ b/Source/WebCore/platform/PlatformGestureEvent.h
@@ -0,0 +1,66 @@
+/*
+ * 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 PlatformGestureEvent_h
+#define PlatformGestureEvent_h
+
+#if ENABLE(GESTURE_EVENTS)
+
+#include "IntPoint.h"
+
+namespace WebCore {
+
+class PlatformGestureEvent {
+public:
+ enum Type {
+ ScrollBeginType,
+ ScrollEndType,
+ };
+
+ PlatformGestureEvent()
+ : m_type(ScrollBeginType)
+ , m_timestamp(0)
+ {
+ }
+
+ Type type() const { return m_type; }
+
+ const IntPoint& position() const { return m_position; } // PlatformWindow coordinates.
+ const IntPoint& globalPosition() const { return m_globalPosition; } // Screen coordinates.
+
+ double timestamp() const { return m_timestamp; }
+
+protected:
+ Type m_type;
+ IntPoint m_position;
+ IntPoint m_globalPosition;
+ double m_timestamp;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(GESTURE_EVENTS)
+
+#endif // PlatformGestureEvent_h
diff --git a/Source/WebCore/platform/PlatformWheelEvent.h b/Source/WebCore/platform/PlatformWheelEvent.h
index 1e5cd53..2698e6e 100644
--- a/Source/WebCore/platform/PlatformWheelEvent.h
+++ b/Source/WebCore/platform/PlatformWheelEvent.h
@@ -98,7 +98,9 @@ namespace WebCore {
, m_altKey(false)
, m_metaKey(false)
#if PLATFORM(MAC)
+ , m_hasPreciseScrollingDeltas(false)
, m_phase(PlatformWheelEventPhaseNone)
+ , m_timestamp(0)
#endif
{
}
@@ -151,6 +153,8 @@ namespace WebCore {
#endif
PlatformWheelEventPhase phase() const { return m_phase; }
+ bool hasPreciseScrollingDeltas() const { return m_hasPreciseScrollingDeltas; }
+ double timestamp() const { return m_timestamp; }
#endif
#if PLATFORM(QT)
@@ -186,7 +190,9 @@ namespace WebCore {
bool m_altKey;
bool m_metaKey;
#if PLATFORM(MAC)
+ bool m_hasPreciseScrollingDeltas;
PlatformWheelEventPhase m_phase;
+ double m_timestamp;
#endif
};
diff --git a/Source/WebCore/platform/PopupMenuStyle.h b/Source/WebCore/platform/PopupMenuStyle.h
index b9a7abc..3cb33cc 100644
--- a/Source/WebCore/platform/PopupMenuStyle.h
+++ b/Source/WebCore/platform/PopupMenuStyle.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 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
@@ -35,7 +35,7 @@ namespace WebCore {
class PopupMenuStyle {
public:
- PopupMenuStyle(const Color& foreground, const Color& background, const Font& font, bool visible, bool isDisplayNone, Length textIndent, TextDirection textDirection)
+ PopupMenuStyle(const Color& foreground, const Color& background, const Font& font, bool visible, bool isDisplayNone, Length textIndent, TextDirection textDirection, bool hasTextDirectionOverride)
: m_foregroundColor(foreground)
, m_backgroundColor(background)
, m_font(font)
@@ -43,6 +43,7 @@ public:
, m_isDisplayNone(isDisplayNone)
, m_textIndent(textIndent)
, m_textDirection(textDirection)
+ , m_hasTextDirectionOverride(hasTextDirectionOverride)
{
}
@@ -53,6 +54,7 @@ public:
bool isDisplayNone() const { return m_isDisplayNone; }
Length textIndent() const { return m_textIndent; }
TextDirection textDirection() const { return m_textDirection; }
+ bool hasTextDirectionOverride() const { return m_hasTextDirectionOverride; }
private:
Color m_foregroundColor;
@@ -62,6 +64,7 @@ private:
bool m_isDisplayNone;
Length m_textIndent;
TextDirection m_textDirection;
+ bool m_hasTextDirectionOverride;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/SchemeRegistry.cpp b/Source/WebCore/platform/SchemeRegistry.cpp
index 71697cb..2bc655e 100644
--- a/Source/WebCore/platform/SchemeRegistry.cpp
+++ b/Source/WebCore/platform/SchemeRegistry.cpp
@@ -86,6 +86,24 @@ static URLSchemesMap& emptyDocumentSchemes()
return emptyDocumentSchemes;
}
+static URLSchemesMap& canDisplayOnlyIfCanRequestSchemes()
+{
+ DEFINE_STATIC_LOCAL(URLSchemesMap, canDisplayOnlyIfCanRequestSchemes, ());
+
+#if ENABLE(BLOB) || ENABLE(FILE_SYSTEM)
+ if (canDisplayOnlyIfCanRequestSchemes.isEmpty()) {
+#if ENABLE(BLOB)
+ canDisplayOnlyIfCanRequestSchemes.add("blob");
+#endif
+#if ENABLE(FILE_SYSTEM)
+ canDisplayOnlyIfCanRequestSchemes.add("filesystem");
+#endif
+ }
+#endif // ENABLE(BLOB) || ENABLE(FILE_SYSTEM)
+
+ return canDisplayOnlyIfCanRequestSchemes;
+}
+
void SchemeRegistry::registerURLSchemeAsLocal(const String& scheme)
{
localURLSchemes().add(scheme);
@@ -121,6 +139,8 @@ void SchemeRegistry::registerURLSchemeAsNoAccess(const String& scheme)
bool SchemeRegistry::shouldTreatURLSchemeAsNoAccess(const String& scheme)
{
+ if (scheme.isEmpty())
+ return false;
return schemesWithUniqueOrigins().contains(scheme);
}
@@ -131,6 +151,8 @@ void SchemeRegistry::registerURLSchemeAsDisplayIsolated(const String& scheme)
bool SchemeRegistry::shouldTreatURLSchemeAsDisplayIsolated(const String& scheme)
{
+ if (scheme.isEmpty())
+ return false;
return displayIsolatedURLSchemes().contains(scheme);
}
@@ -141,6 +163,8 @@ void SchemeRegistry::registerURLSchemeAsSecure(const String& scheme)
bool SchemeRegistry::shouldTreatURLSchemeAsSecure(const String& scheme)
{
+ if (scheme.isEmpty())
+ return false;
return secureSchemes().contains(scheme);
}
@@ -151,7 +175,21 @@ void SchemeRegistry::registerURLSchemeAsEmptyDocument(const String& scheme)
bool SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(const String& scheme)
{
+ if (scheme.isEmpty())
+ return false;
return emptyDocumentSchemes().contains(scheme);
}
+bool SchemeRegistry::canDisplayOnlyIfCanRequest(const String& scheme)
+{
+ if (scheme.isEmpty())
+ return false;
+ return canDisplayOnlyIfCanRequestSchemes().contains(scheme);
+}
+
+void SchemeRegistry::registerAsCanDisplayOnlyIfCanRequest(const String& scheme)
+{
+ canDisplayOnlyIfCanRequestSchemes().add(scheme);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/SchemeRegistry.h b/Source/WebCore/platform/SchemeRegistry.h
index 530fcab..c9cb476 100644
--- a/Source/WebCore/platform/SchemeRegistry.h
+++ b/Source/WebCore/platform/SchemeRegistry.h
@@ -58,6 +58,11 @@ public:
static void registerURLSchemeAsEmptyDocument(const String&);
static bool shouldLoadURLSchemeAsEmptyDocument(const String&);
+
+ // Such schemes should delegate to SecurityOrigin::canRequest for any URL
+ // passed to SecurityOrigin::canDisplay.
+ static bool canDisplayOnlyIfCanRequest(const String& scheme);
+ static void registerAsCanDisplayOnlyIfCanRequest(const String& scheme);
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/ScrollAnimator.cpp b/Source/WebCore/platform/ScrollAnimator.cpp
index 428a79d..6fc78e7 100644
--- a/Source/WebCore/platform/ScrollAnimator.cpp
+++ b/Source/WebCore/platform/ScrollAnimator.cpp
@@ -32,10 +32,13 @@
#include "ScrollAnimator.h"
#include "FloatPoint.h"
+#include "PlatformWheelEvent.h"
#include "ScrollableArea.h"
#include <algorithm>
#include <wtf/PassOwnPtr.h>
+using namespace std;
+
namespace WebCore {
#if !ENABLE(SMOOTH_SCROLLING)
@@ -78,6 +81,44 @@ void ScrollAnimator::scrollToOffsetWithoutAnimation(const FloatPoint& offset)
}
}
+void ScrollAnimator::handleWheelEvent(PlatformWheelEvent& e)
+{
+ Scrollbar* horizontalScrollbar = m_scrollableArea->horizontalScrollbar();
+ Scrollbar* verticalScrollbar = m_scrollableArea->verticalScrollbar();
+
+ // Accept the event if we have a scrollbar in that direction and can still
+ // scroll any further.
+ float deltaX = horizontalScrollbar ? e.deltaX() : 0;
+ float deltaY = verticalScrollbar ? e.deltaY() : 0;
+
+ IntSize maxForwardScrollDelta = m_scrollableArea->maximumScrollPosition() - m_scrollableArea->scrollPosition();
+ IntSize maxBackwardScrollDelta = m_scrollableArea->scrollPosition() - m_scrollableArea->minimumScrollPosition();
+ if ((deltaX < 0 && maxForwardScrollDelta.width() > 0)
+ || (deltaX > 0 && maxBackwardScrollDelta.width() > 0)
+ || (deltaY < 0 && maxForwardScrollDelta.height() > 0)
+ || (deltaY > 0 && maxBackwardScrollDelta.height() > 0)) {
+ e.accept();
+ if (e.granularity() == ScrollByPageWheelEvent) {
+ ASSERT(!e.deltaX());
+ bool negative = deltaY < 0;
+ deltaY = max(max(static_cast<float>(m_scrollableArea->visibleHeight()) * Scrollbar::minFractionToStepWhenPaging(), static_cast<float>(m_scrollableArea->visibleHeight() - Scrollbar::maxOverlapBetweenPages())), 1.0f);
+ if (negative)
+ deltaY = -deltaY;
+ }
+
+ if (deltaY)
+ scroll(VerticalScrollbar, ScrollByPixel, verticalScrollbar->pixelStep(), -deltaY);
+ if (deltaX)
+ scroll(HorizontalScrollbar, ScrollByPixel, horizontalScrollbar->pixelStep(), -deltaX);
+ }
+}
+
+#if ENABLE(GESTURE_EVENTS)
+void ScrollAnimator::handleGestureEvent(const PlatformGestureEvent&)
+{
+}
+#endif
+
FloatPoint ScrollAnimator::currentPosition() const
{
return FloatPoint(m_currentPosX, m_currentPosY);
diff --git a/Source/WebCore/platform/ScrollAnimator.h b/Source/WebCore/platform/ScrollAnimator.h
index 155c6e5..060511c 100644
--- a/Source/WebCore/platform/ScrollAnimator.h
+++ b/Source/WebCore/platform/ScrollAnimator.h
@@ -37,7 +37,13 @@
namespace WebCore {
class FloatPoint;
+class PlatformWheelEvent;
class ScrollableArea;
+class Scrollbar;
+
+#if ENABLE(GESTURE_EVENTS)
+class PlatformGestureEvent;
+#endif
class ScrollAnimator {
public:
@@ -53,12 +59,34 @@ public:
virtual void scrollToOffsetWithoutAnimation(const FloatPoint&);
+ ScrollableArea* scrollableArea() const { return m_scrollableArea; }
+
+ virtual void handleWheelEvent(PlatformWheelEvent&);
+#if ENABLE(GESTURE_EVENTS)
+ virtual void handleGestureEvent(const PlatformGestureEvent&);
+#endif
+
FloatPoint currentPosition() const;
+ virtual void contentAreaWillPaint() const { }
+ virtual void mouseEnteredContentArea() const { }
+ virtual void mouseExitedContentArea() const { }
+ virtual void mouseMovedInContentArea() const { }
+ virtual void willStartLiveResize() { }
+ virtual void contentsResized() const { }
+ virtual void willEndLiveResize() { }
+ virtual void contentAreaDidShow() const { }
+ virtual void contentAreaDidHide() const { }
+
+ virtual void didAddVerticalScrollbar(Scrollbar*) { }
+ virtual void willRemoveVerticalScrollbar(Scrollbar*) { }
+ virtual void didAddHorizontalScrollbar(Scrollbar*) { }
+ virtual void willRemoveHorizontalScrollbar(Scrollbar*) { }
+
protected:
ScrollAnimator(ScrollableArea*);
- void notityPositionChanged();
+ virtual void notityPositionChanged();
ScrollableArea* m_scrollableArea;
float m_currentPosX; // We avoid using a FloatPoint in order to reduce
diff --git a/Source/WebCore/platform/ScrollView.cpp b/Source/WebCore/platform/ScrollView.cpp
index b07c743..cab58e4 100644
--- a/Source/WebCore/platform/ScrollView.cpp
+++ b/Source/WebCore/platform/ScrollView.cpp
@@ -31,12 +31,12 @@
#include "HostWindow.h"
#include "PlatformMouseEvent.h"
#include "PlatformWheelEvent.h"
+#include "ScrollAnimator.h"
#include "Scrollbar.h"
#include "ScrollbarTheme.h"
#include <wtf/StdLibExtras.h>
-
-using std::max;
+using namespace std;
namespace WebCore {
@@ -92,8 +92,10 @@ void ScrollView::setHasHorizontalScrollbar(bool hasBar)
if (hasBar && !m_horizontalScrollbar) {
m_horizontalScrollbar = createScrollbar(HorizontalScrollbar);
addChild(m_horizontalScrollbar.get());
+ ScrollableArea::didAddHorizontalScrollbar(m_horizontalScrollbar.get());
m_horizontalScrollbar->styleChanged();
} else if (!hasBar && m_horizontalScrollbar) {
+ ScrollableArea::willRemoveHorizontalScrollbar(m_horizontalScrollbar.get());
removeChild(m_horizontalScrollbar.get());
m_horizontalScrollbar = 0;
}
@@ -110,8 +112,10 @@ void ScrollView::setHasVerticalScrollbar(bool hasBar)
if (hasBar && !m_verticalScrollbar) {
m_verticalScrollbar = createScrollbar(VerticalScrollbar);
addChild(m_verticalScrollbar.get());
+ ScrollableArea::didAddVerticalScrollbar(m_verticalScrollbar.get());
m_verticalScrollbar->styleChanged();
} else if (!hasBar && m_verticalScrollbar) {
+ ScrollableArea::willRemoveVerticalScrollbar(m_verticalScrollbar.get());
removeChild(m_verticalScrollbar.get());
m_verticalScrollbar = 0;
}
@@ -344,16 +348,49 @@ IntPoint ScrollView::adjustScrollPositionWithinRange(const IntPoint& scrollPoint
return newScrollPosition;
}
+int ScrollView::scrollXForFixedPosition() const
+{
+ int x = scrollX();
+ if (x < 0)
+ x = 0;
+ else if (x > contentsWidth() - visibleContentRect().width())
+ x = contentsWidth() - visibleContentRect().width();
+ return x;
+}
+
+int ScrollView::scrollYForFixedPosition() const
+{
+ int y = scrollY();
+ if (y < 0)
+ y = 0;
+ else if (y > contentsHeight() - visibleContentRect().height())
+ y = contentsHeight() - visibleContentRect().height();
+ return y;
+}
+
+IntSize ScrollView::scrollOffsetForFixedPosition() const
+{
+ return IntSize(scrollXForFixedPosition(), scrollYForFixedPosition());
+}
+
int ScrollView::scrollSize(ScrollbarOrientation orientation) const
{
Scrollbar* scrollbar = ((orientation == HorizontalScrollbar) ? m_horizontalScrollbar : m_verticalScrollbar).get();
return scrollbar ? (scrollbar->totalSize() - scrollbar->visibleSize()) : 0;
}
+void ScrollView::didCompleteRubberBand(const IntSize&) const
+{
+}
+
void ScrollView::setScrollOffset(const IntPoint& offset)
{
- int horizontalOffset = std::max(std::min(offset.x(), contentsWidth() - visibleWidth()), 0);
- int verticalOffset = std::max(std::min(offset.y(), contentsHeight() - visibleHeight()), 0);
+ int horizontalOffset = offset.x();
+ int verticalOffset = offset.y();
+ if (constrainsScrollingToContentEdge()) {
+ horizontalOffset = max(min(horizontalOffset, contentsWidth() - visibleWidth()), 0);
+ verticalOffset = max(min(verticalOffset, contentsHeight() - visibleHeight()), 0);
+ }
IntSize newOffset = m_scrollOffset;
newOffset.setWidth(horizontalOffset - m_scrollOrigin.x());
@@ -425,6 +462,22 @@ bool ScrollView::logicalScroll(ScrollLogicalDirection direction, ScrollGranulari
return scroll(logicalToPhysical(direction, isVerticalDocument(), isFlippedDocument()), granularity);
}
+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()));
+
+ return stretch;
+}
+
void ScrollView::windowResizerRectChanged()
{
if (platformWidget())
@@ -528,7 +581,7 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset)
m_inUpdateScrollbars = true;
- IntPoint scrollPoint = adjustScrollPositionWithinRange(IntPoint(desiredOffset.width(), desiredOffset.height()));
+ IntPoint scrollPoint = adjustScrollPositionWithinRange(IntPoint(desiredOffset));
IntSize scroll(scrollPoint.x(), scrollPoint.y());
if (m_horizontalScrollbar) {
@@ -580,6 +633,12 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset)
ScrollableArea::scrollToOffsetWithoutAnimation(FloatPoint(scroll.width() + m_scrollOrigin.x(), scroll.height() + m_scrollOrigin.y()));
+ // Make sure the scrollbar offsets are up to date.
+ if (m_horizontalScrollbar)
+ m_horizontalScrollbar->offsetDidChange();
+ if (m_verticalScrollbar)
+ m_verticalScrollbar->offsetDidChange();
+
m_inUpdateScrollbars = false;
}
@@ -594,6 +653,14 @@ void ScrollView::scrollContents(const IntSize& scrollDelta)
// with the clip rect every time to keep it smooth.
IntRect clipRect = windowClipRect();
IntRect scrollViewRect = convertToContainingWindow(IntRect(0, 0, visibleWidth(), visibleHeight()));
+ if (ScrollbarTheme::nativeTheme()->usesOverlayScrollbars()) {
+ int verticalScrollbarWidth = verticalScrollbar() ? verticalScrollbar()->width() : 0;
+ int horizontalScrollbarHeight = horizontalScrollbar() ? horizontalScrollbar()->height() : 0;
+
+ scrollViewRect.setWidth(scrollViewRect.width() - verticalScrollbarWidth);
+ scrollViewRect.setHeight(scrollViewRect.height() - horizontalScrollbarHeight);
+ }
+
IntRect updateRect = clipRect;
updateRect.intersect(scrollViewRect);
@@ -761,32 +828,18 @@ void ScrollView::wheelEvent(PlatformWheelEvent& e)
return;
}
- // Accept the event if we have a scrollbar in that direction and can still
- // scroll any further.
- float deltaX = m_horizontalScrollbar ? e.deltaX() : 0;
- float deltaY = m_verticalScrollbar ? e.deltaY() : 0;
-
- IntSize maxForwardScrollDelta = maximumScrollPosition() - scrollPosition();
- IntSize maxBackwardScrollDelta = scrollPosition() - minimumScrollPosition();
- if ((deltaX < 0 && maxForwardScrollDelta.width() > 0)
- || (deltaX > 0 && maxBackwardScrollDelta.width() >0)
- || (deltaY < 0 && maxForwardScrollDelta.height() > 0)
- || (deltaY > 0 && maxBackwardScrollDelta.height() > 0)) {
- e.accept();
- if (e.granularity() == ScrollByPageWheelEvent) {
- ASSERT(!e.deltaX());
- bool negative = deltaY < 0;
- deltaY = max(max(static_cast<float>(visibleHeight()) * Scrollbar::minFractionToStepWhenPaging(), static_cast<float>(visibleHeight() - Scrollbar::maxOverlapBetweenPages())), 1.0f);
- if (negative)
- deltaY = -deltaY;
- }
+ ScrollableArea::handleWheelEvent(e);
+}
- if (deltaY)
- ScrollableArea::scroll(ScrollUp, ScrollByPixel, deltaY);
- if (deltaX)
- ScrollableArea::scroll(ScrollLeft, ScrollByPixel, deltaX);
- }
+#if ENABLE(GESTURE_EVENTS)
+void ScrollView::gestureEvent(const PlatformGestureEvent& gestureEvent)
+{
+ if (platformWidget())
+ return;
+
+ ScrollableArea::handleGestureEvent(gestureEvent);
}
+#endif
void ScrollView::setFrameRect(const IntRect& newRect)
{
@@ -898,6 +951,8 @@ void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
if (context->paintingDisabled() && !context->updatingControlTints())
return;
+ scrollAnimator()->contentAreaWillPaint();
+
IntRect documentDirtyRect = rect;
documentDirtyRect.intersect(frameRect());
@@ -917,6 +972,13 @@ void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
context->restore();
+ IntRect horizontalOverhangRect;
+ IntRect verticalOverhangRect;
+ calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect);
+
+ if (rect.intersects(horizontalOverhangRect) || rect.intersects(verticalOverhangRect))
+ paintOverhangAreas(context, horizontalOverhangRect, verticalOverhangRect, rect);
+
// Now paint the scrollbars.
if (!m_scrollbarsSuppressed && (m_horizontalScrollbar || m_verticalScrollbar)) {
context->save();
@@ -935,6 +997,55 @@ void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
paintPanScrollIcon(context);
}
+void ScrollView::calculateOverhangAreasForPainting(IntRect& horizontalOverhangRect, IntRect& verticalOverhangRect)
+{
+ bool hasOverlayScrollbars = ScrollbarTheme::nativeTheme()->usesOverlayScrollbars();
+ int verticalScrollbarWidth = (verticalScrollbar() && !hasOverlayScrollbars) ? verticalScrollbar()->width() : 0;
+ int horizontalScrollbarHeight = (horizontalScrollbar() && !hasOverlayScrollbars) ? horizontalScrollbar()->height() : 0;
+
+ if (scrollY() < 0) {
+ horizontalOverhangRect = frameRect();
+ horizontalOverhangRect.setHeight(-scrollY());
+ } else if (scrollY() > contentsHeight() - visibleContentRect().height()) {
+ int height = scrollY() - (contentsHeight() - visibleContentRect().height());
+ horizontalOverhangRect = frameRect();
+ horizontalOverhangRect.setY(frameRect().maxY() - height - horizontalScrollbarHeight);
+ horizontalOverhangRect.setHeight(height);
+ }
+
+ if (scrollX() < 0) {
+ verticalOverhangRect.setWidth(-scrollX());
+ 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());
+ verticalOverhangRect.setWidth(width);
+ verticalOverhangRect.setHeight(frameRect().height() - horizontalOverhangRect.height());
+ verticalOverhangRect.setX(frameRect().maxX() - width - verticalScrollbarWidth);
+ if (horizontalOverhangRect.y() == frameRect().y())
+ verticalOverhangRect.setY(frameRect().y() + horizontalOverhangRect.height());
+ else
+ verticalOverhangRect.setY(frameRect().y());
+ }
+}
+
+void ScrollView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect&)
+{
+ // FIXME: This should be checking the dirty rect.
+
+ context->setFillColor(Color::white, ColorSpaceDeviceRGB);
+ if (!horizontalOverhangRect.isEmpty())
+ context->fillRect(horizontalOverhangRect);
+
+ context->setFillColor(Color::white, ColorSpaceDeviceRGB);
+ if (!verticalOverhangRect.isEmpty())
+ context->fillRect(verticalOverhangRect);
+}
+
bool ScrollView::isPointInScrollbarCorner(const IntPoint& windowPoint)
{
if (!scrollbarCornerPresent())
@@ -1070,7 +1181,7 @@ void ScrollView::removePanScrollIcon()
hostWindow()->invalidateContentsAndWindow(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)), true /*immediate*/);
}
-void ScrollView::setScrollOrigin(const IntPoint& origin, bool updatePosition)
+void ScrollView::setScrollOrigin(const IntPoint& origin, bool updatePositionAtAll, bool updatePositionSynchronously)
{
if (m_scrollOrigin == origin)
return;
@@ -1078,12 +1189,12 @@ void ScrollView::setScrollOrigin(const IntPoint& origin, bool updatePosition)
m_scrollOrigin = origin;
if (platformWidget()) {
- platformSetScrollOrigin(origin, updatePosition);
+ platformSetScrollOrigin(origin, updatePositionAtAll, updatePositionSynchronously);
return;
}
// Update if the scroll origin changes, since our position will be different if the content size did not change.
- if (updatePosition)
+ if (updatePositionAtAll && updatePositionSynchronously)
updateScrollbars(scrollOffset());
}
@@ -1117,7 +1228,7 @@ void ScrollView::platformSetScrollbarsSuppressed(bool)
{
}
-void ScrollView::platformSetScrollOrigin(const IntPoint&, bool updatePosition)
+void ScrollView::platformSetScrollOrigin(const IntPoint&, bool updatePositionAtAll, bool updatePositionSynchronously)
{
}
diff --git a/Source/WebCore/platform/ScrollView.h b/Source/WebCore/platform/ScrollView.h
index cb895f6..2bd1447 100644
--- a/Source/WebCore/platform/ScrollView.h
+++ b/Source/WebCore/platform/ScrollView.h
@@ -51,7 +51,6 @@ class wxScrollWinEvent;
namespace WebCore {
class HostWindow;
-class PlatformWheelEvent;
class Scrollbar;
class ScrollView : public Widget, public ScrollableArea {
@@ -62,7 +61,8 @@ public:
virtual int scrollSize(ScrollbarOrientation orientation) const;
virtual int scrollPosition(Scrollbar*) const;
virtual void setScrollOffset(const IntPoint&);
-
+ virtual void didCompleteRubberBand(const IntSize&) const;
+
// NOTE: This should only be called by the overriden setScrollOffset from ScrollableArea.
virtual void scrollTo(const IntSize& newOffset);
@@ -162,6 +162,7 @@ public:
int contentsWidth() const { return contentsSize().width(); }
int contentsHeight() const { return contentsSize().height(); }
virtual void setContentsSize(const IntSize&);
+<<<<<<< HEAD
#if PLATFORM(ANDROID)
int actualWidth() const;
@@ -169,6 +170,8 @@ public:
int actualScrollX() const;
int actualScrollY() const;
#endif
+=======
+>>>>>>> webkit.org at r78450
// Functions for querying the current scrolled position (both as a point, a size, or as individual X and Y values).
IntPoint scrollPosition() const { return visibleContentRect().location(); }
@@ -179,7 +182,14 @@ public:
IntPoint adjustScrollPositionWithinRange(const IntPoint&) const;
int scrollX() const { return scrollPosition().x(); }
int scrollY() const { return scrollPosition().y(); }
-
+
+ // Functions for querying the current scrolled position, negating the effects of overhang.
+ int scrollXForFixedPosition() const;
+ int scrollYForFixedPosition() const;
+ IntSize scrollOffsetForFixedPosition() const;
+
+ IntSize overhangAmount() const;
+
// Functions for scrolling the view.
void setScrollPosition(const IntPoint&);
void scrollBy(const IntSize& s) { return setScrollPosition(scrollPosition() + s); }
@@ -235,6 +245,9 @@ public:
// On Mac the underlying NSScrollView just does the scrolling, but on other platforms
// (like Windows), we need this function in order to do the scroll ourselves.
void wheelEvent(PlatformWheelEvent&);
+#if ENABLE(GESTURE_EVENTS)
+ void gestureEvent(const PlatformGestureEvent&);
+#endif
IntPoint convertChildToSelf(const Widget* child, const IntPoint& point) const
{
@@ -282,7 +295,10 @@ protected:
virtual void repaintContentRectangle(const IntRect&, bool now = false);
virtual void paintContents(GraphicsContext*, const IntRect& damageRect) = 0;
-
+
+ void calculateOverhangAreasForPainting(IntRect& horizontalOverhangRect, IntRect& verticalOverhangRect);
+ virtual void paintOverhangAreas(GraphicsContext*, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect);
+
virtual void contentsResized() = 0;
virtual void visibleContentsResized() = 0;
@@ -299,7 +315,7 @@ protected:
// Scroll the content by invalidating everything.
virtual void scrollContentsSlowPath(const IntRect& updateRect);
- void setScrollOrigin(const IntPoint&, bool updatePosition);
+ void setScrollOrigin(const IntPoint&, bool updatePositionAtAll, bool updatePositionSynchronously);
IntPoint scrollOrigin() { return m_scrollOrigin; }
// Subclassed by FrameView to check the writing-mode of the document.
@@ -383,7 +399,7 @@ private:
void platformRepaintContentRectangle(const IntRect&, bool now);
bool platformIsOffscreen() const;
- void platformSetScrollOrigin(const IntPoint&, bool updatePosition);
+ void platformSetScrollOrigin(const IntPoint&, bool updatePositionAtAll, bool updatePositionSynchronously);
#if PLATFORM(ANDROID)
int platformActualWidth() const;
diff --git a/Source/WebCore/platform/ScrollableArea.cpp b/Source/WebCore/platform/ScrollableArea.cpp
index 176cb7e..00017bd 100644
--- a/Source/WebCore/platform/ScrollableArea.cpp
+++ b/Source/WebCore/platform/ScrollableArea.cpp
@@ -35,12 +35,15 @@
#include "FloatPoint.h"
#include "PlatformWheelEvent.h"
#include "ScrollAnimator.h"
+#include "ScrollbarTheme.h"
#include <wtf/PassOwnPtr.h>
namespace WebCore {
ScrollableArea::ScrollableArea()
: m_scrollAnimator(ScrollAnimator::create(this))
+ , m_constrainsScrollingToContentEdge(true)
+ , m_inLiveResize(false)
{
}
@@ -108,16 +111,72 @@ void ScrollableArea::scrollToYOffsetWithoutAnimation(float y)
scrollToOffsetWithoutAnimation(FloatPoint(m_scrollAnimator->currentPosition().x(), y));
}
+void ScrollableArea::handleWheelEvent(PlatformWheelEvent& wheelEvent)
+{
+ m_scrollAnimator->handleWheelEvent(wheelEvent);
+}
+
+#if ENABLE(GESTURE_EVENTS)
+void ScrollableArea::handleGestureEvent(const PlatformGestureEvent& gestureEvent)
+{
+ m_scrollAnimator->handleGestureEvent(gestureEvent);
+}
+#endif
+
void ScrollableArea::setScrollOffsetFromAnimation(const IntPoint& offset)
{
// Tell the derived class to scroll its contents.
setScrollOffset(offset);
+ bool hasOverlayScrollbars = ScrollbarTheme::nativeTheme()->usesOverlayScrollbars();
+
// Tell the scrollbars to update their thumb postions.
- if (Scrollbar* horizontalScrollbar = this->horizontalScrollbar())
+ if (Scrollbar* horizontalScrollbar = this->horizontalScrollbar()) {
horizontalScrollbar->offsetDidChange();
- if (Scrollbar* verticalScrollbar = this->verticalScrollbar())
+ if (hasOverlayScrollbars)
+ horizontalScrollbar->invalidate();
+ }
+ if (Scrollbar* verticalScrollbar = this->verticalScrollbar()) {
verticalScrollbar->offsetDidChange();
+ if (hasOverlayScrollbars)
+ verticalScrollbar->invalidate();
+ }
+}
+
+void ScrollableArea::willStartLiveResize()
+{
+ if (m_inLiveResize)
+ return;
+ m_inLiveResize = true;
+ scrollAnimator()->willStartLiveResize();
+}
+
+void ScrollableArea::willEndLiveResize()
+{
+ if (!m_inLiveResize)
+ return;
+ m_inLiveResize = false;
+ scrollAnimator()->willEndLiveResize();
+}
+
+void ScrollableArea::didAddVerticalScrollbar(Scrollbar* scrollbar)
+{
+ scrollAnimator()->didAddVerticalScrollbar(scrollbar);
+}
+
+void ScrollableArea::willRemoveVerticalScrollbar(Scrollbar* scrollbar)
+{
+ scrollAnimator()->willRemoveVerticalScrollbar(scrollbar);
+}
+
+void ScrollableArea::didAddHorizontalScrollbar(Scrollbar* scrollbar)
+{
+ scrollAnimator()->didAddHorizontalScrollbar(scrollbar);
+}
+
+void ScrollableArea::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
+{
+ scrollAnimator()->willRemoveHorizontalScrollbar(scrollbar);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/ScrollableArea.h b/Source/WebCore/platform/ScrollableArea.h
index 148ecdb..9839abc 100644
--- a/Source/WebCore/platform/ScrollableArea.h
+++ b/Source/WebCore/platform/ScrollableArea.h
@@ -33,6 +33,7 @@
namespace WebCore {
class FloatPoint;
+class PlatformGestureEvent;
class PlatformWheelEvent;
class ScrollAnimator;
@@ -47,6 +48,26 @@ public:
void scrollToXOffsetWithoutAnimation(float x);
void scrollToYOffsetWithoutAnimation(float x);
+ void handleWheelEvent(PlatformWheelEvent&);
+#if ENABLE(GESTURE_EVENTS)
+ void handleGestureEvent(const PlatformGestureEvent&);
+#endif
+
+ // Functions for controlling if you can scroll past the end of the document.
+ bool constrainsScrollingToContentEdge() const { return m_constrainsScrollingToContentEdge; }
+ void setConstrainsScrollingToContentEdge(bool constrainsScrollingToContentEdge) { m_constrainsScrollingToContentEdge = constrainsScrollingToContentEdge; }
+
+ bool inLiveResize() const { return m_inLiveResize; }
+ void willStartLiveResize();
+ void willEndLiveResize();
+
+ void didAddVerticalScrollbar(Scrollbar*);
+ void willRemoveVerticalScrollbar(Scrollbar*);
+ void didAddHorizontalScrollbar(Scrollbar*);
+ void willRemoveHorizontalScrollbar(Scrollbar*);
+
+ ScrollAnimator* scrollAnimator() const { return m_scrollAnimator.get(); }
+
virtual int scrollSize(ScrollbarOrientation) const = 0;
virtual int scrollPosition(Scrollbar*) const = 0;
virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&) = 0;
@@ -58,7 +79,6 @@ public:
// scroll of the content.
virtual void setScrollOffset(const IntPoint&) = 0;
-
// Convert points and rects between the scrollbar and its containing view.
// The client needs to implement these in order to be aware of layout effects
// like CSS transforms.
@@ -82,12 +102,28 @@ public:
virtual Scrollbar* horizontalScrollbar() const { return 0; }
virtual Scrollbar* verticalScrollbar() const { return 0; }
+ virtual IntPoint scrollPosition() const { ASSERT_NOT_REACHED(); return IntPoint(); }
+ virtual IntPoint minimumScrollPosition() const { ASSERT_NOT_REACHED(); return IntPoint(); }
+ virtual IntPoint maximumScrollPosition() const { ASSERT_NOT_REACHED(); return IntPoint(); }
+ virtual IntRect visibleContentRect(bool = false) const { ASSERT_NOT_REACHED(); return IntRect(); }
+ virtual int visibleHeight() const { ASSERT_NOT_REACHED(); return 0; }
+ virtual int visibleWidth() const { ASSERT_NOT_REACHED(); return 0; }
+ virtual IntSize contentsSize() const { ASSERT_NOT_REACHED(); return IntSize(); }
+ 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 scrollbarWillRenderIntoCompositingLayer() const { return false; }
+
private:
// NOTE: Only called from the ScrollAnimator.
friend class ScrollAnimator;
void setScrollOffsetFromAnimation(const IntPoint&);
OwnPtr<ScrollAnimator> m_scrollAnimator;
+ bool m_constrainsScrollingToContentEdge;
+
+ bool m_inLiveResize;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/Scrollbar.cpp b/Source/WebCore/platform/Scrollbar.cpp
index 4c625f4..5d9a43d 100644
--- a/Source/WebCore/platform/Scrollbar.cpp
+++ b/Source/WebCore/platform/Scrollbar.cpp
@@ -196,7 +196,7 @@ void Scrollbar::autoscrollPressedPart(double delay)
}
// Handle the arrows and track.
- if (scrollableArea()->scroll(pressedPartScrollDirection(), pressedPartScrollGranularity()))
+ if (m_scrollableArea && m_scrollableArea->scroll(pressedPartScrollDirection(), pressedPartScrollGranularity()))
startTimerIfNeeded(delay);
}
@@ -268,7 +268,8 @@ void Scrollbar::moveThumb(int pos)
if (delta) {
float newPosition = static_cast<float>(thumbPos + delta) * maximum() / (trackLen - thumbLen);
- scrollableArea()->scrollToOffsetWithoutAnimation(m_orientation, newPosition);
+ if (m_scrollableArea)
+ m_scrollableArea->scrollToOffsetWithoutAnimation(m_orientation, newPosition);
}
}
@@ -300,9 +301,10 @@ void Scrollbar::setPressedPart(ScrollbarPart part)
bool Scrollbar::mouseMoved(const PlatformMouseEvent& evt)
{
if (m_pressedPart == ThumbPart) {
- if (theme()->shouldSnapBackToDragOrigin(this, evt))
- scrollableArea()->scrollToOffsetWithoutAnimation(m_orientation, m_dragOrigin);
- else {
+ if (theme()->shouldSnapBackToDragOrigin(this, evt)) {
+ if (m_scrollableArea)
+ m_scrollableArea->scrollToOffsetWithoutAnimation(m_orientation, m_dragOrigin);
+ } else {
moveThumb(m_orientation == HorizontalScrollbar ?
convertFromContainingWindow(evt.pos()).x() :
convertFromContainingWindow(evt.pos()).y());
@@ -393,14 +395,14 @@ void Scrollbar::setFrameRect(const IntRect& rect)
IntRect resizerRect = view->convertFromContainingWindow(view->windowResizerRect());
if (rect.intersects(resizerRect)) {
if (orientation() == HorizontalScrollbar) {
- int overlap = rect.right() - resizerRect.x();
- if (overlap > 0 && resizerRect.right() >= rect.right()) {
+ int overlap = rect.maxX() - resizerRect.x();
+ if (overlap > 0 && resizerRect.maxX() >= rect.maxX()) {
adjustedRect.setWidth(rect.width() - overlap);
overlapsResizer = true;
}
} else {
- int overlap = rect.bottom() - resizerRect.y();
- if (overlap > 0 && resizerRect.bottom() >= rect.bottom()) {
+ int overlap = rect.maxY() - resizerRect.y();
+ if (overlap > 0 && resizerRect.maxY() >= rect.maxY()) {
adjustedRect.setHeight(rect.height() - overlap);
overlapsResizer = true;
}
diff --git a/Source/WebCore/platform/ScrollbarThemeComposite.cpp b/Source/WebCore/platform/ScrollbarThemeComposite.cpp
index 7bc266f..26f1494 100644
--- a/Source/WebCore/platform/ScrollbarThemeComposite.cpp
+++ b/Source/WebCore/platform/ScrollbarThemeComposite.cpp
@@ -37,6 +37,8 @@
#include "ScrollableArea.h"
#include "Settings.h"
+using namespace std;
+
namespace WebCore {
#if PLATFORM(WIN)
@@ -246,18 +248,28 @@ void ScrollbarThemeComposite::splitTrack(Scrollbar* scrollbar, const IntRect& un
if (scrollbar->orientation() == HorizontalScrollbar) {
thumbRect = IntRect(trackRect.x() + thumbPos, trackRect.y() + (trackRect.height() - thickness) / 2, thumbLength(scrollbar), thickness);
beforeThumbRect = IntRect(trackRect.x(), trackRect.y(), thumbPos + thumbRect.width() / 2, trackRect.height());
- afterThumbRect = IntRect(trackRect.x() + beforeThumbRect.width(), trackRect.y(), trackRect.right() - beforeThumbRect.right(), trackRect.height());
+ afterThumbRect = IntRect(trackRect.x() + beforeThumbRect.width(), trackRect.y(), trackRect.maxX() - beforeThumbRect.maxX(), trackRect.height());
} else {
thumbRect = IntRect(trackRect.x() + (trackRect.width() - thickness) / 2, trackRect.y() + thumbPos, thickness, thumbLength(scrollbar));
beforeThumbRect = IntRect(trackRect.x(), trackRect.y(), trackRect.width(), thumbPos + thumbRect.height() / 2);
- afterThumbRect = IntRect(trackRect.x(), trackRect.y() + beforeThumbRect.height(), trackRect.width(), trackRect.bottom() - beforeThumbRect.bottom());
+ afterThumbRect = IntRect(trackRect.x(), trackRect.y() + beforeThumbRect.height(), trackRect.width(), trackRect.maxY() - beforeThumbRect.maxY());
}
}
+// Returns the size represented by track taking into account scrolling past
+// the end of the document.
+static float usedTotalSize(Scrollbar* scrollbar)
+{
+ float overhangAtStart = -scrollbar->currentPos();
+ float overhangAtEnd = scrollbar->currentPos() + scrollbar->visibleSize() - scrollbar->totalSize();
+ float overhang = max(0.0f, max(overhangAtStart, overhangAtEnd));
+ return scrollbar->totalSize() + overhang;
+}
+
int ScrollbarThemeComposite::thumbPosition(Scrollbar* scrollbar)
{
if (scrollbar->enabled())
- return scrollbar->currentPos() * (trackLength(scrollbar) - thumbLength(scrollbar)) / scrollbar->maximum();
+ return max(0.0f, scrollbar->currentPos()) * (trackLength(scrollbar) - thumbLength(scrollbar)) / (usedTotalSize(scrollbar) - scrollbar->visibleSize());
return 0;
}
@@ -266,7 +278,7 @@ int ScrollbarThemeComposite::thumbLength(Scrollbar* scrollbar)
if (!scrollbar->enabled())
return 0;
- float proportion = (float)scrollbar->visibleSize() / scrollbar->totalSize();
+ float proportion = scrollbar->visibleSize() / usedTotalSize(scrollbar);
int trackLen = trackLength(scrollbar);
int length = proportion * trackLen;
length = max(length, minimumThumbLength(scrollbar));
diff --git a/Source/WebCore/platform/URLString.h b/Source/WebCore/platform/URLString.h
new file mode 100644
index 0000000..78e4b33
--- /dev/null
+++ b/Source/WebCore/platform/URLString.h
@@ -0,0 +1,52 @@
+/*
+ * 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 GOOGLE, 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 URLString_h
+#define URLString_h
+
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class KURL;
+
+class URLString {
+public:
+ const String& string() const { return m_string; }
+
+private:
+ friend class KURL;
+
+ explicit URLString(const String& string)
+ : m_string(string)
+ {
+ }
+
+ String m_string;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/android/TemporaryLinkStubs.cpp b/Source/WebCore/platform/android/TemporaryLinkStubs.cpp
index d3c8183..cf15462 100644
--- a/Source/WebCore/platform/android/TemporaryLinkStubs.cpp
+++ b/Source/WebCore/platform/android/TemporaryLinkStubs.cpp
@@ -76,6 +76,8 @@
#include "Widget.h"
#include <stdio.h>
#include <stdlib.h>
+#include <wtf/Assertions.h>
+#include <wtf/MainThread.h>
#include <wtf/text/CString.h>
#if USE(JSC)
@@ -296,6 +298,16 @@ void* WebCore::Frame::dragImageForSelection()
return 0;
}
+<<<<<<< HEAD
+=======
+
+WTF::String WebCore::MIMETypeRegistry::getMIMETypeForExtension(WTF::String const&)
+{
+ ASSERT(isMainThread());
+ return WTF::String();
+}
+
+>>>>>>> webkit.org at r78450
void WebCore::Pasteboard::writeImage(WebCore::Node*, WebCore::KURL const&, WTF::String const&) {}
namespace WebCore {
diff --git a/Source/WebCore/platform/audio/FFTFrame.h b/Source/WebCore/platform/audio/FFTFrame.h
index 1a82ef0..f6e2066 100644
--- a/Source/WebCore/platform/audio/FFTFrame.h
+++ b/Source/WebCore/platform/audio/FFTFrame.h
@@ -35,12 +35,18 @@
#include <Accelerate/Accelerate.h>
#endif
-#if !OS(DARWIN) && USE(WEBAUDIO_MKL)
+#if !OS(DARWIN)
+#if USE(WEBAUDIO_MKL)
#include "mkl_dfti.h"
+#endif // USE(WEBAUDIO_MKL)
+#if USE(WEBAUDIO_FFTW)
+#include "fftw3.h"
+#endif // USE(WEBAUDIO_FFTW)
#endif
#include <wtf/PassOwnPtr.h>
#include <wtf/Platform.h>
+#include <wtf/Threading.h>
namespace WebCore {
@@ -56,6 +62,7 @@ public:
FFTFrame(const FFTFrame& frame);
~FFTFrame();
+ static void initialize();
static void cleanup();
void doFFT(float* data);
void doInverseFFT(float* data);
@@ -98,8 +105,8 @@ private:
DSPSplitComplex m_frame;
AudioFloatArray m_realData;
AudioFloatArray m_imagData;
-#endif // OS(DARWIN)
-#if !OS(DARWIN) && USE(WEBAUDIO_MKL)
+#else // !OS(DARWIN)
+#if USE(WEBAUDIO_MKL)
// Interleaves the planar real and imaginary data and returns a
// pointer to the resulting storage which can be used for in-place
// or out-of-place operations. FIXME: ideally all of the MKL
@@ -115,7 +122,31 @@ private:
AudioFloatArray m_complexData;
AudioFloatArray m_realData;
AudioFloatArray m_imagData;
-#endif // !OS(DARWIN) && USE(WEBAUDIO_MKL)
+#endif // USE(WEBAUDIO_MKL)
+#if USE(WEBAUDIO_FFTW)
+ fftwf_plan m_forwardPlan;
+ fftwf_plan m_backwardPlan;
+
+ enum Direction {
+ Forward,
+ Backward
+ };
+
+ // Both the real and imaginary data are stored here.
+ // The real data is stored first, followed by three float values of padding.
+ // The imaginary data is stored after the padding and is 16-byte aligned (if m_data itself is aligned).
+ // The reason we don't use separate arrays for real and imaginary is because the FFTW plans are shared
+ // between FFTFrame instances and require that the real and imaginary data pointers be the same distance apart.
+ AudioFloatArray m_data;
+
+ static Mutex *s_planLock;
+ static fftwf_plan* fftwForwardPlans;
+ static fftwf_plan* fftwBackwardPlans;
+
+ static fftwf_plan fftwPlanForSize(unsigned fftSize, Direction,
+ float*, float*, float*);
+#endif // USE(WEBAUDIO_FFTW)
+#endif // !OS(DARWIN)
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/audio/FFTFrameStub.cpp b/Source/WebCore/platform/audio/FFTFrameStub.cpp
index 17405c9..c76c0e2 100644
--- a/Source/WebCore/platform/audio/FFTFrameStub.cpp
+++ b/Source/WebCore/platform/audio/FFTFrameStub.cpp
@@ -36,9 +36,9 @@
namespace WebCore {
// Normal constructor: allocates for a given fftSize.
-FFTFrame::FFTFrame(unsigned fftSize)
- : m_FFTSize(fftSize)
- , m_log2FFTSize(static_cast<unsigned>(log2(fftSize)))
+FFTFrame::FFTFrame(unsigned /*fftSize*/)
+ : m_FFTSize(0)
+ , m_log2FFTSize(0)
{
ASSERT_NOT_REACHED();
}
diff --git a/Source/WebCore/platform/audio/chromium/AudioBusChromium.cpp b/Source/WebCore/platform/audio/chromium/AudioBusChromium.cpp
index 83ab9bf..de44b1c 100644
--- a/Source/WebCore/platform/audio/chromium/AudioBusChromium.cpp
+++ b/Source/WebCore/platform/audio/chromium/AudioBusChromium.cpp
@@ -42,7 +42,7 @@ PassOwnPtr<AudioBus> AudioBus::loadPlatformResource(const char* name, double sam
PassOwnPtr<AudioBus> createBusFromInMemoryAudioFile(const void* data, size_t dataSize, bool mixToMono, double sampleRate)
{
OwnPtr<AudioBus> audioBus = PlatformBridge::decodeAudioFileData(static_cast<const char*>(data), dataSize, sampleRate);
- if (audioBus->numberOfChannels() == 2 && mixToMono) {
+ 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.
diff --git a/Source/WebCore/platform/audio/fftw/FFTFrameFFTW.cpp b/Source/WebCore/platform/audio/fftw/FFTFrameFFTW.cpp
new file mode 100644
index 0000000..878ed9f
--- /dev/null
+++ b/Source/WebCore/platform/audio/fftw/FFTFrameFFTW.cpp
@@ -0,0 +1,301 @@
+/*
+ * 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.
+ */
+
+// FFTFrame implementation using the FFTW library.
+
+#include "config.h"
+
+#if ENABLE(WEB_AUDIO)
+
+#include "FFTFrame.h"
+
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+const int kMaxFFTPow2Size = 24;
+
+fftwf_plan* FFTFrame::fftwForwardPlans = 0;
+fftwf_plan* FFTFrame::fftwBackwardPlans = 0;
+
+Mutex* FFTFrame::s_planLock = 0;
+
+namespace {
+
+unsigned unpackedFFTWDataSize(unsigned fftSize)
+{
+ return fftSize / 2 + 1;
+}
+
+} // anonymous namespace
+
+
+// Normal constructor: allocates for a given fftSize.
+FFTFrame::FFTFrame(unsigned fftSize)
+ : m_FFTSize(fftSize)
+ , m_log2FFTSize(static_cast<unsigned>(log2(fftSize)))
+ , m_forwardPlan(0)
+ , m_backwardPlan(0)
+ , m_data(2 * (3 + unpackedFFTWDataSize(fftSize))) // enough space for real and imaginary data plus 16-byte alignment padding
+{
+ // We only allow power of two.
+ ASSERT(1UL << m_log2FFTSize == m_FFTSize);
+
+ // FFTW won't create a plan without being able to look at non-null
+ // pointers for the input and output data; it wants to be able to
+ // see whether these arrays are aligned properly for vector
+ // operations. Ideally we would use fftw_malloc and fftw_free for
+ // the input and output arrays to ensure proper alignment for SIMD
+ // operations, so that we don't have to specify FFTW_UNALIGNED
+ // when creating the plan. However, since we don't have control
+ // over the alignment of the array passed to doFFT / doInverseFFT,
+ // we would need to memcpy it in to or out of the FFTFrame, adding
+ // overhead. For the time being, we just assume unaligned data and
+ // pass a temporary pointer down.
+
+ float temporary;
+ m_forwardPlan = fftwPlanForSize(fftSize, Forward,
+ &temporary, realData(), imagData());
+ m_backwardPlan = fftwPlanForSize(fftSize, Backward,
+ realData(), imagData(), &temporary);
+}
+
+// Creates a blank/empty frame (interpolate() must later be called).
+FFTFrame::FFTFrame()
+ : m_FFTSize(0)
+ , m_log2FFTSize(0)
+ , m_forwardPlan(0)
+ , m_backwardPlan(0)
+{
+}
+
+// Copy constructor.
+FFTFrame::FFTFrame(const FFTFrame& frame)
+ : m_FFTSize(frame.m_FFTSize)
+ , m_log2FFTSize(frame.m_log2FFTSize)
+ , m_forwardPlan(0)
+ , m_backwardPlan(0)
+ , m_data(2 * (3 + unpackedFFTWDataSize(fftSize()))) // enough space for real and imaginary data plus 16-byte alignment padding
+{
+ // See the normal constructor for an explanation of the temporary pointer.
+ float temporary;
+ m_forwardPlan = fftwPlanForSize(m_FFTSize, Forward,
+ &temporary, realData(), imagData());
+ m_backwardPlan = fftwPlanForSize(m_FFTSize, Backward,
+ realData(), imagData(), &temporary);
+
+ // Copy/setup frame data.
+ size_t nbytes = sizeof(float) * unpackedFFTWDataSize(fftSize());
+ memcpy(realData(), frame.realData(), nbytes);
+ memcpy(imagData(), frame.imagData(), nbytes);
+}
+
+FFTFrame::~FFTFrame()
+{
+}
+
+void FFTFrame::multiply(const FFTFrame& frame)
+{
+ FFTFrame& frame1 = *this;
+ FFTFrame& frame2 = const_cast<FFTFrame&>(frame);
+
+ float* realP1 = frame1.realData();
+ float* imagP1 = frame1.imagData();
+ const float* realP2 = frame2.realData();
+ const float* imagP2 = frame2.imagData();
+
+ // Scale accounts the peculiar scaling of vecLib on the Mac.
+ // This ensures the right scaling all the way back to inverse FFT.
+ // FIXME: if we change the scaling on the Mac then this scale
+ // factor will need to change too.
+ float scale = 0.5f;
+
+ // Multiply the packed DC/nyquist component
+ realP1[0] *= scale * realP2[0];
+ imagP1[0] *= scale * imagP2[0];
+
+ // Complex multiplication. If this loop turns out to be hot then
+ // we should use SSE or other intrinsics to accelerate it.
+ unsigned halfSize = fftSize() / 2;
+
+ for (unsigned i = 1; i < halfSize; ++i) {
+ float realResult = realP1[i] * realP2[i] - imagP1[i] * imagP2[i];
+ float imagResult = realP1[i] * imagP2[i] + imagP1[i] * realP2[i];
+
+ realP1[i] = scale * realResult;
+ imagP1[i] = scale * imagResult;
+ }
+}
+
+void FFTFrame::doFFT(float* data)
+{
+ fftwf_execute_split_dft_r2c(m_forwardPlan, data, realData(), imagData());
+
+ // Scale the frequency domain data to match vecLib's scale factor
+ // on the Mac. FIXME: if we change the definition of FFTFrame to
+ // eliminate this scale factor then this code will need to change.
+ // Also, if this loop turns out to be hot then we should use SSE
+ // or other intrinsics to accelerate it.
+ float scaleFactor = 2;
+ unsigned length = unpackedFFTWDataSize(fftSize());
+ float* realData = this->realData();
+ float* imagData = this->imagData();
+
+ for (unsigned i = 0; i < length; ++i) {
+ realData[i] = realData[i] * scaleFactor;
+ imagData[i] = imagData[i] * scaleFactor;
+ }
+
+ // Move the Nyquist component to the location expected by the
+ // FFTFrame API.
+ imagData[0] = realData[length - 1];
+}
+
+void FFTFrame::doInverseFFT(float* data)
+{
+ unsigned length = unpackedFFTWDataSize(fftSize());
+ float* realData = this->realData();
+ float* imagData = this->imagData();
+
+ // Move the Nyquist component to the location expected by FFTW.
+ realData[length - 1] = imagData[0];
+ imagData[length - 1] = 0;
+ imagData[0] = 0;
+
+ fftwf_execute_split_dft_c2r(m_backwardPlan, realData, imagData, data);
+
+ // Restore the original scaling of the time domain data.
+ // FIXME: if we change the definition of FFTFrame to eliminate the
+ // scale factor then this code will need to change. Also, if this
+ // loop turns out to be hot then we should use SSE or other
+ // intrinsics to accelerate it.
+ float scaleFactor = 1.0 / (2.0 * fftSize());
+ unsigned n = fftSize();
+ for (unsigned i = 0; i < n; ++i)
+ data[i] *= scaleFactor;
+
+ // Move the Nyquist component back to the location expected by the
+ // FFTFrame API.
+ imagData[0] = realData[length - 1];
+}
+
+void FFTFrame::initialize()
+{
+ if (!fftwForwardPlans) {
+ fftwForwardPlans = new fftwf_plan[kMaxFFTPow2Size];
+ fftwBackwardPlans = new fftwf_plan[kMaxFFTPow2Size];
+ for (int i = 0; i < kMaxFFTPow2Size; ++i) {
+ fftwForwardPlans[i] = 0;
+ fftwBackwardPlans[i] = 0;
+ }
+ }
+
+ if (!s_planLock)
+ s_planLock = new Mutex();
+}
+
+void FFTFrame::cleanup()
+{
+ if (!fftwForwardPlans)
+ return;
+
+ for (int i = 0; i < kMaxFFTPow2Size; ++i) {
+ if (fftwForwardPlans[i])
+ fftwf_destroy_plan(fftwForwardPlans[i]);
+ if (fftwBackwardPlans[i])
+ fftwf_destroy_plan(fftwBackwardPlans[i]);
+ }
+
+ delete[] fftwForwardPlans;
+ delete[] fftwBackwardPlans;
+
+ fftwForwardPlans = 0;
+ fftwBackwardPlans = 0;
+
+ delete s_planLock;
+ s_planLock = 0;
+}
+
+float* FFTFrame::realData() const
+{
+ return const_cast<float*>(m_data.data());
+}
+
+float* FFTFrame::imagData() const
+{
+ // Imaginary data is stored following the real data with enough padding for 16-byte alignment.
+ return const_cast<float*>(realData() + unpackedFFTWDataSize(fftSize()) + 3);
+}
+
+fftwf_plan FFTFrame::fftwPlanForSize(unsigned fftSize, Direction direction,
+ float* data1, float* data2, float* data3)
+{
+ // initialize() must be called first.
+ ASSERT(fftwForwardPlans);
+ if (!fftwForwardPlans)
+ return 0;
+
+ ASSERT(s_planLock);
+ if (!s_planLock)
+ return 0;
+ MutexLocker locker(*s_planLock);
+
+ ASSERT(fftSize);
+ int pow2size = static_cast<int>(log2(fftSize));
+ ASSERT(pow2size < kMaxFFTPow2Size);
+ fftwf_plan* plans = (direction == Forward) ? fftwForwardPlans : fftwBackwardPlans;
+ if (!plans[pow2size]) {
+ fftwf_iodim dimension;
+ dimension.n = fftSize;
+ dimension.is = 1;
+ dimension.os = 1;
+
+ // For the time being, we do not take the input data into
+ // account when choosing a plan, so that we can most easily
+ // reuse plans with different input data.
+
+ // FIXME: allocate input and output data inside this class to
+ // be able to take advantage of alignment and SIMD optimizations.
+ unsigned flags = FFTW_ESTIMATE | FFTW_PRESERVE_INPUT | FFTW_UNALIGNED;
+ switch (direction) {
+ case Forward:
+ plans[pow2size] = fftwf_plan_guru_split_dft_r2c(1, &dimension, 0, 0,
+ data1, data2, data3,
+ flags);
+ break;
+ case Backward:
+ plans[pow2size] = fftwf_plan_guru_split_dft_c2r(1, &dimension, 0, 0,
+ data1, data2, data3,
+ flags);
+ break;
+ }
+ }
+ ASSERT(plans[pow2size]);
+ return plans[pow2size];
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/platform/audio/mac/FFTFrameMac.cpp b/Source/WebCore/platform/audio/mac/FFTFrameMac.cpp
index 0f7efb7..6456da2 100644
--- a/Source/WebCore/platform/audio/mac/FFTFrameMac.cpp
+++ b/Source/WebCore/platform/audio/mac/FFTFrameMac.cpp
@@ -162,6 +162,10 @@ FFTSetup FFTFrame::fftSetupForSize(unsigned fftSize)
return fftSetups[pow2size];
}
+void FFTFrame::initialize()
+{
+}
+
void FFTFrame::cleanup()
{
if (!fftSetups)
diff --git a/Source/WebCore/platform/audio/mkl/FFTFrameMKL.cpp b/Source/WebCore/platform/audio/mkl/FFTFrameMKL.cpp
index f66a485..3ac6b36 100644
--- a/Source/WebCore/platform/audio/mkl/FFTFrameMKL.cpp
+++ b/Source/WebCore/platform/audio/mkl/FFTFrameMKL.cpp
@@ -200,6 +200,10 @@ void FFTFrame::doInverseFFT(float* data)
ASSERT(DftiErrorClass(status, DFTI_NO_ERROR));
}
+void FFTFrame::initialize()
+{
+}
+
void FFTFrame::cleanup()
{
if (!descriptorHandles)
diff --git a/Source/WebCore/platform/brew/MIMETypeRegistryBrew.cpp b/Source/WebCore/platform/brew/MIMETypeRegistryBrew.cpp
index 0a538c2..eae4e3b 100644
--- a/Source/WebCore/platform/brew/MIMETypeRegistryBrew.cpp
+++ b/Source/WebCore/platform/brew/MIMETypeRegistryBrew.cpp
@@ -30,6 +30,8 @@
#include "MIMETypeRegistry.h"
#include "PlatformString.h"
+#include <wtf/Assertions.h>
+#include <wtf/MainThread.h>
namespace WebCore {
@@ -63,6 +65,8 @@ static const ExtensionMap extensionMap[] = {
String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
{
+ ASSERT(isMainThread());
+
String str = ext.lower();
const ExtensionMap* e = extensionMap;
diff --git a/Source/WebCore/platform/brew/SystemTimeBrew.cpp b/Source/WebCore/platform/brew/SystemTimeBrew.cpp
index c1e39fb..6e2fe7e 100644
--- a/Source/WebCore/platform/brew/SystemTimeBrew.cpp
+++ b/Source/WebCore/platform/brew/SystemTimeBrew.cpp
@@ -26,15 +26,16 @@
#include "config.h"
#include "SystemTime.h"
-#include <float.h>
+#include "NotImplemented.h"
+#include <limits>
namespace WebCore {
float userIdleTime()
{
- // return an arbitrarily high userIdleTime so that releasing pages from the page cache isn't postponed
- return FLT_MAX;
-}
-
+ notImplemented();
+ // Return an arbitrarily high userIdleTime so that releasing pages from the page cache isn't postponed.
+ return std::numeric_limits<float>::max();
}
+} // namespace WebCore
diff --git a/Source/WebCore/platform/cf/BinaryPropertyList.cpp b/Source/WebCore/platform/cf/BinaryPropertyList.cpp
index 27b44d4..41769e8 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 StringImpl::computeHash(reinterpret_cast<const UChar*>(array.integers()), array.size() / (sizeof(int) / sizeof(UChar)));
+ return WTF::StringHasher::createBlobHash(array.integers(), array.size());
}
bool IntegerArrayHash::equal(const IntegerArray& a, const IntegerArray& b)
diff --git a/Source/WebCore/platform/cf/FileSystemCF.cpp b/Source/WebCore/platform/cf/FileSystemCF.cpp
index e3a144c..a4b422b 100644
--- a/Source/WebCore/platform/cf/FileSystemCF.cpp
+++ b/Source/WebCore/platform/cf/FileSystemCF.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 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
@@ -25,12 +25,13 @@
* (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 "FileSystem.h"
#import "PlatformString.h"
-#import <wtf/text/CString.h>
#import <wtf/RetainPtr.h>
+#import <wtf/text/CString.h>
namespace WebCore {
@@ -54,4 +55,16 @@ CString fileSystemRepresentation(const String& path)
return string;
}
+RetainPtr<CFURLRef> pathAsURL(const String& path)
+{
+ CFURLPathStyle pathStyle;
+#if PLATFORM(WIN)
+ pathStyle = kCFURLWindowsPathStyle;
+#else
+ pathStyle = kCFURLPOSIXPathStyle;
+#endif
+ return RetainPtr<CFURLRef>(AdoptCF, CFURLCreateWithFileSystemPath(0,
+ RetainPtr<CFStringRef>(AdoptCF, path.createCFString()).get(), pathStyle, FALSE));
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/chromium/ChromiumDataObject.cpp b/Source/WebCore/platform/chromium/ChromiumDataObject.cpp
index 78b794b..f5732df 100644
--- a/Source/WebCore/platform/chromium/ChromiumDataObject.cpp
+++ b/Source/WebCore/platform/chromium/ChromiumDataObject.cpp
@@ -56,9 +56,9 @@ PassRefPtr<ChromiumDataObject> ChromiumDataObject::create(PassRefPtr<ChromiumDat
return adoptRef(new ChromiumDataObject(data));
}
-PassRefPtr<ChromiumDataObject> ChromiumDataObject::createReadable(Clipboard::ClipboardType clipboardType)
+PassRefPtr<ChromiumDataObject> ChromiumDataObject::createReadable(const Frame* frame, Clipboard::ClipboardType clipboardType)
{
- return adoptRef(new ChromiumDataObject(ReadableDataObject::create(clipboardType)));
+ return adoptRef(new ChromiumDataObject(ReadableDataObject::create(frame, clipboardType)));
}
PassRefPtr<ChromiumDataObject> ChromiumDataObject::createWritable(Clipboard::ClipboardType clipboardType)
diff --git a/Source/WebCore/platform/chromium/ChromiumDataObject.h b/Source/WebCore/platform/chromium/ChromiumDataObject.h
index 4aac5c9..919c269 100644
--- a/Source/WebCore/platform/chromium/ChromiumDataObject.h
+++ b/Source/WebCore/platform/chromium/ChromiumDataObject.h
@@ -41,7 +41,7 @@ namespace WebCore {
class ChromiumDataObject : public RefCounted<ChromiumDataObject> {
public:
static PassRefPtr<ChromiumDataObject> create(PassRefPtr<ChromiumDataObjectLegacy> data);
- static PassRefPtr<ChromiumDataObject> createReadable(Clipboard::ClipboardType);
+ static PassRefPtr<ChromiumDataObject> createReadable(const Frame*, Clipboard::ClipboardType);
static PassRefPtr<ChromiumDataObject> createWritable(Clipboard::ClipboardType);
void clearData(const String& type);
diff --git a/Source/WebCore/platform/chromium/ClipboardChromium.cpp b/Source/WebCore/platform/chromium/ClipboardChromium.cpp
index 46b4339..d6ba2d2 100644
--- a/Source/WebCore/platform/chromium/ClipboardChromium.cpp
+++ b/Source/WebCore/platform/chromium/ClipboardChromium.cpp
@@ -91,7 +91,7 @@ PassRefPtr<ClipboardChromium> ClipboardChromium::create(ClipboardType clipboardT
RefPtr<ChromiumDataObject> dataObject =
policy == ClipboardWritable ?
ChromiumDataObject::createWritable(clipboardType) :
- ChromiumDataObject::createReadable(clipboardType);
+ ChromiumDataObject::createReadable(frame, clipboardType);
return adoptRef(new ClipboardChromium(clipboardType, dataObject, policy, frame));
}
diff --git a/Source/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp b/Source/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp
index fec0e9b..91bfccb 100644
--- a/Source/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp
+++ b/Source/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp
@@ -42,6 +42,17 @@
namespace WebCore {
+#if ENABLE(FILE_SYSTEM) && ENABLE(WORKERS)
+String MIMETypeRegistry::getMIMETypeForExtensionThreadSafe(const String &ext)
+{
+ return PlatformBridge::mimeTypeForExtension(ext);
+}
+#endif
+
+// NOTE: We have to define getMIMETypeForExtension() here though the shared
+// implementation has getMIMETypeForExtension() since we don't use the shared
+// implementation bits in MIMETypeRegistry.cpp.
+
String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
{
return PlatformBridge::mimeTypeForExtension(ext);
diff --git a/Source/WebCore/platform/chromium/PlatformBridge.h b/Source/WebCore/platform/chromium/PlatformBridge.h
index f6a2564..9a09b90 100644
--- a/Source/WebCore/platform/chromium/PlatformBridge.h
+++ b/Source/WebCore/platform/chromium/PlatformBridge.h
@@ -109,9 +109,9 @@ public:
static void clipboardWriteData(const String& type, const String& data, const String& metadata);
// Interface for handling copy and paste, drag and drop, and selection copy.
- static HashSet<String> clipboardReadAvailableTypes(PasteboardPrivate::ClipboardBuffer, bool* containsFilenames);
- static bool clipboardReadData(PasteboardPrivate::ClipboardBuffer, const String& type, String& data, String& metadata);
- static Vector<String> clipboardReadFilenames(PasteboardPrivate::ClipboardBuffer);
+ static HashSet<String> clipboardReadAvailableTypes(const Frame*, PasteboardPrivate::ClipboardBuffer, bool* containsFilenames);
+ static bool clipboardReadData(const Frame*, PasteboardPrivate::ClipboardBuffer, const String& type, String& data, String& metadata);
+ static Vector<String> clipboardReadFilenames(const Frame*, PasteboardPrivate::ClipboardBuffer);
// Cookies ------------------------------------------------------------
static void setCookies(const Document*, const KURL&, const String& value);
@@ -171,7 +171,6 @@ public:
// IndexedDB ----------------------------------------------------------
static PassRefPtr<IDBFactoryBackendInterface> idbFactory();
- static void idbShutdown();
// Extracts keyPath from values and returns the corresponding keys.
static void createIDBKeysFromSerializedValuesAndKeyPath(const Vector<RefPtr<SerializedScriptValue> >& values, const String& keyPath, Vector<RefPtr<IDBKey> >& keys);
diff --git a/Source/WebCore/platform/chromium/PopupMenuChromium.cpp b/Source/WebCore/platform/chromium/PopupMenuChromium.cpp
index 075cef0..59441d0 100644
--- a/Source/WebCore/platform/chromium/PopupMenuChromium.cpp
+++ b/Source/WebCore/platform/chromium/PopupMenuChromium.cpp
@@ -32,7 +32,6 @@
#include "config.h"
#include "PopupMenuChromium.h"
-#include "CharacterNames.h"
#include "Chrome.h"
#include "ChromeClientChromium.h"
#include "Font.h"
@@ -56,8 +55,8 @@
#include "SystemTime.h"
#include "TextRun.h"
#include "UserGestureIndicator.h"
-
#include <wtf/CurrentTime.h>
+#include <wtf/unicode/CharacterNames.h>
using namespace WTF;
using namespace Unicode;
@@ -74,17 +73,16 @@ static const int kMaxHeight = 500;
static const int kBorderSize = 1;
static const int kTextToLabelPadding = 10;
static const int kLabelToIconPadding = 5;
+static const int kMinEndOfLinePadding = 2;
static const TimeStamp kTypeAheadTimeoutMs = 1000;
// The settings used for the drop down menu.
// This is the delegate used if none is provided.
static const PopupContainerSettings dropDownSettings = {
- true, // setTextOnIndexChange
- true, // acceptOnAbandon
- false, // loopSelectionNavigation
- false, // restrictWidthOfListBox
- // display item text in its first strong directional character's directionality.
- PopupContainerSettings::FirstStrongDirectionalCharacterDirection,
+ true, // setTextOnIndexChange
+ true, // acceptOnAbandon
+ false, // loopSelectionNavigation
+ false // restrictWidthOfListBox
};
// This class uses WebCore code to paint and handle events for a drop-down list
@@ -330,7 +328,7 @@ PopupContainer::~PopupContainer()
removeChild(m_listBox.get());
}
-IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, const IntPoint& popupInitialCoordinate)
+IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, int popupInitialY)
{
// Reset the max height to its default value, it will be recomputed below
// if necessary.
@@ -350,8 +348,10 @@ IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, co
// If the popup would extend past the bottom of the screen, open upwards
// instead.
FloatRect screen = screenAvailableRect(m_frameView.get());
- widgetRect = chromeClient->windowToScreen(IntRect(popupInitialCoordinate, targetSize));
- if (widgetRect.bottom() > static_cast<int>(screen.bottom())) {
+ // Use this::x() for location because RTL position is considered
+ // in layout().
+ widgetRect = chromeClient->windowToScreen(IntRect(x(), popupInitialY, targetSize.width(), targetSize.height()));
+ if (widgetRect.maxY() > static_cast<int>(screen.maxY())) {
if (widgetRect.y() - widgetRect.height() - targetControlHeight > 0) {
// There is enough room to open upwards.
widgetRect.move(0, -(widgetRect.height() + targetControlHeight));
@@ -359,7 +359,7 @@ IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, co
// Figure whether upwards or downwards has more room and set the
// maximum number of items.
int spaceAbove = widgetRect.y() - targetControlHeight;
- int spaceBelow = screen.bottom() - widgetRect.y();
+ int spaceBelow = screen.maxY() - widgetRect.y();
if (spaceAbove > spaceBelow)
m_listBox->setMaxHeight(spaceAbove);
else
@@ -383,7 +383,7 @@ void PopupContainer::showPopup(FrameView* view)
ChromeClientChromium* chromeClient = chromeClientChromium();
if (chromeClient) {
IntRect popupRect = frameRect();
- chromeClient->popupOpened(this, layoutAndCalculateWidgetRect(popupRect.height(), popupRect.location()), false);
+ chromeClient->popupOpened(this, layoutAndCalculateWidgetRect(popupRect.height(), popupRect.y()), false);
m_popupOpen = true;
}
@@ -399,34 +399,6 @@ void PopupContainer::showPopup(FrameView* view)
invalidate();
}
-void PopupContainer::showExternal(const IntRect& rect, FrameView* v, int index)
-{
- if (!listBox())
- return;
-
- listBox()->setBaseWidth(rect.width());
- listBox()->updateFromElement();
-
- if (listBox()->numItems() < 1) {
- hidePopup();
- return;
- }
-
- // Adjust the popup position to account for scrolling.
- IntPoint location = v->contentsToWindow(rect.location());
- IntRect popupRect(location, rect.size());
-
- // Get the ChromeClient and pass it the popup menu's listbox data.
- m_frameView = v;
- chromeClientChromium()->popupOpened(this, popupRect, true);
-
- // The popup sends its "closed" notification through its parent. Set the
- // parent, even though external popups have no real on-screen widget but a
- // native menu (see |PopupListBox::hidePopup()|);
- if (!m_listBox->parent())
- addChild(m_listBox.get());
-}
-
void PopupContainer::hidePopup()
{
listBox()->hidePopup();
@@ -581,7 +553,7 @@ void PopupContainer::refresh(const IntRect& targetControlRect)
listBox()->updateFromElement();
// Store the original height to check if we need to request the location.
int originalHeight = height();
- IntRect widgetRect = layoutAndCalculateWidgetRect(targetControlRect.height(), location);
+ IntRect widgetRect = layoutAndCalculateWidgetRect(targetControlRect.height(), location.y());
if (originalHeight != widgetRect.height())
setFrameRect(widgetRect);
@@ -967,20 +939,15 @@ void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowInd
}
// Prepare the directionality to draw text.
- bool rtl = false;
- if (m_settings.itemTextDirectionalityHint == PopupContainerSettings::DOMElementDirection)
- rtl = style.textDirection() == RTL;
- else if (m_settings.itemTextDirectionalityHint ==
- PopupContainerSettings::FirstStrongDirectionalCharacterDirection)
- rtl = itemText.defaultWritingDirection() == WTF::Unicode::RightToLeft;
- TextRun textRun(itemText.characters(), itemText.length(), false, 0, 0, rtl);
+ bool rtl = style.textDirection() == RTL;
+ TextRun textRun(itemText.characters(), itemText.length(), false, 0, 0, TextRun::AllowTrailingExpansion, rtl, style.hasTextDirectionOverride());
// If the text is right-to-left, make it right-aligned by adjusting its
// beginning position.
if (rightAligned)
textX += maxWidth - itemFont.width(textRun);
// Draw the item text.
- int textY = rowRect.y() + itemFont.ascent() + (rowRect.height() - itemFont.height()) / 2;
+ int textY = rowRect.y() + itemFont.fontMetrics().ascent() + (rowRect.height() - itemFont.fontMetrics().height()) / 2;
gc->drawBidiText(itemFont, textRun, IntPoint(textX, textY));
// We are using the left padding as the right padding includes room for the scroll-bar which
@@ -1001,7 +968,7 @@ void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowInd
// Draw the the label if applicable.
if (itemLabel.isEmpty())
return;
- TextRun labelTextRun(itemLabel.characters(), itemLabel.length(), false, 0, 0, rtl);
+ TextRun labelTextRun(itemLabel.characters(), itemLabel.length(), false, 0, 0, TextRun::AllowTrailingExpansion, rtl, style.hasTextDirectionOverride());
if (rightAligned)
textX = max(0, m_popupClient->clientPaddingLeft() - m_popupClient->clientInsetLeft());
else
@@ -1120,7 +1087,7 @@ int PopupListBox::getRowHeight(int index)
String icon = m_popupClient->itemIcon(index);
RefPtr<Image> image(Image::loadPlatformResource(icon.utf8().data()));
- int fontHeight = getRowFont(index).height();
+ int fontHeight = getRowFont(index).fontMetrics().height();
int iconHeight = (image && !image->isNull()) ? image->rect().height() : 0;
return max(fontHeight, iconHeight);
@@ -1154,9 +1121,9 @@ void PopupListBox::scrollToRevealRow(int index)
if (rowRect.y() < scrollY()) {
// Row is above current scroll position, scroll up.
ScrollView::setScrollPosition(IntPoint(0, rowRect.y()));
- } else if (rowRect.bottom() > scrollY() + visibleHeight()) {
+ } else if (rowRect.maxY() > scrollY() + visibleHeight()) {
// Row is below current scroll position, scroll down.
- ScrollView::setScrollPosition(IntPoint(0, rowRect.bottom() - visibleHeight()));
+ ScrollView::setScrollPosition(IntPoint(0, rowRect.maxY() - visibleHeight()));
}
}
@@ -1267,6 +1234,9 @@ void PopupListBox::updateFromElement()
type = PopupItem::TypeOption;
m_items.append(new PopupItem(m_popupClient->itemText(i), type));
m_items[i]->enabled = isSelectableItem(i);
+ PopupMenuStyle style = m_popupClient->itemStyle(i);
+ m_items[i]->textDirection = style.textDirection();
+ m_items[i]->hasTextDirectionOverride = style.hasTextDirectionOverride();
}
m_selectedIndex = m_popupClient->selectedIndex();
@@ -1277,9 +1247,12 @@ void PopupListBox::updateFromElement()
void PopupListBox::layout()
{
+ bool isRightAligned = m_popupClient->menuStyle().textDirection() == RTL;
+
// Size our child items.
int baseWidth = 0;
int paddingWidth = 0;
+ int lineEndPaddingWidth = 0;
int y = 0;
for (int i = 0; i < numItems(); ++i) {
// Place the item vertically.
@@ -1312,58 +1285,56 @@ void PopupListBox::layout()
// FIXME: http://b/1210481 We should get the padding of individual option elements.
paddingWidth = max(paddingWidth,
m_popupClient->clientPaddingLeft() + m_popupClient->clientPaddingRight());
+ lineEndPaddingWidth = max(lineEndPaddingWidth,
+ isRightAligned ? m_popupClient->clientPaddingLeft() : m_popupClient->clientPaddingRight());
}
// Calculate scroll bar width.
int windowHeight = 0;
-
-#if OS(DARWIN)
- // Set the popup's window to contain all available items on Mac only, which
- // uses native controls that manage their own scrolling. This allows hit
- // testing to work when selecting items in popups that have more menu entries
- // than the maximum window size.
- m_visibleRows = numItems();
-#else
m_visibleRows = min(numItems(), kMaxVisibleRows);
-#endif
for (int i = 0; i < m_visibleRows; ++i) {
int rowHeight = getRowHeight(i);
-#if !OS(DARWIN)
// Only clip the window height for non-Mac platforms.
if (windowHeight + rowHeight > m_maxHeight) {
m_visibleRows = i;
break;
}
-#endif
windowHeight += rowHeight;
}
// Set our widget and scrollable contents sizes.
int scrollbarWidth = 0;
- if (m_visibleRows < numItems())
+ if (m_visibleRows < numItems()) {
scrollbarWidth = ScrollbarTheme::nativeTheme()->scrollbarThickness();
+ // Use kMinEndOfLinePadding when there is a scrollbar so that we use
+ // as much as (lineEndPaddingWidth - kMinEndOfLinePadding) padding
+ // space for scrollbar and allow user to use CSS padding to make the
+ // popup listbox align with the select element.
+ paddingWidth = paddingWidth - lineEndPaddingWidth + kMinEndOfLinePadding;
+ }
+
int windowWidth;
int contentWidth;
if (m_settings.restrictWidthOfListBox) {
windowWidth = m_baseWidth;
- contentWidth = m_baseWidth - scrollbarWidth - paddingWidth;
+ contentWidth = m_baseWidth - scrollbarWidth;
} else {
windowWidth = baseWidth + scrollbarWidth + paddingWidth;
- contentWidth = baseWidth;
+ contentWidth = baseWidth + paddingWidth;
if (windowWidth < m_baseWidth) {
windowWidth = m_baseWidth;
- contentWidth = m_baseWidth - scrollbarWidth - paddingWidth;
+ contentWidth = m_baseWidth - scrollbarWidth;
} else
m_baseWidth = baseWidth;
}
resize(windowWidth, windowHeight);
- setContentsSize(IntSize(contentWidth, getRowBounds(numItems() - 1).bottom()));
+ setContentsSize(IntSize(contentWidth, getRowBounds(numItems() - 1).maxY()));
if (hostWindow())
scrollToRevealSelection();
@@ -1404,19 +1375,11 @@ PopupMenuChromium::~PopupMenuChromium()
hide();
}
-// The Mac Chromium implementation relies on external control (a Cocoa control)
-// to display, handle the input tracking and menu item selection for the popup.
-// Windows and Linux Chromium let our WebKit port handle the display, while
-// another process manages the popup window and input handling.
void PopupMenuChromium::show(const IntRect& r, FrameView* v, int index)
{
if (!p.popup)
p.popup = PopupContainer::create(client(), PopupContainer::Select, dropDownSettings);
-#if OS(DARWIN)
- p.popup->showExternal(r, v, index);
-#else
p.popup->show(r, v, index);
-#endif
}
void PopupMenuChromium::hide()
diff --git a/Source/WebCore/platform/chromium/PopupMenuChromium.h b/Source/WebCore/platform/chromium/PopupMenuChromium.h
index f326b48..43b8b0e 100644
--- a/Source/WebCore/platform/chromium/PopupMenuChromium.h
+++ b/Source/WebCore/platform/chromium/PopupMenuChromium.h
@@ -65,6 +65,8 @@ struct PopupItem {
String label;
Type type;
int yOffset; // y offset of this item, relative to the top of the popup.
+ TextDirection textDirection;
+ bool hasTextDirectionOverride;
bool enabled;
};
@@ -97,22 +99,6 @@ struct PopupContainerSettings {
// Whether we should restrict the width of the PopupListBox or not.
// Autocomplete popups are restricted, combo-boxes (select tags) aren't.
bool restrictWidthOfListBox;
-
- // A hint on the display directionality of the item text in popup menu.
- //
- // We could either display the items in the drop-down using its DOM element's
- // directionality, or we could display the items in the drop-down using heuristics:
- // such as in its first strong directionality character's direction.
- // Please refer to the discussion (especially comment #7 and #10) in
- // https://bugs.webkit.org/show_bug.cgi?id=27889 for details.
- enum DirectionalityHint {
- // Use the DOM element's directionality to display the item text in popup menu.
- DOMElementDirection,
- // Use the item text's first strong-directional character's directionality
- // to display the item text in popup menu.
- FirstStrongDirectionalCharacterDirection,
- };
- DirectionalityHint itemTextDirectionalityHint;
};
class PopupContainer : public FramelessScrollView {
@@ -142,9 +128,6 @@ public:
// Show the popup
void showPopup(FrameView*);
- // Used on Mac Chromium for HTML select popup menus.
- void showExternal(const IntRect&, FrameView*, int index);
-
// Show the popup in the specified rect for the specified frame.
// Note: this code was somehow arbitrarily factored-out of the Popup class
// so WebViewImpl can create a PopupContainer. This method is used for
@@ -194,7 +177,7 @@ private:
void paintBorder(GraphicsContext*, const IntRect&);
// Layout and calculate popup widget size and location and returns it as IntRect.
- IntRect layoutAndCalculateWidgetRect(int targetControlHeight, const IntPoint& popupInitialCoordinate);
+ IntRect layoutAndCalculateWidgetRect(int targetControlHeight, int popupInitialY);
// Returns the ChromeClient of the page this popup is associated with.
ChromeClientChromium* chromeClientChromium();
diff --git a/Source/WebCore/platform/chromium/ReadableDataObject.cpp b/Source/WebCore/platform/chromium/ReadableDataObject.cpp
index dbf4739..484a1b3 100644
--- a/Source/WebCore/platform/chromium/ReadableDataObject.cpp
+++ b/Source/WebCore/platform/chromium/ReadableDataObject.cpp
@@ -43,13 +43,14 @@ static PasteboardPrivate::ClipboardBuffer clipboardBuffer(Clipboard::ClipboardTy
return clipboardType == Clipboard::DragAndDrop ? PasteboardPrivate::DragBuffer : PasteboardPrivate::StandardBuffer;
}
-PassRefPtr<ReadableDataObject> ReadableDataObject::create(Clipboard::ClipboardType clipboardType)
+PassRefPtr<ReadableDataObject> ReadableDataObject::create(const Frame* frame, Clipboard::ClipboardType clipboardType)
{
- return adoptRef(new ReadableDataObject(clipboardType));
+ return adoptRef(new ReadableDataObject(frame, clipboardType));
}
-ReadableDataObject::ReadableDataObject(Clipboard::ClipboardType clipboardType)
- : m_clipboardType(clipboardType)
+ReadableDataObject::ReadableDataObject(const Frame* frame, Clipboard::ClipboardType clipboardType)
+ : m_frame(frame)
+ , m_clipboardType(clipboardType)
, m_containsFilenames(false)
, m_isTypeCacheInitialized(false)
{
@@ -93,7 +94,7 @@ String ReadableDataObject::getData(const String& type, bool& succeeded) const
return data;
}
succeeded = PlatformBridge::clipboardReadData(
- clipboardBuffer(m_clipboardType), type, data, ignoredMetadata);
+ m_frame, clipboardBuffer(m_clipboardType), type, data, ignoredMetadata);
return data;
}
@@ -102,7 +103,7 @@ String ReadableDataObject::urlTitle() const
String ignoredData;
String urlTitle;
PlatformBridge::clipboardReadData(
- clipboardBuffer(m_clipboardType), mimeTypeTextURIList, ignoredData, urlTitle);
+ m_frame, clipboardBuffer(m_clipboardType), mimeTypeTextURIList, ignoredData, urlTitle);
return urlTitle;
}
@@ -111,7 +112,7 @@ KURL ReadableDataObject::htmlBaseUrl() const
String ignoredData;
String htmlBaseUrl;
PlatformBridge::clipboardReadData(
- clipboardBuffer(m_clipboardType), mimeTypeTextHTML, ignoredData, htmlBaseUrl);
+ m_frame, clipboardBuffer(m_clipboardType), mimeTypeTextHTML, ignoredData, htmlBaseUrl);
return KURL(ParsedURLString, htmlBaseUrl);
}
@@ -123,7 +124,7 @@ bool ReadableDataObject::containsFilenames() const
Vector<String> ReadableDataObject::filenames() const
{
- return PlatformBridge::clipboardReadFilenames(clipboardBuffer(m_clipboardType));
+ return PlatformBridge::clipboardReadFilenames(m_frame, clipboardBuffer(m_clipboardType));
}
void ReadableDataObject::ensureTypeCacheInitialized() const
@@ -132,7 +133,7 @@ void ReadableDataObject::ensureTypeCacheInitialized() const
return;
m_types = PlatformBridge::clipboardReadAvailableTypes(
- clipboardBuffer(m_clipboardType), &m_containsFilenames);
+ m_frame, clipboardBuffer(m_clipboardType), &m_containsFilenames);
m_isTypeCacheInitialized = true;
}
diff --git a/Source/WebCore/platform/chromium/ReadableDataObject.h b/Source/WebCore/platform/chromium/ReadableDataObject.h
index 027e0ed..c6cc310 100644
--- a/Source/WebCore/platform/chromium/ReadableDataObject.h
+++ b/Source/WebCore/platform/chromium/ReadableDataObject.h
@@ -44,7 +44,7 @@ namespace WebCore {
// browser to the renderer.
class ReadableDataObject : public RefCounted<ReadableDataObject> {
public:
- static PassRefPtr<ReadableDataObject> create(Clipboard::ClipboardType);
+ static PassRefPtr<ReadableDataObject> create(const Frame*, Clipboard::ClipboardType);
bool hasData() const;
HashSet<String> types() const;
@@ -57,11 +57,14 @@ public:
Vector<String> filenames() const;
private:
- explicit ReadableDataObject(Clipboard::ClipboardType);
+ explicit ReadableDataObject(const Frame*, Clipboard::ClipboardType);
// This isn't always const... but most of the time it is.
void ensureTypeCacheInitialized() const;
+ // The owner frame. Used to send IPCs back to the correspdonging view via WebFrameClient.
+ const Frame* m_frame;
+
Clipboard::ClipboardType m_clipboardType;
// To avoid making a lot of IPC calls for each drag event, we cache some
diff --git a/Source/WebCore/platform/chromium/ScrollbarThemeChromium.cpp b/Source/WebCore/platform/chromium/ScrollbarThemeChromium.cpp
index b23e625..9e700c2 100644
--- a/Source/WebCore/platform/chromium/ScrollbarThemeChromium.cpp
+++ b/Source/WebCore/platform/chromium/ScrollbarThemeChromium.cpp
@@ -128,7 +128,7 @@ void ScrollbarThemeChromium::paintTickmarks(GraphicsContext* context, Scrollbar*
const float percent = static_cast<float>(i->y()) / scrollbar->totalSize();
// Calculate how far down (in pixels) the tick-mark should appear.
- const int yPos = rect.topLeft().y() + (rect.height() * percent);
+ const int yPos = rect.y() + (rect.height() * percent);
IntPoint tick(scrollbar->x(), yPos);
context->drawImage(dash.get(), ColorSpaceDeviceRGB, tick);
diff --git a/Source/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm b/Source/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm
index fe1a422..b0ba95d 100644
--- a/Source/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm
+++ b/Source/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm
@@ -450,11 +450,11 @@ bool ScrollbarThemeChromiumMac::paint(Scrollbar* scrollbar, GraphicsContext* con
continue;
// Calculate how far down (in pixels) the tick-mark should appear.
- const int yPos = static_cast<int>((thumbArea.topLeft().y() + (thumbArea.height() * percent))) & ~1;
+ const int yPos = static_cast<int>((thumbArea.y() + (thumbArea.height() * percent))) & ~1;
// Paint.
const int indent = 2;
- FloatRect tickRect(thumbArea.topLeft().x() + indent, yPos, thumbArea.width() - 2 * indent - 1, 2);
+ FloatRect tickRect(thumbArea.x() + indent, yPos, thumbArea.width() - 2 * indent - 1, 2);
drawingContext->fillRect(tickRect);
drawingContext->strokeRect(tickRect, 1);
}
diff --git a/Source/WebCore/platform/efl/MIMETypeRegistryEfl.cpp b/Source/WebCore/platform/efl/MIMETypeRegistryEfl.cpp
index d0c95bf..d883e5d 100644
--- a/Source/WebCore/platform/efl/MIMETypeRegistryEfl.cpp
+++ b/Source/WebCore/platform/efl/MIMETypeRegistryEfl.cpp
@@ -31,6 +31,9 @@
#include "config.h"
#include "MIMETypeRegistry.h"
+#include <wtf/Assertions.h>
+#include <wtf/MainThread.h>
+
namespace WebCore {
struct ExtensionMap {
@@ -72,6 +75,8 @@ static const ExtensionMap extensionMap[] = {
String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
{
+ ASSERT(isMainThread());
+
String s = ext.lower();
const ExtensionMap *e = extensionMap;
while (e->extension) {
diff --git a/Source/WebCore/platform/efl/RenderThemeEfl.cpp b/Source/WebCore/platform/efl/RenderThemeEfl.cpp
index 9df12e9..9102d17 100644
--- a/Source/WebCore/platform/efl/RenderThemeEfl.cpp
+++ b/Source/WebCore/platform/efl/RenderThemeEfl.cpp
@@ -1043,4 +1043,83 @@ bool RenderThemeEfl::paintProgressBar(RenderObject* o, const PaintInfo& i, const
}
#endif
+#if ENABLE(VIDEO)
+String RenderThemeEfl::extraMediaControlsStyleSheet()
+{
+ notImplemented();
+ return String();
+}
+
+String RenderThemeEfl::formatMediaControlsCurrentTime(float currentTime, float duration) const
+{
+ notImplemented();
+ return String();
+}
+
+bool RenderThemeEfl::paintMediaFullscreenButton(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ notImplemented();
+ return false;
+}
+
+bool RenderThemeEfl::paintMediaMuteButton(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ notImplemented();
+ return false;
+}
+
+bool RenderThemeEfl::paintMediaPlayButton(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ notImplemented();
+ return false;
+}
+
+bool RenderThemeEfl::paintMediaSeekBackButton(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ notImplemented();
+ return false;
+}
+
+bool RenderThemeEfl::paintMediaSeekForwardButton(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ notImplemented();
+ return false;
+}
+
+bool RenderThemeEfl::paintMediaSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+ notImplemented();
+ return false;
+}
+
+bool RenderThemeEfl::paintMediaSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+ notImplemented();
+ return false;
+}
+
+bool RenderThemeEfl::paintMediaVolumeSliderContainer(RenderObject*, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ notImplemented();
+ return false;
+}
+
+bool RenderThemeEfl::paintMediaVolumeSliderTrack(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ notImplemented();
+ return false;
+}
+
+bool RenderThemeEfl::paintMediaVolumeSliderThumb(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ notImplemented();
+ return false;
+}
+
+bool RenderThemeEfl::paintMediaCurrentTime(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ notImplemented();
+ return false;
+}
+#endif
}
diff --git a/Source/WebCore/platform/efl/RenderThemeEfl.h b/Source/WebCore/platform/efl/RenderThemeEfl.h
index 087e2aa..d4887cf 100644
--- a/Source/WebCore/platform/efl/RenderThemeEfl.h
+++ b/Source/WebCore/platform/efl/RenderThemeEfl.h
@@ -153,6 +153,23 @@ public:
virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&);
#endif
+#if ENABLE(VIDEO)
+ virtual String extraMediaControlsStyleSheet();
+ virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const;
+
+ virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaPlayButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaSeekBackButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaSeekForwardButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaVolumeSliderContainer(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaVolumeSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaVolumeSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaCurrentTime(RenderObject*, const PaintInfo&, const IntRect&);
+#endif
+
protected:
static float defaultFontSize;
diff --git a/Source/WebCore/platform/efl/SystemTimeEfl.cpp b/Source/WebCore/platform/efl/SystemTimeEfl.cpp
index de8c87c..ec6d662 100644
--- a/Source/WebCore/platform/efl/SystemTimeEfl.cpp
+++ b/Source/WebCore/platform/efl/SystemTimeEfl.cpp
@@ -28,7 +28,9 @@
#include "config.h"
#include "SystemTime.h"
+#include "NotImplemented.h"
#include <Ecore.h>
+#include <limits>
namespace WebCore {
@@ -37,4 +39,11 @@ double currentTime()
return ecore_time_get();
}
+float userIdleTime()
+{
+ notImplemented();
+ // Return an arbitrarily high userIdleTime so that releasing pages from the page cache isn't postponed.
+ return std::numeric_limits<float>::max();
}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/efl/TemporaryLinkStubs.cpp b/Source/WebCore/platform/efl/TemporaryLinkStubs.cpp
index ef6e6f7..07ea2e6 100644
--- a/Source/WebCore/platform/efl/TemporaryLinkStubs.cpp
+++ b/Source/WebCore/platform/efl/TemporaryLinkStubs.cpp
@@ -56,12 +56,6 @@ String signedPublicKeyAndChallengeString(unsigned keySizeIndex, const String &ch
return String();
}
-float userIdleTime()
-{
- notImplemented();
- return FLT_MAX;
-}
-
void setCookieStoragePrivateBrowsingEnabled(bool)
{
notImplemented();
diff --git a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp
index f416b47..9e64904 100644
--- a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp
+++ b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp
@@ -25,7 +25,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
#include "ANGLEWebKitBridge.h"
#include <wtf/OwnArrayPtr.h>
@@ -93,7 +93,7 @@ bool ANGLEWebKitBridge::validateShaderSource(const char* shaderSource, ANGLEShad
int logSize = 0;
ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &logSize);
if (logSize > 1) {
- OwnArrayPtr<char> logBuffer(new char[logSize]);
+ OwnArrayPtr<char> logBuffer = adoptArrayPtr(new char[logSize]);
if (logBuffer) {
ShGetInfoLog(compiler, logBuffer.get());
shaderValidationLog = logBuffer.get();
@@ -105,7 +105,7 @@ bool ANGLEWebKitBridge::validateShaderSource(const char* shaderSource, ANGLEShad
int translationLength = 0;
ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &translationLength);
if (translationLength > 1) {
- OwnArrayPtr<char> translationBuffer(new char[translationLength]);
+ OwnArrayPtr<char> translationBuffer = adoptArrayPtr(new char[translationLength]);
if (!translationBuffer)
return false;
ShGetObjectCode(compiler, translationBuffer.get());
@@ -117,4 +117,4 @@ bool ANGLEWebKitBridge::validateShaderSource(const char* shaderSource, ANGLEShad
}
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/ContextShadow.h b/Source/WebCore/platform/graphics/ContextShadow.h
index a1fba5c..c0571f0 100644
--- a/Source/WebCore/platform/graphics/ContextShadow.h
+++ b/Source/WebCore/platform/graphics/ContextShadow.h
@@ -68,6 +68,8 @@ typedef void* PlatformContext;
// This class should be copyable since GraphicsContextQt keeps a stack of
// the shadow state for savePlatformState and restorePlatformState.
+// This class is Deprecated. Platforms should migrate to ShadowBlur.
+
class ContextShadow {
public:
enum {
diff --git a/Source/WebCore/platform/graphics/Extensions3D.h b/Source/WebCore/platform/graphics/Extensions3D.h
index 1a2b7a1..6d6efe5 100644
--- a/Source/WebCore/platform/graphics/Extensions3D.h
+++ b/Source/WebCore/platform/graphics/Extensions3D.h
@@ -52,6 +52,7 @@ public:
// GL_ANGLE_framebuffer_blit / GL_ANGLE_framebuffer_multisample
// GL_OES_texture_float
// GL_OES_standard_derivatives
+ // GL_OES_rgb8_rgba8
// Takes full name of extension; for example,
// "GL_EXT_texture_format_BGRA8888".
@@ -87,6 +88,10 @@ public:
// GL_OES_standard_derivatives names
FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B,
+
+ // GL_OES_rgb8_rgba8 names
+ RGB8_OES = 0x8051,
+ RGBA8_OES = 0x8058,
};
// GL_ARB_robustness
diff --git a/Source/WebCore/platform/graphics/FloatQuad.h b/Source/WebCore/platform/graphics/FloatQuad.h
index 6cd86f6..e913723 100644
--- a/Source/WebCore/platform/graphics/FloatQuad.h
+++ b/Source/WebCore/platform/graphics/FloatQuad.h
@@ -54,9 +54,9 @@ public:
FloatQuad(const FloatRect& inRect)
: m_p1(inRect.location())
- , m_p2(inRect.right(), inRect.y())
- , m_p3(inRect.right(), inRect.bottom())
- , m_p4(inRect.x(), inRect.bottom())
+ , m_p2(inRect.maxX(), inRect.y())
+ , m_p3(inRect.maxX(), inRect.maxY())
+ , m_p4(inRect.x(), inRect.maxY())
{
}
diff --git a/Source/WebCore/platform/graphics/FloatRect.cpp b/Source/WebCore/platform/graphics/FloatRect.cpp
index 0d8a24e..36f3d3a 100644
--- a/Source/WebCore/platform/graphics/FloatRect.cpp
+++ b/Source/WebCore/platform/graphics/FloatRect.cpp
@@ -51,22 +51,22 @@ bool FloatRect::intersects(const FloatRect& other) const
{
// Checking emptiness handles negative widths as well as zero.
return !isEmpty() && !other.isEmpty()
- && x() < other.right() && other.x() < right()
- && y() < other.bottom() && other.y() < bottom();
+ && x() < other.maxX() && other.x() < maxX()
+ && y() < other.maxY() && other.y() < maxY();
}
bool FloatRect::contains(const FloatRect& other) const
{
- return x() <= other.x() && right() >= other.right()
- && y() <= other.y() && bottom() >= other.bottom();
+ return x() <= other.x() && maxX() >= other.maxX()
+ && y() <= other.y() && maxY() >= other.maxY();
}
void FloatRect::intersect(const FloatRect& other)
{
float l = max(x(), other.x());
float t = max(y(), other.y());
- float r = min(right(), other.right());
- float b = min(bottom(), other.bottom());
+ float r = min(maxX(), other.maxX());
+ float b = min(maxY(), other.maxY());
// Return a clean empty rectangle for non-intersecting cases.
if (l >= r || t >= b) {
@@ -91,8 +91,8 @@ void FloatRect::unite(const FloatRect& other)
float l = min(x(), other.x());
float t = min(y(), other.y());
- float r = max(right(), other.right());
- float b = max(bottom(), other.bottom());
+ float r = max(maxX(), other.maxX());
+ float b = max(maxY(), other.maxY());
setLocationAndSizeFromEdges(l, t, r, b);
}
@@ -180,8 +180,8 @@ IntRect enclosingIntRect(const FloatRect& rect)
{
float left = floorf(rect.x());
float top = floorf(rect.y());
- float width = ceilf(rect.right()) - left;
- float height = ceilf(rect.bottom()) - top;
+ float width = ceilf(rect.maxX()) - left;
+ float height = ceilf(rect.maxY()) - top;
return IntRect(safeFloatToInt(left), safeFloatToInt(top),
safeFloatToInt(width), safeFloatToInt(height));
}
diff --git a/Source/WebCore/platform/graphics/FloatRect.h b/Source/WebCore/platform/graphics/FloatRect.h
index 10ad838..733f7cc 100644
--- a/Source/WebCore/platform/graphics/FloatRect.h
+++ b/Source/WebCore/platform/graphics/FloatRect.h
@@ -90,6 +90,8 @@ public:
float x() const { return m_location.x(); }
float y() const { return m_location.y(); }
+ float maxX() const { return x() + width(); }
+ float maxY() const { return y() + height(); }
float width() const { return m_size.width(); }
float height() const { return m_size.height(); }
@@ -100,11 +102,6 @@ public:
bool isEmpty() const { return m_size.isEmpty(); }
- float left() const { return x(); }
- float right() const { return x() + width(); }
- float top() const { return y(); }
- float bottom() const { return y() + height(); }
-
FloatPoint center() const { return FloatPoint(x() + width() / 2, y() + height() / 2); }
void move(const FloatSize& delta) { m_location += delta; }
@@ -119,10 +116,9 @@ public:
// Note, this doesn't match what IntRect::contains(IntPoint&) does; the int version
// is really checking for containment of 1x1 rect, but that doesn't make sense with floats.
bool contains(float px, float py) const
- { return px >= x() && px <= right() && py >= y() && py <= bottom(); }
+ { return px >= x() && px <= maxX() && py >= y() && py <= maxY(); }
bool contains(const FloatPoint& point) const { return contains(point.x(), point.y()); }
-
void inflateX(float dx) {
m_location.setX(m_location.x() - dx);
m_size.setWidth(m_size.width() + dx + dx);
diff --git a/Source/WebCore/platform/graphics/Font.cpp b/Source/WebCore/platform/graphics/Font.cpp
index 394de35..6bdddfc 100644
--- a/Source/WebCore/platform/graphics/Font.cpp
+++ b/Source/WebCore/platform/graphics/Font.cpp
@@ -2,7 +2,7 @@
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2006, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2006, 2010, 2011 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
@@ -247,21 +247,15 @@ bool Font::isSVGFont() const
}
#endif
-String Font::normalizeSpaces(const String& string)
+String Font::normalizeSpaces(const UChar* characters, unsigned length)
{
- const UChar* characters = string.characters();
- unsigned length = string.length();
- Vector<UChar, 256> buffer(length);
- bool didReplacement = false;
-
- for (unsigned i = 0; i < length; ++i) {
- UChar originalCharacter = characters[i];
- buffer[i] = normalizeSpaces(originalCharacter);
- if (buffer[i] != originalCharacter)
- didReplacement = true;
- }
+ UChar* buffer;
+ String normalized = String::createUninitialized(length, buffer);
+
+ for (unsigned i = 0; i < length; ++i)
+ buffer[i] = normalizeSpaces(characters[i]);
- return didReplacement ? String(buffer.data(), length) : string;
+ return normalized;
}
static bool shouldUseFontSmoothing = true;
@@ -293,7 +287,7 @@ Font::CodePath Font::codePath(const TextRun& run) const
return s_codePath;
#if PLATFORM(QT)
- if (run.padding() || run.rtl() || isSmallCaps() || wordSpacing() || letterSpacing())
+ if (run.expansion() || run.rtl() || isSmallCaps() || wordSpacing() || letterSpacing())
return Complex;
#endif
@@ -458,6 +452,56 @@ bool Font::isCJKIdeographOrSymbol(UChar32 c)
return isCJKIdeograph(c);
}
+unsigned Font::expansionOpportunityCount(const UChar* characters, size_t length, TextDirection direction, bool& isAfterExpansion)
+{
+ static bool expandAroundIdeographs = canExpandAroundIdeographsInComplexText();
+ unsigned count = 0;
+ if (direction == LTR) {
+ for (size_t i = 0; i < length; ++i) {
+ UChar32 character = characters[i];
+ if (treatAsSpace(character)) {
+ count++;
+ isAfterExpansion = true;
+ continue;
+ }
+ if (U16_IS_LEAD(character) && i + 1 < length && U16_IS_TRAIL(characters[i + 1])) {
+ character = U16_GET_SUPPLEMENTARY(character, characters[i + 1]);
+ i++;
+ }
+ if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) {
+ if (!isAfterExpansion)
+ count++;
+ count++;
+ isAfterExpansion = true;
+ continue;
+ }
+ isAfterExpansion = false;
+ }
+ } else {
+ for (size_t i = length; i > 0; --i) {
+ UChar32 character = characters[i - 1];
+ if (treatAsSpace(character)) {
+ count++;
+ isAfterExpansion = true;
+ continue;
+ }
+ if (U16_IS_TRAIL(character) && i > 1 && U16_IS_LEAD(characters[i - 2])) {
+ character = U16_GET_SUPPLEMENTARY(characters[i - 2], character);
+ i--;
+ }
+ if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) {
+ if (!isAfterExpansion)
+ count++;
+ count++;
+ isAfterExpansion = true;
+ continue;
+ }
+ isAfterExpansion = false;
+ }
+ }
+ return count;
+}
+
bool Font::canReceiveTextEmphasis(UChar32 c)
{
CharCategory category = Unicode::category(c);
diff --git a/Source/WebCore/platform/graphics/Font.h b/Source/WebCore/platform/graphics/Font.h
index 2957c0a..258240b 100644
--- a/Source/WebCore/platform/graphics/Font.h
+++ b/Source/WebCore/platform/graphics/Font.h
@@ -2,7 +2,7 @@
* Copyright (C) 2000 Lars Knoll (knoll@kde.org)
* (C) 2000 Antti Koivisto (koivisto@kde.org)
* (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2006, 2007, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2006, 2007, 2010, 2011 Apple Inc. All rights reserved.
* Copyright (C) 2008 Holger Hans Peter Freyther
*
* This library is free software; you can redistribute it and/or
@@ -25,14 +25,15 @@
#ifndef Font_h
#define Font_h
-#include "CharacterNames.h"
#include "FontDescription.h"
#include "FontFallbackList.h"
#include "SimpleFontData.h"
+#include "TextDirection.h"
#include "TypesettingFeatures.h"
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/MathExtras.h>
+#include <wtf/unicode/CharacterNames.h>
#if PLATFORM(QT)
#include <QFont>
@@ -43,7 +44,7 @@ namespace WebCore {
class FloatPoint;
class FloatRect;
class FontData;
-class FontFallbackList;
+class FontMetrics;
class FontPlatformData;
class FontSelector;
class GlyphBuffer;
@@ -54,8 +55,6 @@ class TextRun;
struct GlyphData;
-const unsigned defaultUnitsPerEm = 1000;
-
struct GlyphOverflow {
GlyphOverflow()
: left(0)
@@ -124,17 +123,12 @@ public:
bool italic() const { return m_fontDescription.italic(); }
FontWeight weight() const { return m_fontDescription.weight(); }
+ FontWidthVariant widthVariant() const { return m_fontDescription.widthVariant(); }
bool isPlatformFont() const { return m_isPlatformFont; }
// Metrics that we query the FontFallbackList for.
- int ascent(FontBaseline baselineType = AlphabeticBaseline) const { return primaryFont()->ascent(baselineType); }
- int descent(FontBaseline baselineType = AlphabeticBaseline) const { return primaryFont()->descent(baselineType); }
- int height() const { return ascent() + descent(); }
- int lineSpacing() const { return primaryFont()->lineSpacing(); }
- int lineGap() const { return primaryFont()->lineGap(); }
- float xHeight() const { return primaryFont()->xHeight(); }
- unsigned unitsPerEm() const { return primaryFont()->unitsPerEm(); }
+ const FontMetrics& fontMetrics() const { return primaryFont()->fontMetrics(); }
int spaceWidth() const { return (int)ceilf(primaryFont()->adjustedSpaceWidth() + m_letterSpacing); }
float tabWidth(const SimpleFontData& fontData) const { return 8 * ceilf(fontData.adjustedSpaceWidth() + letterSpacing()); }
int emphasisMarkAscent(const AtomicString&) const;
@@ -150,7 +144,9 @@ public:
static bool isCJKIdeograph(UChar32);
static bool isCJKIdeographOrSymbol(UChar32);
-
+
+ static unsigned expansionOpportunityCount(const UChar*, size_t length, TextDirection, bool& isAfterExpansion);
+
#if PLATFORM(QT)
QFont font() const;
#endif
@@ -185,6 +181,7 @@ private:
bool getEmphasisMarkGlyphData(const AtomicString&, GlyphData&) const;
static bool canReturnFallbackFontsForComplexText();
+ static bool canExpandAroundIdeographsInComplexText();
CodePath codePath(const TextRun&) const;
@@ -226,7 +223,7 @@ public:
return character;
}
- static String normalizeSpaces(const String&);
+ static String normalizeSpaces(const UChar*, unsigned length);
#if ENABLE(SVG_FONTS)
bool isSVGFont() const;
diff --git a/Source/WebCore/platform/graphics/FontCache.cpp b/Source/WebCore/platform/graphics/FontCache.cpp
index cfca980..ca82ebd 100644
--- a/Source/WebCore/platform/graphics/FontCache.cpp
+++ b/Source/WebCore/platform/graphics/FontCache.cpp
@@ -57,7 +57,7 @@ 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)
+ bool isPrinterFont = false, FontRenderingMode renderingMode = NormalRenderingMode, FontOrientation orientation = Horizontal, FontWidthVariant widthVariant = RegularWidth)
: m_size(size)
, m_weight(weight)
, m_family(family)
@@ -65,6 +65,7 @@ public:
, m_printerFont(isPrinterFont)
, m_renderingMode(renderingMode)
, m_orientation(orientation)
+ , m_widthVariant(widthVariant)
{
}
@@ -75,7 +76,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_renderingMode == other.m_renderingMode && m_orientation == other.m_orientation && m_widthVariant == other.m_widthVariant;
}
unsigned m_size;
@@ -85,6 +86,7 @@ public:
bool m_printerFont;
FontRenderingMode m_renderingMode;
FontOrientation m_orientation;
+ FontWidthVariant m_widthVariant;
private:
static unsigned hashTableDeletedSize() { return 0xFFFFFFFFU; }
@@ -92,10 +94,11 @@ private:
inline unsigned computeHash(const FontPlatformDataCacheKey& fontKey)
{
- unsigned hashCodes[4] = {
+ unsigned hashCodes[5] = {
CaseFoldingHash::hash(fontKey.m_family),
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)
};
return WTF::StringHasher::createBlobHash<sizeof(hashCodes)>(hashCodes);
@@ -195,7 +198,7 @@ FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fo
}
FontPlatformDataCacheKey key(familyName, fontDescription.computedPixelSize(), fontDescription.weight(), fontDescription.italic(),
- fontDescription.usePrinterFont(), fontDescription.renderingMode(), fontDescription.orientation());
+ fontDescription.usePrinterFont(), fontDescription.renderingMode(), fontDescription.orientation(), 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 12900bf..283d297 100644
--- a/Source/WebCore/platform/graphics/FontDescription.h
+++ b/Source/WebCore/platform/graphics/FontDescription.h
@@ -30,6 +30,7 @@
#include "FontRenderingMode.h"
#include "FontSmoothingMode.h"
#include "FontTraitsMask.h"
+#include "FontWidthVariant.h"
#include "TextRenderingMode.h"
namespace WebCore {
@@ -57,6 +58,7 @@ public:
: m_specifiedSize(0)
, m_computedSize(0)
, m_orientation(Horizontal)
+ , m_widthVariant(RegularWidth)
, m_italic(false)
, m_smallCaps(false)
, m_isAbsoluteSize(false)
@@ -97,6 +99,7 @@ public:
FontTraitsMask traitsMask() const;
bool isSpecifiedFont() const { return m_isSpecifiedFont; }
FontOrientation orientation() const { return m_orientation; }
+ FontWidthVariant widthVariant() const { return m_widthVariant; }
void setFamily(const FontFamily& family) { m_familyList = family; }
void setComputedSize(float s) { m_computedSize = s; }
@@ -117,6 +120,7 @@ public:
void setTextRenderingMode(TextRenderingMode rendering) { m_textRendering = rendering; }
void setIsSpecifiedFont(bool isSpecifiedFont) { m_isSpecifiedFont = isSpecifiedFont; }
void setOrientation(FontOrientation orientation) { m_orientation = orientation; }
+ void setWidthVariant(FontWidthVariant widthVariant) { m_widthVariant = widthVariant; }
private:
FontFamily m_familyList; // The list of font families to be used.
@@ -126,6 +130,8 @@ private:
float m_computedSize; // Computed size adjusted for the minimum font size and the zoom factor.
FontOrientation m_orientation;
+
+ FontWidthVariant m_widthVariant;
bool m_italic : 1;
bool m_smallCaps : 1;
@@ -162,7 +168,8 @@ inline bool FontDescription::operator==(const FontDescription& other) const
&& m_fontSmoothing == other.m_fontSmoothing
&& m_textRendering == other.m_textRendering
&& m_isSpecifiedFont == other.m_isSpecifiedFont
- && m_orientation == other.m_orientation;
+ && m_orientation == other.m_orientation
+ && m_widthVariant == other.m_widthVariant;
}
}
diff --git a/Source/WebCore/platform/graphics/FontFastPath.cpp b/Source/WebCore/platform/graphics/FontFastPath.cpp
index f927c13..034ac22 100644
--- a/Source/WebCore/platform/graphics/FontFastPath.cpp
+++ b/Source/WebCore/platform/graphics/FontFastPath.cpp
@@ -23,7 +23,6 @@
#include "config.h"
#include "Font.h"
-#include "CharacterNames.h"
#include "FloatRect.h"
#include "FontCache.h"
#include "FontFallbackList.h"
@@ -32,8 +31,8 @@
#include "SimpleFontData.h"
#include "TextRun.h"
#include "WidthIterator.h"
-
#include <wtf/MathExtras.h>
+#include <wtf/unicode/CharacterNames.h>
#include <wtf/unicode/Unicode.h>
using namespace WTF;
@@ -252,7 +251,7 @@ int Font::emphasisMarkAscent(const AtomicString& mark) const
if (!markFontData)
return 0;
- return markFontData->ascent();
+ return markFontData->fontMetrics().ascent();
}
int Font::emphasisMarkDescent(const AtomicString& mark) const
@@ -266,7 +265,7 @@ int Font::emphasisMarkDescent(const AtomicString& mark) const
if (!markFontData)
return 0;
- return markFontData->descent();
+ return markFontData->fontMetrics().descent();
}
int Font::emphasisMarkHeight(const AtomicString& mark) const
@@ -280,7 +279,7 @@ int Font::emphasisMarkHeight(const AtomicString& mark) const
if (!markFontData)
return 0;
- return markFontData->height();
+ return markFontData->fontMetrics().height();
}
float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
@@ -414,8 +413,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()) - ascent());
- glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - descent());
+ glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - fontMetrics().ascent());
+ glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - fontMetrics().descent());
glyphOverflow->left = ceilf(it.firstGlyphOverflow());
glyphOverflow->right = ceilf(it.lastGlyphOverflow());
}
diff --git a/Source/WebCore/platform/graphics/FontMetrics.h b/Source/WebCore/platform/graphics/FontMetrics.h
new file mode 100644
index 0000000..89c5545
--- /dev/null
+++ b/Source/WebCore/platform/graphics/FontMetrics.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010-2011. 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 FontMetrics_h
+#define FontMetrics_h
+
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+const unsigned gDefaultUnitsPerEm = 1000;
+
+class FontMetrics {
+public:
+ FontMetrics()
+ : m_unitsPerEm(gDefaultUnitsPerEm)
+ , m_ascent(0)
+ , m_descent(0)
+ , m_lineGap(0)
+ , m_lineSpacing(0)
+ , m_xHeight(0)
+ {
+ }
+
+ unsigned unitsPerEm() const { return m_unitsPerEm; }
+ void setUnitsPerEm(unsigned unitsPerEm) { m_unitsPerEm = unitsPerEm; }
+
+ float floatAscent(FontBaseline baselineType = AlphabeticBaseline) const
+ {
+ if (baselineType == AlphabeticBaseline)
+ return m_ascent;
+ return floatHeight() / 2;
+ }
+
+ void setAscent(float ascent) { m_ascent = ascent; }
+
+ float floatDescent(FontBaseline baselineType = AlphabeticBaseline) const
+ {
+ if (baselineType == AlphabeticBaseline)
+ return m_descent;
+ return floatHeight() / 2;
+ }
+
+ void setDescent(float descent) { m_descent = descent; }
+
+ float floatHeight(FontBaseline baselineType = AlphabeticBaseline) const
+ {
+ return floatAscent(baselineType) + floatDescent(baselineType);
+ }
+
+ float floatLineGap() const { return m_lineGap; }
+ void setLineGap(float lineGap) { m_lineGap = lineGap; }
+
+ float floatLineSpacing() const { return m_lineSpacing; }
+ void setLineSpacing(float lineSpacing) { m_lineSpacing = lineSpacing; }
+
+ float xHeight() const { return m_xHeight; }
+ void setXHeight(float xHeight) { m_xHeight = xHeight; }
+
+ // Integer variants of certain metrics, used for HTML rendering.
+ int ascent(FontBaseline baselineType = AlphabeticBaseline) const
+ {
+ if (baselineType == AlphabeticBaseline)
+ return lroundf(m_ascent);
+ return height() - height() / 2;
+ }
+
+ int descent(FontBaseline baselineType = AlphabeticBaseline) const
+ {
+ if (baselineType == AlphabeticBaseline)
+ return lroundf(m_descent);
+ return height() / 2;
+ }
+
+ int height(FontBaseline baselineType = AlphabeticBaseline) const
+ {
+ return ascent(baselineType) + descent(baselineType);
+ }
+
+ int lineGap() const { return lroundf(m_lineGap); }
+ int lineSpacing() const { return lroundf(m_lineSpacing); }
+
+private:
+ friend class SimpleFontData;
+
+ void reset()
+ {
+ m_unitsPerEm = gDefaultUnitsPerEm;
+ m_ascent = 0;
+ m_descent = 0;
+ m_lineGap = 0;
+ m_lineSpacing = 0;
+ m_xHeight = 0;
+ }
+
+ unsigned m_unitsPerEm;
+ float m_ascent;
+ float m_descent;
+ float m_lineGap;
+ float m_lineSpacing;
+ float m_xHeight;
+};
+
+} // namespace WebCore
+
+#endif // FontMetrics_h
diff --git a/Source/WebCore/platform/graphics/FontWidthVariant.h b/Source/WebCore/platform/graphics/FontWidthVariant.h
new file mode 100644
index 0000000..bbc98ee
--- /dev/null
+++ b/Source/WebCore/platform/graphics/FontWidthVariant.h
@@ -0,0 +1,35 @@
+/*
+ * 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 FontWidthVariant_h
+#define FontWidthVariant_h
+
+namespace WebCore {
+
+enum FontWidthVariant { RegularWidth, HalfWidth, ThirdWidth, QuarterWidth };
+
+} // namespace WebCore
+
+#endif // FontWidthVariant_h
diff --git a/Source/WebCore/platform/graphics/GlyphBuffer.h b/Source/WebCore/platform/graphics/GlyphBuffer.h
index 6f1fe7b..7aac1e3 100644
--- a/Source/WebCore/platform/graphics/GlyphBuffer.h
+++ b/Source/WebCore/platform/graphics/GlyphBuffer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2009, 2011 Apple Inc. All rights reserved.
* Copyright (C) 2007-2008 Torch Mobile Inc.
*
* Redistribution and use in source and binary forms, with or without
@@ -187,7 +187,20 @@ public:
m_advances.append(advance);
}
#endif
-
+
+ void expandLastAdvance(float width)
+ {
+ ASSERT(!isEmpty());
+ GlyphBufferAdvance& lastAdvance = m_advances.last();
+#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN))
+ lastAdvance.width += width;
+#elif OS(WINCE)
+ lastAdvance += width;
+#else
+ lastAdvance += FloatSize(width, 0);
+#endif
+ }
+
private:
Vector<const SimpleFontData*, 2048> m_fontData;
Vector<GlyphBufferGlyph, 2048> m_glyphs;
diff --git a/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp b/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp
index 3df14b9..e7ed193 100644
--- a/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp
+++ b/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp
@@ -29,12 +29,12 @@
#include "config.h"
#include "GlyphPageTreeNode.h"
-#include "CharacterNames.h"
#include "PlatformString.h"
#include "SegmentedFontData.h"
#include "SimpleFontData.h"
#include <stdio.h>
#include <wtf/text/CString.h>
+#include <wtf/unicode/CharacterNames.h>
#include <wtf/unicode/Unicode.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/graphics/GraphicsContext.cpp b/Source/WebCore/platform/graphics/GraphicsContext.cpp
index 9f94ac9..a0a7ea9 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext.cpp
+++ b/Source/WebCore/platform/graphics/GraphicsContext.cpp
@@ -142,6 +142,18 @@ void GraphicsContext::setShadow(const FloatSize& offset, float blur, const Color
setPlatformShadow(offset, blur, color, colorSpace);
}
+void GraphicsContext::setLegacyShadow(const FloatSize& offset, float blur, const Color& color, ColorSpace colorSpace)
+{
+ m_state.shadowOffset = offset;
+ m_state.shadowBlur = blur;
+ m_state.shadowColor = color;
+ m_state.shadowColorSpace = colorSpace;
+#if PLATFORM(CG)
+ m_state.shadowsUseLegacyRadius = true;
+#endif
+ setPlatformShadow(offset, blur, color, colorSpace);
+}
+
void GraphicsContext::clearShadow()
{
m_state.shadowOffset = FloatSize();
@@ -532,10 +544,10 @@ void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorS
InterpolationQuality previousInterpolationQuality = imageInterpolationQuality();
// FIXME: Should be InterpolationLow
setImageInterpolationQuality(InterpolationNone);
- image->draw(this, styleColorSpace, dest, src, op, useLowQualityScale);
+ image->draw(this, styleColorSpace, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), op, useLowQualityScale);
setImageInterpolationQuality(previousInterpolationQuality);
} else
- image->draw(this, styleColorSpace, dest, src, op, useLowQualityScale);
+ image->draw(this, styleColorSpace, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), op, useLowQualityScale);
}
void GraphicsContext::addRoundedRectClip(const RoundedIntRect& rect)
@@ -565,6 +577,14 @@ void GraphicsContext::clipToImageBuffer(ImageBuffer* buffer, const FloatRect& re
buffer->clip(this, rect);
}
+#if !PLATFORM(CG)
+IntRect GraphicsContext::clipBounds() const
+{
+ ASSERT_NOT_REACHED();
+ return IntRect();
+}
+#endif
+
TextDrawingModeFlags GraphicsContext::textDrawingMode() const
{
return m_state.textDrawingMode;
@@ -590,6 +610,34 @@ void GraphicsContext::fillRoundedRect(const RoundedIntRect& rect, const Color& c
fillRoundedRect(rect.rect(), rect.radii().topLeft(), rect.radii().topRight(), rect.radii().bottomLeft(), rect.radii().bottomRight(), color, colorSpace);
}
+#if !PLATFORM(CG)
+void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const RoundedIntRect& roundedHoleRect, const Color& color, ColorSpace colorSpace)
+{
+ if (paintingDisabled())
+ return;
+
+ Path path;
+ path.addRect(rect);
+
+ if (!roundedHoleRect.radii().isZero())
+ path.addRoundedRect(roundedHoleRect.rect(), roundedHoleRect.radii().topLeft(), roundedHoleRect.radii().topRight(), roundedHoleRect.radii().bottomLeft(), roundedHoleRect.radii().bottomRight());
+ else
+ path.addRect(roundedHoleRect.rect());
+
+ WindRule oldFillRule = fillRule();
+ Color oldFillColor = fillColor();
+ ColorSpace oldFillColorSpace = fillColorSpace();
+
+ setFillRule(RULE_EVENODD);
+ setFillColor(color, colorSpace);
+
+ fillPath(path);
+
+ setFillRule(oldFillRule);
+ setFillColor(oldFillColor, oldFillColorSpace);
+}
+#endif
+
void GraphicsContext::setCompositeOperation(CompositeOperator compositeOperation)
{
m_state.compositeOperator = compositeOperation;
diff --git a/Source/WebCore/platform/graphics/GraphicsContext.h b/Source/WebCore/platform/graphics/GraphicsContext.h
index 77321e2..21a9067 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext.h
+++ b/Source/WebCore/platform/graphics/GraphicsContext.h
@@ -176,6 +176,11 @@ namespace WebCore {
, shouldSmoothFonts(true)
, paintingDisabled(false)
, shadowsIgnoreTransforms(false)
+#if PLATFORM(CG)
+ // Core Graphics incorrectly renders shadows with radius > 8px (<rdar://problem/8103442>),
+ // but we need to preserve this buggy behavior for canvas and -webkit-box-shadow.
+ , shadowsUseLegacyRadius(false)
+#endif
{
}
@@ -212,6 +217,9 @@ namespace WebCore {
bool shouldSmoothFonts : 1;
bool paintingDisabled : 1;
bool shadowsIgnoreTransforms : 1;
+#if PLATFORM(CG)
+ bool shadowsUseLegacyRadius : 1;
+#endif
};
class GraphicsContext {
@@ -320,6 +328,7 @@ namespace WebCore {
void fillRect(const FloatRect&, Generator&);
void fillRoundedRect(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color&, ColorSpace);
void fillRoundedRect(const RoundedIntRect&, const Color&, ColorSpace);
+ void fillRectWithRoundedHole(const IntRect&, const RoundedIntRect& roundedHoleRect, const Color&, ColorSpace);
void clearRect(const FloatRect&);
@@ -355,6 +364,8 @@ namespace WebCore {
void clipPath(const Path&, WindRule);
void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias = true);
void clipToImageBuffer(ImageBuffer*, const FloatRect&);
+
+ IntRect clipBounds() const;
TextDrawingModeFlags textDrawingMode() const;
void setTextDrawingMode(TextDrawingModeFlags);
@@ -385,6 +396,10 @@ namespace WebCore {
bool hasShadow() const;
void setShadow(const FloatSize&, float blur, const Color&, ColorSpace);
+ // Legacy shadow blur radius is used for canvas, and -webkit-box-shadow.
+ // It has different treatment of radii > 8px.
+ void setLegacyShadow(const FloatSize&, float blur, const Color&, ColorSpace);
+
bool getShadow(FloatSize&, float&, Color&, ColorSpace&) const;
void clearShadow();
@@ -404,16 +419,11 @@ namespace WebCore {
void setCompositeOperation(CompositeOperator);
CompositeOperator compositeOperation() const;
-#if PLATFORM(SKIA)
- void beginPath();
- void addPath(const Path&);
-#endif
-
void clip(const Path&);
// This clip function is used only by <canvas> code. It allows
// implementations to handle clipping on the canvas differently since
- // the disipline is different.
+ // the discipline is different.
void canvasClip(const Path&);
void clipOut(const Path&);
@@ -500,7 +510,6 @@ namespace WebCore {
bool inTransparencyLayer() const;
void pushTransparencyLayerInternal(const QRect &rect, qreal opacity, QPixmap& alphaMask);
void takeOwnershipOfPlatformContext();
- static QPainter::CompositionMode toQtCompositionMode(CompositeOperator op);
#endif
#if PLATFORM(QT) || PLATFORM(CAIRO)
diff --git a/Source/WebCore/platform/graphics/GraphicsContext3D.cpp b/Source/WebCore/platform/graphics/GraphicsContext3D.cpp
index f7c5a66..324fed8 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext3D.cpp
+++ b/Source/WebCore/platform/graphics/GraphicsContext3D.cpp
@@ -26,7 +26,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
#include "GraphicsContext3D.h"
@@ -1437,4 +1437,4 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData,
} // namespace WebCore
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/GraphicsContext3D.h b/Source/WebCore/platform/graphics/GraphicsContext3D.h
index 24827e5..d6c1cec 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext3D.h
+++ b/Source/WebCore/platform/graphics/GraphicsContext3D.h
@@ -47,7 +47,9 @@
typedef unsigned int GC3Denum;
typedef unsigned char GC3Dboolean;
typedef unsigned int GC3Dbitfield;
+typedef signed char GC3Dbyte;
typedef unsigned char GC3Dubyte;
+typedef short GC3Dshort;
typedef unsigned short GC3Dushort;
typedef int GC3Dint;
typedef int GC3Dsizei;
@@ -117,7 +119,7 @@ class GraphicsContext3DInternal;
class GraphicsContext3D : public RefCounted<GraphicsContext3D> {
public:
- enum WebGLEnumType {
+ enum {
DEPTH_BUFFER_BIT = 0x00000100,
STENCIL_BUFFER_BIT = 0x00000400,
COLOR_BUFFER_BIT = 0x00004000,
@@ -452,6 +454,14 @@ public:
RenderDirectlyToHostWindow
};
+ class ContextLostCallback {
+ public:
+ virtual void onContextLost() = 0;
+ virtual ~ContextLostCallback() {}
+ };
+
+ void setContextLostCallback(PassOwnPtr<ContextLostCallback>);
+
static PassRefPtr<GraphicsContext3D> create(Attributes, HostWindow*, RenderStyle = RenderOffscreen);
~GraphicsContext3D();
@@ -487,10 +497,6 @@ public:
void prepareTexture();
#endif
- // Helper to return the size in bytes of OpenGL data types
- // like GL_FLOAT, GL_INT, etc.
- unsigned int sizeInBytes(GC3Denum type);
-
// Helper to texImage2D with pixel==0 case: pixels are initialized to 0.
// Return true if no GL error is synthesized.
// By default, alignment is 4, the OpenGL default setting.
diff --git a/Source/WebCore/platform/graphics/Icon.h b/Source/WebCore/platform/graphics/Icon.h
index c83685f..2797133 100644
--- a/Source/WebCore/platform/graphics/Icon.h
+++ b/Source/WebCore/platform/graphics/Icon.h
@@ -42,6 +42,7 @@ typedef struct _GdkPixbuf GdkPixbuf;
#elif PLATFORM(EFL)
typedef struct _Evas_Object Evas_Object;
#elif PLATFORM(CHROMIUM)
+#include "Image.h"
#include "PlatformIcon.h"
#endif
@@ -60,6 +61,8 @@ public:
#if PLATFORM(WIN)
static PassRefPtr<Icon> create(HICON hIcon) { return adoptRef(new Icon(hIcon)); }
+#elif PLATFORM(CHROMIUM)
+ static PassRefPtr<Icon> create(PassRefPtr<PlatformIcon> icon) { return adoptRef(new Icon(icon)); }
#endif
private:
@@ -79,8 +82,8 @@ private:
Icon();
Evas_Object* m_icon;
#elif PLATFORM(CHROMIUM)
- Icon(const PlatformIcon&);
- PlatformIcon m_icon;
+ Icon(PassRefPtr<PlatformIcon>);
+ RefPtr<PlatformIcon> m_icon;
#endif
};
diff --git a/Source/WebCore/platform/graphics/IntRect.cpp b/Source/WebCore/platform/graphics/IntRect.cpp
index 188b5f9..7591c41 100644
--- a/Source/WebCore/platform/graphics/IntRect.cpp
+++ b/Source/WebCore/platform/graphics/IntRect.cpp
@@ -44,22 +44,22 @@ bool IntRect::intersects(const IntRect& other) const
{
// Checking emptiness handles negative widths as well as zero.
return !isEmpty() && !other.isEmpty()
- && x() < other.right() && other.x() < right()
- && y() < other.bottom() && other.y() < bottom();
+ && x() < other.maxX() && other.x() < maxX()
+ && y() < other.maxY() && other.y() < maxY();
}
bool IntRect::contains(const IntRect& other) const
{
- return x() <= other.x() && right() >= other.right()
- && y() <= other.y() && bottom() >= other.bottom();
+ return x() <= other.x() && maxX() >= other.maxX()
+ && y() <= other.y() && maxY() >= other.maxY();
}
void IntRect::intersect(const IntRect& other)
{
int l = max(x(), other.x());
int t = max(y(), other.y());
- int r = min(right(), other.right());
- int b = min(bottom(), other.bottom());
+ int r = min(maxX(), other.maxX());
+ int b = min(maxY(), other.maxY());
// Return a clean empty rectangle for non-intersecting cases.
if (l >= r || t >= b) {
@@ -87,8 +87,8 @@ void IntRect::unite(const IntRect& other)
int l = min(x(), other.x());
int t = min(y(), other.y());
- int r = max(right(), other.right());
- int b = max(bottom(), other.bottom());
+ int r = max(maxX(), other.maxX());
+ int b = max(maxY(), other.maxY());
m_location.setX(l);
m_location.setY(t);
diff --git a/Source/WebCore/platform/graphics/IntRect.h b/Source/WebCore/platform/graphics/IntRect.h
index 638db75..3a2433d 100644
--- a/Source/WebCore/platform/graphics/IntRect.h
+++ b/Source/WebCore/platform/graphics/IntRect.h
@@ -91,6 +91,8 @@ public:
int x() const { return m_location.x(); }
int y() const { return m_location.y(); }
+ int maxX() const { return x() + width(); }
+ int maxY() const { return y() + height(); }
int width() const { return m_size.width(); }
int height() const { return m_size.height(); }
@@ -99,18 +101,8 @@ public:
void setWidth(int width) { m_size.setWidth(width); }
void setHeight(int height) { m_size.setHeight(height); }
- // Be careful with these functions. The point is considered to be to the right and below. These are not
- // substitutes for right() and bottom().
- IntPoint topLeft() const { return m_location; }
- IntPoint topRight() const { return IntPoint(right() - 1, y()); }
- IntPoint bottomLeft() const { return IntPoint(x(), bottom() - 1); }
- IntPoint bottomRight() const { return IntPoint(right() - 1, bottom() - 1); }
-
bool isEmpty() const { return m_size.isEmpty(); }
- int right() const { return x() + width(); }
- int bottom() const { return y() + height(); }
-
// NOTE: The result is rounded to integer values, and thus may be not the exact
// center point.
IntPoint center() const { return IntPoint(x() + width() / 2, y() + height() / 2); }
@@ -118,26 +110,26 @@ public:
void move(const IntSize& s) { m_location += s; }
void move(int dx, int dy) { m_location.move(dx, dy); }
- void shiftLeftEdgeTo(int edge)
+ void shiftXEdgeTo(int edge)
{
int delta = edge - x();
setX(edge);
setWidth(std::max(0, width() - delta));
}
- void shiftRightEdgeTo(int edge)
+ void shiftMaxXEdgeTo(int edge)
{
- int delta = edge - right();
+ int delta = edge - maxX();
setWidth(std::max(0, width() + delta));
}
- void shiftTopEdgeTo(int edge)
+ void shiftYEdgeTo(int edge)
{
int delta = edge - y();
setY(edge);
setHeight(std::max(0, height() - delta));
}
- void shiftBottomEdgeTo(int edge)
+ void shiftMaxYEdgeTo(int edge)
{
- int delta = edge - bottom();
+ int delta = edge - maxY();
setHeight(std::max(0, height() + delta));
}
@@ -147,7 +139,7 @@ public:
// This checks to see if the rect contains x,y in the traditional sense.
// Equivalent to checking if the rect contains a 1x1 rect below and to the right of (px,py).
bool contains(int px, int py) const
- { return px >= x() && px < right() && py >= y() && py < bottom(); }
+ { return px >= x() && px < maxX() && py >= y() && py < maxY(); }
bool contains(const IntPoint& point) const { return contains(point.x(), point.y()); }
void intersect(const IntRect&);
diff --git a/Source/WebCore/platform/graphics/IntRectHash.h b/Source/WebCore/platform/graphics/IntRectHash.h
new file mode 100644
index 0000000..7138f33
--- /dev/null
+++ b/Source/WebCore/platform/graphics/IntRectHash.h
@@ -0,0 +1,59 @@
+/*
+ * 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 IntRectHash_h
+#define IntRectHash_h
+
+#include "IntPointHash.h"
+#include "IntRect.h"
+#include "IntSizeHash.h"
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+
+namespace WTF {
+
+template<> struct IntHash<WebCore::IntRect> {
+ static unsigned hash(const WebCore::IntRect& key)
+ {
+ return intHash(static_cast<uint64_t>(DefaultHash<WebCore::IntPoint>::Hash::hash(key.location())) << 32 | DefaultHash<WebCore::IntSize>::Hash::hash(key.size()));
+ }
+ static bool equal(const WebCore::IntRect& a, const WebCore::IntRect& b)
+ {
+ return DefaultHash<WebCore::IntPoint>::Hash::equal(a.location(), b.location()) && DefaultHash<WebCore::IntSize>::Hash::equal(a.size(), b.size());
+ }
+ static const bool safeToCompareToEmptyOrDeleted = true;
+};
+template<> struct DefaultHash<WebCore::IntRect> { typedef IntHash<WebCore::IntRect> Hash; };
+
+template<> struct HashTraits<WebCore::IntRect> : GenericHashTraits<WebCore::IntRect> {
+ static const bool emptyValueIsZero = true;
+ static const bool needsDestruction = false;
+ static void constructDeletedValue(WebCore::IntRect& slot) { new (&slot) WebCore::IntRect(-1, -1, -1, -1); }
+ static bool isDeletedValue(const WebCore::IntRect& value) { return value.x() == -1 && value.y() == -1 && value.width() == -1 && value.height() == -1; }
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/graphics/IntSizeHash.h b/Source/WebCore/platform/graphics/IntSizeHash.h
index ad6eac3..0cca000 100644
--- a/Source/WebCore/platform/graphics/IntSizeHash.h
+++ b/Source/WebCore/platform/graphics/IntSizeHash.h
@@ -24,22 +24,20 @@
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
-using WebCore::IntSize;
-
namespace WTF {
- template<> struct IntHash<IntSize> {
- static unsigned hash(const IntSize& key) { return intHash((static_cast<uint64_t>(key.width()) << 32 | key.height())); }
- static bool equal(const IntSize& a, const IntSize& b) { return a == b; }
+ template<> struct IntHash<WebCore::IntSize> {
+ static unsigned hash(const WebCore::IntSize& key) { return intHash((static_cast<uint64_t>(key.width()) << 32 | key.height())); }
+ static bool equal(const WebCore::IntSize& a, const WebCore::IntSize& b) { return a == b; }
static const bool safeToCompareToEmptyOrDeleted = true;
};
- template<> struct DefaultHash<IntSize> { typedef IntHash<IntSize> Hash; };
+ template<> struct DefaultHash<WebCore::IntSize> { typedef IntHash<WebCore::IntSize> Hash; };
- template<> struct HashTraits<IntSize> : GenericHashTraits<IntSize> {
+ template<> struct HashTraits<WebCore::IntSize> : GenericHashTraits<WebCore::IntSize> {
static const bool emptyValueIsZero = true;
static const bool needsDestruction = false;
- static void constructDeletedValue(IntSize& slot) { new (&slot) IntSize(-1, -1); }
- static bool isDeletedValue(const IntSize& value) { return value.width() == -1 && value.height() == -1; }
+ static void constructDeletedValue(WebCore::IntSize& slot) { new (&slot) WebCore::IntSize(-1, -1); }
+ static bool isDeletedValue(const WebCore::IntSize& value) { return value.width() == -1 && value.height() == -1; }
};
} // namespace WTF
diff --git a/Source/WebCore/platform/graphics/MediaPlayer.cpp b/Source/WebCore/platform/graphics/MediaPlayer.cpp
index 60f55a5..8eed0d2 100644
--- a/Source/WebCore/platform/graphics/MediaPlayer.cpp
+++ b/Source/WebCore/platform/graphics/MediaPlayer.cpp
@@ -698,6 +698,26 @@ double MediaPlayer::maximumDurationToCacheMediaTime() const
return m_private->maximumDurationToCacheMediaTime();
}
+unsigned long MediaPlayer::decodedFrames() const
+{
+ return m_private->decodedFrames();
+}
+
+unsigned long MediaPlayer::droppedFrames() const
+{
+ return m_private->droppedFrames();
+}
+
+unsigned long MediaPlayer::audioBytesDecoded() const
+{
+ return m_private->audioBytesDecoded();
+}
+
+unsigned long MediaPlayer::videoBytesDecoded() const
+{
+ return m_private->videoBytesDecoded();
+}
+
void MediaPlayer::reloadTimerFired(Timer<MediaPlayer>*)
{
m_private->cancelLoad();
diff --git a/Source/WebCore/platform/graphics/MediaPlayer.h b/Source/WebCore/platform/graphics/MediaPlayer.h
index ef0b3eb..1112148 100644
--- a/Source/WebCore/platform/graphics/MediaPlayer.h
+++ b/Source/WebCore/platform/graphics/MediaPlayer.h
@@ -287,6 +287,11 @@ public:
double maximumDurationToCacheMediaTime() const;
+ unsigned long decodedFrames() const;
+ unsigned long droppedFrames() const;
+ unsigned long audioBytesDecoded() const;
+ unsigned long videoBytesDecoded() const;
+
private:
MediaPlayer(MediaPlayerClient*);
void loadWithNextMediaEngine(MediaPlayerFactory*);
diff --git a/Source/WebCore/platform/graphics/MediaPlayerPrivate.h b/Source/WebCore/platform/graphics/MediaPlayerPrivate.h
index 6abe258..04b2612 100644
--- a/Source/WebCore/platform/graphics/MediaPlayerPrivate.h
+++ b/Source/WebCore/platform/graphics/MediaPlayerPrivate.h
@@ -136,6 +136,10 @@ public:
// it is OK to calculate movie time before refreshing the cached time.
virtual double maximumDurationToCacheMediaTime() const { return 0; }
+ virtual unsigned long decodedFrames() const { return 0; }
+ virtual unsigned long droppedFrames() const { return 0; }
+ virtual unsigned long audioBytesDecoded() const { return 0; }
+ virtual unsigned long videoBytesDecoded() const { return 0; }
};
}
diff --git a/Source/WebCore/platform/graphics/ShadowBlur.cpp b/Source/WebCore/platform/graphics/ShadowBlur.cpp
new file mode 100644
index 0000000..f61ecff
--- /dev/null
+++ b/Source/WebCore/platform/graphics/ShadowBlur.cpp
@@ -0,0 +1,733 @@
+/*
+ * Copyright (C) 2011 Apple Inc.
+ * Copyright (C) 2010 Sencha, Inc.
+ * Copyright (C) 2010 Igalia S.L.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ShadowBlur.h"
+
+#include "AffineTransform.h"
+#include "FloatQuad.h"
+#include "GraphicsContext.h"
+#include "ImageBuffer.h"
+#include "Timer.h"
+#include <wtf/MathExtras.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/UnusedParam.h>
+
+using namespace std;
+
+namespace WebCore {
+
+static inline int roundUpToMultipleOf32(int d)
+{
+ return (1 + (d >> 5)) << 5;
+}
+
+// ShadowBlur needs a scratch image as the buffer for the blur filter.
+// Instead of creating and destroying the buffer for every operation,
+// we create a buffer which will be automatically purged via a timer.
+class ScratchBuffer {
+public:
+ ScratchBuffer()
+ : m_purgeTimer(this, &ScratchBuffer::timerFired)
+#if !ASSERT_DISABLED
+ , m_bufferInUse(false)
+#endif
+ {
+ }
+
+ ImageBuffer* getScratchBuffer(const IntSize& size)
+ {
+ ASSERT(!m_bufferInUse);
+#if !ASSERT_DISABLED
+ m_bufferInUse = true;
+#endif
+ // We do not need to recreate the buffer if the current buffer is large enough.
+ if (m_imageBuffer && m_imageBuffer->width() >= size.width() && m_imageBuffer->height() >= size.height())
+ return m_imageBuffer.get();
+
+ // Round to the nearest 32 pixels so we do not grow the buffer for similar sized requests.
+ IntSize roundedSize(roundUpToMultipleOf32(size.width()), roundUpToMultipleOf32(size.height()));
+
+ m_imageBuffer = ImageBuffer::create(roundedSize);
+ return m_imageBuffer.get();
+ }
+
+ void scheduleScratchBufferPurge()
+ {
+#if !ASSERT_DISABLED
+ m_bufferInUse = false;
+#endif
+ if (m_purgeTimer.isActive())
+ m_purgeTimer.stop();
+
+ const double scratchBufferPurgeInterval = 2;
+ m_purgeTimer.startOneShot(scratchBufferPurgeInterval);
+ }
+
+ static ScratchBuffer& shared();
+
+private:
+ void timerFired(Timer<ScratchBuffer>*)
+ {
+ clearScratchBuffer();
+ }
+
+ void clearScratchBuffer()
+ {
+ m_imageBuffer = 0;
+ }
+
+ OwnPtr<ImageBuffer> m_imageBuffer;
+ Timer<ScratchBuffer> m_purgeTimer;
+#if !ASSERT_DISABLED
+ bool m_bufferInUse;
+#endif
+};
+
+ScratchBuffer& ScratchBuffer::shared()
+{
+ DEFINE_STATIC_LOCAL(ScratchBuffer, scratchBuffer, ());
+ return scratchBuffer;
+}
+
+static const int templateSideLength = 1;
+
+ShadowBlur::ShadowBlur(float radius, const FloatSize& offset, const Color& color, ColorSpace colorSpace)
+ : m_color(color)
+ , m_colorSpace(colorSpace)
+ , m_blurRadius(radius)
+ , m_offset(offset)
+ , m_layerImage(0)
+ , m_shadowsIgnoreTransforms(false)
+{
+ // Limit blur radius to 128 to avoid lots of very expensive blurring.
+ m_blurRadius = min<float>(m_blurRadius, 128);
+
+ // The type of shadow is decided by the blur radius, shadow offset, and shadow color.
+ if (!m_color.isValid() || !color.alpha()) {
+ // Can't paint the shadow with invalid or invisible color.
+ m_type = NoShadow;
+ } else if (m_blurRadius > 0) {
+ // Shadow is always blurred, even the offset is zero.
+ m_type = BlurShadow;
+ } else if (!m_offset.width() && !m_offset.height()) {
+ // Without blur and zero offset means the shadow is fully hidden.
+ m_type = NoShadow;
+ } else
+ m_type = SolidShadow;
+}
+
+// Instead of integer division, we use 17.15 for fixed-point division.
+static const int blurSumShift = 15;
+static const float gaussianKernelFactor = 3 / 4.f * sqrtf(2 * piFloat);
+
+void ShadowBlur::blurLayerImage(unsigned char* imageData, const IntSize& size, int rowStride)
+{
+ const int channels[4] =
+#if CPU(BIG_ENDIAN)
+ { 0, 3, 2, 0 };
+#elif CPU(MIDDLE_ENDIAN)
+ { 1, 2, 3, 1 };
+#else
+ { 3, 0, 1, 3 };
+#endif
+
+ int diameter;
+ if (m_shadowsIgnoreTransforms)
+ diameter = max(2, static_cast<int>(floorf((2 / 3.f) * m_blurRadius))); // Canvas shadow. FIXME: we should adjust the blur radius higher up.
+ else {
+ // http://dev.w3.org/csswg/css3-background/#box-shadow
+ // Approximate a Gaussian blur with a standard deviation equal to half the blur radius,
+ // which http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement tell us how to do.
+ // However, shadows rendered according to that spec will extend a little further than m_blurRadius,
+ // so we apply a fudge factor to bring the radius down slightly.
+ float stdDev = m_blurRadius / 2;
+ const float fudgeFactor = 0.88f;
+ diameter = max(2, static_cast<int>(floorf(stdDev * gaussianKernelFactor * fudgeFactor + 0.5f)));
+ }
+
+ enum {
+ leftLobe = 0,
+ rightLobe = 1
+ };
+
+ int lobes[3][2]; // indexed by pass, and left/right lobe
+
+ if (diameter & 1) {
+ // if d is odd, use three box-blurs of size 'd', centered on the output pixel.
+ int lobeSize = (diameter - 1) / 2;
+ lobes[0][leftLobe] = lobeSize;
+ lobes[0][rightLobe] = lobeSize;
+ lobes[1][leftLobe] = lobeSize;
+ lobes[1][rightLobe] = lobeSize;
+ lobes[2][leftLobe] = lobeSize;
+ lobes[2][rightLobe] = lobeSize;
+ } else {
+ // if d is even, two box-blurs of size 'd' (the first one centered on the pixel boundary
+ // between the output pixel and the one to the left, the second one centered on the pixel
+ // boundary between the output pixel and the one to the right) and one box blur of size 'd+1' centered on the output pixel
+ int lobeSize = diameter / 2;
+ lobes[0][leftLobe] = lobeSize;
+ lobes[0][rightLobe] = lobeSize - 1;
+ lobes[1][leftLobe] = lobeSize - 1;
+ lobes[1][rightLobe] = lobeSize;
+ lobes[2][leftLobe] = lobeSize;
+ lobes[2][rightLobe] = lobeSize;
+ }
+
+ // First pass is horizontal.
+ int stride = 4;
+ int delta = rowStride;
+ int final = size.height();
+ int dim = size.width();
+
+ // Two stages: horizontal and vertical
+ for (int pass = 0; pass < 2; ++pass) {
+ unsigned char* pixels = imageData;
+
+ for (int j = 0; j < final; ++j, pixels += delta) {
+ // For each step, we blur the alpha in a channel and store the result
+ // in another channel for the subsequent step.
+ // We use sliding window algorithm to accumulate the alpha values.
+ // This is much more efficient than computing the sum of each pixels
+ // covered by the box kernel size for each x.
+ for (int step = 0; step < 3; ++step) {
+ int side1 = lobes[step][leftLobe];
+ int side2 = lobes[step][rightLobe];
+ int pixelCount = side1 + 1 + side2;
+ int invCount = ((1 << blurSumShift) + pixelCount - 1) / pixelCount;
+ int ofs = 1 + side2;
+ int alpha1 = pixels[channels[step]];
+ int alpha2 = pixels[(dim - 1) * stride + channels[step]];
+
+ unsigned char* ptr = pixels + channels[step + 1];
+ unsigned char* prev = pixels + stride + channels[step];
+ unsigned char* next = pixels + ofs * stride + channels[step];
+
+ int i;
+ int sum = side1 * alpha1 + alpha1;
+ int limit = (dim < side2 + 1) ? dim : side2 + 1;
+
+ for (i = 1; i < limit; ++i, prev += stride)
+ sum += *prev;
+
+ if (limit <= side2)
+ sum += (side2 - limit + 1) * alpha2;
+
+ limit = (side1 < dim) ? side1 : dim;
+ for (i = 0; i < limit; ptr += stride, next += stride, ++i, ++ofs) {
+ *ptr = (sum * invCount) >> blurSumShift;
+ sum += ((ofs < dim) ? *next : alpha2) - alpha1;
+ }
+
+ prev = pixels + channels[step];
+ for (; ofs < dim; ptr += stride, prev += stride, next += stride, ++i, ++ofs) {
+ *ptr = (sum * invCount) >> blurSumShift;
+ sum += (*next) - (*prev);
+ }
+
+ for (; i < dim; ptr += stride, prev += stride, ++i) {
+ *ptr = (sum * invCount) >> blurSumShift;
+ sum += alpha2 - (*prev);
+ }
+ }
+ }
+
+ // Last pass is vertical.
+ stride = rowStride;
+ delta = 4;
+ final = size.width();
+ dim = size.height();
+ }
+}
+
+void ShadowBlur::adjustBlurRadius(GraphicsContext* context)
+{
+ if (!m_shadowsIgnoreTransforms)
+ return;
+
+ const AffineTransform transform = context->getCTM();
+
+ // Adjust blur if we're scaling, since the radius must not be affected by transformations.
+ // FIXME: use AffineTransform::isIdentityOrTranslationOrFlipped()?
+ if (transform.isIdentity())
+ return;
+
+ // Calculate transformed unit vectors.
+ const FloatQuad unitQuad(FloatPoint(0, 0), FloatPoint(1, 0),
+ FloatPoint(0, 1), FloatPoint(1, 1));
+ const FloatQuad transformedUnitQuad = transform.mapQuad(unitQuad);
+
+ // Calculate X axis scale factor.
+ const FloatSize xUnitChange = transformedUnitQuad.p2() - transformedUnitQuad.p1();
+ const float xAxisScale = sqrtf(xUnitChange.width() * xUnitChange.width()
+ + xUnitChange.height() * xUnitChange.height());
+
+ // Calculate Y axis scale factor.
+ const FloatSize yUnitChange = transformedUnitQuad.p3() - transformedUnitQuad.p1();
+ const float yAxisScale = sqrtf(yUnitChange.width() * yUnitChange.width()
+ + yUnitChange.height() * yUnitChange.height());
+
+ // blurLayerImage() does not support per-axis blurring, so calculate a balanced scaling.
+ // FIXME: does AffineTransform.xScale()/yScale() help?
+ const float scale = sqrtf(xAxisScale * yAxisScale);
+ m_blurRadius = roundf(m_blurRadius / scale);
+}
+
+IntRect ShadowBlur::calculateLayerBoundingRect(GraphicsContext* context, const FloatRect& shadowedRect, const IntRect& clipRect)
+{
+ const float roundedRadius = ceilf(m_blurRadius);
+
+ // Calculate the destination of the blurred and/or transformed layer.
+ FloatRect layerRect;
+ float inflation = 0;
+
+ const AffineTransform transform = context->getCTM();
+ if (m_shadowsIgnoreTransforms && !transform.isIdentity()) {
+ FloatQuad transformedPolygon = transform.mapQuad(FloatQuad(shadowedRect));
+ transformedPolygon.move(m_offset);
+ layerRect = transform.inverse().mapQuad(transformedPolygon).boundingBox();
+ } else {
+ layerRect = shadowedRect;
+ layerRect.move(m_offset);
+ }
+
+ // We expand the area by the blur radius to give extra space for the blur transition.
+ if (m_type == BlurShadow) {
+ layerRect.inflate(roundedRadius);
+ inflation = roundedRadius;
+ }
+
+ FloatRect unclippedLayerRect = layerRect;
+
+ if (!clipRect.contains(enclosingIntRect(layerRect))) {
+ // If we are totally outside the clip region, we aren't painting at all.
+ if (intersection(layerRect, clipRect).isEmpty())
+ return IntRect();
+
+ IntRect inflatedClip = clipRect;
+ // Pixels at the edges can be affected by pixels outside the buffer,
+ // so intersect with the clip inflated by the blur.
+ if (m_type == BlurShadow)
+ inflatedClip.inflate(roundedRadius);
+
+ layerRect.intersect(inflatedClip);
+ }
+
+ const float frameSize = inflation * 2;
+ m_sourceRect = FloatRect(0, 0, shadowedRect.width() + frameSize, shadowedRect.height() + frameSize);
+ m_layerOrigin = FloatPoint(layerRect.x(), layerRect.y());
+ m_layerSize = layerRect.size();
+
+ const FloatPoint unclippedLayerOrigin = FloatPoint(unclippedLayerRect.x(), unclippedLayerRect.y());
+ const FloatSize clippedOut = unclippedLayerOrigin - m_layerOrigin;
+
+ // Set the origin as the top left corner of the scratch image, or, in case there's a clipped
+ // out region, set the origin accordingly to the full bounding rect's top-left corner.
+ float translationX = -shadowedRect.x() + inflation - fabsf(clippedOut.width());
+ float translationY = -shadowedRect.y() + inflation - fabsf(clippedOut.height());
+ m_layerContextTranslation = FloatSize(translationX, translationY);
+
+ return enclosingIntRect(layerRect);
+}
+
+GraphicsContext* ShadowBlur::beginShadowLayer(GraphicsContext* graphicsContext, const IntRect& layerRect)
+{
+ adjustBlurRadius(graphicsContext);
+
+ // Don't paint if we are totally outside the clip region.
+ if (layerRect.isEmpty())
+ return 0;
+
+ m_layerImage = ScratchBuffer::shared().getScratchBuffer(layerRect.size());
+ GraphicsContext* layerContext = m_layerImage->context();
+
+ layerContext->save(); // Balanced by restore() in endShadowLayer().
+
+ // Always clear the surface first. FIXME: we could avoid the clear on first allocation.
+ // Add a pixel to avoid later edge aliasing when rotated.
+ layerContext->clearRect(FloatRect(0, 0, m_layerSize.width() + 1, m_layerSize.height() + 1));
+ layerContext->translate(m_layerContextTranslation);
+
+ return layerContext;
+}
+
+void ShadowBlur::endShadowLayer(GraphicsContext* graphicsContext)
+{
+ if (!m_layerImage)
+ return;
+
+ m_layerImage->context()->restore();
+
+ if (m_type == BlurShadow) {
+ IntRect blurRect = enclosingIntRect(FloatRect(FloatPoint(), m_layerSize));
+ RefPtr<ByteArray> layerData = m_layerImage->getUnmultipliedImageData(blurRect);
+ blurLayerImage(layerData->data(), blurRect.size(), blurRect.width() * 4);
+ m_layerImage->putUnmultipliedImageData(layerData.get(), blurRect.size(), blurRect, IntPoint());
+ }
+
+ graphicsContext->save();
+
+ IntSize bufferSize = m_layerImage->size();
+ if (bufferSize != m_layerSize) {
+ // The rect passed to clipToImageBuffer() has to be the size of the entire buffer,
+ // but we may not have cleared it all, so clip to the filled part first.
+ graphicsContext->clip(FloatRect(m_layerOrigin, m_layerSize));
+ }
+ graphicsContext->clipToImageBuffer(m_layerImage, FloatRect(m_layerOrigin, bufferSize));
+ graphicsContext->setFillColor(m_color, m_colorSpace);
+
+ graphicsContext->clearShadow();
+ graphicsContext->fillRect(FloatRect(m_layerOrigin, m_sourceRect.size()));
+
+ graphicsContext->restore();
+
+ m_layerImage = 0;
+
+ // Schedule a purge of the scratch buffer. We do not need to destroy the surface.
+ ScratchBuffer::shared().scheduleScratchBufferPurge();
+}
+
+static void computeSliceSizesFromRadii(int twiceRadius, const RoundedIntRect::Radii& radii, int& leftSlice, int& rightSlice, int& topSlice, int& bottomSlice)
+{
+ leftSlice = twiceRadius + max(radii.topLeft().width(), radii.bottomLeft().width());
+ rightSlice = twiceRadius + max(radii.topRight().width(), radii.bottomRight().width());
+
+ topSlice = twiceRadius + max(radii.topLeft().height(), radii.topRight().height());
+ bottomSlice = twiceRadius + max(radii.bottomLeft().height(), radii.bottomRight().height());
+}
+
+IntSize ShadowBlur::templateSize(const RoundedIntRect::Radii& radii) const
+{
+ const int templateSideLength = 1;
+
+ int leftSlice;
+ int rightSlice;
+ int topSlice;
+ int bottomSlice;
+ computeSliceSizesFromRadii(2 * ceilf(m_blurRadius), radii, leftSlice, rightSlice, topSlice, bottomSlice);
+
+ return IntSize(templateSideLength + leftSlice + rightSlice,
+ templateSideLength + topSlice + bottomSlice);
+}
+
+void ShadowBlur::drawRectShadow(GraphicsContext* graphicsContext, const FloatRect& shadowedRect, const RoundedIntRect::Radii& radii)
+{
+ IntRect layerRect = calculateLayerBoundingRect(graphicsContext, shadowedRect, graphicsContext->clipBounds());
+ if (layerRect.isEmpty())
+ return;
+
+ // drawRectShadowWithTiling does not work with rotations.
+ // https://bugs.webkit.org/show_bug.cgi?id=45042
+ if (!graphicsContext->getCTM().isIdentityOrTranslationOrFlipped() || m_type != BlurShadow) {
+ drawRectShadowWithoutTiling(graphicsContext, shadowedRect, radii, layerRect);
+ return;
+ }
+
+ IntSize templateSize = this->templateSize(radii);
+
+ if (templateSize.width() > shadowedRect.width() || templateSize.height() > shadowedRect.height()
+ || (templateSize.width() * templateSize.height() > m_sourceRect.width() * m_sourceRect.height())) {
+ drawRectShadowWithoutTiling(graphicsContext, shadowedRect, radii, layerRect);
+ return;
+ }
+
+ drawRectShadowWithTiling(graphicsContext, shadowedRect, radii, templateSize);
+}
+
+void ShadowBlur::drawInsetShadow(GraphicsContext* graphicsContext, const FloatRect& rect, const FloatRect& holeRect, const RoundedIntRect::Radii& holeRadii)
+{
+ IntRect layerRect = calculateLayerBoundingRect(graphicsContext, rect, graphicsContext->clipBounds());
+ if (layerRect.isEmpty())
+ return;
+
+ // drawInsetShadowWithTiling does not work with rotations.
+ // https://bugs.webkit.org/show_bug.cgi?id=45042
+ if (!graphicsContext->getCTM().isIdentityOrTranslationOrFlipped() || m_type != BlurShadow) {
+ drawInsetShadowWithoutTiling(graphicsContext, rect, holeRect, holeRadii, layerRect);
+ return;
+ }
+
+ IntSize templateSize = this->templateSize(holeRadii);
+
+ if (templateSize.width() > holeRect.width() || templateSize.height() > holeRect.height()
+ || (templateSize.width() * templateSize.height() > holeRect.width() * holeRect.height())) {
+ drawInsetShadowWithoutTiling(graphicsContext, rect, holeRect, holeRadii, layerRect);
+ return;
+ }
+
+ drawInsetShadowWithTiling(graphicsContext, rect, holeRect, holeRadii, templateSize);
+}
+
+void ShadowBlur::drawRectShadowWithoutTiling(GraphicsContext* graphicsContext, const FloatRect& shadowedRect, const RoundedIntRect::Radii& radii, const IntRect& layerRect)
+{
+ GraphicsContext* shadowContext = beginShadowLayer(graphicsContext, layerRect);
+ if (!shadowContext)
+ return;
+
+ Path path;
+ path.addRoundedRect(shadowedRect, radii.topLeft(), radii.topRight(), radii.bottomLeft(), radii.bottomRight());
+
+ shadowContext->setFillColor(Color::black, ColorSpaceDeviceRGB);
+ shadowContext->fillPath(path);
+
+ endShadowLayer(graphicsContext);
+}
+
+void ShadowBlur::drawInsetShadowWithoutTiling(GraphicsContext* graphicsContext, const FloatRect& rect, const FloatRect& holeRect, const RoundedIntRect::Radii& holeRadii, const IntRect& layerRect)
+{
+ GraphicsContext* shadowContext = beginShadowLayer(graphicsContext, layerRect);
+ if (!shadowContext)
+ return;
+
+ Path path;
+ path.addRect(rect);
+ path.addRoundedRect(holeRect, holeRadii.topLeft(), holeRadii.topRight(), holeRadii.bottomLeft(), holeRadii.bottomRight());
+
+ shadowContext->setFillRule(RULE_EVENODD);
+ shadowContext->setFillColor(Color::black, ColorSpaceDeviceRGB);
+ shadowContext->fillPath(path);
+
+ endShadowLayer(graphicsContext);
+}
+
+/*
+ These functions use tiling to improve the performance of the shadow
+ drawing of rounded rectangles. The code basically does the following
+ steps:
+
+ 1. Calculate the size of the shadow template, a rectangle that
+ contains all the necessary tiles to draw the complete shadow.
+
+ 2. If that size is smaller than the real rectangle render the new
+ template rectangle and its shadow in a new surface, in other case
+ render the shadow of the real rectangle in the destination
+ surface.
+
+ 3. Calculate the sizes and positions of the tiles and their
+ destinations and use drawPattern to render the final shadow. The
+ code divides the rendering in 8 tiles:
+
+ 1 | 2 | 3
+ -----------
+ 4 | | 5
+ -----------
+ 6 | 7 | 8
+
+ The corners are directly copied from the template rectangle to the
+ real one and the side tiles are 1 pixel width, we use them as
+ tiles to cover the destination side. The corner tiles are bigger
+ than just the side of the rounded corner, we need to increase it
+ because the modifications caused by the corner over the blur
+ effect. We fill the central or outer part with solid color to complete
+ the shadow.
+ */
+
+void ShadowBlur::drawInsetShadowWithTiling(GraphicsContext* graphicsContext, const FloatRect& rect, const FloatRect& holeRect, const RoundedIntRect::Radii& radii, const IntSize& templateSize)
+{
+ graphicsContext->save();
+ graphicsContext->clearShadow();
+
+ const float roundedRadius = ceilf(m_blurRadius);
+ const float twiceRadius = roundedRadius * 2;
+
+ m_layerImage = ScratchBuffer::shared().getScratchBuffer(templateSize);
+
+ // Draw the rectangle with hole.
+ FloatRect templateBounds(0, 0, templateSize.width(), templateSize.height());
+ FloatRect templateHole = FloatRect(roundedRadius, roundedRadius, templateSize.width() - twiceRadius, templateSize.height() - twiceRadius);
+ Path path;
+ path.addRect(templateBounds);
+ path.addRoundedRect(templateHole, radii.topLeft(), radii.topRight(), radii.bottomLeft(), radii.bottomRight());
+
+ // Draw shadow into a new ImageBuffer.
+ GraphicsContext* shadowContext = m_layerImage->context();
+ shadowContext->save();
+ shadowContext->clearRect(templateBounds);
+ shadowContext->setFillRule(RULE_EVENODD);
+ shadowContext->setFillColor(Color::black, ColorSpaceDeviceRGB);
+ shadowContext->fillPath(path);
+ blurAndColorShadowBuffer(templateSize);
+ shadowContext->restore();
+
+ FloatRect boundingRect = rect;
+ boundingRect.move(m_offset);
+
+ FloatRect destHoleRect = holeRect;
+ destHoleRect.move(m_offset);
+ FloatRect destHoleBounds = destHoleRect;
+ destHoleBounds.inflate(roundedRadius);
+
+ // Fill the external part of the shadow (which may be visible because of offset).
+ Path exteriorPath;
+ exteriorPath.addRect(boundingRect);
+ exteriorPath.addRect(destHoleBounds);
+
+ graphicsContext->save();
+ graphicsContext->setFillRule(RULE_EVENODD);
+ graphicsContext->setFillColor(m_color, m_colorSpace);
+ graphicsContext->fillPath(exteriorPath);
+ graphicsContext->restore();
+
+ drawLayerPieces(graphicsContext, destHoleBounds, radii, roundedRadius, templateSize, InnerShadow);
+
+ graphicsContext->restore();
+
+ m_layerImage = 0;
+ // Schedule a purge of the scratch buffer.
+ ScratchBuffer::shared().scheduleScratchBufferPurge();
+}
+
+void ShadowBlur::drawRectShadowWithTiling(GraphicsContext* graphicsContext, const FloatRect& shadowedRect, const RoundedIntRect::Radii& radii, const IntSize& templateSize)
+{
+ graphicsContext->save();
+ graphicsContext->clearShadow();
+
+ const float roundedRadius = ceilf(m_blurRadius);
+ const float twiceRadius = roundedRadius * 2;
+
+ m_layerImage = ScratchBuffer::shared().getScratchBuffer(templateSize);
+
+ // Draw the rectangle.
+ FloatRect templateShadow = FloatRect(roundedRadius, roundedRadius, templateSize.width() - twiceRadius, templateSize.height() - twiceRadius);
+ Path path;
+ path.addRoundedRect(templateShadow, radii.topLeft(), radii.topRight(), radii.bottomLeft(), radii.bottomRight());
+
+ // Draw shadow into the ImageBuffer.
+ GraphicsContext* shadowContext = m_layerImage->context();
+ shadowContext->save();
+ shadowContext->clearRect(FloatRect(0, 0, templateSize.width(), templateSize.height()));
+ shadowContext->setFillColor(Color::black, ColorSpaceDeviceRGB);
+ shadowContext->fillPath(path);
+ blurAndColorShadowBuffer(templateSize);
+ shadowContext->restore();
+
+ FloatRect shadowBounds = shadowedRect;
+ shadowBounds.move(m_offset.width(), m_offset.height());
+ shadowBounds.inflate(roundedRadius);
+
+ drawLayerPieces(graphicsContext, shadowBounds, radii, roundedRadius, templateSize, OuterShadow);
+
+ graphicsContext->restore();
+
+ m_layerImage = 0;
+ // Schedule a purge of the scratch buffer.
+ ScratchBuffer::shared().scheduleScratchBufferPurge();
+}
+
+void ShadowBlur::drawLayerPieces(GraphicsContext* graphicsContext, const FloatRect& shadowBounds, const RoundedIntRect::Radii& radii, float roundedRadius, const IntSize& templateSize, ShadowDirection direction)
+{
+ const float twiceRadius = roundedRadius * 2;
+
+ int leftSlice;
+ int rightSlice;
+ int topSlice;
+ int bottomSlice;
+ computeSliceSizesFromRadii(twiceRadius, radii, leftSlice, rightSlice, topSlice, bottomSlice);
+
+ int centerWidth = shadowBounds.width() - leftSlice - rightSlice;
+ int centerHeight = shadowBounds.height() - topSlice - bottomSlice;
+
+ if (direction == OuterShadow) {
+ FloatRect shadowInterior(shadowBounds.x() + leftSlice, shadowBounds.y() + topSlice, centerWidth, centerHeight);
+ if (!shadowInterior.isEmpty()) {
+ graphicsContext->save();
+
+ graphicsContext->setFillColor(m_color, m_colorSpace);
+ graphicsContext->fillRect(shadowInterior);
+
+ graphicsContext->restore();
+ }
+ }
+
+ // Note that drawing the ImageBuffer is faster than creating a Image and drawing that,
+ // because ImageBuffer::draw() knows that it doesn't have to copy the image bits.
+
+ // Top side.
+ FloatRect tileRect = FloatRect(leftSlice, 0, templateSideLength, topSlice);
+ FloatRect destRect = FloatRect(shadowBounds.x() + leftSlice, shadowBounds.y(), centerWidth, topSlice);
+ graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect);
+
+ // Draw the bottom side.
+ tileRect.setY(templateSize.height() - bottomSlice);
+ tileRect.setHeight(bottomSlice);
+ destRect.setY(shadowBounds.maxY() - bottomSlice);
+ destRect.setHeight(bottomSlice);
+ graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect);
+
+ // Left side.
+ tileRect = FloatRect(0, topSlice, leftSlice, templateSideLength);
+ destRect = FloatRect(shadowBounds.x(), shadowBounds.y() + topSlice, leftSlice, centerHeight);
+ graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect);
+
+ // Right side.
+ tileRect.setX(templateSize.width() - rightSlice);
+ tileRect.setWidth(rightSlice);
+ destRect.setX(shadowBounds.maxX() - rightSlice);
+ destRect.setWidth(rightSlice);
+ graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect);
+
+ // Top left corner.
+ tileRect = FloatRect(0, 0, leftSlice, topSlice);
+ destRect = FloatRect(shadowBounds.x(), shadowBounds.y(), leftSlice, topSlice);
+ graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect);
+
+ // Top right corner.
+ tileRect = FloatRect(templateSize.width() - rightSlice, 0, rightSlice, topSlice);
+ destRect = FloatRect(shadowBounds.maxX() - rightSlice, shadowBounds.y(), rightSlice, topSlice);
+ graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect);
+
+ // Bottom right corner.
+ tileRect = FloatRect(templateSize.width() - rightSlice, templateSize.height() - bottomSlice, rightSlice, bottomSlice);
+ destRect = FloatRect(shadowBounds.maxX() - rightSlice, shadowBounds.maxY() - bottomSlice, rightSlice, bottomSlice);
+ graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect);
+
+ // Bottom left corner.
+ tileRect = FloatRect(0, templateSize.height() - bottomSlice, leftSlice, bottomSlice);
+ destRect = FloatRect(shadowBounds.x(), shadowBounds.maxY() - bottomSlice, leftSlice, bottomSlice);
+ graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect);
+}
+
+
+void ShadowBlur::blurAndColorShadowBuffer(const IntSize& templateSize)
+{
+ {
+ IntRect blurRect(IntPoint(), templateSize);
+ RefPtr<ByteArray> layerData = m_layerImage->getUnmultipliedImageData(blurRect);
+ blurLayerImage(layerData->data(), blurRect.size(), blurRect.width() * 4);
+ m_layerImage->putUnmultipliedImageData(layerData.get(), blurRect.size(), blurRect, IntPoint());
+ }
+
+ // Mask the image with the shadow color.
+ GraphicsContext* shadowContext = m_layerImage->context();
+ shadowContext->setCompositeOperation(CompositeSourceIn);
+ shadowContext->setFillColor(m_color, m_colorSpace);
+ shadowContext->fillRect(FloatRect(0, 0, templateSize.width(), templateSize.height()));
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/ShadowBlur.h b/Source/WebCore/platform/graphics/ShadowBlur.h
new file mode 100644
index 0000000..e52d6dc
--- /dev/null
+++ b/Source/WebCore/platform/graphics/ShadowBlur.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2011 Apple Inc.
+ * Copyright (C) 2010 Sencha, Inc.
+ * Copyright (C) 2010 Igalia S.L.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 ShadowBlur_h
+#define ShadowBlur_h
+
+#include "Color.h"
+#include "ColorSpace.h"
+#include "FloatRect.h"
+#include "RoundedIntRect.h"
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class AffineTransform;
+class GraphicsContext;
+class ImageBuffer;
+
+class ShadowBlur {
+ WTF_MAKE_NONCOPYABLE(ShadowBlur);
+public:
+ ShadowBlur(float radius, const FloatSize& offset, const Color&, ColorSpace);
+
+ void setShadowsIgnoreTransforms(bool ignoreTransforms) { m_shadowsIgnoreTransforms = ignoreTransforms; }
+ bool shadowsIgnoreTransforms() const { return m_shadowsIgnoreTransforms; }
+
+ void drawRectShadow(GraphicsContext*, const FloatRect&, const RoundedIntRect::Radii&);
+ void drawInsetShadow(GraphicsContext*, const FloatRect&, const FloatRect& holeRect, const RoundedIntRect::Radii& holeRadii);
+
+private:
+ GraphicsContext* beginShadowLayer(GraphicsContext*, const IntRect& layerRect);
+ void endShadowLayer(GraphicsContext*);
+
+ void adjustBlurRadius(GraphicsContext*);
+ void blurLayerImage(unsigned char*, const IntSize&, int stride);
+
+ enum ShadowDirection {
+ OuterShadow,
+ InnerShadow
+ };
+
+ IntRect calculateLayerBoundingRect(GraphicsContext*, const FloatRect& layerArea, const IntRect& clipRect);
+ IntSize templateSize(const RoundedIntRect::Radii&) const;
+
+ void drawRectShadowWithoutTiling(GraphicsContext*, const FloatRect&, const RoundedIntRect::Radii&, const IntRect& layerRect);
+ void drawRectShadowWithTiling(GraphicsContext*, const FloatRect&, const RoundedIntRect::Radii&, const IntSize& shadowTemplateSize);
+
+ void drawInsetShadowWithoutTiling(GraphicsContext*, const FloatRect&, const FloatRect& holeRect, const RoundedIntRect::Radii&, const IntRect& layerRect);
+ void drawInsetShadowWithTiling(GraphicsContext*, const FloatRect&, const FloatRect& holeRect, const RoundedIntRect::Radii&, const IntSize& shadowTemplateSize);
+
+ void drawLayerPieces(GraphicsContext*, const FloatRect& shadowBounds, const RoundedIntRect::Radii&, float roundedRadius, const IntSize& templateSize, ShadowDirection);
+
+ void blurAndColorShadowBuffer(const IntSize& templateSize);
+
+ enum ShadowType {
+ NoShadow,
+ SolidShadow,
+ BlurShadow
+ };
+
+ ShadowType m_type;
+
+ Color m_color;
+ ColorSpace m_colorSpace;
+ float m_blurRadius;
+ FloatSize m_offset;
+
+ ImageBuffer* m_layerImage; // Buffer to where the temporary shadow will be drawn to.
+
+ FloatRect m_sourceRect; // Sub-rect of m_layerImage that contains the shadow pixels.
+ FloatPoint m_layerOrigin; // Top-left corner of the (possibly clipped) bounding rect to draw the shadow to.
+ FloatSize m_layerSize; // Size of m_layerImage pixels that need blurring.
+ FloatSize m_layerContextTranslation; // Translation to apply to m_layerContext for the shadow to be correctly clipped.
+
+ bool m_shadowsIgnoreTransforms;
+};
+
+} // namespace WebCore
+
+#endif // ShadowBlur_h
diff --git a/Source/WebCore/platform/graphics/SimpleFontData.cpp b/Source/WebCore/platform/graphics/SimpleFontData.cpp
index e773880..2693609 100644
--- a/Source/WebCore/platform/graphics/SimpleFontData.cpp
+++ b/Source/WebCore/platform/graphics/SimpleFontData.cpp
@@ -50,7 +50,6 @@ namespace WebCore {
SimpleFontData::SimpleFontData(const FontPlatformData& platformData, bool isCustomFont, bool isLoading)
: m_maxCharWidth(-1)
, m_avgCharWidth(-1)
- , m_unitsPerEm(defaultUnitsPerEm)
, m_orientation(platformData.orientation())
, m_platformData(platformData)
, m_treatAsFixedPitch(false)
@@ -74,31 +73,36 @@ SimpleFontData::SimpleFontData(PassOwnPtr<SVGFontData> svgFontData, int size, bo
, m_isBrokenIdeographFont(false)
{
SVGFontFaceElement* svgFontFaceElement = m_svgFontData->svgFontFaceElement();
- m_unitsPerEm = svgFontFaceElement->unitsPerEm();
-
- double scale = size;
- if (m_unitsPerEm)
- scale /= m_unitsPerEm;
-
- m_ascent = static_cast<int>(svgFontFaceElement->ascent() * scale);
- m_descent = static_cast<int>(svgFontFaceElement->descent() * scale);
- m_xHeight = static_cast<int>(svgFontFaceElement->xHeight() * scale);
- m_lineGap = 0.1f * size;
- m_lineSpacing = m_ascent + m_descent + m_lineGap;
+ unsigned unitsPerEm = svgFontFaceElement->unitsPerEm();
+
+ float scale = size;
+ if (unitsPerEm)
+ scale /= unitsPerEm;
+
+ float xHeight = svgFontFaceElement->xHeight() * scale;
+ float ascent = svgFontFaceElement->ascent() * scale;
+ float descent = svgFontFaceElement->descent() * scale;
+ float lineGap = 0.1f * size;
+ m_fontMetrics.setUnitsPerEm(unitsPerEm);
+ m_fontMetrics.setAscent(ascent);
+ m_fontMetrics.setDescent(descent);
+ m_fontMetrics.setLineGap(lineGap);
+ m_fontMetrics.setLineSpacing(roundf(ascent) + roundf(descent) + roundf(lineGap));
+ m_fontMetrics.setXHeight(xHeight);
SVGFontElement* associatedFontElement = svgFontFaceElement->associatedFontElement();
Vector<SVGGlyphIdentifier> spaceGlyphs;
associatedFontElement->getGlyphIdentifiersForString(String(" ", 1), spaceGlyphs);
- m_spaceWidth = spaceGlyphs.isEmpty() ? m_xHeight : static_cast<float>(spaceGlyphs.first().horizontalAdvanceX * scale);
+ m_spaceWidth = spaceGlyphs.isEmpty() ? xHeight : spaceGlyphs.first().horizontalAdvanceX * scale;
Vector<SVGGlyphIdentifier> numeralZeroGlyphs;
associatedFontElement->getGlyphIdentifiersForString(String("0", 1), numeralZeroGlyphs);
- m_avgCharWidth = numeralZeroGlyphs.isEmpty() ? m_spaceWidth : static_cast<float>(numeralZeroGlyphs.first().horizontalAdvanceX * scale);
+ m_avgCharWidth = numeralZeroGlyphs.isEmpty() ? m_spaceWidth : numeralZeroGlyphs.first().horizontalAdvanceX * scale;
Vector<SVGGlyphIdentifier> letterWGlyphs;
associatedFontElement->getGlyphIdentifiersForString(String("W", 1), letterWGlyphs);
- m_maxCharWidth = letterWGlyphs.isEmpty() ? m_ascent : static_cast<float>(letterWGlyphs.first().horizontalAdvanceX * scale);
+ m_maxCharWidth = letterWGlyphs.isEmpty() ? ascent : letterWGlyphs.first().horizontalAdvanceX * scale;
// FIXME: is there a way we can get the space glyph from the SVGGlyphIdentifier above?
m_spaceGlyph = 0;
@@ -126,10 +130,10 @@ void SimpleFontData::initCharWidths()
// If we can't retrieve the width of a '0', fall back to the x height.
if (m_avgCharWidth <= 0.f)
- m_avgCharWidth = m_xHeight;
+ m_avgCharWidth = m_fontMetrics.xHeight();
if (m_maxCharWidth <= 0.f)
- m_maxCharWidth = max<float>(m_avgCharWidth, m_ascent);
+ m_maxCharWidth = max(m_avgCharWidth, m_fontMetrics.floatAscent());
}
void SimpleFontData::platformGlyphInit()
diff --git a/Source/WebCore/platform/graphics/SimpleFontData.h b/Source/WebCore/platform/graphics/SimpleFontData.h
index 90713af..07c2bd1 100644
--- a/Source/WebCore/platform/graphics/SimpleFontData.h
+++ b/Source/WebCore/platform/graphics/SimpleFontData.h
@@ -26,6 +26,7 @@
#include "FontBaseline.h"
#include "FontData.h"
+#include "FontMetrics.h"
#include "FontPlatformData.h"
#include "FloatRect.h"
#include "GlyphMetricsMap.h"
@@ -101,15 +102,9 @@ public:
// FIXME: Use the actual metrics for fonts with vertical tables instead of just hard-coding. If the font is horizontally oriented or
// a broken ideographic font, then just hard-code to split ascent/descent down the middle. Otherwise we should actually use the metrics
// from the font itself.
- int ascent(FontBaseline baselineType = AlphabeticBaseline) const { return baselineType == AlphabeticBaseline ? m_ascent : height() - height() / 2; }
- int descent(FontBaseline baselineType = AlphabeticBaseline) const { return baselineType == AlphabeticBaseline ? m_descent : height() / 2; }
- int height() const { return m_ascent + m_descent; }
- int lineSpacing() const { return m_lineSpacing; }
- int lineGap() const { return m_lineGap; }
+ const FontMetrics& fontMetrics() const { return m_fontMetrics; }
float maxCharWidth() const { return m_maxCharWidth; }
float avgCharWidth() const { return m_avgCharWidth; }
- float xHeight() const { return m_xHeight; }
- unsigned unitsPerEm() const { return m_unitsPerEm; }
FloatRect boundsForGlyph(Glyph) const;
float widthForGlyph(Glyph glyph) const;
@@ -211,14 +206,9 @@ private:
float widthForGDIGlyph(Glyph glyph) const;
#endif
- int m_ascent;
- int m_descent;
- int m_lineSpacing;
- int m_lineGap;
+ FontMetrics m_fontMetrics;
float m_maxCharWidth;
float m_avgCharWidth;
- float m_xHeight;
- unsigned m_unitsPerEm;
FontOrientation m_orientation; // This is our supported orientation according to the tables in the font. FontPlatformData will just always have the desired orientation.
// This value represents what we actually support.
diff --git a/Source/WebCore/platform/graphics/StringTruncator.cpp b/Source/WebCore/platform/graphics/StringTruncator.cpp
index 65325f0..8468188 100644
--- a/Source/WebCore/platform/graphics/StringTruncator.cpp
+++ b/Source/WebCore/platform/graphics/StringTruncator.cpp
@@ -29,12 +29,12 @@
#include "config.h"
#include "StringTruncator.h"
-#include "CharacterNames.h"
#include "Font.h"
#include "TextBreakIterator.h"
#include "TextRun.h"
#include <wtf/Assertions.h>
#include <wtf/Vector.h>
+#include <wtf/unicode/CharacterNames.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/graphics/TextRun.h b/Source/WebCore/platform/graphics/TextRun.h
index dce5535..ef434bd 100644
--- a/Source/WebCore/platform/graphics/TextRun.h
+++ b/Source/WebCore/platform/graphics/TextRun.h
@@ -2,7 +2,7 @@
* Copyright (C) 2000 Lars Knoll (knoll@kde.org)
* (C) 2000 Antti Koivisto (koivisto@kde.org)
* (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2006, 2007 Apple Computer, Inc.
+ * Copyright (C) 2003, 2006, 2007, 2011 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
@@ -33,12 +33,18 @@ class RenderSVGResource;
class TextRun {
public:
- TextRun(const UChar* c, int len, bool allowTabs = false, int xpos = 0, int padding = 0, bool rtl = false, bool directionalOverride = false,
+ enum TrailingExpansionBehavior {
+ AllowTrailingExpansion,
+ ForbidTrailingExpansion
+ };
+
+ TextRun(const UChar* c, int len, bool allowTabs = false, int xpos = 0, int expansion = 0, TrailingExpansionBehavior trailingExpansionBehavior = AllowTrailingExpansion, bool rtl = false, bool directionalOverride = false,
bool applyRunRounding = true, bool applyWordRounding = true)
: m_characters(c)
, m_len(len)
, m_xpos(xpos)
- , m_padding(padding)
+ , m_expansion(expansion)
+ , m_trailingExpansionBehavior(trailingExpansionBehavior)
#if ENABLE(SVG)
, m_horizontalGlyphStretch(1)
#endif
@@ -55,12 +61,13 @@ public:
{
}
- TextRun(const String& s, bool allowTabs = false, int xpos = 0, int padding = 0, bool rtl = false, bool directionalOverride = false,
+ TextRun(const String& s, bool allowTabs = false, int xpos = 0, int expansion = 0, TrailingExpansionBehavior trailingExpansionBehavior = AllowTrailingExpansion, bool rtl = false, bool directionalOverride = false,
bool applyRunRounding = true, bool applyWordRounding = true)
: m_characters(s.characters())
, m_len(s.length())
, m_xpos(xpos)
- , m_padding(padding)
+ , m_expansion(expansion)
+ , m_trailingExpansionBehavior(trailingExpansionBehavior)
#if ENABLE(SVG)
, m_horizontalGlyphStretch(1)
#endif
@@ -92,7 +99,8 @@ public:
bool allowTabs() const { return m_allowTabs; }
int xPos() const { return m_xpos; }
- int padding() const { return m_padding; }
+ int expansion() const { return m_expansion; }
+ bool allowsTrailingExpansion() const { return m_trailingExpansionBehavior == AllowTrailingExpansion; }
bool rtl() const { return m_rtl; }
bool ltr() const { return !m_rtl; }
bool directionalOverride() const { return m_directionalOverride; }
@@ -121,7 +129,8 @@ private:
// start of the containing block. In the case of right alignment or center alignment, left start of
// the text line is not the same as left start of the containing block.
int m_xpos;
- int m_padding;
+ int m_expansion;
+ TrailingExpansionBehavior m_trailingExpansionBehavior;
#if ENABLE(SVG)
float m_horizontalGlyphStretch;
#endif
diff --git a/Source/WebCore/platform/graphics/TiledBackingStore.cpp b/Source/WebCore/platform/graphics/TiledBackingStore.cpp
index 1d6f237..f6921ef 100644
--- a/Source/WebCore/platform/graphics/TiledBackingStore.cpp
+++ b/Source/WebCore/platform/graphics/TiledBackingStore.cpp
@@ -73,8 +73,8 @@ void TiledBackingStore::invalidate(const IntRect& contentsDirtyRect)
{
IntRect dirtyRect(mapFromContents(contentsDirtyRect));
- Tile::Coordinate topLeft = tileCoordinateForPoint(dirtyRect.topLeft());
- Tile::Coordinate bottomRight = tileCoordinateForPoint(dirtyRect.bottomRight());
+ Tile::Coordinate topLeft = tileCoordinateForPoint(dirtyRect.location());
+ Tile::Coordinate bottomRight = tileCoordinateForPoint(IntPoint(dirtyRect.maxX(), dirtyRect.maxY()));
for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) {
for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) {
@@ -93,6 +93,8 @@ void TiledBackingStore::updateTileBuffers()
if (m_contentsFrozen)
return;
+ m_client->tiledBackingStorePaintBegin();
+
Vector<IntRect> paintedArea;
Vector<RefPtr<Tile> > dirtyTiles;
TileMap::iterator end = m_tiles.end();
@@ -104,10 +106,10 @@ void TiledBackingStore::updateTileBuffers()
paintedArea.append(mapToContents(it->second->rect()));
}
- if (dirtyTiles.isEmpty())
+ if (dirtyTiles.isEmpty()) {
+ m_client->tiledBackingStorePaintEnd(paintedArea);
return;
-
- m_client->tiledBackingStorePaintBegin();
+ }
// FIXME: In single threaded case, tile back buffers could be updated asynchronously
// one by one and then swapped to front in one go. This would minimize the time spent
@@ -132,8 +134,8 @@ void TiledBackingStore::paint(GraphicsContext* context, const IntRect& rect)
IntRect dirtyRect = mapFromContents(rect);
- Tile::Coordinate topLeft = tileCoordinateForPoint(dirtyRect.topLeft());
- Tile::Coordinate bottomRight = tileCoordinateForPoint(dirtyRect.bottomRight());
+ Tile::Coordinate topLeft = tileCoordinateForPoint(dirtyRect.location());
+ Tile::Coordinate bottomRight = tileCoordinateForPoint(IntPoint(dirtyRect.maxX(), dirtyRect.maxY()));
for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) {
for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) {
@@ -227,8 +229,8 @@ void TiledBackingStore::createTiles()
double shortestDistance = std::numeric_limits<double>::infinity();
Vector<Tile::Coordinate> tilesToCreate;
unsigned requiredTileCount = 0;
- Tile::Coordinate topLeft = tileCoordinateForPoint(coverRect.topLeft());
- Tile::Coordinate bottomRight = tileCoordinateForPoint(coverRect.bottomRight());
+ Tile::Coordinate topLeft = tileCoordinateForPoint(coverRect.location());
+ Tile::Coordinate bottomRight = tileCoordinateForPoint(IntPoint(coverRect.maxX(), coverRect.maxY()));
for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) {
for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) {
Tile::Coordinate currentCoordinate(xCoordinate, yCoordinate);
diff --git a/Source/WebCore/platform/graphics/WidthIterator.cpp b/Source/WebCore/platform/graphics/WidthIterator.cpp
index 412c86e..a1a88da 100644
--- a/Source/WebCore/platform/graphics/WidthIterator.cpp
+++ b/Source/WebCore/platform/graphics/WidthIterator.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2006, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
* Copyright (C) 2008 Holger Hans Peter Freyther
*
* This library is free software; you can redistribute it and/or
@@ -47,6 +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_finalRoundingWidth(0)
, m_fallbackFonts(fallbackFonts)
, m_accountForGlyphBounds(accountForGlyphBounds)
@@ -58,20 +59,19 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const
{
// If the padding is non-zero, count the number of spaces in the run
// and divide that by the padding for per space addition.
- m_padding = m_run.padding();
- if (!m_padding)
- m_padPerSpace = 0;
+ m_expansion = m_run.expansion();
+ if (!m_expansion)
+ m_expansionPerOpportunity = 0;
else {
- int numSpaces = 0;
- for (int i = 0; i < run.length(); i++) {
- if (Font::treatAsSpace(m_run[i]))
- numSpaces++;
- }
+ bool isAfterExpansion = true;
+ unsigned expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion);
+ if (isAfterExpansion && !m_run.allowsTrailingExpansion())
+ expansionOpportunityCount--;
- if (!numSpaces)
- m_padPerSpace = 0;
+ if (!expansionOpportunityCount)
+ m_expansionPerOpportunity = 0;
else
- m_padPerSpace = m_padding / numSpaces;
+ m_expansionPerOpportunity = m_expansion / expansionOpportunityCount;
}
}
@@ -84,7 +84,7 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
const UChar* cp = m_run.data(currentCharacter);
bool rtl = m_run.rtl();
- bool hasExtraSpacing = (m_font->letterSpacing() || m_font->wordSpacing() || m_padding) && !m_run.spacingDisabled();
+ bool hasExtraSpacing = (m_font->letterSpacing() || m_font->wordSpacing() || m_expansion) && !m_run.spacingDisabled();
float widthSinceLastRounding = m_runWidthSoFar;
m_runWidthSoFar = floorf(m_runWidthSoFar);
@@ -173,26 +173,34 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
if (width && m_font->letterSpacing())
width += m_font->letterSpacing();
- if (Font::treatAsSpace(c)) {
- // Account for padding. WebCore uses space padding to justify text.
- // We distribute the specified padding over the available spaces in the run.
- if (m_padding) {
- // Use left over padding if not evenly divisible by number of spaces.
- if (m_padding < m_padPerSpace) {
- width += m_padding;
- m_padding = 0;
- } else {
- float previousPadding = m_padding;
- m_padding -= m_padPerSpace;
- width += roundf(previousPadding) - roundf(m_padding);
+ static bool expandAroundIdeographs = Font::canExpandAroundIdeographsInComplexText();
+ 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))) {
+ float previousExpansion = m_expansion;
+ if (!treatAsSpace && !m_isAfterExpansion) {
+ // Take the expansion opportunity before this ideograph.
+ m_expansion -= m_expansionPerOpportunity;
+ int expansion = roundf(previousExpansion) - roundf(m_expansion);
+ m_runWidthSoFar += expansion;
+ if (glyphBuffer)
+ glyphBuffer->expandLastAdvance(expansion);
+ previousExpansion = m_expansion;
}
- }
+ m_expansion -= m_expansionPerOpportunity;
+ width += roundf(previousExpansion) - roundf(m_expansion);
+ m_isAfterExpansion = true;
+ } else
+ m_isAfterExpansion = false;
// Account for word spacing.
// We apply additional space between "words" by adding width to the space character.
- if (currentCharacter != 0 && !Font::treatAsSpace(cp[-1]) && m_font->wordSpacing())
+ if (treatAsSpace && currentCharacter && !Font::treatAsSpace(cp[-1]) && m_font->wordSpacing())
width += m_font->wordSpacing();
- }
+ } else
+ m_isAfterExpansion = false;
}
if (m_accountForGlyphBounds) {
@@ -247,9 +255,9 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
lastRoundingWidth = width - oldWidth;
if (m_accountForGlyphBounds) {
- m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, bounds.bottom());
+ m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, bounds.maxY());
m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, bounds.y());
- m_lastGlyphOverflow = max<float>(0, bounds.right() - width);
+ m_lastGlyphOverflow = max<float>(0, bounds.maxX() - width);
}
}
@@ -260,13 +268,13 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer* glyphBuffer)
{
- glyphBuffer->clear();
+ int oldSize = glyphBuffer->size();
advance(m_currentCharacter + 1, glyphBuffer);
float w = 0;
- for (int i = 0; i < glyphBuffer->size(); ++i)
+ for (int i = oldSize; i < glyphBuffer->size(); ++i)
w += glyphBuffer->advanceAt(i);
width = w;
- return !glyphBuffer->isEmpty();
+ return glyphBuffer->size() > oldSize;
}
UChar32 WidthIterator::normalizeVoicingMarks(int currentCharacter)
diff --git a/Source/WebCore/platform/graphics/WidthIterator.h b/Source/WebCore/platform/graphics/WidthIterator.h
index 8b3c067..2b4f051 100644
--- a/Source/WebCore/platform/graphics/WidthIterator.h
+++ b/Source/WebCore/platform/graphics/WidthIterator.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2006, 2008, 2011 Apple Inc. All rights reserved.
* Copyright (C) 2008 Holger Hans Peter Freyther
*
* This library is free software; you can redistribute it and/or
@@ -50,8 +50,9 @@ struct WidthIterator {
unsigned m_currentCharacter;
float m_runWidthSoFar;
- float m_padding;
- float m_padPerSpace;
+ float m_expansion;
+ float m_expansionPerOpportunity;
+ bool m_isAfterExpansion;
float m_finalRoundingWidth;
private:
diff --git a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
index 01e25e9..2b4a39e 100644
--- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
+++ b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
@@ -1507,7 +1507,7 @@ void GraphicsLayerCA::pauseCAAnimationOnLayer(AnimatedPropertyID property, const
return;
// Animations on the layer are immutable, so we have to clone and modify.
- RefPtr<PlatformCAAnimation> newAnim = PlatformCAAnimation::create(curAnim.get());
+ RefPtr<PlatformCAAnimation> newAnim = curAnim->copy();
newAnim->setSpeed(0);
newAnim->setTimeOffset(timeOffset);
@@ -1646,7 +1646,7 @@ void GraphicsLayerCA::setupAnimation(PlatformCAAnimation* propertyAnim, const An
float repeatCount = anim->iterationCount();
if (repeatCount == Animation::IterationCountInfinite)
- repeatCount = FLT_MAX;
+ repeatCount = numeric_limits<float>::max();
else if (anim->direction() == Animation::AnimationDirectionAlternate)
repeatCount /= 2;
diff --git a/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h b/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h
index 4bfce63..a8528fd 100644
--- a/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h
+++ b/Source/WebCore/platform/graphics/ca/PlatformCAAnimation.h
@@ -63,13 +63,14 @@ public:
enum ValueFunctionType { NoValueFunction, RotateX, RotateY, RotateZ, ScaleX, ScaleY, ScaleZ, Scale, TranslateX, TranslateY, TranslateZ, Translate };
static PassRefPtr<PlatformCAAnimation> create(AnimationType, const String& keyPath);
- static PassRefPtr<PlatformCAAnimation> create(PlatformAnimationRef animation);
- static PassRefPtr<PlatformCAAnimation> create(const PlatformCAAnimation* animation);
+ static PassRefPtr<PlatformCAAnimation> create(PlatformAnimationRef);
~PlatformCAAnimation();
static bool supportsValueFunction();
+ PassRefPtr<PlatformCAAnimation> copy() const;
+
PlatformAnimationRef platformAnimation() const;
AnimationType animationType() const { return m_type; }
@@ -136,8 +137,7 @@ public:
protected:
PlatformCAAnimation(AnimationType, const String& keyPath);
- PlatformCAAnimation(PlatformAnimationRef animation);
- PlatformCAAnimation(const PlatformCAAnimation* animation);
+ PlatformCAAnimation(PlatformAnimationRef);
private:
AnimationType m_type;
diff --git a/Source/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm b/Source/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm
index 2a00857..506bd40 100644
--- a/Source/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm
+++ b/Source/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm
@@ -159,11 +159,6 @@ PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(PlatformAnimationRef
return adoptRef(new PlatformCAAnimation(animation));
}
-PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(const PlatformCAAnimation* animation)
-{
- return adoptRef(new PlatformCAAnimation(animation));
-}
-
PlatformCAAnimation::PlatformCAAnimation(AnimationType type, const String& keyPath)
: m_type(type)
{
@@ -187,38 +182,36 @@ PlatformCAAnimation::PlatformCAAnimation(PlatformAnimationRef animation)
m_animation = static_cast<CAPropertyAnimation*>(animation);
}
-PlatformCAAnimation::PlatformCAAnimation(const PlatformCAAnimation* animation)
+PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::copy() const
{
- PlatformCAAnimation* newAnimation = new PlatformCAAnimation(animation->animationType(), animation->keyPath());
-
- newAnimation->setBeginTime(animation->beginTime());
- newAnimation->setDuration(animation->duration());
- newAnimation->setSpeed(animation->speed());
- newAnimation->setTimeOffset(animation->timeOffset());
- newAnimation->setRepeatCount(animation->repeatCount());
- newAnimation->setAutoreverses(animation->autoreverses());
- newAnimation->setFillMode(animation->fillMode());
- newAnimation->setRemovedOnCompletion(animation->isRemovedOnCompletion());
- newAnimation->setAdditive(animation->isAdditive());
- newAnimation->copyTimingFunctionFrom(animation);
-
-#if HAVE_MODERN_QUARTZCORE
- newAnimation->setValueFunction(animation->valueFunction());
-#endif
-
- setNonZeroBeginTimeFlag(newAnimation, hasNonZeroBeginTimeFlag(animation));
+ RefPtr<PlatformCAAnimation> animation = create(animationType(), keyPath());
+
+ animation->setBeginTime(beginTime());
+ animation->setDuration(duration());
+ animation->setSpeed(speed());
+ animation->setTimeOffset(timeOffset());
+ animation->setRepeatCount(repeatCount());
+ animation->setAutoreverses(autoreverses());
+ animation->setFillMode(fillMode());
+ animation->setRemovedOnCompletion(isRemovedOnCompletion());
+ animation->setAdditive(isAdditive());
+ animation->copyTimingFunctionFrom(this);
+ animation->setValueFunction(valueFunction());
+
+ setNonZeroBeginTimeFlag(animation.get(), hasNonZeroBeginTimeFlag(this));
// Copy the specific Basic or Keyframe values
- if (animation->animationType() == Keyframe) {
- newAnimation->copyValuesFrom(animation);
- newAnimation->copyKeyTimesFrom(animation);
- newAnimation->copyTimingFunctionsFrom(animation);
+ if (animationType() == Keyframe) {
+ animation->copyValuesFrom(this);
+ animation->copyKeyTimesFrom(this);
+ animation->copyTimingFunctionsFrom(this);
} else {
- newAnimation->copyFromValueFrom(animation);
- newAnimation->copyToValueFrom(animation);
+ animation->copyFromValueFrom(this);
+ animation->copyToValueFrom(this);
}
+
+ return animation;
}
-
PlatformCAAnimation::~PlatformCAAnimation()
{
}
diff --git a/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp b/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp
index 1d27608..9dc30ea 100644
--- a/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp
+++ b/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp
@@ -28,49 +28,22 @@
#if USE(ACCELERATED_COMPOSITING)
+#include "CACFLayerTreeHostClient.h"
#include "LayerChangesFlusher.h"
+#include "LegacyCACFLayerTreeHost.h"
#include "PlatformCALayer.h"
+#include "WKCACFViewLayerTreeHost.h"
#include "WebCoreInstanceHandle.h"
-#include <WebKitSystemInterface/WebKitSystemInterface.h>
#include <limits.h>
#include <wtf/CurrentTime.h>
-#include <wtf/HashMap.h>
#include <wtf/OwnArrayPtr.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
-#include <wtf/StdLibExtras.h>
-#ifndef NDEBUG
-#define D3D_DEBUG_INFO
-#endif
-
-#include <d3d9.h>
-#include <d3dx9.h>
-
-using namespace std;
-
-#pragma comment(lib, "d3d9")
-#pragma comment(lib, "d3dx9")
#ifdef DEBUG_ALL
#pragma comment(lib, "QuartzCore_debug")
#else
#pragma comment(lib, "QuartzCore")
#endif
-static IDirect3D9* s_d3d = 0;
-static IDirect3D9* d3d()
-{
- if (s_d3d)
- return s_d3d;
-
- if (!LoadLibrary(TEXT("d3d9.dll")))
- return 0;
-
- s_d3d = Direct3DCreate9(D3D_SDK_VERSION);
-
- return s_d3d;
-}
-
inline static CGRect winRectToCGRect(RECT rc)
{
return CGRectMake(rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top));
@@ -83,40 +56,6 @@ inline static CGRect winRectToCGRect(RECT rc, RECT relativeToRect)
namespace WebCore {
-static D3DPRESENT_PARAMETERS initialPresentationParameters()
-{
- D3DPRESENT_PARAMETERS parameters = {0};
- parameters.Windowed = TRUE;
- parameters.SwapEffect = D3DSWAPEFFECT_COPY;
- parameters.BackBufferCount = 1;
- parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
- parameters.MultiSampleType = D3DMULTISAMPLE_NONE;
-
- return parameters;
-}
-
-// FIXME: <rdar://6507851> Share this code with CoreAnimation.
-static bool hardwareCapabilitiesIndicateCoreAnimationSupport(const D3DCAPS9& caps)
-{
- // CoreAnimation needs two or more texture units.
- if (caps.MaxTextureBlendStages < 2)
- return false;
-
- // CoreAnimation needs non-power-of-two textures.
- if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))
- return false;
-
- // CoreAnimation needs vertex shader 2.0 or greater.
- if (D3DSHADER_VERSION_MAJOR(caps.VertexShaderVersion) < 2)
- return false;
-
- // CoreAnimation needs pixel shader 2.0 or greater.
- if (D3DSHADER_VERSION_MAJOR(caps.PixelShaderVersion) < 2)
- return false;
-
- return true;
-}
-
bool CACFLayerTreeHost::acceleratedCompositingAvailable()
{
static bool available;
@@ -158,7 +97,7 @@ bool CACFLayerTreeHost::acceleratedCompositingAvailable()
wcex.hInstance = WebCore::instanceHandle();
wcex.lpszClassName = L"CoreAnimationTesterWindowClass";
::RegisterClassEx(&wcex);
- HWND testWindow = ::CreateWindow(L"CoreAnimationTesterWindowClass", L"CoreAnimationTesterWindow", WS_POPUP, -500, -500, 0, 0, 0, 0, 0, 0);
+ HWND testWindow = ::CreateWindow(L"CoreAnimationTesterWindowClass", L"CoreAnimationTesterWindow", WS_POPUP, -500, -500, 20, 20, 0, 0, 0, 0);
if (!testWindow) {
available = false;
@@ -168,6 +107,7 @@ bool CACFLayerTreeHost::acceleratedCompositingAvailable()
RefPtr<CACFLayerTreeHost> host = CACFLayerTreeHost::create();
host->setWindow(testWindow);
available = host->createRenderer();
+ host->setWindow(0);
::DestroyWindow(testWindow);
return available;
@@ -177,22 +117,29 @@ PassRefPtr<CACFLayerTreeHost> CACFLayerTreeHost::create()
{
if (!acceleratedCompositingAvailable())
return 0;
- return adoptRef(new CACFLayerTreeHost());
+ RefPtr<CACFLayerTreeHost> host = WKCACFViewLayerTreeHost::create();
+ if (!host)
+ host = LegacyCACFLayerTreeHost::create();
+ host->initialize();
+ return host.release();
}
CACFLayerTreeHost::CACFLayerTreeHost()
: m_client(0)
- , m_mightBeAbleToCreateDeviceLater(true)
, m_rootLayer(PlatformCALayer::create(PlatformCALayer::LayerTypeRootLayer, 0))
- , m_context(wkCACFContextCreate())
, m_window(0)
- , m_renderTimer(this, &CACFLayerTreeHost::renderTimerFired)
- , m_mustResetLostDeviceBeforeRendering(false)
, m_shouldFlushPendingGraphicsLayerChanges(false)
, m_isFlushingLayerChanges(false)
+#if !ASSERT_DISABLED
+ , m_state(WindowNotSet)
+#endif
+{
+}
+
+void CACFLayerTreeHost::initialize()
{
// Point the CACFContext to this
- wkCACFContextSetUserData(m_context, this);
+ initializeContext(this, m_rootLayer.get());
// Under the root layer, we have a clipping layer to clip the content,
// that contains a scroll layer that we use for scrolling the content.
@@ -212,20 +159,11 @@ CACFLayerTreeHost::CACFLayerTreeHost()
m_rootLayer->setBackgroundColor(debugColor);
CGColorRelease(debugColor);
#endif
-
- if (m_context)
- wkCACFContextSetLayer(m_context, m_rootLayer->platformLayer());
-
-#ifndef NDEBUG
- char* printTreeFlag = getenv("CA_PRINT_TREE");
- m_printTree = printTreeFlag && atoi(printTreeFlag);
-#endif
}
CACFLayerTreeHost::~CACFLayerTreeHost()
{
- setWindow(0);
- wkCACFContextDestroy(m_context);
+ ASSERT_WITH_MESSAGE(m_state != WindowSet, "Must call setWindow(0) before destroying CACFLayerTreeHost");
}
void CACFLayerTreeHost::setWindow(HWND window)
@@ -233,13 +171,28 @@ void CACFLayerTreeHost::setWindow(HWND window)
if (window == m_window)
return;
+#if !ASSERT_DISABLED
+ switch (m_state) {
+ case WindowNotSet:
+ ASSERT_ARG(window, window);
+ ASSERT(!m_window);
+ m_state = WindowSet;
+ break;
+ case WindowSet:
+ ASSERT_ARG(window, !window);
+ ASSERT(m_window);
+ m_state = WindowCleared;
+ break;
+ case WindowCleared:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+#endif
+
if (m_window)
destroyRenderer();
m_window = window;
-
- if (m_window)
- createRenderer();
}
PlatformCALayer* CACFLayerTreeHost::rootLayer() const
@@ -275,109 +228,11 @@ void CACFLayerTreeHost::layerTreeDidChange()
LayerChangesFlusher::shared().flushPendingLayerChangesSoon(this);
}
-bool CACFLayerTreeHost::createRenderer()
-{
- if (m_d3dDevice || !m_mightBeAbleToCreateDeviceLater)
- return m_d3dDevice;
-
- m_mightBeAbleToCreateDeviceLater = false;
- D3DPRESENT_PARAMETERS parameters = initialPresentationParameters();
-
- if (!d3d() || !::IsWindow(m_window))
- return false;
-
- // D3D doesn't like to make back buffers for 0 size windows. We skirt this problem if we make the
- // passed backbuffer width and height non-zero. The window will necessarily get set to a non-zero
- // size eventually, and then the backbuffer size will get reset.
- RECT rect;
- GetClientRect(m_window, &rect);
-
- if (rect.left-rect.right == 0 || rect.bottom-rect.top == 0) {
- parameters.BackBufferWidth = 1;
- parameters.BackBufferHeight = 1;
- }
-
- D3DCAPS9 d3dCaps;
- if (FAILED(d3d()->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps)))
- return false;
-
- DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE;
- if ((d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) && d3dCaps.VertexProcessingCaps)
- behaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
- else
- behaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
-
- COMPtr<IDirect3DDevice9> device;
- if (FAILED(d3d()->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_window, behaviorFlags, &parameters, &device))) {
- // In certain situations (e.g., shortly after waking from sleep), Direct3DCreate9() will
- // return an IDirect3D9 for which IDirect3D9::CreateDevice will always fail. In case we
- // have one of these bad IDirect3D9s, get rid of it so we'll fetch a new one the next time
- // we want to call CreateDevice.
- s_d3d->Release();
- s_d3d = 0;
-
- // Even if we don't have a bad IDirect3D9, in certain situations (e.g., shortly after
- // waking from sleep), CreateDevice will fail, but will later succeed if called again.
- m_mightBeAbleToCreateDeviceLater = true;
-
- return false;
- }
-
- // Now that we've created the IDirect3DDevice9 based on the capabilities we
- // got from the IDirect3D9 global object, we requery the device for its
- // actual capabilities. The capabilities returned by the device can
- // sometimes be more complete, for example when using software vertex
- // processing.
- D3DCAPS9 deviceCaps;
- if (FAILED(device->GetDeviceCaps(&deviceCaps)))
- return false;
-
- if (!hardwareCapabilitiesIndicateCoreAnimationSupport(deviceCaps))
- return false;
-
- m_d3dDevice = device;
-
- initD3DGeometry();
-
- wkCACFContextSetD3DDevice(m_context, m_d3dDevice.get());
-
- if (IsWindow(m_window))
- m_rootLayer->setBounds(bounds());
-
- return true;
-}
-
void CACFLayerTreeHost::destroyRenderer()
{
- LayerChangesFlusher::shared().cancelPendingFlush(this);
-
- wkCACFContextSetLayer(m_context, 0);
-
- wkCACFContextSetD3DDevice(m_context, 0);
- m_d3dDevice = 0;
- if (s_d3d)
- s_d3d->Release();
-
- s_d3d = 0;
m_rootLayer = 0;
m_rootChildLayer = 0;
-
- m_mightBeAbleToCreateDeviceLater = true;
-}
-
-void CACFLayerTreeHost::resize()
-{
- if (!m_d3dDevice)
- return;
-
- // Resetting the device might fail here. But that's OK, because if it does it we will attempt to
- // reset the device the next time we try to render.
- resetDevice(ChangedWindowSize);
-
- if (m_rootLayer) {
- m_rootLayer->setBounds(bounds());
- wkCACFContextFlush(m_context);
- }
+ LayerChangesFlusher::shared().cancelPendingFlush(this);
}
static void getDirtyRects(HWND window, Vector<CGRect>& outRects)
@@ -398,7 +253,7 @@ static void getDirtyRects(HWND window, Vector<CGRect>& outRects)
}
DWORD dataSize = GetRegionData(region.get(), 0, 0);
- OwnArrayPtr<unsigned char> regionDataBuffer(new unsigned char[dataSize]);
+ OwnArrayPtr<unsigned char> regionDataBuffer = adoptArrayPtr(new unsigned char[dataSize]);
RGNDATA* regionData = reinterpret_cast<RGNDATA*>(regionDataBuffer.get());
if (!GetRegionData(region.get(), dataSize, regionData))
return;
@@ -410,120 +265,13 @@ static void getDirtyRects(HWND window, Vector<CGRect>& outRects)
outRects[i] = winRectToCGRect(*rect, clientRect);
}
-void CACFLayerTreeHost::renderTimerFired(Timer<CACFLayerTreeHost>*)
-{
- paint();
-}
-
void CACFLayerTreeHost::paint()
{
- createRenderer();
- if (!m_d3dDevice) {
- if (m_mightBeAbleToCreateDeviceLater)
- renderSoon();
- return;
- }
-
Vector<CGRect> dirtyRects;
getDirtyRects(m_window, dirtyRects);
render(dirtyRects);
}
-void CACFLayerTreeHost::render(const Vector<CGRect>& windowDirtyRects)
-{
- ASSERT(m_d3dDevice);
-
- if (m_mustResetLostDeviceBeforeRendering && !resetDevice(LostDevice)) {
- // We can't reset the device right now. Try again soon.
- renderSoon();
- return;
- }
-
- // All pending animations will have been started with the flush. Fire the animationStarted calls
- double currentTime = WTF::currentTime();
- double currentMediaTime = CACurrentMediaTime();
- double t = currentTime + wkCACFContextGetLastCommitTime(m_context) - currentMediaTime;
- ASSERT(t <= currentTime);
-
- HashSet<RefPtr<PlatformCALayer> >::iterator end = m_pendingAnimatedLayers.end();
- for (HashSet<RefPtr<PlatformCALayer> >::iterator it = m_pendingAnimatedLayers.begin(); it != end; ++it) {
- PlatformCALayerClient* owner = (*it)->owner();
- owner->platformCALayerAnimationStarted(t);
- }
-
- m_pendingAnimatedLayers.clear();
-
- CGRect bounds = this->bounds();
-
- // Give the renderer some space to use. This needs to be valid until the
- // wkCACFContextFinishUpdate() call below.
- char space[4096];
- if (!wkCACFContextBeginUpdate(m_context, space, sizeof(space), currentMediaTime, bounds, windowDirtyRects.data(), windowDirtyRects.size()))
- return;
-
- HRESULT err = S_OK;
- CFTimeInterval timeToNextRender = numeric_limits<CFTimeInterval>::infinity();
-
- do {
- // FIXME: don't need to clear dirty region if layer tree is opaque.
-
- WKCACFUpdateRectEnumerator* e = wkCACFContextCopyUpdateRectEnumerator(m_context);
- if (!e)
- break;
-
- Vector<D3DRECT, 64> rects;
- for (const CGRect* r = wkCACFUpdateRectEnumeratorNextRect(e); r; r = wkCACFUpdateRectEnumeratorNextRect(e)) {
- D3DRECT rect;
- rect.x1 = r->origin.x;
- rect.x2 = rect.x1 + r->size.width;
- rect.y1 = bounds.origin.y + bounds.size.height - (r->origin.y + r->size.height);
- rect.y2 = rect.y1 + r->size.height;
-
- rects.append(rect);
- }
- wkCACFUpdateRectEnumeratorRelease(e);
-
- timeToNextRender = wkCACFContextGetNextUpdateTime(m_context);
-
- if (rects.isEmpty())
- break;
-
- m_d3dDevice->Clear(rects.size(), rects.data(), D3DCLEAR_TARGET, 0, 1.0f, 0);
-
- m_d3dDevice->BeginScene();
- wkCACFContextRenderUpdate(m_context);
- m_d3dDevice->EndScene();
-
- err = m_d3dDevice->Present(0, 0, 0, 0);
-
- if (err == D3DERR_DEVICELOST) {
- wkCACFContextAddUpdateRect(m_context, bounds);
- if (!resetDevice(LostDevice)) {
- // We can't reset the device right now. Try again soon.
- renderSoon();
- return;
- }
- }
- } while (err == D3DERR_DEVICELOST);
-
- wkCACFContextFinishUpdate(m_context);
-
-#ifndef NDEBUG
- if (m_printTree)
- m_rootLayer->printTree();
-#endif
-
- // If timeToNextRender is not infinity, it means animations are running, so queue up to render again
- if (timeToNextRender != numeric_limits<CFTimeInterval>::infinity())
- renderSoon();
-}
-
-void CACFLayerTreeHost::renderSoon()
-{
- if (!m_renderTimer.isActive())
- m_renderTimer.startOneShot(0);
-}
-
void CACFLayerTreeHost::flushPendingGraphicsLayerChangesSoon()
{
m_shouldFlushPendingGraphicsLayerChanges = true;
@@ -545,75 +293,36 @@ void CACFLayerTreeHost::flushPendingLayerChangesNow()
}
// Flush changes stored up in PlatformCALayers to the context so they will be rendered.
- wkCACFContextFlush(m_context);
-
- renderSoon();
+ flushContext();
m_isFlushingLayerChanges = false;
}
-CGRect CACFLayerTreeHost::bounds() const
+void CACFLayerTreeHost::contextDidChange()
{
- RECT clientRect;
- GetClientRect(m_window, &clientRect);
-
- return winRectToCGRect(clientRect);
+ // All pending animations will have been started with the flush. Fire the animationStarted calls.
+ notifyAnimationsStarted();
}
-void CACFLayerTreeHost::initD3DGeometry()
+void CACFLayerTreeHost::notifyAnimationsStarted()
{
- ASSERT(m_d3dDevice);
-
- CGRect bounds = this->bounds();
-
- float x0 = bounds.origin.x;
- float y0 = bounds.origin.y;
- float x1 = x0 + bounds.size.width;
- float y1 = y0 + bounds.size.height;
+ double currentTime = WTF::currentTime();
+ double time = currentTime + lastCommitTime() - CACurrentMediaTime();
+ ASSERT(time <= currentTime);
- D3DXMATRIXA16 projection;
- D3DXMatrixOrthoOffCenterRH(&projection, x0, x1, y0, y1, -1.0f, 1.0f);
+ HashSet<RefPtr<PlatformCALayer> >::iterator end = m_pendingAnimatedLayers.end();
+ for (HashSet<RefPtr<PlatformCALayer> >::iterator it = m_pendingAnimatedLayers.begin(); it != end; ++it)
+ (*it)->animationStarted(time);
- m_d3dDevice->SetTransform(D3DTS_PROJECTION, &projection);
+ m_pendingAnimatedLayers.clear();
}
-bool CACFLayerTreeHost::resetDevice(ResetReason reason)
+CGRect CACFLayerTreeHost::bounds() const
{
- ASSERT(m_d3dDevice);
- ASSERT(m_context);
-
- HRESULT hr = m_d3dDevice->TestCooperativeLevel();
-
- if (hr == D3DERR_DEVICELOST || hr == D3DERR_DRIVERINTERNALERROR) {
- // The device cannot be reset at this time. Try again soon.
- m_mustResetLostDeviceBeforeRendering = true;
- return false;
- }
-
- m_mustResetLostDeviceBeforeRendering = false;
-
- if (reason == LostDevice && hr == D3D_OK) {
- // The device wasn't lost after all.
- return true;
- }
-
- // We can reset the device.
-
- // We have to release the context's D3D resrouces whenever we reset the IDirect3DDevice9 in order to
- // destroy any D3DPOOL_DEFAULT resources that Core Animation has allocated (e.g., textures used
- // for mask layers). See <http://msdn.microsoft.com/en-us/library/bb174425(v=VS.85).aspx>.
- wkCACFContextReleaseD3DResources(m_context);
-
- D3DPRESENT_PARAMETERS parameters = initialPresentationParameters();
- hr = m_d3dDevice->Reset(&parameters);
-
- // TestCooperativeLevel told us the device may be reset now, so we should
- // not be told here that the device is lost.
- ASSERT(hr != D3DERR_DEVICELOST);
-
- initD3DGeometry();
+ RECT clientRect;
+ GetClientRect(m_window, &clientRect);
- return true;
+ return winRectToCGRect(clientRect);
}
}
diff --git a/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.h b/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.h
index fc61f39..6d91a73 100644
--- a/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.h
+++ b/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.h
@@ -47,75 +47,59 @@ typedef struct CGImage* CGImageRef;
namespace WebCore {
+class CACFLayerTreeHostClient;
class PlatformCALayer;
-class CACFLayerTreeHostClient {
-public:
- virtual ~CACFLayerTreeHostClient() { }
- virtual void flushPendingGraphicsLayerChanges() { }
-};
-
-// FIXME: Currently there is a CACFLayerTreeHost for each WebView and each
-// has its own CARenderOGLContext and Direct3DDevice9, which is inefficient.
-// (https://bugs.webkit.org/show_bug.cgi?id=31855)
class CACFLayerTreeHost : public RefCounted<CACFLayerTreeHost> {
friend PlatformCALayer;
public:
static PassRefPtr<CACFLayerTreeHost> create();
- ~CACFLayerTreeHost();
+ virtual ~CACFLayerTreeHost();
static bool acceleratedCompositingAvailable();
void setClient(CACFLayerTreeHostClient* client) { m_client = client; }
void setRootChildLayer(PlatformCALayer*);
- void layerTreeDidChange();
void setWindow(HWND);
- void paint();
- void resize();
+ virtual void paint();
+ virtual void resize() = 0;
void flushPendingGraphicsLayerChangesSoon();
void flushPendingLayerChangesNow();
protected:
- PlatformCALayer* rootLayer() const;
- void addPendingAnimatedLayer(PassRefPtr<PlatformCALayer>);
-
-private:
CACFLayerTreeHost();
- bool createRenderer();
- void destroyRenderer();
- void renderSoon();
- void renderTimerFired(Timer<CACFLayerTreeHost>*);
-
CGRect bounds() const;
+ PlatformCALayer* rootLayer() const;
+ HWND window() const { return m_window; }
+ void notifyAnimationsStarted();
- void initD3DGeometry();
+ virtual bool createRenderer() = 0;
+ virtual void destroyRenderer();
+ virtual void contextDidChange();
- // Call this when the device window has changed size or when IDirect3DDevice9::Present returns
- // D3DERR_DEVICELOST. Returns true if the device was recovered, false if rendering must be
- // aborted and reattempted soon.
- enum ResetReason { ChangedWindowSize, LostDevice };
- bool resetDevice(ResetReason);
+private:
+ void initialize();
+ void addPendingAnimatedLayer(PassRefPtr<PlatformCALayer>);
+ void layerTreeDidChange();
- void render(const Vector<CGRect>& dirtyRects = Vector<CGRect>());
+ virtual void flushContext() = 0;
+ virtual CFTimeInterval lastCommitTime() const = 0;
+ virtual void render(const Vector<CGRect>& dirtyRects = Vector<CGRect>()) = 0;
+ virtual void initializeContext(void* userData, PlatformCALayer*) = 0;
CACFLayerTreeHostClient* m_client;
- bool m_mightBeAbleToCreateDeviceLater;
- COMPtr<IDirect3DDevice9> m_d3dDevice;
RefPtr<PlatformCALayer> m_rootLayer;
RefPtr<PlatformCALayer> m_rootChildLayer;
- WKCACFContext* m_context;
+ HashSet<RefPtr<PlatformCALayer> > m_pendingAnimatedLayers;
HWND m_window;
- Timer<CACFLayerTreeHost> m_renderTimer;
- bool m_mustResetLostDeviceBeforeRendering;
bool m_shouldFlushPendingGraphicsLayerChanges;
bool m_isFlushingLayerChanges;
- HashSet<RefPtr<PlatformCALayer> > m_pendingAnimatedLayers;
-#ifndef NDEBUG
- bool m_printTree;
+#if !ASSERT_DISABLED
+ enum { WindowNotSet, WindowSet, WindowCleared } m_state;
#endif
};
diff --git a/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHostClient.h b/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHostClient.h
new file mode 100644
index 0000000..845f934
--- /dev/null
+++ b/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHostClient.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 CACFLayerTreeHostClient_h
+#define CACFLayerTreeHostClient_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+namespace WebCore {
+
+class CACFLayerTreeHostClient {
+public:
+ virtual ~CACFLayerTreeHostClient() { }
+ virtual void flushPendingGraphicsLayerChanges() { }
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // CACFLayerTreeHostClient_h
diff --git a/Source/WebCore/platform/graphics/ca/win/LegacyCACFLayerTreeHost.cpp b/Source/WebCore/platform/graphics/ca/win/LegacyCACFLayerTreeHost.cpp
new file mode 100644
index 0000000..772244b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/ca/win/LegacyCACFLayerTreeHost.cpp
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LegacyCACFLayerTreeHost.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "PlatformCALayer.h"
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
+
+#ifndef NDEBUG
+#define D3D_DEBUG_INFO
+#endif
+
+#include <d3d9.h>
+#include <d3dx9.h>
+
+#pragma comment(lib, "d3d9")
+#pragma comment(lib, "d3dx9")
+
+using namespace std;
+
+namespace WebCore {
+
+static IDirect3D9* s_d3d = 0;
+static IDirect3D9* d3d()
+{
+ if (s_d3d)
+ return s_d3d;
+
+ if (!LoadLibrary(TEXT("d3d9.dll")))
+ return 0;
+
+ s_d3d = Direct3DCreate9(D3D_SDK_VERSION);
+
+ return s_d3d;
+}
+
+static D3DPRESENT_PARAMETERS initialPresentationParameters()
+{
+ D3DPRESENT_PARAMETERS parameters = {0};
+ parameters.Windowed = TRUE;
+ parameters.SwapEffect = D3DSWAPEFFECT_COPY;
+ parameters.BackBufferCount = 1;
+ parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
+ parameters.MultiSampleType = D3DMULTISAMPLE_NONE;
+
+ return parameters;
+}
+
+// FIXME: <rdar://6507851> Share this code with CoreAnimation.
+static bool hardwareCapabilitiesIndicateCoreAnimationSupport(const D3DCAPS9& caps)
+{
+ // CoreAnimation needs two or more texture units.
+ if (caps.MaxTextureBlendStages < 2)
+ return false;
+
+ // CoreAnimation needs non-power-of-two textures.
+ if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))
+ return false;
+
+ // CoreAnimation needs vertex shader 2.0 or greater.
+ if (D3DSHADER_VERSION_MAJOR(caps.VertexShaderVersion) < 2)
+ return false;
+
+ // CoreAnimation needs pixel shader 2.0 or greater.
+ if (D3DSHADER_VERSION_MAJOR(caps.PixelShaderVersion) < 2)
+ return false;
+
+ return true;
+}
+
+PassRefPtr<LegacyCACFLayerTreeHost> LegacyCACFLayerTreeHost::create()
+{
+ return adoptRef(new LegacyCACFLayerTreeHost);
+}
+
+LegacyCACFLayerTreeHost::LegacyCACFLayerTreeHost()
+ : m_renderTimer(this, &LegacyCACFLayerTreeHost::renderTimerFired)
+ , m_context(wkCACFContextCreate())
+ , m_mightBeAbleToCreateDeviceLater(true)
+ , m_mustResetLostDeviceBeforeRendering(false)
+{
+#ifndef NDEBUG
+ char* printTreeFlag = getenv("CA_PRINT_TREE");
+ m_printTree = printTreeFlag && atoi(printTreeFlag);
+#endif
+}
+
+LegacyCACFLayerTreeHost::~LegacyCACFLayerTreeHost()
+{
+ wkCACFContextDestroy(m_context);
+}
+
+void LegacyCACFLayerTreeHost::initializeContext(void* userData, PlatformCALayer* layer)
+{
+ wkCACFContextSetUserData(m_context, userData);
+ wkCACFContextSetLayer(m_context, layer->platformLayer());
+}
+
+bool LegacyCACFLayerTreeHost::createRenderer()
+{
+ if (m_d3dDevice || !m_mightBeAbleToCreateDeviceLater)
+ return m_d3dDevice;
+
+ m_mightBeAbleToCreateDeviceLater = false;
+ D3DPRESENT_PARAMETERS parameters = initialPresentationParameters();
+
+ if (!d3d() || !::IsWindow(window()))
+ return false;
+
+ // D3D doesn't like to make back buffers for 0 size windows. We skirt this problem if we make the
+ // passed backbuffer width and height non-zero. The window will necessarily get set to a non-zero
+ // size eventually, and then the backbuffer size will get reset.
+ RECT rect;
+ GetClientRect(window(), &rect);
+
+ if (rect.left-rect.right == 0 || rect.bottom-rect.top == 0) {
+ parameters.BackBufferWidth = 1;
+ parameters.BackBufferHeight = 1;
+ }
+
+ D3DCAPS9 d3dCaps;
+ if (FAILED(d3d()->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps)))
+ return false;
+
+ DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE;
+ if ((d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) && d3dCaps.VertexProcessingCaps)
+ behaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
+ else
+ behaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
+
+ COMPtr<IDirect3DDevice9> device;
+ if (FAILED(d3d()->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window(), behaviorFlags, &parameters, &device))) {
+ // In certain situations (e.g., shortly after waking from sleep), Direct3DCreate9() will
+ // return an IDirect3D9 for which IDirect3D9::CreateDevice will always fail. In case we
+ // have one of these bad IDirect3D9s, get rid of it so we'll fetch a new one the next time
+ // we want to call CreateDevice.
+ s_d3d->Release();
+ s_d3d = 0;
+
+ // Even if we don't have a bad IDirect3D9, in certain situations (e.g., shortly after
+ // waking from sleep), CreateDevice will fail, but will later succeed if called again.
+ m_mightBeAbleToCreateDeviceLater = true;
+
+ return false;
+ }
+
+ // Now that we've created the IDirect3DDevice9 based on the capabilities we
+ // got from the IDirect3D9 global object, we requery the device for its
+ // actual capabilities. The capabilities returned by the device can
+ // sometimes be more complete, for example when using software vertex
+ // processing.
+ D3DCAPS9 deviceCaps;
+ if (FAILED(device->GetDeviceCaps(&deviceCaps)))
+ return false;
+
+ if (!hardwareCapabilitiesIndicateCoreAnimationSupport(deviceCaps))
+ return false;
+
+ m_d3dDevice = device;
+
+ initD3DGeometry();
+
+ wkCACFContextSetD3DDevice(m_context, m_d3dDevice.get());
+
+ if (IsWindow(window())) {
+ rootLayer()->setBounds(bounds());
+ flushContext();
+ }
+
+ return true;
+}
+
+void LegacyCACFLayerTreeHost::destroyRenderer()
+{
+ wkCACFContextSetLayer(m_context, 0);
+
+ wkCACFContextSetD3DDevice(m_context, 0);
+ m_d3dDevice = 0;
+ if (s_d3d)
+ s_d3d->Release();
+
+ s_d3d = 0;
+ m_mightBeAbleToCreateDeviceLater = true;
+
+ CACFLayerTreeHost::destroyRenderer();
+}
+
+void LegacyCACFLayerTreeHost::resize()
+{
+ if (!m_d3dDevice)
+ return;
+
+ // Resetting the device might fail here. But that's OK, because if it does it we will attempt to
+ // reset the device the next time we try to render.
+ resetDevice(ChangedWindowSize);
+
+ if (rootLayer()) {
+ rootLayer()->setBounds(bounds());
+ flushContext();
+ }
+}
+
+void LegacyCACFLayerTreeHost::renderTimerFired(Timer<LegacyCACFLayerTreeHost>*)
+{
+ paint();
+}
+
+void LegacyCACFLayerTreeHost::paint()
+{
+ createRenderer();
+ if (!m_d3dDevice) {
+ if (m_mightBeAbleToCreateDeviceLater)
+ renderSoon();
+ return;
+ }
+
+ CACFLayerTreeHost::paint();
+}
+
+void LegacyCACFLayerTreeHost::render(const Vector<CGRect>& windowDirtyRects)
+{
+ ASSERT(m_d3dDevice);
+
+ if (m_mustResetLostDeviceBeforeRendering && !resetDevice(LostDevice)) {
+ // We can't reset the device right now. Try again soon.
+ renderSoon();
+ return;
+ }
+
+ CGRect bounds = this->bounds();
+
+ // Give the renderer some space to use. This needs to be valid until the
+ // wkCACFContextFinishUpdate() call below.
+ char space[4096];
+ if (!wkCACFContextBeginUpdate(m_context, space, sizeof(space), CACurrentMediaTime(), bounds, windowDirtyRects.data(), windowDirtyRects.size()))
+ return;
+
+ HRESULT err = S_OK;
+ CFTimeInterval timeToNextRender = numeric_limits<CFTimeInterval>::infinity();
+
+ do {
+ // FIXME: don't need to clear dirty region if layer tree is opaque.
+
+ WKCACFUpdateRectEnumerator* e = wkCACFContextCopyUpdateRectEnumerator(m_context);
+ if (!e)
+ break;
+
+ Vector<D3DRECT, 64> rects;
+ for (const CGRect* r = wkCACFUpdateRectEnumeratorNextRect(e); r; r = wkCACFUpdateRectEnumeratorNextRect(e)) {
+ D3DRECT rect;
+ rect.x1 = r->origin.x;
+ rect.x2 = rect.x1 + r->size.width;
+ rect.y1 = bounds.origin.y + bounds.size.height - (r->origin.y + r->size.height);
+ rect.y2 = rect.y1 + r->size.height;
+
+ rects.append(rect);
+ }
+ wkCACFUpdateRectEnumeratorRelease(e);
+
+ timeToNextRender = wkCACFContextGetNextUpdateTime(m_context);
+
+ if (rects.isEmpty())
+ break;
+
+ m_d3dDevice->Clear(rects.size(), rects.data(), D3DCLEAR_TARGET, 0, 1.0f, 0);
+
+ m_d3dDevice->BeginScene();
+ wkCACFContextRenderUpdate(m_context);
+ m_d3dDevice->EndScene();
+
+ err = m_d3dDevice->Present(0, 0, 0, 0);
+
+ if (err == D3DERR_DEVICELOST) {
+ wkCACFContextAddUpdateRect(m_context, bounds);
+ if (!resetDevice(LostDevice)) {
+ // We can't reset the device right now. Try again soon.
+ renderSoon();
+ return;
+ }
+ }
+ } while (err == D3DERR_DEVICELOST);
+
+ wkCACFContextFinishUpdate(m_context);
+
+#ifndef NDEBUG
+ if (m_printTree)
+ rootLayer()->printTree();
+#endif
+
+ // If timeToNextRender is not infinity, it means animations are running, so queue up to render again
+ if (timeToNextRender != numeric_limits<CFTimeInterval>::infinity())
+ renderSoon();
+}
+
+void LegacyCACFLayerTreeHost::renderSoon()
+{
+ if (!m_renderTimer.isActive())
+ m_renderTimer.startOneShot(0);
+}
+
+void LegacyCACFLayerTreeHost::flushContext()
+{
+ wkCACFContextFlush(m_context);
+ contextDidChange();
+}
+
+void LegacyCACFLayerTreeHost::contextDidChange()
+{
+ renderSoon();
+ CACFLayerTreeHost::contextDidChange();
+}
+
+CFTimeInterval LegacyCACFLayerTreeHost::lastCommitTime() const
+{
+ return wkCACFContextGetLastCommitTime(m_context);
+}
+
+void LegacyCACFLayerTreeHost::initD3DGeometry()
+{
+ ASSERT(m_d3dDevice);
+
+ CGRect bounds = this->bounds();
+
+ float x0 = bounds.origin.x;
+ float y0 = bounds.origin.y;
+ float x1 = x0 + bounds.size.width;
+ float y1 = y0 + bounds.size.height;
+
+ D3DXMATRIXA16 projection;
+ D3DXMatrixOrthoOffCenterRH(&projection, x0, x1, y0, y1, -1.0f, 1.0f);
+
+ m_d3dDevice->SetTransform(D3DTS_PROJECTION, &projection);
+}
+
+bool LegacyCACFLayerTreeHost::resetDevice(ResetReason reason)
+{
+ ASSERT(m_d3dDevice);
+ ASSERT(m_context);
+
+ HRESULT hr = m_d3dDevice->TestCooperativeLevel();
+
+ if (hr == D3DERR_DEVICELOST || hr == D3DERR_DRIVERINTERNALERROR) {
+ // The device cannot be reset at this time. Try again soon.
+ m_mustResetLostDeviceBeforeRendering = true;
+ return false;
+ }
+
+ m_mustResetLostDeviceBeforeRendering = false;
+
+ if (reason == LostDevice && hr == D3D_OK) {
+ // The device wasn't lost after all.
+ return true;
+ }
+
+ // We can reset the device.
+
+ // We have to release the context's D3D resrouces whenever we reset the IDirect3DDevice9 in order to
+ // destroy any D3DPOOL_DEFAULT resources that Core Animation has allocated (e.g., textures used
+ // for mask layers). See <http://msdn.microsoft.com/en-us/library/bb174425(v=VS.85).aspx>.
+ wkCACFContextReleaseD3DResources(m_context);
+
+ D3DPRESENT_PARAMETERS parameters = initialPresentationParameters();
+ hr = m_d3dDevice->Reset(&parameters);
+
+ // TestCooperativeLevel told us the device may be reset now, so we should
+ // not be told here that the device is lost.
+ ASSERT(hr != D3DERR_DEVICELOST);
+
+ initD3DGeometry();
+
+ return true;
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/ca/win/LegacyCACFLayerTreeHost.h b/Source/WebCore/platform/graphics/ca/win/LegacyCACFLayerTreeHost.h
new file mode 100644
index 0000000..bfa530b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/ca/win/LegacyCACFLayerTreeHost.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 LegacyCACFLayerTreeHost_h
+#define LegacyCACFLayerTreeHost_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "CACFLayerTreeHost.h"
+
+namespace WebCore {
+
+// FIXME: Currently there is a LegacyCACFLayerTreeHost for each WebView and each
+// has its own WKCACFContext and Direct3DDevice9, which is inefficient.
+// (https://bugs.webkit.org/show_bug.cgi?id=31855)
+class LegacyCACFLayerTreeHost : public CACFLayerTreeHost {
+public:
+ static PassRefPtr<LegacyCACFLayerTreeHost> create();
+ virtual ~LegacyCACFLayerTreeHost();
+
+private:
+ LegacyCACFLayerTreeHost();
+
+ void initD3DGeometry();
+
+ // Call this when the device window has changed size or when IDirect3DDevice9::Present returns
+ // D3DERR_DEVICELOST. Returns true if the device was recovered, false if rendering must be
+ // aborted and reattempted soon.
+ enum ResetReason { ChangedWindowSize, LostDevice };
+ bool resetDevice(ResetReason);
+
+ void renderSoon();
+ void renderTimerFired(Timer<LegacyCACFLayerTreeHost>*);
+
+ virtual void initializeContext(void* userData, PlatformCALayer*);
+ virtual void resize();
+ virtual bool createRenderer();
+ virtual void destroyRenderer();
+ virtual CFTimeInterval lastCommitTime() const;
+ virtual void flushContext();
+ virtual void contextDidChange();
+ virtual void paint();
+ virtual void render(const Vector<CGRect>& dirtyRects = Vector<CGRect>());
+
+ Timer<LegacyCACFLayerTreeHost> m_renderTimer;
+ COMPtr<IDirect3DDevice9> m_d3dDevice;
+ WKCACFContext* m_context;
+ bool m_mightBeAbleToCreateDeviceLater;
+ bool m_mustResetLostDeviceBeforeRendering;
+
+#ifndef NDEBUG
+ bool m_printTree;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // LegacyCACFLayerTreeHost_h
diff --git a/Source/WebCore/platform/graphics/ca/win/PlatformCAAnimationWin.cpp b/Source/WebCore/platform/graphics/ca/win/PlatformCAAnimationWin.cpp
index 228bb01..6e3011b 100644
--- a/Source/WebCore/platform/graphics/ca/win/PlatformCAAnimationWin.cpp
+++ b/Source/WebCore/platform/graphics/ca/win/PlatformCAAnimationWin.cpp
@@ -145,11 +145,6 @@ PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(PlatformAnimationRef
return adoptRef(new PlatformCAAnimation(animation));
}
-PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(const PlatformCAAnimation* animation)
-{
- return adoptRef(new PlatformCAAnimation(animation));
-}
-
PlatformCAAnimation::PlatformCAAnimation(AnimationType type, const String& keyPath)
: m_type(type)
{
@@ -176,33 +171,33 @@ PlatformCAAnimation::PlatformCAAnimation(PlatformAnimationRef animation)
m_animation = animation;
}
-PlatformCAAnimation::PlatformCAAnimation(const PlatformCAAnimation* animation)
+PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::copy() const
{
- m_animation.adoptCF(CACFAnimationCreate((animation->animationType() == Basic) ? kCACFBasicAnimation : kCACFKeyframeAnimation));
- RetainPtr<CFStringRef> keyPath(AdoptCF, animation->keyPath().createCFString());
- CACFAnimationSetKeyPath(m_animation.get(), keyPath.get());
-
- setBeginTime(animation->beginTime());
- setDuration(animation->duration());
- setSpeed(animation->speed());
- setTimeOffset(animation->timeOffset());
- setRepeatCount(animation->repeatCount());
- setAutoreverses(animation->autoreverses());
- setFillMode(animation->fillMode());
- setRemovedOnCompletion(animation->isRemovedOnCompletion());
- setAdditive(animation->isAdditive());
- copyTimingFunctionFrom(animation);
- setValueFunction(animation->valueFunction());
-
+ RefPtr<PlatformCAAnimation> animation = create(animationType(), keyPath());
+
+ animation->setBeginTime(beginTime());
+ animation->setDuration(duration());
+ animation->setSpeed(speed());
+ animation->setTimeOffset(timeOffset());
+ animation->setRepeatCount(repeatCount());
+ animation->setAutoreverses(autoreverses());
+ animation->setFillMode(fillMode());
+ animation->setRemovedOnCompletion(isRemovedOnCompletion());
+ animation->setAdditive(isAdditive());
+ animation->copyTimingFunctionFrom(this);
+ animation->setValueFunction(valueFunction());
+
// Copy the specific Basic or Keyframe values
- if (animation->animationType() == Keyframe) {
- copyValuesFrom(animation);
- copyKeyTimesFrom(animation);
- copyTimingFunctionsFrom(animation);
+ if (animationType() == Keyframe) {
+ animation->copyValuesFrom(this);
+ animation->copyKeyTimesFrom(this);
+ animation->copyTimingFunctionsFrom(this);
} else {
- copyFromValueFrom(animation);
- copyToValueFrom(animation);
+ animation->copyFromValueFrom(this);
+ animation->copyToValueFrom(this);
}
+
+ return animation;
}
PlatformCAAnimation::~PlatformCAAnimation()
diff --git a/Source/WebCore/platform/graphics/ca/win/WKCACFViewLayerTreeHost.cpp b/Source/WebCore/platform/graphics/ca/win/WKCACFViewLayerTreeHost.cpp
new file mode 100644
index 0000000..e672c2d
--- /dev/null
+++ b/Source/WebCore/platform/graphics/ca/win/WKCACFViewLayerTreeHost.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WKCACFViewLayerTreeHost.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "PlatformCALayer.h"
+#include "SoftLinking.h"
+#include <wtf/CurrentTime.h>
+
+typedef struct _CACFLayer* CACFLayerRef;
+
+namespace WebCore {
+
+#ifdef DEBUG_ALL
+SOFT_LINK_DEBUG_LIBRARY(WebKitQuartzCoreAdditions)
+#else
+SOFT_LINK_LIBRARY(WebKitQuartzCoreAdditions)
+#endif
+
+SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewCreate, WKCACFViewRef, __cdecl, (), ())
+SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewSetLayer, void, __cdecl, (WKCACFViewRef view, CACFLayerRef layer), (view, layer))
+SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewUpdate, void, __cdecl, (WKCACFViewRef view, HWND window, const CGRect* bounds), (view, window, bounds))
+SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewCanDraw, bool, __cdecl, (WKCACFViewRef view), (view))
+SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewDraw, void, __cdecl, (WKCACFViewRef view), (view))
+SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewFlushContext, void, __cdecl, (WKCACFViewRef view), (view))
+SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewInvalidateRects, void, __cdecl, (WKCACFViewRef view, const CGRect rects[], size_t count), (view, rects, count))
+typedef void (*WKCACFViewContextDidChangeCallback)(WKCACFViewRef view, void* info);
+SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewSetContextDidChangeCallback, void, __cdecl, (WKCACFViewRef view, WKCACFViewContextDidChangeCallback callback, void* info), (view, callback, info))
+SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewGetLastCommitTime, CFTimeInterval, __cdecl, (WKCACFViewRef view), (view))
+SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewSetContextUserData, void, __cdecl, (WKCACFViewRef view, void* userData), (view, userData))
+
+PassRefPtr<WKCACFViewLayerTreeHost> WKCACFViewLayerTreeHost::create()
+{
+ if (!WebKitQuartzCoreAdditionsLibrary())
+ return 0;
+
+ return adoptRef(new WKCACFViewLayerTreeHost);
+}
+
+WKCACFViewLayerTreeHost::WKCACFViewLayerTreeHost()
+ : m_view(AdoptCF, WKCACFViewCreate())
+ , m_viewNeedsUpdate(true)
+{
+}
+
+void WKCACFViewLayerTreeHost::updateViewIfNeeded()
+{
+ if (!m_viewNeedsUpdate)
+ return;
+ m_viewNeedsUpdate = false;
+
+ CGRect layerBounds = rootLayer()->bounds();
+
+ CGRect bounds = this->bounds();
+ WKCACFViewUpdate(m_view.get(), window(), &bounds);
+
+ if (CGRectEqualToRect(layerBounds, rootLayer()->bounds()))
+ return;
+
+ // Flush the context so the layer's rendered bounds will match our bounds.
+ flushContext();
+}
+
+void WKCACFViewLayerTreeHost::contextDidChangeCallback(WKCACFViewRef view, void* info)
+{
+ ASSERT_ARG(view, view);
+ ASSERT_ARG(info, info);
+
+ WKCACFViewLayerTreeHost* host = static_cast<WKCACFViewLayerTreeHost*>(info);
+ ASSERT_ARG(view, view == host->m_view);
+ host->contextDidChange();
+}
+
+void WKCACFViewLayerTreeHost::contextDidChange()
+{
+ // Tell the WKCACFView to start rendering now that we have some contents to render.
+ updateViewIfNeeded();
+
+ CACFLayerTreeHost::contextDidChange();
+}
+
+void WKCACFViewLayerTreeHost::initializeContext(void* userData, PlatformCALayer* layer)
+{
+ WKCACFViewSetContextUserData(m_view.get(), userData);
+ WKCACFViewSetLayer(m_view.get(), layer->platformLayer());
+ WKCACFViewSetContextDidChangeCallback(m_view.get(), contextDidChangeCallback, this);
+}
+
+void WKCACFViewLayerTreeHost::resize()
+{
+ m_viewNeedsUpdate = true;
+}
+
+bool WKCACFViewLayerTreeHost::createRenderer()
+{
+ updateViewIfNeeded();
+ return WKCACFViewCanDraw(m_view.get());
+}
+
+void WKCACFViewLayerTreeHost::destroyRenderer()
+{
+ m_viewNeedsUpdate = true;
+ WKCACFViewUpdate(m_view.get(), 0, 0);
+ WKCACFViewSetContextUserData(m_view.get(), 0);
+ WKCACFViewSetLayer(m_view.get(), 0);
+ WKCACFViewSetContextDidChangeCallback(m_view.get(), 0, 0);
+
+ CACFLayerTreeHost::destroyRenderer();
+}
+
+CFTimeInterval WKCACFViewLayerTreeHost::lastCommitTime() const
+{
+ return WKCACFViewGetLastCommitTime(m_view.get());
+}
+
+void WKCACFViewLayerTreeHost::flushContext()
+{
+ WKCACFViewFlushContext(m_view.get());
+}
+
+void WKCACFViewLayerTreeHost::paint()
+{
+ updateViewIfNeeded();
+ CACFLayerTreeHost::paint();
+}
+
+void WKCACFViewLayerTreeHost::render(const Vector<CGRect>& dirtyRects)
+{
+ WKCACFViewInvalidateRects(m_view.get(), dirtyRects.data(), dirtyRects.size());
+ WKCACFViewDraw(m_view.get());
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/ca/win/WKCACFViewLayerTreeHost.h b/Source/WebCore/platform/graphics/ca/win/WKCACFViewLayerTreeHost.h
new file mode 100644
index 0000000..af09f76
--- /dev/null
+++ b/Source/WebCore/platform/graphics/ca/win/WKCACFViewLayerTreeHost.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 WKCACFViewLayerTreeHost_h
+#define WKCACFViewLayerTreeHost_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "CACFLayerTreeHost.h"
+
+typedef struct _WKCACFView* WKCACFViewRef;
+
+namespace WebCore {
+
+class WKCACFViewLayerTreeHost : public CACFLayerTreeHost {
+public:
+ static PassRefPtr<WKCACFViewLayerTreeHost> create();
+
+private:
+ WKCACFViewLayerTreeHost();
+
+ void updateViewIfNeeded();
+ static void contextDidChangeCallback(WKCACFViewRef, void* info);
+
+ virtual void initializeContext(void* userData, PlatformCALayer*);
+ virtual void resize();
+ virtual bool createRenderer();
+ virtual void destroyRenderer();
+ virtual void flushContext();
+ virtual void contextDidChange();
+ virtual void paint();
+ virtual void render(const Vector<CGRect>& dirtyRects = Vector<CGRect>());
+ virtual CFTimeInterval lastCommitTime() const;
+
+ RetainPtr<WKCACFViewRef> m_view;
+ bool m_viewNeedsUpdate;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // WKCACFViewLayerTreeHost_h
diff --git a/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp b/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp
index 013a4af..ee159a1 100644
--- a/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp
+++ b/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp
@@ -106,7 +106,11 @@ cairo_operator_t toCairoOperator(CompositeOperator op)
case CompositeXOR:
return CAIRO_OPERATOR_XOR;
case CompositePlusDarker:
+#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0)
+ return CAIRO_OPERATOR_DARKEN;
+#else
return CAIRO_OPERATOR_SATURATE;
+#endif
case CompositeHighlight:
// There is no Cairo equivalent for CompositeHighlight.
return CAIRO_OPERATOR_OVER;
diff --git a/Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h
index 50ea00f..5807102 100644
--- a/Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h
+++ b/Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h
@@ -24,6 +24,7 @@
#include "FontOrientation.h"
#include "FontRenderingMode.h"
+#include "FontWidthVariant.h"
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
@@ -40,7 +41,7 @@ struct FontCustomPlatformData {
public:
FontCustomPlatformData(FT_Face, SharedBuffer*);
~FontCustomPlatformData();
- FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontRenderingMode = NormalRenderingMode);
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
static bool supportsFormat(const String&);
private:
diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
index 51b5ee6..f7d6040 100644
--- a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
@@ -173,7 +173,7 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& d
destx = -originx;
originx = 0;
}
- int endx = rect.right();
+ int endx = rect.maxX();
if (endx > size.width())
endx = size.width();
int numColumns = endx - originx;
@@ -184,7 +184,7 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& d
desty = -originy;
originy = 0;
}
- int endy = rect.bottom();
+ int endy = rect.maxY();
if (endy > size.height())
endy = size.height();
int numRows = endy - originy;
@@ -239,9 +239,9 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
ASSERT(destx >= 0);
ASSERT(destx < size.width());
ASSERT(originx >= 0);
- ASSERT(originx <= sourceRect.right());
+ ASSERT(originx <= sourceRect.maxX());
- int endx = destPoint.x() + sourceRect.right();
+ int endx = destPoint.x() + sourceRect.maxX();
ASSERT(endx <= size.width());
int numColumns = endx - destx;
@@ -251,9 +251,9 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
ASSERT(desty >= 0);
ASSERT(desty < size.height());
ASSERT(originy >= 0);
- ASSERT(originy <= sourceRect.bottom());
+ ASSERT(originy <= sourceRect.maxY());
- int endy = destPoint.y() + sourceRect.bottom();
+ int endy = destPoint.y() + sourceRect.maxY();
ASSERT(endy <= size.height());
int numRows = endy - desty;
diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
index c19bd72..187d296 100644
--- a/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
@@ -26,7 +26,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
#include "GraphicsContext3D.h"
#include "GraphicsContextCG.h"
@@ -105,7 +105,7 @@ bool GraphicsContext3D::getImageData(Image* image,
decoder.setData(image->data(), true);
if (!decoder.frameCount())
return false;
- decodedImage = decoder.createFrameAtIndex(0);
+ decodedImage.adoptCF(decoder.createFrameAtIndex(0));
cgImage = decodedImage.get();
} else
cgImage = image->nativeImageForCurrentFrame();
@@ -116,6 +116,34 @@ bool GraphicsContext3D::getImageData(Image* image,
size_t height = CGImageGetHeight(cgImage);
if (!width || !height)
return false;
+
+ // See whether the image is using an indexed color space, and if
+ // so, re-render it into an RGB color space. The image re-packing
+ // code requires color data, not color table indices, for the
+ // image data.
+ CGColorSpaceRef colorSpace = CGImageGetColorSpace(cgImage);
+ CGColorSpaceModel model = CGColorSpaceGetModel(colorSpace);
+ if (model == kCGColorSpaceModelIndexed) {
+ RetainPtr<CGContextRef> bitmapContext;
+ // FIXME: we should probably manually convert the image by indexing into
+ // the color table, which would allow us to avoid premultiplying the
+ // alpha channel. Creation of a bitmap context with an alpha channel
+ // doesn't seem to work unless it's premultiplied.
+ bitmapContext.adoptCF(CGBitmapContextCreate(0, width, height, 8, width * 4,
+ deviceRGBColorSpaceRef(),
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
+ if (!bitmapContext)
+ return false;
+
+ CGContextSetBlendMode(bitmapContext.get(), kCGBlendModeCopy);
+ CGContextSetInterpolationQuality(bitmapContext.get(), kCGInterpolationNone);
+ CGContextDrawImage(bitmapContext.get(), CGRectMake(0, 0, width, height), cgImage);
+
+ // Now discard the original CG image and replace it with a copy from the bitmap context.
+ decodedImage.adoptCF(CGBitmapContextCreateImage(bitmapContext.get()));
+ cgImage = decodedImage.get();
+ }
+
size_t bitsPerComponent = CGImageGetBitsPerComponent(cgImage);
size_t bitsPerPixel = CGImageGetBitsPerPixel(cgImage);
if (bitsPerComponent != 8 && bitsPerComponent != 16)
@@ -168,10 +196,11 @@ bool GraphicsContext3D::getImageData(Image* image,
AlphaFormat alphaFormat = AlphaFormatNone;
switch (CGImageGetAlphaInfo(cgImage)) {
case kCGImageAlphaPremultipliedFirst:
- // This path is only accessible for MacOS earlier than 10.6.4.
// This is a special case for texImage2D with HTMLCanvasElement input,
- // in which case image->data() should be null.
- ASSERT(!image->data());
+ // in which case image->data() should be null, or indexed color models,
+ // where we need premultiplied alpha to create the bitmap context
+ // successfully.
+ ASSERT(!image->data() || model == kCGColorSpaceModelIndexed);
if (!premultiplyAlpha)
neededAlphaOp = AlphaDoUnmultiply;
alphaFormat = AlphaFormatFirst;
@@ -254,4 +283,4 @@ void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imag
} // namespace WebCore
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index bcfc37b..3591479 100644
--- a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -35,6 +35,7 @@
#include "KURL.h"
#include "Path.h"
#include "Pattern.h"
+#include "ShadowBlur.h"
#include <CoreGraphics/CoreGraphics.h>
#include <wtf/MathExtras.h>
@@ -165,9 +166,9 @@ void GraphicsContext::drawRect(const IntRect& rect)
setCGFillColor(context, strokeColor(), strokeColorSpace());
CGRect rects[4] = {
FloatRect(rect.x(), rect.y(), rect.width(), 1),
- FloatRect(rect.x(), rect.bottom() - 1, rect.width(), 1),
+ FloatRect(rect.x(), rect.maxY() - 1, rect.width(), 1),
FloatRect(rect.x(), rect.y() + 1, 1, rect.height() - 2),
- FloatRect(rect.right() - 1, rect.y() + 1, 1, rect.height() - 2)
+ FloatRect(rect.maxX() - 1, rect.y() + 1, 1, rect.height() - 2)
};
CGContextFillRects(context, rects, 4);
if (oldFillColor != strokeColor())
@@ -563,7 +564,7 @@ void GraphicsContext::fillPath(const Path& path)
CGContextClip(layerContext);
m_state.fillGradient->paint(layerContext);
- CGContextDrawLayerAtPoint(context, CGPointMake(rect.left(), rect.top()), layer);
+ CGContextDrawLayerAtPoint(context, CGPointMake(rect.x(), rect.y()), layer);
CGLayerRelease(layer);
} else {
CGContextBeginPath(context);
@@ -616,6 +617,16 @@ void GraphicsContext::strokePath(const Path& path)
CGContextStrokePath(context);
}
+static float radiusToLegacyRadius(float radius)
+{
+ return radius > 8 ? 8 + 4 * sqrt((radius - 8) / 2) : radius;
+}
+
+static bool hasBlurredShadow(const GraphicsContextState& state)
+{
+ return state.shadowColor.isValid() && state.shadowColor.alpha() && state.shadowBlur;
+}
+
void GraphicsContext::fillRect(const FloatRect& rect)
{
if (paintingDisabled())
@@ -626,11 +637,16 @@ void GraphicsContext::fillRect(const FloatRect& rect)
if (m_state.fillGradient) {
CGContextSaveGState(context);
if (hasShadow()) {
- CGContextConcatCTM(context, m_state.fillGradient->gradientSpaceTransform());
CGLayerRef layer = CGLayerCreateWithContext(context, CGSizeMake(rect.width(), rect.height()), 0);
CGContextRef layerContext = CGLayerGetContext(layer);
+
+ CGContextTranslateCTM(layerContext, -rect.x(), -rect.y());
+ CGContextAddRect(layerContext, rect);
+ CGContextClip(layerContext);
+
+ CGContextConcatCTM(layerContext, m_state.fillGradient->gradientSpaceTransform());
m_state.fillGradient->paint(layerContext);
- CGContextDrawLayerAtPoint(context, CGPointMake(rect.left(), rect.top()), layer);
+ CGContextDrawLayerAtPoint(context, CGPointMake(rect.x(), rect.y()), layer);
CGLayerRelease(layer);
} else {
CGContextClipToRect(context, rect);
@@ -643,7 +659,22 @@ 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.
+ if (drawOwnShadow) {
+ float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur;
+ // Turn off CG shadows.
+ CGContextSaveGState(context);
+ CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
+
+ ShadowBlur contextShadow(shadowBlur, m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace);
+ contextShadow.drawRectShadow(this, rect, RoundedIntRect::Radii());
+ }
+
CGContextFillRect(context, rect);
+
+ if (drawOwnShadow)
+ CGContextRestoreGState(context);
}
void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
@@ -658,7 +689,21 @@ 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.
+ if (drawOwnShadow) {
+ float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur;
+ // Turn off CG shadows.
+ CGContextSaveGState(context);
+ CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
+
+ ShadowBlur contextShadow(shadowBlur, m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace);
+ contextShadow.drawRectShadow(this, rect, RoundedIntRect::Radii());
+ }
+
CGContextFillRect(context, rect);
+
+ if (drawOwnShadow)
+ CGContextRestoreGState(context);
if (oldFillColor != color || oldColorSpace != colorSpace)
setCGFillColor(context, oldFillColor, oldColorSpace);
@@ -678,12 +723,72 @@ 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.
+ if (drawOwnShadow) {
+ float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur;
+
+ // Turn off CG shadows.
+ CGContextSaveGState(context);
+ CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
+
+ ShadowBlur contextShadow(shadowBlur, m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace);
+ contextShadow.drawRectShadow(this, rect, RoundedIntRect::Radii(topLeft, topRight, bottomLeft, bottomRight));
+ }
+
fillPath(path);
+ if (drawOwnShadow)
+ CGContextRestoreGState(context);
+
if (oldFillColor != color || oldColorSpace != colorSpace)
setCGFillColor(context, oldFillColor, oldColorSpace);
}
+void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const RoundedIntRect& roundedHoleRect, const Color& color, ColorSpace colorSpace)
+{
+ if (paintingDisabled())
+ return;
+
+ CGContextRef context = platformContext();
+
+ Path path;
+ path.addRect(rect);
+
+ if (!roundedHoleRect.radii().isZero())
+ path.addRoundedRect(roundedHoleRect.rect(), roundedHoleRect.radii().topLeft(), roundedHoleRect.radii().topRight(), roundedHoleRect.radii().bottomLeft(), roundedHoleRect.radii().bottomRight());
+ else
+ path.addRect(roundedHoleRect.rect());
+
+ WindRule oldFillRule = fillRule();
+ Color oldFillColor = fillColor();
+ ColorSpace oldFillColorSpace = fillColorSpace();
+
+ setFillRule(RULE_EVENODD);
+ 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;
+ if (drawOwnShadow) {
+ float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur;
+
+ // Turn off CG shadows.
+ CGContextSaveGState(context);
+ CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
+
+ ShadowBlur contextShadow(shadowBlur, m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace);
+ contextShadow.drawInsetShadow(this, rect, roundedHoleRect.rect(), roundedHoleRect.radii());
+ }
+
+ fillPath(path);
+
+ if (drawOwnShadow)
+ CGContextRestoreGState(context);
+
+ setFillRule(oldFillRule);
+ setFillColor(oldFillColor, oldFillColorSpace);
+}
+
void GraphicsContext::clip(const FloatRect& rect)
{
if (paintingDisabled())
@@ -722,6 +827,11 @@ void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
CGContextClip(context);
}
+IntRect GraphicsContext::clipBounds() const
+{
+ return enclosingIntRect(CGContextGetClipBoundingBox(platformContext()));
+}
+
void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
{
if (paintingDisabled())
@@ -766,6 +876,9 @@ void GraphicsContext::setPlatformShadow(const FloatSize& offset, float blur, con
{
if (paintingDisabled())
return;
+
+ // FIXME: we could avoid the shadow setup cost when we know we'll render the shadow ourselves.
+
CGFloat xOffset = offset.width();
CGFloat yOffset = offset.height();
CGFloat blurRadius = blur;
diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
index 295f632..ab5907e 100644
--- a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -267,7 +267,7 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& i
RefPtr<ByteArray> result = ByteArray::create(rect.width() * rect.height() * 4);
unsigned char* data = result->data();
- if (rect.x() < 0 || rect.y() < 0 || rect.right() > size.width() || rect.bottom() > size.height())
+ if (rect.x() < 0 || rect.y() < 0 || rect.maxX() > size.width() || rect.maxY() > size.height())
memset(data, 0, result->length());
int originx = rect.x();
@@ -276,7 +276,7 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& i
destx = -originx;
originx = 0;
}
- int endx = rect.right();
+ int endx = rect.maxX();
if (endx > size.width())
endx = size.width();
int numColumns = endx - originx;
@@ -287,7 +287,7 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& i
desty = -originy;
originy = 0;
}
- int endy = rect.bottom();
+ int endy = rect.maxY();
if (endy > size.height())
endy = size.height();
int numRows = endy - originy;
@@ -377,9 +377,9 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
ASSERT(destx >= 0);
ASSERT(destx < size.width());
ASSERT(originx >= 0);
- ASSERT(originx <= sourceRect.right());
+ ASSERT(originx <= sourceRect.maxX());
- int endx = destPoint.x() + sourceRect.right();
+ int endx = destPoint.x() + sourceRect.maxX();
ASSERT(endx <= size.width());
int numColumns = endx - destx;
@@ -389,9 +389,9 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
ASSERT(desty >= 0);
ASSERT(desty < size.height());
ASSERT(originy >= 0);
- ASSERT(originy <= sourceRect.bottom());
+ ASSERT(originy <= sourceRect.maxY());
- int endy = destPoint.y() + sourceRect.bottom();
+ int endy = destPoint.y() + sourceRect.maxY();
ASSERT(endy <= size.height());
int numRows = endy - desty;
diff --git a/Source/WebCore/platform/graphics/cg/ImageCG.cpp b/Source/WebCore/platform/graphics/cg/ImageCG.cpp
index dfee96a..08f65bd 100644
--- a/Source/WebCore/platform/graphics/cg/ImageCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageCG.cpp
@@ -204,7 +204,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const F
adjustedDestRect.setHeight(subimageRect.height() / yScale);
image.adoptCF(CGImageCreateWithImageInRect(image.get(), subimageRect));
- if (currHeight < srcRect.bottom()) {
+ if (currHeight < srcRect.maxY()) {
ASSERT(CGImageGetHeight(image.get()) == currHeight - CGRectIntegral(srcRect).origin.y);
adjustedDestRect.setHeight(CGImageGetHeight(image.get()) / yScale);
}
@@ -224,7 +224,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const F
// Flip the coords.
CGContextScaleCTM(context, 1, -1);
- adjustedDestRect.setY(-adjustedDestRect.bottom());
+ adjustedDestRect.setY(-adjustedDestRect.maxY());
// Adjust the color space.
image = imageWithColorSpace(image.get(), styleColorSpace);
diff --git a/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp b/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp
index 92861fc..4598602 100644
--- a/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp
+++ b/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp
@@ -146,7 +146,10 @@ void ComplexTextController::reset(unsigned offset)
// TextRun has been reached.
bool ComplexTextController::nextScriptRun()
{
- if (!hb_utf16_script_run_next(&m_numCodePoints, &m_item.item, m_run.characters(), m_run.length(), &m_indexOfNextScriptRun))
+ // Ensure we're not pointing at the small caps buffer.
+ m_item.string = m_run.characters();
+
+ if (!hb_utf16_script_run_next(0, &m_item.item, m_run.characters(), m_run.length(), &m_indexOfNextScriptRun))
return false;
// It is actually wrong to consider script runs at all in this code.
@@ -184,11 +187,33 @@ float ComplexTextController::widthOfFullRun()
void ComplexTextController::setupFontForScriptRun()
{
- const FontData* fontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false).fontData;
+ FontDataVariant fontDataVariant = AutoVariant;
+ // Determine if this script run needs to be converted to small caps.
+ // nextScriptRun() will always send us a run of the same case, because a
+ // case change while in small-caps mode always results in different
+ // FontData, so we only need to check the first character's case.
+ if (m_font->isSmallCaps() && u_islower(m_item.string[m_item.item.pos])) {
+ m_smallCapsString = String(m_run.data(m_item.item.pos), m_item.item.length);
+ m_smallCapsString.makeUpper();
+ m_item.string = m_smallCapsString.characters();
+ m_item.item.pos = 0;
+ fontDataVariant = SmallCapsVariant;
+ }
+ const FontData* fontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false, fontDataVariant).fontData;
const FontPlatformData& platformData = fontData->fontDataForCharacter(' ')->platformData();
m_item.face = platformData.harfbuzzFace();
void* opaquePlatformData = const_cast<FontPlatformData*>(&platformData);
m_item.font->userData = opaquePlatformData;
+
+ int size = platformData.size();
+ m_item.font->x_ppem = size;
+ m_item.font->y_ppem = size;
+ // x_ and y_scale are the conversion factors from font design space (fEmSize) to 1/64th of device pixels in 16.16 format.
+ const int devicePixelFraction = 64;
+ const int multiplyFor16Dot16 = 1 << 16;
+ int scale = devicePixelFraction * size * multiplyFor16Dot16 / platformData.emSizeInFontUnits();
+ m_item.font->x_scale = scale;
+ m_item.font->y_scale = scale;
}
HB_FontRec* ComplexTextController::allocHarfbuzzFont()
@@ -197,13 +222,6 @@ HB_FontRec* ComplexTextController::allocHarfbuzzFont()
memset(font, 0, sizeof(HB_FontRec));
font->klass = &harfbuzzSkiaClass;
font->userData = 0;
- // The values which harfbuzzSkiaClass returns are already scaled to
- // pixel units, so we just set all these to one to disable further
- // scaling.
- font->x_ppem = 1;
- font->y_ppem = 1;
- font->x_scale = 1;
- font->y_scale = 1;
return font;
}
@@ -369,7 +387,7 @@ const TextRun& ComplexTextController::getNormalizedTextRun(const TextRun& origin
sourceText = normalizedString.getBuffer();
}
- normalizedBuffer.set(new UChar[normalizedBufferLength + 1]);
+ normalizedBuffer = adoptArrayPtr(new UChar[normalizedBufferLength + 1]);
normalizeSpacesAndMirrorChars(sourceText, originalRun.rtl(), normalizedBuffer.get(), normalizedBufferLength);
diff --git a/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.h b/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.h
index a2aea60..6a93878 100644
--- a/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.h
+++ b/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.h
@@ -111,7 +111,7 @@ public:
const unsigned short* logClusters() const { return m_item.log_clusters; }
// return the number of code points in the current script run
- const unsigned numCodePoints() const { return m_numCodePoints; }
+ const unsigned numCodePoints() const { return m_item.item.length; }
// Return the current pixel position of the controller.
const unsigned offsetX() const { return m_offsetX; }
@@ -141,7 +141,6 @@ private:
ssize_t m_indexOfNextScriptRun; // Indexes the script run in |m_run|.
unsigned m_offsetX; // Offset in pixels to the start of the next script run.
unsigned m_pixelWidth; // Width (in px) of the current script run.
- unsigned m_numCodePoints; // Code points in current script run.
unsigned m_glyphsArrayCapacity; // Current size of all the Harfbuzz arrays.
OwnPtr<TextRun> m_normalizedRun;
@@ -155,6 +154,7 @@ private:
// each word break we accumulate error. This is the
// number of pixels that we are behind so far.
int m_letterSpacing; // pixels to be added after each glyph.
+ String m_smallCapsString; // substring of m_run converted to small caps.
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
index d00faf8..a38f6bd 100644
--- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
@@ -343,7 +343,7 @@ void ContentLayerChromium::draw()
ASSERT(sv && sv->initialized());
GraphicsContext3D* context = layerRendererContext();
GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
- m_contentsTexture->bindTexture();
+ bindContentsTexture();
layerRenderer()->useShader(sv->contentShaderProgram());
GLC(context, context->uniform1i(sv->shaderSamplerLocation(), 0));
@@ -361,8 +361,21 @@ void ContentLayerChromium::draw()
drawOpacity(), sv->shaderMatrixLocation(),
sv->shaderAlphaLocation());
}
- m_contentsTexture->unreserve();
+ unreserveContentsTexture();
+}
+
+void ContentLayerChromium::unreserveContentsTexture()
+{
+ if (m_contentsTexture)
+ m_contentsTexture->unreserve();
}
+void ContentLayerChromium::bindContentsTexture()
+{
+ if (m_contentsTexture)
+ m_contentsTexture->bindTexture();
+}
+
+
}
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h
index dc1630b..3363518 100644
--- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h
@@ -50,6 +50,9 @@ public:
virtual ~ContentLayerChromium();
virtual void updateContentsIfDirty();
+ virtual void unreserveContentsTexture();
+ virtual void bindContentsTexture();
+
virtual void draw();
virtual bool drawsContent() { return m_owner && m_owner->drawsContent(); }
diff --git a/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
index 2d4ca41..d956841 100644
--- a/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
@@ -36,12 +36,20 @@
#include "GraphicsContext3D.h"
#include "SharedGraphicsContext3D.h"
+#if ENABLE(SKIA_GPU)
+#include "GrContext.h"
+#endif
+
#if USE(ACCELERATED_COMPOSITING)
#include "Canvas2DLayerChromium.h"
#endif
namespace WebCore {
+#if ENABLE(SKIA_GPU)
+extern GrContext* GetGlobalGrContext();
+#endif
+
struct DrawingBufferInternal {
unsigned offscreenColorTexture;
#if USE(ACCELERATED_COMPOSITING)
@@ -72,7 +80,7 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
bool multisampleExtensionSupported,
bool packedDepthStencilExtensionSupported)
: m_context(context)
- , m_size(-1, -1)
+ , m_size(size)
, m_multisampleExtensionSupported(multisampleExtensionSupported)
, m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupported)
, m_fbo(0)
@@ -119,6 +127,8 @@ void DrawingBuffer::publishToPlatformLayer()
if (m_callback)
m_callback->willPublish();
+ if (multisample())
+ commit();
unsigned parentTexture = m_internal->platformLayer->textureId();
// FIXME: We do the copy in the canvas' (child) context so that it executes in the correct order relative to
// other commands in the child context. This ensures that the parent texture always contains a complete
@@ -126,6 +136,9 @@ void DrawingBuffer::publishToPlatformLayer()
// happens before the compositor draws. This means we might draw stale frames sometimes. Ideally this
// would insert a fence into the child command stream that the compositor could wait for.
m_context->makeContextCurrent();
+#if ENABLE(SKIA_GPU)
+ GetGlobalGrContext()->flush(false);
+#endif
static_cast<Extensions3DChromium*>(m_context->getExtensions())->copyTextureToParentTextureCHROMIUM(m_colorBuffer, parentTexture);
m_context->flush();
}
diff --git a/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h b/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h
index d120424..92fb7b3 100644
--- a/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h
@@ -44,8 +44,8 @@ public:
virtual bool supports(const String&);
virtual void ensureEnabled(const String&);
virtual int getGraphicsResetStatusARB();
- virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter) { }
- virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height) { }
+ virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter);
+ virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height);
enum {
// GL_CHROMIUM_map_sub (enums inherited from GL_ARB_vertex_buffer_object)
diff --git a/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
index f4c0dee..33ebc59 100644
--- a/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
@@ -399,6 +399,28 @@ static int CALLBACK traitsInFamilyEnumProc(CONST LOGFONT* logFont, CONST TEXTMET
return 1;
}
+struct GetLastResortFallbackFontProcData {
+ GetLastResortFallbackFontProcData(FontCache* fontCache, const FontDescription* fontDescription, wchar_t* fontName)
+ : m_fontCache(fontCache)
+ , m_fontDescription(fontDescription)
+ , m_fontName(fontName)
+ , m_fontData(0)
+ {
+ }
+
+ FontCache* m_fontCache;
+ const FontDescription* m_fontDescription;
+ wchar_t* m_fontName;
+ SimpleFontData* m_fontData;
+};
+
+static int CALLBACK getLastResortFallbackFontProc(const LOGFONT* logFont, const TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
+{
+ GetLastResortFallbackFontProcData* procData = reinterpret_cast<GetLastResortFallbackFontProcData*>(lParam);
+ procData->m_fontData = fontDataFromDescriptionAndLogFont(procData->m_fontCache, *procData->m_fontDescription, *logFont, procData->m_fontName);
+ return !procData->m_fontData;
+}
+
void FontCache::platformInit()
{
// Not needed on Windows.
@@ -548,6 +570,21 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& desc
return simpleFont;
}
+ // Fall back to all the fonts installed in this PC. When a font has a
+ // localized name according to the system locale as well as an English name,
+ // both GetTextFace() and EnumFontFamilies() return the localized name. So,
+ // FontCache::createFontPlatformData() does not filter out the fonts
+ // returned by this EnumFontFamilies() call.
+ HDC dc = GetDC(0);
+ if (dc) {
+ GetLastResortFallbackFontProcData procData(this, &description, fallbackFontName);
+ EnumFontFamilies(dc, 0, getLastResortFallbackFontProc, reinterpret_cast<LPARAM>(&procData));
+ ReleaseDC(0, dc);
+
+ if (procData.m_fontData)
+ return procData.m_fontData;
+ }
+
ASSERT_NOT_REACHED();
return 0;
}
diff --git a/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
index 5da4d5a..e57a84c 100644
--- a/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
@@ -246,10 +246,11 @@ IntRect TransparencyAwareGlyphPainter::estimateTextBounds()
for (int i = 0; i < m_numGlyphs; i++)
totalWidth += lroundf(m_glyphBuffer.advanceAt(m_from + i));
- return IntRect(m_point.x() - (m_font->ascent() + m_font->descent()) / 2,
- m_point.y() - m_font->ascent() - m_font->lineGap(),
- totalWidth + m_font->ascent() + m_font->descent(),
- m_font->lineSpacing());
+ const FontMetrics& fontMetrics = m_font->fontMetrics();
+ return IntRect(m_point.x() - (fontMetrics.ascent() + fontMetrics.descent()) / 2,
+ m_point.y() - fontMetrics.ascent() - fontMetrics.lineGap(),
+ totalWidth + fontMetrics.ascent() + fontMetrics.descent(),
+ fontMetrics.lineSpacing());
}
bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs,
@@ -270,7 +271,7 @@ bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs,
// Windows' origin is the top-left of the bounding box, so we have
// to subtract off the font ascent to get it.
int x = lroundf(m_point.x() + startAdvance);
- int y = lroundf(m_point.y() - m_font->ascent());
+ int y = lroundf(m_point.y() - m_font->fontMetrics().ascent());
// If there is a non-blur shadow and both the fill color and shadow color
// are opaque, handle without skia.
@@ -354,10 +355,11 @@ IntRect TransparencyAwareUniscribePainter::estimateTextBounds()
// This algorithm for estimating how much extra space we need (the text may
// go outside the selection rect) is based roughly on
// TransparencyAwareGlyphPainter::estimateTextBounds above.
- return IntRect(left - (m_font->ascent() + m_font->descent()) / 2,
- m_point.y() - m_font->ascent() - m_font->lineGap(),
- (right - left) + m_font->ascent() + m_font->descent(),
- m_font->lineSpacing());
+ const FontMetrics& fontMetrics = m_font->fontMetrics();
+ return IntRect(left - (fontMetrics.ascent() + fontMetrics.descent()) / 2,
+ m_point.y() - fontMetrics.ascent() - fontMetrics.lineGap(),
+ (right - left) + fontMetrics.ascent() + fontMetrics.descent(),
+ fontMetrics.lineSpacing());
}
} // namespace
@@ -367,6 +369,11 @@ bool Font::canReturnFallbackFontsForComplexText()
return false;
}
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+ return false;
+}
+
void Font::drawGlyphs(GraphicsContext* graphicsContext,
const SimpleFontData* font,
const GlyphBuffer& glyphBuffer,
@@ -496,14 +503,14 @@ void Font::drawComplexText(GraphicsContext* graphicsContext,
COLORREF savedTextColor = GetTextColor(hdc);
SetTextColor(hdc, textColor);
state.draw(graphicsContext, hdc, static_cast<int>(point.x()) + shadowOffset.width(),
- static_cast<int>(point.y() - ascent()) + shadowOffset.height(), from, to);
+ static_cast<int>(point.y() - fontMetrics().ascent()) + shadowOffset.height(), from, to);
SetTextColor(hdc, savedTextColor);
}
// 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() - ascent()), from, to);
+ static_cast<int>(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 822bbbb..823dbc9 100644
--- a/Source/WebCore/platform/graphics/chromium/FontLinux.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontLinux.cpp
@@ -55,6 +55,11 @@ bool Font::canReturnFallbackFontsForComplexText()
return false;
}
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+ return false;
+}
+
static bool isCanvasMultiLayered(SkCanvas* canvas)
{
SkCanvas::LayerIter layerIterator(canvas, false);
@@ -204,7 +209,7 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run,
ComplexTextController controller(run, point.x(), this);
controller.setWordSpacingAdjustment(wordSpacing());
controller.setLetterSpacingAdjustment(letterSpacing());
- controller.setPadding(run.padding());
+ controller.setPadding(run.expansion());
if (run.rtl()) {
// FIXME: this causes us to shape the text twice -- once to compute the width and then again
@@ -213,7 +218,7 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run,
controller.reset(point.x() + controller.widthOfFullRun());
// We need to set the padding again because ComplexTextController layout consumed the value.
// Fixing the above problem would help here too.
- controller.setPadding(run.padding());
+ controller.setPadding(run.expansion());
}
while (controller.nextScriptRun()) {
@@ -241,7 +246,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
ComplexTextController controller(run, 0, this);
controller.setWordSpacingAdjustment(wordSpacing());
controller.setLetterSpacingAdjustment(letterSpacing());
- controller.setPadding(run.padding());
+ controller.setPadding(run.expansion());
return controller.widthOfFullRun();
}
@@ -275,11 +280,11 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat,
ComplexTextController controller(run, 0, this);
controller.setWordSpacingAdjustment(wordSpacing());
controller.setLetterSpacingAdjustment(letterSpacing());
- controller.setPadding(run.padding());
+ controller.setPadding(run.expansion());
if (run.rtl()) {
// See FIXME in drawComplexText.
controller.reset(controller.widthOfFullRun());
- controller.setPadding(run.padding());
+ controller.setPadding(run.expansion());
}
unsigned basePosition = 0;
@@ -326,11 +331,11 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run,
ComplexTextController controller(run, 0, this);
controller.setWordSpacingAdjustment(wordSpacing());
controller.setLetterSpacingAdjustment(letterSpacing());
- controller.setPadding(run.padding());
+ controller.setPadding(run.expansion());
if (run.rtl()) {
// See FIXME in drawComplexText.
controller.reset(controller.widthOfFullRun());
- controller.setPadding(run.padding());
+ controller.setPadding(run.expansion());
}
// Iterate through the script runs in logical order, searching for the run covering the positions of interest.
diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
index a1ea012..6f9009f 100644
--- a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
@@ -36,6 +36,7 @@
#include "PlatformBridge.h"
#include "PlatformString.h"
+#include "SkAdvancedTypefaceMetrics.h"
#include "SkPaint.h"
#include "SkTypeface.h"
@@ -71,6 +72,7 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src)
: m_typeface(src.m_typeface)
, m_family(src.m_family)
, m_textSize(src.m_textSize)
+ , m_emSizeInFontUnits(src.m_emSizeInFontUnits)
, m_fakeBold(src.m_fakeBold)
, m_fakeItalic(src.m_fakeItalic)
, m_orientation(src.m_orientation)
@@ -84,6 +86,7 @@ FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float tex
: m_typeface(tf)
, m_family(family)
, m_textSize(textSize)
+ , m_emSizeInFontUnits(0)
, m_fakeBold(fakeBold)
, m_fakeItalic(fakeItalic)
, m_orientation(orientation)
@@ -96,6 +99,7 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize)
: m_typeface(src.m_typeface)
, m_family(src.m_family)
, m_textSize(textSize)
+ , m_emSizeInFontUnits(src.m_emSizeInFontUnits)
, m_fakeBold(src.m_fakeBold)
, m_fakeItalic(src.m_fakeItalic)
, m_harfbuzzFace(src.m_harfbuzzFace)
@@ -109,6 +113,17 @@ FontPlatformData::~FontPlatformData()
SkSafeUnref(m_typeface);
}
+int FontPlatformData::emSizeInFontUnits() const
+{
+ if (m_emSizeInFontUnits)
+ return m_emSizeInFontUnits;
+
+ SkAdvancedTypefaceMetrics* metrics = m_typeface->getAdvancedTypefaceMetrics(false);
+ m_emSizeInFontUnits = metrics->fEmSize;
+ metrics->unref();
+ return m_emSizeInFontUnits;
+}
+
FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src)
{
SkRefCnt_SafeAssign(m_typeface, src.m_typeface);
@@ -120,6 +135,7 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src)
m_harfbuzzFace = src.m_harfbuzzFace;
m_orientation = src.m_orientation;
m_style = src.m_style;
+ m_emSizeInFontUnits = src.m_emSizeInFontUnits;
return *this;
}
diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
index 43771d7..d9ebb61 100644
--- a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
+++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
@@ -63,6 +63,7 @@ public:
FontPlatformData(WTF::HashTableDeletedValueType)
: m_typeface(hashTableDeletedFontValue())
, m_textSize(0)
+ , m_emSizeInFontUnits(0)
, m_fakeBold(false)
, m_fakeItalic(false)
{ }
@@ -70,6 +71,7 @@ public:
FontPlatformData()
: m_typeface(0)
, m_textSize(0)
+ , m_emSizeInFontUnits(0)
, m_fakeBold(false)
, m_fakeItalic(false)
, m_orientation(Horizontal)
@@ -78,6 +80,7 @@ public:
FontPlatformData(float textSize, bool fakeBold, bool fakeItalic)
: m_typeface(0)
, m_textSize(textSize)
+ , m_emSizeInFontUnits(0)
, m_fakeBold(fakeBold)
, m_fakeItalic(fakeItalic)
, m_orientation(Horizontal)
@@ -107,6 +110,7 @@ public:
unsigned hash() const;
float size() const { return m_textSize; }
+ int emSizeInFontUnits() const;
FontOrientation orientation() const { return m_orientation; }
@@ -153,6 +157,7 @@ private:
SkTypeface* m_typeface;
CString m_family;
float m_textSize;
+ mutable int m_emSizeInFontUnits;
bool m_fakeBold;
bool m_fakeItalic;
FontOrientation m_orientation;
diff --git a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
index 4393f97..953ee2f 100644
--- a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
+++ b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
@@ -83,6 +83,22 @@ struct GLES2Canvas::State {
AffineTransform m_ctm;
WTF::Vector<Path> m_clippingPaths;
bool m_clippingEnabled;
+
+ // 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
+ // PlatformContextSkia::State::applyAlpha(), but the type is different.
+ Color applyAlpha(const Color& c)
+ {
+ int s = roundf(m_alpha * 256);
+ if (s >= 256)
+ return c;
+ if (s < 0)
+ return Color();
+
+ int a = (c.alpha() * s) >> 8;
+ return Color(c.red(), c.green(), c.blue(), a);
+ }
+
};
static inline FloatPoint operator*(const FloatPoint& f, float scale)
@@ -192,7 +208,7 @@ void GLES2Canvas::fillPath(const Path& path)
{
m_context->applyCompositeOperator(m_state->m_compositeOp);
applyClipping(m_state->m_clippingEnabled);
- fillPath(path, m_state->m_fillColor);
+ fillPath(path, m_state->applyAlpha(m_state->m_fillColor));
}
void GLES2Canvas::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
@@ -214,7 +230,7 @@ void GLES2Canvas::fillRect(const FloatRect& rect, const Color& color, ColorSpace
void GLES2Canvas::fillRect(const FloatRect& rect)
{
- fillRect(rect, m_state->m_fillColor, ColorSpaceDeviceRGB);
+ fillRect(rect, m_state->applyAlpha(m_state->m_fillColor), ColorSpaceDeviceRGB);
}
void GLES2Canvas::setFillColor(const Color& color, ColorSpace colorSpace)
@@ -322,8 +338,8 @@ void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, c
m_context->useQuadVertices();
m_context->setActiveTexture(GraphicsContext3D::TEXTURE0);
- for (int y = tileIdxRect.y(); y <= tileIdxRect.bottom(); y++) {
- for (int x = tileIdxRect.x(); x <= tileIdxRect.right(); x++)
+ for (int y = tileIdxRect.y(); y <= tileIdxRect.maxY(); y++) {
+ for (int x = tileIdxRect.x(); x <= tileIdxRect.maxX(); x++)
drawTexturedRectTile(texture, tiles.tileIndex(x, y), srcRect, dstRect, transform, alpha);
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
index 5e8d148..488230c 100644
--- a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
@@ -263,6 +263,17 @@ void GraphicsLayerChromium::setContentsOpaque(bool opaque)
updateContentsOpaque();
}
+void GraphicsLayerChromium::setMaskLayer(GraphicsLayer* maskLayer)
+{
+ if (maskLayer == m_maskLayer)
+ return;
+
+ GraphicsLayer::setMaskLayer(maskLayer);
+
+ LayerChromium* maskLayerChromium = m_maskLayer ? m_maskLayer->platformLayer() : 0;
+ m_layer->setMaskLayer(maskLayerChromium);
+}
+
void GraphicsLayerChromium::setBackfaceVisibility(bool visible)
{
if (m_backfaceVisibility == visible)
@@ -283,6 +294,15 @@ void GraphicsLayerChromium::setOpacity(float opacity)
primaryLayer()->setOpacity(opacity);
}
+void GraphicsLayerChromium::setReplicatedByLayer(GraphicsLayer* layer)
+{
+ GraphicsLayerChromium* layerChromium = static_cast<GraphicsLayerChromium*>(layer);
+ GraphicsLayer::setReplicatedByLayer(layer);
+ LayerChromium* replicaLayer = layerChromium ? layerChromium->primaryLayer() : 0;
+ primaryLayer()->setReplicaLayer(replicaLayer);
+}
+
+
void GraphicsLayerChromium::setContentsNeedsDisplay()
{
if (m_contentsLayer)
@@ -494,6 +514,7 @@ void GraphicsLayerChromium::updateAnchorPoint()
{
primaryLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y()));
primaryLayer()->setAnchorPointZ(m_anchorPoint.z());
+
updateLayerPosition();
}
diff --git a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
index 130c25c..92c61fe 100644
--- a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
@@ -67,6 +67,7 @@ public:
virtual void setPreserves3D(bool);
virtual void setMasksToBounds(bool);
virtual void setDrawsContent(bool);
+ virtual void setMaskLayer(GraphicsLayer*);
virtual void setBackgroundColor(const Color&);
virtual void clearBackgroundColor();
@@ -74,6 +75,8 @@ public:
virtual void setContentsOpaque(bool);
virtual void setBackfaceVisibility(bool);
+ virtual void setReplicatedByLayer(GraphicsLayer*);
+
virtual void setOpacity(float);
virtual void setNeedsDisplay();
diff --git a/Source/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp b/Source/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp
index 056d8eb..26ca64e 100644
--- a/Source/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp
+++ b/Source/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp
@@ -94,7 +94,7 @@ static void glyphsToAdvances(HB_Font hbFont, const HB_Glyph* glyphs, hb_uint32 n
font->setupPaint(&paint);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- OwnArrayPtr<uint16_t> glyphs16(new uint16_t[numGlyphs]);
+ OwnArrayPtr<uint16_t> glyphs16 = adoptArrayPtr(new uint16_t[numGlyphs]);
if (!glyphs16.get())
return;
for (unsigned i = 0; i < numGlyphs; ++i)
@@ -120,7 +120,7 @@ static HB_Bool canRender(HB_Font hbFont, const HB_UChar16* characters, hb_uint32
font->setupPaint(&paint);
paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
- OwnArrayPtr<uint16_t> glyphs16(new uint16_t[length]);
+ OwnArrayPtr<uint16_t> glyphs16 = adoptArrayPtr(new uint16_t[length]);
if (!glyphs16.get())
return 0;
int numGlyphs = paint.textToGlyphs(characters, length * sizeof(uint16_t), glyphs16.get());
diff --git a/Source/WebCore/platform/graphics/chromium/IconChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/IconChromium.cpp
index e958d4a..398cc3b 100644
--- a/Source/WebCore/platform/graphics/chromium/IconChromiumWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/IconChromium.cpp
@@ -1,10 +1,10 @@
/*
- * 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
* met:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -31,25 +31,18 @@
#include "config.h"
#include "Icon.h"
-#include <windows.h>
-#include <shellapi.h>
-
#include "GraphicsContext.h"
-#include "PlatformContextSkia.h"
#include "PlatformString.h"
-#include "SkiaUtils.h"
namespace WebCore {
-Icon::Icon(const PlatformIcon& icon)
+Icon::Icon(PassRefPtr<PlatformIcon> icon)
: m_icon(icon)
{
}
Icon::~Icon()
{
- if (m_icon)
- DestroyIcon(m_icon);
}
void Icon::paint(GraphicsContext* context, const IntRect& rect)
@@ -57,9 +50,9 @@ void Icon::paint(GraphicsContext* context, const IntRect& rect)
if (context->paintingDisabled())
return;
- HDC hdc = context->platformContext()->canvas()->beginPlatformPaint();
- DrawIconEx(hdc, rect.x(), rect.y(), m_icon, rect.width(), rect.height(), 0, 0, DI_NORMAL);
- context->platformContext()->canvas()->endPlatformPaint();
+ // An Icon doesn't know the color space of the file upload control.
+ // So use ColorSpaceDeviceRGB.
+ context->drawImage(m_icon.get(), ColorSpaceDeviceRGB, rect);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
index b7ab098..8d01d9b 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
@@ -143,6 +143,7 @@ PassRefPtr<LayerChromium> LayerChromium::create(GraphicsLayerChromium* owner)
LayerChromium::LayerChromium(GraphicsLayerChromium* owner)
: m_owner(owner)
, m_contentsDirty(false)
+ , m_maskLayer(0)
, m_targetRenderSurface(0)
, m_superlayer(0)
, m_anchorPoint(0.5, 0.5)
@@ -162,6 +163,7 @@ LayerChromium::LayerChromium(GraphicsLayerChromium* owner)
, m_drawDepth(0)
, m_layerRenderer(0)
, m_renderSurface(0)
+ , m_replicaLayer(0)
{
}
@@ -433,9 +435,7 @@ void LayerChromium::drawTexturedQuad(GraphicsContext3D* context, const Transform
renderMatrix.scale3d(width, height, 1);
// Apply the projection matrix before sending the transform over to the shader.
- renderMatrix.multiply(projectionMatrix);
-
- toGLMatrix(&glMatrix[0], renderMatrix);
+ toGLMatrix(&glMatrix[0], projectionMatrix * renderMatrix);
GLC(context, context->uniformMatrix4fv(matrixLocation, false, &glMatrix[0], 1));
@@ -457,8 +457,7 @@ void LayerChromium::drawDebugBorder()
layerRenderer()->useShader(sv->borderShaderProgram());
TransformationMatrix renderMatrix = drawTransform();
renderMatrix.scale3d(bounds().width(), bounds().height(), 1);
- renderMatrix.multiply(layerRenderer()->projectionMatrix());
- toGLMatrix(&glMatrix[0], renderMatrix);
+ toGLMatrix(&glMatrix[0], layerRenderer()->projectionMatrix() * renderMatrix);
GraphicsContext3D* context = layerRendererContext();
GLC(context, context->uniformMatrix4fv(sv->borderShaderMatrixLocation(), false, &glMatrix[0], 1));
diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerChromium.h
index a0a690f..5c7e2b1 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.h
@@ -112,6 +112,9 @@ public:
void setName(const String& name) { m_name = name; }
String name() const { return m_name; }
+ void setMaskLayer(LayerChromium* maskLayer) { m_maskLayer = maskLayer; }
+ LayerChromium* maskLayer() const { return m_maskLayer.get(); }
+
void setNeedsDisplay(const FloatRect& dirtyRect);
void setNeedsDisplay();
const FloatRect& dirtyRect() const { return m_dirtyRect; }
@@ -152,12 +155,17 @@ public:
void setOwner(GraphicsLayerChromium* owner) { m_owner = owner; }
+ void setReplicaLayer(LayerChromium* layer) { m_replicaLayer = layer; }
+ LayerChromium* replicaLayer() { return m_replicaLayer; }
+
// Returns the rect containtaining this layer in the current view's coordinate system.
const IntRect getDrawRect() const;
// These methods typically need to be overwritten by derived classes.
virtual bool drawsContent() { return false; }
virtual void updateContentsIfDirty() { }
+ virtual void unreserveContentsTexture() { }
+ virtual void bindContentsTexture() { }
virtual void draw() { }
void drawDebugBorder();
@@ -222,6 +230,8 @@ protected:
FloatRect m_dirtyRect;
bool m_contentsDirty;
+ RefPtr<LayerChromium> m_maskLayer;
+
// Render surface this layer draws into. This is a surface that can belong
// either to this layer (if m_targetRenderSurface == m_renderSurface) or
// to an ancestor of this layer. The target render surface determines the
@@ -298,6 +308,9 @@ private:
// Hierarchical bounding rect containing the layer and its descendants.
IntRect m_drawableContentRect;
+ // Replica layer used for reflections.
+ LayerChromium* m_replicaLayer;
+
String m_name;
};
diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
index 90eac74..f5548c9 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
@@ -143,20 +143,19 @@ void LayerRendererChromium::useShader(unsigned programId)
IntRect LayerRendererChromium::verticalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect)
{
- IntRect verticalScrollbar(IntPoint(contentRect.right(), contentRect.y()), IntSize(visibleRect.width() - contentRect.width(), visibleRect.height()));
+ IntRect verticalScrollbar(IntPoint(contentRect.maxX(), contentRect.y()), IntSize(visibleRect.width() - contentRect.width(), visibleRect.height()));
return verticalScrollbar;
}
IntRect LayerRendererChromium::horizontalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect)
{
- IntRect horizontalScrollbar(IntPoint(contentRect.x(), contentRect.bottom()), IntSize(visibleRect.width(), visibleRect.height() - contentRect.height()));
+ IntRect horizontalScrollbar(IntPoint(contentRect.x(), contentRect.maxY()), IntSize(visibleRect.width(), visibleRect.height() - contentRect.height()));
return horizontalScrollbar;
}
void LayerRendererChromium::invalidateRootLayerRect(const IntRect& dirtyRect, const IntRect& visibleRect, const IntRect& contentRect)
{
- if (contentRect.intersects(dirtyRect))
- m_rootLayerTiler->invalidateRect(dirtyRect);
+ m_rootLayerTiler->invalidateRect(dirtyRect);
if (m_horizontalScrollbarTiler) {
IntRect scrollbar = horizontalScrollbarRect(visibleRect, contentRect);
if (dirtyRect.intersects(scrollbar)) {
@@ -266,6 +265,11 @@ void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect
// Re-enable color writes to layers, which may be partially transparent.
m_context->colorMask(true, true, true, true);
+ // 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;
+
// Set the root visible/content rects --- used by subsequent drawLayers calls.
m_rootVisibleRect = visibleRect;
m_rootContentRect = contentRect;
@@ -346,8 +350,8 @@ void LayerRendererChromium::setRootLayer(PassRefPtr<LayerChromium> layer)
void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect)
{
- ASSERT(rect.right() <= rootLayerTextureSize().width()
- && rect.bottom() <= rootLayerTextureSize().height());
+ ASSERT(rect.maxX() <= rootLayerTextureSize().width()
+ && rect.maxY() <= rootLayerTextureSize().height());
if (!pixels)
return;
@@ -388,7 +392,7 @@ bool LayerRendererChromium::isLayerVisible(LayerChromium* layer, const Transform
// bounds into clip space.
TransformationMatrix renderMatrix = matrix;
renderMatrix.scale3d(layer->bounds().width(), layer->bounds().height(), 1);
- renderMatrix.multiply(m_projectionMatrix);
+ renderMatrix = m_projectionMatrix * renderMatrix;
FloatRect layerRect(-0.5, -0.5, 1, 1);
FloatRect mappedRect = renderMatrix.mapRect(layerRect);
@@ -434,12 +438,12 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr
// LT = Tr[l]
layerLocalTransform.translate3d(position.x(), position.y(), layer->anchorPointZ());
// LT = Tr[l] * M[l]
- layerLocalTransform.multLeft(layer->transform());
+ layerLocalTransform.multiply(layer->transform());
// LT = Tr[l] * M[l] * Tr[c]
layerLocalTransform.translate3d(centerOffsetX, centerOffsetY, -layer->anchorPointZ());
TransformationMatrix combinedTransform = parentMatrix;
- combinedTransform = combinedTransform.multLeft(layerLocalTransform);
+ combinedTransform = combinedTransform.multiply(layerLocalTransform);
FloatRect layerRect(-0.5 * layer->bounds().width(), -0.5 * layer->bounds().height(), layer->bounds().width(), layer->bounds().height());
IntRect transformedLayerRect;
@@ -448,12 +452,17 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr
// these conditions hold:
// 1. The layer clips its descendants and its transform is not a simple translation.
// 2. If the layer has opacity != 1 and does not have a preserves-3d transform style.
+ // 3. The layer uses a mask
+ // 4. The layer has a replica (used for reflections)
// If a layer preserves-3d then we don't create a RenderSurface for it to avoid flattening
// out its children. The opacity value of the children layers is multiplied by the opacity
// of their parent.
bool useSurfaceForClipping = layer->masksToBounds() && !isScaleOrTranslation(combinedTransform);
bool useSurfaceForOpacity = layer->opacity() != 1 && !layer->preserves3D();
- if ((useSurfaceForClipping || useSurfaceForOpacity) && layer->descendantsDrawContent()) {
+ bool useSurfaceForMasking = layer->maskLayer();
+ bool useSurfaceForReflection = layer->replicaLayer();
+ if (((useSurfaceForClipping || useSurfaceForOpacity) && layer->descendantsDrawContent())
+ || useSurfaceForMasking || useSurfaceForReflection) {
RenderSurfaceChromium* renderSurface = layer->m_renderSurface.get();
if (!renderSurface)
renderSurface = layer->createRenderSurface();
@@ -487,6 +496,18 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr
renderSurface->m_layerList.clear();
+ if (layer->maskLayer()) {
+ renderSurface->m_maskLayer = layer->maskLayer();
+ layer->maskLayer()->setLayerRenderer(this);
+ layer->maskLayer()->m_targetRenderSurface = renderSurface;
+ } else
+ renderSurface->m_maskLayer = 0;
+
+ if (layer->replicaLayer() && layer->replicaLayer()->maskLayer()) {
+ layer->replicaLayer()->maskLayer()->setLayerRenderer(this);
+ layer->replicaLayer()->maskLayer()->m_targetRenderSurface = renderSurface;
+ }
+
renderSurfaceLayerList.append(layer);
} else {
// DT = M[p] * LT
@@ -540,7 +561,7 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr
}
// Apply the sublayer transform at the center of the layer.
- sublayerMatrix.multLeft(layer->sublayerTransform());
+ sublayerMatrix.multiply(layer->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:
@@ -558,16 +579,13 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr
if (sublayer->m_renderSurface) {
RenderSurfaceChromium* sublayerRenderSurface = sublayer->m_renderSurface.get();
- const IntRect& contentRect = sublayerRenderSurface->contentRect();
- FloatRect sublayerRect(-0.5 * contentRect.width(), -0.5 * contentRect.height(),
- contentRect.width(), contentRect.height());
- layer->m_drawableContentRect.unite(enclosingIntRect(sublayerRenderSurface->m_drawTransform.mapRect(sublayerRect)));
+ layer->m_drawableContentRect.unite(enclosingIntRect(sublayerRenderSurface->drawableContentRect()));
descendants.append(sublayer);
} else
layer->m_drawableContentRect.unite(sublayer->m_drawableContentRect);
}
- if (layer->masksToBounds())
+ if (layer->masksToBounds() || useSurfaceForMasking)
layer->m_drawableContentRect.intersect(transformedLayerRect);
if (layer->m_renderSurface && layer != m_rootLayer) {
@@ -577,9 +595,13 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr
// Restrict the RenderSurface size to the portion that's visible.
FloatSize centerOffsetDueToClipping;
- renderSurface->m_contentRect.intersect(layer->m_scissorRect);
- FloatPoint clippedSurfaceCenter = renderSurface->contentRectCenter();
- centerOffsetDueToClipping = clippedSurfaceCenter - surfaceCenter;
+ // Don't clip if the layer is reflected as the reflection shouldn't be
+ // clipped.
+ if (!layer->replicaLayer()) {
+ renderSurface->m_contentRect.intersect(layer->m_scissorRect);
+ FloatPoint clippedSurfaceCenter = renderSurface->contentRectCenter();
+ centerOffsetDueToClipping = clippedSurfaceCenter - surfaceCenter;
+ }
// The RenderSurface backing texture cannot exceed the maximum supported
// texture size.
@@ -596,6 +618,15 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr
// Adjust the origin of the transform to be the center of the render surface.
renderSurface->m_drawTransform = renderSurface->m_originTransform;
renderSurface->m_drawTransform.translate3d(surfaceCenter.x() + centerOffsetDueToClipping.width(), surfaceCenter.y() + centerOffsetDueToClipping.height(), 0);
+
+ // Compute the transformation matrix used to draw the replica of the render
+ // surface.
+ if (layer->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(surfaceCenter.x() - anchorPoint.x() * bounds.width(), surfaceCenter.y() - anchorPoint.y() * bounds.height(), 0);
+ }
}
// Compute the depth value of the center of the layer which will be used when
@@ -682,10 +713,10 @@ void LayerRendererChromium::drawLayer(LayerChromium* layer, RenderSurfaceChromiu
if (!isLayerVisible)
return;
- // FIXME: Need to take into account the transform of the containing
- // RenderSurface here, otherwise single-sided layers that draw on
- // transformed surfaces won't always be culled properly.
- if (!layer->doubleSided() && layer->m_drawTransform.m33() < 0)
+ // 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->m_renderSurface ? layer->m_renderSurface->drawTransform().multiply(layer->m_drawTransform) : layer->m_drawTransform);
+ if (!layer->doubleSided() && combinedDrawMatrix.m33() < 0)
return;
if (layer->drawsContent()) {
@@ -711,7 +742,7 @@ void LayerRendererChromium::setScissorToRect(const IntRect& scissorRect)
// But, if rendering to offscreen texture, we reverse our sense of 'upside down'.
int scissorY;
if (m_currentRenderSurface == m_defaultRenderSurface && !m_compositeOffscreen)
- scissorY = m_currentRenderSurface->m_contentRect.height() - (scissorRect.bottom() - m_currentRenderSurface->m_contentRect.y());
+ scissorY = m_currentRenderSurface->m_contentRect.height() - (scissorRect.maxY() - m_currentRenderSurface->m_contentRect.y());
else
scissorY = scissorRect.y() - m_currentRenderSurface->m_contentRect.y();
GLC(m_context.get(), m_context->scissor(scissorX, scissorY, scissorRect.width(), scissorRect.height()));
@@ -737,9 +768,9 @@ bool LayerRendererChromium::checkTextureSize(const IntSize& textureSize)
void LayerRendererChromium::setDrawViewportRect(const IntRect& drawRect, bool flipY)
{
if (flipY)
- m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.right(), drawRect.bottom(), drawRect.y());
+ m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.maxY(), drawRect.y());
else
- m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.right(), drawRect.y(), drawRect.bottom());
+ m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.y(), drawRect.maxY());
GLC(m_context.get(), m_context->viewport(0, 0, drawRect.width(), drawRect.height()));
}
diff --git a/Source/WebCore/platform/graphics/chromium/LayerTexture.cpp b/Source/WebCore/platform/graphics/chromium/LayerTexture.cpp
index 32bfa0b..23cb4b3 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerTexture.cpp
+++ b/Source/WebCore/platform/graphics/chromium/LayerTexture.cpp
@@ -79,6 +79,7 @@ void LayerTexture::unreserve()
void LayerTexture::bindTexture()
{
+ ASSERT(m_textureManager->hasTexture(m_token));
m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId);
}
diff --git a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp
index 6b65e66..e28c084 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp
@@ -145,8 +145,8 @@ void LayerTilerChromium::contentRectToTileIndices(const IntRect& contentRect, in
left = layerRect.x() / m_tileSize.width();
top = layerRect.y() / m_tileSize.height();
- right = (layerRect.right() - 1) / m_tileSize.width();
- bottom = (layerRect.bottom() - 1) / m_tileSize.height();
+ right = (layerRect.maxX() - 1) / m_tileSize.width();
+ bottom = (layerRect.maxY() - 1) / m_tileSize.height();
}
IntRect LayerTilerChromium::contentRectToLayerRect(const IntRect& contentRect) const
@@ -272,7 +272,11 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont
// Get the contents of the updated rect.
const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false);
ASSERT(bitmap.width() == paintRect.width() && bitmap.height() == paintRect.height());
+ if (bitmap.width() != paintRect.width() || bitmap.height() != paintRect.height())
+ CRASH();
uint8_t* paintPixels = static_cast<uint8_t*>(bitmap.getPixels());
+ if (!paintPixels)
+ CRASH();
#elif PLATFORM(CG)
Vector<uint8_t> canvasPixels;
int rowBytes = 4 * paintRect.width();
@@ -299,9 +303,15 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont
#error "Need to implement for your platform."
#endif
+ // Painting could cause compositing to get turned off, which may cause the tiler to become invalidated mid-update.
+ if (!m_tiles.size())
+ return;
+
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
Tile* tile = m_tiles[tileIndex(i, j)].get();
+ if (!tile)
+ CRASH();
if (!tile->dirty())
continue;
@@ -320,13 +330,21 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont
// Calculate tile-space rectangle to upload into.
IntRect destRect(IntPoint(sourceRect.x() - anchor.x(), sourceRect.y() - anchor.y()), sourceRect.size());
- ASSERT(destRect.x() >= 0);
- ASSERT(destRect.y() >= 0);
+ if (destRect.x() < 0)
+ CRASH();
+ if (destRect.y() < 0)
+ CRASH();
// Offset from paint rectangle to this tile's dirty rectangle.
IntPoint paintOffset(sourceRect.x() - paintRect.x(), sourceRect.y() - paintRect.y());
- ASSERT(paintOffset.x() >= 0);
- ASSERT(paintOffset.y() >= 0);
+ if (paintOffset.x() < 0)
+ CRASH();
+ if (paintOffset.y() < 0)
+ CRASH();
+ if (paintOffset.x() + destRect.width() > paintRect.width())
+ CRASH();
+ if (paintOffset.y() + destRect.height() > paintRect.height())
+ CRASH();
uint8_t* pixelSource;
if (paintRect.width() == sourceRect.width() && !paintOffset.x())
@@ -357,7 +375,7 @@ void LayerTilerChromium::setLayerPosition(const IntPoint& layerPosition)
void LayerTilerChromium::draw(const IntRect& contentRect)
{
- if (m_skipsDraw)
+ if (m_skipsDraw || !m_tiles.size())
return;
// We reuse the shader program used by ContentLayerChromium.
@@ -394,6 +412,9 @@ void LayerTilerChromium::resizeLayer(const IntSize& size)
int width = (size.width() + m_tileSize.width() - 1) / m_tileSize.width();
int height = (size.height() + m_tileSize.height() - 1) / m_tileSize.height();
+ if (height && (width > INT_MAX / height))
+ CRASH();
+
Vector<OwnPtr<Tile> > newTiles;
newTiles.resize(width * height);
for (int j = 0; j < m_layerTileSize.height(); ++j)
@@ -409,7 +430,7 @@ void LayerTilerChromium::growLayerToContain(const IntRect& contentRect)
{
// Grow the tile array to contain this content rect.
IntRect layerRect = contentRectToLayerRect(contentRect);
- IntSize layerSize = IntSize(layerRect.right(), layerRect.bottom());
+ IntSize layerSize = IntSize(layerRect.maxX(), layerRect.maxY());
IntSize newSize = layerSize.expandedTo(m_layerSize);
resizeLayer(newSize);
diff --git a/Source/WebCore/platform/graphics/chromium/PlatformIcon.h b/Source/WebCore/platform/graphics/chromium/PlatformIcon.h
index 51613b8..b485917 100644
--- a/Source/WebCore/platform/graphics/chromium/PlatformIcon.h
+++ b/Source/WebCore/platform/graphics/chromium/PlatformIcon.h
@@ -31,11 +31,11 @@
#ifndef PlatformIcon_h
#define PlatformIcon_h
-typedef struct HICON__* HICON;
-
namespace WebCore {
-typedef HICON PlatformIcon;
+class Image;
+
+typedef Image PlatformIcon;
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
index 696828f..b3ce9d7 100644
--- a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
@@ -38,15 +38,17 @@ namespace WebCore {
RenderSurfaceChromium::SharedValues::SharedValues(GraphicsContext3D* context)
: m_context(context)
, m_shaderProgram(0)
+ , m_maskShaderProgram(0)
, m_shaderSamplerLocation(-1)
, m_shaderMatrixLocation(-1)
, m_shaderAlphaLocation(-1)
+ , m_maskShaderSamplerLocation(-1)
+ , m_maskShaderMaskSamplerLocation(-1)
+ , m_maskShaderMatrixLocation(-1)
+ , m_maskShaderAlphaLocation(-1)
, m_initialized(false)
{
- // The following program composites layers whose contents are the results of a previous
- // render operation and therefore doesn't perform any color swizzling. It is used
- // in scrolling and for compositing offscreen textures.
- char renderSurfaceVertexShaderString[] =
+ char vertexShaderString[] =
"attribute vec4 a_position; \n"
"attribute vec2 a_texCoord; \n"
"uniform mat4 matrix; \n"
@@ -56,7 +58,7 @@ RenderSurfaceChromium::SharedValues::SharedValues(GraphicsContext3D* context)
" gl_Position = matrix * a_position; \n"
" v_texCoord = a_texCoord; \n"
"} \n";
- char renderSurfaceFragmentShaderString[] =
+ char fragmentShaderString[] =
"precision mediump float; \n"
"varying vec2 v_texCoord; \n"
"uniform sampler2D s_texture; \n"
@@ -66,9 +68,22 @@ RenderSurfaceChromium::SharedValues::SharedValues(GraphicsContext3D* context)
" vec4 texColor = texture2D(s_texture, v_texCoord); \n"
" gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n"
"} \n";
+ char fragmentShaderWithMaskString[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "uniform sampler2D s_mask; \n"
+ "uniform float alpha; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texColor = texture2D(s_texture, v_texCoord); \n"
+ " vec4 maskColor = texture2D(s_mask, v_texCoord); \n"
+ " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha * maskColor.w; \n"
+ "} \n";
- m_shaderProgram = LayerChromium::createShaderProgram(m_context, renderSurfaceVertexShaderString, renderSurfaceFragmentShaderString);
- if (!m_shaderProgram) {
+ m_shaderProgram = LayerChromium::createShaderProgram(m_context, vertexShaderString, fragmentShaderString);
+ m_maskShaderProgram = LayerChromium::createShaderProgram(m_context, vertexShaderString, fragmentShaderWithMaskString);
+ if (!m_shaderProgram || !m_maskShaderProgram) {
LOG_ERROR("RenderSurfaceChromium: Failed to create shader program");
return;
}
@@ -76,10 +91,24 @@ RenderSurfaceChromium::SharedValues::SharedValues(GraphicsContext3D* context)
GLC(m_context, m_shaderSamplerLocation = m_context->getUniformLocation(m_shaderProgram, "s_texture"));
GLC(m_context, m_shaderMatrixLocation = m_context->getUniformLocation(m_shaderProgram, "matrix"));
GLC(m_context, m_shaderAlphaLocation = m_context->getUniformLocation(m_shaderProgram, "alpha"));
- if (m_shaderSamplerLocation == -1 || m_shaderMatrixLocation == -1 || m_shaderAlphaLocation == -1) {
- LOG_ERROR("Failed to initialize texture layer shader.");
+
+ GLC(m_context, m_maskShaderSamplerLocation = m_context->getUniformLocation(m_maskShaderProgram, "s_texture"));
+ GLC(m_context, m_maskShaderMaskSamplerLocation = m_context->getUniformLocation(m_maskShaderProgram, "s_mask"));
+ GLC(m_context, m_maskShaderMatrixLocation = m_context->getUniformLocation(m_maskShaderProgram, "matrix"));
+ GLC(m_context, m_maskShaderAlphaLocation = m_context->getUniformLocation(m_maskShaderProgram, "alpha"));
+
+ if (m_shaderSamplerLocation == -1 || m_shaderMatrixLocation == -1 || m_shaderAlphaLocation == -1
+ || m_maskShaderSamplerLocation == -1 || m_maskShaderMaskSamplerLocation == -1 || m_maskShaderMatrixLocation == -1 || m_maskShaderAlphaLocation == -1) {
+ LOG_ERROR("Failed to initialize render surface shaders.");
return;
}
+
+ GLC(m_context, m_context->useProgram(m_shaderProgram));
+ GLC(m_context, m_context->uniform1i(m_shaderSamplerLocation, 0));
+ GLC(m_context, m_context->useProgram(m_maskShaderProgram));
+ GLC(m_context, m_context->uniform1i(m_maskShaderSamplerLocation, 0));
+ GLC(m_context, m_context->uniform1i(m_maskShaderMaskSamplerLocation, 1));
+ GLC(m_context, m_context->useProgram(0));
m_initialized = true;
}
@@ -87,10 +116,13 @@ RenderSurfaceChromium::SharedValues::~SharedValues()
{
if (m_shaderProgram)
GLC(m_context, m_context->deleteProgram(m_shaderProgram));
+ if (m_maskShaderProgram)
+ GLC(m_context, m_context->deleteProgram(m_maskShaderProgram));
}
RenderSurfaceChromium::RenderSurfaceChromium(LayerChromium* owningLayer)
: m_owningLayer(owningLayer)
+ , m_maskLayer(0)
, m_skipsDraw(false)
{
}
@@ -116,6 +148,17 @@ LayerRendererChromium* RenderSurfaceChromium::layerRenderer()
return m_owningLayer->layerRenderer();
}
+FloatRect RenderSurfaceChromium::drawableContentRect() const
+{
+ FloatRect localContentRect(-0.5 * m_contentRect.width(), -0.5 * m_contentRect.height(),
+ m_contentRect.width(), m_contentRect.height());
+ FloatRect drawableContentRect = m_drawTransform.mapRect(localContentRect);
+ if (m_owningLayer->replicaLayer())
+ drawableContentRect.unite(m_replicaDrawTransform.mapRect(localContentRect));
+
+ return drawableContentRect;
+}
+
bool RenderSurfaceChromium::prepareContentsTexture()
{
IntSize requiredSize(m_contentRect.size());
@@ -136,24 +179,69 @@ bool RenderSurfaceChromium::prepareContentsTexture()
return true;
}
-void RenderSurfaceChromium::draw()
+void RenderSurfaceChromium::drawSurface(LayerChromium* maskLayer, const TransformationMatrix& drawTransform)
{
- if (m_skipsDraw || !m_contentsTexture)
- return;
-
- m_contentsTexture->bindTexture();
+ GraphicsContext3D* context3D = layerRenderer()->context();
+ int shaderMatrixLocation = -1;
+ int shaderAlphaLocation = -1;
const RenderSurfaceChromium::SharedValues* sv = layerRenderer()->renderSurfaceSharedValues();
ASSERT(sv && sv->initialized());
+ bool useMask = false;
+ if (maskLayer && maskLayer->drawsContent()) {
+ maskLayer->updateContentsIfDirty();
+ if (!maskLayer->bounds().isEmpty()) {
+ context3D->makeContextCurrent();
+ layerRenderer()->useShader(sv->maskShaderProgram());
+ GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE0));
+ m_contentsTexture->bindTexture();
+ GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE1));
+ maskLayer->bindContentsTexture();
+ GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE0));
+ shaderMatrixLocation = sv->maskShaderMatrixLocation();
+ shaderAlphaLocation = sv->maskShaderAlphaLocation();
+ useMask = true;
+ }
+ }
+
+ if (!useMask) {
+ layerRenderer()->useShader(sv->shaderProgram());
+ m_contentsTexture->bindTexture();
+ shaderMatrixLocation = sv->shaderMatrixLocation();
+ shaderAlphaLocation = sv->shaderAlphaLocation();
+ }
+
+ LayerChromium::drawTexturedQuad(layerRenderer()->context(), layerRenderer()->projectionMatrix(), drawTransform,
+ m_contentRect.width(), m_contentRect.height(), m_drawOpacity,
+ shaderMatrixLocation, shaderAlphaLocation);
+
+ m_contentsTexture->unreserve();
+
+ if (maskLayer)
+ maskLayer->unreserveContentsTexture();
+}
+
+void RenderSurfaceChromium::draw()
+{
+ if (m_skipsDraw || !m_contentsTexture)
+ return;
+ // FIXME: By using the same RenderSurface for both the content and its reflection,
+ // it's currently not possible to apply a separate mask to the reflection layer
+ // or correctly handle opacity in reflections (opacity must be applied after drawing
+ // both the layer and its reflection). The solution is to introduce yet another RenderSurface
+ // to draw the layer and its reflection in. For now we only apply a separate reflection
+ // mask if the contents don't have a mask of their own.
+ LayerChromium* replicaMaskLayer = m_maskLayer;
+ if (!m_maskLayer && m_owningLayer->replicaLayer())
+ replicaMaskLayer = m_owningLayer->replicaLayer()->maskLayer();
- layerRenderer()->useShader(sv->shaderProgram());
layerRenderer()->setScissorToRect(m_scissorRect);
- LayerChromium::drawTexturedQuad(layerRenderer()->context(), layerRenderer()->projectionMatrix(), m_drawTransform,
- m_contentRect.width(), m_contentRect.height(), m_drawOpacity,
- sv->shaderMatrixLocation(), sv->shaderAlphaLocation());
+ // Reflection draws before the layer.
+ if (m_owningLayer->replicaLayer())
+ drawSurface(replicaMaskLayer, m_replicaDrawTransform);
- m_contentsTexture->unreserve();
+ drawSurface(m_maskLayer, m_drawTransform);
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
index 689a6eb..b1f6a5c 100644
--- a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
@@ -55,6 +55,11 @@ public:
FloatPoint contentRectCenter() const { return FloatRect(m_contentRect).center(); }
IntRect contentRect() const { return m_contentRect; }
+ // Returns the rect that encloses the RenderSurface including any reflection.
+ FloatRect drawableContentRect() const;
+
+ TransformationMatrix drawTransform() const { return m_drawTransform; }
+
// Stores values that are shared between instances of this class that are
// associated with the same LayerRendererChromium (and hence the same GL
// context).
@@ -64,30 +69,44 @@ public:
~SharedValues();
unsigned shaderProgram() const { return m_shaderProgram; }
+ unsigned maskShaderProgram() const { return m_maskShaderProgram; }
int shaderSamplerLocation() const { return m_shaderSamplerLocation; }
int shaderMatrixLocation() const { return m_shaderMatrixLocation; }
int shaderAlphaLocation() const { return m_shaderAlphaLocation; }
+ int maskShaderSamplerLocation() const { return m_maskShaderSamplerLocation; }
+ int maskShaderMaskSamplerLocation() const { return m_maskShaderMaskSamplerLocation; }
+ int maskShaderMatrixLocation() const { return m_maskShaderMatrixLocation; }
+ int maskShaderAlphaLocation() const { return m_maskShaderAlphaLocation; }
bool initialized() const { return m_initialized; }
private:
GraphicsContext3D* m_context;
unsigned m_shaderProgram;
+ unsigned m_maskShaderProgram;
int m_shaderSamplerLocation;
int m_shaderMatrixLocation;
int m_shaderAlphaLocation;
+ int m_maskShaderSamplerLocation;
+ int m_maskShaderMaskSamplerLocation;
+ int m_maskShaderMatrixLocation;
+ int m_maskShaderAlphaLocation;
bool m_initialized;
};
private:
LayerRendererChromium* layerRenderer();
+ void drawSurface(LayerChromium* maskLayer, const TransformationMatrix& drawTransform);
LayerChromium* m_owningLayer;
+ LayerChromium* m_maskLayer;
+
IntRect m_contentRect;
bool m_skipsDraw;
OwnPtr<LayerTexture> m_contentsTexture;
float m_drawOpacity;
TransformationMatrix m_drawTransform;
+ TransformationMatrix m_replicaDrawTransform;
TransformationMatrix m_originTransform;
IntRect m_scissorRect;
Vector<LayerChromium*> m_layerList;
diff --git a/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
index c23c586..1450c5a 100644
--- a/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
@@ -54,14 +54,9 @@ static inline float scaleEmToUnits(float x, int unitsPerEm)
void SimpleFontData::platformInit()
{
if (!m_platformData.size()) {
- m_ascent = 0;
- m_descent = 0;
- m_lineGap = 0;
- m_lineSpacing = 0;
+ m_fontMetrics.reset();
m_avgCharWidth = 0;
m_maxCharWidth = 0;
- m_xHeight = 0;
- m_unitsPerEm = 0;
return;
}
@@ -82,10 +77,11 @@ void SimpleFontData::platformInit()
m_avgCharWidth = textMetric.tmAveCharWidth;
m_maxCharWidth = textMetric.tmMaxCharWidth;
- m_ascent = textMetric.tmAscent;
- m_descent = textMetric.tmDescent;
- m_lineGap = textMetric.tmExternalLeading;
- m_xHeight = m_ascent * 0.56f; // Best guess for xHeight for non-Truetype fonts.
+ // FIXME: Access ascent/descent/lineGap with floating point precision.
+ float ascent = textMetric.tmAscent;
+ float descent = textMetric.tmDescent;
+ float lineGap = textMetric.tmExternalLeading;
+ float xHeight = ascent * 0.56f; // Best guess for xHeight for non-Truetype fonts.
OUTLINETEXTMETRIC outlineTextMetric;
if (GetOutlineTextMetrics(dc, sizeof(outlineTextMetric), &outlineTextMetric) > 0) {
@@ -94,10 +90,14 @@ void SimpleFontData::platformInit()
MAT2 identityMatrix = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
DWORD len = GetGlyphOutlineW(dc, 'x', GGO_METRICS, &glyphMetrics, 0, 0, &identityMatrix);
if (len != GDI_ERROR && glyphMetrics.gmBlackBoxY > 0)
- m_xHeight = static_cast<float>(glyphMetrics.gmBlackBoxY);
+ xHeight = static_cast<float>(glyphMetrics.gmBlackBoxY);
}
- m_lineSpacing = m_ascent + m_descent + m_lineGap;
+ m_fontMetrics.setAscent(ascent);
+ m_fontMetrics.setDescent(descent);
+ m_fontMetrics.setLineGap(lineGap);
+ m_fontMetrics.setXHeight(xHeight);
+ m_fontMetrics.setLineSpacing(ascent + descent + lineGap);
SelectObject(dc, oldFont);
ReleaseDC(0, dc);
diff --git a/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp b/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
index 355d837..9423d1e 100644
--- a/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
+++ b/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
@@ -55,14 +55,9 @@ static const size_t maxVDMXTableSize = 1024 * 1024; // 1 MB
void SimpleFontData::platformInit()
{
if (!m_platformData.size()) {
- m_ascent = 0;
- m_descent = 0;
- m_lineGap = 0;
- m_lineSpacing = 0;
+ m_fontMetrics.reset();
m_avgCharWidth = 0;
m_maxCharWidth = 0;
- m_xHeight = 0;
- m_unitsPerEm = 0;
return;
}
@@ -88,26 +83,35 @@ void SimpleFontData::platformInit()
fastFree(vdmxTable);
}
+ float ascent;
+ float descent;
+
// Beware those who step here: This code is designed to match Win32 font
// metrics *exactly*.
if (isVDMXValid) {
- m_ascent = vdmxAscent;
- m_descent = -vdmxDescent;
+ ascent = vdmxAscent;
+ descent = -vdmxDescent;
} else {
SkScalar height = -metrics.fAscent + metrics.fDescent + metrics.fLeading;
- m_ascent = SkScalarRound(-metrics.fAscent);
- m_descent = SkScalarRound(height) - m_ascent;
+ ascent = SkScalarRound(-metrics.fAscent);
+ descent = SkScalarRound(height) - ascent;
}
+ m_fontMetrics.setAscent(ascent);
+ m_fontMetrics.setDescent(descent);
+
+ float xHeight;
if (metrics.fXHeight)
- m_xHeight = metrics.fXHeight;
+ xHeight = metrics.fXHeight;
else {
// hack taken from the Windows port
- m_xHeight = static_cast<float>(m_ascent) * 0.56;
+ xHeight = ascent * 0.56f;
}
- m_lineGap = SkScalarRound(metrics.fLeading);
- m_lineSpacing = m_ascent + m_descent + m_lineGap;
+ float lineGap = SkScalarToFloat(metrics.fLeading);
+ m_fontMetrics.setLineGap(lineGap);
+ m_fontMetrics.setXHeight(xHeight);
+ m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));
if (m_orientation == Vertical) {
static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a');
@@ -128,7 +132,7 @@ void SimpleFontData::platformInit()
if (metrics.fAvgCharWidth)
m_avgCharWidth = SkScalarRound(metrics.fAvgCharWidth);
else {
- m_avgCharWidth = m_xHeight;
+ m_avgCharWidth = xHeight;
GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
diff --git a/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp b/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp
index ba66eae..193271d 100644
--- a/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp
@@ -446,9 +446,9 @@ void TransparencyWin::compositeOpaqueComposite()
identity.reset();
destCanvas->setMatrix(identity);
- destRect.set(m_transformedSourceRect.x(), m_transformedSourceRect.y(), m_transformedSourceRect.right(), m_transformedSourceRect.bottom());
+ destRect.set(m_transformedSourceRect.x(), m_transformedSourceRect.y(), m_transformedSourceRect.maxX(), m_transformedSourceRect.maxY());
} else
- destRect.set(m_sourceRect.x(), m_sourceRect.y(), m_sourceRect.right(), m_sourceRect.bottom());
+ destRect.set(m_sourceRect.x(), m_sourceRect.y(), m_sourceRect.maxX(), m_sourceRect.maxY());
SkPaint paint;
paint.setFilterBitmap(true);
@@ -487,7 +487,7 @@ void TransparencyWin::compositeTextComposite()
SkMatrix identity;
identity.reset();
destCanvas->setMatrix(identity);
- SkRect destRect = { m_transformedSourceRect.x(), m_transformedSourceRect.y(), m_transformedSourceRect.right(), m_transformedSourceRect.bottom() };
+ SkRect destRect = { m_transformedSourceRect.x(), m_transformedSourceRect.y(), m_transformedSourceRect.maxX(), m_transformedSourceRect.maxY() };
// Note that we need to specify the source layer subset, since the bitmap
// may have been cached and it could be larger than what we're using.
diff --git a/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp b/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp
index aa18b4a..c060b43 100644
--- a/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp
+++ b/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp
@@ -51,14 +51,14 @@ UniscribeHelperTextRun::UniscribeHelperTextRun(const TextRun& run,
setLetterSpacing(font.letterSpacing());
setSpaceWidth(font.spaceWidth());
setWordSpacing(font.wordSpacing());
- setAscent(font.primaryFont()->ascent());
+ setAscent(font.fontMetrics().ascent());
init();
- // Padding is the amount to add to make justification happen. This
+ // Expansion is the amount to add to make justification happen. This
// should be done after Init() so all the runs are already measured.
- if (run.padding() > 0)
- justify(run.padding());
+ if (run.expansion() > 0)
+ justify(run.expansion());
}
UniscribeHelperTextRun::UniscribeHelperTextRun(
@@ -121,7 +121,7 @@ bool UniscribeHelperTextRun::nextWinFontData(
m_hfonts.append(simpleFontData->platformData().hfont());
m_scriptCaches.append(simpleFontData->platformData().scriptCache());
m_fontProperties.append(simpleFontData->platformData().scriptFontProperties());
- m_ascents.append(simpleFontData->ascent());
+ m_ascents.append(simpleFontData->fontMetrics().ascent());
}
*hfont = m_hfonts[m_fontIndex - 1];
diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
index 776b83f..41cd180 100644
--- a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
@@ -60,6 +60,7 @@ VideoLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context)
, m_rgbaShaderMatrixLocation(0)
, m_rgbaWidthScaleFactorLocation(0)
, m_ccMatrixLocation(0)
+ , m_signAdjLocation(0)
, m_yTextureLocation(0)
, m_uTextureLocation(0)
, m_vTextureLocation(0)
@@ -96,14 +97,15 @@ VideoLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context)
"uniform sampler2D u_texture; \n"
"uniform sampler2D v_texture; \n"
"uniform float alpha; \n"
+ "uniform float adj; \n"
"uniform mat3 cc_matrix; \n"
"void main() \n"
"{ \n"
" float y = texture2D(y_texture, v_texCoord).x; \n"
- " float u = texture2D(u_texture, v_texCoord).r - .5; \n"
- " float v = texture2D(v_texture, v_texCoord).r - .5; \n"
+ " float u = texture2D(u_texture, v_texCoord).x - adj; \n"
+ " float v = texture2D(v_texture, v_texCoord).x - adj; \n"
" vec3 rgb = cc_matrix * vec3(y, u, v); \n"
- " gl_FragColor = vec4(rgb.x, rgb.y, rgb.z, 1.0) * alpha; \n"
+ " gl_FragColor = vec4(rgb, float(1)) * alpha; \n"
"} \n";
char rgbaFragmentShaderString[] =
@@ -113,7 +115,7 @@ VideoLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context)
"uniform float alpha; \n"
"void main() \n"
"{ \n"
- " vec4 texColor = texture2D(rgba_texture, vec2(v_texCoord.x, 1.0 - v_texCoord.y)); \n"
+ " vec4 texColor = texture2D(rgba_texture, vec2(v_texCoord.x, float(1) - v_texCoord.y)); \n"
" gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n"
"} \n";
@@ -135,6 +137,7 @@ VideoLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context)
m_uTextureLocation = m_context->getUniformLocation(m_yuvShaderProgram, "u_texture");
m_vTextureLocation = m_context->getUniformLocation(m_yuvShaderProgram, "v_texture");
m_ccMatrixLocation = m_context->getUniformLocation(m_yuvShaderProgram, "cc_matrix");
+ m_signAdjLocation = m_context->getUniformLocation(m_yuvShaderProgram, "adj");
m_yuvAlphaLocation = m_context->getUniformLocation(m_yuvShaderProgram, "alpha");
ASSERT(m_yuvShaderMatrixLocation != -1);
@@ -143,6 +146,7 @@ VideoLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context)
ASSERT(m_uTextureLocation != -1);
ASSERT(m_vTextureLocation != -1);
ASSERT(m_ccMatrixLocation != -1);
+ ASSERT(m_signAdjLocation != -1);
ASSERT(m_yuvAlphaLocation != -1);
m_rgbaShaderMatrixLocation = m_context->getUniformLocation(m_rgbaShaderProgram, "matrix");
@@ -375,6 +379,12 @@ void VideoLayerChromium::drawYUV(const SharedValues* sv)
GLC(context, context->uniform1i(sv->uTextureLocation(), 2));
GLC(context, context->uniform1i(sv->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(sv->signAdjLocation(), 0.5));
+
GLC(context, context->uniformMatrix3fv(sv->ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1));
drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(),
diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h
index 0992ab7..ac3bca9 100644
--- a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h
@@ -70,6 +70,7 @@ public:
int rgbaAlphaLocation() const { return m_rgbaAlphaLocation; }
int rgbaTextureLocation() const { return m_rgbaTextureLocation; }
int ccMatrixLocation() const { return m_ccMatrixLocation; }
+ int signAdjLocation() const { return m_signAdjLocation; }
bool initialized() const { return m_initialized; }
private:
GraphicsContext3D* m_context;
@@ -80,6 +81,7 @@ public:
int m_rgbaShaderMatrixLocation;
int m_rgbaWidthScaleFactorLocation;
int m_ccMatrixLocation;
+ int m_signAdjLocation;
int m_yTextureLocation;
int m_uTextureLocation;
int m_vTextureLocation;
diff --git a/Source/WebCore/platform/graphics/cocoa/FontPlatformData.h b/Source/WebCore/platform/graphics/cocoa/FontPlatformData.h
index 8cf08fb..ca38029 100644
--- a/Source/WebCore/platform/graphics/cocoa/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/cocoa/FontPlatformData.h
@@ -25,6 +25,7 @@
#define FontPlatformData_h
#include "FontOrientation.h"
+#include "FontWidthVariant.h"
#include <wtf/text/StringImpl.h>
#ifdef __OBJC__
@@ -59,11 +60,12 @@ inline CTFontRef toCTFontRef(NSFont *nsFont) { return reinterpret_cast<CTFontRef
class FontPlatformData {
public:
- FontPlatformData(float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation = Horizontal)
+ 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)
@@ -72,13 +74,14 @@ class FontPlatformData {
{
}
- FontPlatformData(NSFont *nsFont, float size, bool syntheticBold = false, bool syntheticOblique = false, FontOrientation = Horizontal);
+ 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)
+ 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)
@@ -96,17 +99,20 @@ class FontPlatformData {
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[2] = { (uintptr_t)m_font, m_orientation << 2 | m_syntheticBold << 1 | m_syntheticOblique };
+ 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);
}
@@ -115,7 +121,7 @@ class FontPlatformData {
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_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; }
diff --git a/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm b/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm
index 8dacbe3..b40f698 100644
--- a/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm
+++ b/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm
@@ -30,6 +30,9 @@
namespace WebCore {
+// These CoreText Text Spacing feature selectors are not defined in CoreText.
+enum TextSpacingCTFeatureSelector { TextSpacingProportional, TextSpacingFullWidth, TextSpacingHalfWidth, TextSpacingThirdWidth, TextSpacingQuarterWidth };
+
#if PLATFORM(MAC)
void FontPlatformData::loadFont(NSFont* nsFont, float, NSFont*& outNSFont, CGFontRef& cgFont)
{
@@ -42,10 +45,11 @@ void FontPlatformData::loadFont(NSFont* nsFont, float, NSFont*& outNSFont, CGFon
}
#endif // PLATFORM(MAC)
-FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation)
+FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation, FontWidthVariant widthVariant)
: m_syntheticBold(syntheticBold)
, m_syntheticOblique(syntheticOblique)
, m_size(size)
+ , m_widthVariant(widthVariant)
, m_font(nsFont)
#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
// FIXME: Chromium: The following code isn't correct for the Chromium port since the sandbox might
@@ -79,6 +83,7 @@ FontPlatformData::FontPlatformData(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;
m_isColorBitmapFont = f.m_isColorBitmapFont;
m_orientation = f.m_orientation;
@@ -99,6 +104,7 @@ 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;
@@ -165,12 +171,48 @@ bool FontPlatformData::allowsLigatures() const
return ![[m_font coveredCharacterSet] characterIsMember:'a'];
}
+inline int mapFontWidthVariantToCTFeatureSelector(FontWidthVariant variant)
+{
+ switch(variant) {
+ case RegularWidth:
+ return TextSpacingProportional;
+
+ case HalfWidth:
+ return TextSpacingHalfWidth;
+
+ case ThirdWidth:
+ return TextSpacingThirdWidth;
+
+ case QuarterWidth:
+ return TextSpacingQuarterWidth;
+ }
+
+ ASSERT_NOT_REACHED();
+ return TextSpacingProportional;
+}
+
CTFontRef FontPlatformData::ctFont() const
{
- if (m_font)
- return toCTFontRef(m_font);
- if (!m_CTFont)
- m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_cgFont.get(), m_size, 0, 0));
+ if (m_widthVariant == RegularWidth) {
+ if (m_font)
+ return toCTFontRef(m_font);
+ if (!m_CTFont)
+ m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_cgFont.get(), m_size, 0, 0));
+ return m_CTFont.get();
+ }
+
+ if (!m_CTFont) {
+ int featureTypeValue = kTextSpacingType;
+ int featureSelectorValue = mapFontWidthVariantToCTFeatureSelector(m_widthVariant);
+ RetainPtr<CTFontRef> sourceFont(AdoptCF, CTFontCreateWithGraphicsFont(m_cgFont.get(), m_size, 0, 0));
+ RetainPtr<CTFontDescriptorRef> sourceDescriptor(AdoptCF, CTFontCopyFontDescriptor(sourceFont.get()));
+ RetainPtr<CFNumberRef> featureType(AdoptCF, CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &featureTypeValue));
+ RetainPtr<CFNumberRef> featureSelector(AdoptCF, CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &featureSelectorValue));
+ RetainPtr<CTFontDescriptorRef> newDescriptor(AdoptCF, CTFontDescriptorCreateCopyWithFeature(sourceDescriptor.get(), featureType.get(), featureSelector.get()));
+ RetainPtr<CTFontRef> newFont(AdoptCF, CTFontCreateWithFontDescriptor(newDescriptor.get(), m_size, 0));
+
+ m_CTFont = newFont.get() ? newFont : sourceFont;
+ }
return m_CTFont.get();
}
diff --git a/Source/WebCore/platform/graphics/efl/FontEfl.cpp b/Source/WebCore/platform/graphics/efl/FontEfl.cpp
index d3ca183..83cc7ff 100644
--- a/Source/WebCore/platform/graphics/efl/FontEfl.cpp
+++ b/Source/WebCore/platform/graphics/efl/FontEfl.cpp
@@ -50,6 +50,11 @@ bool Font::canReturnFallbackFontsForComplexText()
return false;
}
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+ return false;
+}
+
float Font::floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>*, GlyphOverflow*) const
{
notImplemented();
diff --git a/Source/WebCore/platform/graphics/filters/DistantLightSource.cpp b/Source/WebCore/platform/graphics/filters/DistantLightSource.cpp
new file mode 100644
index 0000000..4c3b49b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/DistantLightSource.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
+ * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2010 Zoltan Herczeg <zherczeg@webkit.org>
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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(FILTERS)
+#include "DistantLightSource.h"
+
+#include "RenderTreeAsText.h"
+
+namespace WebCore {
+
+void DistantLightSource::initPaintingData(PaintingData& paintingData)
+{
+ float azimuth = deg2rad(m_azimuth);
+ float elevation = deg2rad(m_elevation);
+ paintingData.lightVector.setX(cosf(azimuth) * cosf(elevation));
+ paintingData.lightVector.setY(sinf(azimuth) * cosf(elevation));
+ paintingData.lightVector.setZ(sinf(elevation));
+ paintingData.lightVectorLength = 1;
+}
+
+void DistantLightSource::updatePaintingData(PaintingData&, int, int, float)
+{
+}
+
+bool DistantLightSource::setAzimuth(float azimuth)
+{
+ if (m_azimuth == azimuth)
+ return false;
+ m_azimuth = azimuth;
+ return true;
+}
+
+bool DistantLightSource::setElevation(float elevation)
+{
+ if (m_elevation == elevation)
+ return false;
+ m_elevation = elevation;
+ return true;
+}
+
+TextStream& DistantLightSource::externalRepresentation(TextStream& ts) const
+{
+ ts << "[type=DISTANT-LIGHT] ";
+ ts << "[azimuth=\"" << azimuth() << "\"]";
+ ts << "[elevation=\"" << elevation() << "\"]";
+ return ts;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(FILTERS)
diff --git a/Source/WebCore/platform/graphics/filters/DistantLightSource.h b/Source/WebCore/platform/graphics/filters/DistantLightSource.h
index d5d474f..1e19c62 100644
--- a/Source/WebCore/platform/graphics/filters/DistantLightSource.h
+++ b/Source/WebCore/platform/graphics/filters/DistantLightSource.h
@@ -36,7 +36,9 @@ public:
}
float azimuth() const { return m_azimuth; }
+ bool setAzimuth(float);
float elevation() const { return m_elevation; }
+ bool setElevation(float);
virtual void initPaintingData(PaintingData&);
virtual void updatePaintingData(PaintingData&, int x, int y, float z);
diff --git a/Source/WebCore/platform/graphics/filters/FEDiffuseLighting.cpp b/Source/WebCore/platform/graphics/filters/FEDiffuseLighting.cpp
index a8a825a..5f9d049 100644
--- a/Source/WebCore/platform/graphics/filters/FEDiffuseLighting.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEDiffuseLighting.cpp
@@ -52,9 +52,12 @@ Color FEDiffuseLighting::lightingColor() const
return m_lightingColor;
}
-void FEDiffuseLighting::setLightingColor(const Color& lightingColor)
+bool FEDiffuseLighting::setLightingColor(const Color& lightingColor)
{
+ if (m_lightingColor == lightingColor)
+ return false;
m_lightingColor = lightingColor;
+ return true;
}
float FEDiffuseLighting::surfaceScale() const
@@ -62,9 +65,12 @@ float FEDiffuseLighting::surfaceScale() const
return m_surfaceScale;
}
-void FEDiffuseLighting::setSurfaceScale(float surfaceScale)
+bool FEDiffuseLighting::setSurfaceScale(float surfaceScale)
{
+ if (m_surfaceScale == surfaceScale)
+ return false;
m_surfaceScale = surfaceScale;
+ return true;
}
float FEDiffuseLighting::diffuseConstant() const
@@ -72,9 +78,12 @@ float FEDiffuseLighting::diffuseConstant() const
return m_diffuseConstant;
}
-void FEDiffuseLighting::setDiffuseConstant(float diffuseConstant)
+bool FEDiffuseLighting::setDiffuseConstant(float diffuseConstant)
{
+ if (m_diffuseConstant == diffuseConstant)
+ return false;
m_diffuseConstant = diffuseConstant;
+ return true;
}
float FEDiffuseLighting::kernelUnitLengthX() const
@@ -82,9 +91,12 @@ float FEDiffuseLighting::kernelUnitLengthX() const
return m_kernelUnitLengthX;
}
-void FEDiffuseLighting::setKernelUnitLengthX(float kernelUnitLengthX)
+bool FEDiffuseLighting::setKernelUnitLengthX(float kernelUnitLengthX)
{
+ if (m_kernelUnitLengthX == kernelUnitLengthX)
+ return false;
m_kernelUnitLengthX = kernelUnitLengthX;
+ return true;
}
float FEDiffuseLighting::kernelUnitLengthY() const
@@ -92,9 +104,12 @@ float FEDiffuseLighting::kernelUnitLengthY() const
return m_kernelUnitLengthY;
}
-void FEDiffuseLighting::setKernelUnitLengthY(float kernelUnitLengthY)
+bool FEDiffuseLighting::setKernelUnitLengthY(float kernelUnitLengthY)
{
+ if (m_kernelUnitLengthY == kernelUnitLengthY)
+ return false;
m_kernelUnitLengthY = kernelUnitLengthY;
+ return true;
}
const LightSource* FEDiffuseLighting::lightSource() const
diff --git a/Source/WebCore/platform/graphics/filters/FEDiffuseLighting.h b/Source/WebCore/platform/graphics/filters/FEDiffuseLighting.h
index b58b47a..5f20651 100644
--- a/Source/WebCore/platform/graphics/filters/FEDiffuseLighting.h
+++ b/Source/WebCore/platform/graphics/filters/FEDiffuseLighting.h
@@ -36,19 +36,19 @@ public:
virtual ~FEDiffuseLighting();
Color lightingColor() const;
- void setLightingColor(const Color&);
+ bool setLightingColor(const Color&);
float surfaceScale() const;
- void setSurfaceScale(float);
+ bool setSurfaceScale(float);
float diffuseConstant() const;
- void setDiffuseConstant(float);
+ bool setDiffuseConstant(float);
float kernelUnitLengthX() const;
- void setKernelUnitLengthX(float);
+ bool setKernelUnitLengthX(float);
float kernelUnitLengthY() const;
- void setKernelUnitLengthY(float);
+ bool setKernelUnitLengthY(float);
const LightSource* lightSource() const;
void setLightSource(PassRefPtr<LightSource>);
diff --git a/Source/WebCore/platform/graphics/filters/FilterEffect.cpp b/Source/WebCore/platform/graphics/filters/FilterEffect.cpp
index 85154b5..f07d00c 100644
--- a/Source/WebCore/platform/graphics/filters/FilterEffect.cpp
+++ b/Source/WebCore/platform/graphics/filters/FilterEffect.cpp
@@ -77,6 +77,16 @@ FilterEffect* FilterEffect::inputEffect(unsigned number) const
return m_inputEffects.at(number).get();
}
+void FilterEffect::clearResult()
+{
+ if (m_imageBufferResult)
+ m_imageBufferResult.clear();
+ if (m_unmultipliedImageResult)
+ m_unmultipliedImageResult.clear();
+ if (m_premultipliedImageResult)
+ m_premultipliedImageResult.clear();
+}
+
ImageBuffer* FilterEffect::asImageBuffer()
{
if (!hasResult())
@@ -109,7 +119,7 @@ PassRefPtr<ByteArray> FilterEffect::asPremultipliedImage(const IntRect& rect)
inline void FilterEffect::copyImageBytes(ByteArray* source, ByteArray* destination, const IntRect& rect)
{
// Copy the necessary lines.
- if (rect.x() < 0 || rect.y() < 0 || rect.bottom() > m_absolutePaintRect.width() || rect.bottom() > m_absolutePaintRect.height())
+ if (rect.x() < 0 || rect.y() < 0 || rect.maxY() > m_absolutePaintRect.width() || rect.maxY() > m_absolutePaintRect.height())
memset(destination->data(), 0, destination->length());
int xOrigin = rect.x();
@@ -118,7 +128,7 @@ inline void FilterEffect::copyImageBytes(ByteArray* source, ByteArray* destinati
xDest = -xOrigin;
xOrigin = 0;
}
- int xEnd = rect.right();
+ int xEnd = rect.maxX();
if (xEnd > m_absolutePaintRect.width())
xEnd = m_absolutePaintRect.width();
@@ -128,7 +138,7 @@ inline void FilterEffect::copyImageBytes(ByteArray* source, ByteArray* destinati
yDest = -yOrigin;
yOrigin = 0;
}
- int yEnd = rect.bottom();
+ int yEnd = rect.maxY();
if (yEnd > m_absolutePaintRect.height())
yEnd = m_absolutePaintRect.height();
diff --git a/Source/WebCore/platform/graphics/filters/FilterEffect.h b/Source/WebCore/platform/graphics/filters/FilterEffect.h
index 062dd1b..2de8ac5 100644
--- a/Source/WebCore/platform/graphics/filters/FilterEffect.h
+++ b/Source/WebCore/platform/graphics/filters/FilterEffect.h
@@ -53,6 +53,7 @@ public:
virtual ~FilterEffect();
bool hasResult() const { return m_imageBufferResult || m_unmultipliedImageResult || m_premultipliedImageResult; }
+ void clearResult();
ImageBuffer* asImageBuffer();
PassRefPtr<ByteArray> asUnmultipliedImage(const IntRect&);
PassRefPtr<ByteArray> asPremultipliedImage(const IntRect&);
diff --git a/Source/WebCore/platform/graphics/filters/LightSource.cpp b/Source/WebCore/platform/graphics/filters/LightSource.cpp
index de0691e..cf262e8 100644
--- a/Source/WebCore/platform/graphics/filters/LightSource.cpp
+++ b/Source/WebCore/platform/graphics/filters/LightSource.cpp
@@ -3,6 +3,7 @@
* Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
* Copyright (C) 2005 Eric Seidel <eric@webkit.org>
* Copyright (C) 2010 Zoltan Herczeg <zherczeg@webkit.org>
+ * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>, University of Szeged.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -33,136 +34,80 @@
namespace WebCore {
-void PointLightSource::initPaintingData(PaintingData&)
+bool LightSource::setAzimuth(float azimuth)
{
+ if (m_type == LS_DISTANT)
+ return static_cast<DistantLightSource*>(this)->setAzimuth(azimuth);
+ return false;
}
-void PointLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z)
+bool LightSource::setElevation(float elevation)
{
- paintingData.lightVector.setX(m_position.x() - x);
- paintingData.lightVector.setY(m_position.y() - y);
- paintingData.lightVector.setZ(m_position.z() - z);
- paintingData.lightVectorLength = paintingData.lightVector.length();
+ if (m_type == LS_DISTANT)
+ return static_cast<DistantLightSource*>(this)->setElevation(elevation);
+ return false;
}
-// spot-light edge darkening depends on an absolute treshold
-// according to the SVG 1.1 SE light regression tests
-static const float antiAliasTreshold = 0.016f;
-
-void SpotLightSource::initPaintingData(PaintingData& paintingData)
+bool LightSource::setX(float x)
{
- paintingData.privateColorVector = paintingData.colorVector;
- paintingData.directionVector.setX(m_direction.x() - m_position.x());
- paintingData.directionVector.setY(m_direction.y() - m_position.y());
- paintingData.directionVector.setZ(m_direction.z() - m_position.z());
- paintingData.directionVector.normalize();
-
- if (!m_limitingConeAngle) {
- paintingData.coneCutOffLimit = 0.0f;
- paintingData.coneFullLight = -antiAliasTreshold;
- } else {
- float limitingConeAngle = m_limitingConeAngle;
- if (limitingConeAngle < 0.0f)
- limitingConeAngle = -limitingConeAngle;
- if (limitingConeAngle > 90.0f)
- limitingConeAngle = 90.0f;
- paintingData.coneCutOffLimit = cosf(deg2rad(180.0f - limitingConeAngle));
- paintingData.coneFullLight = paintingData.coneCutOffLimit - antiAliasTreshold;
- }
-
- // Optimization for common specularExponent values
- if (!m_specularExponent)
- paintingData.specularExponent = 0;
- else if (m_specularExponent == 1.0f)
- paintingData.specularExponent = 1;
- else // It is neither 0.0f nor 1.0f
- paintingData.specularExponent = 2;
+ if (m_type == LS_SPOT)
+ return static_cast<SpotLightSource*>(this)->setX(x);
+ if (m_type == LS_POINT)
+ return static_cast<PointLightSource*>(this)->setX(x);
+ return false;
}
-void SpotLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z)
+bool LightSource::setY(float y)
{
- paintingData.lightVector.setX(m_position.x() - x);
- paintingData.lightVector.setY(m_position.y() - y);
- paintingData.lightVector.setZ(m_position.z() - z);
- paintingData.lightVectorLength = paintingData.lightVector.length();
-
- float cosineOfAngle = (paintingData.lightVector * paintingData.directionVector) / paintingData.lightVectorLength;
- if (cosineOfAngle > paintingData.coneCutOffLimit) {
- // No light is produced, scanlines are not updated
- paintingData.colorVector.setX(0.0f);
- paintingData.colorVector.setY(0.0f);
- paintingData.colorVector.setZ(0.0f);
- return;
- }
-
- // Set the color of the pixel
- float lightStrength;
- switch (paintingData.specularExponent) {
- case 0:
- lightStrength = 1.0f; // -cosineOfAngle ^ 0 == 1
- break;
- case 1:
- lightStrength = -cosineOfAngle; // -cosineOfAngle ^ 1 == -cosineOfAngle
- break;
- default:
- lightStrength = powf(-cosineOfAngle, m_specularExponent);
- break;
- }
-
- if (cosineOfAngle > paintingData.coneFullLight)
- lightStrength *= (paintingData.coneCutOffLimit - cosineOfAngle) / (paintingData.coneCutOffLimit - paintingData.coneFullLight);
-
- if (lightStrength > 1.0f)
- lightStrength = 1.0f;
-
- paintingData.colorVector.setX(paintingData.privateColorVector.x() * lightStrength);
- paintingData.colorVector.setY(paintingData.privateColorVector.y() * lightStrength);
- paintingData.colorVector.setZ(paintingData.privateColorVector.z() * lightStrength);
+ if (m_type == LS_SPOT)
+ return static_cast<SpotLightSource*>(this)->setY(y);
+ if (m_type == LS_POINT)
+ return static_cast<PointLightSource*>(this)->setY(y);
+ return false;
}
-void DistantLightSource::initPaintingData(PaintingData& paintingData)
+bool LightSource::setZ(float z)
{
- float azimuth = deg2rad(m_azimuth);
- float elevation = deg2rad(m_elevation);
- paintingData.lightVector.setX(cosf(azimuth) * cosf(elevation));
- paintingData.lightVector.setY(sinf(azimuth) * cosf(elevation));
- paintingData.lightVector.setZ(sinf(elevation));
- paintingData.lightVectorLength = 1;
+ if (m_type == LS_SPOT)
+ return static_cast<SpotLightSource*>(this)->setZ(z);
+ if (m_type == LS_POINT)
+ return static_cast<PointLightSource*>(this)->setZ(z);
+ return false;
}
-void DistantLightSource::updatePaintingData(PaintingData&, int, int, float)
+bool LightSource::setPointsAtX(float pointsAtX)
{
+ if (m_type == LS_SPOT)
+ return static_cast<SpotLightSource*>(this)->setPointsAtX(pointsAtX);
+ return false;
}
-static TextStream& operator<<(TextStream& ts, const FloatPoint3D& p)
+bool LightSource::setPointsAtY(float pointsAtY)
{
- ts << "x=" << p.x() << " y=" << p.y() << " z=" << p.z();
- return ts;
+ if (m_type == LS_SPOT)
+ return static_cast<SpotLightSource*>(this)->setPointsAtY(pointsAtY);
+ return false;
}
-TextStream& PointLightSource::externalRepresentation(TextStream& ts) const
+bool LightSource::setPointsAtZ(float pointsAtZ)
{
- ts << "[type=POINT-LIGHT] ";
- ts << "[position=\"" << position() << "\"]";
- return ts;
+ if (m_type == LS_SPOT)
+ return static_cast<SpotLightSource*>(this)->setPointsAtZ(pointsAtZ);
+ return false;
}
-TextStream& SpotLightSource::externalRepresentation(TextStream& ts) const
+bool LightSource::setSpecularExponent(float specularExponent)
{
- ts << "[type=SPOT-LIGHT] ";
- ts << "[position=\"" << position() << "\"]";
- ts << "[direction=\"" << direction() << "\"]";
- ts << "[specularExponent=\"" << specularExponent() << "\"]";
- ts << "[limitingConeAngle=\"" << limitingConeAngle() << "\"]";
- return ts;
+ if (m_type == LS_SPOT)
+ return static_cast<SpotLightSource*>(this)->setSpecularExponent(specularExponent);
+ return false;
}
-TextStream& DistantLightSource::externalRepresentation(TextStream& ts) const
+bool LightSource::setLimitingConeAngle(float limitingConeAngle)
{
- ts << "[type=DISTANT-LIGHT] ";
- ts << "[azimuth=\"" << azimuth() << "\"]";
- ts << "[elevation=\"" << elevation() << "\"]";
- return ts;
+ if (m_type == LS_SPOT)
+ return static_cast<SpotLightSource*>(this)->setLimitingConeAngle(limitingConeAngle);
+ return false;
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/filters/LightSource.h b/Source/WebCore/platform/graphics/filters/LightSource.h
index 013e910..24c319a 100644
--- a/Source/WebCore/platform/graphics/filters/LightSource.h
+++ b/Source/WebCore/platform/graphics/filters/LightSource.h
@@ -74,6 +74,17 @@ public:
// specified "surfaceScale" constant, which type is <number> in the SVG standard
virtual void updatePaintingData(PaintingData&, int x, int y, float z) = 0;
+ bool setAzimuth(float);
+ bool setElevation(float);
+ bool setX(float);
+ bool setY(float);
+ bool setZ(float);
+ bool setPointsAtX(float);
+ bool setPointsAtY(float);
+ bool setPointsAtZ(float);
+ bool setSpecularExponent(float);
+ bool setLimitingConeAngle(float);
+
private:
LightType m_type;
};
diff --git a/Source/WebCore/platform/graphics/filters/PointLightSource.cpp b/Source/WebCore/platform/graphics/filters/PointLightSource.cpp
new file mode 100644
index 0000000..207ed8e
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/PointLightSource.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
+ * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2010 Zoltan Herczeg <zherczeg@webkit.org>
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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(FILTERS)
+#include "PointLightSource.h"
+
+#include "TextStream.h"
+
+namespace WebCore {
+
+void PointLightSource::initPaintingData(PaintingData&)
+{
+}
+
+void PointLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z)
+{
+ paintingData.lightVector.setX(m_position.x() - x);
+ paintingData.lightVector.setY(m_position.y() - y);
+ paintingData.lightVector.setZ(m_position.z() - z);
+ paintingData.lightVectorLength = paintingData.lightVector.length();
+}
+
+bool PointLightSource::setX(float x)
+{
+ if (m_position.x() == x)
+ return false;
+ m_position.setX(x);
+ return true;
+}
+
+bool PointLightSource::setY(float y)
+{
+ if (m_position.y() == y)
+ return false;
+ m_position.setY(y);
+ return true;
+}
+
+bool PointLightSource::setZ(float z)
+{
+ if (m_position.z() == z)
+ return false;
+ m_position.setZ(z);
+ return true;
+}
+
+static TextStream& operator<<(TextStream& ts, const FloatPoint3D& p)
+{
+ ts << "x=" << p.x() << " y=" << p.y() << " z=" << p.z();
+ return ts;
+}
+
+TextStream& PointLightSource::externalRepresentation(TextStream& ts) const
+{
+ ts << "[type=POINT-LIGHT] ";
+ ts << "[position=\"" << position() << "\"]";
+ return ts;
+}
+
+}; // namespace WebCore
+
+#endif // ENABLE(FILTERS)
diff --git a/Source/WebCore/platform/graphics/filters/PointLightSource.h b/Source/WebCore/platform/graphics/filters/PointLightSource.h
index 163c829..a93bf2c 100644
--- a/Source/WebCore/platform/graphics/filters/PointLightSource.h
+++ b/Source/WebCore/platform/graphics/filters/PointLightSource.h
@@ -36,6 +36,9 @@ public:
}
const FloatPoint3D& position() const { return m_position; }
+ bool setX(float);
+ bool setY(float);
+ bool setZ(float);
virtual void initPaintingData(PaintingData&);
virtual void updatePaintingData(PaintingData&, int x, int y, float z);
diff --git a/Source/WebCore/platform/graphics/filters/SpotLightSource.cpp b/Source/WebCore/platform/graphics/filters/SpotLightSource.cpp
new file mode 100644
index 0000000..648fcae
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/SpotLightSource.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com>
+ * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
+ * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2010 Zoltan Herczeg <zherczeg@webkit.org>
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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(FILTERS)
+#include "SpotLightSource.h"
+
+#include "TextStream.h"
+
+namespace WebCore {
+
+// spot-light edge darkening depends on an absolute treshold
+// according to the SVG 1.1 SE light regression tests
+static const float antiAliasTreshold = 0.016f;
+
+void SpotLightSource::initPaintingData(PaintingData& paintingData)
+{
+ paintingData.privateColorVector = paintingData.colorVector;
+ paintingData.directionVector.setX(m_direction.x() - m_position.x());
+ paintingData.directionVector.setY(m_direction.y() - m_position.y());
+ paintingData.directionVector.setZ(m_direction.z() - m_position.z());
+ paintingData.directionVector.normalize();
+
+ if (!m_limitingConeAngle) {
+ paintingData.coneCutOffLimit = 0.0f;
+ paintingData.coneFullLight = -antiAliasTreshold;
+ } else {
+ float limitingConeAngle = m_limitingConeAngle;
+ if (limitingConeAngle < 0.0f)
+ limitingConeAngle = -limitingConeAngle;
+ if (limitingConeAngle > 90.0f)
+ limitingConeAngle = 90.0f;
+ paintingData.coneCutOffLimit = cosf(deg2rad(180.0f - limitingConeAngle));
+ paintingData.coneFullLight = paintingData.coneCutOffLimit - antiAliasTreshold;
+ }
+
+ // Optimization for common specularExponent values
+ if (!m_specularExponent)
+ paintingData.specularExponent = 0;
+ else if (m_specularExponent == 1.0f)
+ paintingData.specularExponent = 1;
+ else // It is neither 0.0f nor 1.0f
+ paintingData.specularExponent = 2;
+}
+
+void SpotLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z)
+{
+ paintingData.lightVector.setX(m_position.x() - x);
+ paintingData.lightVector.setY(m_position.y() - y);
+ paintingData.lightVector.setZ(m_position.z() - z);
+ paintingData.lightVectorLength = paintingData.lightVector.length();
+
+ float cosineOfAngle = (paintingData.lightVector * paintingData.directionVector) / paintingData.lightVectorLength;
+ if (cosineOfAngle > paintingData.coneCutOffLimit) {
+ // No light is produced, scanlines are not updated
+ paintingData.colorVector.setX(0.0f);
+ paintingData.colorVector.setY(0.0f);
+ paintingData.colorVector.setZ(0.0f);
+ return;
+ }
+
+ // Set the color of the pixel
+ float lightStrength;
+ switch (paintingData.specularExponent) {
+ case 0:
+ lightStrength = 1.0f; // -cosineOfAngle ^ 0 == 1
+ break;
+ case 1:
+ lightStrength = -cosineOfAngle; // -cosineOfAngle ^ 1 == -cosineOfAngle
+ break;
+ default:
+ lightStrength = powf(-cosineOfAngle, m_specularExponent);
+ break;
+ }
+
+ if (cosineOfAngle > paintingData.coneFullLight)
+ lightStrength *= (paintingData.coneCutOffLimit - cosineOfAngle) / (paintingData.coneCutOffLimit - paintingData.coneFullLight);
+
+ if (lightStrength > 1.0f)
+ lightStrength = 1.0f;
+
+ paintingData.colorVector.setX(paintingData.privateColorVector.x() * lightStrength);
+ paintingData.colorVector.setY(paintingData.privateColorVector.y() * lightStrength);
+ paintingData.colorVector.setZ(paintingData.privateColorVector.z() * lightStrength);
+}
+
+bool SpotLightSource::setX(float x)
+{
+ if (m_position.x() == x)
+ return false;
+ m_position.setX(x);
+ return true;
+}
+
+bool SpotLightSource::setY(float y)
+{
+ if (m_position.y() == y)
+ return false;
+ m_position.setY(y);
+ return true;
+}
+
+bool SpotLightSource::setZ(float z)
+{
+ if (m_position.z() == z)
+ return false;
+ m_position.setZ(z);
+ return true;
+}
+
+bool SpotLightSource::setPointsAtX(float pointsAtX)
+{
+ if (m_direction.x() == pointsAtX)
+ return false;
+ m_direction.setX(pointsAtX);
+ return true;
+}
+
+bool SpotLightSource::setPointsAtY(float pointsAtY)
+{
+ if (m_direction.y() == pointsAtY)
+ return false;
+ m_direction.setY(pointsAtY);
+ return true;
+}
+
+bool SpotLightSource::setPointsAtZ(float pointsAtZ)
+{
+ if (m_direction.z() == pointsAtZ)
+ return false;
+ m_direction.setZ(pointsAtZ);
+ return true;
+}
+
+bool SpotLightSource::setSpecularExponent(float specularExponent)
+{
+ if (m_specularExponent == specularExponent)
+ return false;
+ m_specularExponent = specularExponent;
+ return true;
+}
+
+bool SpotLightSource::setLimitingConeAngle(float limitingConeAngle)
+{
+ if (m_limitingConeAngle == limitingConeAngle)
+ return false;
+ m_limitingConeAngle = limitingConeAngle;
+ return true;
+}
+
+static TextStream& operator<<(TextStream& ts, const FloatPoint3D& p)
+{
+ ts << "x=" << p.x() << " y=" << p.y() << " z=" << p.z();
+ return ts;
+}
+
+TextStream& SpotLightSource::externalRepresentation(TextStream& ts) const
+{
+ ts << "[type=SPOT-LIGHT] ";
+ ts << "[position=\"" << position() << "\"]";
+ ts << "[direction=\"" << direction() << "\"]";
+ ts << "[specularExponent=\"" << specularExponent() << "\"]";
+ ts << "[limitingConeAngle=\"" << limitingConeAngle() << "\"]";
+ return ts;
+}
+
+}; // namespace WebCore
+
+#endif // ENABLE(FILTERS)
diff --git a/Source/WebCore/platform/graphics/filters/SpotLightSource.h b/Source/WebCore/platform/graphics/filters/SpotLightSource.h
index cd6a614..b4f1b61 100644
--- a/Source/WebCore/platform/graphics/filters/SpotLightSource.h
+++ b/Source/WebCore/platform/graphics/filters/SpotLightSource.h
@@ -37,10 +37,18 @@ public:
}
const FloatPoint3D& position() const { return m_position; }
+ bool setX(float);
+ bool setY(float);
+ bool setZ(float);
const FloatPoint3D& direction() const { return m_direction; }
+ bool setPointsAtX(float);
+ bool setPointsAtY(float);
+ bool setPointsAtZ(float);
float specularExponent() const { return m_specularExponent; }
+ bool setSpecularExponent(float);
float limitingConeAngle() const { return m_limitingConeAngle; }
+ bool setLimitingConeAngle(float);
virtual void initPaintingData(PaintingData&);
virtual void updatePaintingData(PaintingData&, int x, int y, float z);
diff --git a/Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp b/Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp
index c547224..841c8a3 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, FontRenderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode)
{
return FontPlatformData(m_fontFace, size, bold, italic);
}
diff --git a/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp b/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp
index 97fd81a..6290eeb 100644
--- a/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp
+++ b/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp
@@ -50,21 +50,28 @@ void SimpleFontData::platformInit()
cairo_font_extents_t font_extents;
cairo_text_extents_t text_extents;
cairo_scaled_font_extents(m_platformData.scaledFont(), &font_extents);
- m_ascent = static_cast<int>(lroundf(font_extents.ascent));
- m_descent = static_cast<int>(lroundf(font_extents.descent));
- m_lineSpacing = static_cast<int>(lroundf(font_extents.height));
+
+ m_fontMetrics.setAscent(font_extents.ascent);
+ m_fontMetrics.setDescent(font_extents.descent);
+
// There seems to be some rounding error in cairo (or in how we
// use cairo) with some fonts, like DejaVu Sans Mono, which makes
// cairo report a height smaller than ascent + descent, which is
// wrong and confuses WebCore's layout system. Workaround this
// while we figure out what's going on.
- if (m_lineSpacing < m_ascent + m_descent)
- m_lineSpacing = m_ascent + m_descent;
+ float lineSpacing = font_extents.height;
+ if (lineSpacing < font_extents.ascent + font_extents.descent)
+ lineSpacing = font_extents.ascent + font_extents.descent;
+
+ m_fontMetrics.setLineSpacing(lroundf(lineSpacing));
+ m_fontMetrics.setLineGap(lineSpacing - font_extents.ascent - font_extents.descent);
+
cairo_scaled_font_text_extents(m_platformData.scaledFont(), "x", &text_extents);
- m_xHeight = text_extents.height;
+ m_fontMetrics.setXHeight(text_extents.height);
+
cairo_scaled_font_text_extents(m_platformData.scaledFont(), " ", &text_extents);
m_spaceWidth = static_cast<float>(text_extents.x_advance);
- m_lineGap = m_lineSpacing - m_ascent - m_descent;
+
m_syntheticBoldOffset = m_platformData.syntheticBold() ? 1.0f : 0.f;
}
diff --git a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
index dae83a2..2a83fcf 100644
--- a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
@@ -30,7 +30,7 @@
#include "config.h"
-#if ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(3D_CANVAS)
+#if ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(WEBGL)
#include "DrawingBuffer.h"
@@ -41,10 +41,11 @@ namespace WebCore {
PassRefPtr<DrawingBuffer> DrawingBuffer::create(GraphicsContext3D* context, const IntSize& size)
{
Extensions3D* extensions = context->getExtensions();
- bool multisampleSupported = extensions->supports("GL_ANGLE_framebuffer_blit") && extensions->supports("GL_ANGLE_framebuffer_multisample");
+ bool multisampleSupported = extensions->supports("GL_ANGLE_framebuffer_blit") && extensions->supports("GL_ANGLE_framebuffer_multisample") && extensions->supports("GL_OES_rgb8_rgba8");
if (multisampleSupported) {
extensions->ensureEnabled("GL_ANGLE_framebuffer_blit");
extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample");
+ extensions->ensureEnabled("GL_OES_rgb8_rgba8");
}
bool packedDepthStencilSupported = extensions->supports("GL_OES_packed_depth_stencil");
if (packedDepthStencilSupported)
@@ -145,8 +146,6 @@ void DrawingBuffer::resizeDepthStencil(int sampleCount)
void DrawingBuffer::reset(const IntSize& newSize)
{
- if (m_size == newSize)
- return;
m_size = newSize;
if (!m_context)
@@ -155,13 +154,15 @@ void DrawingBuffer::reset(const IntSize& newSize)
m_context->makeContextCurrent();
const GraphicsContext3D::Attributes& attributes = m_context->getContextAttributes();
- unsigned long internalColorFormat, colorFormat;
+ unsigned long internalColorFormat, colorFormat, internalRenderbufferFormat;
if (attributes.alpha) {
internalColorFormat = GraphicsContext3D::RGBA;
colorFormat = GraphicsContext3D::RGBA;
+ internalRenderbufferFormat = Extensions3D::RGBA8_OES;
} else {
internalColorFormat = GraphicsContext3D::RGB;
colorFormat = GraphicsContext3D::RGB;
+ internalRenderbufferFormat = Extensions3D::RGB8_OES;
}
@@ -175,7 +176,7 @@ void DrawingBuffer::reset(const IntSize& newSize)
m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer);
- m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, internalColorFormat, m_size.width(), m_size.height());
+ m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, internalRenderbufferFormat, m_size.width(), m_size.height());
m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer);
resizeDepthStencil(sampleCount);
if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
@@ -192,7 +193,8 @@ void DrawingBuffer::reset(const IntSize& newSize)
m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE);
m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0);
m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
- resizeDepthStencil(0);
+ if (!multisample())
+ resizeDepthStencil(0);
if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
// Cleanup
clear();
diff --git a/Source/WebCore/platform/graphics/gpu/LoopBlinnPathCache.cpp b/Source/WebCore/platform/graphics/gpu/LoopBlinnPathCache.cpp
new file mode 100644
index 0000000..35f15e5
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/LoopBlinnPathCache.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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"
+
+#include "LoopBlinnPathCache.h"
+
+namespace WebCore {
+
+LoopBlinnPathCache::LoopBlinnPathCache()
+{
+}
+
+LoopBlinnPathCache::~LoopBlinnPathCache()
+{
+}
+
+void LoopBlinnPathCache::addVertex(float x, float y,
+ float k, float l, float m)
+{
+ m_vertices.append(x);
+ m_vertices.append(y);
+ m_texcoords.append(k);
+ m_texcoords.append(l);
+ m_texcoords.append(m);
+}
+
+void LoopBlinnPathCache::clear()
+{
+ m_vertices.clear();
+ m_texcoords.clear();
+ m_interiorVertices.clear();
+#ifdef LOOP_BLINN_PATH_CACHE_DEBUG_INTERIOR_EDGES
+ m_interiorEdgeVertices.clear();
+#endif // LOOP_BLINN_PATH_CACHE_DEBUG_INTERIOR_EDGES
+}
+
+void LoopBlinnPathCache::addInteriorVertex(float x, float y)
+{
+ m_interiorVertices.append(x);
+ m_interiorVertices.append(y);
+}
+
+#ifdef LOOP_BLINN_PATH_CACHE_DEBUG_INTERIOR_EDGES
+unsigned LoopBlinnPathCache::numberOfInteriorEdgeVertices() const
+{
+ return m_interiorEdgeVertices.size() / 2;
+}
+
+const float* LoopBlinnPathCache::interiorEdgeVertices() const
+{
+ if (!numberOfInteriorEdgeVertices())
+ return 0;
+ return m_interiorEdgeVertices.data();
+}
+
+void LoopBlinnPathCache::addInteriorEdgeVertex(float x, float y)
+{
+ m_interiorEdgeVertices.append(x);
+ m_interiorEdgeVertices.append(y);
+}
+#endif // LOOP_BLINN_PATH_CACHE_DEBUG_INTERIOR_EDGES
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/gpu/LoopBlinnPathCache.h b/Source/WebCore/platform/graphics/gpu/LoopBlinnPathCache.h
new file mode 100644
index 0000000..d21d246
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/LoopBlinnPathCache.h
@@ -0,0 +1,123 @@
+/*
+ * 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 LoopBlinnPathCache_h
+#define LoopBlinnPathCache_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+// A cache of the processed triangle mesh for a given path. Because these
+// might be expensive to allocate (using malloc/free internally), it is
+// recommended to try to reuse them when possible.
+
+// Uncomment the following to obtain debugging information for the edges
+// facing the interior region of the mesh.
+// #define LOOP_BLINN_PATH_CACHE_DEBUG_INTERIOR_EDGES
+
+class LoopBlinnPathCache {
+ WTF_MAKE_NONCOPYABLE(LoopBlinnPathCache);
+public:
+ LoopBlinnPathCache();
+ ~LoopBlinnPathCache();
+
+ unsigned numberOfVertices() const { return m_vertices.size() / 2; }
+
+ // Get the base pointer to the vertex information. There are two
+ // coordinates per vertex. This pointer is valid until the cache is
+ // cleared or another vertex is added. Returns 0 if there are no
+ // vertices in the mesh.
+ const float* vertices() const
+ {
+ if (!numberOfVertices())
+ return 0;
+ return m_vertices.data();
+ }
+
+ // Get the base pointer to the texture coordinate information. There
+ // are three coordinates per vertex. This pointer is valid until the
+ // cache is cleared or another vertex is added. Returns 0 if
+ // there are no vertices in the mesh.
+ const float* texcoords() const
+ {
+ if (!numberOfVertices())
+ return 0;
+ return m_texcoords.data();
+ }
+
+ // Adds a vertex's information to the cache. The first two arguments
+ // are the x and y coordinates of the vertex on the plane; the last
+ // three arguments are the cubic texture coordinates associated with
+ // this vertex.
+ void addVertex(float x, float y,
+ float /*k*/, float /*l*/, float /*m*/);
+
+ unsigned numberOfInteriorVertices() const { return m_interiorVertices.size() / 2; }
+
+ // Base pointer to the interior vertices; two coordinates per
+ // vertex, which can be drawn as GL_TRIANGLES. Returns 0 if there
+ // are no interior vertices in the mesh.
+ const float* interiorVertices() const
+ {
+ if (!numberOfInteriorVertices())
+ return 0;
+ return m_interiorVertices.data();
+ }
+
+ void addInteriorVertex(float x, float y);
+
+ // Clears all of the stored vertex information in this cache.
+ void clear();
+
+#ifdef LOOP_BLINN_PATH_CACHE_DEBUG_INTERIOR_EDGES
+ // The number of interior edge vertices
+ unsigned numberOfInteriorEdgeVertices() const;
+ // Base pointer to the interior vertices; two coordinates per
+ // vertex, which can be drawn as GL_LINES. Returns 0 if there are
+ // no interior edge vertices in the mesh.
+ const float* interiorEdgeVertices() const;
+ void addInteriorEdgeVertex(float x, float y);
+#endif // LOOP_BLINN_PATH_CACHE_DEBUG_INTERIOR_EDGES
+
+private:
+ // The two-dimensional vertices of the triangle mesh.
+ Vector<float> m_vertices;
+
+ // The three-dimensional cubic texture coordinates.
+ Vector<float> m_texcoords;
+
+ Vector<float> m_interiorVertices;
+
+#ifdef LOOP_BLINN_PATH_CACHE_DEBUG_INTERIOR_EDGES
+ // The following is only for debugging
+ Vector<float> m_interiorEdgeVertices;
+#endif // LOOP_BLINN_PATH_CACHE_DEBUG_INTERIOR_EDGES
+};
+
+} // namespace WebCore
+
+#endif // LoopBlinnPathCache_h
diff --git a/Source/WebCore/platform/graphics/gpu/LoopBlinnPathProcessor.cpp b/Source/WebCore/platform/graphics/gpu/LoopBlinnPathProcessor.cpp
new file mode 100644
index 0000000..e84ddbf
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/LoopBlinnPathProcessor.cpp
@@ -0,0 +1,1228 @@
+/*
+ * 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"
+
+#include "LoopBlinnPathProcessor.h"
+
+#include "FloatPoint.h"
+#include "FloatRect.h"
+#include "LoopBlinnClassifier.h"
+#include "LoopBlinnConstants.h"
+#include "LoopBlinnLocalTriangulator.h"
+#include "LoopBlinnMathUtils.h"
+#include "LoopBlinnPathCache.h"
+#include "LoopBlinnTextureCoords.h"
+#include "PODArena.h"
+#include "PODIntervalTree.h"
+#include "Path.h"
+#include "internal_glu.h"
+#include <algorithm>
+#include <wtf/Assertions.h>
+#include <wtf/FastMalloc.h>
+
+#if PLATFORM(SKIA)
+#include "SkGeometry.h"
+#include "SkPath.h"
+#include "SkScalar.h"
+#else
+// Must port to your platform.
+#endif
+
+namespace WebCore {
+
+using LoopBlinnMathUtils::XRay;
+using LoopBlinnMathUtils::chopCubicAt;
+using LoopBlinnMathUtils::numXRayCrossingsForCubic;
+using LoopBlinnMathUtils::trianglesOverlap;
+using LoopBlinnMathUtils::xRayCrossesLine;
+using LoopBlinnPathProcessorImplementation::Contour;
+using LoopBlinnPathProcessorImplementation::Segment;
+
+namespace {
+
+#ifndef NDEBUG
+String valueToString(const FloatRect& arg)
+{
+ StringBuilder builder;
+ builder.append("[FloatRect x=");
+ builder.append(String::number(arg.x()));
+ builder.append(" y=");
+ builder.append(String::number(arg.y()));
+ builder.append(" maxX=");
+ builder.append(String::number(arg.maxX()));
+ builder.append(" maxY=");
+ builder.append(String::number(arg.maxY()));
+ builder.append("]");
+ return builder.toString();
+}
+#endif
+
+struct SweepData;
+
+} // anonymous namespace
+
+namespace LoopBlinnPathProcessorImplementation {
+class Segment;
+}
+
+#ifndef NDEBUG
+// Routines needed to print the types of IntervalNodes we instantiate
+// in this file.
+template <>
+struct ValueToString<float> {
+ static String string(const float& value)
+ {
+ return String::number(value);
+ }
+};
+
+template <>
+struct ValueToString<SweepData*> {
+ static String string(SweepData* const& value)
+ {
+ return String::format("0x%p", value);
+ }
+};
+
+template <>
+struct ValueToString<LoopBlinnPathProcessorImplementation::Segment*> {
+ static String string(LoopBlinnPathProcessorImplementation::Segment* const& value)
+ {
+ return String::format("0x%p", value);
+ }
+};
+#endif
+
+namespace LoopBlinnPathProcessorImplementation {
+
+//----------------------------------------------------------------------
+// Segment
+//
+
+// Describes a segment of the path: either a cubic or a line segment.
+// These are stored in a doubly linked list to speed up curve
+// subdivision, which occurs due to either rendering artifacts in the
+// loop case or due to overlapping triangles.
+class Segment {
+ WTF_MAKE_NONCOPYABLE(Segment);
+public:
+ enum Kind {
+ Cubic,
+ Line
+ };
+
+ // No-argument constructor allows construction by the PODArena class.
+ Segment()
+ : m_arena(0)
+ , m_kind(Cubic)
+ , m_prev(0)
+ , m_next(0)
+ , m_contour(0)
+ , m_triangulator(0)
+ , m_markedForSubdivision(false)
+ {
+ }
+
+ // Initializer for cubic curve segments.
+ void setup(PODArena* arena,
+ Contour* contour,
+ FloatPoint cp0,
+ FloatPoint cp1,
+ FloatPoint cp2,
+ FloatPoint cp3)
+ {
+ m_arena = arena;
+ m_contour = contour;
+ m_kind = Cubic;
+ m_points[0] = cp0;
+ m_points[1] = cp1;
+ m_points[2] = cp2;
+ m_points[3] = cp3;
+ computeBoundingBox();
+ }
+
+ // Initializer for line segments.
+ void setup(PODArena* arena,
+ Contour* contour,
+ FloatPoint p0,
+ FloatPoint p1)
+ {
+ m_arena = arena;
+ m_contour = contour;
+ m_kind = Line;
+ m_points[0] = p0;
+ m_points[1] = p1;
+ computeBoundingBox();
+ }
+
+ Kind kind() const { return m_kind; }
+
+ // Returns the i'th control point, 0 <= i < 4.
+ const FloatPoint& getPoint(int i)
+ {
+ ASSERT(i >= 0 && i < 4);
+ return m_points[i];
+ }
+
+ Segment* next() const { return m_next; }
+ Segment* prev() const { return m_prev; }
+
+ void setNext(Segment* next) { m_next = next; }
+ void setPrev(Segment* prev) { m_prev = prev; }
+
+ // The contour this segment belongs to.
+ Contour* contour() const { return m_contour; }
+
+ // Subdivides the current segment at the given parameter value (0 <=
+ // t <= 1) and replaces it with the two newly created Segments in
+ // the linked list, if possible. Returns a pointer to the leftmost
+ // Segment.
+ Segment* subdivide(float param)
+ {
+ FloatPoint dst[7];
+ chopCubicAt(m_points, dst, param);
+ Segment* left = m_arena->allocateObject<Segment>();
+ Segment* right = m_arena->allocateObject<Segment>();
+ left->setup(m_arena, m_contour, dst[0], dst[1], dst[2], dst[3]);
+ right->setup(m_arena, m_contour, dst[3], dst[4], dst[5], dst[6]);
+ left->setNext(right);
+ right->setPrev(left);
+ // Try to set up a link between "this->prev()" and "left".
+ if (prev()) {
+ left->setPrev(prev());
+ prev()->setNext(left);
+ }
+ // Try to set up a link between "this->next()" and "right".
+ Segment* n = next();
+ if (n) {
+ right->setNext(n);
+ n->setPrev(right);
+ }
+ // Set up a link between "this" and "left"; this is only to
+ // provide a certain amount of continuity during forward iteration.
+ setNext(left);
+ return left;
+ }
+
+ // Subdivides the current segment at the halfway point and replaces
+ // it with the two newly created Segments in the linked list, if
+ // possible. Returns a pointer to the leftmost Segment.
+ Segment* subdivide() { return subdivide(0.5f); }
+
+ const FloatRect& boundingBox() const { return m_boundingBox; }
+
+ // Computes the number of times a query line starting at the given
+ // point and extending to x=+infinity crosses this segment. Outgoing
+ // "ambiguous" argument indicates whether the query intersected an
+ // endpoint or tangent point of the segment, indicating that another
+ // query point is preferred.
+ int numCrossingsForXRay(const XRay& xRay, bool& ambiguous) const
+ {
+ if (m_kind == Cubic)
+ // Should consider caching the monotonic cubics.
+ return numXRayCrossingsForCubic(xRay, m_points, ambiguous);
+
+ return xRayCrossesLine(xRay, m_points, ambiguous) ? 1 : 0;
+ }
+
+ // Performs a local triangulation of the control points in this
+ // segment. This operation only makes sense for cubic type segments.
+ // texCoords may be null when the klm coordinates have not been
+ // computed yet.
+ void triangulate(LoopBlinnLocalTriangulator::InsideEdgeComputation computeInsideEdges,
+ const LoopBlinnTextureCoords::Result* texCoords);
+
+ // Returns the number of control point triangles associated with
+ // this segment.
+ int numberOfTriangles() const
+ {
+ if (!m_triangulator)
+ return 0;
+ return m_triangulator->numberOfTriangles();
+ }
+
+ // Fetches the given control point triangle for this segment.
+ LoopBlinnLocalTriangulator::Triangle* getTriangle(int index)
+ {
+ ASSERT(m_triangulator);
+ return m_triangulator->getTriangle(index);
+ }
+
+ // Number of vertices along the inside edge of this segment. This
+ // can be called either for line or cubic type segments.
+ int numberOfInteriorVertices() const
+ {
+ if (m_kind == Cubic) {
+ if (m_triangulator)
+ return m_triangulator->numberOfInteriorVertices();
+
+ return 0;
+ }
+
+ return 2;
+ }
+
+ // Returns the given interior vertex, 0 <= index < numberOfInteriorVertices().
+ FloatPoint getInteriorVertex(int index) const
+ {
+ ASSERT(index >= 0 && index < numberOfInteriorVertices());
+ if (m_kind == Cubic) {
+ FloatPoint res;
+ if (m_triangulator) {
+ LoopBlinnLocalTriangulator::Vertex* vertex = m_triangulator->getInteriorVertex(index);
+ if (vertex)
+ res.set(vertex->xyCoordinates().x(), vertex->xyCoordinates().y());
+ }
+ return res;
+ }
+
+ return m_points[index];
+ }
+
+ // State to assist with curve subdivision.
+ bool markedForSubdivision() const { return m_markedForSubdivision; }
+ void setMarkedForSubdivision(bool markedForSubdivision) { m_markedForSubdivision = markedForSubdivision; }
+
+#ifndef NDEBUG
+ // Suppport for printing Segments.
+ String toString() const
+ {
+ StringBuilder builder;
+ builder.append("[Segment kind=");
+ builder.append(kind() == Line ? "line" : "cubic");
+ builder.append(" boundingBox=");
+ builder.append(valueToString(boundingBox()));
+ builder.append(" contour=0x");
+ builder.append(String::format("%p", contour()));
+ builder.append(" markedForSubdivision=");
+ builder.append(markedForSubdivision() ? "true" : "false");
+ builder.append("]");
+ return builder.toString();
+ }
+#endif
+
+ private:
+ // Computes the bounding box of this Segment.
+ void computeBoundingBox()
+ {
+ switch (m_kind) {
+ case Cubic:
+ m_boundingBox.fitToPoints(m_points[0], m_points[1], m_points[2], m_points[3]);
+ break;
+
+ case Line:
+ m_boundingBox.fitToPoints(m_points[0], m_points[1]);
+ break;
+ }
+ }
+
+ PODArena* m_arena;
+ Kind m_kind;
+ FloatPoint m_points[4];
+ Segment* m_prev;
+ Segment* m_next;
+ Contour* m_contour;
+ FloatRect m_boundingBox;
+ LoopBlinnLocalTriangulator* m_triangulator;
+ bool m_markedForSubdivision;
+};
+
+//----------------------------------------------------------------------
+// Contour
+//
+
+// Describes a closed contour of the path.
+class Contour {
+ WTF_MAKE_NONCOPYABLE(Contour);
+public:
+ Contour()
+ {
+ m_first = &m_sentinel;
+ m_first->setNext(m_first);
+ m_first->setPrev(m_first);
+ m_isOrientedCounterClockwise = true;
+ m_boundingBoxDirty = false;
+ m_fillSide = LoopBlinnConstants::RightSide;
+ }
+
+ void add(Segment* segment)
+ {
+ if (m_first == &m_sentinel) {
+ // First element is the sentinel. Replace it with the incoming
+ // segment.
+ segment->setNext(m_first);
+ segment->setPrev(m_first);
+ m_first->setNext(segment);
+ m_first->setPrev(segment);
+ m_first = segment;
+ } else {
+ // m_first->prev() is the sentinel.
+ ASSERT(m_first->prev() == &m_sentinel);
+ Segment* last = m_sentinel.prev();
+ last->setNext(segment);
+ segment->setPrev(last);
+ segment->setNext(&m_sentinel);
+ m_sentinel.setPrev(segment);
+ }
+ m_boundingBoxDirty = true;
+ }
+
+ // Subdivides the given segment at the given parametric value.
+ // Returns a pointer to the first of the two portions of the
+ // subdivided segment.
+ Segment* subdivide(Segment* segment, float param)
+ {
+ Segment* left = segment->subdivide(param);
+ if (m_first == segment)
+ m_first = left;
+ return left;
+ }
+
+ // Subdivides the given segment at the halfway point. Returns a
+ // pointer to the first of the two portions of the subdivided
+ // segment.
+ Segment* subdivide(Segment* segment)
+ {
+ Segment* left = segment->subdivide();
+ if (m_first == segment)
+ m_first = left;
+ return left;
+ }
+
+ // Returns the first segment in the contour for iteration.
+ Segment* begin() const { return m_first; }
+
+ // Returns the last segment in the contour for iteration. Callers
+ // should not iterate over this segment. In other words:
+ // for (Segment* cur = contour->begin();
+ // cur != contour->end();
+ // cur = cur->next()) {
+ // // .. process cur ...
+ // }
+ Segment* end()
+ {
+ ASSERT(m_first->prev() == &m_sentinel);
+ return &m_sentinel;
+ }
+
+ bool isOrientedCounterClockwise() const { return m_isOrientedCounterClockwise; }
+ void setIsOrientedCounterClockwise(bool isOrientedCounterClockwise) { m_isOrientedCounterClockwise = isOrientedCounterClockwise; }
+
+ const FloatRect& boundingBox()
+ {
+ if (m_boundingBoxDirty) {
+ bool first = true;
+ for (Segment* cur = begin(); cur != end(); cur = cur->next()) {
+ if (first)
+ m_boundingBox = cur->boundingBox();
+ else
+ m_boundingBox.unite(cur->boundingBox());
+ first = false;
+ }
+
+ m_boundingBoxDirty = false;
+ }
+ return m_boundingBox;
+ }
+
+ // Returns which side of this contour is filled.
+ LoopBlinnConstants::FillSide fillSide() const
+ {
+ return m_fillSide;
+ }
+
+ void setFillSide(LoopBlinnConstants::FillSide fillSide)
+ {
+ m_fillSide = fillSide;
+ }
+
+private:
+ // The start of the segment chain. The segments are kept in a
+ // circular doubly linked list for rapid access to the beginning and
+ // end.
+ Segment* m_first;
+
+ // The sentinel element at the end of the chain, needed for
+ // reasonable iteration semantics.
+ Segment m_sentinel;
+
+ bool m_isOrientedCounterClockwise;
+
+ FloatRect m_boundingBox;
+ bool m_boundingBoxDirty;
+
+ // Which side of this contour should be filled.
+ LoopBlinnConstants::FillSide m_fillSide;
+};
+
+//----------------------------------------------------------------------
+// Segment
+//
+
+// Definition of Segment::triangulate(), which must come after
+// declaration of Contour.
+void Segment::triangulate(LoopBlinnLocalTriangulator::InsideEdgeComputation computeInsideEdges,
+ const LoopBlinnTextureCoords::Result* texCoords)
+{
+ ASSERT(m_kind == Cubic);
+ if (!m_triangulator)
+ m_triangulator = m_arena->allocateObject<LoopBlinnLocalTriangulator>();
+ m_triangulator->reset();
+ for (int i = 0; i < 4; i++) {
+ LoopBlinnLocalTriangulator::Vertex* vertex = m_triangulator->getVertex(i);
+ if (texCoords) {
+ vertex->set(getPoint(i).x(),
+ getPoint(i).y(),
+ texCoords->klmCoordinates[i].x(),
+ texCoords->klmCoordinates[i].y(),
+ texCoords->klmCoordinates[i].z());
+ } else {
+ vertex->set(getPoint(i).x(),
+ getPoint(i).y(),
+ // No texture coordinates yet
+ 0, 0, 0);
+ }
+ }
+ m_triangulator->triangulate(computeInsideEdges, contour()->fillSide());
+}
+
+} // namespace LoopBlinnPathProcessorImplementation
+
+//----------------------------------------------------------------------
+// LoopBlinnPathProcessor
+//
+
+LoopBlinnPathProcessor::LoopBlinnPathProcessor()
+ : m_arena(PODArena::create())
+#ifndef NDEBUG
+ , m_verboseLogging(false)
+#endif
+{
+}
+
+LoopBlinnPathProcessor::LoopBlinnPathProcessor(PassRefPtr<PODArena> arena)
+ : m_arena(arena)
+#ifndef NDEBUG
+ , m_verboseLogging(false)
+#endif
+{
+}
+
+LoopBlinnPathProcessor::~LoopBlinnPathProcessor()
+{
+}
+
+void LoopBlinnPathProcessor::process(const Path& path, LoopBlinnPathCache& cache)
+{
+ buildContours(path);
+
+ // Run plane-sweep algorithm to determine overlaps of control point
+ // curves and subdivide curves appropriately.
+ subdivideCurves();
+
+ // Determine orientations of countours. Based on orientation and the
+ // number of curve crossings at a random point on the contour,
+ // determine whether to fill the left or right side of the contour.
+ determineSidesToFill();
+
+ // Classify curves, compute texture coordinates and subdivide as
+ // necessary to eliminate rendering artifacts. Do the final
+ // triangulation of the curve segments, determining the path along
+ // the interior of the shape.
+ for (Vector<Contour*>::iterator iter = m_contours.begin(); iter != m_contours.end(); ++iter) {
+ Contour* cur = *iter;
+ for (Segment* seg = cur->begin(); seg != cur->end(); seg = seg->next()) {
+ if (seg->kind() == Segment::Cubic) {
+ LoopBlinnClassifier::Result classification = LoopBlinnClassifier::classify(seg->getPoint(0),
+ seg->getPoint(1),
+ seg->getPoint(2),
+ seg->getPoint(3));
+#ifndef NDEBUG
+ if (m_verboseLogging)
+ LOG_ERROR("Classification: %d", (int) classification.curveType);
+#endif
+ LoopBlinnTextureCoords::Result texCoords =
+ LoopBlinnTextureCoords::compute(classification, cur->fillSide());
+ if (texCoords.hasRenderingArtifact) {
+ // FIXME: there is a problem where the algorithm
+ // sometimes fails to converge when splitting at the
+ // subdivision parameter value. For the time being,
+ // split halfway.
+ cur->subdivide(seg);
+ // Next iteration will handle the newly subdivided curves
+ } else {
+ if (!texCoords.isLineOrPoint) {
+ seg->triangulate(LoopBlinnLocalTriangulator::ComputeInsideEdges, &texCoords);
+ for (int i = 0; i < seg->numberOfTriangles(); i++) {
+ LoopBlinnLocalTriangulator::Triangle* triangle = seg->getTriangle(i);
+ for (int j = 0; j < 3; j++) {
+ LoopBlinnLocalTriangulator::Vertex* vert = triangle->getVertex(j);
+ cache.addVertex(vert->xyCoordinates().x(),
+ vert->xyCoordinates().y(),
+ vert->klmCoordinates().x(),
+ vert->klmCoordinates().y(),
+ vert->klmCoordinates().z());
+ }
+ }
+#ifdef LOOP_BLINN_PATH_CACHE_DEBUG_INTERIOR_EDGES
+ // Show the end user the interior edges as well
+ for (int i = 1; i < seg->numberOfInteriorVertices(); i++) {
+ FloatPoint vert = seg->getInteriorVertex(i);
+ // Duplicate previous vertex to be able to draw GL_LINES
+ FloatPoint prev = seg->getInteriorVertex(i - 1);
+ cache.addInteriorEdgeVertex(prev.x(), prev.y());
+ cache.addInteriorEdgeVertex(vert.x(), vert.y());
+ }
+#endif // LOOP_BLINN_PATH_CACHE_DEBUG_INTERIOR_EDGES
+ }
+ }
+ }
+ }
+ }
+
+ // Run the interior paths through a tessellation algorithm
+ // supporting multiple contours.
+ tessellateInterior(cache);
+}
+
+void LoopBlinnPathProcessor::buildContours(const Path& path)
+{
+ // Clear out the contours
+ m_contours.clear();
+#if PLATFORM(SKIA)
+ SkPath::Iter iter(*path.platformPath(), false);
+ SkPoint points[4];
+ SkPath::Verb verb;
+ Contour* contour = 0;
+ SkPoint curPoint = { 0 };
+ SkPoint moveToPoint = { 0 };
+ do {
+ verb = iter.next(points);
+ if (verb != SkPath::kMove_Verb) {
+ if (!contour) {
+ contour = m_arena->allocateObject<Contour>();
+ m_contours.append(contour);
+ }
+ }
+ switch (verb) {
+ case SkPath::kMove_Verb: {
+ contour = m_arena->allocateObject<Contour>();
+ m_contours.append(contour);
+ curPoint = points[0];
+ moveToPoint = points[0];
+#ifndef NDEBUG
+ if (m_verboseLogging)
+ LOG_ERROR("MoveTo (%f, %f)", points[0].fX, points[0].fY);
+#endif
+ break;
+ }
+ case SkPath::kLine_Verb: {
+ Segment* segment = m_arena->allocateObject<Segment>();
+ if (iter.isCloseLine()) {
+ segment->setup(m_arena.get(), contour, curPoint, points[1]);
+#ifndef NDEBUG
+ if (m_verboseLogging)
+ LOG_ERROR("CloseLineTo (%f, %f), (%f, %f)", curPoint.fX, curPoint.fY, points[1].fX, points[1].fY);
+#endif
+ contour->add(segment);
+ contour = 0;
+ } else {
+ segment->setup(m_arena.get(), contour, points[0], points[1]);
+#ifndef NDEBUG
+ if (m_verboseLogging)
+ LOG_ERROR("LineTo (%f, %f), (%f, %f)", points[0].fX, points[0].fY, points[1].fX, points[1].fY);
+#endif
+ contour->add(segment);
+ curPoint = points[1];
+ }
+ break;
+ }
+ case SkPath::kQuad_Verb: {
+ // Need to degree elevate the quadratic into a cubic
+ SkPoint cubic[4];
+ SkConvertQuadToCubic(points, cubic);
+ Segment* segment = m_arena->allocateObject<Segment>();
+ segment->setup(m_arena.get(), contour,
+ cubic[0], cubic[1], cubic[2], cubic[3]);
+#ifndef NDEBUG
+ if (m_verboseLogging)
+ LOG_ERROR("Quad->CubicTo (%f, %f), (%f, %f), (%f, %f), (%f, %f)", cubic[0].fX, cubic[0].fY, cubic[1].fX, cubic[1].fY, cubic[2].fX, cubic[2].fY, cubic[3].fX, cubic[3].fY);
+#endif
+ contour->add(segment);
+ curPoint = cubic[3];
+ break;
+ }
+ case SkPath::kCubic_Verb: {
+ Segment* segment = m_arena->allocateObject<Segment>();
+ segment->setup(m_arena.get(), contour, points[0], points[1], points[2], points[3]);
+#ifndef NDEBUG
+ if (m_verboseLogging)
+ LOG_ERROR("CubicTo (%f, %f), (%f, %f), (%f, %f), (%f, %f)", points[0].fX, points[0].fY, points[1].fX, points[1].fY, points[2].fX, points[2].fY, points[3].fX, points[3].fY);
+#endif
+ contour->add(segment);
+ curPoint = points[3];
+ break;
+ }
+ case SkPath::kClose_Verb: {
+ Segment* segment = m_arena->allocateObject<Segment>();
+ segment->setup(m_arena.get(), contour, curPoint, moveToPoint);
+#ifndef NDEBUG
+ if (m_verboseLogging)
+ LOG_ERROR("Close (%f, %f) -> (%f, %f)", curPoint.fX, curPoint.fY, moveToPoint.fX, moveToPoint.fY);
+#endif
+ contour->add(segment);
+ contour = 0;
+ }
+ case SkPath::kDone_Verb:
+ break;
+ }
+ } while (verb != SkPath::kDone_Verb);
+#else // !PLATFORM(SKIA)
+ // Must port to your platform.
+ ASSERT_NOT_REACHED();
+#endif
+}
+
+#ifndef NDEBUG
+Vector<Segment*> LoopBlinnPathProcessor::allSegmentsOverlappingY(Contour* queryContour, float x, float y)
+{
+ Vector<Segment*> res;
+ for (Vector<Contour*>::iterator iter = m_contours.begin(); iter != m_contours.end(); ++iter) {
+ Contour* cur = *iter;
+ for (Segment* seg = cur->begin(); seg != cur->end(); seg = seg->next()) {
+ const FloatRect& boundingBox = seg->boundingBox();
+ if (boundingBox.y() <= y && y <= boundingBox.maxY())
+ res.append(seg);
+ }
+ }
+ return res;
+}
+#endif
+
+// Uncomment this to debug the orientation computation.
+// #define GPU_PATH_PROCESSOR_DEBUG_ORIENTATION
+
+void LoopBlinnPathProcessor::determineSidesToFill()
+{
+ // Loop and Blinn's algorithm can only easily emulate the even/odd
+ // fill rule, and only for non-intersecting curves. We can determine
+ // which side of each curve segment to fill based on its
+ // clockwise/counterclockwise orientation and how many other
+ // contours surround it.
+
+ // To optimize the query of all curve segments intersecting a
+ // horizontal line going to x=+infinity, we build up an interval
+ // tree whose keys are the y extents of the segments.
+ PODIntervalTree<float, Segment*> tree(m_arena);
+ typedef PODIntervalTree<float, Segment*>::IntervalType IntervalType;
+
+ for (Vector<Contour*>::iterator iter = m_contours.begin(); iter != m_contours.end(); ++iter) {
+ Contour* cur = *iter;
+ determineOrientation(cur);
+ for (Segment* seg = cur->begin(); seg != cur->end(); seg = seg->next()) {
+ const FloatRect& boundingBox = seg->boundingBox();
+ tree.add(tree.createInterval(boundingBox.y(), boundingBox.maxY(), seg));
+ }
+ }
+
+ // Now iterate through the contours and pick a random segment (in
+ // this case we use the first) and a random point on that segment.
+ // Find all segments from other contours which intersect this one
+ // and count the number of crossings a horizontal line to
+ // x=+infinity makes with those contours. This combined with the
+ // orientation of the curve tells us which side to fill -- again,
+ // assuming an even/odd fill rule, which is all we can easily
+ // handle.
+ for (Vector<Contour*>::iterator iter = m_contours.begin(); iter != m_contours.end(); ++iter) {
+ Contour* cur = *iter;
+
+ bool ambiguous = true;
+ int numCrossings = 0;
+
+ // For each contour, attempt to find a point on the contour which,
+ // when we cast an XRay, does not intersect the other contours at
+ // an ambiguous point (the junction between two curves or at a
+ // tangent point). Ambiguous points make the determination of
+ // whether this contour is contained within another fragile. Note
+ // that this loop is only an approximation to the selection of a
+ // good casting point. We could as well evaluate a segment to
+ // determine a point upon it.
+ for (Segment* seg = cur->begin();
+ ambiguous && seg != cur->end();
+ seg = seg->next()) {
+ numCrossings = 0;
+ // We use a zero-sized vertical interval for the query.
+ Vector<IntervalType> overlaps = tree.allOverlaps(tree.createInterval(seg->getPoint(0).y(),
+ seg->getPoint(0).y(),
+ 0));
+#if defined(GPU_PATH_PROCESSOR_DEBUG_ORIENTATION) && !defined(NDEBUG)
+ Vector<Segment*> slowOverlaps = allSegmentsOverlappingY(cur, seg->getPoint(0).x(), seg->getPoint(0).y());
+ if (overlaps.size() != slowOverlaps.size()) {
+ LOG_ERROR("For query point (%f, %f) on contour 0x%p:", seg->getPoint(0).x(), seg->getPoint(0).y(), cur);
+ LOG_ERROR(" overlaps:");
+ for (size_t i = 0; i < overlaps.size(); i++)
+ LOG_ERROR(" %d: %s", i+1, overlaps[i].data()->toString().ascii().data());
+ LOG_ERROR(" slowOverlaps:");
+ for (size_t i = 0; i < slowOverlaps.size(); i++)
+ LOG_ERROR(" %d: %s", (i+1) slowOverlaps[i]->toString());
+ LOG_ERROR("Interval tree:");
+ tree.dump();
+ }
+ ASSERT(overlaps.size() == slowOverlaps.size());
+#endif // defined(GPU_PATH_PROCESSOR_DEBUG_ORIENTATION) && !defined(NDEBUG)
+ for (Vector<IntervalType>::iterator iter = overlaps.begin(); iter != overlaps.end(); ++iter) {
+ const IntervalType& interval = *iter;
+ Segment* querySegment = interval.data();
+ // Ignore segments coming from the same contour.
+ if (querySegment->contour() != cur) {
+ // Only perform queries that can affect the computation.
+ const FloatRect& boundingBox = querySegment->contour()->boundingBox();
+ if (seg->getPoint(0).x() >= boundingBox.x()
+ && seg->getPoint(0).x() <= boundingBox.maxX()) {
+ numCrossings += querySegment->numCrossingsForXRay(seg->getPoint(0),
+ ambiguous);
+ if (ambiguous) {
+#ifndef NDEBUG
+ if (m_verboseLogging) {
+ LOG_ERROR("Ambiguous intersection query at point (%f, %f)", seg->getPoint(0).x(), seg->getPoint(0).y());
+ LOG_ERROR("Query segment: %s", querySegment->toString().ascii().data());
+ }
+#endif
+ break; // Abort iteration over overlaps.
+ }
+ }
+ }
+ }
+ } // for (Segment* seg = cur->begin(); ...
+
+ cur->setFillSide((cur->isOrientedCounterClockwise() ^ (numCrossings & 1)) ? LoopBlinnConstants::LeftSide : LoopBlinnConstants::RightSide);
+ }
+}
+
+void LoopBlinnPathProcessor::determineOrientation(Contour* contour)
+{
+ // Determine signed area of the polygon represented by the points
+ // along the segments. Consider this an approximation to the true
+ // orientation of the polygon; it probably won't handle
+ // self-intersecting curves correctly.
+ //
+ // There is also a pretty basic assumption here that the contour is
+ // closed.
+ float signedArea = 0;
+ for (Segment* seg = contour->begin();
+ seg != contour->end();
+ seg = seg->next()) {
+ int limit = (seg->kind() == Segment::Cubic) ? 4 : 2;
+ for (int i = 1; i < limit; i++) {
+ const FloatPoint& prevPoint = seg->getPoint(i - 1);
+ const FloatPoint& point = seg->getPoint(i);
+ float curArea = prevPoint.x() * point.y() - prevPoint.y() * point.x();
+#ifndef NDEBUG
+ if (m_verboseLogging)
+ LOG_ERROR("Adding to signed area (%f, %f) -> (%f, %f) = %f", prevPoint.x(), prevPoint.y(), point.x(), point.y(), curArea);
+#endif
+ signedArea += curArea;
+ }
+ }
+
+ if (signedArea > 0)
+ contour->setIsOrientedCounterClockwise(true);
+ else
+ contour->setIsOrientedCounterClockwise(false);
+}
+
+namespace {
+
+//----------------------------------------------------------------------
+// Classes and typedefs needed for curve subdivision. These can't be scoped
+// within the subdivideCurves() method itself, because templates then fail
+// to instantiate.
+
+// The user data which is placed in the PODIntervalTree.
+struct SweepData {
+ SweepData()
+ : triangle(0)
+ , segment(0)
+ {
+ }
+
+ // The triangle this interval is associated with
+ LoopBlinnLocalTriangulator::Triangle* triangle;
+ // The segment the triangle is associated with
+ Segment* segment;
+};
+
+typedef PODIntervalTree<float, SweepData*> SweepTree;
+typedef SweepTree::IntervalType SweepInterval;
+
+// The entry / exit events which occur at the minimum and maximum x
+// coordinates of the control point triangles' bounding boxes.
+//
+// Note that this class requires its copy constructor and assignment
+// operator since it needs to be stored in a Vector.
+class SweepEvent {
+public:
+ SweepEvent()
+ : m_x(0)
+ , m_entry(false)
+ , m_interval(0, 0, 0)
+ {
+ }
+
+ // Initializes the SweepEvent.
+ void setup(float x, bool entry, SweepInterval interval)
+ {
+ m_x = x;
+ m_entry = entry;
+ m_interval = interval;
+ }
+
+ float x() const { return m_x; }
+ bool entry() const { return m_entry; }
+ const SweepInterval& interval() const { return m_interval; }
+
+ bool operator<(const SweepEvent& other) const
+ {
+ return m_x < other.m_x;
+ }
+
+private:
+ float m_x;
+ bool m_entry;
+ SweepInterval m_interval;
+};
+
+bool trianglesOverlap(LoopBlinnLocalTriangulator::Triangle* t0,
+ LoopBlinnLocalTriangulator::Triangle* t1)
+{
+ return trianglesOverlap(t0->getVertex(0)->xyCoordinates(),
+ t0->getVertex(1)->xyCoordinates(),
+ t0->getVertex(2)->xyCoordinates(),
+ t1->getVertex(0)->xyCoordinates(),
+ t1->getVertex(1)->xyCoordinates(),
+ t1->getVertex(2)->xyCoordinates());
+}
+
+} // anonymous namespace
+
+void LoopBlinnPathProcessor::subdivideCurves()
+{
+ // We need to determine all overlaps of all control point triangles
+ // (from different segments, not the same segment) and, if any
+ // exist, subdivide the associated curves.
+ //
+ // The plane-sweep algorithm determines all overlaps of a set of
+ // rectangles in the 2D plane. Our problem maps very well to this
+ // algorithm and significantly reduces the complexity compared to a
+ // naive implementation.
+ //
+ // Each bounding box of a control point triangle is converted into
+ // an "entry" event at its smallest X coordinate and an "exit" event
+ // at its largest X coordinate. Each event has an associated
+ // one-dimensional interval representing the Y span of the bounding
+ // box. We sort these events by increasing X coordinate. We then
+ // iterate through them. For each entry event we add the interval to
+ // a side interval tree, and query this tree for overlapping
+ // intervals. Any overlapping interval corresponds to an overlapping
+ // bounding box. For each exit event we remove the associated
+ // interval from the interval tree.
+
+ Vector<Segment*> curSegments;
+ Vector<Segment*> nextSegments;
+
+ // Start things off by considering all of the segments
+ for (Vector<Contour*>::iterator iter = m_contours.begin(); iter != m_contours.end(); ++iter) {
+ Contour* cur = *iter;
+ for (Segment* seg = cur->begin(); seg != cur->end(); seg = seg->next()) {
+ if (seg->kind() == Segment::Cubic) {
+ seg->triangulate(LoopBlinnLocalTriangulator::DontComputeInsideEdges, 0);
+ curSegments.append(seg);
+ }
+ }
+ }
+
+ // Subdivide curves at most this many times
+ const int MaxIterations = 5;
+ Vector<SweepInterval> overlaps;
+
+ for (int currentIteration = 0; currentIteration < MaxIterations; ++currentIteration) {
+ if (!curSegments.size())
+ // Done
+ break;
+
+ Vector<SweepEvent> events;
+ SweepTree tree(m_arena);
+ for (Vector<Segment*>::iterator iter = curSegments.begin(); iter != curSegments.end(); ++iter) {
+ Segment* seg = *iter;
+ ASSERT(seg->kind() == Segment::Cubic);
+ for (int i = 0; i < seg->numberOfTriangles(); i++) {
+ LoopBlinnLocalTriangulator::Triangle* triangle = seg->getTriangle(i);
+ FloatRect boundingBox;
+ boundingBox.fitToPoints(triangle->getVertex(0)->xyCoordinates(),
+ triangle->getVertex(1)->xyCoordinates(),
+ triangle->getVertex(2)->xyCoordinates());
+ // Ignore zero-width triangles to avoid issues with
+ // coincident entry and exit events for the same triangle
+ if (boundingBox.maxX() > boundingBox.x()) {
+ SweepData* data = m_arena->allocateObject<SweepData>();
+ data->triangle = triangle;
+ data->segment = seg;
+ SweepInterval interval = tree.createInterval(boundingBox.y(), boundingBox.maxY(), data);
+ // Add entry and exit events
+ SweepEvent event;
+ event.setup(boundingBox.x(), true, interval);
+ events.append(event);
+ event.setup(boundingBox.maxX(), false, interval);
+ events.append(event);
+ }
+ }
+ }
+
+ // Sort events by increasing X coordinate
+ std::sort(events.begin(), events.end());
+#ifndef NDEBUG
+ for (size_t ii = 1; ii < events.size(); ++ii)
+ ASSERT(events[ii - 1].x() <= events[ii].x());
+#endif
+
+ // Now iterate through the events
+ for (Vector<SweepEvent>::iterator iter = events.begin(); iter != events.end(); ++iter) {
+ SweepEvent event = *iter;
+ if (event.entry()) {
+ // See whether the associated segment has been subdivided yet
+ if (!event.interval().data()->segment->markedForSubdivision()) {
+ // Query the tree
+ overlaps.clear();
+ tree.allOverlaps(event.interval(), overlaps);
+ // Now see exactly which triangles overlap this one
+ for (Vector<SweepInterval>::iterator iter = overlaps.begin(); iter != overlaps.end(); ++iter) {
+ SweepInterval overlap = *iter;
+ // Only pay attention to overlaps from a different Segment
+ if (event.interval().data()->segment != overlap.data()->segment) {
+ // See whether the triangles actually overlap
+ if (trianglesOverlap(event.interval().data()->triangle,
+ overlap.data()->triangle)) {
+ // Actually subdivide the segments.
+ // Each one might already have been subdivided.
+ Segment* seg = event.interval().data()->segment;
+ conditionallySubdivide(seg, nextSegments);
+ seg = overlap.data()->segment;
+ conditionallySubdivide(seg, nextSegments);
+ }
+ }
+ }
+ }
+ // Add this interval into the tree
+ tree.add(event.interval());
+ } else {
+ // Remove this interval from the tree
+ tree.remove(event.interval());
+ }
+ }
+
+ curSegments.swap(nextSegments);
+ nextSegments.clear();
+ }
+}
+
+void LoopBlinnPathProcessor::conditionallySubdivide(Segment* seg, Vector<Segment*>& nextSegments)
+{
+ if (!seg->markedForSubdivision()) {
+ seg->setMarkedForSubdivision(true);
+ Segment* next = seg->contour()->subdivide(seg);
+ // Triangulate the newly subdivided segments.
+ next->triangulate(LoopBlinnLocalTriangulator::DontComputeInsideEdges, 0);
+ next->next()->triangulate(LoopBlinnLocalTriangulator::DontComputeInsideEdges, 0);
+ // Add them for the next iteration.
+ nextSegments.append(next);
+ nextSegments.append(next->next());
+ }
+}
+
+#ifndef NDEBUG
+void LoopBlinnPathProcessor::subdivideCurvesSlow()
+{
+ // Alternate, significantly slower algorithm for curve subdivision
+ // for use in debugging.
+ Vector<Segment*> curSegments;
+ Vector<Segment*> nextSegments;
+
+ // Start things off by considering all of the segments
+ for (Vector<Contour*>::iterator iter = m_contours.begin(); iter != m_contours.end(); ++iter) {
+ Contour* cur = *iter;
+ for (Segment* seg = cur->begin(); seg != cur->end(); seg = seg->next()) {
+ if (seg->kind() == Segment::Cubic) {
+ seg->triangulate(LoopBlinnLocalTriangulator::DontComputeInsideEdges, 0);
+ curSegments.append(seg);
+ }
+ }
+ }
+
+ // Subdivide curves at most this many times
+ const int MaxIterations = 5;
+
+ for (int currentIteration = 0; currentIteration < MaxIterations; ++currentIteration) {
+ if (!curSegments.size())
+ // Done
+ break;
+
+ for (Vector<Segment*>::iterator iter = curSegments.begin(); iter != curSegments.end(); ++iter) {
+ Segment* seg = *iter;
+ ASSERT(seg->kind() == Segment::Cubic);
+ for (Vector<Segment*>::iterator iter2 = curSegments.begin();
+ iter2 != curSegments.end();
+ iter2++) {
+ Segment* seg2 = *iter2;
+ ASSERT(seg2->kind() == Segment::Cubic);
+ if (seg != seg2) {
+ for (int i = 0; i < seg->numberOfTriangles(); i++) {
+ LoopBlinnLocalTriangulator::Triangle* triangle = seg->getTriangle(i);
+ for (int j = 0; j < seg2->numberOfTriangles(); j++) {
+ LoopBlinnLocalTriangulator::Triangle* triangle2 = seg2->getTriangle(j);
+ if (trianglesOverlap(triangle, triangle2)) {
+ conditionallySubdivide(seg, nextSegments);
+ conditionallySubdivide(seg2, nextSegments);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ curSegments.swap(nextSegments);
+ nextSegments.clear();
+ }
+}
+#endif
+
+namespace {
+
+//----------------------------------------------------------------------
+// Structures and callbacks for tessellation of the interior region of
+// the contours.
+
+// The user data for the GLU tessellator.
+struct TessellationState {
+ TessellationState(LoopBlinnPathCache& inputCache)
+ : cache(inputCache) { }
+
+ LoopBlinnPathCache& cache;
+ Vector<void*> allocatedPointers;
+};
+
+static void vertexCallback(void* vertexData, void* data)
+{
+ TessellationState* state = static_cast<TessellationState*>(data);
+ GLdouble* location = static_cast<GLdouble*>(vertexData);
+ state->cache.addInteriorVertex(static_cast<float>(location[0]),
+ static_cast<float>(location[1]));
+}
+
+static void combineCallback(GLdouble coords[3], void* vertexData[4],
+ GLfloat weight[4], void** outData,
+ void* polygonData)
+{
+ TessellationState* state = static_cast<TessellationState*>(polygonData);
+ GLdouble* outVertex = static_cast<GLdouble*>(fastMalloc(3 * sizeof(GLdouble)));
+ state->allocatedPointers.append(outVertex);
+ outVertex[0] = coords[0];
+ outVertex[1] = coords[1];
+ outVertex[2] = coords[2];
+ *outData = outVertex;
+}
+
+static void edgeFlagCallback(GLboolean)
+{
+ // No-op just to prevent triangle strips and fans from being passed to us.
+ // See the OpenGL Programming Guide, Chapter 11, "Tessellators and Quadrics".
+}
+
+} // anonymous namespace
+
+void LoopBlinnPathProcessor::tessellateInterior(LoopBlinnPathCache& cache)
+{
+ // Because the GLU tessellator requires its input in
+ // double-precision format, we need to make a separate copy of the
+ // data.
+ Vector<GLdouble> vertexData;
+ Vector<size_t> contourEndings;
+ // For avoiding adding coincident vertices.
+ float curX = 0, curY = 0;
+ for (Vector<Contour*>::iterator iter = m_contours.begin(); iter != m_contours.end(); ++iter) {
+ Contour* cur = *iter;
+ bool first = true;
+ for (Segment* seg = cur->begin(); seg != cur->end(); seg = seg->next()) {
+ int numberOfInteriorVertices = seg->numberOfInteriorVertices();
+ for (int i = 0; i < numberOfInteriorVertices - 1; i++) {
+ FloatPoint point = seg->getInteriorVertex(i);
+ if (first) {
+ first = false;
+ vertexData.append(point.x());
+ vertexData.append(point.y());
+ vertexData.append(0);
+ curX = point.x();
+ curY = point.y();
+ } else if (point.x() != curX || point.y() != curY) {
+ vertexData.append(point.x());
+ vertexData.append(point.y());
+ vertexData.append(0);
+ curX = point.x();
+ curY = point.y();
+ }
+ }
+ }
+ contourEndings.append(vertexData.size());
+ }
+ // Now that we have all of the vertex data in a stable location in
+ // memory, call the tessellator.
+ GLUtesselator* tess = internal_gluNewTess();
+ TessellationState state(cache);
+ internal_gluTessCallback(tess, GLU_TESS_VERTEX_DATA,
+ reinterpret_cast<GLvoid (*)()>(vertexCallback));
+ internal_gluTessCallback(tess, GLU_TESS_COMBINE_DATA,
+ reinterpret_cast<GLvoid (*)()>(combineCallback));
+ internal_gluTessCallback(tess, GLU_TESS_EDGE_FLAG,
+ reinterpret_cast<GLvoid (*)()>(edgeFlagCallback));
+ internal_gluTessBeginPolygon(tess, &state);
+ internal_gluTessBeginContour(tess);
+ GLdouble* base = vertexData.data();
+ int contourIndex = 0;
+ for (size_t i = 0; i < vertexData.size(); i += 3) {
+ if (i == contourEndings[contourIndex]) {
+ internal_gluTessEndContour(tess);
+ internal_gluTessBeginContour(tess);
+ ++contourIndex;
+ }
+ internal_gluTessVertex(tess, &base[i], &base[i]);
+ }
+ internal_gluTessEndContour(tess);
+ internal_gluTessEndPolygon(tess);
+ for (size_t i = 0; i < state.allocatedPointers.size(); i++)
+ fastFree(state.allocatedPointers[i]);
+ internal_gluDeleteTess(tess);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/gpu/LoopBlinnPathProcessor.h b/Source/WebCore/platform/graphics/gpu/LoopBlinnPathProcessor.h
new file mode 100644
index 0000000..ad89bc1
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/LoopBlinnPathProcessor.h
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+// The main entry point for Loop and Blinn's GPU accelerated curve
+// rendering algorithm.
+
+#ifndef LoopBlinnPathProcessor_h
+#define LoopBlinnPathProcessor_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+// We use a namespace for classes which are simply implementation
+// details of the algorithm but which we need to reference from the
+// class definition.
+namespace LoopBlinnPathProcessorImplementation {
+
+class Contour;
+class Segment;
+
+} // namespace LoopBlinnPathProcessorImplementation
+
+class Path;
+class LoopBlinnPathCache;
+class PODArena;
+
+// The LoopBlinnPathProcessor turns a Path (assumed to contain one or
+// more closed regions) into a set of exterior and interior triangles,
+// stored in the LoopBlinnPathCache. The exterior triangles have
+// associated 3D texture coordinates which are used to evaluate the
+// curve's inside/outside function on a per-pixel basis. The interior
+// triangles are filled with 100% opacity.
+//
+// Note that the fill style and management of multiple layers are
+// separate concerns, handled at a higher level with shaders and
+// polygon offsets.
+class LoopBlinnPathProcessor {
+public:
+ LoopBlinnPathProcessor();
+ explicit LoopBlinnPathProcessor(PassRefPtr<PODArena>);
+ ~LoopBlinnPathProcessor();
+
+ // Transforms the given path into a triangle mesh for rendering
+ // using Loop and Blinn's shader, placing the result into the given
+ // LoopBlinnPathCache.
+ void process(const Path&, LoopBlinnPathCache&);
+
+#ifndef NDEBUG
+ // Enables or disables verbose logging in debug mode.
+ void setVerboseLogging(bool onOrOff);
+#endif
+
+private:
+ // Builds a list of contours for the given path.
+ void buildContours(const Path&);
+
+ // Determines whether the left or right side of each contour should
+ // be filled.
+ void determineSidesToFill();
+
+ // Determines whether the given (closed) contour is oriented
+ // clockwise or counterclockwise.
+ void determineOrientation(LoopBlinnPathProcessorImplementation::Contour*);
+
+ // Subdivides the curves so that there are no overlaps of the
+ // triangles associated with the curves' control points.
+ void subdivideCurves();
+
+ // Helper function used during curve subdivision.
+ void conditionallySubdivide(LoopBlinnPathProcessorImplementation::Segment*,
+ Vector<LoopBlinnPathProcessorImplementation::Segment*>& nextSegments);
+
+ // Tessellates the interior regions of the contours.
+ void tessellateInterior(LoopBlinnPathCache&);
+
+#ifndef NDEBUG
+ // For debugging the orientation computation. Returns all of the
+ // segments overlapping the given Y coordinate.
+ Vector<LoopBlinnPathProcessorImplementation::Segment*> allSegmentsOverlappingY(LoopBlinnPathProcessorImplementation::Contour*, float x, float y);
+
+ // For debugging the curve subdivision algorithm. Subdivides the
+ // curves using an alternate, slow (O(n^3)) algorithm.
+ void subdivideCurvesSlow();
+#endif
+
+ // PODArena from which to allocate temporary objects.
+ RefPtr<PODArena> m_arena;
+
+ // The contours described by the path.
+ Vector<LoopBlinnPathProcessorImplementation::Contour*> m_contours;
+
+#ifndef NDEBUG
+ // Whether or not to perform verbose logging in debug mode.
+ bool m_verboseLogging;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // LoopBlinnPathProcessor_h
diff --git a/Source/WebCore/platform/graphics/gpu/LoopBlinnShader.cpp b/Source/WebCore/platform/graphics/gpu/LoopBlinnShader.cpp
new file mode 100644
index 0000000..364e6c8
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/LoopBlinnShader.cpp
@@ -0,0 +1,59 @@
+/*
+ * 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"
+
+#include "LoopBlinnShader.h"
+
+#include "GraphicsContext3D.h"
+
+namespace WebCore {
+
+LoopBlinnShader::LoopBlinnShader(GraphicsContext3D* context, unsigned program)
+ : Shader(context, program)
+{
+ m_worldViewProjectionLocation = context->getUniformLocation(program, "worldViewProjection");
+ m_positionLocation = context->getAttribLocation(program, "position");
+ m_klmLocation = context->getAttribLocation(program, "klm");
+}
+
+void LoopBlinnShader::use(unsigned vertexOffset, unsigned klmOffset, const AffineTransform& transform)
+{
+ m_context->useProgram(m_program);
+
+ float matrix[16];
+ affineTo4x4(transform, matrix);
+ m_context->uniformMatrix4fv(m_worldViewProjectionLocation, false /*transpose*/, matrix, 1 /*count*/);
+
+ m_context->vertexAttribPointer(m_positionLocation, 2, GraphicsContext3D::FLOAT, false, 0, vertexOffset);
+ m_context->enableVertexAttribArray(m_positionLocation);
+
+ if (m_klmLocation != -1) {
+ m_context->vertexAttribPointer(m_klmLocation, 3, GraphicsContext3D::FLOAT, false, 0, klmOffset);
+ m_context->enableVertexAttribArray(m_klmLocation);
+ }
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/gpu/LoopBlinnShader.h b/Source/WebCore/platform/graphics/gpu/LoopBlinnShader.h
new file mode 100644
index 0000000..2d24dc3
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/LoopBlinnShader.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:
+ *
+ * 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 LoopBlinnShader_h
+#define LoopBlinnShader_h
+
+#include "Shader.h"
+
+namespace WebCore {
+
+class GraphicsContext3D;
+
+class LoopBlinnShader : public Shader {
+public:
+ enum Region {
+ Interior,
+ Exterior
+ };
+
+protected:
+ LoopBlinnShader(GraphicsContext3D*, unsigned program);
+
+ // This assumes the vertices and klm coordinates are stored in the
+ // same, currently bound, buffer object, contiguously and at the
+ // specified offsets.
+ void use(unsigned vertexOffset, unsigned klmOffset, const AffineTransform&);
+
+private:
+ int m_worldViewProjectionLocation;
+ int m_positionLocation;
+ int m_klmLocation;
+};
+
+} // namespace WebCore
+
+#endif // LoopBlinnShader_h
diff --git a/Source/WebCore/platform/graphics/gpu/LoopBlinnSolidFillShader.cpp b/Source/WebCore/platform/graphics/gpu/LoopBlinnSolidFillShader.cpp
new file mode 100644
index 0000000..43a97ef
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/LoopBlinnSolidFillShader.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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"
+
+#include "LoopBlinnSolidFillShader.h"
+
+#include "GraphicsContext3D.h"
+
+namespace WebCore {
+
+PassOwnPtr<LoopBlinnSolidFillShader> LoopBlinnSolidFillShader::create(GraphicsContext3D* context,
+ LoopBlinnShader::Region region,
+ Shader::AntialiasType antialiasType)
+{
+ VertexType type = (region == Interior) ? LoopBlinnInterior : LoopBlinnExterior;
+ unsigned program = loadProgram(context,
+ generateVertex(type, SolidFill),
+ generateFragment(type, SolidFill, antialiasType));
+ if (!program)
+ return 0;
+ return new LoopBlinnSolidFillShader(context, program);
+}
+
+LoopBlinnSolidFillShader::LoopBlinnSolidFillShader(GraphicsContext3D* context, unsigned program)
+ : LoopBlinnShader(context, program)
+{
+ m_colorLocation = context->getUniformLocation(program, "color");
+}
+
+void LoopBlinnSolidFillShader::use(unsigned vertexOffset, unsigned klmOffset, const AffineTransform& transform, const Color& color)
+{
+ LoopBlinnShader::use(vertexOffset, klmOffset, transform);
+
+ float rgba[4];
+ color.getRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);
+ m_context->uniform4f(m_colorLocation, rgba[0] * rgba[3], rgba[1] * rgba[3], rgba[2] * rgba[3], rgba[3]);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/gpu/LoopBlinnSolidFillShader.h b/Source/WebCore/platform/graphics/gpu/LoopBlinnSolidFillShader.h
new file mode 100644
index 0000000..36312a2
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/LoopBlinnSolidFillShader.h
@@ -0,0 +1,52 @@
+/*
+ * 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 LoopBlinnSolidFillShader_h
+#define LoopBlinnSolidFillShader_h
+
+#include "LoopBlinnShader.h"
+
+namespace WebCore {
+
+class GraphicsContext3D;
+
+class LoopBlinnSolidFillShader : public LoopBlinnShader {
+public:
+ static PassOwnPtr<LoopBlinnSolidFillShader> create(GraphicsContext3D*, Region, AntialiasType);
+
+ // This assumes the vertices and klm coordinates are stored in the
+ // same, currently bound, buffer object, contiguously and at the
+ // specified offsets.
+ void use(unsigned vertexOffset, unsigned klmOffset, const AffineTransform&, const Color&);
+
+private:
+ LoopBlinnSolidFillShader(GraphicsContext3D*, unsigned program);
+
+ int m_colorLocation;
+};
+
+} // namespace WebCore
+
+#endif // LoopBlinnSolidFillShader_h
diff --git a/Source/WebCore/platform/graphics/gpu/Shader.cpp b/Source/WebCore/platform/graphics/gpu/Shader.cpp
index 6978322..1b9bfd5 100644
--- a/Source/WebCore/platform/graphics/gpu/Shader.cpp
+++ b/Source/WebCore/platform/graphics/gpu/Shader.cpp
@@ -38,6 +38,7 @@
#include "GraphicsContext3D.h"
#include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
namespace WebCore {
@@ -56,14 +57,34 @@ void Shader::affineTo3x3(const AffineTransform& transform, float mat[9])
}
// static
-unsigned Shader::loadShader(GraphicsContext3D* context, unsigned type, const char* shaderSource)
+void Shader::affineTo4x4(const AffineTransform& transform, float mat[16])
+{
+ mat[0] = transform.a();
+ mat[1] = transform.b();
+ mat[2] = 0.0f;
+ mat[3] = 0.0f;
+ mat[4] = transform.c();
+ mat[5] = transform.d();
+ mat[6] = 0.0f;
+ mat[7] = 0.0f;
+ mat[8] = 0.0f;
+ mat[9] = 0.0f;
+ mat[10] = 1.0f;
+ mat[11] = 0.0f;
+ mat[12] = transform.e();
+ mat[13] = transform.f();
+ mat[14] = 0.0f;
+ mat[15] = 1.0f;
+}
+
+// static
+unsigned Shader::loadShader(GraphicsContext3D* context, unsigned type, const String& shaderSource)
{
unsigned shader = context->createShader(type);
if (!shader)
return 0;
- String shaderSourceStr(shaderSource);
- context->shaderSource(shader, shaderSourceStr);
+ context->shaderSource(shader, shaderSource);
context->compileShader(shader);
int compileStatus = 0;
context->getShaderiv(shader, GraphicsContext3D::COMPILE_STATUS, &compileStatus);
@@ -77,7 +98,7 @@ unsigned Shader::loadShader(GraphicsContext3D* context, unsigned type, const cha
}
// static
-unsigned Shader::loadProgram(GraphicsContext3D* context, const char* vertexShaderSource, const char* fragmentShaderSource)
+unsigned Shader::loadProgram(GraphicsContext3D* context, const String& vertexShaderSource, const String& fragmentShaderSource)
{
unsigned vertexShader = loadShader(context, GraphicsContext3D::VERTEX_SHADER, vertexShaderSource);
if (!vertexShader)
@@ -111,6 +132,146 @@ Shader::~Shader()
m_context->deleteProgram(m_program);
}
+// static
+String Shader::generateVertex(Shader::VertexType vertexType, Shader::FillType fillType)
+{
+ StringBuilder builder;
+ switch (vertexType) {
+ case TwoDimensional:
+ builder.append(
+ "uniform mat3 matrix;\n"
+ "attribute vec3 position;\n");
+ break;
+ case LoopBlinnInterior:
+ builder.append(
+ "uniform mat4 worldViewProjection;\n"
+ "attribute vec2 position;\n");
+ break;
+ case LoopBlinnExterior:
+ builder.append(
+ "uniform mat4 worldViewProjection;\n"
+ "attribute vec2 position;\n"
+ "attribute vec3 klm;\n"
+ "varying vec3 v_klm;\n");
+ break;
+ }
+
+ if (fillType == TextureFill) {
+ builder.append(
+ "uniform mat3 texMatrix;\n"
+ "varying vec3 texCoord;\n");
+ }
+
+ builder.append(
+ "void main() {\n");
+
+ if (vertexType == TwoDimensional) {
+ builder.append(
+ "gl_Position = vec4(matrix * position, 1.0);\n");
+ } else {
+ builder.append(
+ "gl_Position = worldViewProjection * vec4(position, 0.0, 1.0);\n");
+ if (vertexType == LoopBlinnExterior) {
+ builder.append(
+ "v_klm = klm;\n");
+ }
+ }
+
+ if (fillType == TextureFill) {
+ builder.append(
+ "texCoord = texMatrix * position;\n");
+ }
+
+ builder.append(
+ "}\n");
+
+ return builder.toString();
}
+// static
+String Shader::generateFragment(Shader::VertexType vertexType, Shader::FillType fillType, Shader::AntialiasType antialiasType)
+{
+ StringBuilder builder;
+ builder.append(
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n");
+
+ if (vertexType == LoopBlinnExterior) {
+ if (antialiasType == Antialiased) {
+ builder.append(
+ "#extension GL_OES_standard_derivatives : enable\n");
+ }
+ builder.append(
+ "varying vec3 v_klm;\n");
+ }
+
+ switch (fillType) {
+ case SolidFill:
+ builder.append(
+ "uniform vec4 color;\n");
+ break;
+ case TextureFill:
+ builder.append(
+ "uniform sampler2D sampler;\n"
+ "uniform float globalAlpha;\n"
+ "varying vec3 texCoord;\n");
+ break;
+ }
+
+ builder.append(
+ "void main() {\n");
+
+ if (vertexType != LoopBlinnExterior) {
+ builder.append(
+ "float alpha = 1.0;\n");
+ } else {
+ if (antialiasType == Antialiased) {
+ builder.append(
+ " // Gradients\n"
+ " vec3 px = dFdx(v_klm);\n"
+ " vec3 py = dFdy(v_klm);\n"
+ "\n"
+ " // Chain rule\n"
+ " float k2 = v_klm.x * v_klm.x;\n"
+ " float c = k2 * v_klm.x - v_klm.y * v_klm.z;\n"
+ " float k23 = 3.0 * k2;\n"
+ " float cx = k23 * px.x - v_klm.z * px.y - v_klm.y * px.z;\n"
+ " float cy = k23 * py.x - v_klm.z * py.y - v_klm.y * py.z;\n"
+ "\n"
+ " // Signed distance\n"
+ " float sd = c / sqrt(cx * cx + cy * cy);\n"
+ "\n"
+ " // Linear alpha\n"
+ " // FIXME: figure out why this needs to be\n"
+ " // negated compared to the HLSL version, and also why\n"
+ " // we need an adjustment by +1.0 for it to look good.\n"
+ " // float alpha = clamp(0.5 - sd, 0.0, 1.0);\n"
+ " float alpha = clamp(sd + 0.5, 0.0, 1.0);\n");
+ } else {
+ builder.append(
+ " float t = v_klm.x * v_klm.x * v_klm.x - v_klm.y * v_klm.z;\n"
+ " float alpha = clamp(sign(t), 0.0, 1.0);\n");
+ }
+ }
+
+ switch (fillType) {
+ case SolidFill:
+ builder.append(
+ "gl_FragColor = color * alpha;\n");
+ break;
+ case TextureFill:
+ builder.append(
+ "gl_FragColor = texture2D(sampler, texCoord.xy) * alpha * globalAlpha;\n");
+ break;
+ }
+
+ builder.append(
+ "}\n");
+
+ return builder.toString();
+}
+
+} // namespace WebCore
+
#endif
diff --git a/Source/WebCore/platform/graphics/gpu/Shader.h b/Source/WebCore/platform/graphics/gpu/Shader.h
index 4f62ca9..35d1a3b 100644
--- a/Source/WebCore/platform/graphics/gpu/Shader.h
+++ b/Source/WebCore/platform/graphics/gpu/Shader.h
@@ -33,6 +33,7 @@
#include <wtf/Noncopyable.h>
#include <wtf/PassOwnPtr.h>
+#include <wtf/text/WTFString.h>
namespace WebCore {
@@ -42,13 +43,35 @@ class Color;
class Shader {
WTF_MAKE_NONCOPYABLE(Shader);
+public:
+ enum VertexType {
+ TwoDimensional,
+ LoopBlinnInterior,
+ LoopBlinnExterior
+ };
+
+ enum FillType {
+ SolidFill,
+ TextureFill
+ };
+
+ // Currently only applies to the Loop-Blinn vertex type.
+ enum AntialiasType {
+ NotAntialiased,
+ Antialiased
+ };
+
protected:
Shader(GraphicsContext3D*, unsigned program);
~Shader();
+ static String generateVertex(VertexType, FillType);
+ static String generateFragment(VertexType, FillType, AntialiasType);
+
static void affineTo3x3(const AffineTransform&, float mat[9]);
- static unsigned loadShader(GraphicsContext3D*, unsigned type, const char* shaderSource);
- static unsigned loadProgram(GraphicsContext3D*, const char* vertexShaderSource, const char* fragmentShaderSource);
+ static void affineTo4x4(const AffineTransform&, float mat[16]);
+ static unsigned loadShader(GraphicsContext3D*, unsigned type, const String& shaderSource);
+ static unsigned loadProgram(GraphicsContext3D*, const String& vertexShaderSource, const String& fragmentShaderSource);
GraphicsContext3D* m_context;
unsigned m_program;
diff --git a/Source/WebCore/platform/graphics/gpu/SolidFillShader.cpp b/Source/WebCore/platform/graphics/gpu/SolidFillShader.cpp
index 86079be..78381f0 100644
--- a/Source/WebCore/platform/graphics/gpu/SolidFillShader.cpp
+++ b/Source/WebCore/platform/graphics/gpu/SolidFillShader.cpp
@@ -49,23 +49,9 @@ SolidFillShader::SolidFillShader(GraphicsContext3D* context, unsigned program)
PassOwnPtr<SolidFillShader> SolidFillShader::create(GraphicsContext3D* context)
{
- static const char* vertexShaderSource =
- "uniform mat3 matrix;\n"
- "uniform vec4 color;\n"
- "attribute vec3 position;\n"
- "void main() {\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 mat3 matrix;\n"
- "uniform vec4 color;\n"
- "void main() {\n"
- " gl_FragColor = color;\n"
- "}\n";
- unsigned program = loadProgram(context, vertexShaderSource, fragmentShaderSource);
+ unsigned program = loadProgram(context,
+ generateVertex(Shader::TwoDimensional, Shader::SolidFill),
+ generateFragment(Shader::TwoDimensional, Shader::SolidFill, Shader::NotAntialiased));
if (!program)
return 0;
return new SolidFillShader(context, program);
diff --git a/Source/WebCore/platform/graphics/gpu/TexShader.cpp b/Source/WebCore/platform/graphics/gpu/TexShader.cpp
index d7ffa17..9eb5c16 100644
--- a/Source/WebCore/platform/graphics/gpu/TexShader.cpp
+++ b/Source/WebCore/platform/graphics/gpu/TexShader.cpp
@@ -43,33 +43,16 @@ TexShader::TexShader(GraphicsContext3D* context, unsigned program)
{
m_matrixLocation = context->getUniformLocation(program, "matrix");
m_texMatrixLocation = context->getUniformLocation(program, "texMatrix");
- m_alphaLocation = context->getUniformLocation(program, "alpha");
+ m_alphaLocation = context->getUniformLocation(program, "globalAlpha");
m_positionLocation = context->getAttribLocation(program, "position");
m_samplerLocation = context->getUniformLocation(program, "sampler");
}
PassOwnPtr<TexShader> TexShader::create(GraphicsContext3D* context)
{
- static const char* vertexShaderSource =
- "uniform mat3 matrix;\n"
- "uniform mat3 texMatrix;\n"
- "attribute vec3 position;\n"
- "varying vec3 texCoord;\n"
- "void main() {\n"
- " texCoord = texMatrix * position;\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 sampler;\n"
- "uniform float alpha;\n"
- "varying vec3 texCoord;\n"
- "void main() {\n"
- " gl_FragColor = texture2D(sampler, texCoord.xy)* vec4(alpha);\n"
- "}\n";
- unsigned program = loadProgram(context, vertexShaderSource, fragmentShaderSource);
+ unsigned program = loadProgram(context,
+ generateVertex(Shader::TwoDimensional, Shader::TextureFill),
+ generateFragment(Shader::TwoDimensional, Shader::TextureFill, Shader::NotAntialiased));
if (!program)
return 0;
return new TexShader(context, program);
diff --git a/Source/WebCore/platform/graphics/gpu/Texture.cpp b/Source/WebCore/platform/graphics/gpu/Texture.cpp
index e1f8114..b1ba827 100644
--- a/Source/WebCore/platform/graphics/gpu/Texture.cpp
+++ b/Source/WebCore/platform/graphics/gpu/Texture.cpp
@@ -166,7 +166,7 @@ void Texture::updateSubRect(void* pixels, const IntRect& updateRect)
int tempBuffSize = // Temporary buffer size is the smaller of the max texture size or the updateRectSanitized
min(m_tiles.maxTextureSize(), m_tiles.borderTexels() + updateRectSanitized.width()) *
min(m_tiles.maxTextureSize(), m_tiles.borderTexels() + updateRectSanitized.height());
- OwnArrayPtr<uint32_t> tempBuff(new uint32_t[tempBuffSize]);
+ OwnArrayPtr<uint32_t> tempBuff = adoptArrayPtr(new uint32_t[tempBuffSize]);
for (int tile = 0; tile < m_tiles.numTiles(); tile++) {
// Intersect with tile
diff --git a/Source/WebCore/platform/graphics/gpu/TilingData.cpp b/Source/WebCore/platform/graphics/gpu/TilingData.cpp
index a98add7..e7c4e4c 100644
--- a/Source/WebCore/platform/graphics/gpu/TilingData.cpp
+++ b/Source/WebCore/platform/graphics/gpu/TilingData.cpp
@@ -89,9 +89,9 @@ IntRect TilingData::tileBoundsWithBorder(int tile) const
if (m_borderTexels) {
int x1 = bounds.x();
- int x2 = bounds.right();
+ int x2 = bounds.maxX();
int y1 = bounds.y();
- int y2 = bounds.bottom();
+ int y2 = bounds.maxY();
if (tileXIndex(tile) > 0)
x1--;
@@ -182,8 +182,8 @@ IntRect TilingData::overlappedTileIndices(const WebCore::IntRect &srcRect) const
{
int x = tileXIndexFromSrcCoord(srcRect.x());
int y = tileYIndexFromSrcCoord(srcRect.y());
- int r = tileXIndexFromSrcCoord(srcRect.right());
- int b = tileYIndexFromSrcCoord(srcRect.bottom());
+ int r = tileXIndexFromSrcCoord(srcRect.maxX());
+ int b = tileYIndexFromSrcCoord(srcRect.maxY());
return IntRect(x, y, r - x, b - y);
}
diff --git a/Source/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm b/Source/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm
index e6dfdb8..13c0968 100644
--- a/Source/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm
+++ b/Source/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm
@@ -25,7 +25,7 @@
#include "config.h"
-#if ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(3D_CANVAS)
+#if ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(WEBGL)
#include "DrawingBuffer.h"
diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
index c113c69..69bdeab 100644
--- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
@@ -1384,11 +1384,15 @@ static HashSet<String> mimeTypeCache()
// These formats are supported by GStreamer, but not
// correctly advertised.
- if (g_str_equal(name, "video/x-h264")
- || g_str_equal(name, "audio/x-m4a")) {
+ if (g_str_equal(name, "video/x-h264")) {
cache.add(String("video/mp4"));
+ cached = true;
+ }
+
+ if (g_str_equal(name, "audio/x-m4a")) {
cache.add(String("audio/aac"));
cache.add(String("audio/mp4"));
+ cache.add(String("audio/x-m4a"));
cached = true;
}
@@ -1466,6 +1470,15 @@ static HashSet<String> mimeTypeCache()
for (int index = 0; extensions[index]; index++) {
if (g_str_equal(extensions[index], "m4v"))
cache.add(String("video/x-m4v"));
+
+ // Workaround for
+ // https://bugzilla.gnome.org/show_bug.cgi?id=640709.
+ // typefindfunctions <= 0.10.32 doesn't
+ // register the H264 typefinder correctly so
+ // as a workaround we check the registered
+ // file extensions for it.
+ if (g_str_equal(extensions[index], "h264"))
+ cache.add(String("video/mp4"));
}
}
}
diff --git a/Source/WebCore/platform/graphics/gtk/FontGtk.cpp b/Source/WebCore/platform/graphics/gtk/FontGtk.cpp
index 4d6f509..216fb56 100644
--- a/Source/WebCore/platform/graphics/gtk/FontGtk.cpp
+++ b/Source/WebCore/platform/graphics/gtk/FontGtk.cpp
@@ -215,6 +215,11 @@ bool Font::canReturnFallbackFontsForComplexText()
return false;
}
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+ return false;
+}
+
static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context, const FloatPoint& point, PangoLayoutLine* layoutLine, PangoRegionType renderRegion)
{
ContextShadow* shadow = graphicsContext->contextShadow();
diff --git a/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp
index ce7ec46..017b1e4 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, FontRenderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, 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 86f99b2..7ffe89a 100644
--- a/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.h
+++ b/Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.h
@@ -23,6 +23,7 @@
#include "FontOrientation.h"
#include "FontRenderingMode.h"
+#include "FontWidthVariant.h"
#include <wtf/Forward.h>
namespace WebCore {
@@ -38,7 +39,7 @@ namespace WebCore {
static bool supportsFormat(const String&);
- FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontRenderingMode = NormalRenderingMode);
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
};
FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer*);
diff --git a/Source/WebCore/platform/graphics/haiku/FontHaiku.cpp b/Source/WebCore/platform/graphics/haiku/FontHaiku.cpp
index 819fecb..5a1a1d0 100644
--- a/Source/WebCore/platform/graphics/haiku/FontHaiku.cpp
+++ b/Source/WebCore/platform/graphics/haiku/FontHaiku.cpp
@@ -65,6 +65,11 @@ bool Font::canReturnFallbackFontsForComplexText()
return false;
}
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+ return false;
+}
+
void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font,
const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
{
diff --git a/Source/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp b/Source/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp
index b1e7082..4ded761 100644
--- a/Source/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp
+++ b/Source/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp
@@ -48,11 +48,11 @@ void SimpleFontData::platformInit()
font_height height;
font->GetHeight(&height);
- m_ascent = static_cast<int>(height.ascent);
- m_descent = static_cast<int>(height.descent);
- m_lineSpacing = m_ascent + m_descent;
- m_xHeight = height.ascent * 0.56f; // Hack taken from the win port.
- m_lineGap = height.leading;
+ m_fontMetrics.setAscent(height.ascent);
+ m_fontMetrics.setDescent(height.descent);
+ m_fontMetrics.setXHeight(height.ascent * 0.56f); // Hack taken from the win port.
+ m_fontMetrics.setLineGap(height.leading);
+ m_fontMetrics.setLineSpacing(lroundf(height.ascent) + lroundf(height.descent) + lroundf(height.leading));
}
void SimpleFontData::platformCharWidthInit()
diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp
index 86f6bec..1fe3d28 100644
--- a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp
+++ b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009, 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
@@ -25,14 +25,13 @@
#include "config.h"
#include "ComplexTextController.h"
-#include <ApplicationServices/ApplicationServices.h>
-#include "CharacterNames.h"
#include "FloatSize.h"
#include "Font.h"
#include "TextBreakIterator.h"
#include "TextRun.h"
-
+#include <ApplicationServices/ApplicationServices.h>
#include <wtf/StdLibExtras.h>
+#include <wtf/unicode/CharacterNames.h>
#if defined(BUILDING_ON_LEOPARD)
// Undefined when compiling agains the 10.5 SDK.
@@ -71,7 +70,8 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru
, m_glyphInCurrentRun(0)
, m_characterInCurrentGlyph(0)
, m_finalRoundingWidth(0)
- , m_padding(run.padding())
+ , m_expansion(run.expansion())
+ , m_afterExpansion(true)
, m_fallbackFonts(fallbackFonts)
, m_minGlyphBoundingBoxX(numeric_limits<float>::max())
, m_maxGlyphBoundingBoxX(numeric_limits<float>::min())
@@ -79,19 +79,18 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru
, m_maxGlyphBoundingBoxY(numeric_limits<float>::min())
, m_lastRoundingGlyph(0)
{
- if (!m_padding)
- m_padPerSpace = 0;
+ if (!m_expansion)
+ m_expansionPerOpportunity = 0;
else {
- int numSpaces = 0;
- for (int s = 0; s < m_run.length(); s++) {
- if (Font::treatAsSpace(m_run[s]))
- numSpaces++;
- }
+ bool isAfterExpansion = true;
+ unsigned expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion);
+ if (isAfterExpansion && !m_run.allowsTrailingExpansion())
+ expansionOpportunityCount--;
- if (!numSpaces)
- m_padPerSpace = 0;
+ if (!expansionOpportunityCount)
+ m_expansionPerOpportunity = 0;
else
- m_padPerSpace = m_padding / numSpaces;
+ m_expansionPerOpportunity = m_expansion / expansionOpportunityCount;
}
collectComplexTextRuns();
@@ -118,9 +117,9 @@ int ComplexTextController::offsetForPosition(float h, bool includePartialGlyphs)
CFIndex hitGlyphStart = complexTextRun.indexAt(j);
CFIndex hitGlyphEnd;
if (m_run.ltr())
- hitGlyphEnd = max<CFIndex>(hitGlyphStart, j + 1 < complexTextRun.glyphCount() ? complexTextRun.indexAt(j + 1) : static_cast<CFIndex>(complexTextRun.stringLength()));
+ hitGlyphEnd = max<CFIndex>(hitGlyphStart, j + 1 < complexTextRun.glyphCount() ? complexTextRun.indexAt(j + 1) : static_cast<CFIndex>(complexTextRun.indexEnd()));
else
- hitGlyphEnd = max<CFIndex>(hitGlyphStart, j > 0 ? complexTextRun.indexAt(j - 1) : static_cast<CFIndex>(complexTextRun.stringLength()));
+ hitGlyphEnd = max<CFIndex>(hitGlyphStart, j > 0 ? complexTextRun.indexAt(j - 1) : static_cast<CFIndex>(complexTextRun.indexEnd()));
// FIXME: Instead of dividing the glyph's advance equally between the characters, this
// could use the glyph's "ligature carets". However, there is no Core Text API to get the
@@ -311,6 +310,7 @@ ComplexTextController::ComplexTextRun::ComplexTextRun(const SimpleFontData* font
, m_characters(characters)
, m_stringLocation(stringLocation)
, m_stringLength(stringLength)
+ , m_indexEnd(stringLength)
, m_isMonotonic(true)
{
#if USE(CORE_TEXT) && USE(ATSUI)
@@ -335,7 +335,7 @@ void ComplexTextController::ComplexTextRun::setIsNonMonotonic()
m_glyphEndOffsets.grow(m_glyphCount);
for (size_t i = 0; i < m_glyphCount; ++i) {
- CFIndex nextMappedIndex = m_stringLength;
+ CFIndex nextMappedIndex = m_indexEnd;
for (size_t j = indexAt(i) + 1; j < m_stringLength; ++j) {
if (mappedIndices[j]) {
nextMappedIndex = j;
@@ -370,9 +370,9 @@ void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
unsigned glyphEndOffset;
if (complexTextRun.isMonotonic()) {
if (ltr)
- glyphEndOffset = max<unsigned>(glyphStartOffset, g + 1 < glyphCount ? static_cast<unsigned>(complexTextRun.indexAt(g + 1)) : complexTextRun.stringLength());
+ glyphEndOffset = max<unsigned>(glyphStartOffset, static_cast<unsigned>(g + 1 < glyphCount ? complexTextRun.indexAt(g + 1) : complexTextRun.indexEnd()));
else
- glyphEndOffset = max<unsigned>(glyphStartOffset, g > 0 ? static_cast<unsigned>(complexTextRun.indexAt(g - 1)) : complexTextRun.stringLength());
+ glyphEndOffset = max<unsigned>(glyphStartOffset, static_cast<unsigned>(g > 0 ? complexTextRun.indexAt(g - 1) : complexTextRun.indexEnd()));
} else
glyphEndOffset = complexTextRun.endOffsetAt(g);
@@ -386,7 +386,7 @@ void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
unsigned oldCharacterInCurrentGlyph = m_characterInCurrentGlyph;
m_characterInCurrentGlyph = min(m_currentCharacter - complexTextRun.stringLocation(), glyphEndOffset) - glyphStartOffset;
- // FIXME: Instead of dividing the glyph's advance equially between the characters, this
+ // FIXME: Instead of dividing the glyph's advance equally between the characters, this
// could use the glyph's "ligature carets". However, there is no Core Text API to get the
// ligature carets.
if (glyphStartOffset == glyphEndOffset) {
@@ -421,6 +421,7 @@ void ComplexTextController::adjustGlyphsAndAdvances()
{
CGFloat widthSinceLastRounding = 0;
size_t runCount = m_complexTextRuns.size();
+ bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_expansion) && !m_run.spacingDisabled();
for (size_t r = 0; r < runCount; ++r) {
ComplexTextRun& complexTextRun = *m_complexTextRuns[r];
unsigned glyphCount = complexTextRun.glyphCount();
@@ -433,7 +434,6 @@ void ComplexTextController::adjustGlyphsAndAdvances()
const UChar* cp = complexTextRun.characters();
CGFloat roundedSpaceWidth = roundCGFloat(fontData->spaceWidth());
bool roundsAdvances = !m_font.isPrinterFont() && fontData->platformData().roundsGlyphAdvances();
- bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_padding) && !m_run.spacingDisabled();
CGPoint glyphOrigin = CGPointZero;
CFIndex lastCharacterIndex = m_run.ltr() ? numeric_limits<CFIndex>::min() : numeric_limits<CFIndex>::max();
bool isMonotonic = true;
@@ -489,25 +489,29 @@ void ComplexTextController::adjustGlyphsAndAdvances()
advance.width += m_font.letterSpacing();
// Handle justification and word-spacing.
- if (treatAsSpace) {
- // Account for padding. WebCore uses space padding to justify text.
- // We distribute the specified padding over the available spaces in the run.
- if (m_padding) {
- // Use leftover padding if not evenly divisible by number of spaces.
- if (m_padding < m_padPerSpace) {
- advance.width += m_padding;
- m_padding = 0;
- } else {
- float previousPadding = m_padding;
- m_padding -= m_padPerSpace;
- advance.width += roundf(previousPadding) - roundf(m_padding);
+ 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())) {
+ float previousExpansion = m_expansion;
+ if (!treatAsSpace && !m_afterExpansion) {
+ // Take the expansion opportunity before this ideograph.
+ m_expansion -= m_expansionPerOpportunity;
+ int expansion = roundf(previousExpansion) - roundf(m_expansion);
+ m_totalWidth += expansion;
+ m_adjustedAdvances.last().width += expansion;
+ previousExpansion = m_expansion;
}
- }
+ m_expansion -= m_expansionPerOpportunity;
+ advance.width += roundf(previousExpansion) - roundf(m_expansion);
+ m_afterExpansion = true;
+ } else
+ m_afterExpansion = false;
// Account for word-spacing.
- if (characterIndex > 0 && !Font::treatAsSpace(*m_run.data(characterIndex - 1)) && m_font.wordSpacing())
+ if (treatAsSpace && characterIndex > 0 && !Font::treatAsSpace(*m_run.data(characterIndex - 1)) && m_font.wordSpacing())
advance.width += m_font.wordSpacing();
- }
+ } else
+ m_afterExpansion = false;
}
// Deal with the float/integer impedance mismatch between CG and WebCore. "Words" (characters
@@ -549,9 +553,9 @@ void ComplexTextController::adjustGlyphsAndAdvances()
FloatRect glyphBounds = fontData->boundsForGlyph(glyph);
glyphBounds.move(glyphOrigin.x, glyphOrigin.y);
m_minGlyphBoundingBoxX = min(m_minGlyphBoundingBoxX, glyphBounds.x());
- m_maxGlyphBoundingBoxX = max(m_maxGlyphBoundingBoxX, glyphBounds.right());
+ m_maxGlyphBoundingBoxX = max(m_maxGlyphBoundingBoxX, glyphBounds.maxX());
m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, glyphBounds.y());
- m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, glyphBounds.bottom());
+ m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, glyphBounds.maxY());
glyphOrigin.x += advance.width;
glyphOrigin.y += advance.height;
diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextController.h b/Source/WebCore/platform/graphics/mac/ComplexTextController.h
index 9cf80a6..63f93a2 100644
--- a/Source/WebCore/platform/graphics/mac/ComplexTextController.h
+++ b/Source/WebCore/platform/graphics/mac/ComplexTextController.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009, 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
@@ -72,9 +72,9 @@ private:
class ComplexTextRun : public RefCounted<ComplexTextRun> {
public:
#if USE(CORE_TEXT)
- static PassRefPtr<ComplexTextRun> create(CTRunRef ctRun, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength)
+ static PassRefPtr<ComplexTextRun> create(CTRunRef ctRun, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, CFRange runRange)
{
- return adoptRef(new ComplexTextRun(ctRun, fontData, characters, stringLocation, stringLength));
+ return adoptRef(new ComplexTextRun(ctRun, fontData, characters, stringLocation, stringLength, runRange));
}
#endif
#if USE(ATSUI)
@@ -94,6 +94,7 @@ private:
unsigned stringLocation() const { return m_stringLocation; }
size_t stringLength() const { return m_stringLength; }
ALWAYS_INLINE CFIndex indexAt(size_t i) const;
+ CFIndex indexEnd() const { return m_indexEnd; }
CFIndex endOffsetAt(size_t i) const { ASSERT(!m_isMonotonic); return m_glyphEndOffsets[i]; }
const CGGlyph* glyphs() const { return m_glyphs; }
const CGSize* advances() const { return m_advances; }
@@ -102,7 +103,7 @@ private:
private:
#if USE(CORE_TEXT)
- ComplexTextRun(CTRunRef, const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength);
+ ComplexTextRun(CTRunRef, const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength, CFRange runRange);
void createTextRunFromFontDataCoreText(bool ltr);
#endif
#if USE(ATSUI)
@@ -133,6 +134,7 @@ private:
#if USE(ATSUI)
Vector<CFIndex, 64> m_atsuiIndices;
#endif
+ CFIndex m_indexEnd;
Vector<CFIndex, 64> m_glyphEndOffsets;
Vector<CGGlyph, 64> m_glyphsVector;
const CGGlyph* m_glyphs;
@@ -175,8 +177,9 @@ private:
unsigned m_glyphInCurrentRun;
unsigned m_characterInCurrentGlyph;
float m_finalRoundingWidth;
- float m_padding;
- float m_padPerSpace;
+ float m_expansion;
+ float m_expansionPerOpportunity;
+ 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 9c2ab6b..b367fdf 100644
--- a/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp
+++ b/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp
@@ -25,10 +25,10 @@
#if USE(ATSUI)
-#include "CharacterNames.h"
#include "Font.h"
#include "ShapeArabic.h"
#include "TextRun.h"
+#include <wtf/unicode/CharacterNames.h>
#ifdef __LP64__
// ATSUTextInserted() is SPI in 64-bit.
@@ -146,6 +146,7 @@ ComplexTextController::ComplexTextRun::ComplexTextRun(ATSUTextLayout atsuTextLay
, m_characters(characters)
, m_stringLocation(stringLocation)
, m_stringLength(stringLength)
+ , m_indexEnd(stringLength)
, m_directionalOverride(directionalOverride)
, m_isMonotonic(true)
{
diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp
index 07fb153..239113f 100644
--- a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp
+++ b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp
@@ -42,12 +42,13 @@ extern const CFStringRef kCTTypesetterOptionForcedEmbeddingLevel;
namespace WebCore {
-ComplexTextController::ComplexTextRun::ComplexTextRun(CTRunRef ctRun, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength)
+ComplexTextController::ComplexTextRun::ComplexTextRun(CTRunRef ctRun, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, CFRange runRange)
: m_coreTextRun(ctRun)
, m_fontData(fontData)
, m_characters(characters)
, m_stringLocation(stringLocation)
, m_stringLength(stringLength)
+ , m_indexEnd(runRange.location + runRange.length)
, m_isMonotonic(true)
{
m_glyphCount = CTRunGetGlyphCount(m_coreTextRun.get());
@@ -165,7 +166,8 @@ void ComplexTextController::collectComplexTextRunsForCharactersCoreText(const UC
for (CFIndex r = 0; r < runCount; r++) {
CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());
- m_complexTextRuns.append(ComplexTextRun::create(ctRun, fontData, cp, stringLocation, length));
+ CFRange runRange = CTRunGetStringRange(ctRun);
+ m_complexTextRuns.append(ComplexTextRun::create(ctRun, fontData, cp, stringLocation, length, runRange));
}
}
diff --git a/Source/WebCore/platform/graphics/mac/FontCacheMac.mm b/Source/WebCore/platform/graphics/mac/FontCacheMac.mm
index 068bd8e..c254906 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());
+ return new FontPlatformData(platformFont, size, syntheticBold, syntheticOblique, fontDescription.orientation(), fontDescription.widthVariant());
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp b/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp
index 02bac9c..865051d 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()) - ascent());
- glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - descent());
+ glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - fontMetrics().ascent());
+ glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - 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 d04d0e4..f2bc33d 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, FontRenderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation, FontWidthVariant widthVariant, FontRenderingMode)
{
- return FontPlatformData(m_cgFont, size, bold, italic, orientation);
+ return FontPlatformData(m_cgFont, size, bold, italic, orientation, widthVariant);
}
FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
diff --git a/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h
index 7043d7e..c7ae1ca 100644
--- a/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h
+++ b/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h
@@ -23,6 +23,7 @@
#include "FontOrientation.h"
#include "FontRenderingMode.h"
+#include "FontWidthVariant.h"
#include <CoreFoundation/CFBase.h>
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
@@ -47,7 +48,7 @@ public:
~FontCustomPlatformData();
- FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontRenderingMode = NormalRenderingMode);
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, 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 8519667..acd7562 100644
--- a/Source/WebCore/platform/graphics/mac/FontMac.mm
+++ b/Source/WebCore/platform/graphics/mac/FontMac.mm
@@ -47,6 +47,11 @@ bool Font::canReturnFallbackFontsForComplexText()
return true;
}
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+ return true;
+}
+
static void showGlyphsWithAdvances(const SimpleFontData* font, CGContextRef context, const CGGlyph* glyphs, const CGSize* advances, size_t count)
{
const FontPlatformData& platformData = font->platformData();
@@ -60,8 +65,8 @@ static void showGlyphsWithAdvances(const SimpleFontData* font, CGContextRef cont
savedMatrix = CGContextGetTextMatrix(context);
CGAffineTransform runMatrix = CGAffineTransformConcat(savedMatrix, rotateLeftTransform);
// Move start point to put glyphs into original region.
- runMatrix.tx = savedMatrix.tx + font->ascent();
- runMatrix.ty = savedMatrix.ty + font->descent();
+ runMatrix.tx = savedMatrix.tx + font->fontMetrics().ascent();
+ runMatrix.ty = savedMatrix.ty + font->fontMetrics().descent();
CGContextSetTextMatrix(context, runMatrix);
}
diff --git a/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp b/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
index 5388c24..8b04ffa 100644
--- a/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
+++ b/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
@@ -39,8 +39,8 @@ namespace WebCore {
#ifndef BUILDING_ON_TIGER
static bool shouldUseCoreText(UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
- if (fontData->orientation() == Vertical && !fontData->isBrokenIdeographFont()) {
- // Ideographs don't have a vertical variant.
+ if (fontData->platformData().widthVariant() != RegularWidth || (fontData->orientation() == Vertical && !fontData->isBrokenIdeographFont())) {
+ // Ideographs don't have a vertical variant or width variants.
for (unsigned i = 0; i < bufferLength; ++i) {
if (!Font::isCJKIdeograph(buffer[i]))
return true;
diff --git a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
index 21eb59d..aaa250b 100644
--- a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
+++ b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
@@ -25,7 +25,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
#include "GraphicsContext3D.h"
@@ -245,6 +245,10 @@ bool GraphicsContext3D::isGLES2Compliant() const
return false;
}
+void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>)
+{
+}
+
}
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
index 2361f6a..8b1fb92 100644
--- a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
+++ b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
@@ -616,7 +616,7 @@ QTTime MediaPlayerPrivateQTKit::createQTTime(float time) const
if (!metaDataAvailable())
return QTMakeTime(0, 600);
long timeScale = [[m_qtMovie.get() attributeForKey:QTMovieTimeScaleAttribute] longValue];
- return QTMakeTime(time * timeScale, timeScale);
+ return QTMakeTime(lroundf(time * timeScale), timeScale);
}
void MediaPlayerPrivateQTKit::resumeLoad()
diff --git a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
index 92585c6..3094498 100644
--- a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
+++ b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
@@ -218,19 +218,20 @@ void SimpleFontData::platformInit()
int iAscent;
int iDescent;
int iLineGap;
+ unsigned unitsPerEm;
#ifdef BUILDING_ON_TIGER
- wkGetFontMetrics(m_platformData.cgFont(), &iAscent, &iDescent, &iLineGap, &m_unitsPerEm);
+ wkGetFontMetrics(m_platformData.cgFont(), &iAscent, &iDescent, &iLineGap, &unitsPerEm);
#else
iAscent = CGFontGetAscent(m_platformData.cgFont());
iDescent = CGFontGetDescent(m_platformData.cgFont());
iLineGap = CGFontGetLeading(m_platformData.cgFont());
- m_unitsPerEm = CGFontGetUnitsPerEm(m_platformData.cgFont());
+ unitsPerEm = CGFontGetUnitsPerEm(m_platformData.cgFont());
#endif
float pointSize = m_platformData.m_size;
- float fAscent = scaleEmToUnits(iAscent, m_unitsPerEm) * pointSize;
- float fDescent = -scaleEmToUnits(iDescent, m_unitsPerEm) * pointSize;
- float fLineGap = scaleEmToUnits(iLineGap, m_unitsPerEm) * pointSize;
+ float ascent = scaleEmToUnits(iAscent, unitsPerEm) * pointSize;
+ float descent = -scaleEmToUnits(iDescent, unitsPerEm) * pointSize;
+ float lineGap = scaleEmToUnits(iLineGap, unitsPerEm) * pointSize;
// We need to adjust Times, Helvetica, and Courier to closely match the
// vertical metrics of their Microsoft counterparts that are the de facto
@@ -239,25 +240,23 @@ void SimpleFontData::platformInit()
// and add it to the ascent.
NSString *familyName = [m_platformData.font() familyName];
if ([familyName isEqualToString:@"Times"] || [familyName isEqualToString:@"Helvetica"] || [familyName isEqualToString:@"Courier"])
- fAscent += floorf(((fAscent + fDescent) * 0.15f) + 0.5f);
+ ascent += floorf(((ascent + descent) * 0.15f) + 0.5f);
else if ([familyName isEqualToString:@"Geeza Pro"]) {
// Geeza Pro has glyphs that draw slightly above the ascent or far below the descent. Adjust
// those vertical metrics to better match reality, so that diacritics at the bottom of one line
// do not overlap diacritics at the top of the next line.
- fAscent *= 1.08f;
- fDescent *= 2.f;
+ ascent *= 1.08f;
+ descent *= 2.f;
}
- m_ascent = lroundf(fAscent);
- m_descent = lroundf(fDescent);
- m_lineGap = lroundf(fLineGap);
- m_lineSpacing = m_ascent + m_descent + m_lineGap;
-
+ // Compute and store line spacing, before the line metrics hacks are applied.
+ m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));
+
// Hack Hiragino line metrics to allow room for marked text underlines.
// <rdar://problem/5386183>
- if (m_descent < 3 && m_lineGap >= 3 && [familyName hasPrefix:@"Hiragino"]) {
- m_lineGap -= 3 - m_descent;
- m_descent = 3;
+ if (descent < 3 && lineGap >= 3 && [familyName hasPrefix:@"Hiragino"]) {
+ lineGap -= 3 - descent;
+ descent = 3;
}
if (m_orientation == Vertical) {
@@ -278,6 +277,8 @@ void SimpleFontData::platformInit()
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();
@@ -288,21 +289,27 @@ void SimpleFontData::platformInit()
// 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_xHeight = static_cast<float>(max(CGRectGetMaxX(xBox), -CGRectGetMinY(xBox)));
+ xHeight = static_cast<float>(max(CGRectGetMaxX(xBox), -CGRectGetMinY(xBox)));
} else {
#ifndef BUILDING_ON_TIGER
- m_xHeight = static_cast<float>(CGFontGetXHeight(m_platformData.cgFont())) / m_unitsPerEm;
+ xHeight = static_cast<float>(CGFontGetXHeight(m_platformData.cgFont())) / unitsPerEm;
#else
- m_xHeight = m_platformData.font() ? [m_platformData.font() xHeight] : 0;
+ 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 m_xHeight in that case.
+ // 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>(m_xHeight) && fAscent)
- m_xHeight = 2 * fAscent / 3;
+ if (!static_cast<int>(xHeight) && ascent)
+ xHeight = 2 * ascent / 3;
}
+
+ m_fontMetrics.setUnitsPerEm(unitsPerEm);
+ m_fontMetrics.setAscent(ascent);
+ m_fontMetrics.setDescent(descent);
+ m_fontMetrics.setLineGap(lineGap);
+ m_fontMetrics.setXHeight(xHeight);
}
-
+
static CFDataRef copyFontTableForTag(FontPlatformData& platformData, FourCharCode tableName)
{
#ifdef BUILDING_ON_TIGER
@@ -337,7 +344,7 @@ void SimpleFontData::platformCharWidthInit()
if (os2Table && CFDataGetLength(os2Table.get()) >= 4) {
const UInt8* os2 = CFDataGetBytePtr(os2Table.get());
SInt16 os2AvgCharWidth = os2[2] * 256 + os2[3];
- m_avgCharWidth = scaleEmToUnits(os2AvgCharWidth, m_unitsPerEm) * m_platformData.m_size;
+ m_avgCharWidth = scaleEmToUnits(os2AvgCharWidth, m_fontMetrics.unitsPerEm()) * m_platformData.m_size;
}
RetainPtr<CFDataRef> headTable(AdoptCF, copyFontTableForTag(m_platformData, 'head'));
@@ -348,7 +355,7 @@ void SimpleFontData::platformCharWidthInit()
SInt16 xMin = static_cast<SInt16>(uxMin);
SInt16 xMax = static_cast<SInt16>(uxMax);
float diff = static_cast<float>(xMax - xMin);
- m_maxCharWidth = scaleEmToUnits(diff, m_unitsPerEm) * m_platformData.m_size;
+ m_maxCharWidth = scaleEmToUnits(diff, m_fontMetrics.unitsPerEm()) * m_platformData.m_size;
}
// Fallback to a cross-platform estimate, which will populate these values if they are non-positive.
@@ -387,7 +394,7 @@ SimpleFontData* SimpleFontData::scaledFontData(const FontDescription& fontDescri
BEGIN_BLOCK_OBJC_EXCEPTIONS;
float size = m_platformData.size() * scaleFactor;
- FontPlatformData scaledFontData([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toSize:size], size);
+ FontPlatformData scaledFontData([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toSize:size], size, false, false, m_platformData.orientation());
// AppKit resets the type information (screen/printer) when you convert a font to a different size.
// We have to fix up the font that we're handed back.
@@ -470,13 +477,13 @@ FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const
#ifndef BUILDING_ON_TIGER
boundingBox = CTFontGetBoundingRectsForGlyphs(m_platformData.ctFont(),
orientation() == Vertical ? kCTFontVerticalOrientation : kCTFontHorizontalOrientation, &glyph, 0, 1);
- boundingBox.setY(-boundingBox.bottom());
+ 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.bottom());
+ boundingBox.setY(-boundingBox.maxY());
#endif
if (m_syntheticBoldOffset)
boundingBox.setWidth(boundingBox.width() + m_syntheticBoldOffset);
diff --git a/Source/WebCore/platform/graphics/mac/WebGLLayer.mm b/Source/WebCore/platform/graphics/mac/WebGLLayer.mm
index c24181b..d1007b9 100644
--- a/Source/WebCore/platform/graphics/mac/WebGLLayer.mm
+++ b/Source/WebCore/platform/graphics/mac/WebGLLayer.mm
@@ -26,7 +26,7 @@
#include "config.h"
#if USE(ACCELERATED_COMPOSITING)
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
#import "WebGLLayer.h"
@@ -163,5 +163,5 @@ static void freeData(void *, const void *data, size_t /* size */)
@end
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(WEBGL)
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp
index 3eb5196..df45147 100644
--- a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp
+++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp
@@ -25,7 +25,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
#include "Extensions3DOpenGL.h"
@@ -79,6 +79,10 @@ bool Extensions3DOpenGL::supports(const String& name)
if (name == "GL_ANGLE_framebuffer_multisample")
return m_availableExtensions.contains("GL_EXT_framebuffer_multisample");
+ // Desktop GL always supports GL_OES_rgb8_rgba8.
+ if (name == "GL_OES_rgb8_rgba8")
+ return true;
+
// If GL_ARB_texture_float is available then we report GL_OES_texture_float and
// GL_OES_texture_half_float as available.
if (name == "GL_OES_texture_float" || name == "GL_OES_texture_half_float")
@@ -125,4 +129,4 @@ void Extensions3DOpenGL::renderbufferStorageMultisample(unsigned long target, un
} // namespace WebCore
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
index 7c103f3..c224e20 100644
--- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
+++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
@@ -25,7 +25,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
#include "GraphicsContext3D.h"
@@ -83,7 +83,7 @@ void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* co
int rowBytes = m_currentWidth * 4;
int totalBytes = rowBytes * m_currentHeight;
- OwnArrayPtr<unsigned char> pixels(new unsigned char[totalBytes]);
+ OwnArrayPtr<unsigned char> pixels = adoptArrayPtr(new unsigned char[totalBytes]);
if (!pixels)
return;
@@ -1437,28 +1437,6 @@ void GraphicsContext3D::deleteTexture(Platform3DObject texture)
glDeleteTextures(1, &texture);
}
-uint32_t GraphicsContext3D::sizeInBytes(GC3Denum type)
-{
- switch (type) {
- case GL_BYTE:
- return sizeof(GLbyte);
- case GL_UNSIGNED_BYTE:
- return sizeof(GLubyte);
- case GL_SHORT:
- return sizeof(GLshort);
- case GL_UNSIGNED_SHORT:
- return sizeof(GLushort);
- case GL_INT:
- return sizeof(GLint);
- case GL_UNSIGNED_INT:
- return sizeof(GLuint);
- case GL_FLOAT:
- return sizeof(GLfloat);
- default:
- return 0;
- }
-}
-
void GraphicsContext3D::synthesizeGLError(GC3Denum error)
{
m_syntheticErrors.add(error);
@@ -1473,4 +1451,4 @@ Extensions3D* GraphicsContext3D::getExtensions()
}
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp
index 03f9b7c..2e2082d 100644
--- a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp
+++ b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp
@@ -390,7 +390,7 @@ void TextureMapperGL::drawTexture(const BitmapTexture& texture, const IntRect& t
const GLfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1};
GL_CMD(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, unitRect))
- TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix).multLeft(modelViewMatrix).multLeft(TransformationMatrix(
+ TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix).multiply(modelViewMatrix).multiply(TransformationMatrix(
targetRect.width(), 0, 0, 0,
0, targetRect.height(), 0, 0,
0, 0, 1, 0,
@@ -606,7 +606,7 @@ void TextureMapperGL::paintToTarget(const BitmapTexture& aSurface, const IntSize
const BitmapTextureGL& surface = static_cast<const BitmapTextureGL&>(aSurface);
// Create the model-view-projection matrix to display on screen.
- TransformationMatrix matrix = createProjectionMatrix(surfaceSize, true).multLeft(transform).multLeft(
+ TransformationMatrix matrix = createProjectionMatrix(surfaceSize, true).multiply(transform).multiply(
TransformationMatrix(
surface.m_actualSize.width(), 0, 0, 0,
0, surface.m_actualSize.height(), 0, 0,
diff --git a/Source/WebCore/platform/graphics/pango/FontCustomPlatformDataPango.cpp b/Source/WebCore/platform/graphics/pango/FontCustomPlatformDataPango.cpp
index a158689..f9d36d3 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, FontRenderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode)
{
return FontPlatformData(m_fontFace, size, bold, italic);
}
diff --git a/Source/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp b/Source/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp
index d0bf836..3fe15b3 100644
--- a/Source/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp
+++ b/Source/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp
@@ -49,21 +49,27 @@ void SimpleFontData::platformInit()
cairo_font_extents_t font_extents;
cairo_text_extents_t text_extents;
cairo_scaled_font_extents(m_platformData.m_scaledFont, &font_extents);
- m_ascent = static_cast<int>(lroundf(font_extents.ascent));
- m_descent = static_cast<int>(lroundf(font_extents.descent));
- m_lineSpacing = static_cast<int>(lroundf(font_extents.height));
+
+ m_fontMetrics.setAscent(font_extents.ascent);
+ m_fontMetrics.setDescent(font_extents.descent);
+
// There seems to be some rounding error in cairo (or in how we
// use cairo) with some fonts, like DejaVu Sans Mono, which makes
// cairo report a height smaller than ascent + descent, which is
// wrong and confuses WebCore's layout system. Workaround this
// while we figure out what's going on.
- if (m_lineSpacing < m_ascent + m_descent)
- m_lineSpacing = m_ascent + m_descent;
+ float lineSpacing = font_extents.height;
+ if (lineSpacing < font_extents.ascent + font_extents.descent)
+ lineSpacing = font_extents.ascent + font_extents.descent;
+ m_fontMetrics.setLineSpacing(lroundf(lineSpacing));
+ m_fontMetrics.setLineGap(lineSpacing - font_extents.ascent - font_extents.descent);
+
cairo_scaled_font_text_extents(m_platformData.m_scaledFont, "x", &text_extents);
- m_xHeight = text_extents.height;
+ m_fontMetrics.setXHeight(text_extents.height);
+
cairo_scaled_font_text_extents(m_platformData.m_scaledFont, " ", &text_extents);
- m_spaceWidth = static_cast<float>(text_extents.x_advance);
- m_lineGap = m_lineSpacing - m_ascent - m_descent;
+ m_spaceWidth = static_cast<float>(text_extents.x_advance);
+
m_syntheticBoldOffset = m_platformData.syntheticBold() ? 1.0f : 0.f;
}
diff --git a/Source/WebCore/platform/graphics/qt/ContextShadowQt.cpp b/Source/WebCore/platform/graphics/qt/ContextShadowQt.cpp
index 37d6b44..9eb31a7 100644
--- a/Source/WebCore/platform/graphics/qt/ContextShadowQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/ContextShadowQt.cpp
@@ -57,7 +57,7 @@ private:
ShadowBuffer::ShadowBuffer(QObject* parent)
: QObject(parent)
- , timerId(0)
+ , timerId(-1)
{
}
@@ -89,7 +89,8 @@ QImage* ShadowBuffer::scratchImage(const QSize& size)
void ShadowBuffer::schedulePurge()
{
static const double BufferPurgeDelay = 2; // seconds
- killTimer(timerId);
+ if (timerId >= 0)
+ killTimer(timerId);
timerId = startTimer(BufferPurgeDelay * 1000);
}
diff --git a/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp b/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp
index cd28f0e..5238d46 100644
--- a/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp
@@ -25,7 +25,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
#include "Extensions3DQt.h"
@@ -58,4 +58,4 @@ int Extensions3DQt::getGraphicsResetStatusARB()
} // namespace WebCore
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h
index 54fa679..e8441d2 100644
--- a/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h
+++ b/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h
@@ -24,6 +24,7 @@
#include "FontOrientation.h"
#include "FontRenderingMode.h"
+#include "FontWidthVariant.h"
#include <wtf/FastAllocBase.h>
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
@@ -42,7 +43,7 @@ public:
// for use with QFontDatabase::addApplicationFont/removeApplicationFont
int m_handle;
- FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontRenderingMode = NormalRenderingMode);
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, 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 e2f009b..ec8747d 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, FontRenderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode)
{
QFont font;
font.setFamily(QFontDatabase::applicationFontFamilies(m_handle)[0]);
diff --git a/Source/WebCore/platform/graphics/qt/FontQt.cpp b/Source/WebCore/platform/graphics/qt/FontQt.cpp
index 778a13f..646cd0e 100644
--- a/Source/WebCore/platform/graphics/qt/FontQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/FontQt.cpp
@@ -61,14 +61,14 @@ static const QString fromRawDataWithoutRef(const String& string, int start = 0,
static QTextLine setupLayout(QTextLayout* layout, const TextRun& style)
{
int flags = style.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
- if (style.padding())
+ if (style.expansion())
flags |= Qt::TextJustificationForced;
layout->setFlags(flags);
layout->beginLayout();
QTextLine line = layout->createLine();
line.setLineWidth(INT_MAX/256);
- if (style.padding())
- line.setLineWidth(line.naturalTextWidth() + style.padding());
+ if (style.expansion())
+ line.setLineWidth(line.naturalTextWidth() + style.expansion());
layout->endLayout();
return line;
}
@@ -107,7 +107,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
textStrokePen = QPen(QColor(ctx->strokeColor()), ctx->strokeThickness());
}
- String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
QString string = fromRawDataWithoutRef(sanitized);
QPointF pt(point.x(), point.y());
@@ -196,7 +196,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
p->save();
p->setPen(ctxShadow->m_color);
p->translate(ctxShadow->offset());
- p->drawText(pt, string, flags, run.padding());
+ p->drawText(pt, string, flags, run.expansion());
p->restore();
} else {
QFontMetrics fm(font);
@@ -210,7 +210,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
// Since it will be blurred anyway, we don't care about render hints.
shadowPainter->setFont(p->font());
shadowPainter->setPen(ctxShadow->m_color);
- shadowPainter->drawText(pt, string, flags, run.padding());
+ shadowPainter->drawText(pt, string, flags, run.expansion());
ctxShadow->endShadowLayer(ctx);
}
}
@@ -243,7 +243,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
if (ctx->textDrawingMode() & TextModeFill) {
QPen previousPen = p->pen();
p->setPen(textFillPen);
- p->drawText(pt, string, flags, run.padding());
+ p->drawText(pt, string, flags, run.expansion());
p->setPen(previousPen);
}
}
@@ -299,7 +299,7 @@ float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer
if (!run.length())
return 0;
- String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
QString string = fromRawDataWithoutRef(sanitized);
int w = QFontMetrics(font()).width(string, -1, Qt::TextBypassShaping);
@@ -308,7 +308,7 @@ float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer
if (treatAsSpace(run[0]))
w -= m_wordSpacing;
- return w + run.padding();
+ return w + run.expansion();
#else
Q_ASSERT(false);
return 0;
@@ -324,9 +324,9 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
return 0;
if (run.length() == 1 && treatAsSpace(run[0]))
- return QFontMetrics(font()).width(space) + run.padding();
+ return QFontMetrics(font()).width(space) + run.expansion();
- String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
QString string = fromRawDataWithoutRef(sanitized);
int w = QFontMetrics(font()).width(string);
@@ -334,13 +334,13 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
if (treatAsSpace(run[0]))
w -= m_wordSpacing;
- return w + run.padding();
+ return w + run.expansion();
}
int Font::offsetForPositionForSimpleText(const TextRun& run, float position, bool includePartialGlyphs) const
{
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
- String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
QString string = fromRawDataWithoutRef(sanitized);
QFontMetrics fm(font());
@@ -367,7 +367,7 @@ int Font::offsetForPositionForSimpleText(const TextRun& run, float position, boo
int Font::offsetForPositionForComplexText(const TextRun& run, float position, bool) const
{
- String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
QString string = fromRawDataWithoutRef(sanitized);
QTextLayout layout(string, font());
@@ -378,7 +378,7 @@ 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(String(run.characters(), run.length()));
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
QString wholeText = fromRawDataWithoutRef(sanitized);
QString selectedText = fromRawDataWithoutRef(sanitized, from, qMin(to - from, wholeText.length() - from));
@@ -394,7 +394,7 @@ FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint&
FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const
{
- String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
QString string = fromRawDataWithoutRef(sanitized);
QTextLayout layout(string, font());
@@ -413,6 +413,11 @@ bool Font::canReturnFallbackFontsForComplexText()
return false;
}
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+ return false;
+}
+
bool Font::primaryFontHasGlyphForCharacter(UChar32) const
{
notImplemented();
diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
index 295212c..8b87f5f 100644
--- a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
@@ -34,7 +34,7 @@
#include <wtf/UnusedParam.h>
#include <wtf/text/CString.h>
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
namespace WebCore {
@@ -1611,28 +1611,6 @@ void GraphicsContext3D::deleteTexture(Platform3DObject texture)
glDeleteTextures(1, &texture);
}
-unsigned int GraphicsContext3D::sizeInBytes(GC3Denum type)
-{
- switch (type) {
- case GraphicsContext3D::BYTE:
- return sizeof(GLbyte);
- case GraphicsContext3D::UNSIGNED_BYTE:
- return sizeof(GLubyte);
- case GraphicsContext3D::SHORT:
- return sizeof(GLshort);
- case GraphicsContext3D::UNSIGNED_SHORT:
- return sizeof(GLushort);
- case GraphicsContext3D::INT:
- return sizeof(GLint);
- case GraphicsContext3D::UNSIGNED_INT:
- return sizeof(GLuint);
- case GraphicsContext3D::FLOAT:
- return sizeof(GLfloat);
- default:
- return 0;
- }
-}
-
void GraphicsContext3D::synthesizeGLError(GC3Denum error)
{
m_internal->m_syntheticErrors.add(error);
@@ -1669,6 +1647,10 @@ bool GraphicsContext3D::getImageData(Image* image,
format, type, neededAlphaOp, outputVector.data());
}
+void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>)
+{
+}
+
}
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index 4dabe09..bf2826c 100644
--- a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -62,14 +62,11 @@
#include <QPolygonF>
#include <QStack>
#include <QVector>
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
+#include <wtf/MathExtras.h>
namespace WebCore {
-QPainter::CompositionMode GraphicsContext::toQtCompositionMode(CompositeOperator op)
+static inline QPainter::CompositionMode toQtCompositionMode(CompositeOperator op)
{
switch (op) {
case CompositeClear:
@@ -231,8 +228,15 @@ GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p, cons
if (!painter)
return;
+#if OS(SYMBIAN)
+ if (painter->paintEngine()->type() == QPaintEngine::OpenVG)
+ antiAliasingForRectsAndLines = true;
+ else
+ antiAliasingForRectsAndLines = painter->testRenderHint(QPainter::Antialiasing);
+#else
// Use the default the QPainter was constructed with.
antiAliasingForRectsAndLines = painter->testRenderHint(QPainter::Antialiasing);
+#endif
// Used for default image interpolation quality.
initialSmoothPixmapTransformHint = painter->testRenderHint(QPainter::SmoothPixmapTransform);
@@ -784,7 +788,7 @@ void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
p->setClipPath(platformPath, Qt::IntersectClip);
}
-void drawFocusRingForPath(QPainter* p, const QPainterPath& path, int width, const Color& color, bool antiAliasing)
+void drawFocusRingForPath(QPainter* p, const QPainterPath& path, const Color& color, bool antiAliasing)
{
const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::Antialiasing, antiAliasing);
@@ -794,9 +798,8 @@ void drawFocusRingForPath(QPainter* p, const QPainterPath& path, int width, cons
QPen nPen = p->pen();
nPen.setColor(color);
- nPen.setWidth(width);
p->setBrush(Qt::NoBrush);
- nPen.setStyle(Qt::SolidLine);
+ nPen.setStyle(Qt::DotLine);
p->strokePath(path, nPen);
p->setBrush(oldBrush);
@@ -805,14 +808,14 @@ void drawFocusRingForPath(QPainter* p, const QPainterPath& path, int width, cons
p->setRenderHint(QPainter::Antialiasing, antiAlias);
}
-void GraphicsContext::drawFocusRing(const Path& path, int width, int offset, const Color& color)
+void GraphicsContext::drawFocusRing(const Path& path, int /* width */, int offset, const Color& color)
{
// FIXME: Use 'offset' for something? http://webkit.org/b/49909
if (paintingDisabled() || !color.isValid())
return;
- drawFocusRingForPath(m_data->p(), path.platformPath(), width, color, m_data->antiAliasingForRectsAndLines);
+ drawFocusRingForPath(m_data->p(), path.platformPath(), color, m_data->antiAliasingForRectsAndLines);
}
/**
@@ -840,8 +843,7 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int
tmpPath.addRoundedRect(rect, radius, radius);
path = path.united(tmpPath);
}
-
- drawFocusRingForPath(m_data->p(), path, width, color, m_data->antiAliasingForRectsAndLines);
+ drawFocusRingForPath(m_data->p(), path, color, m_data->antiAliasingForRectsAndLines);
}
void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool)
@@ -896,7 +898,7 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
qreal deviceScaleY = sqrtf(deviceTransform.m21() * deviceTransform.m21() + deviceTransform.m22() * deviceTransform.m22());
QPoint deviceOrigin(frect.x() * deviceScaleX, frect.y() * deviceScaleY);
- QPoint deviceLowerRight(frect.right() * deviceScaleX, frect.bottom() * deviceScaleY);
+ QPoint deviceLowerRight(frect.maxX() * deviceScaleX, frect.maxY() * deviceScaleY);
// Don't let the height or width round to 0 unless either was originally 0
if (deviceOrigin.y() == deviceLowerRight.y() && frect.height())
@@ -1135,7 +1137,7 @@ void GraphicsContext::rotate(float radians)
if (paintingDisabled())
return;
- m_data->p()->rotate(180 / M_PI*radians);
+ m_data->p()->rotate(rad2deg(qreal(radians)));
}
void GraphicsContext::scale(const FloatSize& s)
diff --git a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
index 75fb427..0d7aa45 100644
--- a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
@@ -305,7 +305,7 @@ public:
}
} m_state;
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
const GraphicsContext3D* m_gc3D;
#endif
@@ -335,7 +335,7 @@ GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer)
#if ENABLE(TILED_BACKING_STORE)
, m_tiledBackingStore(0)
#endif
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
, m_gc3D(0)
#endif
{
@@ -529,12 +529,12 @@ void GraphicsLayerQtImpl::updateTransform()
// have to maintain that ourselves for 3D.
localTransform
.translate3d(originX + m_state.pos.x(), originY + m_state.pos.y(), m_state.anchorPoint.z())
- .multLeft(m_baseTransform)
+ .multiply(m_baseTransform)
.translate3d(-originX, -originY, -m_state.anchorPoint.z());
// This is the actual 3D transform of this item, with the ancestors' transform baked in.
m_transformRelativeToRootLayer = TransformationMatrix(parent ? parent->m_transformRelativeToRootLayer : TransformationMatrix())
- .multLeft(localTransform);
+ .multiply(localTransform);
// Now we have enough information to determine if the layer is facing backwards.
if (!m_state.backfaceVisibility && m_transformRelativeToRootLayer.inverse().m33() < 0) {
@@ -562,7 +562,7 @@ void GraphicsLayerQtImpl::updateTransform()
if (!m_state.childrenTransform.isIdentity()) {
m_transformRelativeToRootLayer
.translate(m_size.width() / 2, m_size.height() /2)
- .multLeft(m_state.childrenTransform)
+ .multiply(m_state.childrenTransform)
.translate(-m_size.width() / 2, -m_size.height() /2);
}
@@ -647,7 +647,7 @@ 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(3D_CANVAS)
+#if ENABLE(WEBGL)
case Canvas3DContentType:
m_gc3D->paint(painter, option->rect);
break;
@@ -791,7 +791,7 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform
setFlag(ItemHasNoContents, !m_layer->drawsContent());
break;
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
case Canvas3DContentType:
if (m_pendingContent.contentType != m_currentContent.contentType)
update();
@@ -1250,7 +1250,7 @@ void GraphicsLayerQt::setContentsBackgroundColor(const Color& color)
GraphicsLayer::setContentsBackgroundColor(color);
}
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
void GraphicsLayerQt::setContentsToGraphicsContext3D(const GraphicsContext3D* ctx)
{
if (ctx == m_impl->m_gc3D)
diff --git a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h
index 8027143..569bd8d 100644
--- a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h
+++ b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h
@@ -20,7 +20,7 @@
#ifndef GraphicsLayerQt_h
#define GraphicsLayerQt_h
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
#include "GraphicsContext3D.h"
#endif
#include "GraphicsLayer.h"
@@ -79,7 +79,7 @@ public:
virtual void setContentsNeedsDisplay();
virtual void setContentsToMedia(PlatformLayer*);
virtual void setContentsBackgroundColor(const Color&);
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
virtual void setContentsToGraphicsContext3D(const GraphicsContext3D*);
virtual void setGraphicsContext3DNeedsDisplay();
#endif
diff --git a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp
index d1567ec..62f5c3e 100644
--- a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp
@@ -188,7 +188,7 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& i
RefPtr<ByteArray> result = ByteArray::create(rect.width() * rect.height() * 4);
unsigned char* data = result->data();
- if (rect.x() < 0 || rect.y() < 0 || rect.right() > size.width() || rect.bottom() > size.height())
+ if (rect.x() < 0 || rect.y() < 0 || rect.maxX() > size.width() || rect.maxY() > size.height())
memset(data, 0, result->length());
int originx = rect.x();
@@ -197,7 +197,7 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& i
destx = -originx;
originx = 0;
}
- int endx = rect.right();
+ int endx = rect.maxX();
if (endx > size.width())
endx = size.width();
int numColumns = endx - originx;
@@ -208,7 +208,7 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& i
desty = -originy;
originy = 0;
}
- int endy = rect.bottom();
+ int endy = rect.maxY();
if (endy > size.height())
endy = size.height();
int numRows = endy - originy;
@@ -302,9 +302,9 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
ASSERT(destx >= 0);
ASSERT(destx < size.width());
ASSERT(originx >= 0);
- ASSERT(originx <= sourceRect.right());
+ ASSERT(originx <= sourceRect.maxX());
- int endx = destPoint.x() + sourceRect.right();
+ int endx = destPoint.x() + sourceRect.maxX();
ASSERT(endx <= size.width());
int numColumns = endx - destx;
@@ -314,9 +314,9 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
ASSERT(desty >= 0);
ASSERT(desty < size.height());
ASSERT(originy >= 0);
- ASSERT(originy <= sourceRect.bottom());
+ ASSERT(originy <= sourceRect.maxY());
- int endy = destPoint.y() + sourceRect.bottom();
+ int endy = destPoint.y() + sourceRect.maxY();
ASSERT(endy <= size.height());
int numRows = endy - desty;
diff --git a/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
index 71352e4..3540994 100644
--- a/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
@@ -213,7 +213,7 @@ bool ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex)
// now into the ImageFrame - even if the image is not
ImageFrame* const buffer = &m_frameBufferCache[frameIndex];
- buffer->setRect(m_reader->currentImageRect());
+ buffer->setOriginalFrameRect(m_reader->currentImageRect());
buffer->setStatus(ImageFrame::FrameComplete);
buffer->setDuration(m_reader->nextImageDelay());
buffer->setPixmap(pixmap);
diff --git a/Source/WebCore/platform/graphics/qt/ImageQt.cpp b/Source/WebCore/platform/graphics/qt/ImageQt.cpp
index 58f82ef..0c8ce9e 100644
--- a/Source/WebCore/platform/graphics/qt/ImageQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/ImageQt.cpp
@@ -120,11 +120,9 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
CompositeOperator previousOperator = ctxt->compositeOperation();
- ctxt->setCompositeOperation(op);
- QPainter* p = ctxt->platformContext();
- if (!pixmap.hasAlpha() && p->compositionMode() == QPainter::CompositionMode_SourceOver)
- p->setCompositionMode(QPainter::CompositionMode_Source);
+ ctxt->setCompositeOperation(!pixmap.hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
+ QPainter* p = ctxt->platformContext();
QTransform transform(patternTransform);
// If this would draw more than one scaled tile, we scale the pixmap first and then use the result to draw.
@@ -223,15 +221,8 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
return;
}
- QPainter* painter(ctxt->platformContext());
-
- QPainter::CompositionMode compositionMode = GraphicsContext::toQtCompositionMode(op);
-
- if (!image->hasAlpha() && painter->compositionMode() == QPainter::CompositionMode_SourceOver)
- compositionMode = QPainter::CompositionMode_Source;
-
- QPainter::CompositionMode lastCompositionMode = painter->compositionMode();
- painter->setCompositionMode(compositionMode);
+ CompositeOperator previousOperator = ctxt->compositeOperation();
+ ctxt->setCompositeOperation(!image->hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
ContextShadow* shadow = ctxt->contextShadow();
if (shadow->m_type != ContextShadow::NoShadow) {
@@ -243,11 +234,9 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
}
}
- // Test using example site at
- // http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html
- painter->drawPixmap(normalizedDst, *image, normalizedSrc);
+ ctxt->platformContext()->drawPixmap(normalizedDst, *image, normalizedSrc);
- painter->setCompositionMode(lastCompositionMode);
+ ctxt->setCompositeOperation(previousOperator);
if (imageObserver())
imageObserver()->didDraw(this);
diff --git a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
index b881036..fab4db1 100644
--- a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
+++ b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
@@ -102,7 +102,7 @@ MediaPlayerPrivatePhonon::MediaPlayerPrivatePhonon(MediaPlayer* player)
// Make sure we get updates for each frame
m_videoWidget->installEventFilter(this);
- foreach (QWidget* widget, qFindChildren<QWidget*>(m_videoWidget))
+ foreach (QWidget* widget, m_videoWidget->findChildren<QWidget*>())
widget->installEventFilter(this);
connect(m_mediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
diff --git a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
index 0a4c0f6..caf9c2d 100644
--- a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
@@ -215,7 +215,7 @@ void MediaPlayerPrivateQt::commitLoad(const String& url)
// Don't set the header if there are no cookies.
// This prevents a warning from being emitted.
if (!cookies.isEmpty())
- request.setHeader(QNetworkRequest::CookieHeader, qVariantFromValue(cookies));
+ request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookies));
// Set the refferer, but not when requesting insecure content from a secure page
QUrl documentUrl = QUrl(QString(document->documentURI()));
@@ -543,7 +543,7 @@ void MediaPlayerPrivateQt::updateStates()
m_readyState = MediaPlayer::HaveCurrentData;
} else if (currentStatus == QMediaPlayer::BufferedMedia
|| currentStatus == QMediaPlayer::EndOfMedia) {
- m_networkState = MediaPlayer::Idle;
+ m_networkState = MediaPlayer::Loaded;
m_readyState = MediaPlayer::HaveEnoughData;
} else if (currentStatus == QMediaPlayer::InvalidMedia) {
m_networkState = MediaPlayer::NetworkError;
@@ -618,6 +618,21 @@ void MediaPlayerPrivateQt::paint(GraphicsContext* context, const IntRect& rect)
m_videoScene->render(painter, QRectF(QRect(rect)), m_videoItem->sceneBoundingRect());
}
+void MediaPlayerPrivateQt::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& rect)
+{
+ if (context->paintingDisabled())
+ return;
+
+ if (!m_isVisible)
+ return;
+
+ // Grab the painter and widget
+ QPainter* painter = context->platformContext();
+
+ // Render the video, using the item as it might not be in the scene
+ m_videoItem->paint(painter, 0, 0);
+}
+
void MediaPlayerPrivateQt::repaint()
{
m_webCorePlayer->repaint();
diff --git a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h
index 2621432..e4133db 100644
--- a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h
+++ b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h
@@ -89,6 +89,8 @@ public:
void setSize(const IntSize&);
void paint(GraphicsContext*, const IntRect&);
+ // reimplemented for canvas drawImage(HTMLVideoElement)
+ void paintCurrentFrameInContext(GraphicsContext*, const IntRect&);
bool supportsFullscreen() const { return true; }
diff --git a/Source/WebCore/platform/graphics/qt/PathQt.cpp b/Source/WebCore/platform/graphics/qt/PathQt.cpp
index 571b405..ad482f7 100644
--- a/Source/WebCore/platform/graphics/qt/PathQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/PathQt.cpp
@@ -39,15 +39,9 @@
#include <QPainterPath>
#include <QTransform>
#include <QString>
+#include <wtf/MathExtras.h>
#include <wtf/OwnPtr.h>
-#define _USE_MATH_DEFINES
-#include <math.h>
-
-#ifndef M_PI
-# define M_PI 3.14159265358979323846
-#endif
-
namespace WebCore {
Path::Path()
@@ -263,7 +257,6 @@ void Path::closeSubpath()
m_path.closeSubpath();
}
-#define DEGREES(t) ((t) * 180.0 / M_PI)
void Path::addArc(const FloatPoint& p, float r, float sar, float ear, bool anticlockwise)
{
qreal xc = p.x();
@@ -280,8 +273,8 @@ void Path::addArc(const FloatPoint& p, float r, float sar, float ear, bool antic
anticlockwise = !anticlockwise;
//end hack
- float sa = DEGREES(sar);
- float ea = DEGREES(ear);
+ float sa = rad2deg(sar);
+ float ea = rad2deg(ear);
double span = 0;
@@ -438,6 +431,14 @@ float Path::normalAngleAtLength(float length, bool& ok)
qreal percent = m_path.percentAtLength(length);
qreal angle = m_path.angleAtPercent(percent);
+ // Normalize angle value.
+ // QPainterPath returns angle values with the origo being at the top left corner.
+ // In case of moveTo(0, 0) and addLineTo(0, 10) the angle is 270,
+ // while the caller expects it to be 90.
+ // Normalize the value by mirroring it to the x-axis.
+ // For more info look at pathLengthApplierFunction().
+ if (angle > 0)
+ angle = 360 - angle;
return angle;
}
diff --git a/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp b/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
index 47ddf02..9e43558 100644
--- a/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
@@ -24,7 +24,7 @@
#include "config.h"
#include "SimpleFontData.h"
-#include <QFontMetrics>
+#include <QFontMetricsF>
namespace WebCore {
@@ -41,25 +41,19 @@ bool SimpleFontData::containsCharacters(const UChar*, int) const
void SimpleFontData::platformInit()
{
if (!m_platformData.size()) {
- m_ascent = 0;
- m_descent = 0;
- m_lineGap = 0;
- m_lineSpacing = 0;
+ m_fontMetrics.reset();
m_avgCharWidth = 0;
m_maxCharWidth = 0;
- m_xHeight = 0;
- m_unitsPerEm = 0;
return;
}
- QFontMetrics fm(m_platformData.font());
-
- m_ascent = fm.ascent();
- m_descent = fm.descent();
- m_lineSpacing = fm.lineSpacing();
- m_xHeight = fm.xHeight();
+ QFontMetricsF fm(m_platformData.font());
+ m_fontMetrics.setAscent(fm.ascent());
+ m_fontMetrics.setDescent(fm.descent());
+ m_fontMetrics.setXHeight(fm.xHeight());
+ m_fontMetrics.setLineGap(fm.leading());
+ m_fontMetrics.setLineSpacing(fm.lineSpacing());
m_spaceWidth = fm.width(QLatin1Char(' '));
- m_lineGap = fm.leading();
}
void SimpleFontData::platformGlyphInit()
diff --git a/Source/WebCore/platform/graphics/qt/TransparencyLayer.h b/Source/WebCore/platform/graphics/qt/TransparencyLayer.h
index ff9ef20..f13deb0 100644
--- a/Source/WebCore/platform/graphics/qt/TransparencyLayer.h
+++ b/Source/WebCore/platform/graphics/qt/TransparencyLayer.h
@@ -59,9 +59,8 @@ public:
painter.setPen(p->pen());
painter.setBrush(p->brush());
painter.setTransform(p->transform(), true);
- painter.setOpacity(p->opacity());
painter.setFont(p->font());
- painter.setCompositionMode(p->compositionMode());
+ painter.setOpacity(1);
}
TransparencyLayer()
diff --git a/Source/WebCore/platform/graphics/skia/FloatRectSkia.cpp b/Source/WebCore/platform/graphics/skia/FloatRectSkia.cpp
index a10371f..23045ba 100644
--- a/Source/WebCore/platform/graphics/skia/FloatRectSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/FloatRectSkia.cpp
@@ -43,7 +43,7 @@ FloatRect::FloatRect(const SkRect& r)
FloatRect::operator SkRect() const
{
- SkRect rect = { x(), y(), right(), bottom() };
+ SkRect rect = { x(), y(), maxX(), maxY() };
return rect;
}
diff --git a/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp
index 0b31dfa..0e68c21 100644
--- a/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp
+++ b/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp
@@ -65,7 +65,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
#endif
}
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation, FontRenderingMode mode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation, FontWidthVariant, FontRenderingMode mode)
{
#if OS(WINDOWS)
ASSERT(m_fontReference);
@@ -114,13 +114,12 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b
// not allow access from CSS.
static String createUniqueFontName()
{
- Vector<char> fontUuid(sizeof(GUID));
- CoCreateGuid(reinterpret_cast<GUID*>(fontUuid.data()));
+ GUID fontUuid;
+ CoCreateGuid(&fontUuid);
- Vector<char> fontNameVector;
- base64Encode(fontUuid, fontNameVector);
- ASSERT(fontNameVector.size() < LF_FACESIZE);
- return String(fontNameVector.data(), fontNameVector.size());
+ String fontName = base64Encode(reinterpret_cast<char*>(&fontUuid), sizeof(fontUuid));
+ ASSERT(fontName.length() < LF_FACESIZE);
+ return fontName;
}
#endif
diff --git a/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.h
index 4228b40..2dee3ab 100644
--- a/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.h
+++ b/Source/WebCore/platform/graphics/skia/FontCustomPlatformData.h
@@ -34,6 +34,7 @@
#include "FontOrientation.h"
#include "FontRenderingMode.h"
+#include "FontWidthVariant.h"
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
@@ -65,7 +66,7 @@ public:
~FontCustomPlatformData();
- FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal,
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth,
FontRenderingMode = NormalRenderingMode);
static bool supportsFormat(const String&);
diff --git a/Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp b/Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
index c4b753b..5950c35 100644
--- a/Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
@@ -26,7 +26,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
#include "GraphicsContext3D.h"
@@ -87,4 +87,4 @@ bool GraphicsContext3D::getImageData(Image* image,
} // namespace WebCore
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
index 1a7112b..9f2ed32 100644
--- a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
@@ -309,20 +309,6 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
platformContext()->clipPathAntiAliased(path);
}
-void GraphicsContext::addPath(const Path& path)
-{
- if (paintingDisabled())
- return;
- platformContext()->addPath(*path.platformPath());
-}
-
-void GraphicsContext::beginPath()
-{
- if (paintingDisabled())
- return;
- platformContext()->beginPath();
-}
-
void GraphicsContext::clearPlatformShadow()
{
if (paintingDisabled())
@@ -431,11 +417,7 @@ void GraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule)
if (platformContext()->useGPU())
platformContext()->gpuCanvas()->clipPath(pathToClip);
- // FIXME: Be smarter about this.
- beginPath();
- addPath(pathToClip);
-
- SkPath path = platformContext()->currentPathInLocalCoordinates();
+ SkPath path = *pathToClip.platformPath();
if (!isPathSkiaSafe(getCTM(), path))
return;
@@ -738,17 +720,13 @@ void GraphicsContext::fillPath(const Path& pathToFill)
if (paintingDisabled())
return;
- // FIXME: Be smarter about this.
- beginPath();
- addPath(pathToFill);
-
if (platformContext()->useGPU() && platformContext()->canAccelerate()) {
platformContext()->prepareForHardwareDraw();
platformContext()->gpuCanvas()->fillPath(pathToFill);
return;
}
- SkPath path = platformContext()->currentPathInLocalCoordinates();
+ SkPath path = *pathToFill.platformPath();
if (!isPathSkiaSafe(getCTM(), path))
return;
@@ -1204,11 +1182,7 @@ void GraphicsContext::strokePath(const Path& pathToStroke)
if (paintingDisabled())
return;
- // FIXME: Be smarter about this.
- beginPath();
- addPath(pathToStroke);
-
- SkPath path = platformContext()->currentPathInLocalCoordinates();
+ SkPath path = *pathToStroke.platformPath();
if (!isPathSkiaSafe(getCTM(), path))
return;
diff --git a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
index 2c489ef..2721523 100644
--- a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
@@ -2,11 +2,11 @@
* Copyright (c) 2008, Google Inc. All rights reserved.
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. 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
@@ -16,7 +16,7 @@
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -162,12 +162,14 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
}
template <Multiply multiplied>
-PassRefPtr<ByteArray> getImageData(const IntRect& rect, const SkBitmap& bitmap,
+PassRefPtr<ByteArray> getImageData(const IntRect& rect, SkDevice& srcDevice,
const IntSize& size)
{
RefPtr<ByteArray> result = ByteArray::create(rect.width() * rect.height() * 4);
- if (bitmap.config() == SkBitmap::kNo_Config) {
+ SkBitmap::Config srcConfig = srcDevice.accessBitmap(false).config();
+
+ if (srcConfig == SkBitmap::kNo_Config) {
// This is an empty SkBitmap that could not be configured.
ASSERT(!size.width() || !size.height());
return result.release();
@@ -177,8 +179,8 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const SkBitmap& bitmap,
if (rect.x() < 0
|| rect.y() < 0
- || rect.right() > size.width()
- || rect.bottom() > size.height())
+ || rect.maxX() > size.width()
+ || rect.maxY() > size.height())
memset(data, 0, result->length());
int originX = rect.x();
@@ -187,12 +189,12 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const SkBitmap& bitmap,
destX = -originX;
originX = 0;
}
- int endX = rect.right();
+ int endX = rect.maxX();
if (endX > size.width())
endX = size.width();
int numColumns = endX - originX;
- if (numColumns <= 0)
+ if (numColumns <= 0)
return result.release();
int originY = rect.y();
@@ -201,38 +203,42 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const SkBitmap& bitmap,
destY = -originY;
originY = 0;
}
- int endY = rect.bottom();
+ int endY = rect.maxY();
if (endY > size.height())
endY = size.height();
int numRows = endY - originY;
- if (numRows <= 0)
+ if (numRows <= 0)
return result.release();
- ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
- SkAutoLockPixels bitmapLock(bitmap);
+ ASSERT(srcConfig == SkBitmap::kARGB_8888_Config);
unsigned destBytesPerRow = 4 * rect.width();
+
+ SkBitmap srcBitmap;
+ srcDevice.readPixels(SkIRect::MakeXYWH(originX, originY, numColumns, numRows), &srcBitmap);
+
unsigned char* destRow = data + destY * destBytesPerRow + destX * 4;
+ // Do conversion of byte order and alpha divide (if necessary)
for (int y = 0; y < numRows; ++y) {
- uint32_t* srcRow = bitmap.getAddr32(originX, originY + y);
+ SkPMColor* srcBitmapRow = srcBitmap.getAddr32(0, y);
for (int x = 0; x < numColumns; ++x) {
+ SkPMColor srcPMColor = srcBitmapRow[x];
unsigned char* destPixel = &destRow[x * 4];
if (multiplied == Unmultiplied) {
- SkColor color = srcRow[x];
- unsigned a = SkColorGetA(color);
- destPixel[0] = a ? SkColorGetR(color) * 255 / a : 0;
- destPixel[1] = a ? SkColorGetG(color) * 255 / a : 0;
- destPixel[2] = a ? SkColorGetB(color) * 255 / a : 0;
+ unsigned char a = SkGetPackedA32(srcPMColor);
+ destPixel[0] = a ? SkGetPackedR32(srcPMColor) * 255 / a : 0;
+ destPixel[1] = a ? SkGetPackedG32(srcPMColor) * 255 / a : 0;
+ destPixel[2] = a ? SkGetPackedB32(srcPMColor) * 255 / a : 0;
destPixel[3] = a;
} else {
// Input and output are both pre-multiplied, we just need to re-arrange the
// bytes from the bitmap format to RGBA.
- destPixel[0] = SkGetPackedR32(srcRow[x]);
- destPixel[1] = SkGetPackedG32(srcRow[x]);
- destPixel[2] = SkGetPackedB32(srcRow[x]);
- destPixel[3] = SkGetPackedA32(srcRow[x]);
+ destPixel[0] = SkGetPackedR32(srcPMColor);
+ destPixel[1] = SkGetPackedG32(srcPMColor);
+ destPixel[2] = SkGetPackedB32(srcPMColor);
+ destPixel[3] = SkGetPackedA32(srcPMColor);
}
}
destRow += destBytesPerRow;
@@ -244,18 +250,18 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const SkBitmap& bitmap,
PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
{
context()->platformContext()->syncSoftwareCanvas();
- return getImageData<Unmultiplied>(rect, *context()->platformContext()->bitmap(), m_size);
+ return getImageData<Unmultiplied>(rect, *context()->platformContext()->canvas()->getDevice(), m_size);
}
PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
{
context()->platformContext()->syncSoftwareCanvas();
- return getImageData<Premultiplied>(rect, *context()->platformContext()->bitmap(), m_size);
+ return getImageData<Premultiplied>(rect, *context()->platformContext()->canvas()->getDevice(), m_size);
}
template <Multiply multiplied>
-void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint,
- const SkBitmap& bitmap, const IntSize& size)
+void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint,
+ SkDevice* dstDevice, const IntSize& size)
{
ASSERT(sourceRect.width() > 0);
ASSERT(sourceRect.height() > 0);
@@ -265,9 +271,9 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
ASSERT(destX >= 0);
ASSERT(destX < size.width());
ASSERT(originX >= 0);
- ASSERT(originX < sourceRect.right());
+ ASSERT(originX < sourceRect.maxX());
- int endX = destPoint.x() + sourceRect.right();
+ int endX = destPoint.x() + sourceRect.maxX();
ASSERT(endX <= size.width());
int numColumns = endX - destX;
@@ -277,21 +283,33 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
ASSERT(destY >= 0);
ASSERT(destY < size.height());
ASSERT(originY >= 0);
- ASSERT(originY < sourceRect.bottom());
+ ASSERT(originY < sourceRect.maxY());
- int endY = destPoint.y() + sourceRect.bottom();
+ int endY = destPoint.y() + sourceRect.maxY();
ASSERT(endY <= size.height());
int numRows = endY - destY;
- ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
- SkAutoLockPixels bitmapLock(bitmap);
-
unsigned srcBytesPerRow = 4 * sourceSize.width();
- const unsigned char* srcRow = source->data() + originY * srcBytesPerRow + originX * 4;
+ SkBitmap deviceBitmap = dstDevice->accessBitmap(true);
+ SkAutoLockPixels deviceAutoLock(deviceBitmap);
+ // If the device's bitmap doesn't have pixels we will make a temp and call writePixels on the device.
+ bool temporaryBitmap = !deviceBitmap.getPixels();
+ SkBitmap destBitmap;
+
+ if (temporaryBitmap) {
+ destBitmap.setConfig(SkBitmap::kARGB_8888_Config, numColumns, numRows, srcBytesPerRow);
+ if (!destBitmap.allocPixels())
+ CRASH();
+ } else
+ deviceBitmap.extractSubset(&destBitmap, SkIRect::MakeXYWH(destX, destY, numColumns, numRows));
+
+ // Whether we made a temporary or not destBitmap is always configured to be written at 0,0
+ SkAutoLockPixels destAutoLock(destBitmap);
+ const unsigned char* srcRow = source->data() + originY * srcBytesPerRow + originX * 4;
for (int y = 0; y < numRows; ++y) {
- uint32_t* destRow = bitmap.getAddr32(destX, destY + y);
+ SkPMColor* destRow = destBitmap.getAddr32(0, y);
for (int x = 0; x < numColumns; ++x) {
const unsigned char* srcPixel = &srcRow[x * 4];
if (multiplied == Unmultiplied) {
@@ -301,22 +319,26 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
unsigned char b = SkMulDiv255Ceiling(srcPixel[2], alpha);
destRow[x] = SkPackARGB32(alpha, r, g, b);
} else
- destRow[x] = SkPackARGB32(srcPixel[3], srcPixel[0],
- srcPixel[1], srcPixel[2]);
+ destRow[x] = SkPackARGB32(srcPixel[3], srcPixel[0], srcPixel[1], srcPixel[2]);
}
srcRow += srcBytesPerRow;
}
+
+ // If we used a temporary then write it to the device
+ if (temporaryBitmap)
+ dstDevice->writePixels(destBitmap, destX, destY);
}
void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
{
- context()->platformContext()->prepareForSoftwareDraw();
- putImageData<Unmultiplied>(source, sourceSize, sourceRect, destPoint, *context()->platformContext()->bitmap(), m_size);
+ context()->platformContext()->syncSoftwareCanvas();
+ putImageData<Unmultiplied>(source, sourceSize, sourceRect, destPoint, context()->platformContext()->canvas()->getDevice(), m_size);
}
void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
{
- putImageData<Premultiplied>(source, sourceSize, sourceRect, destPoint, *context()->platformContext()->bitmap(), m_size);
+ context()->platformContext()->syncSoftwareCanvas();
+ putImageData<Premultiplied>(source, sourceSize, sourceRect, destPoint, context()->platformContext()->canvas()->getDevice(), m_size);
}
String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
@@ -324,14 +346,27 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
Vector<unsigned char> encodedImage;
+ SkDevice* device = context()->platformContext()->canvas()->getDevice();
+ SkBitmap bitmap = device->accessBitmap(false);
+
+ // if we can't see the pixels directly, call readPixels() to get a copy.
+ // this could happen if the device is backed by a GPU.
+ bitmap.lockPixels(); // balanced by our destructor, or explicitly if getPixels() fails
+ if (!bitmap.getPixels()) {
+ bitmap.unlockPixels();
+ SkIRect bounds = SkIRect::MakeWH(device->width(), device->height());
+ 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(*context()->platformContext()->bitmap(), compressionQuality, &encodedImage))
+ if (!JPEGImageEncoder::encode(bitmap, compressionQuality, &encodedImage))
return "data:,";
} else {
- if (!PNGImageEncoder::encode(*context()->platformContext()->bitmap(), &encodedImage))
+ if (!PNGImageEncoder::encode(bitmap, &encodedImage))
return "data:,";
ASSERT(mimeType == "image/png");
}
diff --git a/Source/WebCore/platform/graphics/skia/IntRectSkia.cpp b/Source/WebCore/platform/graphics/skia/IntRectSkia.cpp
index ea138ee..0024086 100644
--- a/Source/WebCore/platform/graphics/skia/IntRectSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/IntRectSkia.cpp
@@ -37,14 +37,14 @@ namespace WebCore {
IntRect::operator SkIRect() const
{
- SkIRect rect = { x(), y(), right(), bottom() };
+ SkIRect rect = { x(), y(), maxX(), maxY() };
return rect;
}
IntRect::operator SkRect() const
{
SkRect rect;
- rect.set(SkIntToScalar(x()), SkIntToScalar(y()), SkIntToScalar(right()), SkIntToScalar(bottom()));
+ rect.set(SkIntToScalar(x()), SkIntToScalar(y()), SkIntToScalar(maxX()), SkIntToScalar(maxY()));
return rect;
}
diff --git a/Source/WebCore/platform/graphics/skia/PathSkia.cpp b/Source/WebCore/platform/graphics/skia/PathSkia.cpp
index 89323c4..6318c21 100644
--- a/Source/WebCore/platform/graphics/skia/PathSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/PathSkia.cpp
@@ -227,28 +227,20 @@ void Path::transform(const AffineTransform& xform)
m_path->transform(xform);
}
-// Computes the bounding box for the stroke and style currently selected into
-// the given bounding box. This also takes into account the stroke width.
-static FloatRect boundingBoxForCurrentStroke(const GraphicsContext* context)
-{
- SkPaint paint;
- context->platformContext()->setupPaintForStroking(&paint, 0, 0);
- SkPath boundingPath;
- paint.getFillPath(context->platformContext()->currentPathInLocalCoordinates(), &boundingPath);
- return boundingPath.getBounds();
-}
-
FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
{
GraphicsContext* scratch = scratchContext();
scratch->save();
- scratch->beginPath();
- scratch->addPath(*this);
if (applier)
applier->strokeStyle(scratch);
- FloatRect r = boundingBoxForCurrentStroke(scratch);
+ SkPaint paint;
+ scratch->platformContext()->setupPaintForStroking(&paint, 0, 0);
+ SkPath boundingPath;
+ paint.getFillPath(*platformPath(), &boundingPath);
+
+ FloatRect r = boundingPath.getBounds();
scratch->restore();
return r;
}
diff --git a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
index d852e9b..5e08b3c 100644
--- a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
@@ -51,6 +51,12 @@
#include "SkDashPathEffect.h"
#include "SkShader.h"
+#if ENABLE(SKIA_GPU)
+#include "GrContext.h"
+#include "SkGpuDevice.h"
+#include "SkGpuDeviceFactory.h"
+#endif
+
#include <wtf/MathExtras.h>
#include <wtf/OwnArrayPtr.h>
#include <wtf/Vector.h>
@@ -62,6 +68,18 @@
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 -----------------------------------------------------------------------
@@ -266,7 +284,7 @@ void PlatformContextSkia::beginLayerClippedToImage(const FloatRect& rect,
// create the resulting image.
m_state->m_clip = rect;
SkRect bounds = { SkFloatToScalar(rect.x()), SkFloatToScalar(rect.y()),
- SkFloatToScalar(rect.right()), SkFloatToScalar(rect.bottom()) };
+ SkFloatToScalar(rect.maxX()), SkFloatToScalar(rect.maxY()) };
canvas()->clipRect(bounds);
canvas()->saveLayerAlpha(&bounds, 255,
@@ -550,38 +568,12 @@ SkColor PlatformContextSkia::effectiveStrokeColor() const
return m_state->applyAlpha(m_state->m_strokeColor);
}
-void PlatformContextSkia::beginPath()
-{
- m_path.reset();
-}
-
-void PlatformContextSkia::addPath(const SkPath& path)
-{
- m_path.addPath(path, m_canvas->getTotalMatrix());
-}
-
-SkPath PlatformContextSkia::currentPathInLocalCoordinates() const
-{
- SkPath localPath = m_path;
- const SkMatrix& matrix = m_canvas->getTotalMatrix();
- SkMatrix inverseMatrix;
- if (!matrix.invert(&inverseMatrix))
- return SkPath();
- localPath.transform(inverseMatrix);
- return localPath;
-}
-
void PlatformContextSkia::canvasClipPath(const SkPath& path)
{
m_state->m_canvasClipApplied = true;
m_canvas->clipPath(path);
}
-void PlatformContextSkia::setFillRule(SkPath::FillType fr)
-{
- m_path.setFillType(fr);
-}
-
void PlatformContextSkia::setFillShader(SkShader* fillShader)
{
if (fillShader)
@@ -625,7 +617,11 @@ const SkBitmap* PlatformContextSkia::bitmap() const
bool PlatformContextSkia::isPrinting()
{
+#if ENABLE(SKIA_GPU)
+ return true;
+#else
return m_canvas->getTopPlatformDevice().IsVectorial();
+#endif
}
void PlatformContextSkia::getImageResamplingHint(IntSize* srcSize, FloatSize* dstSize) const
@@ -739,6 +735,19 @@ void PlatformContextSkia::setSharedGraphicsContext3D(SharedGraphicsContext3D* co
m_gpuCanvas = new GLES2Canvas(context, drawingBuffer, size);
m_uploadTexture.clear();
drawingBuffer->setWillPublishCallback(WillPublishCallbackImpl::create(this));
+
+#if ENABLE(SKIA_GPU)
+ m_useGPU = false;
+ context->makeContextCurrent();
+ m_gpuCanvas->bindFramebuffer();
+
+ GrContext* gr = GetGlobalGrContext();
+ gr->resetContext();
+ 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();
+ m_canvas->setDeviceFactory(factory);
+#endif
} else {
syncSoftwareCanvas();
m_uploadTexture.clear();
@@ -750,8 +759,13 @@ void PlatformContextSkia::setSharedGraphicsContext3D(SharedGraphicsContext3D* co
void PlatformContextSkia::prepareForSoftwareDraw() const
{
- if (!m_useGPU)
+ if (!m_useGPU) {
+#if ENABLE(SKIA_GPU)
+ if (m_gpuCanvas)
+ m_gpuCanvas->context()->makeContextCurrent();
+#endif
return;
+ }
if (m_backingStoreState == Hardware) {
// Depending on the blend mode we need to do one of a few things:
@@ -804,8 +818,13 @@ void PlatformContextSkia::prepareForHardwareDraw() const
void PlatformContextSkia::syncSoftwareCanvas() const
{
- if (!m_useGPU)
+ if (!m_useGPU) {
+#if ENABLE(SKIA_GPU)
+ if (m_gpuCanvas)
+ m_gpuCanvas->bindFramebuffer();
+#endif
return;
+ }
if (m_backingStoreState == Hardware)
readbackHardwareToSoftware();
@@ -865,7 +884,7 @@ void PlatformContextSkia::readbackHardwareToSoftware() const
const SkBitmap& bitmap = m_canvas->getDevice()->accessBitmap(true);
SkAutoLockPixels lock(bitmap);
int width = bitmap.width(), height = bitmap.height();
- OwnArrayPtr<uint32_t> buf(new uint32_t[width]);
+ OwnArrayPtr<uint32_t> buf = adoptArrayPtr(new uint32_t[width]);
SharedGraphicsContext3D* context = m_gpuCanvas->context();
m_gpuCanvas->bindFramebuffer();
// Flips the image vertically.
diff --git a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h
index 0304486..d7dd6a9 100644
--- a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h
+++ b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h
@@ -118,7 +118,6 @@ public:
void setAlpha(float);
void setLineCap(SkPaint::Cap);
void setLineJoin(SkPaint::Join);
- void setFillRule(SkPath::FillType);
void setXfermodeMode(SkXfermode::Mode);
void setFillColor(SkColor);
void setFillShader(SkShader*);
@@ -137,10 +136,6 @@ public:
float getAlpha() const;
int getNormalizedAlpha() const;
- void beginPath();
- void addPath(const SkPath&);
- SkPath currentPathInLocalCoordinates() const;
-
void canvasClipPath(const SkPath&);
// Returns the fill color. The returned color has it's alpha adjusted
@@ -220,9 +215,6 @@ private:
// mStateStack.back().
State* m_state;
- // Current path in global coordinates.
- SkPath m_path;
-
// Stores image sizes for a hint to compute image resampling modes.
// Values are used in ImageSkia.cpp
IntSize m_imageResamplingHintSrcSize;
diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
index 85fa3ee..47a27c6 100644
--- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
+++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
@@ -26,7 +26,7 @@
#include "Image.h"
#include "TextureMapperNode.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
#include "GraphicsContext3D.h"
#endif
@@ -73,7 +73,7 @@ public:
virtual void setContentsToImage(Image*);
virtual void setContentsToMedia(PlatformLayer*);
virtual void setContentsBackgroundColor(const Color&);
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
virtual void setContentsToGraphicsContext3D(const GraphicsContext3D*);
virtual void setGraphicsContext3DNeedsDisplay();
#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp
index 09051f9..bf53e61 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp
@@ -318,7 +318,7 @@ void TextureMapperNode::computeLocalTransform()
m_transforms.local =
TransformationMatrix()
.translate3d(originX + m_state.pos.x(), originY + m_state.pos.y(), m_state.anchorPoint.z())
- .multLeft(m_state.transform)
+ .multiply(m_state.transform)
.translate3d(-originX, -originY, -m_state.anchorPoint.z());
m_transforms.localDirty = false;
}
@@ -352,7 +352,7 @@ void TextureMapperNode::computeReplicaTransform()
m_nearestSurfaceSize = nearestSurfaceSize();
if (m_layerType != TransparencyLayer) {
- m_transforms.replica = TransformationMatrix(m_transforms.target).multLeft(m_state.replicaLayer->m_transforms.local);
+ m_transforms.replica = TransformationMatrix(m_transforms.target).multiply(m_state.replicaLayer->m_transforms.local);
return;
}
@@ -361,7 +361,7 @@ void TextureMapperNode::computeReplicaTransform()
m_transforms.replica =
TransformationMatrix()
.translate(originX, originY)
- .multLeft(m_state.replicaLayer->m_transforms.local)
+ .multiply(m_state.replicaLayer->m_transforms.local)
.translate(-originX, -originY);
}
@@ -377,7 +377,7 @@ void TextureMapperNode::computeTransformations()
TextureMapperNode* parent = m_parent;
computeLocalTransform();
- m_transforms.target = TransformationMatrix(parent ? parent->m_transforms.forDescendants : TransformationMatrix()).multLeft(m_transforms.local);
+ m_transforms.target = TransformationMatrix(parent ? parent->m_transforms.forDescendants : TransformationMatrix()).multiply(m_transforms.local);
m_transforms.forDescendants = (m_layerType == ClipLayer ? TransformationMatrix() : m_transforms.target);
if (m_effectTarget)
@@ -408,10 +408,10 @@ void TextureMapperNode::computeTransformations()
if (m_transforms.perspectiveDirty)
m_transforms.perspective = TransformationMatrix()
.translate(centerPoint.x(), centerPoint.y())
- .multLeft(m_state.childrenTransform)
+ .multiply(m_state.childrenTransform)
.translate(-centerPoint.x(), -centerPoint.y());
m_transforms.perspectiveDirty = false;
- m_transforms.forDescendants.multLeft(m_transforms.perspective);
+ m_transforms.forDescendants.multiply(m_transforms.perspective);
}
void TextureMapperNode::uploadTextureFromContent(TextureMapper* textureMapper, const IntRect& visibleRect, GraphicsLayer* layer)
diff --git a/Source/WebCore/platform/graphics/transforms/AffineTransform.cpp b/Source/WebCore/platform/graphics/transforms/AffineTransform.cpp
index 3f88140..a1ffa30 100644
--- a/Source/WebCore/platform/graphics/transforms/AffineTransform.cpp
+++ b/Source/WebCore/platform/graphics/transforms/AffineTransform.cpp
@@ -222,14 +222,6 @@ AffineTransform& AffineTransform::translate(double tx, double ty)
return *this;
}
-// *this = translation * *this
-AffineTransform& AffineTransform::translateRight(double tx, double ty)
-{
- m_transform[4] += tx;
- m_transform[5] += ty;
- return *this;
-}
-
AffineTransform& AffineTransform::scaleNonUniform(double sx, double sy)
{
return scale(sx, sy);
@@ -324,9 +316,9 @@ FloatRect AffineTransform::mapRect(const FloatRect& rect) const
FloatQuad result;
result.setP1(mapPoint(rect.location()));
- result.setP2(mapPoint(FloatPoint(rect.right(), rect.y())));
- result.setP3(mapPoint(FloatPoint(rect.right(), rect.bottom())));
- result.setP4(mapPoint(FloatPoint(rect.x(), rect.bottom())));
+ result.setP2(mapPoint(FloatPoint(rect.maxX(), rect.y())));
+ result.setP3(mapPoint(FloatPoint(rect.maxX(), rect.maxY())));
+ result.setP4(mapPoint(FloatPoint(rect.x(), rect.maxY())));
return result.boundingBox();
}
diff --git a/Source/WebCore/platform/graphics/transforms/AffineTransform.h b/Source/WebCore/platform/graphics/transforms/AffineTransform.h
index 50d0655..3e3995f 100644
--- a/Source/WebCore/platform/graphics/transforms/AffineTransform.h
+++ b/Source/WebCore/platform/graphics/transforms/AffineTransform.h
@@ -103,7 +103,6 @@ public:
AffineTransform& rotate(double d);
AffineTransform& rotateFromVector(double x, double y);
AffineTransform& translate(double tx, double ty);
- AffineTransform& translateRight(double tx, double ty);
AffineTransform& shear(double sx, double sy);
AffineTransform& flipX();
AffineTransform& flipY();
@@ -172,6 +171,11 @@ public:
operator wxGraphicsMatrix() const;
#endif
+ static AffineTransform translation(double x, double y)
+ {
+ return AffineTransform(1, 0, 0, 1, x, y);
+ }
+
private:
void setMatrix(const Transform m)
{
diff --git a/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h b/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h
index 0a0aaf0..dd5dae2 100644
--- a/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h
+++ b/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h
@@ -55,7 +55,7 @@ private:
virtual bool apply(TransformationMatrix& transform, const IntSize&) const
{
- transform.multLeft(TransformationMatrix(m_matrix));
+ transform.multiply(TransformationMatrix(m_matrix));
return false;
}
diff --git a/Source/WebCore/platform/graphics/transforms/MatrixTransformOperation.h b/Source/WebCore/platform/graphics/transforms/MatrixTransformOperation.h
index fd9b27e..6f4e725 100644
--- a/Source/WebCore/platform/graphics/transforms/MatrixTransformOperation.h
+++ b/Source/WebCore/platform/graphics/transforms/MatrixTransformOperation.h
@@ -62,7 +62,7 @@ private:
virtual bool apply(TransformationMatrix& transform, const IntSize&) const
{
TransformationMatrix matrix(m_a, m_b, m_c, m_d, m_e, m_f);
- transform.multLeft(TransformationMatrix(matrix));
+ transform.multiply(matrix);
return false;
}
diff --git a/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.cpp b/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.cpp
index 9fd03a1..18bfe37 100644
--- a/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.cpp
+++ b/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "PerspectiveTransformOperation.h"
-#include <algorithm>
+#include <wtf/MathExtras.h>
using namespace std;
@@ -37,22 +37,29 @@ PassRefPtr<TransformOperation> PerspectiveTransformOperation::blend(const Transf
if (from && !from->isSameType(*this))
return this;
- if (blendToIdentity)
- return PerspectiveTransformOperation::create(m_p + (1. - m_p) * progress);
+ if (blendToIdentity) {
+ double p = m_p.calcFloatValue(1);
+ p = p + (1. - p) * progress; // FIXME: this seems wrong. https://bugs.webkit.org/show_bug.cgi?id=52700
+ return PerspectiveTransformOperation::create(Length(clampToPositiveInteger(p), Fixed));
+ }
const PerspectiveTransformOperation* fromOp = static_cast<const PerspectiveTransformOperation*>(from);
- double fromP = fromOp ? fromOp->m_p : 0;
- double toP = m_p;
+ Length fromP = fromOp ? fromOp->m_p : Length(m_p.type());
+ Length toP = m_p;
TransformationMatrix fromT;
TransformationMatrix toT;
- fromT.applyPerspective(fromP);
- toT.applyPerspective(toP);
+ fromT.applyPerspective(fromP.calcFloatValue(1));
+ toT.applyPerspective(toP.calcFloatValue(1));
toT.blend(fromT, progress);
TransformationMatrix::DecomposedType decomp;
toT.decompose(decomp);
-
- return PerspectiveTransformOperation::create(decomp.perspectiveZ ? -1.0 / decomp.perspectiveZ : 0.0);
+
+ if (decomp.perspectiveZ) {
+ double val = -1.0 / decomp.perspectiveZ;
+ return PerspectiveTransformOperation::create(Length(clampToPositiveInteger(val), Fixed));
+ }
+ return PerspectiveTransformOperation::create(Length(0, Fixed));
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h b/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h
index 834cc83..886d3dc 100644
--- a/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h
+++ b/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h
@@ -26,21 +26,22 @@
#ifndef PerspectiveTransformOperation_h
#define PerspectiveTransformOperation_h
+#include "Length.h"
#include "TransformOperation.h"
namespace WebCore {
class PerspectiveTransformOperation : public TransformOperation {
public:
- static PassRefPtr<PerspectiveTransformOperation> create(double p)
+ static PassRefPtr<PerspectiveTransformOperation> create(const Length& p)
{
return adoptRef(new PerspectiveTransformOperation(p));
}
- double perspective() const { return m_p; }
+ Length perspective() const { return m_p; }
private:
- virtual bool isIdentity() const { return m_p == 0; }
+ virtual bool isIdentity() const { return m_p.calcFloatValue(1) == 0; }
virtual OperationType getOperationType() const { return PERSPECTIVE; }
virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == PERSPECTIVE; }
@@ -54,18 +55,19 @@ private:
virtual bool apply(TransformationMatrix& transform, const IntSize&) const
{
- transform.applyPerspective(m_p);
+ transform.applyPerspective(m_p.calcFloatValue(1));
return false;
}
virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false);
- PerspectiveTransformOperation(double p)
+ PerspectiveTransformOperation(const Length& p)
: m_p(p)
{
+ ASSERT(p.isFixed());
}
- double m_p;
+ Length m_p;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp b/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp
index 357a140..c7283a5 100644
--- a/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp
+++ b/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp
@@ -55,21 +55,17 @@ namespace WebCore {
// webmasters - are to be held responsible. Basically, don't be a jerk, and remember that anything free comes
// with no guarantee.
-// A Note About row-major vs. column major matrixes
+// A clarification about the storage of matrix elements
//
-// The clients of this class (CSSMatrix and SVGMatrix) assume a column-major ordering.
-// That means that when the matrix is initialized with 16 values, the first 4 values
-// go in the 4 rows of the first column, etc. And in the dereferencing calls, the first
-// digit is the column (e.g., m23() is column 2 row 3). Because C++ uses row-major arrays
-// the internal matrix is stored in row-major order, so m[2][0] means row 2, column 0. This
-// has no bearing on how the matrix is viewed on the outside, since all access is done
-// with function calls. But it does help make the code more clear if you know that.
+// This class uses a 2 dimensional array internally to store the elements of the matrix. The first index into
+// the array refers to the column that the element lies in; the second index refers to the row.
//
-// FIXME: Multiply calls are named for what they do in the internal, row-major world.
-// multLeft is actually a multRight in a column-major world, and multiply is a multLeft
-// in a column-major world. For now I've left it that way to avoid too many confusing
-// changes to the code. In particular AffineTransform uses these same terms for the
-// opposite operations. So we have to be VERY careful when we change them.
+// In other words, this is the layout of the matrix:
+//
+// | m_matrix[0][0] m_matrix[1][0] m_matrix[2][0] m_matrix[3][0] |
+// | m_matrix[0][1] m_matrix[1][1] m_matrix[2][1] m_matrix[3][1] |
+// | m_matrix[0][2] m_matrix[1][2] m_matrix[2][2] m_matrix[3][2] |
+// | m_matrix[0][3] m_matrix[1][3] m_matrix[2][3] m_matrix[3][3] |
typedef double Vector4[4];
typedef double Vector3[3];
@@ -634,7 +630,7 @@ TransformationMatrix& TransformationMatrix::scaleNonUniform(double sx, double sy
mat.m_matrix[0][0] = sx;
mat.m_matrix[1][1] = sy;
- multLeft(mat);
+ multiply(mat);
return *this;
}
@@ -645,7 +641,7 @@ TransformationMatrix& TransformationMatrix::scale3d(double sx, double sy, double
mat.m_matrix[1][1] = sy;
mat.m_matrix[2][2] = sz;
- multLeft(mat);
+ multiply(mat);
return *this;
}
@@ -732,7 +728,7 @@ TransformationMatrix& TransformationMatrix::rotate3d(double x, double y, double
mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f;
mat.m_matrix[3][3] = 1.0f;
}
- multLeft(mat);
+ multiply(mat);
return *this;
}
@@ -783,7 +779,7 @@ TransformationMatrix& TransformationMatrix::rotate3d(double rx, double ry, doubl
mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f;
mat.m_matrix[3][3] = 1.0f;
- rmat.multLeft(mat);
+ rmat.multiply(mat);
rx /= 2.0f;
sinA = sin(rx);
@@ -803,9 +799,9 @@ TransformationMatrix& TransformationMatrix::rotate3d(double rx, double ry, doubl
mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f;
mat.m_matrix[3][3] = 1.0f;
- rmat.multLeft(mat);
+ rmat.multiply(mat);
- multLeft(rmat);
+ multiply(rmat);
return *this;
}
@@ -869,7 +865,7 @@ TransformationMatrix& TransformationMatrix::skew(double sx, double sy)
mat.m_matrix[0][1] = tan(sy); // note that the y shear goes in the first row
mat.m_matrix[1][0] = tan(sx); // and the x shear in the second row
- multLeft(mat);
+ multiply(mat);
return *this;
}
@@ -879,7 +875,7 @@ TransformationMatrix& TransformationMatrix::applyPerspective(double p)
if (p != 0)
mat.m_matrix[2][3] = -1/p;
- multLeft(mat);
+ multiply(mat);
return *this;
}
@@ -896,7 +892,7 @@ TransformationMatrix TransformationMatrix::rectToRect(const FloatRect& from, con
//
// *this = mat * *this
//
-TransformationMatrix& TransformationMatrix::multLeft(const TransformationMatrix& mat)
+TransformationMatrix& TransformationMatrix::multiply(const TransformationMatrix& mat)
{
Matrix4 tmp;
@@ -1105,25 +1101,25 @@ void TransformationMatrix::recompose(const DecomposedType& decomp)
2 * (xz - yw), 2 * (yz + xw), 1 - 2 * (xx + yy), 0,
0, 0, 0, 1);
- multLeft(rotationMatrix);
+ multiply(rotationMatrix);
// now apply skew
if (decomp.skewYZ) {
TransformationMatrix tmp;
tmp.setM32((float) decomp.skewYZ);
- multLeft(tmp);
+ multiply(tmp);
}
if (decomp.skewXZ) {
TransformationMatrix tmp;
tmp.setM31((float) decomp.skewXZ);
- multLeft(tmp);
+ multiply(tmp);
}
if (decomp.skewXY) {
TransformationMatrix tmp;
tmp.setM21((float) decomp.skewXY);
- multLeft(tmp);
+ multiply(tmp);
}
// finally, apply scale
diff --git a/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h b/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h
index c883675..fa27c0e 100644
--- a/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h
+++ b/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h
@@ -208,11 +208,8 @@ public:
void setF(double f) { m_matrix[3][1] = f; }
// this = this * mat
- TransformationMatrix& multiply(const TransformationMatrix& t) { return *this *= t; }
+ TransformationMatrix& multiply(const TransformationMatrix&);
- // this = mat * this
- TransformationMatrix& multLeft(const TransformationMatrix& mat);
-
TransformationMatrix& scale(double);
TransformationMatrix& scaleNonUniform(double sx, double sy);
TransformationMatrix& scale3d(double sx, double sy, double sz);
@@ -296,19 +293,18 @@ public:
}
bool operator!=(const TransformationMatrix& other) const { return !(*this == other); }
-
- // *this = *this * t (i.e., a multRight)
+
+ // *this = *this * t
TransformationMatrix& operator*=(const TransformationMatrix& t)
{
- *this = *this * t;
- return *this;
+ return multiply(t);
}
- // result = *this * t (i.e., a multRight)
+ // result = *this * t
TransformationMatrix operator*(const TransformationMatrix& t) const
{
- TransformationMatrix result = t;
- result.multLeft(*this);
+ TransformationMatrix result = *this;
+ result.multiply(t);
return result;
}
diff --git a/Source/WebCore/platform/graphics/win/FontCGWin.cpp b/Source/WebCore/platform/graphics/win/FontCGWin.cpp
index 8012722..fe26c43 100644
--- a/Source/WebCore/platform/graphics/win/FontCGWin.cpp
+++ b/Source/WebCore/platform/graphics/win/FontCGWin.cpp
@@ -167,8 +167,12 @@ static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData
drawIntoBitmap = true;
// We put slop into this rect, since glyphs can overflow the ascent/descent bounds and the left/right edges.
// FIXME: Can get glyphs' optical bounds (even from CG) to get this right.
- int lineGap = font->lineGap();
- textRect = IntRect(point.x() - (font->ascent() + font->descent()) / 2, point.y() - font->ascent() - lineGap, totalWidth + font->ascent() + font->descent(), font->lineSpacing());
+ const FontMetrics& fontMetrics = font->fontMetrics();
+ int lineGap = fontMetrics.lineGap();
+ textRect = IntRect(point.x() - (fontMetrics.ascent() + fontMetrics.descent()) / 2,
+ point.y() - fontMetrics.ascent() - lineGap,
+ totalWidth + fontMetrics.ascent() + fontMetrics.descent(),
+ fontMetrics.lineSpacing());
bitmap.set(graphicsContext->createWindowsBitmap(textRect.size()));
memset(bitmap->buffer(), 255, bitmap->bufferLength());
hdc = bitmap->hdc();
@@ -288,7 +292,7 @@ static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData
buffer[i + 2] = fillColor.red();
buffer[i + 3] = alpha;
}
- graphicsContext->drawWindowsBitmap(bitmap.get(), textRect.topLeft());
+ graphicsContext->drawWindowsBitmap(bitmap.get(), textRect.location());
} else
graphicsContext->releaseWindowsContext(hdc, textRect, true, false);
}
diff --git a/Source/WebCore/platform/graphics/win/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
index 9cae99b..4aee6cd 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, FontRenderingMode renderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode renderingMode)
{
ASSERT(m_fontReference);
ASSERT(T2embedLibrary());
@@ -154,13 +154,12 @@ static unsigned long WINAPIV readEmbedProc(void* stream, void* buffer, unsigned
// not allow access from CSS.
static String createUniqueFontName()
{
- Vector<char> fontUuid(sizeof(GUID));
- CoCreateGuid(reinterpret_cast<GUID*>(fontUuid.data()));
+ GUID fontUuid;
+ CoCreateGuid(&fontUuid);
- Vector<char> fontNameVector;
- base64Encode(fontUuid, fontNameVector);
- ASSERT(fontNameVector.size() < LF_FACESIZE);
- return String(fontNameVector.data(), fontNameVector.size());
+ String fontName = base64Encode(reinterpret_cast<char*>(&fontUuid), sizeof(fontUuid));
+ ASSERT(fontName.length() < LF_FACESIZE);
+ return fontName;
}
FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
diff --git a/Source/WebCore/platform/graphics/win/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/win/FontCustomPlatformData.h
index de33c63..abdb356 100644
--- a/Source/WebCore/platform/graphics/win/FontCustomPlatformData.h
+++ b/Source/WebCore/platform/graphics/win/FontCustomPlatformData.h
@@ -23,6 +23,7 @@
#include "FontOrientation.h"
#include "FontRenderingMode.h"
+#include "FontWidthVariant.h"
#include "PlatformString.h"
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
@@ -45,7 +46,7 @@ public:
~FontCustomPlatformData();
- FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontRenderingMode = NormalRenderingMode);
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, 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 c3decbf..fd30a6d 100644
--- a/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp
+++ b/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp
@@ -32,7 +32,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
cairo_font_face_destroy(m_fontFace);
}
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, 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 9c67037..ea3ae38 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);
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth);
static bool supportsFormat(const String&);
diff --git a/Source/WebCore/platform/graphics/win/FontWin.cpp b/Source/WebCore/platform/graphics/win/FontWin.cpp
index 2ed9eb3..47c44bc 100644
--- a/Source/WebCore/platform/graphics/win/FontWin.cpp
+++ b/Source/WebCore/platform/graphics/win/FontWin.cpp
@@ -45,6 +45,11 @@ bool Font::canReturnFallbackFontsForComplexText()
return true;
}
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+ return false;
+}
+
FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h,
int from, int to) const
{
@@ -122,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()) - ascent());
- glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - descent());
+ glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - fontMetrics().ascent());
+ glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - 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/GraphicsContextWin.cpp b/Source/WebCore/platform/graphics/win/GraphicsContextWin.cpp
index f1953e4..bb22024 100644
--- a/Source/WebCore/platform/graphics/win/GraphicsContextWin.cpp
+++ b/Source/WebCore/platform/graphics/win/GraphicsContextWin.cpp
@@ -154,7 +154,7 @@ void GraphicsContextPlatformPrivate::clip(const FloatRect& clipRect)
{
if (!m_hdc)
return;
- IntersectClipRect(m_hdc, clipRect.x(), clipRect.y(), clipRect.right(), clipRect.bottom());
+ IntersectClipRect(m_hdc, clipRect.x(), clipRect.y(), clipRect.maxX(), clipRect.maxY());
}
void GraphicsContextPlatformPrivate::clip(const Path&)
diff --git a/Source/WebCore/platform/graphics/win/IconWin.cpp b/Source/WebCore/platform/graphics/win/IconWin.cpp
index 4d4d219..7e03362 100644
--- a/Source/WebCore/platform/graphics/win/IconWin.cpp
+++ b/Source/WebCore/platform/graphics/win/IconWin.cpp
@@ -25,7 +25,6 @@
#include "GraphicsContext.h"
#include "LocalWindowsContext.h"
#include "PlatformString.h"
-#include <tchar.h>
#include <windows.h>
#if OS(WINCE)
@@ -68,16 +67,16 @@ PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
#if OS(WINCE)
return 0;
#else
- TCHAR buffer[MAX_PATH];
- UINT length = ::GetSystemDirectory(buffer, WTF_ARRAY_LENGTH(buffer));
+ WCHAR buffer[MAX_PATH];
+ UINT length = ::GetSystemDirectoryW(buffer, WTF_ARRAY_LENGTH(buffer));
if (!length)
return 0;
-
- if (_tcscat_s(buffer, TEXT("\\shell32.dll")))
+
+ if (wcscat_s(buffer, L"\\shell32.dll"))
return 0;
HICON hIcon;
- if (!::ExtractIconEx(buffer, shell32MultipleFileIconIndex, 0, &hIcon, 1))
+ if (!::ExtractIconExW(buffer, shell32MultipleFileIconIndex, 0, &hIcon, 1))
return 0;
return adoptRef(new Icon(hIcon));
#endif
diff --git a/Source/WebCore/platform/graphics/win/IntRectWin.cpp b/Source/WebCore/platform/graphics/win/IntRectWin.cpp
index fe25a7f..6af6735 100644
--- a/Source/WebCore/platform/graphics/win/IntRectWin.cpp
+++ b/Source/WebCore/platform/graphics/win/IntRectWin.cpp
@@ -38,7 +38,7 @@ IntRect::IntRect(const RECT& r)
IntRect::operator RECT() const
{
- RECT rect = { x(), y(), right(), bottom() };
+ RECT rect = { x(), y(), maxX(), maxY() };
return rect;
}
diff --git a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp
index 01db7f2..dd3cd32 100644
--- a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp
+++ b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp
@@ -34,6 +34,11 @@
#include <CoreGraphics/CGColor.h>
#endif
+#if USE(ACCELERATED_COMPOSITING)
+#include "CACFLayerTreeHost.h"
+#include "PlatformCALayer.h"
+#endif
+
namespace WebCore {
MediaPlayerPrivateFullscreenWindow::MediaPlayerPrivateFullscreenWindow(MediaPlayerPrivateFullscreenClient* client)
@@ -47,8 +52,11 @@ MediaPlayerPrivateFullscreenWindow::MediaPlayerPrivateFullscreenWindow(MediaPlay
MediaPlayerPrivateFullscreenWindow::~MediaPlayerPrivateFullscreenWindow()
{
- if (m_hwnd)
- close();
+ if (!m_hwnd)
+ return;
+
+ ::DestroyWindow(m_hwnd);
+ ASSERT(!m_hwnd);
}
void MediaPlayerPrivateFullscreenWindow::createWindow(HWND parentHwnd)
@@ -65,8 +73,7 @@ void MediaPlayerPrivateFullscreenWindow::createWindow(HWND parentHwnd)
windowAtom = ::RegisterClassEx(&wcex);
}
- if (m_hwnd)
- close();
+ ASSERT(!m_hwnd);
MONITORINFO mi = {0};
mi.cbSize = sizeof(MONITORINFO);
@@ -87,12 +94,6 @@ void MediaPlayerPrivateFullscreenWindow::createWindow(HWND parentHwnd)
::SetFocus(m_hwnd);
}
-void MediaPlayerPrivateFullscreenWindow::close()
-{
- ::DestroyWindow(m_hwnd);
- ASSERT(!m_hwnd);
-}
-
#if USE(ACCELERATED_COMPOSITING)
void MediaPlayerPrivateFullscreenWindow::setRootChildLayer(PassRefPtr<PlatformCALayer> rootChild)
{
diff --git a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.h b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.h
index c1ae762..e07bbac 100644
--- a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.h
+++ b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.h
@@ -26,9 +26,10 @@
#ifndef MediaPlayerPrivateFullscreenWindow_h
#define MediaPlayerPrivateFullscreenWindow_h
+#include <wtf/RefPtr.h>
+
#if USE(ACCELERATED_COMPOSITING)
-#include "CACFLayerTreeHost.h"
-#include "PlatformCALayer.h"
+#include "CACFLayerTreeHostClient.h"
#endif
typedef unsigned WPARAM;
@@ -40,6 +41,11 @@ typedef unsigned int UINT;
namespace WebCore {
+#if USE(ACCELERATED_COMPOSITING)
+class CACFLayerTreeHost;
+class PlatformCALayer;
+#endif
+
class MediaPlayerPrivateFullscreenClient {
public:
virtual LRESULT fullscreenClientWndProc(HWND, UINT message, WPARAM, LPARAM) = 0;
@@ -53,13 +59,10 @@ public:
~MediaPlayerPrivateFullscreenWindow();
void createWindow(HWND ownerWindow);
- void close();
HWND hwnd() const { return m_hwnd; }
#if USE(ACCELERATED_COMPOSITING)
- CACFLayerTreeHost* layerView() const { return m_layerTreeHost.get(); }
-
PlatformCALayer* rootChildLayer() const { return m_rootChild.get(); }
void setRootChildLayer(PassRefPtr<PlatformCALayer>);
#endif
diff --git a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
index 0b91455..d47de2b 100644
--- a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
+++ b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
@@ -1059,7 +1059,7 @@ float MediaPlayerPrivateQuickTimeVisualContext::mediaTimeForTimeValue(float time
if (m_readyState < MediaPlayer::HaveMetadata || !(timeScale = m_movie->timeScale()))
return timeValue;
- long mediaTimeValue = static_cast<long>(timeValue * timeScale);
+ long mediaTimeValue = lroundf(timeValue * timeScale);
return static_cast<float>(mediaTimeValue) / timeScale;
}
diff --git a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
index 431d624..07b7621 100644
--- a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
+++ b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
@@ -622,7 +622,7 @@ void MediaPlayerPrivate::paint(GraphicsContext* p, const IntRect& r)
m_qtGWorld->paint(hdc, r.x(), r.y());
if (usingTempBitmap)
- p->drawWindowsBitmap(bitmap.get(), r.topLeft());
+ p->drawWindowsBitmap(bitmap.get(), r.location());
else
p->releaseWindowsContext(hdc, r);
diff --git a/Source/WebCore/platform/graphics/win/QTMovie.cpp b/Source/WebCore/platform/graphics/win/QTMovie.cpp
index dfa1d36..4cd8161 100644
--- a/Source/WebCore/platform/graphics/win/QTMovie.cpp
+++ b/Source/WebCore/platform/graphics/win/QTMovie.cpp
@@ -33,7 +33,9 @@
#include <Movies.h>
#include <QTML.h>
#include <QuickTimeComponents.h>
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
#include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
#include <wtf/Noncopyable.h>
#include <wtf/Vector.h>
@@ -46,7 +48,6 @@ static const long subTitleTrackType = 'sbtl';
static const long mpeg4ObjectDescriptionTrackType = 'odsm';
static const long mpeg4SceneDescriptionTrackType = 'sdsm';
static const long closedCaptionDisplayPropertyID = 'disp';
-static LPCTSTR fullscreenQTMoviePointerProp = TEXT("fullscreenQTMoviePointer");
// Resizing GWorlds is slow, give them a minimum size so size of small
// videos can be animated smoothly
@@ -60,7 +61,7 @@ union UppParam {
void* ptr;
};
-static Vector<CFStringRef>* gSupportedTypes = 0;
+static CFMutableArrayRef gSupportedTypes = 0;
static SInt32 quickTimeVersion = 0;
class QTMoviePrivate : public QTMovieTaskClient {
@@ -374,10 +375,10 @@ void QTMovie::setCurrentTime(float time) const
m_private->m_seeking = true;
TimeScale scale = GetMovieTimeScale(m_private->m_movie);
if (m_private->m_movieController) {
- QTRestartAtTimeRecord restart = { time * scale , 0 };
+ QTRestartAtTimeRecord restart = { lroundf(time * scale) , 0 };
MCDoAction(m_private->m_movieController, mcActionRestartAtTime, (void *)&restart);
} else
- SetMovieTimeValue(m_private->m_movie, TimeValue(time * scale));
+ SetMovieTimeValue(m_private->m_movie, TimeValue(lroundf(time * scale)));
QTMovieTask::sharedTask()->updateTaskTimer();
}
@@ -747,112 +748,59 @@ long QTMovie::timeScale() const
return GetMovieTimeScale(m_private->m_movie);
}
+static void getMIMETypeCallBack(const char* type);
+
static void initializeSupportedTypes()
{
if (gSupportedTypes)
return;
- gSupportedTypes = new Vector<CFStringRef>;
+ gSupportedTypes = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
if (quickTimeVersion < minimumQuickTimeVersion) {
LOG_ERROR("QuickTime version %x detected, at least %x required. Returning empty list of supported media MIME types.", quickTimeVersion, minimumQuickTimeVersion);
return;
}
// QuickTime doesn't have an importer for video/quicktime. Add it manually.
- gSupportedTypes->append(CFSTR("video/quicktime"));
-
- for (int index = 0; index < 2; index++) {
- ComponentDescription findCD;
-
- // look at all movie importers that can import in place and are installed.
- findCD.componentType = MovieImportType;
- findCD.componentSubType = 0;
- findCD.componentManufacturer = 0;
- findCD.componentFlagsMask = cmpIsMissing | movieImportSubTypeIsFileExtension | canMovieImportInPlace | dontAutoFileMovieImport;
-
- // look at those registered by HFS file types the first time through, by file extension the second time
- findCD.componentFlags = canMovieImportInPlace | (index ? movieImportSubTypeIsFileExtension : 0);
-
- long componentCount = CountComponents(&findCD);
- if (!componentCount)
- continue;
+ CFArrayAppendValue(gSupportedTypes, CFSTR("video/quicktime"));
+
+ wkGetQuickTimeMIMETypeList(getMIMETypeCallBack);
+}
- Component comp = 0;
- while (comp = FindNextComponent(comp, &findCD)) {
- // Does this component have a MIME type container?
- ComponentDescription infoCD;
- OSErr err = GetComponentInfo(comp, &infoCD, nil /*name*/, nil /*info*/, nil /*icon*/);
- if (err)
- continue;
- if (!(infoCD.componentFlags & hasMovieImportMIMEList))
- continue;
- QTAtomContainer mimeList = 0;
- err = MovieImportGetMIMETypeList((ComponentInstance)comp, &mimeList);
- if (err || !mimeList)
- continue;
+static void getMIMETypeCallBack(const char* type)
+{
+ ASSERT(type);
+ CFStringRef cfType = CFStringCreateWithCString(kCFAllocatorDefault, type, kCFStringEncodingMacRoman);
+ if (!cfType)
+ return;
- // Grab every type from the container.
- QTLockContainer(mimeList);
- int typeCount = QTCountChildrenOfType(mimeList, kParentAtomIsContainer, kMimeInfoMimeTypeTag);
- for (int typeIndex = 1; typeIndex <= typeCount; typeIndex++) {
- QTAtom mimeTag = QTFindChildByIndex(mimeList, 0, kMimeInfoMimeTypeTag, typeIndex, 0);
- if (!mimeTag)
- continue;
- char* atomData;
- long typeLength;
- if (noErr != QTGetAtomDataPtr(mimeList, mimeTag, &typeLength, &atomData))
- continue;
-
- char typeBuffer[256];
- if (typeLength >= sizeof(typeBuffer))
- continue;
- memcpy(typeBuffer, atomData, typeLength);
- typeBuffer[typeLength] = 0;
-
- // Only add "audio/..." and "video/..." types.
- if (strncmp(typeBuffer, "audio/", 6) && strncmp(typeBuffer, "video/", 6))
- continue;
-
- CFStringRef cfMimeType = CFStringCreateWithCString(0, typeBuffer, kCFStringEncodingUTF8);
- if (!cfMimeType)
- continue;
-
- // Only add each type once.
- bool alreadyAdded = false;
- for (int addedIndex = 0; addedIndex < gSupportedTypes->size(); addedIndex++) {
- CFStringRef type = gSupportedTypes->at(addedIndex);
- if (kCFCompareEqualTo == CFStringCompare(cfMimeType, type, kCFCompareCaseInsensitive)) {
- alreadyAdded = true;
- break;
- }
- }
- if (!alreadyAdded)
- gSupportedTypes->append(cfMimeType);
- else
- CFRelease(cfMimeType);
- }
- DisposeHandle(mimeList);
- }
+ // Filter out all non-audio or -video MIME Types, and only add each type once:
+ if (CFStringHasPrefix(cfType, CFSTR("audio/")) || CFStringHasPrefix(cfType, CFSTR("video/"))) {
+ CFRange range = CFRangeMake(0, CFArrayGetCount(gSupportedTypes));
+ if (!CFArrayContainsValue(gSupportedTypes, range, cfType))
+ CFArrayAppendValue(gSupportedTypes, cfType);
}
+
+ CFRelease(cfType);
}
unsigned QTMovie::countSupportedTypes()
{
initializeSupportedTypes();
- return static_cast<unsigned>(gSupportedTypes->size());
+ return static_cast<unsigned>(CFArrayGetCount(gSupportedTypes));
}
void QTMovie::getSupportedType(unsigned index, const UChar*& str, unsigned& len)
{
initializeSupportedTypes();
- ASSERT(index < gSupportedTypes->size());
+ ASSERT(index < CFArrayGetCount(gSupportedTypes));
// Allocate sufficient buffer to hold any MIME type
static UniChar* staticBuffer = 0;
if (!staticBuffer)
staticBuffer = new UniChar[32];
- CFStringRef cfstr = gSupportedTypes->at(index);
+ CFStringRef cfstr = (CFStringRef)CFArrayGetValueAtIndex(gSupportedTypes, index);
len = CFStringGetLength(cfstr);
CFRange range = { 0, len };
CFStringGetCharacters(cfstr, range, staticBuffer);
diff --git a/Source/WebCore/platform/graphics/win/QTMovieGWorld.cpp b/Source/WebCore/platform/graphics/win/QTMovieGWorld.cpp
index e13f732..4be1bbb 100644
--- a/Source/WebCore/platform/graphics/win/QTMovieGWorld.cpp
+++ b/Source/WebCore/platform/graphics/win/QTMovieGWorld.cpp
@@ -40,7 +40,7 @@ using namespace std;
static const long minimumQuickTimeVersion = 0x07300000; // 7.3
-static LPCTSTR fullscreenQTMovieGWorldPointerProp = TEXT("fullscreenQTMovieGWorldPointer");
+static LPCWSTR fullscreenQTMovieGWorldPointerProp = L"fullscreenQTMovieGWorldPointer";
// Resizing GWorlds is slow, give them a minimum size so size of small
// videos can be animated smoothly
@@ -378,10 +378,10 @@ bool QTMovieGWorld::isDisabled() const
LRESULT QTMovieGWorld::fullscreenWndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam)
{
- QTMovieGWorld* movie = static_cast<QTMovieGWorld*>(GetProp(wnd, fullscreenQTMovieGWorldPointerProp));
+ QTMovieGWorld* movie = static_cast<QTMovieGWorld*>(GetPropW(wnd, fullscreenQTMovieGWorldPointerProp));
if (message == WM_DESTROY)
- RemoveProp(wnd, fullscreenQTMovieGWorldPointerProp);
+ RemovePropW(wnd, fullscreenQTMovieGWorldPointerProp);
if (!movie)
return DefWindowProc(wnd, message, wParam, lParam);
@@ -423,7 +423,7 @@ HWND QTMovieGWorld::enterFullscreen(QTMovieGWorldFullscreenClient* client)
// Set the 'this' pointer on the HWND
HWND wnd = static_cast<HWND>(GetPortNativeWindow(m_private->m_fullscreenWindow));
- SetProp(wnd, fullscreenQTMovieGWorldPointerProp, static_cast<HANDLE>(this));
+ SetPropW(wnd, fullscreenQTMovieGWorldPointerProp, static_cast<HANDLE>(this));
return wnd;
}
diff --git a/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp b/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
index 20d42ff..30a931e 100644
--- a/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
+++ b/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
@@ -29,20 +29,19 @@
#include "config.h"
#include "SimpleFontData.h"
-#include <winsock2.h>
#include "Font.h"
#include "FontCache.h"
#include "FloatRect.h"
#include "FontDescription.h"
#include "PlatformString.h"
-#include <wtf/MathExtras.h>
-#include <wtf/RetainPtr.h>
-#include <unicode/uchar.h>
-#include <unicode/unorm.h>
#include <ApplicationServices/ApplicationServices.h>
#include <WebKitSystemInterface/WebKitSystemInterface.h>
#include <mlang.h>
-#include <tchar.h>
+#include <unicode/uchar.h>
+#include <unicode/unorm.h>
+#include <winsock2.h>
+#include <wtf/MathExtras.h>
+#include <wtf/RetainPtr.h>
namespace WebCore {
@@ -64,19 +63,19 @@ void SimpleFontData::platformInit()
int iAscent = CGFontGetAscent(font);
int iDescent = CGFontGetDescent(font);
int iLineGap = CGFontGetLeading(font);
- m_unitsPerEm = CGFontGetUnitsPerEm(font);
+ unsigned unitsPerEm = CGFontGetUnitsPerEm(font);
float pointSize = m_platformData.size();
- float fAscent = scaleEmToUnits(iAscent, m_unitsPerEm) * pointSize;
- float fDescent = -scaleEmToUnits(iDescent, m_unitsPerEm) * pointSize;
- float fLineGap = scaleEmToUnits(iLineGap, m_unitsPerEm) * pointSize;
+ float fAscent = scaleEmToUnits(iAscent, unitsPerEm) * pointSize;
+ float fDescent = -scaleEmToUnits(iDescent, unitsPerEm) * pointSize;
+ float fLineGap = scaleEmToUnits(iLineGap, unitsPerEm) * pointSize;
if (!isCustomFont()) {
HDC dc = GetDC(0);
HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
int faceLength = GetTextFace(dc, 0, 0);
- Vector<TCHAR> faceName(faceLength);
+ Vector<WCHAR> faceName(faceLength);
GetTextFace(dc, faceLength, faceName.data());
- m_isSystemFont = !_tcscmp(faceName.data(), _T("Lucida Grande"));
+ m_isSystemFont = !wcscmp(faceName.data(), L"Lucida Grande");
SelectObject(dc, oldFont);
ReleaseDC(0, dc);
@@ -88,15 +87,15 @@ void SimpleFontData::platformInit()
// web standard. The AppKit adjustment of 20% is too big and is
// incorrectly added to line spacing, so we use a 15% adjustment instead
// and add it to the ascent.
- if (!_tcscmp(faceName.data(), _T("Times")) || !_tcscmp(faceName.data(), _T("Helvetica")) || !_tcscmp(faceName.data(), _T("Courier")))
+ if (!wcscmp(faceName.data(), L"Times") || !wcscmp(faceName.data(), L"Helvetica") || !wcscmp(faceName.data(), L"Courier"))
fAscent += floorf(((fAscent + fDescent) * 0.15f) + 0.5f);
}
}
- m_ascent = lroundf(fAscent);
- m_descent = lroundf(fDescent);
- m_lineGap = lroundf(fLineGap);
- m_lineSpacing = m_ascent + m_descent + m_lineGap;
+ m_fontMetrics.setAscent(fAscent);
+ m_fontMetrics.setDescent(fDescent);
+ 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.
@@ -109,11 +108,13 @@ void SimpleFontData::platformInit()
// 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_xHeight = scaleEmToUnits(max(CGRectGetMaxX(xBox), CGRectGetMaxY(xBox)), m_unitsPerEm) * pointSize;
+ m_fontMetrics.setXHeight(scaleEmToUnits(max(CGRectGetMaxX(xBox), CGRectGetMaxY(xBox)), unitsPerEm) * pointSize);
} else {
int iXHeight = CGFontGetXHeight(font);
- m_xHeight = scaleEmToUnits(iXHeight, m_unitsPerEm) * pointSize;
+ m_fontMetrics.setXHeight(scaleEmToUnits(iXHeight, unitsPerEm) * pointSize);
}
+
+ m_fontMetrics.setUnitsPerEm(unitsPerEm);
}
void SimpleFontData::platformCharWidthInit()
@@ -133,7 +134,7 @@ FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const
CGRect box;
CGFontGetGlyphBBoxes(m_platformData.cgFont(), &glyph, 1, &box);
float pointSize = m_platformData.size();
- CGFloat scale = pointSize / unitsPerEm();
+ CGFloat scale = pointSize / fontMetrics().unitsPerEm();
FloatRect boundingBox = CGRectApplyAffineTransform(box, CGAffineTransformMakeScale(scale, -scale));
if (m_syntheticBoldOffset)
boundingBox.setWidth(boundingBox.width() + m_syntheticBoldOffset);
diff --git a/Source/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp b/Source/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp
index 62ea060..277a13f 100644
--- a/Source/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp
+++ b/Source/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp
@@ -37,7 +37,6 @@
#include <cairo.h>
#include <cairo-win32.h>
#include <mlang.h>
-#include <tchar.h>
#include <wtf/MathExtras.h>
namespace WebCore {
@@ -63,13 +62,16 @@ void SimpleFontData::platformInit()
TEXTMETRIC textMetrics;
GetTextMetrics(hdc, &textMetrics);
- m_ascent = lroundf(textMetrics.tmAscent * metricsMultiplier);
- m_descent = lroundf(textMetrics.tmDescent * metricsMultiplier);
- m_xHeight = m_ascent * 0.56f; // Best guess for xHeight for non-Truetype fonts.
- m_lineGap = lroundf(textMetrics.tmExternalLeading * metricsMultiplier);
- m_lineSpacing = m_ascent + m_descent + m_lineGap;
- m_avgCharWidth = lroundf(textMetrics.tmAveCharWidth * metricsMultiplier);
- m_maxCharWidth = lroundf(textMetrics.tmMaxCharWidth * metricsMultiplier);
+ float ascent = textMetrics.tmAscent * metricsMultiplier;
+ float descent = textMetrics.tmDescent * metricsMultiplier;
+ float xHeight = ascent * 0.56f; // Best guess for xHeight for non-Truetype fonts.
+ float lineGap = textMetrics.tmExternalLeading * metricsMultiplier;
+ m_fontMetrics.setAscent(ascent);
+ m_fontMetrics.setDescent(descent);
+ m_fontMetrics.setLineGap(lineGap);
+ m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));
+ m_avgCharWidth = textMetrics.tmAveCharWidth * metricsMultiplier;
+ m_maxCharWidth = textMetrics.tmMaxCharWidth * metricsMultiplier;
OUTLINETEXTMETRIC metrics;
if (GetOutlineTextMetrics(hdc, sizeof(metrics), &metrics) > 0) {
@@ -78,9 +80,10 @@ void SimpleFontData::platformInit()
MAT2 mat = { 1, 0, 0, 1 };
DWORD len = GetGlyphOutline(hdc, 'x', GGO_METRICS, &gm, 0, 0, &mat);
if (len != GDI_ERROR && gm.gmptGlyphOrigin.y > 0)
- m_xHeight = gm.gmptGlyphOrigin.y * metricsMultiplier;
+ xHeight = gm.gmptGlyphOrigin.y * metricsMultiplier;
}
+ m_fontMetrics.setXHeight(xHeight);
cairo_win32_scaled_font_done_font(scaledFont);
m_isSystemFont = false;
diff --git a/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp b/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
index 60afe6a..323ff73 100644
--- a/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
+++ b/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
@@ -29,16 +29,15 @@
#include "config.h"
#include "SimpleFontData.h"
-#include <winsock2.h>
#include "Font.h"
#include "FontCache.h"
#include "FloatRect.h"
#include "FontDescription.h"
-#include <wtf/MathExtras.h>
+#include <mlang.h>
#include <unicode/uchar.h>
#include <unicode/unorm.h>
-#include <mlang.h>
-#include <tchar.h>
+#include <winsock2.h>
+#include <wtf/MathExtras.h>
#if PLATFORM(CG)
#include <ApplicationServices/ApplicationServices.h>
@@ -66,14 +65,9 @@ bool SimpleFontData::shouldApplyMacAscentHack()
void SimpleFontData::initGDIFont()
{
if (!m_platformData.size()) {
- m_ascent = 0;
- m_descent = 0;
- m_lineGap = 0;
- m_lineSpacing = 0;
+ m_fontMetrics.reset();
m_avgCharWidth = 0;
m_maxCharWidth = 0;
- m_xHeight = 0;
- m_unitsPerEm = 0;
return;
}
@@ -82,21 +76,25 @@ void SimpleFontData::initGDIFont()
OUTLINETEXTMETRIC metrics;
GetOutlineTextMetrics(hdc, sizeof(metrics), &metrics);
TEXTMETRIC& textMetrics = metrics.otmTextMetrics;
- m_ascent = textMetrics.tmAscent;
- m_descent = textMetrics.tmDescent;
- m_lineGap = textMetrics.tmExternalLeading;
- m_lineSpacing = m_ascent + m_descent + m_lineGap;
+ float ascent = textMetrics.tmAscent;
+ float descent = textMetrics.tmDescent;
+ float lineGap = textMetrics.tmExternalLeading;
+ m_fontMetrics.setAscent(ascent);
+ m_fontMetrics.setDescent(descent);
+ m_fontMetrics.setLineGap(lineGap);
+ m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));
m_avgCharWidth = textMetrics.tmAveCharWidth;
m_maxCharWidth = textMetrics.tmMaxCharWidth;
- m_xHeight = m_ascent * 0.56f; // Best guess for xHeight if no x glyph is present.
+ float xHeight = ascent * 0.56f; // Best guess for xHeight if no x glyph is present.
GLYPHMETRICS gm;
MAT2 mat = { 1, 0, 0, 1 };
DWORD len = GetGlyphOutline(hdc, 'x', GGO_METRICS, &gm, 0, 0, &mat);
if (len != GDI_ERROR && gm.gmptGlyphOrigin.y > 0)
- m_xHeight = gm.gmptGlyphOrigin.y;
+ xHeight = gm.gmptGlyphOrigin.y;
- m_unitsPerEm = metrics.otmEMSquare;
+ m_fontMetrics.setXHeight(xHeight);
+ m_fontMetrics.setUnitsPerEm(metrics.otmEMSquare);
SelectObject(hdc, oldFont);
ReleaseDC(0, hdc);
diff --git a/Source/WebCore/platform/graphics/win/UniscribeController.cpp b/Source/WebCore/platform/graphics/win/UniscribeController.cpp
index dac6c3e..ebbed51 100644
--- a/Source/WebCore/platform/graphics/win/UniscribeController.cpp
+++ b/Source/WebCore/platform/graphics/win/UniscribeController.cpp
@@ -49,7 +49,7 @@ UniscribeController::UniscribeController(const Font* font, const TextRun& run, H
, m_end(run.length())
, m_currentCharacter(0)
, m_runWidthSoFar(0)
- , m_padding(run.padding())
+ , m_padding(run.expansion())
, m_computingOffsetPosition(false)
, m_includePartialGlyphs(false)
, m_offsetX(0)
@@ -394,9 +394,9 @@ bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, const S
FloatRect glyphBounds = fontData->boundsForGlyph(glyph);
glyphBounds.move(m_glyphOrigin.x(), m_glyphOrigin.y());
m_minGlyphBoundingBoxX = min(m_minGlyphBoundingBoxX, glyphBounds.x());
- m_maxGlyphBoundingBoxX = max(m_maxGlyphBoundingBoxX, glyphBounds.right());
+ m_maxGlyphBoundingBoxX = max(m_maxGlyphBoundingBoxX, glyphBounds.maxX());
m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, glyphBounds.y());
- m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, glyphBounds.bottom());
+ m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, glyphBounds.maxY());
m_glyphOrigin.move(advance + offsetX, -offsetY);
// Mutate the glyph array to contain our altered advances.
diff --git a/Source/WebCore/platform/graphics/win/WKCAImageQueue.cpp b/Source/WebCore/platform/graphics/win/WKCAImageQueue.cpp
index c2a178b..c8f2116 100644
--- a/Source/WebCore/platform/graphics/win/WKCAImageQueue.cpp
+++ b/Source/WebCore/platform/graphics/win/WKCAImageQueue.cpp
@@ -24,11 +24,11 @@
*/
#include "config.h"
+#include "WKCAImageQueue.h"
#if USE(ACCELERATED_COMPOSITING)
-#include "WKCAImageQueue.h"
-
+#include <CoreFoundation/CoreFoundation.h>
#include <WebKitSystemInterface/WebKitSystemInterface.h>
#include <wtf/RetainPtr.h>
diff --git a/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp
index f61ae8e..fb97fe1 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, FontRenderingMode renderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode renderingMode)
{
FontDescription fontDesc;
fontDesc.setComputedSize(size);
@@ -59,16 +59,14 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b
// not allow access from CSS.
static String createUniqueFontName()
{
- Vector<char> fontUuid(sizeof(GUID));
+ GUID fontUuid;
- unsigned int* ptr = reinterpret_cast<unsigned int*>(fontUuid.data());
+ unsigned int* ptr = reinterpret_cast<unsigned int*>(&fontUuid);
for (int i = 0; i < sizeof(GUID) / sizeof(int) ; ++i)
*(ptr + i) = static_cast<unsigned int>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0));
- Vector<char> fontNameVector;
- base64Encode(fontUuid, fontNameVector);
- ASSERT(fontNameVector.size() < LF_FACESIZE);
- String fontName(fontNameVector.data(), fontNameVector.size());
+ String fontName = base64Encode(reinterpret_cast<char*>(&fontUuid), sizeof(fontUuid));
+ ASSERT(fontName.length() < LF_FACESIZE);
return fontName.replace('/', '_');
}
diff --git a/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.h
index 0508246..fe7ee94 100644
--- a/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.h
+++ b/Source/WebCore/platform/graphics/wince/FontCustomPlatformData.h
@@ -23,6 +23,7 @@
#include "FontDescription.h"
#include "FontRenderingMode.h"
+#include "FontWidthVariant.h"
#include "PlatformString.h"
#include <wtf/Noncopyable.h>
@@ -47,7 +48,7 @@ namespace WebCore {
~FontCustomPlatformData();
- FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation fontOrientation = Horizontal, FontRenderingMode = NormalRenderingMode);
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
static bool supportsFormat(const String&);
diff --git a/Source/WebCore/platform/graphics/wince/FontWinCE.cpp b/Source/WebCore/platform/graphics/wince/FontWinCE.cpp
index 5a4c8da..c3e6ce4 100644
--- a/Source/WebCore/platform/graphics/wince/FontWinCE.cpp
+++ b/Source/WebCore/platform/graphics/wince/FontWinCE.cpp
@@ -86,6 +86,7 @@ public:
TextRunComponent::TextRunComponent(const UChar *start, int length, const TextRun& parentTextRun, const Font &font, int o)
: m_textRun(start, length, parentTextRun.allowTabs(), 0, 0
+ , parentTextRun.allowsTrailingExpansion() ? TextRun::AllowTrailingExpansion : TextRun::ForbidTrailingExpansion
, parentTextRun.rtl()
, parentTextRun.directionalOverride()
, parentTextRun.applyRunRounding()
@@ -112,7 +113,7 @@ static int generateComponents(TextRunComponents* components, const Font &font, c
{
int letterSpacing = font.letterSpacing();
int wordSpacing = font.wordSpacing();
- int padding = run.padding();
+ int padding = run.expansion();
int numSpaces = 0;
if (padding) {
for (int i = 0; i < run.length(); i++)
@@ -340,4 +341,9 @@ bool Font::canReturnFallbackFontsForComplexText()
return false;
}
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+ return false;
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp b/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp
index 9b672d2..7b1c27b 100644
--- a/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp
+++ b/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp
@@ -23,7 +23,6 @@
#include "GraphicsContext.h"
#include "AffineTransform.h"
-#include "CharacterNames.h"
#include "Font.h"
#include "GDIExtras.h"
#include "GlyphBuffer.h"
@@ -33,9 +32,9 @@
#include "PlatformPathWinCE.h"
#include "SharedBitmap.h"
#include "SimpleFontData.h"
-#include <wtf/OwnPtr.h>
-
#include <windows.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/unicode/CharacterNames.h>
namespace WebCore {
@@ -62,7 +61,7 @@ static inline int stableRound(double d)
// Unlike enclosingIntRect(), this function does strict rounding.
static inline IntRect roundRect(const FloatRect& r)
{
- return IntRect(stableRound(r.x()), stableRound(r.y()), stableRound(r.right()) - stableRound(r.x()), stableRound(r.bottom()) - stableRound(r.y()));
+ return IntRect(stableRound(r.x()), stableRound(r.y()), stableRound(r.maxX()) - stableRound(r.x()), stableRound(r.maxY()) - stableRound(r.y()));
}
// Rotation transformation
@@ -129,8 +128,8 @@ template<class Transform, class Rect, class Value> static inline Rect mapRect(co
{
Value x[4], y[4];
Value l, t, r, b;
- r = rect.right() - 1;
- b = rect.bottom() - 1;
+ r = rect.maxX() - 1;
+ b = rect.maxY() - 1;
transform.map(rect.x(), rect.y(), x, y);
transform.map(rect.x(), b, x + 1, y + 1);
transform.map(r, b, x + 2, y + 2);
@@ -503,10 +502,10 @@ TransparentLayerDC::TransparentLayerDC(GraphicsContextPlatformPrivate* data, Int
m_rotation.m_postShiftX -= m_origRect.x();
m_rotation.m_postShiftY -= m_origRect.y();
- FloatPoint topLeft = m_data->m_transform.mapPoint(FloatPoint(rectBeforeTransform->topLeft()));
- FloatPoint topRight(rectBeforeTransform->right() - 1, rectBeforeTransform->y());
+ FloatPoint topLeft = m_data->m_transform.mapPoint(FloatPoint(rectBeforeTransform->location()));
+ FloatPoint topRight(rectBeforeTransform->maxX() - 1, rectBeforeTransform->y());
topRight = m_data->m_transform.mapPoint(topRight);
- FloatPoint bottomLeft(rectBeforeTransform->x(), rectBeforeTransform->bottom() - 1);
+ FloatPoint bottomLeft(rectBeforeTransform->x(), rectBeforeTransform->maxY() - 1);
bottomLeft = m_data->m_transform.mapPoint(bottomLeft);
FloatSize sideTop = topRight - topLeft;
FloatSize sideLeft = bottomLeft - topLeft;
@@ -656,7 +655,7 @@ void GraphicsContext::drawRect(const IntRect& rect)
if (trRect.height() <= 0)
trRect.setHeight(1);
- Rectangle(dc, trRect.x(), trRect.y(), trRect.right(), trRect.bottom());
+ Rectangle(dc, trRect.x(), trRect.y(), trRect.maxX(), trRect.maxY());
}
SelectObject(dc, oldPen);
@@ -726,7 +725,7 @@ void GraphicsContext::drawEllipse(const IntRect& rect)
oldPen = SelectObject(dc, GetStockObject(NULL_PEN));
if (brush || pen)
- Ellipse(dc, trRect.x(), trRect.y(), trRect.right(), trRect.bottom());
+ Ellipse(dc, trRect.x(), trRect.y(), trRect.maxX(), trRect.maxY());
SelectObject(dc, oldPen);
SelectObject(dc, oldBrush);
@@ -839,7 +838,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
}
HGDIOBJ oldBrush = SelectObject(dc, GetStockObject(NULL_BRUSH));
- Ellipse(dc, trRect.x(), trRect.y(), trRect.right(), trRect.bottom());
+ Ellipse(dc, trRect.x(), trRect.y(), trRect.maxX(), trRect.maxY());
SelectObject(dc, oldBrush);
if (newClip)
@@ -960,9 +959,9 @@ void GraphicsContext::clip(const FloatRect& rect)
OwnPtr<HRGN> clipRgn(CreateRectRgn(0, 0, 0, 0));
if (GetClipRgn(m_data->m_dc, clipRgn.get()) > 0)
- IntersectClipRect(m_data->m_dc, trRect.x(), trRect.y(), trRect.right(), trRect.bottom());
+ IntersectClipRect(m_data->m_dc, trRect.x(), trRect.y(), trRect.maxX(), trRect.maxY());
else {
- clipRgn.set(CreateRectRgn(trRect.x(), trRect.y(), trRect.right(), trRect.bottom()));
+ clipRgn.set(CreateRectRgn(trRect.x(), trRect.y(), trRect.maxX(), trRect.maxY()));
SelectClipRgn(m_data->m_dc, clipRgn.get());
}
}
@@ -977,7 +976,7 @@ void GraphicsContext::clipOut(const IntRect& rect)
IntRect trRect = m_data->mapRect(rect);
- ExcludeClipRect(m_data->m_dc, trRect.x(), trRect.y(), trRect.right(), trRect.bottom());
+ ExcludeClipRect(m_data->m_dc, trRect.x(), trRect.y(), trRect.maxX(), trRect.maxY());
}
void GraphicsContext::drawFocusRing(const Path& path, int width, int offset, const Color& color)
@@ -1093,8 +1092,8 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float width)
OwnPtr<HPEN> pen = createPen(strokeColor(), strokeThickness(), strokeStyle());
HGDIOBJ oldPen = SelectObject(dc, pen.get());
- int right = trRect.right() - 1;
- int bottom = trRect.bottom() - 1;
+ int right = trRect.maxX() - 1;
+ int bottom = trRect.maxY() - 1;
const POINT intPoints[5] =
{
{ trRect.x(), trRect.y() },
@@ -1536,8 +1535,8 @@ void GraphicsContext::drawText(const Font& font, const TextRun& run, const IntPo
float oldOpacity = m_data->m_opacity;
m_data->m_opacity *= fillColor().alpha() / 255.0;
- FloatRect textRect = font.selectionRectForText(run, point, font.height(), from, to);
- textRect.setY(textRect.y() - font.ascent());
+ FloatRect textRect = font.selectionRectForText(run, point, font.fontMetrics().height(), from, to);
+ textRect.setY(textRect.y() - font.fontMetrics().ascent());
IntRect trRect = enclosingIntRect(m_data->mapRect(textRect));
RECT bmpRect;
AlphaPaintType alphaPaintType = mustSupportAlpha ? AlphaPaintOther : AlphaPaintNone;
@@ -1546,7 +1545,7 @@ void GraphicsContext::drawText(const Font& font, const TextRun& run, const IntPo
GraphicsContext gc(0);
gc.setBitmap(bmp);
gc.scale(FloatSize(m_data->m_transform.a(), m_data->m_transform.d()));
- font.drawText(&gc, run, IntPoint(0, font.ascent()), from, to);
+ font.drawText(&gc, run, IntPoint(0, font.fontMetrics().ascent()), from, to);
}
unsigned key1;
HDC memDC = bmp->getDC(&key1);
@@ -1591,7 +1590,7 @@ void GraphicsContext::drawText(const SimpleFontData* fontData, const GlyphBuffer
? fontData->platformData().getScaledFontHandle(height, scaleX == scaleY ? 0 : width)
: 0;
- FloatPoint startPoint(point.x(), point.y() - fontData->ascent());
+ FloatPoint startPoint(point.x(), point.y() - fontData->fontMetrics().ascent());
FloatPoint trPoint = m_data->mapPoint(startPoint);
int y = stableRound(trPoint.y());
diff --git a/Source/WebCore/platform/graphics/wince/PlatformPathWinCE.cpp b/Source/WebCore/platform/graphics/wince/PlatformPathWinCE.cpp
index 8534f89..8efe661 100644
--- a/Source/WebCore/platform/graphics/wince/PlatformPathWinCE.cpp
+++ b/Source/WebCore/platform/graphics/wince/PlatformPathWinCE.cpp
@@ -119,7 +119,7 @@ static inline void bezier(int segments, Vector<PathPoint>& pts, const PathPoint*
static bool containsPoint(const FloatRect& r, const FloatPoint& p)
{
- return p.x() >= r.x() && p.y() >= r.y() && p.x() < r.right() && p.y() < r.bottom();
+ return p.x() >= r.x() && p.y() >= r.y() && p.x() < r.maxX() && p.y() < r.maxY();
}
static void normalizeAngle(float& angle)
@@ -146,7 +146,7 @@ static void inflateRectToContainPoint(FloatRect& r, float x, float y)
return;
}
if (x < r.x()) {
- r.setWidth(r.right() - x);
+ r.setWidth(r.maxX() - x);
r.setX(x);
} else {
float w = x - r.x() + 1;
@@ -154,7 +154,7 @@ static void inflateRectToContainPoint(FloatRect& r, float x, float y)
r.setWidth(w);
}
if (y < r.y()) {
- r.setHeight(r.bottom() - y);
+ r.setHeight(r.maxY() - y);
r.setY(y);
} else {
float h = y - r.y() + 1;
@@ -740,8 +740,8 @@ void PlatformPath::addRect(const FloatRect& r)
{
moveTo(r.location());
- float right = r.right() - 1;
- float bottom = r.bottom() - 1;
+ float right = r.maxX() - 1;
+ float bottom = r.maxY() - 1;
addLineTo(FloatPoint(right, r.y()));
addLineTo(FloatPoint(right, bottom));
addLineTo(FloatPoint(r.x(), bottom));
diff --git a/Source/WebCore/platform/graphics/wince/SharedBitmap.cpp b/Source/WebCore/platform/graphics/wince/SharedBitmap.cpp
index 168a5e2..2bf0028 100644
--- a/Source/WebCore/platform/graphics/wince/SharedBitmap.cpp
+++ b/Source/WebCore/platform/graphics/wince/SharedBitmap.cpp
@@ -135,7 +135,7 @@ bool SharedBitmap::to16bit()
int width = newBmpInfo.width();
int paddedWidth = newBmpInfo.paddedWidth();
int bufferSize = paddedWidth * newBmpInfo.height();
- OwnArrayPtr<unsigned> newPixelData(new unsigned[bufferSize / 2]);
+ OwnArrayPtr<unsigned> newPixelData = adoptArrayPtr(new unsigned[bufferSize / 2]);
void* newPixels = newPixelData.get();
if (!newPixels)
@@ -481,8 +481,8 @@ void SharedBitmap::drawPattern(HDC hdc, const AffineTransform& transform, const
RECT dstRectWin = {
stableRound(trRect.x()),
stableRound(trRect.y()),
- stableRound(trRect.right()),
- stableRound(trRect.bottom()),
+ stableRound(trRect.maxX()),
+ stableRound(trRect.maxY()),
};
if (dstRectWin.right <= dstRectWin.left || dstRectWin.bottom <= dstRectWin.top)
return;
@@ -497,8 +497,8 @@ void SharedBitmap::drawPattern(HDC hdc, const AffineTransform& transform, const
RECT srcRectWin = {
0,
0,
- stableRound(visibleDstRect.right()) - stableRound(visibleDstRect.x()),
- stableRound(visibleDstRect.bottom()) - stableRound(visibleDstRect.y())
+ stableRound(visibleDstRect.maxX()) - stableRound(visibleDstRect.x()),
+ stableRound(visibleDstRect.maxY()) - stableRound(visibleDstRect.y())
};
if (srcRectWin.right <= 0 || srcRectWin.bottom <= 0)
return;
diff --git a/Source/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp b/Source/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp
index 27a021e..8abafbd 100644
--- a/Source/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp
+++ b/Source/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp
@@ -27,7 +27,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
#include "config.h"
#include "SimpleFontData.h"
@@ -35,9 +34,8 @@
#include "Font.h"
#include "FontCache.h"
#include "FontDescription.h"
-#include <wtf/MathExtras.h>
#include <mlang.h>
-#include <tchar.h>
+#include <wtf/MathExtras.h>
namespace WebCore {
@@ -51,11 +49,14 @@ void SimpleFontData::platformInit()
const TEXTMETRIC& tm = m_platformData.metrics();
m_isSystemFont = m_platformData.isSystemFont();
- m_ascent = (tm.tmAscent * m_platformData.size() + 36) / 72;
- m_descent = (tm.tmDescent * m_platformData.size() + 36) / 72;
- m_lineGap = (tm.tmExternalLeading * m_platformData.size() + 36) / 72;
- m_lineSpacing = m_ascent + m_descent + m_lineGap;
- m_xHeight = m_ascent * 0.56f;
+ float ascent = (tm.tmAscent * m_platformData.size() + 36) / 72.0f;
+ float descent = (tm.tmDescent * m_platformData.size() + 36) / 72.0f;
+ float lineGap = (tm.tmExternalLeading * m_platformData.size() + 36) / 72.0f;
+ m_fontMetrics.setAscent(ascent);
+ m_fontMetrics.setDescent(descent);
+ m_fontMetrics.setLineGap(lineGap);
+ m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));
+ m_fontMetrics.setXHeight(ascent * 0.56f);
}
void SimpleFontData::platformDestroy()
diff --git a/Source/WebCore/platform/graphics/wx/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/wx/FontCustomPlatformData.cpp
index 6133372..055f0fc 100644
--- a/Source/WebCore/platform/graphics/wx/FontCustomPlatformData.cpp
+++ b/Source/WebCore/platform/graphics/wx/FontCustomPlatformData.cpp
@@ -31,7 +31,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
{
}
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontRenderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode)
{
return FontPlatformData(size, bold, italic);
}
diff --git a/Source/WebCore/platform/graphics/wx/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/wx/FontCustomPlatformData.h
index 86f99b2..c975296 100644
--- a/Source/WebCore/platform/graphics/wx/FontCustomPlatformData.h
+++ b/Source/WebCore/platform/graphics/wx/FontCustomPlatformData.h
@@ -23,7 +23,9 @@
#include "FontOrientation.h"
#include "FontRenderingMode.h"
+#include "FontWidthVariant.h"
#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
namespace WebCore {
@@ -38,7 +40,7 @@ namespace WebCore {
static bool supportsFormat(const String&);
- FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontRenderingMode = NormalRenderingMode);
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
};
FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer*);
diff --git a/Source/WebCore/platform/graphics/wx/FontPlatformData.h b/Source/WebCore/platform/graphics/wx/FontPlatformData.h
index 9ae8b54..3ef0179 100644
--- a/Source/WebCore/platform/graphics/wx/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/wx/FontPlatformData.h
@@ -30,6 +30,7 @@
#define FontPlatformData_h
#include "FontDescription.h"
+#include "FontWidthVariant.h"
#include "FontOrientation.h"
#include "StringImpl.h"
#include <wtf/Forward.h>
@@ -150,6 +151,9 @@ public:
FontOrientation orientation() const { return Horizontal; } // FIXME: Implement.
+ // We don't support this yet, so just return the default value for now.
+ FontWidthVariant widthVariant() const { return RegularWidth; }
+
#if OS(WINDOWS)
bool useGDI() const;
HFONT hfont() const;
diff --git a/Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp b/Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
index 66c69ee..c125b7c 100644
--- a/Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
+++ b/Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
@@ -126,7 +126,7 @@ unsigned FontPlatformData::computeHash() const
thisFont->GetStyle(),
thisFont->GetWeight(),
thisFont->GetUnderlined(),
- StringImpl::computeHash(thisFont->GetFaceName().utf8_str())
+ WTF::StringHasher::createHash(thisFont->GetFaceName().utf8_str().data())
};
return WTF::StringHasher::createBlobHash<sizeof(hashCodes)>(hashCodes);
diff --git a/Source/WebCore/platform/graphics/wx/FontWx.cpp b/Source/WebCore/platform/graphics/wx/FontWx.cpp
index c01e249..c48f3c7 100644
--- a/Source/WebCore/platform/graphics/wx/FontWx.cpp
+++ b/Source/WebCore/platform/graphics/wx/FontWx.cpp
@@ -32,6 +32,7 @@
#include "IntRect.h"
#include "NotImplemented.h"
#include "SimpleFontData.h"
+#include "TextRun.h"
#if OS(WINDOWS)
#include "UniscribeController.h"
@@ -57,6 +58,15 @@ bool Font::canReturnFallbackFontsForComplexText()
#endif
}
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+#if OS(DARWIN)
+ return true;
+#else
+ return false;
+#endif
+}
+
void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
int from, int numGlyphs, const FloatPoint& point) const
{
diff --git a/Source/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/Source/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
index f1c09c5..991be79 100644
--- a/Source/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
+++ b/Source/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
@@ -515,7 +515,7 @@ void GraphicsContext::fillPath(const Path& path)
#if USE(WXGC)
wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
if (gc)
- gc->FillPath(path.platformPath());
+ gc->FillPath(*path.platformPath());
#endif
}
@@ -524,7 +524,7 @@ void GraphicsContext::strokePath(const Path& path)
#if USE(WXGC)
wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
if (gc)
- gc->StrokePath(path.platformPath());
+ gc->StrokePath(*path.platformPath());
#endif
}
diff --git a/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp b/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
index 0e24bfc..4f24e4c 100644
--- a/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
+++ b/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
@@ -53,12 +53,12 @@ void SimpleFontData::platformInit()
wxFont *font = m_platformData.font();
if (font && font->IsOk()) {
wxFontProperties props = wxFontProperties(font);
- m_ascent = props.GetAscent();
- m_descent = props.GetDescent();
- m_lineSpacing = props.GetLineSpacing();
- m_xHeight = props.GetXHeight();
- m_unitsPerEm = 1; // FIXME!
- m_lineGap = props.GetLineGap();
+ m_fontMetrics.setAscent(props.GetAscent());
+ m_fontMetrics.setDescent(props.GetDescent());
+ m_fontMetrics.setXHeight(props.GetXHeight());
+ m_fontMetrics.setUnitsPerEm(1); // FIXME!
+ m_fontMetrics.setLineGap(props.GetLineGap());
+ m_fontMetrics.setLineSpacing(props.GetLineSpacing());
}
m_syntheticBoldOffset = 0.0f;
diff --git a/Source/WebCore/platform/gtk/GtkVersioning.h b/Source/WebCore/platform/gtk/GtkVersioning.h
index 7e9fcd1..70e1bbe 100644
--- a/Source/WebCore/platform/gtk/GtkVersioning.h
+++ b/Source/WebCore/platform/gtk/GtkVersioning.h
@@ -94,7 +94,10 @@ const gchar* gtk_menu_item_get_label(GtkMenuItem*);
#define gtk_selection_data_get_length(data) (data)->length
#define gtk_selection_data_get_data(data) (data)->data
#define gtk_selection_data_get_target(data) (data)->target
-#define gtk_adjustment_set_page_size(adj, value) (adj)->page_size = value
+#define gtk_adjustment_set_page_size(adj, newValue) ((adj)->page_size = newValue)
+#define gtk_adjustment_set_value(adj, newValue) ((adj)->value = newValue)
+#define gtk_adjustment_set_lower(adj, newValue) ((adj)->lower = newValue)
+#define gtk_adjustment_set_upper(adj, newValue) ((adj)->upper = newValue)
void gtk_adjustment_configure(GtkAdjustment* adjustment, gdouble value, gdouble lower, gdouble upper,
gdouble stepIncrement, gdouble pageIncrement, gdouble pageSize);
diff --git a/Source/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp b/Source/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp
index 8fc3020..9f7f14c 100644
--- a/Source/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp
+++ b/Source/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp
@@ -28,6 +28,9 @@
#include "config.h"
#include "MIMETypeRegistry.h"
+#include <wtf/Assertions.h>
+#include <wtf/MainThread.h>
+
namespace WebCore {
struct ExtensionMap {
@@ -62,6 +65,8 @@ static const ExtensionMap extensionMap [] = {
String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
{
+ ASSERT(isMainThread());
+
String s = ext.lower();
const ExtensionMap *e = extensionMap;
while (e->extension) {
diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk.cpp b/Source/WebCore/platform/gtk/RenderThemeGtk.cpp
index bfe3901..1e9f159 100644
--- a/Source/WebCore/platform/gtk/RenderThemeGtk.cpp
+++ b/Source/WebCore/platform/gtk/RenderThemeGtk.cpp
@@ -224,15 +224,47 @@ bool RenderThemeGtk::paintTextArea(RenderObject* o, const PaintInfo& i, const In
return paintTextField(o, i, r);
}
-static void paintGdkPixbuf(GraphicsContext* context, const GdkPixbuf* icon, const IntPoint& iconPoint)
-{
+static void paintGdkPixbuf(GraphicsContext* context, const GdkPixbuf* icon, const IntRect& iconRect)
+{
+ IntSize iconSize(gdk_pixbuf_get_width(icon), gdk_pixbuf_get_height(icon));
+ if (iconRect.size() != iconSize) {
+ // We could use cairo_scale() here but cairo/pixman downscale quality is quite bad.
+ GRefPtr<GdkPixbuf> scaledIcon = gdk_pixbuf_scale_simple(icon, iconRect.width(), iconRect.height(),
+ GDK_INTERP_BILINEAR);
+ icon = scaledIcon.get();
+ }
+
cairo_t* cr = context->platformContext();
cairo_save(cr);
- gdk_cairo_set_source_pixbuf(cr, icon, iconPoint.x(), iconPoint.y());
+ gdk_cairo_set_source_pixbuf(cr, icon, iconRect.x(), iconRect.y());
cairo_paint(cr);
cairo_restore(cr);
}
+// Defined in GTK+ (gtk/gtkiconfactory.c)
+static const gint gtkIconSizeMenu = 16;
+static const gint gtkIconSizeSmallToolbar = 18;
+static const gint gtkIconSizeButton = 20;
+static const gint gtkIconSizeLargeToolbar = 24;
+static const gint gtkIconSizeDnd = 32;
+static const gint gtkIconSizeDialog = 48;
+
+static GtkIconSize getIconSizeForPixelSize(gint pixelSize)
+{
+ if (pixelSize < gtkIconSizeSmallToolbar)
+ return GTK_ICON_SIZE_MENU;
+ if (pixelSize >= gtkIconSizeSmallToolbar && pixelSize < gtkIconSizeButton)
+ return GTK_ICON_SIZE_SMALL_TOOLBAR;
+ if (pixelSize >= gtkIconSizeButton && pixelSize < gtkIconSizeLargeToolbar)
+ return GTK_ICON_SIZE_BUTTON;
+ if (pixelSize >= gtkIconSizeLargeToolbar && pixelSize < gtkIconSizeDnd)
+ return GTK_ICON_SIZE_LARGE_TOOLBAR;
+ if (pixelSize >= gtkIconSizeDnd && pixelSize < gtkIconSizeDialog)
+ return GTK_ICON_SIZE_DND;
+
+ return GTK_ICON_SIZE_DIALOG;
+}
+
void RenderThemeGtk::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
adjustSearchFieldCancelButtonStyle(selector, style, e);
@@ -243,57 +275,77 @@ bool RenderThemeGtk::paintSearchFieldResultsButton(RenderObject* o, const PaintI
return paintSearchFieldResultsDecoration(o, i, rect);
}
-void RenderThemeGtk::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+static void adjustSearchFieldIconStyle(RenderStyle* style)
{
style->resetBorder();
style->resetPadding();
+ // Get the icon size based on the font size.
+ int fontSize = style->fontSize();
+ if (fontSize < gtkIconSizeMenu) {
+ style->setWidth(Length(fontSize, Fixed));
+ style->setHeight(Length(fontSize, Fixed));
+ return;
+ }
gint width = 0, height = 0;
- gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
+ gtk_icon_size_lookup(getIconSizeForPixelSize(fontSize), &width, &height);
style->setWidth(Length(width, Fixed));
style->setHeight(Length(height, Fixed));
}
-static IntPoint centerRectVerticallyInParentInputElement(RenderObject* object, const IntRect& rect)
+void RenderThemeGtk::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ adjustSearchFieldIconStyle(style);
+}
+
+static IntRect centerRectVerticallyInParentInputElement(RenderObject* renderObject, const IntRect& rect)
{
- Node* input = object->node()->shadowAncestorNode(); // Get the renderer of <input> element.
+ // Get the renderer of <input> element.
+ Node* input = renderObject->node()->shadowAncestorNode();
if (!input->renderer()->isBox())
- return rect.topLeft();
+ return IntRect();
// If possible center the y-coordinate of the rect vertically in the parent input element.
// We also add one pixel here to ensure that the y coordinate is rounded up for box heights
// that are even, which looks in relation to the box text.
IntRect inputContentBox = toRenderBox(input->renderer())->absoluteContentBox();
- return IntPoint(rect.x(), inputContentBox.y() + (inputContentBox.height() - rect.height() + 1) / 2);
+ // Make sure the scaled decoration stays square and will fit in its parent's box.
+ int iconSize = std::min(inputContentBox.width(), std::min(inputContentBox.height(), rect.height()));
+ IntRect scaledRect(rect.x(), inputContentBox.y() + (inputContentBox.height() - iconSize + 1) / 2, iconSize, iconSize);
+ return scaledRect;
}
bool RenderThemeGtk::paintSearchFieldResultsDecoration(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
+ IntRect iconRect = centerRectVerticallyInParentInputElement(renderObject, rect);
+ if (iconRect.isEmpty())
+ return false;
+
GRefPtr<GdkPixbuf> icon = getStockIcon(GTK_TYPE_ENTRY, GTK_STOCK_FIND,
gtkTextDirection(renderObject->style()->direction()),
- gtkIconState(this, renderObject), GTK_ICON_SIZE_MENU);
- paintGdkPixbuf(paintInfo.context, icon.get(), centerRectVerticallyInParentInputElement(renderObject, rect));
+ gtkIconState(this, renderObject),
+ getIconSizeForPixelSize(rect.height()));
+ paintGdkPixbuf(paintInfo.context, icon.get(), iconRect);
return false;
}
void RenderThemeGtk::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
- style->resetBorder();
- style->resetPadding();
-
- gint width = 0, height = 0;
- gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
- style->setWidth(Length(width, Fixed));
- style->setHeight(Length(height, Fixed));
+ adjustSearchFieldIconStyle(style);
}
bool RenderThemeGtk::paintSearchFieldCancelButton(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
+ IntRect iconRect = centerRectVerticallyInParentInputElement(renderObject, rect);
+ if (iconRect.isEmpty())
+ return false;
+
GRefPtr<GdkPixbuf> icon = getStockIcon(GTK_TYPE_ENTRY, GTK_STOCK_CLEAR,
gtkTextDirection(renderObject->style()->direction()),
- gtkIconState(this, renderObject), GTK_ICON_SIZE_MENU);
- paintGdkPixbuf(paintInfo.context, icon.get(), centerRectVerticallyInParentInputElement(renderObject, rect));
+ gtkIconState(this, renderObject),
+ getIconSizeForPixelSize(rect.height()));
+ paintGdkPixbuf(paintInfo.context, icon.get(), iconRect);
return false;
}
@@ -316,14 +368,21 @@ bool RenderThemeGtk::paintCapsLockIndicator(RenderObject* renderObject, const Pa
if (paintInfo.context->paintingDisabled())
return true;
+ int iconSize = std::min(rect.width(), rect.height());
GRefPtr<GdkPixbuf> icon = getStockIcon(GTK_TYPE_ENTRY, GTK_STOCK_CAPS_LOCK_WARNING,
gtkTextDirection(renderObject->style()->direction()),
- gtkIconState(this, renderObject), GTK_ICON_SIZE_MENU);
+ 0, getIconSizeForPixelSize(iconSize));
+
+ // Only re-scale the icon when it's smaller than the minimum icon size.
+ if (iconSize >= gtkIconSizeMenu)
+ iconSize = gdk_pixbuf_get_height(icon.get());
// GTK+ locates the icon right aligned in the entry. The given rectangle is already
// centered vertically by RenderTextControlSingleLine.
- IntPoint iconPosition(rect.x() + rect.width() - gdk_pixbuf_get_width(icon.get()), rect.y());
- paintGdkPixbuf(paintInfo.context, icon.get(), iconPosition);
+ IntRect iconRect(rect.x() + rect.width() - iconSize,
+ rect.y() + (rect.height() - iconSize) / 2,
+ iconSize, iconSize);
+ paintGdkPixbuf(paintInfo.context, icon.get(), iconRect);
return true;
}
@@ -421,10 +480,11 @@ bool RenderThemeGtk::paintMediaButton(RenderObject* renderObject, GraphicsContex
gtkTextDirection(renderObject->style()->direction()),
gtkIconState(this, renderObject),
getMediaButtonIconSize(m_mediaIconSize));
- IntPoint iconPoint(rect.x() + (rect.width() - m_mediaIconSize) / 2,
- rect.y() + (rect.height() - m_mediaIconSize) / 2);
+ IntRect iconRect(rect.x() + (rect.width() - m_mediaIconSize) / 2,
+ rect.y() + (rect.height() - m_mediaIconSize) / 2,
+ m_mediaIconSize, m_mediaIconSize);
context->fillRect(FloatRect(rect), m_panelColor, ColorSpaceDeviceRGB);
- paintGdkPixbuf(context, icon.get(), iconPoint);
+ paintGdkPixbuf(context, icon.get(), iconRect);
return false;
}
diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk.h b/Source/WebCore/platform/gtk/RenderThemeGtk.h
index 5765782..f5e03a9 100644
--- a/Source/WebCore/platform/gtk/RenderThemeGtk.h
+++ b/Source/WebCore/platform/gtk/RenderThemeGtk.h
@@ -31,11 +31,8 @@
#include "GRefPtr.h"
#include "RenderTheme.h"
-#ifdef GTK_API_VERSION_2
-#include "gtkdrawing.h"
-#endif
-
typedef gulong GType;
+typedef struct _GdkColormap GdkColormap;
namespace WebCore {
@@ -92,7 +89,8 @@ public:
#endif
#ifdef GTK_API_VERSION_2
- GtkWidget* gtkScrollbar();
+ GtkWidget* gtkVScrollbar() const;
+ GtkWidget* gtkHScrollbar() const;
static void getIndicatorMetrics(ControlPart, int& indicatorSize, int& indicatorSpacing);
#else
GtkStyleContext* gtkScrollbarStyle();
@@ -171,6 +169,9 @@ protected:
virtual bool paintCapsLockIndicator(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&);
+
private:
void platformInit();
static void setTextInputBorders(RenderStyle*);
@@ -195,12 +196,10 @@ private:
#ifdef GTK_API_VERSION_2
void setupWidgetAndAddToContainer(GtkWidget*, GtkWidget*) const;
- bool paintRenderObject(GtkThemeWidgetType, RenderObject*, GraphicsContext*, const IntRect&, int flags = 0);
void refreshComboBoxChildren() const;
void getComboBoxPadding(RenderStyle*, int& left, int& top, int& right, int& bottom) const;
int getComboBoxSeparatorWidth() const;
int comboBoxArrowSize(RenderStyle*) const;
- GtkThemeParts m_themeParts;
GtkWidget* gtkButton() const;
GtkWidget* gtkEntry() const;
@@ -216,6 +215,7 @@ private:
GtkWidget* gtkComboBoxArrow() const;
GtkWidget* gtkComboBoxSeparator() const;
+ GdkColormap* m_colormap;
mutable GtkWidget* m_gtkWindow;
mutable GtkWidget* m_gtkContainer;
mutable GtkWidget* m_gtkButton;
@@ -230,6 +230,8 @@ private:
mutable GtkWidget* m_gtkComboBoxButton;
mutable GtkWidget* m_gtkComboBoxArrow;
mutable GtkWidget* m_gtkComboBoxSeparator;
+ mutable GtkWidget* m_gtkVScrollbar;
+ mutable GtkWidget* m_gtkHScrollbar;
bool m_themePartsHaveRGBAColormap;
friend class WidgetRenderingContext;
#endif
diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk2.cpp b/Source/WebCore/platform/gtk/RenderThemeGtk2.cpp
index de4195d..534aa97 100644
--- a/Source/WebCore/platform/gtk/RenderThemeGtk2.cpp
+++ b/Source/WebCore/platform/gtk/RenderThemeGtk2.cpp
@@ -41,7 +41,6 @@
#include "TextDirection.h"
#include "UserAgentStyleSheets.h"
#include "WidgetRenderingContext.h"
-#include "gtkdrawing.h"
#include <gdk/gdk.h>
#include <gtk/gtk.h>
@@ -50,7 +49,6 @@ namespace WebCore {
// This is not a static method, because we want to avoid having GTK+ headers in RenderThemeGtk.h.
extern GtkTextDirection gtkTextDirection(TextDirection);
-static int mozGtkRefCount = 0;
void RenderThemeGtk::platformInit()
{
m_themePartsHaveRGBAColormap = true;
@@ -68,30 +66,18 @@ void RenderThemeGtk::platformInit()
m_gtkComboBoxButton = 0;
m_gtkComboBoxArrow = 0;
m_gtkComboBoxSeparator = 0;
+ m_gtkVScrollbar = 0;
+ m_gtkHScrollbar = 0;
- memset(&m_themeParts, 0, sizeof(GtkThemeParts));
- GdkColormap* colormap = gdk_screen_get_rgba_colormap(gdk_screen_get_default());
- if (!colormap) {
+ m_colormap = gdk_screen_get_rgba_colormap(gdk_screen_get_default());
+ if (!m_colormap) {
m_themePartsHaveRGBAColormap = false;
- colormap = gdk_screen_get_default_colormap(gdk_screen_get_default());
+ m_colormap = gdk_screen_get_default_colormap(gdk_screen_get_default());
}
- m_themeParts.colormap = colormap;
-
- // Initialize the Mozilla theme drawing code.
- if (!mozGtkRefCount) {
- moz_gtk_init();
- moz_gtk_use_theme_parts(&m_themeParts);
- }
- ++mozGtkRefCount;
}
RenderThemeGtk::~RenderThemeGtk()
{
- --mozGtkRefCount;
-
- if (!mozGtkRefCount)
- moz_gtk_shutdown();
-
if (m_gtkWindow)
gtk_widget_destroy(m_gtkWindow);
}
@@ -147,34 +133,6 @@ static GtkStateType getGtkStateType(RenderThemeGtk* theme, RenderObject* object)
return GTK_STATE_NORMAL;
}
-bool RenderThemeGtk::paintRenderObject(GtkThemeWidgetType type, RenderObject* renderObject, GraphicsContext* context, const IntRect& rect, int flags)
-{
- // Painting is disabled so just claim to have succeeded
- if (context->paintingDisabled())
- return false;
-
- GtkWidgetState widgetState;
- widgetState.active = isPressed(renderObject);
- widgetState.focused = isFocused(renderObject);
-
- // https://bugs.webkit.org/show_bug.cgi?id=18364
- // The Mozilla theme drawing code, only paints a button as pressed when it's pressed
- // while hovered. Until we move away from the Mozila code, work-around the issue by
- // forcing a pressed button into the hovered state. This ensures that buttons activated
- // via the keyboard have the proper rendering.
- widgetState.inHover = isHovered(renderObject) || (type == MOZ_GTK_BUTTON && isPressed(renderObject));
-
- // FIXME: Disabled does not always give the correct appearance for ReadOnly
- widgetState.disabled = !isEnabled(renderObject) || isReadOnlyControl(renderObject);
- widgetState.isDefault = false;
- widgetState.canDefault = false;
- widgetState.depressed = false;
-
- WidgetRenderingContext widgetContext(context, rect);
- return !widgetContext.paintMozillaWidget(type, &widgetState, flags,
- gtkTextDirection(renderObject->style()->direction()));
-}
-
static void setToggleSize(const RenderThemeGtk* theme, RenderStyle* style, GtkWidget* widget)
{
// The width and height are both specified, so we shouldn't change them.
@@ -608,6 +566,15 @@ bool RenderThemeGtk::paintProgressBar(RenderObject* renderObject, const PaintInf
}
#endif
+void RenderThemeGtk::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+{
+}
+
+bool RenderThemeGtk::paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&)
+{
+ return true;
+}
+
GRefPtr<GdkPixbuf> RenderThemeGtk::getStockIcon(GType widgetType, const char* iconName, gint direction, gint state, gint iconSize)
{
ASSERT(widgetType == GTK_TYPE_CONTAINER || widgetType == GTK_TYPE_ENTRY);
@@ -708,7 +675,7 @@ GtkWidget* RenderThemeGtk::gtkContainer() const
return m_gtkContainer;
m_gtkWindow = gtk_window_new(GTK_WINDOW_POPUP);
- gtk_widget_set_colormap(m_gtkWindow, m_themeParts.colormap);
+ gtk_widget_set_colormap(m_gtkWindow, m_colormap);
setupWidget(m_gtkWindow);
gtk_widget_set_name(m_gtkWindow, "MozillaGtkWidget");
@@ -882,9 +849,22 @@ GtkWidget* RenderThemeGtk::gtkComboBoxSeparator() const
return m_gtkComboBoxSeparator;
}
-GtkWidget* RenderThemeGtk::gtkScrollbar()
+GtkWidget* RenderThemeGtk::gtkHScrollbar() const
+{
+ if (m_gtkHScrollbar)
+ return m_gtkHScrollbar;
+ m_gtkHScrollbar = gtk_hscrollbar_new(0);
+ setupWidgetAndAddToContainer(m_gtkHScrollbar, gtkContainer());
+ return m_gtkHScrollbar;
+}
+
+GtkWidget* RenderThemeGtk::gtkVScrollbar() const
{
- return moz_gtk_get_scrollbar_widget();
+ if (m_gtkVScrollbar)
+ return m_gtkVScrollbar;
+ m_gtkVScrollbar = gtk_vscrollbar_new(0);
+ setupWidgetAndAddToContainer(m_gtkVScrollbar, gtkContainer());
+ return m_gtkVScrollbar;
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp b/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp
index 1a9f445..7fa0f04 100644
--- a/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp
+++ b/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp
@@ -45,6 +45,8 @@ namespace WebCore {
// This is the default value defined by GTK+, where it was defined as MIN_ARROW_SIZE in gtkarrow.c.
static const int minArrowSize = 15;
+// This is the default value defined by GTK+, where it was defined as MIN_ARROW_WIDTH in gtkspinbutton.c.
+static const int minSpinButtonArrowSize = 6;
typedef HashMap<GType, GRefPtr<GtkStyleContext> > StyleContextMap;
static StyleContextMap& styleContextMap();
@@ -543,7 +545,7 @@ bool RenderThemeGtk::paintMenuList(RenderObject* renderObject, const PaintInfo&
cairo_clip(cairoContext);
gtk_render_line(separatorStyleContext, cairoContext,
separatorPosition.x(), separatorPosition.y(),
- separatorPosition.x(), innerRect.bottom());
+ separatorPosition.x(), innerRect.maxY());
cairo_restore(cairoContext);
}
@@ -720,6 +722,117 @@ bool RenderThemeGtk::paintProgressBar(RenderObject* renderObject, const PaintInf
}
#endif
+static gint spinButtonArrowSize(GtkStyleContext* context)
+{
+ const PangoFontDescription* fontDescription = gtk_style_context_get_font(context, static_cast<GtkStateFlags>(0));
+ gint fontSize = pango_font_description_get_size(fontDescription);
+ gint arrowSize = max(PANGO_PIXELS(fontSize), minSpinButtonArrowSize);
+
+ return arrowSize - arrowSize % 2; // Force even.
+}
+
+void RenderThemeGtk::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ GtkStyleContext* context = getStyleContext(GTK_TYPE_SPIN_BUTTON);
+
+ GtkBorder padding;
+ gtk_style_context_get_padding(context, static_cast<GtkStateFlags>(0), &padding);
+
+ int width = spinButtonArrowSize(context) + padding.left + padding.right;
+ style->setWidth(Length(width, Fixed));
+ style->setMinWidth(Length(width, Fixed));
+}
+
+static void paintSpinArrowButton(RenderTheme* theme, GtkStyleContext* context, RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect, GtkArrowType arrowType)
+{
+ ASSERT(arrowType == GTK_ARROW_UP || arrowType == GTK_ARROW_DOWN);
+
+ gtk_style_context_save(context);
+ gtk_style_context_add_class(context, GTK_STYLE_CLASS_BUTTON);
+
+ GtkTextDirection direction = gtk_style_context_get_direction(context);
+ guint state = static_cast<guint>(gtk_style_context_get_state(context));
+ if (!(state & GTK_STATE_FLAG_INSENSITIVE)) {
+ if (theme->isPressed(renderObject)) {
+ if ((arrowType == GTK_ARROW_UP && theme->isSpinUpButtonPartPressed(renderObject))
+ || (arrowType == GTK_ARROW_DOWN && !theme->isSpinUpButtonPartPressed(renderObject)))
+ state |= GTK_STATE_FLAG_ACTIVE;
+ } else if (theme->isHovered(renderObject)) {
+ if ((arrowType == GTK_ARROW_UP && theme->isSpinUpButtonPartHovered(renderObject))
+ || (arrowType == GTK_ARROW_DOWN && !theme->isSpinUpButtonPartHovered(renderObject)))
+ state |= GTK_STATE_FLAG_PRELIGHT;
+ }
+ }
+ gtk_style_context_set_state(context, static_cast<GtkStateFlags>(state));
+
+ // Paint button.
+ IntRect buttonRect(rect);
+ guint junction = gtk_style_context_get_junction_sides(context);
+ if (arrowType == GTK_ARROW_UP)
+ junction |= GTK_JUNCTION_BOTTOM;
+ else {
+ junction |= GTK_JUNCTION_TOP;
+ buttonRect.move(0, rect.height() / 2);
+ }
+ buttonRect.setHeight(rect.height() / 2);
+ gtk_style_context_set_junction_sides(context, static_cast<GtkJunctionSides>(junction));
+
+ gtk_render_background(context, paintInfo.context->platformContext(), buttonRect.x(), buttonRect.y(), buttonRect.width(), buttonRect.height());
+ gtk_render_frame(context, paintInfo.context->platformContext(), buttonRect.x(), buttonRect.y(), buttonRect.width(), buttonRect.height());
+
+ // Paint arrow centered inside button.
+ // This code is based on gtkspinbutton.c code.
+ IntRect arrowRect;
+ gdouble angle;
+ if (arrowType == GTK_ARROW_UP) {
+ angle = 0;
+ arrowRect.setY(rect.y());
+ arrowRect.setHeight(rect.height() / 2 - 2);
+ } else {
+ angle = G_PI;
+ arrowRect.setY(rect.y() + buttonRect.y());
+ arrowRect.setHeight(rect.height() - arrowRect.y() - 2);
+ }
+ arrowRect.setWidth(rect.width() - 3);
+ if (direction == GTK_TEXT_DIR_LTR)
+ arrowRect.setX(rect.x() + 1);
+ else
+ arrowRect.setX(rect.x() + 2);
+
+ gint width = arrowRect.width() / 2;
+ width -= width % 2 - 1; // Force odd.
+ gint height = (width + 1) / 2;
+
+ arrowRect.move((arrowRect.width() - width) / 2, (arrowRect.height() - height) / 2);
+ gtk_render_arrow(context, paintInfo.context->platformContext(), angle, arrowRect.x(), arrowRect.y(), width);
+
+ gtk_style_context_restore(context);
+}
+
+bool RenderThemeGtk::paintInnerSpinButton(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ GtkStyleContext* context = getStyleContext(GTK_TYPE_SPIN_BUTTON);
+ gtk_style_context_save(context);
+
+ GtkTextDirection direction = static_cast<GtkTextDirection>(gtkTextDirection(renderObject->style()->direction()));
+ gtk_style_context_set_direction(context, direction);
+
+ guint flags = 0;
+ if (!isEnabled(renderObject) || isReadOnlyControl(renderObject))
+ flags |= GTK_STATE_FLAG_INSENSITIVE;
+ else if (isFocused(renderObject))
+ flags |= GTK_STATE_FLAG_FOCUSED;
+ gtk_style_context_set_state(context, static_cast<GtkStateFlags>(flags));
+ gtk_style_context_remove_class(context, GTK_STYLE_CLASS_ENTRY);
+
+ paintSpinArrowButton(this, context, renderObject, paintInfo, rect, GTK_ARROW_UP);
+ paintSpinArrowButton(this, context, renderObject, paintInfo, rect, GTK_ARROW_DOWN);
+
+ gtk_style_context_restore(context);
+
+ return false;
+}
+
GRefPtr<GdkPixbuf> RenderThemeGtk::getStockIcon(GType widgetType, const char* iconName, gint direction, gint state, gint iconSize)
{
GtkStyleContext* context = getStyleContext(widgetType);
diff --git a/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp b/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp
index cb9b0f8..7f7c269 100644
--- a/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp
+++ b/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp
@@ -228,9 +228,10 @@ bool ScrollbarThemeGtk::paint(Scrollbar* scrollbar, GraphicsContext* graphicsCon
scrollMask |= ThumbPart;
}
- paintScrollbarBackground(graphicsContext, scrollbar);
-
- if (scrollMask & TrackBGPart)
+ ScrollbarControlPartMask allButtons = BackButtonStartPart | BackButtonEndPart
+ | ForwardButtonStartPart | ForwardButtonEndPart;
+ if (scrollMask & TrackBGPart || scrollMask & ThumbPart || scrollMask & allButtons)
+ paintScrollbarBackground(graphicsContext, scrollbar);
paintTrackBackground(graphicsContext, scrollbar, trackPaintRect);
// Paint the back and forward buttons.
diff --git a/Source/WebCore/platform/gtk/ScrollbarThemeGtk2.cpp b/Source/WebCore/platform/gtk/ScrollbarThemeGtk2.cpp
index 79295c1..1ab8850 100644
--- a/Source/WebCore/platform/gtk/ScrollbarThemeGtk2.cpp
+++ b/Source/WebCore/platform/gtk/ScrollbarThemeGtk2.cpp
@@ -28,12 +28,12 @@
#ifdef GTK_API_VERSION_2
+#include "GtkVersioning.h"
#include "PlatformMouseEvent.h"
#include "RenderThemeGtk.h"
#include "ScrollView.h"
#include "Scrollbar.h"
#include "WidgetRenderingContext.h"
-#include "gtkdrawing.h"
#include <gtk/gtk.h>
namespace WebCore {
@@ -46,107 +46,169 @@ static void gtkStyleSetCallback(GtkWidget* widget, GtkStyle* previous, Scrollbar
ScrollbarThemeGtk::ScrollbarThemeGtk()
{
updateThemeProperties();
- g_signal_connect(static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get())->gtkScrollbar(),
+ g_signal_connect(static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get())->gtkHScrollbar(),
"style-set", G_CALLBACK(gtkStyleSetCallback), this);
}
void ScrollbarThemeGtk::updateThemeProperties()
{
- MozGtkScrollbarMetrics metrics;
- moz_gtk_get_scrollbar_metrics(&metrics);
-
- m_thumbFatness = metrics.slider_width;
- m_troughBorderWidth = metrics.trough_border;
- m_stepperSize = metrics.stepper_size;
- m_stepperSpacing = metrics.stepper_spacing;
- m_minThumbLength = metrics.min_slider_size;
- m_troughUnderSteppers = metrics.trough_under_steppers;
- m_hasForwardButtonStartPart = metrics.has_secondary_forward_stepper;
- m_hasBackButtonEndPart = metrics.has_secondary_backward_stepper;
-
+ GtkWidget* scrollbar = static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get())->gtkHScrollbar();
+ gtk_widget_style_get(scrollbar,
+ "slider_width", &m_thumbFatness,
+ "trough_border", &m_troughBorderWidth,
+ "stepper-size", &m_stepperSize,
+ "trough-under-steppers", &m_troughUnderSteppers,
+ "has-secondary-forward-stepper", &m_hasForwardButtonStartPart,
+ "has-secondary-backward-stepper", &m_hasBackButtonEndPart, NULL);
+ m_minThumbLength = gtk_range_get_min_slider_size(GTK_RANGE(scrollbar));
updateScrollbarsFrameThickness();
}
-void ScrollbarThemeGtk::paintTrackBackground(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
+static GtkWidget* getWidgetForScrollbar(Scrollbar* scrollbar)
{
- GtkWidgetState state;
- state.focused = FALSE;
- state.isDefault = FALSE;
- state.canDefault = FALSE;
- state.disabled = FALSE;
- state.active = FALSE;
- state.inHover = FALSE;
+ RenderThemeGtk* theme = static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get());
+ return scrollbar->orientation() == VerticalScrollbar ? theme->gtkVScrollbar() : theme->gtkHScrollbar();
+}
+void ScrollbarThemeGtk::paintTrackBackground(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
+{
// Paint the track background. If the trough-under-steppers property is true, this
// should be the full size of the scrollbar, but if is false, it should only be the
// track rect.
- IntRect fullScrollbarRect = rect;
+ IntRect fullScrollbarRect(rect);
if (m_troughUnderSteppers)
fullScrollbarRect = IntRect(scrollbar->x(), scrollbar->y(), scrollbar->width(), scrollbar->height());
- GtkThemeWidgetType type = scrollbar->orientation() == VerticalScrollbar ? MOZ_GTK_SCROLLBAR_TRACK_VERTICAL : MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL;
WidgetRenderingContext widgetContext(context, fullScrollbarRect);
- widgetContext.paintMozillaWidget(type, &state, 0);
+ IntRect paintRect(IntPoint(), fullScrollbarRect.size());
+ widgetContext.gtkPaintBox(paintRect, getWidgetForScrollbar(scrollbar),
+ GTK_STATE_ACTIVE, GTK_SHADOW_IN, "trough");
}
void ScrollbarThemeGtk::paintScrollbarBackground(GraphicsContext* context, Scrollbar* scrollbar)
{
- // This is unused by the moz_gtk_scrollecd_window_paint.
- GtkWidgetState state;
IntRect fullScrollbarRect = IntRect(scrollbar->x(), scrollbar->y(), scrollbar->width(), scrollbar->height());
+
WidgetRenderingContext widgetContext(context, fullScrollbarRect);
- widgetContext.paintMozillaWidget(MOZ_GTK_SCROLLED_WINDOW, &state, 0);
+ widgetContext.gtkPaintBox(fullScrollbarRect, getWidgetForScrollbar(scrollbar),
+ GTK_STATE_NORMAL, GTK_SHADOW_IN, "scrolled_window");
}
void ScrollbarThemeGtk::paintThumb(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
{
- GtkWidgetState state;
- state.focused = FALSE;
- state.isDefault = FALSE;
- state.canDefault = FALSE;
- state.disabled = FALSE;
- state.active = scrollbar->pressedPart() == ThumbPart;
- state.inHover = scrollbar->hoveredPart() == ThumbPart;
- state.maxpos = scrollbar->maximum();
- state.curpos = scrollbar->currentPos();
-
- GtkThemeWidgetType type = scrollbar->orientation() == VerticalScrollbar ? MOZ_GTK_SCROLLBAR_THUMB_VERTICAL : MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL;
+ GtkWidget* widget = getWidgetForScrollbar(scrollbar);
+ gboolean activateSlider;
+ gtk_widget_style_get(widget, "activate-slider", &activateSlider, NULL);
+
+ GtkStateType stateType = GTK_STATE_NORMAL;
+ GtkShadowType shadowType = GTK_SHADOW_OUT;
+ if (activateSlider && scrollbar->pressedPart() == ThumbPart) {
+ stateType = GTK_STATE_ACTIVE;
+ shadowType = GTK_SHADOW_IN;
+ } else if (scrollbar->pressedPart() == ThumbPart || scrollbar->hoveredPart() == ThumbPart)
+ stateType = GTK_STATE_PRELIGHT;
+
+ // The adjustment controls the rendering of the scrollbar thumb. If it's not set
+ // properly the theme may not draw the thumb borders properly.
+ GtkAdjustment* adjustment = gtk_range_get_adjustment(GTK_RANGE(widget));
+ gtk_adjustment_set_value(adjustment, scrollbar->currentPos());
+ gtk_adjustment_set_lower(adjustment, 0);
+ gtk_adjustment_set_upper(adjustment, scrollbar->maximum());
+
+ GtkOrientation orientation = GTK_ORIENTATION_HORIZONTAL;
+ if (scrollbar->orientation() == VerticalScrollbar) {
+ gtk_adjustment_set_page_size(adjustment, rect.height());
+ orientation = GTK_ORIENTATION_VERTICAL;
+ } else
+ gtk_adjustment_set_page_size(adjustment, rect.width());
+
WidgetRenderingContext widgetContext(context, rect);
- widgetContext.paintMozillaWidget(type, &state, 0);
+ IntRect sliderRect(IntPoint(), rect.size());
+ widgetContext.gtkPaintSlider(sliderRect, widget, stateType, shadowType, "slider", orientation);
}
void ScrollbarThemeGtk::paintButton(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart part)
{
- int flags = 0;
- if (scrollbar->orientation() == VerticalScrollbar)
- flags |= MOZ_GTK_STEPPER_VERTICAL;
-
- if (part == ForwardButtonEndPart)
- flags |= (MOZ_GTK_STEPPER_DOWN | MOZ_GTK_STEPPER_BOTTOM);
- if (part == ForwardButtonStartPart)
- flags |= MOZ_GTK_STEPPER_DOWN;
-
- GtkWidgetState state;
- state.focused = TRUE;
- state.isDefault = TRUE;
- state.canDefault = TRUE;
- state.depressed = FALSE;
+ // The buttons will be disabled if the thumb is as the appropriate extreme.
+ GtkShadowType shadowType = GTK_SHADOW_OUT;
+ GtkStateType stateType = GTK_STATE_INSENSITIVE;
+ bool pressed = (part == scrollbar->pressedPart());
if ((BackButtonStartPart == part && scrollbar->currentPos())
|| (BackButtonEndPart == part && scrollbar->currentPos())
|| (ForwardButtonEndPart == part && scrollbar->currentPos() != scrollbar->maximum())
|| (ForwardButtonStartPart == part && scrollbar->currentPos() != scrollbar->maximum())) {
- state.disabled = FALSE;
- state.active = part == scrollbar->pressedPart();
- state.inHover = part == scrollbar->hoveredPart();
+ stateType = GTK_STATE_NORMAL;
+ if (pressed) {
+ stateType = GTK_STATE_ACTIVE;
+ shadowType = GTK_SHADOW_IN;
+ } else if (part == scrollbar->hoveredPart())
+ stateType = GTK_STATE_PRELIGHT;
+ }
+
+ // Themes determine how to draw the button (which button to draw) based on the allocation
+ // of the widget. Where the target rect is in relation to the total widget allocation
+ // determines the button.
+ ScrollbarOrientation orientation = scrollbar->orientation();
+ int buttonSize = (orientation == VerticalScrollbar) ? rect.height() : rect.width();
+ int totalAllocation = buttonSize * 5; // One space for each button and one extra.
+ int buttonOffset = 0;
+ if (ForwardButtonStartPart == part)
+ buttonOffset = buttonSize;
+ else if (BackButtonEndPart == part)
+ buttonOffset = 3 * buttonSize;
+ else if (ForwardButtonEndPart == part)
+ buttonOffset = 4 * buttonSize;
+
+ // Now we want the allocation to be relative to the origin of the painted rect.
+ GtkWidget* widget = getWidgetForScrollbar(scrollbar);
+ GtkAllocation allocation;
+ gtk_widget_get_allocation(widget, &allocation);
+ allocation.x = allocation.y = 0;
+ allocation.width = rect.width();
+ allocation.height = rect.height();
+
+ if (orientation == VerticalScrollbar) {
+ allocation.height = totalAllocation;
+ allocation.y -= buttonOffset;
} else {
- state.disabled = TRUE;
- state.active = FALSE;
- state.inHover = FALSE;
+ allocation.width = totalAllocation;
+ allocation.x -= buttonOffset;
}
+ gtk_widget_set_allocation(widget, &allocation);
+ const char* detail = orientation == VerticalScrollbar ? "vscrollbar" : "hscrollbar";
WidgetRenderingContext widgetContext(context, rect);
- widgetContext.paintMozillaWidget(MOZ_GTK_SCROLLBAR_BUTTON, &state, flags);
+
+ IntRect buttonRect(IntPoint(), rect.size());
+ widgetContext.gtkPaintBox(buttonRect, widget, stateType, shadowType, detail);
+
+ float arrowScaling;
+ gtk_widget_style_get(widget, "arrow-scaling", &arrowScaling, NULL);
+ IntSize arrowSize = rect.size();
+ arrowSize.scale(arrowScaling);
+ IntRect arrowRect(IntPoint(buttonRect.x() + (buttonRect.width() - arrowSize.width()) / 2,
+ buttonRect.y() + (buttonRect.height() - arrowSize.height()) / 2),
+ arrowSize);
+ if (pressed) {
+ int arrowDisplacementX, arrowDisplacementY;
+ gtk_widget_style_get(widget,
+ "arrow-displacement-x", &arrowDisplacementX,
+ "arrow-displacement-y", &arrowDisplacementY,
+ NULL);
+ arrowRect.move(arrowDisplacementX, arrowDisplacementY);
+ }
+
+ GtkArrowType arrowType = GTK_ARROW_DOWN;
+ if (orientation == VerticalScrollbar) {
+ if (part == BackButtonEndPart || part == BackButtonStartPart)
+ arrowType = GTK_ARROW_UP;
+ } else if (orientation == HorizontalScrollbar) {
+ arrowType = GTK_ARROW_RIGHT;
+ if (part == BackButtonEndPart || part == BackButtonStartPart)
+ arrowType = GTK_ARROW_LEFT;
+ }
+ widgetContext.gtkPaintArrow(arrowRect, widget, stateType, shadowType, arrowType, detail);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/gtk/WidgetRenderingContext.cpp b/Source/WebCore/platform/gtk/WidgetRenderingContext.cpp
index 51b32ea..9e640f6 100644
--- a/Source/WebCore/platform/gtk/WidgetRenderingContext.cpp
+++ b/Source/WebCore/platform/gtk/WidgetRenderingContext.cpp
@@ -103,8 +103,8 @@ WidgetRenderingContext::WidgetRenderingContext(GraphicsContext* graphicsContext,
width = (1 + (width >> 5)) << 5;
height = (1 + (height >> 5)) << 5;
- gScratchBuffer = gdk_pixmap_new(0, width, height, gdk_colormap_get_visual(theme->m_themeParts.colormap)->depth);
- gdk_drawable_set_colormap(gScratchBuffer, theme->m_themeParts.colormap);
+ gScratchBuffer = gdk_pixmap_new(0, width, height, gdk_colormap_get_visual(theme->m_colormap)->depth);
+ gdk_drawable_set_colormap(gScratchBuffer, theme->m_colormap);
}
m_target = gScratchBuffer;
@@ -143,19 +143,19 @@ WidgetRenderingContext::~WidgetRenderingContext()
scheduleScratchBufferPurge();
}
-bool WidgetRenderingContext::paintMozillaWidget(GtkThemeWidgetType type, GtkWidgetState* state, int flags, GtkTextDirection textDirection)
-{
- // Sometimes moz_gtk_widget_paint modifies the clipping rectangle, so we must use a copy.
- GdkRectangle clipRect = m_paintRect;
- m_hadError = moz_gtk_widget_paint(type, m_target, &clipRect, &m_paintRect,
- state, flags, textDirection) != MOZ_GTK_SUCCESS;
- return !m_hadError;
-}
-
void WidgetRenderingContext::gtkPaintBox(const IntRect& rect, GtkWidget* widget, GtkStateType stateType, GtkShadowType shadowType, const gchar* detail)
{
GdkRectangle paintRect = { m_paintRect.x + rect.x(), m_paintRect.y + rect.y(), rect.width(), rect.height() };
- gtk_paint_box(gtk_widget_get_style(widget), m_target, stateType, shadowType, &m_paintRect,
+
+ // Some widgets also need their allocation adjusted to account for extra space.
+ // Right now only scrollbar buttons have significant allocations.
+ GtkAllocation allocation;
+ gtk_widget_get_allocation(widget, &allocation);
+ allocation.x += m_paintRect.x;
+ allocation.y += m_paintRect.y;
+ gtk_widget_set_allocation(widget, &allocation);
+
+ gtk_paint_box(gtk_widget_get_style(widget), m_target, stateType, shadowType, &paintRect,
widget, detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height);
}
diff --git a/Source/WebCore/platform/gtk/WidgetRenderingContext.h b/Source/WebCore/platform/gtk/WidgetRenderingContext.h
index e248f04..8639a98 100644
--- a/Source/WebCore/platform/gtk/WidgetRenderingContext.h
+++ b/Source/WebCore/platform/gtk/WidgetRenderingContext.h
@@ -25,7 +25,11 @@
#ifdef GTK_API_VERSION_2
#include "IntRect.h"
-#include "gtkdrawing.h"
+
+// Usually this is too expensive to have in headers, but GtkStateType GtkShadowType are
+// enums and cannot be forward declared. WidgetRenderingContext.h is currently only
+// included in RenderThemeGtk2.cpp and ScrollbarThemeGtk2.cpp.
+#include <gtk/gtk.h>
namespace WebCore {
@@ -37,7 +41,6 @@ public:
WidgetRenderingContext(GraphicsContext*, const IntRect&);
~WidgetRenderingContext();
- bool paintMozillaWidget(GtkThemeWidgetType, GtkWidgetState*, int flags, GtkTextDirection = GTK_TEXT_DIR_NONE);
void gtkPaintBox(const IntRect&, GtkWidget*, GtkStateType, GtkShadowType, const gchar*);
void gtkPaintFlatBox(const IntRect&, GtkWidget*, GtkStateType, GtkShadowType, const gchar*);
void gtkPaintFocus(const IntRect&, GtkWidget*, GtkStateType, const gchar*);
diff --git a/Source/WebCore/platform/gtk/gtk2drawing.c b/Source/WebCore/platform/gtk/gtk2drawing.c
deleted file mode 100644
index 3979b7f..0000000
--- a/Source/WebCore/platform/gtk/gtk2drawing.c
+++ /dev/null
@@ -1,552 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2002
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Brian Ryner <bryner@brianryner.com> (Original Author)
- * Pierre Chanial <p_ch@verizon.net>
- * Michael Ventnor <m.ventnor@gmail.com>
- * Alp Toker <alp@nuanti.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/*
- * This file contains painting functions for each of the gtk2 widgets.
- * Adapted from the gtkdrawing.c, and gtk+2.0 source.
- */
-
-#ifdef GTK_API_VERSION_2
-
-#undef GTK_DISABLE_DEPRECATED
-#undef GDK_DISABLE_DEPRECATED
-
-#include <gdk/gdkprivate.h>
-#include "gtkdrawing.h"
-#include "GtkVersioning.h"
-#include <math.h>
-#include <string.h>
-
-#define XTHICKNESS(style) (style->xthickness)
-#define YTHICKNESS(style) (style->ythickness)
-
-static GtkThemeParts *gParts = NULL;
-static style_prop_t style_prop_func;
-static gboolean is_initialized;
-
-void
-moz_gtk_use_theme_parts(GtkThemeParts* parts)
-{
- gParts = parts;
-}
-
-/* Because we have such an unconventional way of drawing widgets, signal to the GTK theme engine
- that they are drawing for Mozilla instead of a conventional GTK app so they can do any specific
- things they may want to do. */
-static void
-moz_gtk_set_widget_name(GtkWidget* widget)
-{
- gtk_widget_set_name(widget, "MozillaGtkWidget");
-}
-
-gint
-moz_gtk_enable_style_props(style_prop_t styleGetProp)
-{
- style_prop_func = styleGetProp;
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-ensure_window_widget()
-{
- if (!gParts->protoWindow) {
- gParts->protoWindow = gtk_window_new(GTK_WINDOW_POPUP);
-
- if (gParts->colormap)
- gtk_widget_set_colormap(gParts->protoWindow, gParts->colormap);
-
- gtk_widget_realize(gParts->protoWindow);
- moz_gtk_set_widget_name(gParts->protoWindow);
- }
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-setup_widget_prototype(GtkWidget* widget)
-{
- ensure_window_widget();
- if (!gParts->protoLayout) {
- gParts->protoLayout = gtk_fixed_new();
- gtk_container_add(GTK_CONTAINER(gParts->protoWindow), gParts->protoLayout);
- }
-
- gtk_container_add(GTK_CONTAINER(gParts->protoLayout), widget);
- gtk_widget_realize(widget);
- g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-ensure_scrollbar_widget()
-{
- if (!gParts->vertScrollbarWidget) {
- gParts->vertScrollbarWidget = gtk_vscrollbar_new(NULL);
- setup_widget_prototype(gParts->vertScrollbarWidget);
- }
- if (!gParts->horizScrollbarWidget) {
- gParts->horizScrollbarWidget = gtk_hscrollbar_new(NULL);
- setup_widget_prototype(gParts->horizScrollbarWidget);
- }
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-ensure_scrolled_window_widget()
-{
- if (!gParts->scrolledWindowWidget) {
- gParts->scrolledWindowWidget = gtk_scrolled_window_new(NULL, NULL);
- setup_widget_prototype(gParts->scrolledWindowWidget);
- }
- return MOZ_GTK_SUCCESS;
-}
-
-static GtkStateType
-ConvertGtkState(GtkWidgetState* state)
-{
- if (state->disabled)
- return GTK_STATE_INSENSITIVE;
- else if (state->depressed)
- return (state->inHover ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
- else if (state->inHover)
- return (state->active ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT);
- else
- return GTK_STATE_NORMAL;
-}
-
-static gint
-TSOffsetStyleGCArray(GdkGC** gcs, gint xorigin, gint yorigin)
-{
- int i;
- /* there are 5 gc's in each array, for each of the widget states */
- for (i = 0; i < 5; ++i)
- gdk_gc_set_ts_origin(gcs[i], xorigin, yorigin);
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-TSOffsetStyleGCs(GtkStyle* style, gint xorigin, gint yorigin)
-{
- TSOffsetStyleGCArray(style->fg_gc, xorigin, yorigin);
- TSOffsetStyleGCArray(style->bg_gc, xorigin, yorigin);
- TSOffsetStyleGCArray(style->light_gc, xorigin, yorigin);
- TSOffsetStyleGCArray(style->dark_gc, xorigin, yorigin);
- TSOffsetStyleGCArray(style->mid_gc, xorigin, yorigin);
- TSOffsetStyleGCArray(style->text_gc, xorigin, yorigin);
- TSOffsetStyleGCArray(style->base_gc, xorigin, yorigin);
- gdk_gc_set_ts_origin(style->black_gc, xorigin, yorigin);
- gdk_gc_set_ts_origin(style->white_gc, xorigin, yorigin);
- return MOZ_GTK_SUCCESS;
-}
-
-gint
-moz_gtk_init()
-{
- GtkWidgetClass *entry_class;
-
- is_initialized = TRUE;
-
- /* Add style property to GtkEntry.
- * Adding the style property to the normal GtkEntry class means that it
- * will work without issues inside GtkComboBox and for Spinbuttons. */
- entry_class = g_type_class_ref(GTK_TYPE_ENTRY);
- gtk_widget_class_install_style_property(entry_class,
- g_param_spec_boolean("honors-transparent-bg-hint",
- "Transparent BG enabling flag",
- "If TRUE, the theme is able to draw the GtkEntry on non-prefilled background.",
- FALSE,
- G_PARAM_READWRITE));
-
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-moz_gtk_scrolled_window_paint(GdkDrawable* drawable, GdkRectangle* rect,
- GdkRectangle* cliprect, GtkWidgetState* state)
-{
- GtkStyle* style;
- GtkAllocation allocation;
- GtkWidget* widget;
-
- ensure_scrolled_window_widget();
- widget = gParts->scrolledWindowWidget;
-
- gtk_widget_get_allocation(widget, &allocation);
- allocation.x = rect->x;
- allocation.y = rect->y;
- allocation.width = rect->width;
- allocation.height = rect->height;
- gtk_widget_set_allocation(widget, &allocation);
-
- style = gtk_widget_get_style(widget);
- TSOffsetStyleGCs(style, rect->x - 1, rect->y - 1);
- gtk_paint_shadow(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
- cliprect, gParts->scrolledWindowWidget, "scrolled_window",
- rect->x, rect->y, rect->width, rect->height);
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-moz_gtk_scrollbar_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
- GdkRectangle* cliprect, GtkWidgetState* state,
- GtkScrollbarButtonFlags flags,
- GtkTextDirection direction)
-{
- GtkStateType state_type = ConvertGtkState(state);
- GtkShadowType shadow_type = (state->active) ?
- GTK_SHADOW_IN : GTK_SHADOW_OUT;
- GdkRectangle arrow_rect;
- GtkStyle* style;
- GtkWidget *scrollbar;
- GtkAllocation allocation;
- GtkArrowType arrow_type;
- gint arrow_displacement_x, arrow_displacement_y;
- const char* detail = (flags & MOZ_GTK_STEPPER_VERTICAL) ?
- "vscrollbar" : "hscrollbar";
-
- ensure_scrollbar_widget();
-
- if (flags & MOZ_GTK_STEPPER_VERTICAL)
- scrollbar = gParts->vertScrollbarWidget;
- else
- scrollbar = gParts->horizScrollbarWidget;
-
- gtk_widget_set_direction(scrollbar, direction);
-
- /* Some theme engines (i.e., ClearLooks) check the scrollbar's allocation
- to determine where it should paint rounded corners on the buttons.
- We need to trick them into drawing the buttons the way we want them. */
-
- gtk_widget_get_allocation(scrollbar, &allocation);
- allocation.x = rect->x;
- allocation.y = rect->y;
- allocation.width = rect->width;
- allocation.height = rect->height;
-
- if (flags & MOZ_GTK_STEPPER_VERTICAL) {
- allocation.height *= 5;
- if (flags & MOZ_GTK_STEPPER_DOWN) {
- arrow_type = GTK_ARROW_DOWN;
- if (flags & MOZ_GTK_STEPPER_BOTTOM)
- allocation.y -= 4 * rect->height;
- else
- allocation.y -= rect->height;
-
- } else {
- arrow_type = GTK_ARROW_UP;
- if (flags & MOZ_GTK_STEPPER_BOTTOM)
- allocation.y -= 3 * rect->height;
- }
- } else {
- allocation.width *= 5;
- if (flags & MOZ_GTK_STEPPER_DOWN) {
- arrow_type = GTK_ARROW_RIGHT;
- if (flags & MOZ_GTK_STEPPER_BOTTOM)
- allocation.x -= 4 * rect->width;
- else
- allocation.x -= rect->width;
- } else {
- arrow_type = GTK_ARROW_LEFT;
- if (flags & MOZ_GTK_STEPPER_BOTTOM)
- allocation.x -= 3 * rect->width;
- }
- }
-
- gtk_widget_set_allocation(scrollbar, &allocation);
- style = gtk_widget_get_style(scrollbar);
-
- TSOffsetStyleGCs(style, rect->x, rect->y);
-
- gtk_paint_box(style, drawable, state_type, shadow_type, cliprect,
- scrollbar, detail, rect->x, rect->y,
- rect->width, rect->height);
-
- arrow_rect.width = rect->width / 2;
- arrow_rect.height = rect->height / 2;
- arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2;
- arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2;
-
- if (state_type == GTK_STATE_ACTIVE) {
- gtk_widget_style_get(scrollbar,
- "arrow-displacement-x", &arrow_displacement_x,
- "arrow-displacement-y", &arrow_displacement_y,
- NULL);
-
- arrow_rect.x += arrow_displacement_x;
- arrow_rect.y += arrow_displacement_y;
- }
-
- gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
- scrollbar, detail, arrow_type, TRUE, arrow_rect.x,
- arrow_rect.y, arrow_rect.width, arrow_rect.height);
-
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-moz_gtk_scrollbar_trough_paint(GtkThemeWidgetType widget,
- GdkDrawable* drawable, GdkRectangle* rect,
- GdkRectangle* cliprect, GtkWidgetState* state,
- GtkTextDirection direction)
-{
- GtkStyle* style;
- GtkScrollbar *scrollbar;
-
- ensure_scrollbar_widget();
-
- if (widget == MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL)
- scrollbar = GTK_SCROLLBAR(gParts->horizScrollbarWidget);
- else
- scrollbar = GTK_SCROLLBAR(gParts->vertScrollbarWidget);
-
- gtk_widget_set_direction(GTK_WIDGET(scrollbar), direction);
-
- style = gtk_widget_get_style(GTK_WIDGET(scrollbar));
-
- TSOffsetStyleGCs(style, rect->x, rect->y);
- gtk_paint_box(style, drawable, GTK_STATE_ACTIVE, GTK_SHADOW_IN, cliprect,
- GTK_WIDGET(scrollbar), "trough", rect->x, rect->y,
- rect->width, rect->height);
-
- if (state->focused) {
- gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect,
- GTK_WIDGET(scrollbar), "trough",
- rect->x, rect->y, rect->width, rect->height);
- }
-
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-moz_gtk_scrollbar_thumb_paint(GtkThemeWidgetType widget,
- GdkDrawable* drawable, GdkRectangle* rect,
- GdkRectangle* cliprect, GtkWidgetState* state,
- GtkTextDirection direction)
-{
- GtkStateType state_type = (state->inHover || state->active) ?
- GTK_STATE_PRELIGHT : GTK_STATE_NORMAL;
- GtkShadowType shadow_type = GTK_SHADOW_OUT;
- GtkStyle* style;
- GtkScrollbar *scrollbar;
- GtkAdjustment *adj;
- gboolean activate_slider;
-
- ensure_scrollbar_widget();
-
- if (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL)
- scrollbar = GTK_SCROLLBAR(gParts->horizScrollbarWidget);
- else
- scrollbar = GTK_SCROLLBAR(gParts->vertScrollbarWidget);
-
- gtk_widget_set_direction(GTK_WIDGET(scrollbar), direction);
-
- /* Make sure to set the scrollbar range before painting so that
- everything is drawn properly. At least the bluecurve (and
- maybe other) themes don't draw the top or bottom black line
- surrounding the scrollbar if the theme thinks that it's butted
- up against the scrollbar arrows. Note the increases of the
- clip rect below. */
- /* Changing the cliprect is pretty bogus. This lets themes draw
- outside the frame, which means we don't invalidate them
- correctly. See bug 297508. But some themes do seem to need
- it. So we modify the frame's overflow area to account for what
- we're doing here; see nsNativeThemeGTK::GetWidgetOverflow. */
- adj = gtk_range_get_adjustment(GTK_RANGE(scrollbar));
-
- if (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) {
- cliprect->x -= 1;
- cliprect->width += 2;
- gtk_adjustment_set_page_size(adj, rect->width);
- }
- else {
- cliprect->y -= 1;
- cliprect->height += 2;
- gtk_adjustment_set_page_size(adj, rect->height);
- }
-
-#if GTK_CHECK_VERSION(2, 14, 0)
- gtk_adjustment_configure(adj,
- state->curpos,
- 0,
- state->maxpos,
- gtk_adjustment_get_step_increment(adj),
- gtk_adjustment_get_page_increment(adj),
- gtk_adjustment_get_page_size(adj));
-#else
- adj->lower = 0;
- adj->value = state->curpos;
- adj->upper = state->maxpos;
- gtk_adjustment_changed(adj);
-#endif
-
- style = gtk_widget_get_style(GTK_WIDGET(scrollbar));
-
- gtk_widget_style_get(GTK_WIDGET(scrollbar), "activate-slider",
- &activate_slider, NULL);
-
- if (activate_slider && state->active) {
- shadow_type = GTK_SHADOW_IN;
- state_type = GTK_STATE_ACTIVE;
- }
-
- TSOffsetStyleGCs(style, rect->x, rect->y);
-
- gtk_paint_slider(style, drawable, state_type, shadow_type, cliprect,
- GTK_WIDGET(scrollbar), "slider", rect->x, rect->y,
- rect->width, rect->height,
- (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) ?
- GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL);
-
- return MOZ_GTK_SUCCESS;
-}
-
-gint
-moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
- gint* right, gint* bottom, GtkTextDirection direction,
- gboolean inhtml)
-{
- GtkWidget* w;
- GtkStyle *style;
-
- switch (widget) {
- /* These widgets have no borders, since they are not containers. */
- case MOZ_GTK_SCROLLBAR_BUTTON:
- case MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL:
- case MOZ_GTK_SCROLLBAR_TRACK_VERTICAL:
- case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
- case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
- *left = *top = *right = *bottom = 0;
- return MOZ_GTK_SUCCESS;
- default:
- g_warning("Unsupported widget type: %d", widget);
- return MOZ_GTK_UNKNOWN_WIDGET;
- }
-
- style = gtk_widget_get_style(w);
- *right = *left = XTHICKNESS(style);
- *bottom = *top = YTHICKNESS(style);
-
- return MOZ_GTK_SUCCESS;
-}
-
-gint
-moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics *metrics)
-{
- ensure_scrollbar_widget();
-
- gtk_widget_style_get (gParts->horizScrollbarWidget,
- "slider_width", &metrics->slider_width,
- "trough_border", &metrics->trough_border,
- "stepper_size", &metrics->stepper_size,
- "stepper_spacing", &metrics->stepper_spacing,
- "trough_under_steppers", &metrics->trough_under_steppers,
- "has_secondary_forward_stepper", &metrics->has_secondary_forward_stepper,
- "has_secondary_backward_stepper", &metrics->has_secondary_backward_stepper,
- NULL);
-
- metrics->min_slider_size = gtk_range_get_min_slider_size(GTK_RANGE(gParts->horizScrollbarWidget));
-
- return MOZ_GTK_SUCCESS;
-}
-
-gint
-moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
- GdkRectangle* rect, GdkRectangle* cliprect,
- GtkWidgetState* state, gint flags,
- GtkTextDirection direction)
-{
- switch (widget) {
- case MOZ_GTK_SCROLLBAR_BUTTON:
- return moz_gtk_scrollbar_button_paint(drawable, rect, cliprect, state,
- (GtkScrollbarButtonFlags) flags,
- direction);
- break;
- case MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL:
- case MOZ_GTK_SCROLLBAR_TRACK_VERTICAL:
- return moz_gtk_scrollbar_trough_paint(widget, drawable, rect,
- cliprect, state, direction);
- break;
- case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
- case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
- return moz_gtk_scrollbar_thumb_paint(widget, drawable, rect,
- cliprect, state, direction);
- break;
- case MOZ_GTK_SCROLLED_WINDOW:
- return moz_gtk_scrolled_window_paint(drawable, rect, cliprect, state);
- break;
- default:
- g_warning("Unknown widget type: %d", widget);
- }
-
- return MOZ_GTK_UNKNOWN_WIDGET;
-}
-
-GtkWidget* moz_gtk_get_scrollbar_widget(void)
-{
- if (!is_initialized)
- return NULL;
- ensure_scrollbar_widget();
- return gParts->horizScrollbarWidget;
-}
-
-gint
-moz_gtk_shutdown()
-{
- GtkWidgetClass *entry_class;
- entry_class = g_type_class_peek(GTK_TYPE_ENTRY);
- g_type_class_unref(entry_class);
-
- is_initialized = FALSE;
-
- return MOZ_GTK_SUCCESS;
-}
-
-void moz_gtk_destroy_theme_parts_widgets(GtkThemeParts* parts)
-{
- if (!parts)
- return;
-
- if (parts->protoWindow) {
- gtk_widget_destroy(parts->protoWindow);
- parts->protoWindow = NULL;
- }
-}
-
-#endif // GTK_API_VERSION_2
diff --git a/Source/WebCore/platform/gtk/gtkdrawing.h b/Source/WebCore/platform/gtk/gtkdrawing.h
deleted file mode 100644
index cdb343c..0000000
--- a/Source/WebCore/platform/gtk/gtkdrawing.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2002
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Brian Ryner <bryner@brianryner.com> (Original Author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/**
- * gtkdrawing.h: GTK widget rendering utilities
- *
- * gtkdrawing provides an API for rendering GTK widgets in the
- * current theme to a pixmap or window, without requiring an actual
- * widget instantiation, similar to the Macintosh Appearance Manager
- * or Windows XP's DrawThemeBackground() API.
- */
-
-#ifndef _GTK_DRAWING_H_
-#define _GTK_DRAWING_H_
-
-#undef GTK_DISABLE_DEPRECATED
-
-#include <gtk/gtk.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/*** type definitions ***/
-typedef struct {
- guint8 active;
- guint8 focused;
- guint8 inHover;
- guint8 disabled;
- guint8 isDefault;
- guint8 canDefault;
- /* The depressed state is for buttons which remain active for a longer period:
- * activated toggle buttons or buttons showing a popup menu. */
- guint8 depressed;
- gint32 curpos; /* curpos and maxpos are used for scrollbars */
- gint32 maxpos;
-} GtkWidgetState;
-
-typedef struct {
- gint slider_width;
- gint trough_border;
- gint stepper_size;
- gint stepper_spacing;
- gint min_slider_size;
- gboolean trough_under_steppers;
- gboolean has_secondary_forward_stepper;
- gboolean has_secondary_backward_stepper;
-} MozGtkScrollbarMetrics;
-
-typedef struct _GtkThemeParts {
- GdkColormap* colormap;
- GtkWidget* protoWindow;
- GtkWidget* protoLayout;
- GtkWidget* horizScrollbarWidget;
- GtkWidget* vertScrollbarWidget;
- GtkWidget* scrolledWindowWidget;
-} GtkThemeParts;
-
-typedef enum {
- MOZ_GTK_STEPPER_DOWN = 1 << 0,
- MOZ_GTK_STEPPER_BOTTOM = 1 << 1,
- MOZ_GTK_STEPPER_VERTICAL = 1 << 2
-} GtkScrollbarButtonFlags;
-
-/* function type for moz_gtk_enable_style_props */
-typedef gint (*style_prop_t)(GtkStyle*, const gchar*, gint);
-
-/*** result/error codes ***/
-#define MOZ_GTK_SUCCESS 0
-#define MOZ_GTK_UNKNOWN_WIDGET -1
-#define MOZ_GTK_UNSAFE_THEME -2
-
-/*** widget type constants ***/
-typedef enum {
- /* Paints a GtkButton. flags is a GtkReliefStyle. */
- MOZ_GTK_BUTTON,
- /**
- * Paints the button of a GtkScrollbar. flags is a GtkArrowType giving
- * the arrow direction.
- */
- MOZ_GTK_SCROLLBAR_BUTTON,
- /* Paints the trough (track) of a GtkScrollbar. */
- MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL,
- MOZ_GTK_SCROLLBAR_TRACK_VERTICAL,
- /* Paints the slider (thumb) of a GtkScrollbar. */
- MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL,
- MOZ_GTK_SCROLLBAR_THUMB_VERTICAL,
- /* Paints the background of a scrolled window */
- MOZ_GTK_SCROLLED_WINDOW,
-} GtkThemeWidgetType;
-
-/*** General library functions ***/
-/**
- * Initializes the drawing library. You must call this function
- * prior to using any other functionality.
- * returns: MOZ_GTK_SUCCESS if there were no errors
- * MOZ_GTK_UNSAFE_THEME if the current theme engine is known
- * to crash with gtkdrawing.
- */
-gint moz_gtk_init();
-
-/**
- * Instruct the drawing library to do all rendering based on
- * the given collection of theme parts. If any members of the
- * GtkThemeParts struct are NULL, they will be created lazily.
- */
-void
-moz_gtk_use_theme_parts(GtkThemeParts* parts);
-
-/**
- * Enable GTK+ 1.2.9+ theme enhancements. You must provide a pointer
- * to the GTK+ 1.2.9+ function "gtk_style_get_prop_experimental".
- * styleGetProp: pointer to gtk_style_get_prop_experimental
- *
- * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
- */
-gint moz_gtk_enable_style_props(style_prop_t styleGetProp);
-
-/**
- * Perform cleanup of the drawing library. You should call this function
- * when your program exits, or you no longer need the library.
- *
- * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
- */
-gint moz_gtk_shutdown();
-
-/**
- * Destroy the widgets in the given GtkThemeParts, which should
- * be destroyed before the GtkThemeParts can be freed.
- */
-void moz_gtk_destroy_theme_parts_widgets(GtkThemeParts* parts);
-
-/*** Widget drawing ***/
-/**
- * Paint a widget in the current theme.
- * widget: a constant giving the widget to paint
- * rect: the bounding rectangle for the widget
- * cliprect: a clipprect rectangle for this painting operation
- * state: the state of the widget. ignored for some widgets.
- * flags: widget-dependant flags; see the GtkThemeWidgetType definition.
- * direction: the text direction, to draw the widget correctly LTR and RTL.
- */
-gint
-moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
- GdkRectangle* rect, GdkRectangle* cliprect,
- GtkWidgetState* state, gint flags,
- GtkTextDirection direction);
-
-/*** Widget metrics ***/
-/**
- * Get the border size of a widget
- * left/right: [OUT] the widget's left/right border
- * top/bottom: [OUT] the widget's top/bottom border
- * direction: the text direction for the widget
- * inhtml: boolean indicating whether this widget will be drawn as a HTML form control,
- * in order to workaround a size issue (MOZ_GTK_BUTTON only, ignored otherwise)
- *
- * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
- */
-gint moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
- gint* right, gint* bottom, GtkTextDirection direction,
- gboolean inhtml);
-/**
- * Get the desired metrics for a GtkScrollbar
- * metrics: [IN] struct which will contain the metrics
- *
- * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
- */
-gint
-moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics* metrics);
-
-/**
- * Retrieve an actual GTK scrollbar widget for style analysis. It will not
- * be modified.
- */
-GtkWidget* moz_gtk_get_scrollbar_widget(void);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif
diff --git a/Source/WebCore/platform/haiku/MIMETypeRegistryHaiku.cpp b/Source/WebCore/platform/haiku/MIMETypeRegistryHaiku.cpp
index 685827e..3cfddf9 100644
--- a/Source/WebCore/platform/haiku/MIMETypeRegistryHaiku.cpp
+++ b/Source/WebCore/platform/haiku/MIMETypeRegistryHaiku.cpp
@@ -31,6 +31,8 @@
#include "PlatformString.h"
#include <MimeType.h>
+#include <wtf/Assertions.h>
+#include <wtf/MainThread.h>
#include <wtf/text/CString.h>
namespace WebCore {
@@ -62,6 +64,8 @@ static const ExtensionMap extensionMap[] = {
String MIMETypeRegistry::getMIMETypeForExtension(const String& ext)
{
+ ASSERT(isMainThread());
+
String str = ext.lower();
// Try WebCore built-in types.
diff --git a/Source/WebCore/platform/image-decoders/ImageDecoder.cpp b/Source/WebCore/platform/image-decoders/ImageDecoder.cpp
index 17208b5..2aae205 100644
--- a/Source/WebCore/platform/image-decoders/ImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/ImageDecoder.cpp
@@ -38,7 +38,9 @@ using namespace std;
namespace WebCore {
-static unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const SharedBuffer& sharedBuffer, unsigned offset)
+namespace {
+
+unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const SharedBuffer& sharedBuffer, unsigned offset)
{
unsigned bytesExtracted = 0;
const char* moreData;
@@ -53,55 +55,80 @@ static unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const
return bytesExtracted;
}
+<<<<<<< HEAD
#if !OS(ANDROID)
// This method requires BMPImageDecoder, PNGImageDecoder, ICOImageDecoder and
// JPEGDecoder, which aren't used on Android, and which don't all compile.
// TODO: Find a better fix.
+=======
+bool matchesGIFSignature(char* contents)
+{
+ return !memcmp(contents, "GIF8", 4);
+}
+
+bool matchesPNGSignature(char* contents)
+{
+ return !memcmp(contents, "\x89\x50\x4E\x47", 4);
+}
+
+bool matchesJPEGSignature(char* contents)
+{
+ return !memcmp(contents, "\xFF\xD8\xFF", 3);
+}
+
+#if USE(WEBP)
+bool matchesWebPSignature(char* contents)
+{
+ return !memcmp(contents, "RIFF", 4) && !memcmp(contents + 8, "WEBPVP", 6);
+}
+#endif
+
+bool matchesBMPSignature(char* contents)
+{
+ return !memcmp(contents, "BM", 2);
+}
+
+bool matchesICOSignature(char* contents)
+{
+ return !memcmp(contents, "\x00\x00\x01\x00", 4);
+}
+
+bool matchesCURSignature(char* contents)
+{
+ return !memcmp(contents, "\x00\x00\x02\x00", 4);
+}
+
+}
+
+>>>>>>> webkit.org at r78450
ImageDecoder* ImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
{
- // We need at least 4 bytes to figure out what kind of image we're dealing
- // with.
- static const unsigned maxMarkerLength = 4;
- char contents[maxMarkerLength];
- unsigned length = copyFromSharedBuffer(contents, maxMarkerLength, data, 0);
- if (length < maxMarkerLength)
+ static const unsigned lengthOfLongestSignature = 14; // To wit: "RIFF????WEBPVP"
+ char contents[lengthOfLongestSignature];
+ unsigned length = copyFromSharedBuffer(contents, lengthOfLongestSignature, data, 0);
+ if (length < lengthOfLongestSignature)
return 0;
- // GIFs begin with GIF8(7 or 9).
- if (strncmp(contents, "GIF8", 4) == 0)
+ if (matchesGIFSignature(contents))
return new GIFImageDecoder(alphaOption, gammaAndColorProfileOption);
- // Test for PNG.
- if (!memcmp(contents, "\x89\x50\x4E\x47", 4))
+ if (matchesPNGSignature(contents))
return new PNGImageDecoder(alphaOption, gammaAndColorProfileOption);
- // JPEG
- if (!memcmp(contents, "\xFF\xD8\xFF", 3))
+ if (matchesJPEGSignature(contents))
return new JPEGImageDecoder(alphaOption, gammaAndColorProfileOption);
#if USE(WEBP)
- if (!memcmp(contents, "RIFF", 4)) {
- static const unsigned webpExtraMarker = 6;
- static const unsigned webpExtraMarkeroffset = 8;
- char header[webpExtraMarker];
- unsigned length = copyFromSharedBuffer(header, webpExtraMarker, data, webpExtraMarkeroffset);
- if (length >= webpExtraMarker) {
- if (!memcmp(header, "WEBPVP", webpExtraMarker))
- return new WEBPImageDecoder(alphaOption, gammaAndColorProfileOption);
- }
- }
+ if (matchesWebPSignature(contents))
+ return new WEBPImageDecoder(alphaOption, gammaAndColorProfileOption);
#endif
- // BMP
- if (strncmp(contents, "BM", 2) == 0)
+ if (matchesBMPSignature(contents))
return new BMPImageDecoder(alphaOption, gammaAndColorProfileOption);
- // ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
- // CURs begin with 2-byte 0 followed by 2-byte 2.
- if (!memcmp(contents, "\x00\x00\x01\x00", 4) || !memcmp(contents, "\x00\x00\x02\x00", 4))
+ if (matchesICOSignature(contents) || matchesCURSignature(contents))
return new ICOImageDecoder(alphaOption, gammaAndColorProfileOption);
- // Give up. We don't know what the heck this is.
return 0;
}
#endif // !OS(ANDROID)
@@ -123,7 +150,7 @@ ImageFrame& ImageFrame::operator=(const ImageFrame& other)
return *this;
copyReferenceToBitmapData(other);
- setRect(other.rect());
+ setOriginalFrameRect(other.originalFrameRect());
setStatus(other.status());
setDuration(other.duration());
setDisposalMethod(other.disposalMethod());
@@ -131,7 +158,7 @@ ImageFrame& ImageFrame::operator=(const ImageFrame& other)
return *this;
}
-void ImageFrame::clear()
+void ImageFrame::clearPixelData()
{
m_backingStore.clear();
m_bytes = 0;
@@ -142,7 +169,7 @@ void ImageFrame::clear()
// later.
}
-void ImageFrame::zeroFill()
+void ImageFrame::zeroFillPixelData()
{
memset(m_bytes, 0, m_size.width() * m_size.height() * sizeof(PixelData));
m_hasAlpha = true;
@@ -176,8 +203,7 @@ bool ImageFrame::setSize(int newWidth, int newHeight)
m_bytes = m_backingStore.data();
m_size = IntSize(newWidth, newHeight);
- // Zero the image.
- zeroFill();
+ zeroFillPixelData();
return true;
}
diff --git a/Source/WebCore/platform/image-decoders/ImageDecoder.h b/Source/WebCore/platform/image-decoders/ImageDecoder.h
index c581ba1..7d0d0d4 100644
--- a/Source/WebCore/platform/image-decoders/ImageDecoder.h
+++ b/Source/WebCore/platform/image-decoders/ImageDecoder.h
@@ -50,9 +50,8 @@ namespace WebCore {
// FIXME: Do we want better encapsulation?
typedef Vector<char> ColorProfile;
- // The ImageFrame object represents the decoded image data in RGBA32
- // format. This buffer is what all decoders write a single frame into.
- // Frames are then instantiated for drawing by being handed this buffer.
+ // ImageFrame represents the decoded image data. This buffer is what all
+ // decoders write a single frame into.
class ImageFrame {
public:
enum FrameStatus { FrameEmpty, FramePartial, FrameComplete };
@@ -80,19 +79,17 @@ namespace WebCore {
// create a new copy of the image data, only increase the ref count.
ImageFrame& operator=(const ImageFrame& other);
- // Deletes the pixel data entirely; used by ImageDecoder to save memory
- // when we no longer need to display a frame and only need its metadata.
- void clear();
+ // These do not touch other metadata, only the raw pixel data.
+ void clearPixelData();
+ void zeroFillPixelData();
- // Zeroes the pixel data in the buffer, setting it to fully-transparent.
- void zeroFill();
-
- // Creates a new copy of the image data in |other|, so the two images
- // can be modified independently. Returns whether the copy succeeded.
+ // Makes this frame have an independent copy of the provided image's
+ // pixel data, so that modifications in one frame are not reflected in
+ // the other. Returns whether the copy succeeded.
bool copyBitmapData(const ImageFrame&);
- // Creates a new reference to the image data in |other|. The two images
- // share a common backing store.
+ // Makes this frame reference the provided image's pixel data, so that
+ // modifications in one frame are reflected in the other.
void copyReferenceToBitmapData(const ImageFrame&);
// Copies the pixel data at [(startX, startY), (endX, startY)) to the
@@ -116,18 +113,17 @@ namespace WebCore {
#endif
// Allocates space for the pixel data. Must be called before any pixels
- // are written. Will return true on success, false if the memory
- // allocation fails. Calling this multiple times is undefined and may
- // leak memory.
+ // are written. Must only be called once. Returns whether allocation
+ // succeeded.
bool setSize(int newWidth, int newHeight);
- // To be used by ImageSource::createFrameAtIndex(). Returns a pointer
- // to the underlying native image data. This pointer will be owned by
- // the BitmapImage and freed in FrameData::clear().
+ // Returns a caller-owned pointer to the underlying native image data.
+ // (Actual use: This pointer will be owned by BitmapImage and freed in
+ // FrameData::clear()).
NativeImagePtr asNewNativeImage() const;
bool hasAlpha() const;
- const IntRect& rect() const { return m_rect; }
+ const IntRect& originalFrameRect() const { return m_originalFrameRect; }
FrameStatus status() const { return m_status; }
unsigned duration() const { return m_duration; }
FrameDisposalMethod disposalMethod() const { return m_disposalMethod; }
@@ -135,7 +131,7 @@ namespace WebCore {
void setHasAlpha(bool alpha);
void setColorProfile(const ColorProfile&);
- void setRect(const IntRect& r) { m_rect = r; }
+ void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; }
void setStatus(FrameStatus status);
void setDuration(unsigned duration) { m_duration = duration; }
void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
@@ -184,7 +180,11 @@ namespace WebCore {
g = static_cast<unsigned>(g * alphaPercent);
b = static_cast<unsigned>(b * alphaPercent);
}
+<<<<<<< HEAD
#if PLATFORM(ANDROID)
+=======
+#if PLATFORM(SKIA)
+>>>>>>> webkit.org at r78450
*dest = SkPackARGB32(a, r, g, b);
#else
*dest = (a << 24 | r << 16 | g << 8 | b);
@@ -202,35 +202,26 @@ namespace WebCore {
#else
NativeBackingStore m_backingStore;
PixelData* m_bytes; // The memory is backed by m_backingStore.
- IntSize m_size; // The size of the buffer. This should be the
- // same as ImageDecoder::m_size.
- bool m_hasAlpha; // Whether or not any of the pixels in the buffer
- // have transparency.
+ IntSize m_size;
+ bool m_hasAlpha;
ColorProfile m_colorProfile;
#endif
- IntRect m_rect; // The rect of the original specified frame within
- // the overall buffer. This will always just be
- // the entire buffer except for GIF frames whose
- // original rect was smaller than the overall
- // image size.
- FrameStatus m_status; // Whether or not this frame is completely
- // finished decoding.
- unsigned m_duration; // The animation delay.
- FrameDisposalMethod m_disposalMethod; // What to do with this frame's data when
- // initializing the next frame.
- bool m_premultiplyAlpha; // Whether to premultiply alpha into R, G, B
- // channels; by default it's true.
+ IntRect m_originalFrameRect; // This will always just be the entire
+ // buffer except for GIF frames whose
+ // original rect was smaller than the
+ // overall image size.
+ FrameStatus m_status;
+ unsigned m_duration;
+ FrameDisposalMethod m_disposalMethod;
+ bool m_premultiplyAlpha;
};
- // The ImageDecoder class represents a base class for specific image format
- // decoders (e.g., GIF, JPG, PNG, ICO) to derive from. All decoders decode
- // into RGBA32 format and the base class manages the RGBA32 frame cache.
+ // ImageDecoder is a base for all format-specific decoders
+ // (e.g. JPEGImageDecoder). This base manages the ImageFrame cache.
//
- // ENABLE(IMAGE_DECODER_DOWN_SAMPLING) allows image decoders to write
- // directly to scaled output buffers by down sampling. Call
- // setMaxNumPixels() to specify the biggest size that decoded images can
- // have. Image decoders will deflate those images that are bigger than
- // m_maxNumPixels. (Not supported by all image decoders yet)
+ // ENABLE(IMAGE_DECODER_DOWN_SAMPLING) allows image decoders to downsample
+ // at decode time. Image decoders will downsample any images larger than
+ // |m_maxNumPixels|. FIXME: Not yet supported by all decoders.
class ImageDecoder {
WTF_MAKE_NONCOPYABLE(ImageDecoder); WTF_MAKE_FAST_ALLOCATED;
public:
@@ -241,19 +232,15 @@ namespace WebCore {
, m_sizeAvailable(false)
, m_maxNumPixels(-1)
, m_isAllDataReceived(false)
- , m_failed(false)
- {
- }
+ , m_failed(false) { }
- virtual ~ImageDecoder() {}
+ virtual ~ImageDecoder() { }
- // Factory function to create an ImageDecoder. Ports that subclass
- // ImageDecoder can provide their own implementation of this to avoid
- // needing to write a dedicated setData() implementation.
+ // Returns a caller-owned decoder of the appropriate type. Returns 0 if
+ // we can't sniff a supported type from the provided data (possibly
+ // because there isn't enough data yet).
static ImageDecoder* create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
- // The the filename extension usually associated with an undecoded image
- // of this type.
virtual String filenameExtension() const = 0;
bool isAllDataReceived() const { return m_isAllDataReceived; }
@@ -266,41 +253,33 @@ namespace WebCore {
m_isAllDataReceived = allDataReceived;
}
- // Whether or not the size information has been decoded yet. This
- // default implementation just returns true if the size has been set and
- // we have not seen a failure. Decoders may want to override this to
- // lazily decode enough of the image to get the size.
+ // Lazily-decodes enough of the image to get the size (if possible).
+ // FIXME: Right now that has to be done by each subclass; factor the
+ // decode call out and use it here.
virtual bool isSizeAvailable()
{
- return !m_failed && m_sizeAvailable;
+ return !m_failed && m_sizeAvailable;
}
- // Returns the size of the image.
- virtual IntSize size() const
- {
- return m_size;
- }
+ virtual IntSize size() const { return m_size; }
IntSize scaledSize() const
{
return m_scaled ? IntSize(m_scaledColumns.size(), m_scaledRows.size()) : size();
}
- // Returns the size of frame |index|. This will only differ from size()
- // for formats where different frames are different sizes (namely ICO,
- // where each frame represents a different icon within the master file).
- // Notably, this does not return different sizes for different GIF
- // frames, since while these may be stored as smaller rectangles, during
- // decoding they are composited to create a full-size frame.
+ // This will only differ from size() for ICO (where each frame is a
+ // different icon) or other formats where different frames are different
+ // sizes. This does NOT differ from size() for GIF, since decoding GIFs
+ // composites any smaller frames against previous frames to create full-
+ // size frames.
virtual IntSize frameSizeAtIndex(size_t) const
{
return size();
}
- // Called by the image decoders to set their decoded size, this also
- // checks the size for validity. It will return true if the size was
- // set, or false if there is an error. On error, the m_failed flag will
- // be set and the caller should immediately stop decoding.
+ // Returns whether the size is legal (i.e. not going to result in
+ // overflow elsewhere). If not, marks decoding as failed.
virtual bool setSize(unsigned width, unsigned height)
{
if (isOverSize(width, height))
@@ -310,26 +289,19 @@ namespace WebCore {
return true;
}
- // The total number of frames for the image. Classes that support
- // multiple frames will scan the image data for the answer if they need
- // to (without necessarily decoding all of the individual frames).
+ // Lazily-decodes enough of the image to get the frame count (if
+ // possible), without decoding the individual frames.
+ // FIXME: Right now that has to be done by each subclass; factor the
+ // decode call out and use it here.
virtual size_t frameCount() { return 1; }
- // The number of repetitions to perform for an animation loop.
virtual int repetitionCount() const { return cAnimationNone; }
- // Called to obtain the ImageFrame full of decoded data for rendering.
- // The decoder plugin will decode as much of the frame as it can before
- // handing back the buffer.
+ // Decodes as much of the requested frame as possible, and returns an
+ // ImageDecoder-owned pointer.
virtual ImageFrame* frameBufferAtIndex(size_t) = 0;
- // Whether or not the underlying image format even supports alpha
- // transparency.
- virtual bool supportsAlpha() const { return true; }
-
void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; }
-
- // Whether or not the gamma and color profile are applied.
bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; }
// Sets the "decode failure" flag. For caller convenience (since so
@@ -344,13 +316,10 @@ namespace WebCore {
bool failed() const { return m_failed; }
- // Wipe out frames in the frame buffer cache before |clearBeforeFrame|,
- // assuming this can be done without breaking decoding. Different
- // decoders place different restrictions on what frames are safe to
- // destroy, so this is left to them to implement.
- // For convenience's sake, we provide a default (empty) implementation,
- // since in practice only GIFs will ever use this.
- virtual void clearFrameBufferCache(size_t clearBeforeFrame) { }
+ // Clears decoded pixel data from before the provided frame unless that
+ // data may be needed to decode future frames (e.g. due to GIF frame
+ // compositing).
+ virtual void clearFrameBufferCache(size_t) { }
#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
void setMaxNumPixels(int m) { m_maxNumPixels = m; }
@@ -378,8 +347,6 @@ namespace WebCore {
// and return it as a (signed) int. Avoid overflow.
static bool isOverSize(unsigned width, unsigned height)
{
- // width * height must not exceed (2 ^ 29) - 1, so that we don't
- // overflow when we multiply by 4.
unsigned long long total_size = static_cast<unsigned long long>(width)
* static_cast<unsigned long long>(height);
return total_size > ((1 << 29) - 1);
diff --git a/Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp b/Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp
index 1805bc7..5c00553 100644
--- a/Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp
+++ b/Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp
@@ -87,7 +87,7 @@ bool BMPImageReader::decodeBMP(bool onlySize)
m_buffer->setHasAlpha(false);
// For BMPs, the frame always fills the entire image.
- m_buffer->setRect(IntRect(IntPoint(), m_parent->size()));
+ m_buffer->setOriginalFrameRect(IntRect(IntPoint(), m_parent->size()));
if (!m_isTopDown)
m_coord.setY(m_parent->size().height() - 1);
@@ -707,7 +707,7 @@ BMPImageReader::ProcessingResult BMPImageReader::processNonRLEData(bool inRLE, i
} else {
m_seenNonZeroAlphaPixel = true;
if (m_seenZeroAlphaPixel) {
- m_buffer->zeroFill();
+ m_buffer->zeroFillPixelData();
m_seenZeroAlphaPixel = false;
} else if (alpha != 255)
m_buffer->setHasAlpha(true);
diff --git a/Source/WebCore/platform/image-decoders/cg/ImageDecoderCG.cpp b/Source/WebCore/platform/image-decoders/cg/ImageDecoderCG.cpp
index 0b90107..43d6a52 100644
--- a/Source/WebCore/platform/image-decoders/cg/ImageDecoderCG.cpp
+++ b/Source/WebCore/platform/image-decoders/cg/ImageDecoderCG.cpp
@@ -72,7 +72,7 @@ bool ImageFrame::setSize(int newWidth, int newHeight)
m_bytes = reinterpret_cast<PixelData*>(CFDataGetMutableBytePtr(m_backingStore.get()));
m_size = IntSize(newWidth, newHeight);
- zeroFill();
+ zeroFillPixelData();
return true;
}
diff --git a/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
index e6de597..7e334a9 100644
--- a/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
@@ -174,14 +174,14 @@ void GIFImageDecoder::clearFrameBufferCache(size_t clearBeforeFrame)
Vector<ImageFrame>::iterator i(end);
for (; (i != m_frameBufferCache.begin()) && ((i->status() == ImageFrame::FrameEmpty) || (i->disposalMethod() == ImageFrame::DisposeOverwritePrevious)); --i) {
if ((i->status() == ImageFrame::FrameComplete) && (i != end))
- i->clear();
+ i->clearPixelData();
}
// Now |i| holds the last frame we need to preserve; clear prior frames.
for (Vector<ImageFrame>::iterator j(m_frameBufferCache.begin()); j != i; ++j) {
ASSERT(j->status() != ImageFrame::FramePartial);
if (j->status() != ImageFrame::FrameEmpty)
- j->clear();
+ j->clearPixelData();
}
}
@@ -266,7 +266,7 @@ bool GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration,
if (!m_currentBufferSawAlpha) {
// The whole frame was non-transparent, so it's possible that the entire
// resulting buffer was non-transparent, and we can setHasAlpha(false).
- if (buffer.rect().contains(IntRect(IntPoint(), scaledSize())))
+ if (buffer.originalFrameRect().contains(IntRect(IntPoint(), scaledSize())))
buffer.setHasAlpha(false);
else if (frameIndex) {
// Tricky case. This frame does not have alpha only if everywhere
@@ -289,7 +289,7 @@ bool GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration,
// The only remaining case is a DisposeOverwriteBgcolor frame. If
// it had no alpha, and its rect is contained in the current frame's
// rect, we know the current frame has no alpha.
- if ((prevBuffer->disposalMethod() == ImageFrame::DisposeOverwriteBgcolor) && !prevBuffer->hasAlpha() && buffer.rect().contains(prevBuffer->rect()))
+ if ((prevBuffer->disposalMethod() == ImageFrame::DisposeOverwriteBgcolor) && !prevBuffer->hasAlpha() && buffer.originalFrameRect().contains(prevBuffer->originalFrameRect()))
buffer.setHasAlpha(false);
}
}
@@ -327,17 +327,17 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
IntRect frameRect(frameReader->x_offset, frameReader->y_offset, frameReader->width, frameReader->height);
// Make sure the frameRect doesn't extend outside the buffer.
- if (frameRect.right() > size().width())
+ if (frameRect.maxX() > size().width())
frameRect.setWidth(size().width() - frameReader->x_offset);
- if (frameRect.bottom() > size().height())
+ if (frameRect.maxY() > size().height())
frameRect.setHeight(size().height() - frameReader->y_offset);
ImageFrame* const buffer = &m_frameBufferCache[frameIndex];
int left = upperBoundScaledX(frameRect.x());
- int right = lowerBoundScaledX(frameRect.right(), left);
+ int right = lowerBoundScaledX(frameRect.maxX(), left);
int top = upperBoundScaledY(frameRect.y());
- int bottom = lowerBoundScaledY(frameRect.bottom(), top);
- buffer->setRect(IntRect(left, top, right - left, bottom - top));
+ int bottom = lowerBoundScaledY(frameRect.maxY(), top);
+ buffer->setOriginalFrameRect(IntRect(left, top, right - left, bottom - top));
if (!frameIndex) {
// This is the first frame, so we're not relying on any previous data.
@@ -367,7 +367,7 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
} else {
// We want to clear the previous frame to transparent, without
// affecting pixels in the image outside of the frame.
- const IntRect& prevRect = prevBuffer->rect();
+ const IntRect& prevRect = prevBuffer->originalFrameRect();
const IntSize& bufferSize = scaledSize();
if (!frameIndex || prevRect.contains(IntRect(IntPoint(), scaledSize()))) {
// Clearing the first frame, or a frame the size of the whole
@@ -378,8 +378,8 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
// Copy the whole previous buffer, then clear just its frame.
if (!buffer->copyBitmapData(*prevBuffer))
return setFailed();
- for (int y = prevRect.y(); y < prevRect.bottom(); ++y) {
- for (int x = prevRect.x(); x < prevRect.right(); ++x)
+ for (int y = prevRect.y(); y < prevRect.maxY(); ++y) {
+ for (int x = prevRect.x(); x < prevRect.maxX(); ++x)
buffer->setRGBA(x, y, 0, 0, 0, 0);
}
if ((prevRect.width() > 0) && (prevRect.height() > 0))
diff --git a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
index a255c25..1434c65 100644
--- a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
@@ -222,6 +222,12 @@ public:
// jpeglib cannot convert these to rgb, but it can convert ycck
// to cmyk.
m_info.out_color_space = JCS_CMYK;
+
+ // Same as with grayscale images, we convert CMYK images to RGBA
+ // ones. When we keep the color profiles of these CMYK images,
+ // CoreGraphics will convert their colors again. So, we discard
+ // their color profiles to prevent color corruption.
+ m_decoder->setIgnoreGammaAndColorProfile(true);
break;
default:
return m_decoder->setFailed();
@@ -462,7 +468,7 @@ bool JPEGImageDecoder::outputScanlines()
buffer.setColorProfile(m_colorProfile);
// For JPEGs, the frame always fills the entire image.
- buffer.setRect(IntRect(IntPoint(), size()));
+ buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
}
jpeg_decompress_struct* info = m_reader->info();
diff --git a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
index 801f1ab..d095cbb 100644
--- a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
+++ b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
@@ -45,7 +45,6 @@ namespace WebCore {
virtual bool isSizeAvailable();
virtual bool setSize(unsigned width, unsigned height);
virtual ImageFrame* frameBufferAtIndex(size_t index);
- virtual bool supportsAlpha() const { return false; }
// CAUTION: setFailed() deletes |m_reader|. Be careful to avoid
// accessing deleted memory, especially when calling this from inside
// JPEGImageReader!
diff --git a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
index 755d704..8edfe36 100644
--- a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
@@ -341,7 +341,7 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex,
buffer.setColorProfile(m_colorProfile);
// For PNGs, the frame always fills the entire image.
- buffer.setRect(IntRect(IntPoint(), size()));
+ buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
if (m_reader->pngPtr()->interlaced)
m_reader->createInterlaceBuffer((m_reader->hasAlpha() ? 4 : 3) * size().width() * size().height());
diff --git a/Source/WebCore/platform/image-decoders/qt/ImageFrameQt.cpp b/Source/WebCore/platform/image-decoders/qt/ImageFrameQt.cpp
index 81c22cf..a3cfbf6 100644
--- a/Source/WebCore/platform/image-decoders/qt/ImageFrameQt.cpp
+++ b/Source/WebCore/platform/image-decoders/qt/ImageFrameQt.cpp
@@ -50,14 +50,14 @@ ImageFrame& ImageFrame::operator=(const ImageFrame& other)
return *this;
copyBitmapData(other);
- setRect(other.rect());
+ setOriginalFrameRect(other.originalFrameRect());
setStatus(other.status());
setDuration(other.duration());
setDisposalMethod(other.disposalMethod());
return *this;
}
-void ImageFrame::clear()
+void ImageFrame::clearPixelData()
{
m_pixmap = QPixmap();
m_image = QImage();
@@ -68,7 +68,7 @@ void ImageFrame::clear()
// other metadata out of this frame later.
}
-void ImageFrame::zeroFill()
+void ImageFrame::zeroFillPixelData()
{
if (m_pixmap.isNull() && !m_image.isNull()) {
m_pixmap = QPixmap(m_image.width(), m_image.height());
@@ -101,8 +101,7 @@ bool ImageFrame::setSize(int newWidth, int newHeight)
if (m_pixmap.isNull())
return false;
- // Zero the image.
- zeroFill();
+ zeroFillPixelData();
return true;
}
diff --git a/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp b/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
index a1c8261..c7dcc7a 100644
--- a/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
+++ b/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
@@ -51,7 +51,7 @@ ImageFrame& ImageFrame::operator=(const ImageFrame& other)
// Keep the pixels locked since we will be writing directly into the
// bitmap throughout this object's lifetime.
m_bitmap.lockPixels();
- setRect(other.rect());
+ setOriginalFrameRect(other.originalFrameRect());
setStatus(other.status());
setDuration(other.duration());
setDisposalMethod(other.disposalMethod());
@@ -59,7 +59,7 @@ ImageFrame& ImageFrame::operator=(const ImageFrame& other)
return *this;
}
-void ImageFrame::clear()
+void ImageFrame::clearPixelData()
{
m_bitmap.reset();
m_status = FrameEmpty;
@@ -69,7 +69,7 @@ void ImageFrame::clear()
// other metadata out of this frame later.
}
-void ImageFrame::zeroFill()
+void ImageFrame::zeroFillPixelData()
{
m_bitmap.eraseARGB(0, 0, 0, 0);
}
@@ -93,8 +93,7 @@ bool ImageFrame::setSize(int newWidth, int newHeight)
if (!m_bitmap.allocPixels())
return false;
- // Zero the image.
- zeroFill();
+ zeroFillPixelData();
return true;
}
diff --git a/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp b/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp
index 8045ada..3db00f6 100644
--- a/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp
@@ -116,7 +116,7 @@ bool WEBPImageDecoder::decode(bool onlySize)
}
buffer.setStatus(ImageFrame::FrameComplete);
buffer.setHasAlpha(false);
- buffer.setRect(IntRect(IntPoint(), size()));
+ buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
return true;
}
diff --git a/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h b/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h
index cde1bbf..c32e047 100644
--- a/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h
+++ b/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h
@@ -42,7 +42,6 @@ public:
virtual String filenameExtension() const { return "vp8"; }
virtual bool isSizeAvailable();
virtual ImageFrame* frameBufferAtIndex(size_t index);
- virtual bool supportsAlpha() const { return false; }
private:
// Returns false in case of decoding failure.
diff --git a/Source/WebCore/platform/mac/DragImageMac.mm b/Source/WebCore/platform/mac/DragImageMac.mm
index f444b6e..fc58173 100644
--- a/Source/WebCore/platform/mac/DragImageMac.mm
+++ b/Source/WebCore/platform/mac/DragImageMac.mm
@@ -28,9 +28,16 @@
#if ENABLE(DRAG_SUPPORT)
#import "CachedImage.h"
+#import "Font.h"
+#import "FontDescription.h"
+#import "FontSelector.h"
+#import "GraphicsContext.h"
#import "Image.h"
#import "KURL.h"
#import "ResourceResponse.h"
+#import "Settings.h"
+#import "StringTruncator.h"
+#import "TextRun.h"
namespace WebCore {
@@ -98,7 +105,210 @@ RetainPtr<NSImage> createDragImageIconForCachedImage(CachedImage* image)
return [[NSWorkspace sharedWorkspace] iconForFileType:extension];
}
+
+
+const float DragLabelBorderX = 4;
+//Keep border_y in synch with DragController::LinkDragBorderInset
+const float DragLabelBorderY = 2;
+const float DragLabelRadius = 5;
+const float LabelBorderYOffset = 2;
+
+const float MinDragLabelWidthBeforeClip = 120;
+const float MaxDragLabelWidth = 320;
+
+const float DragLinkLabelFontsize = 11;
+const float DragLinkUrlFontSize = 10;
+
+// FIXME - we should move all the functionality of NSString extras to WebCore
+
+static Font& fontFromNSFont(NSFont *font)
+{
+ static NSFont *currentFont;
+ DEFINE_STATIC_LOCAL(Font, currentRenderer, ());
+
+ if ([font isEqual:currentFont])
+ return currentRenderer;
+ if (currentFont)
+ CFRelease(currentFont);
+ currentFont = font;
+ CFRetain(currentFont);
+ FontPlatformData f(font, [font pointSize]);
+ currentRenderer = Font(f, ![[NSGraphicsContext currentContext] isDrawingToScreen]);
+ return currentRenderer;
+}
+
+static bool canUseFastRenderer(const UniChar* buffer, unsigned length)
+{
+ unsigned i;
+ for (i = 0; i < length; i++) {
+ UCharDirection direction = u_charDirection(buffer[i]);
+ if (direction == U_RIGHT_TO_LEFT || direction > U_OTHER_NEUTRAL)
+ return false;
+ }
+ return true;
+}
+
+static float widthWithFont(NSString *string, NSFont *font)
+{
+ unsigned length = [string length];
+ Vector<UniChar, 2048> buffer(length);
+ [string getCharacters:buffer.data()];
+
+ if (canUseFastRenderer(buffer.data(), length)) {
+ Font webCoreFont(FontPlatformData(font, [font pointSize]), ![[NSGraphicsContext currentContext] isDrawingToScreen]);
+ TextRun run(buffer.data(), length);
+ run.disableRoundingHacks();
+ return webCoreFont.floatWidth(run);
+ }
+
+ return [string sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil]].width;
+}
+
+static inline CGFloat webkit_CGCeiling(CGFloat value)
+{
+ if (sizeof(value) == sizeof(float))
+ return ceilf(value);
+ return static_cast<CGFloat>(ceil(value));
+}
+
+static void drawAtPoint(NSString *string, NSPoint point, NSFont *font, NSColor *textColor)
+{
+ unsigned length = [string length];
+ Vector<UniChar, 2048> buffer(length);
+
+ [string getCharacters:buffer.data()];
+
+ if (canUseFastRenderer(buffer.data(), length)) {
+ // The following is a half-assed attempt to match AppKit's rounding rules for drawAtPoint.
+ // It's probably incorrect for high DPI.
+ // If you change this, be sure to test all the text drawn this way in Safari, including
+ // the status bar, bookmarks bar, tab bar, and activity window.
+ point.y = webkit_CGCeiling(point.y);
+
+ NSGraphicsContext *nsContext = [NSGraphicsContext currentContext];
+ CGContextRef cgContext = static_cast<CGContextRef>([nsContext graphicsPort]);
+ GraphicsContext graphicsContext(cgContext);
+
+ // Safari doesn't flip the NSGraphicsContext before calling WebKit, yet WebCore requires a flipped graphics context.
+ BOOL flipped = [nsContext isFlipped];
+ if (!flipped)
+ CGContextScaleCTM(cgContext, 1, -1);
+
+ Font webCoreFont(FontPlatformData(font, [font pointSize]), ![nsContext isDrawingToScreen], Antialiased);
+ TextRun run(buffer.data(), length);
+ run.disableRoundingHacks();
+
+ CGFloat red;
+ CGFloat green;
+ CGFloat blue;
+ CGFloat alpha;
+ [[textColor colorUsingColorSpaceName:NSDeviceRGBColorSpace] getRed:&red green:&green blue:&blue alpha:&alpha];
+ graphicsContext.setFillColor(makeRGBA(red * 255, green * 255, blue * 255, alpha * 255), ColorSpaceDeviceRGB);
+
+ webCoreFont.drawText(&graphicsContext, run, FloatPoint(point.x, (flipped ? point.y : (-1 * point.y))));
+
+ if (!flipped)
+ CGContextScaleCTM(cgContext, 1, -1);
+ } else {
+ // The given point is on the baseline.
+ if ([[NSView focusView] isFlipped])
+ point.y -= [font ascender];
+ else
+ point.y += [font descender];
+
+ [string drawAtPoint:point withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, textColor, NSForegroundColorAttributeName, nil]];
+ }
+}
+
+static void drawDoubledAtPoint(NSString *string, NSPoint textPoint, NSColor *topColor, NSColor *bottomColor, NSFont *font)
+{
+ // turn off font smoothing so translucent text draws correctly (Radar 3118455)
+ drawAtPoint(string, textPoint, font, bottomColor);
+
+ textPoint.y += 1;
+ drawAtPoint(string, textPoint, font, topColor);
+}
+
+DragImageRef createDragImageForLink(KURL& url, const String& title, Frame* frame)
+{
+ if (!frame)
+ return nil;
+ NSString *label = 0;
+ if (!title.isEmpty())
+ label = title;
+ NSURL *cocoaURL = url;
+ NSString *urlString = [cocoaURL absoluteString];
+
+ BOOL drawURLString = YES;
+ BOOL clipURLString = NO;
+ BOOL clipLabelString = NO;
+
+ if (!label) {
+ drawURLString = NO;
+ label = urlString;
+ }
+
+ NSFont *labelFont = [[NSFontManager sharedFontManager] convertFont:[NSFont systemFontOfSize:DragLinkLabelFontsize]
+ toHaveTrait:NSBoldFontMask];
+ NSFont *urlFont = [NSFont systemFontOfSize:DragLinkUrlFontSize];
+ NSSize labelSize;
+ labelSize.width = widthWithFont(label, labelFont);
+ labelSize.height = [labelFont ascender] - [labelFont descender];
+ if (labelSize.width > MaxDragLabelWidth){
+ labelSize.width = MaxDragLabelWidth;
+ clipLabelString = YES;
+ }
+
+ NSSize imageSize;
+ imageSize.width = labelSize.width + DragLabelBorderX * 2;
+ imageSize.height = labelSize.height + DragLabelBorderY * 2;
+ if (drawURLString) {
+ NSSize urlStringSize;
+ urlStringSize.width = widthWithFont(urlString, urlFont);
+ urlStringSize.height = [urlFont ascender] - [urlFont descender];
+ imageSize.height += urlStringSize.height;
+ if (urlStringSize.width > MaxDragLabelWidth) {
+ imageSize.width = std::max(MaxDragLabelWidth + DragLabelBorderY * 2, MinDragLabelWidthBeforeClip);
+ clipURLString = YES;
+ } else
+ imageSize.width = std::max(labelSize.width + DragLabelBorderX * 2, urlStringSize.width + DragLabelBorderX * 2);
+ }
+ NSImage *dragImage = [[[NSImage alloc] initWithSize: imageSize] autorelease];
+ [dragImage lockFocus];
+
+ [[NSColor colorWithDeviceRed: 0.7f green: 0.7f blue: 0.7f alpha: 0.8f] set];
+
+ // Drag a rectangle with rounded corners
+ NSBezierPath *path = [NSBezierPath bezierPath];
+ [path appendBezierPathWithOvalInRect: NSMakeRect(0, 0, DragLabelRadius * 2, DragLabelRadius * 2)];
+ [path appendBezierPathWithOvalInRect: NSMakeRect(0, imageSize.height - DragLabelRadius * 2, DragLabelRadius * 2, DragLabelRadius * 2)];
+ [path appendBezierPathWithOvalInRect: NSMakeRect(imageSize.width - DragLabelRadius * 2, imageSize.height - DragLabelRadius * 2, DragLabelRadius * 2, DragLabelRadius * 2)];
+ [path appendBezierPathWithOvalInRect: NSMakeRect(imageSize.width - DragLabelRadius * 2, 0, DragLabelRadius * 2, DragLabelRadius * 2)];
+
+ [path appendBezierPathWithRect: NSMakeRect(DragLabelRadius, 0, imageSize.width - DragLabelRadius * 2, imageSize.height)];
+ [path appendBezierPathWithRect: NSMakeRect(0, DragLabelRadius, DragLabelRadius + 10, imageSize.height - 2 * DragLabelRadius)];
+ [path appendBezierPathWithRect: NSMakeRect(imageSize.width - DragLabelRadius - 20, DragLabelRadius, DragLabelRadius + 20, imageSize.height - 2 * DragLabelRadius)];
+ [path fill];
+
+ NSColor *topColor = [NSColor colorWithDeviceWhite:0.0f alpha:0.75f];
+ NSColor *bottomColor = [NSColor colorWithDeviceWhite:1.0f alpha:0.5f];
+ if (drawURLString) {
+ if (clipURLString)
+ urlString = StringTruncator::centerTruncate(urlString, imageSize.width - (DragLabelBorderX * 2), fontFromNSFont(urlFont));
+
+ drawDoubledAtPoint(urlString, NSMakePoint(DragLabelBorderX, DragLabelBorderY - [urlFont descender]), topColor, bottomColor, urlFont);
+ }
+
+ if (clipLabelString)
+ label = StringTruncator::rightTruncate(label, imageSize.width - (DragLabelBorderX * 2), fontFromNSFont(labelFont));
+ drawDoubledAtPoint(label, NSMakePoint(DragLabelBorderX, imageSize.height - LabelBorderYOffset - [labelFont pointSize]), topColor, bottomColor, labelFont);
+
+ [dragImage unlockFocus];
+
+ return dragImage;
+}
+
} // namespace WebCore
#endif // ENABLE(DRAG_SUPPORT)
diff --git a/Source/WebCore/platform/mac/EmptyProtocolDefinitions.h b/Source/WebCore/platform/mac/EmptyProtocolDefinitions.h
index b73177b..04bf236 100644
--- a/Source/WebCore/platform/mac/EmptyProtocolDefinitions.h
+++ b/Source/WebCore/platform/mac/EmptyProtocolDefinitions.h
@@ -23,6 +23,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef EmptyProtocolDefinitions_h
+#define EmptyProtocolDefinitions_h
+
#if defined(__OBJC__)
#define EMPTY_PROTOCOL(NAME) \
@@ -47,3 +50,5 @@ EMPTY_PROTOCOL(NSURLDownloadDelegate)
#undef EMPTY_PROTOCOL
#endif /* defined(__OBJC__) */
+
+#endif /* EmptyProtocolDefinitions_h */
diff --git a/Source/WebCore/platform/mac/FileSystemMac.mm b/Source/WebCore/platform/mac/FileSystemMac.mm
index 0df3c89..bbeb76a 100644
--- a/Source/WebCore/platform/mac/FileSystemMac.mm
+++ b/Source/WebCore/platform/mac/FileSystemMac.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 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
@@ -25,10 +25,12 @@
* (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 "FileSystem.h"
#import "PlatformString.h"
+#import <wtf/RetainPtr.h>
#import <wtf/text/CString.h>
namespace WebCore {
@@ -62,4 +64,25 @@ CString openTemporaryFile(const char* prefix, PlatformFileHandle& platformFileHa
return CString(temporaryFilePath.data());
}
+bool canExcludeFromBackup()
+{
+#ifdef BUILDING_ON_TIGER
+ return false;
+#else
+ return true;
+#endif
+}
+
+bool excludeFromBackup(const String& path)
+{
+#ifdef BUILDING_ON_TIGER
+ UNUSED_PARAM(path);
+ return false;
+#else
+ // It is critical to pass FALSE for excludeByPath because excluding by path requires root privileges.
+ CSBackupSetItemExcluded(pathAsURL(path).get(), TRUE, FALSE);
+ return true;
+#endif
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/mac/MIMETypeRegistryMac.mm b/Source/WebCore/platform/mac/MIMETypeRegistryMac.mm
index 82348e0..3792b5a 100644
--- a/Source/WebCore/platform/mac/MIMETypeRegistryMac.mm
+++ b/Source/WebCore/platform/mac/MIMETypeRegistryMac.mm
@@ -28,12 +28,15 @@
#include "MIMETypeRegistry.h"
#include "WebCoreSystemInterface.h"
+#include <wtf/Assertions.h>
+#include <wtf/MainThread.h>
namespace WebCore
{
String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
{
+ ASSERT(isMainThread());
return wkGetMIMETypeForExtension(ext);
}
diff --git a/Source/WebCore/platform/mac/PasteboardMac.mm b/Source/WebCore/platform/mac/PasteboardMac.mm
index 71e4046..65180a0 100644
--- a/Source/WebCore/platform/mac/PasteboardMac.mm
+++ b/Source/WebCore/platform/mac/PasteboardMac.mm
@@ -27,7 +27,6 @@
#import "Pasteboard.h"
#import "CachedResource.h"
-#import "CharacterNames.h"
#import "DOMRangeInternal.h"
#import "Document.h"
#import "DocumentFragment.h"
@@ -49,10 +48,10 @@
#import "Text.h"
#import "WebCoreNSStringExtras.h"
#import "markup.h"
-
#import <wtf/StdLibExtras.h>
#import <wtf/RetainPtr.h>
#import <wtf/UnusedParam.h>
+#import <wtf/unicode/CharacterNames.h>
@interface NSAttributedString (AppKitSecretsIKnowAbout)
- (id)_initWithDOMRange:(DOMRange *)domRange;
diff --git a/Source/WebCore/platform/mac/PopupMenuMac.mm b/Source/WebCore/platform/mac/PopupMenuMac.mm
index 1bf500b..e69bcb2 100644
--- a/Source/WebCore/platform/mac/PopupMenuMac.mm
+++ b/Source/WebCore/platform/mac/PopupMenuMac.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2008, 2010, 2011 Apple Inc. All rights reserved.
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
*
* This library is free software; you can redistribute it and/or
@@ -75,6 +75,11 @@ void PopupMenuMac::populate()
if (!client()->shouldPopOver())
[m_popup.get() addItemWithTitle:@""];
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ TextDirection menuTextDirection = client()->menuStyle().textDirection();
+ [m_popup.get() setUserInterfaceLayoutDirection:menuTextDirection == LTR ? NSUserInterfaceLayoutDirectionLeftToRight : NSUserInterfaceLayoutDirectionRightToLeft];
+#endif // !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+
ASSERT(client());
int size = client()->listSize();
@@ -92,13 +97,27 @@ void PopupMenuMac::populate()
}
[attributes setObject:font forKey:NSFontAttributeName];
}
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ RetainPtr<NSMutableParagraphStyle> paragraphStyle(AdoptNS, [[NSParagraphStyle defaultParagraphStyle] mutableCopy]);
+ [paragraphStyle.get() setAlignment:menuTextDirection == LTR ? NSLeftTextAlignment : NSRightTextAlignment];
+ NSWritingDirection writingDirection = style.textDirection() == LTR ? NSWritingDirectionLeftToRight : NSWritingDirectionRightToLeft;
+ [paragraphStyle.get() setBaseWritingDirection:writingDirection];
+ if (style.hasTextDirectionOverride()) {
+ RetainPtr<NSNumber> writingDirectionValue(AdoptNS, [[NSNumber alloc] initWithInteger:writingDirection + NSTextWritingDirectionOverride]);
+ RetainPtr<NSArray> writingDirectionArray(AdoptNS, [[NSArray alloc] initWithObjects:writingDirectionValue.get(), nil]);
+ [attributes setObject:writingDirectionArray.get() forKey:NSWritingDirectionAttributeName];
+ }
+ [attributes setObject:paragraphStyle.get() forKey:NSParagraphStyleAttributeName];
+#endif // !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+
// FIXME: Add support for styling the foreground and background colors.
// FIXME: Find a way to customize text color when an item is highlighted.
- NSAttributedString* string = [[NSAttributedString alloc] initWithString:client()->itemText(i) attributes:attributes];
+ NSAttributedString *string = [[NSAttributedString alloc] initWithString:client()->itemText(i) attributes:attributes];
[attributes release];
[m_popup.get() addItemWithTitle:@""];
- NSMenuItem* menuItem = [m_popup.get() lastItem];
+ NSMenuItem *menuItem = [m_popup.get() lastItem];
[menuItem setAttributedTitle:string];
[menuItem setEnabled:client()->itemIsEnabled(i)];
[menuItem setToolTip:client()->itemToolTip(i)];
diff --git a/Source/WebCore/platform/mac/ScrollAnimatorMac.h b/Source/WebCore/platform/mac/ScrollAnimatorMac.h
index f05db40..3f7612a 100644
--- a/Source/WebCore/platform/mac/ScrollAnimatorMac.h
+++ b/Source/WebCore/platform/mac/ScrollAnimatorMac.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * 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
@@ -28,17 +28,30 @@
#if ENABLE(SMOOTH_SCROLLING)
+#include "FloatPoint.h"
+#include "FloatSize.h"
+#include "HeaderDetection.h"
#include "ScrollAnimator.h"
+#include "Timer.h"
+#include "WebCoreSystemInterface.h"
#include <wtf/RetainPtr.h>
#ifdef __OBJC__
@class ScrollAnimationHelperDelegate;
+@class ScrollbarPainterDelegate;
+@class ScrollbarPainterControllerDelegate;
+@class ScrollbarPainterDelegate;
#else
class ScrollAnimationHelperDelegate;
+class ScrollbarPainterDelegate;
+class ScrollbarPainterControllerDelegate;
+class ScrollbarPainterDelegate;
#endif
namespace WebCore {
+class Scrollbar;
+
class ScrollAnimatorMac : public ScrollAnimator {
public:
ScrollAnimatorMac(ScrollableArea*);
@@ -47,12 +60,72 @@ public:
virtual bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier);
virtual void scrollToOffsetWithoutAnimation(const FloatPoint&);
- // Called by the ScrollAnimationHelperDelegate.
- void immediateScrollToPoint(const FloatPoint& newPosition);
+#if ENABLE(RUBBER_BANDING)
+ virtual void handleWheelEvent(PlatformWheelEvent&);
+#if ENABLE(GESTURE_EVENTS)
+ virtual void handleGestureEvent(const PlatformGestureEvent&);
+#endif
+#endif
+ void immediateScrollToPoint(const FloatPoint& newPosition);
+ void immediateScrollByDeltaX(float deltaX);
+ void immediateScrollByDeltaY(float deltaY);
+
private:
RetainPtr<id> m_scrollAnimationHelper;
RetainPtr<ScrollAnimationHelperDelegate> m_scrollAnimationHelperDelegate;
+
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ RetainPtr<WKScrollbarPainterControllerRef> m_scrollbarPainterController;
+ RetainPtr<ScrollbarPainterControllerDelegate> m_scrollbarPainterControllerDelegate;
+ RetainPtr<id> m_scrollbarPainterDelegate;
+#endif
+
+ virtual void notityPositionChanged();
+ virtual void contentAreaWillPaint() const;
+ virtual void mouseEnteredContentArea() const;
+ virtual void mouseExitedContentArea() const;
+ virtual void mouseMovedInContentArea() const;
+ virtual void willStartLiveResize();
+ virtual void contentsResized() const;
+ virtual void willEndLiveResize();
+ virtual void contentAreaDidShow() const;
+ virtual void contentAreaDidHide() const;
+
+ virtual void didAddVerticalScrollbar(Scrollbar*);
+ virtual void willRemoveVerticalScrollbar(Scrollbar*);
+ virtual void didAddHorizontalScrollbar(Scrollbar*);
+ virtual void willRemoveHorizontalScrollbar(Scrollbar*);
+
+ float adjustScrollXPositionIfNecessary(float) const;
+ float adjustScrollYPositionIfNecessary(float) const;
+ FloatPoint adjustScrollPositionIfNecessary(const FloatPoint&) const;
+
+#if ENABLE(RUBBER_BANDING)
+ bool allowsVerticalStretching() const;
+ bool allowsHorizontalStretching() const;
+ bool pinnedInDirection(float deltaX, float deltaY);
+ void snapRubberBand();
+ void snapRubberBandTimerFired(Timer<ScrollAnimatorMac>*);
+ void smoothScrollWithEvent(PlatformWheelEvent&);
+ void beginScrollGesture();
+ void endScrollGesture();
+
+ bool m_inScrollGesture;
+ bool m_momentumScrollInProgress;
+ bool m_ignoreMomentumScrolls;
+ CFTimeInterval m_lastMomemtumScrollTimestamp;
+ FloatSize m_overflowScrollDelta;
+ FloatSize m_stretchScrollForce;
+ FloatSize m_momentumVelocity;
+
+ // Rubber band state.
+ CFTimeInterval m_startTime;
+ FloatSize m_startStretch;
+ FloatPoint m_origOrigin;
+ FloatSize m_origVelocity;
+ Timer<ScrollAnimatorMac> m_snapRubberBandTimer;
+#endif
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm b/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
index 59b333b..c1154d5 100644
--- a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
+++ b/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * 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
@@ -30,10 +30,20 @@
#include "ScrollAnimatorMac.h"
#include "FloatPoint.h"
+#include "IntRect.h"
+#include "PlatformGestureEvent.h"
+#include "PlatformWheelEvent.h"
+#include "ScrollView.h"
#include "ScrollableArea.h"
+#include "ScrollbarTheme.h"
+#include "ScrollbarThemeMac.h"
#include <wtf/PassOwnPtr.h>
+#include <wtf/UnusedParam.h>
-@interface NSObject (NSScrollAnimationHelperDetails)
+using namespace WebCore;
+using namespace std;
+
+@interface NSObject (ScrollAnimationHelperDetails)
- (id)initWithDelegate:(id)delegate;
- (void)_stopRun;
- (BOOL)_isAnimating;
@@ -44,18 +54,7 @@
{
WebCore::ScrollAnimatorMac* _animator;
}
-
- (id)initWithScrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator;
-
-- (NSRect)bounds;
-- (void)_immediateScrollToPoint:(NSPoint)newPosition;
-- (NSSize)convertSizeToBase:(NSSize)size;
-- (NSSize)convertSizeFromBase:(NSSize)size;
-
-- (id)superview; // Return nil.
-- (id)documentView; // Return nil.
-- (id)window; // Return nil.
-- (void)_recursiveRecomputeToolTips; // No-op.
@end
static NSSize abs(NSSize size)
@@ -80,14 +79,24 @@ static NSSize abs(NSSize size)
return self;
}
+- (void)scrollAnimatorDestroyed
+{
+ _animator = 0;
+}
+
- (NSRect)bounds
{
+ if (!_animator)
+ return NSZeroRect;
+
WebCore::FloatPoint currentPosition = _animator->currentPosition();
return NSMakeRect(currentPosition.x(), currentPosition.y(), 0, 0);
}
- (void)_immediateScrollToPoint:(NSPoint)newPosition
{
+ if (!_animator)
+ return;
_animator->immediateScrollToPoint(newPosition);
}
@@ -101,6 +110,16 @@ static NSSize abs(NSSize size)
return abs(size);
}
+- (NSSize)convertSizeToBacking:(NSSize)size
+{
+ return abs(size);
+}
+
+- (NSSize)convertSizeFromBacking:(NSSize)size
+{
+ return abs(size);
+}
+
- (id)superview
{
return nil;
@@ -122,6 +141,307 @@ static NSSize abs(NSSize size)
@end
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+
+@interface ScrollbarPainterControllerDelegate : NSObject
+{
+ WebCore::ScrollAnimatorMac* _animator;
+}
+- (id)initWithScrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator;
+@end
+
+@implementation ScrollbarPainterControllerDelegate
+
+- (id)initWithScrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator
+{
+ self = [super init];
+ if (!self)
+ return nil;
+
+ _animator = scrollAnimator;
+ return self;
+}
+
+- (void)scrollAnimatorDestroyed
+{
+ _animator = 0;
+}
+
+- (NSRect)contentAreaRectForScrollerImpPair:(id)scrollerImpPair
+{
+ UNUSED_PARAM(scrollerImpPair);
+ if (!_animator)
+ return NSZeroRect;
+
+ WebCore::IntSize contentsSize = _animator->scrollableArea()->contentsSize();
+ return NSMakeRect(0, 0, contentsSize.width(), contentsSize.height());
+}
+
+- (BOOL)inLiveResizeForScrollerImpPair:(id)scrollerImpPair
+{
+ UNUSED_PARAM(scrollerImpPair);
+ if (!_animator)
+ return NO;
+
+ return _animator->scrollableArea()->inLiveResize();
+}
+
+- (NSPoint)mouseLocationInContentAreaForScrollerImpPair:(id)scrollerImpPair
+{
+ UNUSED_PARAM(scrollerImpPair);
+ if (!_animator)
+ return NSZeroPoint;
+
+ return _animator->scrollableArea()->currentMousePosition();
+}
+
+- (NSPoint)scrollerImpPair:(id)scrollerImpPair convertContentPoint:(NSPoint)pointInContentArea toScrollerImp:(id)scrollerImp
+{
+ UNUSED_PARAM(scrollerImpPair);
+ if (!_animator)
+ return NSZeroPoint;
+
+ WebCore::Scrollbar* scrollbar = 0;
+ if (wkScrollbarPainterIsHorizontal((WKScrollbarPainterRef)scrollerImp))
+ scrollbar = _animator->scrollableArea()->horizontalScrollbar();
+ else
+ scrollbar = _animator->scrollableArea()->verticalScrollbar();
+
+ // It is possible to have a null scrollbar here since it is possible for this delegate
+ // method to be called between the moment when a scrollbar has been set to 0 and the
+ // moment when its destructor has been called. We should probably de-couple some
+ // of the clean-up work in ScrollbarThemeMac::unregisterScrollbar() to avoid this
+ // issue.
+ if (!scrollbar)
+ return WebCore::IntPoint();
+
+ return scrollbar->convertFromContainingView(WebCore::IntPoint(pointInContentArea));
+}
+
+- (void)scrollerImpPair:(id)scrollerImpPair setContentAreaNeedsDisplayInRect:(NSRect)rect
+{
+ UNUSED_PARAM(scrollerImpPair);
+ UNUSED_PARAM(rect);
+}
+
+- (void)scrollerImpPair:(id)scrollerImpPair updateScrollerStyleForNewRecommendedScrollerStyle:(NSScrollerStyle)newRecommendedScrollerStyle
+{
+ if (!_animator)
+ return;
+
+ WKScrollbarPainterControllerRef painterController = (WKScrollbarPainterControllerRef)scrollerImpPair;
+ WebCore::ScrollbarThemeMac* macTheme = (WebCore::ScrollbarThemeMac*)WebCore::ScrollbarTheme::nativeTheme();
+
+ WKScrollbarPainterRef oldVerticalPainter = wkVerticalScrollbarPainterForController(painterController);
+ if (oldVerticalPainter) {
+ WebCore::Scrollbar* verticalScrollbar = _animator->scrollableArea()->verticalScrollbar();
+ WKScrollbarPainterRef newVerticalPainter = wkMakeScrollbarReplacementPainter(oldVerticalPainter,
+ newRecommendedScrollerStyle,
+ verticalScrollbar->controlSize(),
+ false);
+ macTheme->setNewPainterForScrollbar(verticalScrollbar, newVerticalPainter);
+ }
+
+ WKScrollbarPainterRef oldHorizontalPainter = wkHorizontalScrollbarPainterForController(painterController);
+ if (oldHorizontalPainter) {
+ WebCore::Scrollbar* horizontalScrollbar = _animator->scrollableArea()->horizontalScrollbar();
+ WKScrollbarPainterRef newHorizontalPainter = wkMakeScrollbarReplacementPainter(oldHorizontalPainter,
+ newRecommendedScrollerStyle,
+ horizontalScrollbar->controlSize(),
+ true);
+ macTheme->setNewPainterForScrollbar(horizontalScrollbar, newHorizontalPainter);
+ }
+
+ wkSetScrollbarPainterControllerStyle(painterController, newRecommendedScrollerStyle);
+}
+
+@end
+
+@interface ScrollbarPartAnimation : NSAnimation
+{
+ RetainPtr<WKScrollbarPainterRef> _scrollerPainter;
+ WebCore::ScrollbarPart _part;
+ WebCore::ScrollAnimatorMac* _animator;
+ CGFloat _initialAlpha;
+ CGFloat _newAlpha;
+}
+- (id)initWithScrollbarPainter:(WKScrollbarPainterRef)scrollerPainter part:(WebCore::ScrollbarPart)part scrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator animateAlphaTo:(CGFloat)newAlpha duration:(NSTimeInterval)duration;
+@end
+
+@implementation ScrollbarPartAnimation
+
+- (id)initWithScrollbarPainter:(WKScrollbarPainterRef)scrollerPainter part:(WebCore::ScrollbarPart)part scrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator animateAlphaTo:(CGFloat)newAlpha duration:(NSTimeInterval)duration
+{
+ self = [super initWithDuration:duration animationCurve:NSAnimationEaseInOut];
+ if (!self)
+ return nil;
+
+ _scrollerPainter = scrollerPainter;
+ _part = part;
+ _animator = scrollAnimator;
+ _initialAlpha = _part == WebCore::ThumbPart ? wkScrollbarPainterKnobAlpha(_scrollerPainter.get()) : wkScrollbarPainterTrackAlpha(_scrollerPainter.get());
+ _newAlpha = newAlpha;
+
+ return self;
+}
+
+- (void)setCurrentProgress:(NSAnimationProgress)progress
+{
+ [super setCurrentProgress:progress];
+
+ if (!_animator)
+ return;
+
+ CGFloat currentAlpha;
+ if (_initialAlpha > _newAlpha)
+ currentAlpha = 1 - progress;
+ else
+ currentAlpha = progress;
+
+ if (_part == WebCore::ThumbPart)
+ wkSetScrollbarPainterKnobAlpha(_scrollerPainter.get(), currentAlpha);
+ else
+ wkSetScrollbarPainterTrackAlpha(_scrollerPainter.get(), currentAlpha);
+
+ // Invalidate the scrollbars so that they paint the animation
+ if (WebCore::Scrollbar* verticalScrollbar = _animator->scrollableArea()->verticalScrollbar())
+ _animator->scrollableArea()->invalidateScrollbarRect(verticalScrollbar, WebCore::IntRect(0, 0, verticalScrollbar->width(), verticalScrollbar->height()));
+ if (WebCore::Scrollbar* horizontalScrollbar = _animator->scrollableArea()->horizontalScrollbar())
+ _animator->scrollableArea()->invalidateScrollbarRect(horizontalScrollbar, WebCore::IntRect(0, 0, horizontalScrollbar->width(), horizontalScrollbar->height()));
+}
+
+- (void)scrollAnimatorDestroyed
+{
+ [self stopAnimation];
+ _animator = 0;
+}
+
+@end
+
+@interface ScrollbarPainterDelegate : NSObject<NSAnimationDelegate>
+{
+ WebCore::ScrollAnimatorMac* _animator;
+
+ RetainPtr<ScrollbarPartAnimation> _verticalKnobAnimation;
+ RetainPtr<ScrollbarPartAnimation> _horizontalKnobAnimation;
+
+ RetainPtr<ScrollbarPartAnimation> _verticalTrackAnimation;
+ RetainPtr<ScrollbarPartAnimation> _horizontalTrackAnimation;
+}
+- (id)initWithScrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator;
+@end
+
+@implementation ScrollbarPainterDelegate
+
+- (id)initWithScrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator
+{
+ self = [super init];
+ if (!self)
+ return nil;
+
+ _animator = scrollAnimator;
+ return self;
+}
+
+- (NSRect)convertRectToBacking:(NSRect)aRect
+{
+ return aRect;
+}
+
+- (NSRect)convertRectFromBacking:(NSRect)aRect
+{
+ return aRect;
+}
+
+- (CALayer *)layer
+{
+ if (!_animator)
+ return nil;
+ if (!_animator->scrollableArea()->scrollbarWillRenderIntoCompositingLayer())
+ return nil;
+
+ // FIXME: This should attempt to return an actual layer.
+ static CALayer *dummyLayer = [[CALayer alloc] init];
+ return dummyLayer;
+}
+
+- (void)setUpAnimation:(RetainPtr<ScrollbarPartAnimation>&)scrollbarPartAnimation scrollerPainter:(WKScrollbarPainterRef)scrollerPainter part:(WebCore::ScrollbarPart)part animateAlphaTo:(CGFloat)newAlpha duration:(NSTimeInterval)duration
+{
+ // If we are currently animating, stop
+ if (scrollbarPartAnimation) {
+ [scrollbarPartAnimation.get() stopAnimation];
+ scrollbarPartAnimation = nil;
+ }
+
+ scrollbarPartAnimation.adoptNS([[ScrollbarPartAnimation alloc] initWithScrollbarPainter:scrollerPainter
+ part:part
+ scrollAnimator:_animator
+ animateAlphaTo:newAlpha
+ duration:duration]);
+ [scrollbarPartAnimation.get() setAnimationBlockingMode:NSAnimationNonblocking];
+ [scrollbarPartAnimation.get() startAnimation];
+}
+
+- (void)scrollerImp:(id)scrollerImp animateKnobAlphaTo:(CGFloat)newKnobAlpha duration:(NSTimeInterval)duration
+{
+ if (!_animator)
+ 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
+ [self setUpAnimation:_verticalKnobAnimation scrollerPainter:scrollerPainter part:WebCore::ThumbPart animateAlphaTo:newKnobAlpha duration:duration];
+}
+
+- (void)scrollerImp:(id)scrollerImp animateTrackAlphaTo:(CGFloat)newTrackAlpha duration:(NSTimeInterval)duration
+{
+ if (!_animator)
+ 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
+ [self setUpAnimation:_verticalTrackAnimation scrollerPainter:scrollerPainter part:WebCore::BackTrackPart animateAlphaTo:newTrackAlpha duration:duration];
+}
+
+- (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()));
+
+ }
+}
+
+- (void)scrollAnimatorDestroyed
+{
+ _animator = 0;
+ [_verticalKnobAnimation.get() scrollAnimatorDestroyed];
+ [_horizontalKnobAnimation.get() scrollAnimatorDestroyed];
+ [_verticalTrackAnimation.get() scrollAnimatorDestroyed];
+ [_horizontalTrackAnimation.get() scrollAnimatorDestroyed];
+}
+
+@end
+#endif // #if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+
namespace WebCore {
PassOwnPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea)
@@ -131,13 +451,33 @@ PassOwnPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea
ScrollAnimatorMac::ScrollAnimatorMac(ScrollableArea* scrollableArea)
: ScrollAnimator(scrollableArea)
+#if ENABLE(RUBBER_BANDING)
+ , m_inScrollGesture(false)
+ , m_momentumScrollInProgress(false)
+ , m_ignoreMomentumScrolls(false)
+ , m_lastMomemtumScrollTimestamp(0)
+ , m_startTime(0)
+ , m_snapRubberBandTimer(this, &ScrollAnimatorMac::snapRubberBandTimerFired)
+#endif
{
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)
+ m_scrollbarPainterControllerDelegate.adoptNS([[ScrollbarPainterControllerDelegate alloc] initWithScrollAnimator:this]);
+ m_scrollbarPainterController = wkMakeScrollbarPainterController(m_scrollbarPainterControllerDelegate.get());
+ m_scrollbarPainterDelegate.adoptNS([[ScrollbarPainterDelegate alloc] initWithScrollAnimator:this]);
+#endif
}
ScrollAnimatorMac::~ScrollAnimatorMac()
{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ [m_scrollbarPainterControllerDelegate.get() scrollAnimatorDestroyed];
+ [(id)m_scrollbarPainterController.get() setDelegate:nil];
+ [m_scrollbarPainterDelegate.get() scrollAnimatorDestroyed];
+ [m_scrollAnimationHelperDelegate.get() scrollAnimatorDestroyed];
+#endif
}
bool ScrollAnimatorMac::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier)
@@ -167,16 +507,567 @@ bool ScrollAnimatorMac::scroll(ScrollbarOrientation orientation, ScrollGranulari
void ScrollAnimatorMac::scrollToOffsetWithoutAnimation(const FloatPoint& offset)
{
[m_scrollAnimationHelper.get() _stopRun];
- ScrollAnimator::scrollToOffsetWithoutAnimation(offset);
+ immediateScrollToPoint(offset);
+}
+
+float ScrollAnimatorMac::adjustScrollXPositionIfNecessary(float position) const
+{
+ if (!m_scrollableArea->constrainsScrollingToContentEdge())
+ return position;
+
+ return max<float>(min<float>(position, m_scrollableArea->contentsSize().width() - m_scrollableArea->visibleWidth()), 0);
+}
+
+float ScrollAnimatorMac::adjustScrollYPositionIfNecessary(float position) const
+{
+ if (!m_scrollableArea->constrainsScrollingToContentEdge())
+ return position;
+
+ return max<float>(min<float>(position, m_scrollableArea->contentsSize().height() - m_scrollableArea->visibleHeight()), 0);
+}
+
+FloatPoint ScrollAnimatorMac::adjustScrollPositionIfNecessary(const FloatPoint& position) const
+{
+ if (!m_scrollableArea->constrainsScrollingToContentEdge())
+ return position;
+
+ float newX = max<float>(min<float>(position.x(), m_scrollableArea->contentsSize().width() - m_scrollableArea->visibleWidth()), 0);
+ float newY = max<float>(min<float>(position.y(), m_scrollableArea->contentsSize().height() - m_scrollableArea->visibleHeight()), 0);
+
+ return FloatPoint(newX, newY);
}
void ScrollAnimatorMac::immediateScrollToPoint(const FloatPoint& newPosition)
{
- m_currentPosX = newPosition.x();
- m_currentPosY = newPosition.y();
+ FloatPoint adjustedPosition = adjustScrollPositionIfNecessary(newPosition);
+
+ m_currentPosX = adjustedPosition.x();
+ m_currentPosY = adjustedPosition.y();
notityPositionChanged();
}
+void ScrollAnimatorMac::immediateScrollByDeltaX(float deltaX)
+{
+ m_currentPosX = adjustScrollXPositionIfNecessary(m_currentPosX + deltaX);
+ notityPositionChanged();
+}
+
+void ScrollAnimatorMac::immediateScrollByDeltaY(float deltaY)
+{
+ m_currentPosY = adjustScrollYPositionIfNecessary(m_currentPosY + deltaY);
+ notityPositionChanged();
+}
+
+void ScrollAnimatorMac::notityPositionChanged()
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkContentAreaScrolled(m_scrollbarPainterController.get());
+#endif
+ ScrollAnimator::notityPositionChanged();
+}
+
+void ScrollAnimatorMac::contentAreaWillPaint() const
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkContentAreaWillPaint(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::mouseEnteredContentArea() const
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkMouseEnteredContentArea(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::mouseExitedContentArea() const
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkMouseExitedContentArea(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::mouseMovedInContentArea() const
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkMouseMovedInContentArea(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::willStartLiveResize()
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkWillStartLiveResize(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::contentsResized() const
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkContentAreaResized(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::willEndLiveResize()
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkWillEndLiveResize(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::contentAreaDidShow() const
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkContentAreaDidShow(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::contentAreaDidHide() const
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkContentAreaDidHide(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::didAddVerticalScrollbar(Scrollbar* scrollbar)
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ WKScrollbarPainterRef painter = static_cast<WebCore::ScrollbarThemeMac*>(WebCore::ScrollbarTheme::nativeTheme())->painterForScrollbar(scrollbar);
+ wkScrollbarPainterSetDelegate(painter, m_scrollbarPainterDelegate.get());
+ wkSetPainterForPainterController(m_scrollbarPainterController.get(), painter, false);
+ if (scrollableArea()->inLiveResize())
+ wkSetScrollbarPainterKnobAlpha(painter, 1);
+#else
+ UNUSED_PARAM(scrollbar);
+#endif
+}
+
+void ScrollAnimatorMac::willRemoveVerticalScrollbar(Scrollbar* scrollbar)
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ WKScrollbarPainterRef painter = static_cast<WebCore::ScrollbarThemeMac*>(WebCore::ScrollbarTheme::nativeTheme())->painterForScrollbar(scrollbar);
+ wkScrollbarPainterSetDelegate(painter, nil);
+ wkSetPainterForPainterController(m_scrollbarPainterController.get(), nil, false);
+#else
+ UNUSED_PARAM(scrollbar);
+#endif
+}
+
+void ScrollAnimatorMac::didAddHorizontalScrollbar(Scrollbar* scrollbar)
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ WKScrollbarPainterRef painter = static_cast<WebCore::ScrollbarThemeMac*>(WebCore::ScrollbarTheme::nativeTheme())->painterForScrollbar(scrollbar);
+ wkScrollbarPainterSetDelegate(painter, m_scrollbarPainterDelegate.get());
+ wkSetPainterForPainterController(m_scrollbarPainterController.get(), painter, true);
+ if (scrollableArea()->inLiveResize())
+ wkSetScrollbarPainterKnobAlpha(painter, 1);
+#else
+ UNUSED_PARAM(scrollbar);
+#endif
+}
+
+void ScrollAnimatorMac::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ WKScrollbarPainterRef painter = static_cast<WebCore::ScrollbarThemeMac*>(WebCore::ScrollbarTheme::nativeTheme())->painterForScrollbar(scrollbar);
+ wkScrollbarPainterSetDelegate(painter, nil);
+ wkSetPainterForPainterController(m_scrollbarPainterController.get(), nil, true);
+#else
+ UNUSED_PARAM(scrollbar);
+#endif
+}
+
+#if ENABLE(RUBBER_BANDING)
+
+static const float scrollVelocityZeroingTimeout = 0.10f;
+static const float rubberbandStiffness = 20;
+static const float rubberbandDirectionLockStretchRatio = 1;
+static const float rubberbandMinimumRequiredDeltaBeforeStretch = 10;
+static const float rubberbandAmplitude = 0.31f;
+static const float rubberbandPeriod = 1.6f;
+
+static float elasticDeltaForTimeDelta(float initialPosition, float initialVelocity, float elapsedTime)
+{
+ float amplitude = rubberbandAmplitude;
+ float period = rubberbandPeriod;
+ float criticalDampeningFactor = expf((-elapsedTime * rubberbandStiffness) / period);
+
+ return (initialPosition + (-initialVelocity * elapsedTime * amplitude)) * criticalDampeningFactor;
+}
+
+static float elasticDeltaForReboundDelta(float delta)
+{
+ float stiffness = std::max(rubberbandStiffness, 1.0f);
+ return delta / stiffness;
+}
+
+static float reboundDeltaForElasticDelta(float delta)
+{
+ return delta * rubberbandStiffness;
+}
+
+static float scrollWheelMultiplier()
+{
+ static float multiplier = -1;
+ if (multiplier < 0) {
+ multiplier = [[NSUserDefaults standardUserDefaults] floatForKey:@"NSScrollWheelMultiplier"];
+ if (multiplier <= 0)
+ multiplier = 1;
+ }
+ return multiplier;
+}
+
+void ScrollAnimatorMac::handleWheelEvent(PlatformWheelEvent& wheelEvent)
+{
+ if (!wheelEvent.hasPreciseScrollingDeltas()) {
+ ScrollAnimator::handleWheelEvent(wheelEvent);
+ return;
+ }
+
+ wheelEvent.accept();
+
+ bool isMometumScrollEvent = (wheelEvent.phase() != PlatformWheelEventPhaseNone);
+ if (m_ignoreMomentumScrolls && (isMometumScrollEvent || m_snapRubberBandTimer.isActive())) {
+ if (wheelEvent.phase() == PlatformWheelEventPhaseEnded)
+ m_ignoreMomentumScrolls = false;
+ return;
+ }
+
+ smoothScrollWithEvent(wheelEvent);
+}
+
+void ScrollAnimatorMac::handleGestureEvent(const PlatformGestureEvent& gestureEvent)
+{
+ if (gestureEvent.type() == PlatformGestureEvent::ScrollBeginType)
+ beginScrollGesture();
+ else
+ endScrollGesture();
+}
+
+bool ScrollAnimatorMac::pinnedInDirection(float deltaX, float deltaY)
+{
+ FloatSize limitDelta;
+ 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());
+ } 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());
+ }
+ } 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());
+ } 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());
+ }
+ }
+
+ if ((deltaX != 0 || deltaY != 0) && (limitDelta.width() < 1 && limitDelta.height() < 1))
+ return true;
+ return false;
+}
+
+bool ScrollAnimatorMac::allowsVerticalStretching() const
+{
+ Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
+ Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
+ if (((vScroller && vScroller->enabled()) || (!hScroller || !hScroller->enabled())))
+ return true;
+
+ return false;
+}
+
+bool ScrollAnimatorMac::allowsHorizontalStretching() const
+{
+ Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
+ Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
+ if (((hScroller && hScroller->enabled()) || (!vScroller || !vScroller->enabled())))
+ return true;
+
+ return false;
+}
+
+void ScrollAnimatorMac::smoothScrollWithEvent(PlatformWheelEvent& wheelEvent)
+{
+ float deltaX = m_overflowScrollDelta.width();
+ float deltaY = m_overflowScrollDelta.height();
+
+ // Reset overflow values because we may decide to remove delta at various points and put it into overflow.
+ m_overflowScrollDelta = FloatSize();
+
+ float eventCoallescedDeltaX = -wheelEvent.deltaX();
+ float eventCoallescedDeltaY = -wheelEvent.deltaY();
+
+ deltaX += eventCoallescedDeltaX;
+ deltaY += eventCoallescedDeltaY;
+
+ // Slightly prefer scrolling vertically by applying the = case to deltaY
+ if (fabsf(deltaY) >= fabsf(deltaX))
+ deltaX = 0;
+ else
+ deltaY = 0;
+
+ bool isVerticallyStretched = false;
+ bool isHorizontallyStretched = false;
+ bool shouldStretch = false;
+
+ IntSize stretchAmount = m_scrollableArea->overhangAmount();
+
+ isHorizontallyStretched = stretchAmount.width();
+ isVerticallyStretched = stretchAmount.height();
+
+ PlatformWheelEventPhase phase = wheelEvent.phase();
+
+ // If we are starting momentum scrolling then do some setup.
+ if (!m_momentumScrollInProgress && (phase == PlatformWheelEventPhaseBegan || phase == PlatformWheelEventPhaseChanged))
+ m_momentumScrollInProgress = true;
+
+ CFTimeInterval timeDelta = wheelEvent.timestamp() - m_lastMomemtumScrollTimestamp;
+ if (m_inScrollGesture || m_momentumScrollInProgress) {
+ if (m_lastMomemtumScrollTimestamp && timeDelta > 0 && timeDelta < scrollVelocityZeroingTimeout) {
+ m_momentumVelocity.setWidth(eventCoallescedDeltaX / (float)timeDelta);
+ m_momentumVelocity.setHeight(eventCoallescedDeltaY / (float)timeDelta);
+ m_lastMomemtumScrollTimestamp = wheelEvent.timestamp();
+ } else {
+ m_lastMomemtumScrollTimestamp = wheelEvent.timestamp();
+ m_momentumVelocity = FloatSize();
+ }
+
+ if (isVerticallyStretched) {
+ if (!isHorizontallyStretched && pinnedInDirection(deltaX, 0)) {
+ // Stretching only in the vertical.
+ if (deltaY != 0 && (fabsf(deltaX / deltaY) < rubberbandDirectionLockStretchRatio))
+ deltaX = 0;
+ else if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
+ deltaX = 0;
+ } else
+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
+ }
+ } else if (isHorizontallyStretched) {
+ // Stretching only in the horizontal.
+ if (pinnedInDirection(0, deltaY)) {
+ if (deltaX != 0 && (fabsf(deltaY / deltaX) < rubberbandDirectionLockStretchRatio))
+ deltaY = 0;
+ else if (fabsf(deltaY) < rubberbandMinimumRequiredDeltaBeforeStretch) {
+ m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY);
+ deltaY = 0;
+ } else
+ m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY);
+ }
+ } else {
+ // Not stretching at all yet.
+ if (pinnedInDirection(deltaX, deltaY)) {
+ if (fabsf(deltaY) >= fabsf(deltaX)) {
+ if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
+ deltaX = 0;
+ } else
+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
+ }
+ shouldStretch = true;
+ }
+ }
+ }
+
+ if (deltaX != 0 || deltaY != 0) {
+ if (!(shouldStretch || isVerticallyStretched || isHorizontallyStretched)) {
+ if (deltaY != 0) {
+ deltaY *= scrollWheelMultiplier();
+ immediateScrollByDeltaY(deltaY);
+ }
+ if (deltaX != 0) {
+ deltaX *= scrollWheelMultiplier();
+ immediateScrollByDeltaX(deltaX);
+ }
+ } else {
+ if (!allowsHorizontalStretching()) {
+ deltaX = 0;
+ eventCoallescedDeltaX = 0;
+ } else if ((deltaX != 0) && !isHorizontallyStretched && !pinnedInDirection(deltaX, 0)) {
+ deltaX *= scrollWheelMultiplier();
+
+ m_scrollableArea->setConstrainsScrollingToContentEdge(false);
+ immediateScrollByDeltaX(deltaX);
+ m_scrollableArea->setConstrainsScrollingToContentEdge(true);
+
+ deltaX = 0;
+ }
+
+ if (!allowsVerticalStretching()) {
+ deltaY = 0;
+ eventCoallescedDeltaY = 0;
+ } else if ((deltaY != 0) && !isVerticallyStretched && !pinnedInDirection(0, deltaY)) {
+ deltaY *= scrollWheelMultiplier();
+
+ m_scrollableArea->setConstrainsScrollingToContentEdge(false);
+ immediateScrollByDeltaY(deltaY);
+ m_scrollableArea->setConstrainsScrollingToContentEdge(true);
+
+ deltaY = 0;
+ }
+
+ IntSize stretchAmount = m_scrollableArea->overhangAmount();
+
+ if (m_momentumScrollInProgress) {
+ if ((pinnedInDirection(eventCoallescedDeltaX, eventCoallescedDeltaY) || (fabsf(eventCoallescedDeltaX) + fabsf(eventCoallescedDeltaY) <= 0)) && m_lastMomemtumScrollTimestamp) {
+ m_ignoreMomentumScrolls = true;
+ m_momentumScrollInProgress = false;
+ snapRubberBand();
+ }
+ }
+
+ m_stretchScrollForce.setWidth(m_stretchScrollForce.width() + deltaX);
+ m_stretchScrollForce.setHeight(m_stretchScrollForce.height() + deltaY);
+
+ FloatSize dampedDelta(ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.width())), ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.height())));
+ FloatPoint origOrigin = m_scrollableArea->visibleContentRect().location() - stretchAmount;
+ FloatPoint newOrigin = origOrigin + dampedDelta;
+
+ if (origOrigin != newOrigin) {
+ m_scrollableArea->setConstrainsScrollingToContentEdge(false);
+ immediateScrollToPoint(newOrigin);
+ m_scrollableArea->setConstrainsScrollingToContentEdge(true);
+ }
+ }
+ }
+
+ if (m_momentumScrollInProgress && phase == PlatformWheelEventPhaseEnded) {
+ m_momentumScrollInProgress = false;
+ m_ignoreMomentumScrolls = false;
+ m_lastMomemtumScrollTimestamp = 0;
+ }
+}
+
+void ScrollAnimatorMac::beginScrollGesture()
+{
+ m_inScrollGesture = true;
+ m_momentumScrollInProgress = false;
+ m_ignoreMomentumScrolls = false;
+ m_lastMomemtumScrollTimestamp = 0;
+ m_momentumVelocity = FloatSize();
+
+ IntSize stretchAmount = m_scrollableArea->overhangAmount();
+ m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(stretchAmount.width()));
+ m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(stretchAmount.height()));
+
+ m_overflowScrollDelta = FloatSize();
+
+ if (m_snapRubberBandTimer.isActive())
+ m_snapRubberBandTimer.stop();
+}
+
+void ScrollAnimatorMac::endScrollGesture()
+{
+ snapRubberBand();
+}
+
+void ScrollAnimatorMac::snapRubberBand()
+{
+ CFTimeInterval timeDelta = [[NSProcessInfo processInfo] systemUptime] - m_lastMomemtumScrollTimestamp;
+ if (m_lastMomemtumScrollTimestamp && timeDelta >= scrollVelocityZeroingTimeout)
+ m_momentumVelocity = FloatSize();
+
+ m_inScrollGesture = false;
+
+ if (m_snapRubberBandTimer.isActive())
+ return;
+
+ m_startTime = [NSDate timeIntervalSinceReferenceDate];
+ m_startStretch = FloatSize();
+ m_origOrigin = FloatPoint();
+ m_origVelocity = FloatSize();
+
+ m_snapRubberBandTimer.startRepeating(1.0/60.0);
+}
+
+static inline float roundTowardZero(float num)
+{
+ return num > 0 ? ceilf(num - 0.5f) : floorf(num + 0.5f);
+}
+
+static inline float roundToDevicePixelTowardZero(float num)
+{
+ float roundedNum = roundf(num);
+ if (fabs(num - roundedNum) < 0.125)
+ num = roundedNum;
+
+ return roundTowardZero(num);
+}
+
+void ScrollAnimatorMac::snapRubberBandTimerFired(Timer<ScrollAnimatorMac>*)
+{
+ if (!m_momentumScrollInProgress || m_ignoreMomentumScrolls) {
+ CFTimeInterval timeDelta = [NSDate timeIntervalSinceReferenceDate] - m_startTime;
+
+ if (m_startStretch == FloatSize()) {
+ m_startStretch = m_scrollableArea->overhangAmount();
+ if (m_startStretch == FloatSize()) {
+ m_snapRubberBandTimer.stop();
+ m_stretchScrollForce = FloatSize();
+ m_startTime = 0;
+ m_startStretch = FloatSize();
+ m_origOrigin = FloatPoint();
+ m_origVelocity = FloatSize();
+
+ return;
+ }
+
+ m_origOrigin = m_scrollableArea->visibleContentRect().location() - m_startStretch;
+ m_origVelocity = m_momentumVelocity;
+
+ // Just like normal scrolling, prefer vertical rubberbanding
+ if (fabsf(m_origVelocity.height()) >= fabsf(m_origVelocity.width()))
+ m_origVelocity.setWidth(0);
+
+ // Don't rubber-band horizontally if it's not possible to scroll horizontally
+ Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
+ if (!hScroller || !hScroller->enabled())
+ m_origVelocity.setWidth(0);
+
+ // Don't rubber-band vertically if it's not possible to scroll horizontally
+ Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
+ if (!vScroller || !vScroller->enabled())
+ m_origVelocity.setHeight(0);
+ }
+
+ FloatPoint delta(roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.width(), -m_origVelocity.width(), (float)timeDelta)),
+ roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.height(), -m_origVelocity.height(), (float)timeDelta)));
+
+ if (fabs(delta.x()) >= 1 || fabs(delta.y()) >= 1) {
+ FloatPoint newOrigin = m_origOrigin + delta;
+
+ m_scrollableArea->setConstrainsScrollingToContentEdge(false);
+ immediateScrollToPoint(newOrigin);
+ m_scrollableArea->setConstrainsScrollingToContentEdge(true);
+
+ FloatSize newStretch = m_scrollableArea->overhangAmount();
+
+ m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(newStretch.width()));
+ m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(newStretch.height()));
+ } else {
+ immediateScrollToPoint(m_origOrigin);
+
+ m_scrollableArea->didCompleteRubberBand(roundedIntSize(m_startStretch));
+
+ m_snapRubberBandTimer.stop();
+ m_stretchScrollForce = FloatSize();
+
+ m_startTime = 0;
+ m_startStretch = FloatSize();
+ m_origOrigin = FloatPoint();
+ m_origVelocity = FloatSize();
+ }
+ } else {
+ m_startTime = [NSDate timeIntervalSinceReferenceDate];
+ m_startStretch = FloatSize();
+ }
+}
+#endif
+
} // namespace WebCore
#endif // ENABLE(SMOOTH_SCROLLING)
diff --git a/Source/WebCore/platform/mac/ScrollViewMac.mm b/Source/WebCore/platform/mac/ScrollViewMac.mm
index 93ec971..ff2e14e 100644
--- a/Source/WebCore/platform/mac/ScrollViewMac.mm
+++ b/Source/WebCore/platform/mac/ScrollViewMac.mm
@@ -203,10 +203,10 @@ bool ScrollView::platformIsOffscreen() const
return ![platformWidget() window] || ![[platformWidget() window] isVisible];
}
-void ScrollView::platformSetScrollOrigin(const IntPoint& origin, bool updatePosition)
+void ScrollView::platformSetScrollOrigin(const IntPoint& origin, bool updatePositionAtAll, bool updatePositionSynchronously)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- [scrollView() setScrollOrigin:origin updatePosition:updatePosition];
+ [scrollView() setScrollOrigin:origin updatePositionAtAll:updatePositionAtAll immediately:updatePositionSynchronously];
END_BLOCK_OBJC_EXCEPTIONS;
}
diff --git a/Source/WebCore/platform/mac/ScrollbarThemeMac.h b/Source/WebCore/platform/mac/ScrollbarThemeMac.h
index 8b5412d..844a088 100644
--- a/Source/WebCore/platform/mac/ScrollbarThemeMac.h
+++ b/Source/WebCore/platform/mac/ScrollbarThemeMac.h
@@ -26,7 +26,9 @@
#ifndef ScrollbarThemeMac_h
#define ScrollbarThemeMac_h
+#include "HeaderDetection.h"
#include "ScrollbarThemeComposite.h"
+#include "WebCoreSystemInterface.h"
namespace WebCore {
@@ -50,6 +52,11 @@ public:
virtual void registerScrollbar(Scrollbar*);
virtual void unregisterScrollbar(Scrollbar*);
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ void setNewPainterForScrollbar(Scrollbar*, WKScrollbarPainterRef);
+ WKScrollbarPainterRef painterForScrollbar(Scrollbar*);
+#endif
+
protected:
virtual bool hasButtons(Scrollbar*);
virtual bool hasThumb(Scrollbar*);
diff --git a/Source/WebCore/platform/mac/ScrollbarThemeMac.mm b/Source/WebCore/platform/mac/ScrollbarThemeMac.mm
index 032d9f3..c35dfa0 100644
--- a/Source/WebCore/platform/mac/ScrollbarThemeMac.mm
+++ b/Source/WebCore/platform/mac/ScrollbarThemeMac.mm
@@ -29,17 +29,13 @@
#include "ImageBuffer.h"
#include "LocalCurrentGraphicsContext.h"
#include "PlatformMouseEvent.h"
+#include "ScrollAnimatorMac.h"
#include "ScrollView.h"
-#include "WebCoreSystemInterface.h"
#include <Carbon/Carbon.h>
#include <wtf/HashMap.h>
#include <wtf/StdLibExtras.h>
#include <wtf/UnusedParam.h>
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
-#define USE_WK_SCROLLBAR_PAINTER
-#endif
-
// FIXME: There are repainting problems due to Aqua scroll bar buttons' visual overflow.
using namespace std;
@@ -47,7 +43,7 @@ using namespace WebCore;
namespace WebCore {
-#if defined(USE_WK_SCROLLBAR_PAINTER)
+#if USE(WK_SCROLLBAR_PAINTER)
typedef HashMap<Scrollbar*, RetainPtr<WKScrollbarPainterRef> > ScrollbarPainterMap;
#else
typedef HashSet<Scrollbar*> ScrollbarPainterMap;
@@ -83,7 +79,7 @@ static ScrollbarPainterMap* scrollbarMap()
return;
ScrollbarPainterMap::iterator end = scrollbarMap()->end();
for (ScrollbarPainterMap::iterator it = scrollbarMap()->begin(); it != end; ++it) {
-#if defined(USE_WK_SCROLLBAR_PAINTER)
+#if USE(WK_SCROLLBAR_PAINTER)
it->first->styleChanged();
it->first->invalidate();
#else
@@ -117,13 +113,15 @@ ScrollbarTheme* ScrollbarTheme::nativeTheme()
}
// FIXME: Get these numbers from CoreUI.
-static int cScrollbarThickness[] = { 15, 11 };
static int cRealButtonLength[] = { 28, 21 };
-static int cButtonInset[] = { 14, 11 };
static int cButtonHitInset[] = { 3, 2 };
// cRealButtonLength - cButtonInset
static int cButtonLength[] = { 14, 10 };
+#if !USE(WK_SCROLLBAR_PAINTER)
+static int cScrollbarThickness[] = { 15, 11 };
+static int cButtonInset[] = { 14, 11 };
static int cThumbMinLength[] = { 26, 20 };
+#endif
static int cOuterButtonLength[] = { 16, 14 }; // The outer button in a double button pair is a bit bigger.
static int cOuterButtonOverlap = 2;
@@ -131,13 +129,15 @@ static int cOuterButtonOverlap = 2;
static float gInitialButtonDelay = 0.5f;
static float gAutoscrollButtonDelay = 0.05f;
static bool gJumpOnTrackClick = false;
+
+#if USE(WK_SCROLLBAR_PAINTER)
+static ScrollbarButtonsPlacement gButtonPlacement = ScrollbarButtonsNone;
+#else
static ScrollbarButtonsPlacement gButtonPlacement = ScrollbarButtonsDoubleEnd;
+#endif
static void updateArrowPlacement()
{
-#if defined(USE_WK_SCROLLBAR_PAINTER)
- gButtonPlacement = ScrollbarButtonsNone;
-#else
NSString *buttonPlacement = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleScrollBarVariant"];
if ([buttonPlacement isEqualToString:@"Single"])
gButtonPlacement = ScrollbarButtonsSingle;
@@ -145,16 +145,20 @@ static void updateArrowPlacement()
gButtonPlacement = ScrollbarButtonsDoubleStart;
else if ([buttonPlacement isEqualToString:@"DoubleBoth"])
gButtonPlacement = ScrollbarButtonsDoubleBoth;
- else
- gButtonPlacement = ScrollbarButtonsDoubleEnd; // The default is ScrollbarButtonsDoubleEnd.
+ else {
+#if USE(WK_SCROLLBAR_PAINTER)
+ gButtonPlacement = ScrollbarButtonsNone;
+#else
+ gButtonPlacement = ScrollbarButtonsDoubleEnd;
#endif
+ }
}
void ScrollbarThemeMac::registerScrollbar(Scrollbar* scrollbar)
{
-#if defined(USE_WK_SCROLLBAR_PAINTER)
- WKScrollbarPainterRef scrollbarPainter = wkMakeScrollbarPainter(scrollbar->controlSize(),
- scrollbar->orientation() == HorizontalScrollbar);
+#if USE(WK_SCROLLBAR_PAINTER)
+ bool isHorizontal = scrollbar->orientation() == HorizontalScrollbar;
+ WKScrollbarPainterRef scrollbarPainter = wkMakeScrollbarPainter(scrollbar->controlSize(), isHorizontal);
scrollbarMap()->add(scrollbar, scrollbarPainter);
#else
scrollbarMap()->add(scrollbar);
@@ -163,9 +167,22 @@ void ScrollbarThemeMac::registerScrollbar(Scrollbar* scrollbar)
void ScrollbarThemeMac::unregisterScrollbar(Scrollbar* scrollbar)
{
+
scrollbarMap()->remove(scrollbar);
}
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+void ScrollbarThemeMac::setNewPainterForScrollbar(Scrollbar* scrollbar, WKScrollbarPainterRef newPainter)
+{
+ scrollbarMap()->set(scrollbar, newPainter);
+}
+
+WKScrollbarPainterRef ScrollbarThemeMac::painterForScrollbar(Scrollbar* scrollbar)
+{
+ return scrollbarMap()->get(scrollbar).get();
+}
+#endif
+
ScrollbarThemeMac::ScrollbarThemeMac()
{
static bool initialized;
@@ -192,13 +209,20 @@ void ScrollbarThemeMac::preferencesChanged()
int ScrollbarThemeMac::scrollbarThickness(ScrollbarControlSize controlSize)
{
+#if USE(WK_SCROLLBAR_PAINTER)
+ return wkScrollbarThickness(controlSize);
+#else
return cScrollbarThickness[controlSize];
+#endif
}
bool ScrollbarThemeMac::usesOverlayScrollbars() const
{
- // FIXME: This should be enabled when <rdar://problem/8492788> is resolved.
+#if USE(WK_SCROLLBAR_PAINTER)
+ return wkScrollbarPainterUsesOverlayScrollers();
+#else
return false;
+#endif
}
double ScrollbarThemeMac::initialAutoscrollTimerDelay()
@@ -218,20 +242,29 @@ ScrollbarButtonsPlacement ScrollbarThemeMac::buttonsPlacement() const
bool ScrollbarThemeMac::hasButtons(Scrollbar* scrollbar)
{
- return scrollbar->enabled() && (scrollbar->orientation() == HorizontalScrollbar ?
- scrollbar->width() :
- scrollbar->height()) >= 2 * (cRealButtonLength[scrollbar->controlSize()] - cButtonHitInset[scrollbar->controlSize()]);
+ return scrollbar->enabled() && gButtonPlacement != ScrollbarButtonsNone
+ && (scrollbar->orientation() == HorizontalScrollbar
+ ? scrollbar->width()
+ : scrollbar->height()) >= 2 * (cRealButtonLength[scrollbar->controlSize()] - cButtonHitInset[scrollbar->controlSize()]);
}
bool ScrollbarThemeMac::hasThumb(Scrollbar* scrollbar)
{
+ int minLengthForThumb;
+#if USE(WK_SCROLLBAR_PAINTER)
+ minLengthForThumb = wkScrollbarMinimumTotalLengthNeededForThumb(scrollbarMap()->get(scrollbar).get());
+#else
+ minLengthForThumb = 2 * cButtonInset[scrollbar->controlSize()] + cThumbMinLength[scrollbar->controlSize()] + 1;
+#endif
return scrollbar->enabled() && (scrollbar->orientation() == HorizontalScrollbar ?
scrollbar->width() :
- scrollbar->height()) >= 2 * cButtonInset[scrollbar->controlSize()] + cThumbMinLength[scrollbar->controlSize()] + 1;
+ scrollbar->height()) >= minLengthForThumb;
}
static IntRect buttonRepaintRect(const IntRect& buttonRect, ScrollbarOrientation orientation, ScrollbarControlSize controlSize, bool start)
{
+ ASSERT(gButtonPlacement != ScrollbarButtonsNone);
+
IntRect paintRect(buttonRect);
if (orientation == HorizontalScrollbar) {
paintRect.setWidth(cRealButtonLength[controlSize]);
@@ -359,7 +392,11 @@ IntRect ScrollbarThemeMac::trackRect(Scrollbar* scrollbar, bool painting)
int ScrollbarThemeMac::minimumThumbLength(Scrollbar* scrollbar)
{
+#if USE(WK_SCROLLBAR_PAINTER)
+ return wkScrollbarMinimumThumbLength(scrollbarMap()->get(scrollbar).get());
+#else
return cThumbMinLength[scrollbar->controlSize()];
+#endif
}
bool ScrollbarThemeMac::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& evt)
@@ -391,15 +428,32 @@ static int scrollbarPartToHIPressedState(ScrollbarPart part)
bool ScrollbarThemeMac::paint(Scrollbar* scrollbar, GraphicsContext* context, const IntRect& damageRect)
{
-#if defined(USE_WK_SCROLLBAR_PAINTER)
+#if USE(WK_SCROLLBAR_PAINTER)
+ float value = 0.0f;
+ float totalSize = 0.0f;
+
+ if (scrollbar->currentPos() < 0) {
+ // Scrolled past the top.
+ value = 0.0f;
+ totalSize = scrollbar->totalSize() - scrollbar->currentPos();
+ } else if (scrollbar->visibleSize() + scrollbar->currentPos() > scrollbar->totalSize()) {
+ // Scrolled past the bottom.
+ value = 1.0f;
+ totalSize = scrollbar->visibleSize() + scrollbar->currentPos();
+ } else {
+ // Within the bounds of the scrollable area.
+ value = scrollbar->currentPos() / scrollbar->maximum();
+ totalSize = scrollbar->totalSize();
+ }
+
context->save();
context->clip(damageRect);
context->translate(scrollbar->frameRect().x(), scrollbar->frameRect().y());
LocalCurrentGraphicsContext localContext(context);
wkScrollbarPainterPaint(scrollbarMap()->get(scrollbar).get(),
scrollbar->enabled(),
- scrollbar->currentPos() / scrollbar->maximum(),
- static_cast<CGFloat>(scrollbar->visibleSize()) / scrollbar->totalSize(),
+ value,
+ static_cast<CGFloat>(scrollbar->visibleSize()) / totalSize,
scrollbar->frameRect());
context->restore();
return true;
@@ -409,9 +463,27 @@ bool ScrollbarThemeMac::paint(Scrollbar* scrollbar, GraphicsContext* context, co
trackInfo.version = 0;
trackInfo.kind = scrollbar->controlSize() == RegularScrollbar ? kThemeMediumScrollBar : kThemeSmallScrollBar;
trackInfo.bounds = scrollbar->frameRect();
+
+ float maximum = 0.0f;
+ float position = 0.0f;
+ if (scrollbar->currentPos() < 0) {
+ // Scrolled past the top.
+ maximum = (scrollbar->totalSize() - scrollbar->currentPos()) - scrollbar->visibleSize();
+ position = 0;
+ } else if (scrollbar->visibleSize() + scrollbar->currentPos() > scrollbar->totalSize()) {
+ // Scrolled past the bottom.
+ maximum = scrollbar->currentPos();
+ position = maximum;
+ } else {
+ // Within the bounds of the scrollable area.
+ maximum = scrollbar->maximum();
+ position = scrollbar->currentPos();
+ }
+
trackInfo.min = 0;
- trackInfo.max = scrollbar->maximum();
- trackInfo.value = scrollbar->currentPos();
+ trackInfo.max = static_cast<int>(maximum);
+ trackInfo.value = static_cast<int>(position);
+
trackInfo.trackInfo.scrollbar.viewsize = scrollbar->visibleSize();
trackInfo.attributes = 0;
if (scrollbar->orientation() == HorizontalScrollbar)
diff --git a/Source/WebCore/platform/mac/WebCoreSystemInterface.h b/Source/WebCore/platform/mac/WebCoreSystemInterface.h
index 045864a..e6d6cf6 100644
--- a/Source/WebCore/platform/mac/WebCoreSystemInterface.h
+++ b/Source/WebCore/platform/mac/WebCoreSystemInterface.h
@@ -147,6 +147,8 @@ extern void (*wkSignalCFReadStreamEnd)(CFReadStreamRef stream);
extern void (*wkSignalCFReadStreamError)(CFReadStreamRef stream, CFStreamError *error);
extern void (*wkSignalCFReadStreamHasBytes)(CFReadStreamRef stream);
extern unsigned (*wkInitializeMaximumHTTPConnectionCountPerHost)(unsigned preferredConnectionCount);
+extern int (*wkGetHTTPPipeliningPriority)(NSURLRequest *);
+extern void (*wkSetHTTPPipeliningPriority)(NSMutableURLRequest *, int priority);
extern void (*wkSetCONNECTProxyForStream)(CFReadStreamRef, CFStringRef proxyHost, CFNumberRef proxyPort);
extern void (*wkSetCONNECTProxyAuthorizationForStream)(CFReadStreamRef, CFStringRef proxyAuthorizationString);
extern CFHTTPMessageRef (*wkCopyCONNECTProxyResponse)(CFReadStreamRef, CFURLRef responseURL);
@@ -189,9 +191,50 @@ extern CGImageRef (*wkIOSurfaceContextCreateImage)(CGContextRef context);
typedef struct __WKScrollbarPainter *WKScrollbarPainterRef;
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 int (*wkScrollbarThickness)(int controlSize);
+extern int (*wkScrollbarMinimumThumbLength)(WKScrollbarPainterRef);
+extern int (*wkScrollbarMinimumTotalLengthNeededForThumb)(WKScrollbarPainterRef);
+extern CGFloat (*wkScrollbarPainterKnobAlpha)(WKScrollbarPainterRef);
+extern void (*wkSetScrollbarPainterKnobAlpha)(WKScrollbarPainterRef, CGFloat);
+extern CGFloat (*wkScrollbarPainterTrackAlpha)(WKScrollbarPainterRef);
+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);
+extern WKScrollbarPainterRef (*wkHorizontalScrollbarPainterForController)(WKScrollbarPainterControllerRef);
+extern void (*wkSetScrollbarPainterControllerStyle)(WKScrollbarPainterControllerRef, int newStyle);
+extern void (*wkContentAreaScrolled)(WKScrollbarPainterControllerRef);
+extern void (*wkContentAreaWillPaint)(WKScrollbarPainterControllerRef);
+extern void (*wkMouseEnteredContentArea)(WKScrollbarPainterControllerRef);
+extern void (*wkMouseExitedContentArea)(WKScrollbarPainterControllerRef);
+extern void (*wkMouseMovedInContentArea)(WKScrollbarPainterControllerRef);
+extern void (*wkWillStartLiveResize)(WKScrollbarPainterControllerRef);
+extern void (*wkContentAreaResized)(WKScrollbarPainterControllerRef);
+extern void (*wkWillEndLiveResize)(WKScrollbarPainterControllerRef);
+extern void (*wkContentAreaDidShow)(WKScrollbarPainterControllerRef);
+extern void (*wkContentAreaDidHide)(WKScrollbarPainterControllerRef);
+
+extern bool (*wkScrollbarPainterUsesOverlayScrollers)(void);
#endif
+extern void (*wkUnregisterUniqueIdForElement)(id element);
+extern void (*wkAccessibilityHandleFocusChanged)(void);
+extern CFTypeID (*wkGetAXTextMarkerTypeID)(void);
+extern CFTypeID (*wkGetAXTextMarkerRangeTypeID)(void);
+extern CFTypeRef (*wkCreateAXTextMarkerRange)(CFTypeRef start, CFTypeRef end);
+extern CFTypeRef (*wkCopyAXTextMarkerRangeStart)(CFTypeRef range);
+extern CFTypeRef (*wkCopyAXTextMarkerRangeEnd)(CFTypeRef range);
+extern CFTypeRef (*wkCreateAXTextMarker)(const void *bytes, size_t len);
+extern BOOL (*wkGetBytesFromAXTextMarker)(CFTypeRef textMarker, void *bytes, size_t length);
+extern AXUIElementRef (*wkCreateAXUIElementRef)(id element);
+
}
#endif
diff --git a/Source/WebCore/platform/mac/WebCoreSystemInterface.mm b/Source/WebCore/platform/mac/WebCoreSystemInterface.mm
index 047827f..24bdcb1 100644
--- a/Source/WebCore/platform/mac/WebCoreSystemInterface.mm
+++ b/Source/WebCore/platform/mac/WebCoreSystemInterface.mm
@@ -89,6 +89,8 @@ void (*wkSetNSURLConnectionDefersCallbacks)(NSURLConnection *, BOOL);
void (*wkSetNSURLRequestShouldContentSniff)(NSMutableURLRequest *, BOOL);
id (*wkCreateNSURLConnectionDelegateProxy)(void);
unsigned (*wkInitializeMaximumHTTPConnectionCountPerHost)(unsigned preferredConnectionCount);
+int (*wkGetHTTPPipeliningPriority)(NSURLRequest *);
+void (*wkSetHTTPPipeliningPriority)(NSMutableURLRequest *, int priority);
void (*wkSetCONNECTProxyForStream)(CFReadStreamRef, CFStringRef proxyHost, CFNumberRef proxyPort);
void (*wkSetCONNECTProxyAuthorizationForStream)(CFReadStreamRef, CFStringRef proxyAuthorizationString);
CFHTTPMessageRef (*wkCopyCONNECTProxyResponse)(CFReadStreamRef, CFURLRef responseURL);
@@ -127,5 +129,46 @@ CGContextRef (*wkIOSurfaceContextCreate)(IOSurfaceRef surface, unsigned width, u
CGImageRef (*wkIOSurfaceContextCreateImage)(CGContextRef context);
WKScrollbarPainterRef (*wkMakeScrollbarPainter)(int controlSize, bool isHorizontal);
+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);
+int (*wkScrollbarThickness)(int controlSize);
+int (*wkScrollbarMinimumThumbLength)(WKScrollbarPainterRef);
+int (*wkScrollbarMinimumTotalLengthNeededForThumb)(WKScrollbarPainterRef);
+CGFloat (*wkScrollbarPainterKnobAlpha)(WKScrollbarPainterRef);
+void (*wkSetScrollbarPainterKnobAlpha)(WKScrollbarPainterRef, CGFloat);
+CGFloat (*wkScrollbarPainterTrackAlpha)(WKScrollbarPainterRef);
+void (*wkSetScrollbarPainterTrackAlpha)(WKScrollbarPainterRef, CGFloat);
+bool (*wkScrollbarPainterIsHorizontal)(WKScrollbarPainterRef);
+void (*wkScrollbarPainterSetOverlayState)(WKScrollbarPainterRef, int overlayScrollerState);
+
+WKScrollbarPainterControllerRef (*wkMakeScrollbarPainterController)(id painterControllerDelegate);
+void (*wkSetPainterForPainterController)(WKScrollbarPainterControllerRef, WKScrollbarPainterRef, bool isHorizontal);
+WKScrollbarPainterRef (*wkVerticalScrollbarPainterForController)(WKScrollbarPainterControllerRef);
+WKScrollbarPainterRef (*wkHorizontalScrollbarPainterForController)(WKScrollbarPainterControllerRef);
+void (*wkSetScrollbarPainterControllerStyle)(WKScrollbarPainterControllerRef, int newStyle);
+void (*wkContentAreaScrolled)(WKScrollbarPainterControllerRef);
+void (*wkContentAreaWillPaint)(WKScrollbarPainterControllerRef);
+void (*wkMouseEnteredContentArea)(WKScrollbarPainterControllerRef);
+void (*wkMouseExitedContentArea)(WKScrollbarPainterControllerRef);
+void (*wkMouseMovedInContentArea)(WKScrollbarPainterControllerRef);
+void (*wkWillStartLiveResize)(WKScrollbarPainterControllerRef);
+void (*wkContentAreaResized)(WKScrollbarPainterControllerRef);
+void (*wkWillEndLiveResize)(WKScrollbarPainterControllerRef);
+void (*wkContentAreaDidShow)(WKScrollbarPainterControllerRef);
+void (*wkContentAreaDidHide)(WKScrollbarPainterControllerRef);
+
+bool (*wkScrollbarPainterUsesOverlayScrollers)(void);
#endif
+
+void (*wkUnregisterUniqueIdForElement)(id element);
+void (*wkAccessibilityHandleFocusChanged)(void);
+CFTypeID (*wkGetAXTextMarkerTypeID)(void);
+CFTypeID (*wkGetAXTextMarkerRangeTypeID)(void);
+CFTypeRef (*wkCreateAXTextMarkerRange)(CFTypeRef start, CFTypeRef end);
+CFTypeRef (*wkCopyAXTextMarkerRangeStart)(CFTypeRef range);
+CFTypeRef (*wkCopyAXTextMarkerRangeEnd)(CFTypeRef range);
+CFTypeRef (*wkCreateAXTextMarker)(const void *bytes, size_t len);
+BOOL (*wkGetBytesFromAXTextMarker)(CFTypeRef textMarker, void *bytes, size_t length);
+AXUIElementRef (*wkCreateAXUIElementRef)(id element);
+
diff --git a/Source/WebCore/platform/mac/WheelEventMac.mm b/Source/WebCore/platform/mac/WheelEventMac.mm
index d4fc698..74265d1 100644
--- a/Source/WebCore/platform/mac/WheelEventMac.mm
+++ b/Source/WebCore/platform/mac/WheelEventMac.mm
@@ -64,6 +64,7 @@ PlatformWheelEvent::PlatformWheelEvent(NSEvent* event, NSView *windowView)
, m_altKey([event modifierFlags] & NSAlternateKeyMask)
, m_metaKey([event modifierFlags] & NSCommandKeyMask)
, m_phase(phaseForEvent(event))
+ , m_timestamp([event timestamp])
{
BOOL continuous;
@@ -71,11 +72,13 @@ PlatformWheelEvent::PlatformWheelEvent(NSEvent* event, NSView *windowView)
if (continuous) {
m_wheelTicksX = m_deltaX / static_cast<float>(Scrollbar::pixelsPerLineStep());
m_wheelTicksY = m_deltaY / static_cast<float>(Scrollbar::pixelsPerLineStep());
+ m_hasPreciseScrollingDeltas = true;
} else {
m_wheelTicksX = m_deltaX;
m_wheelTicksY = m_deltaY;
m_deltaX *= static_cast<float>(Scrollbar::pixelsPerLineStep());
m_deltaY *= static_cast<float>(Scrollbar::pixelsPerLineStep());
+ m_hasPreciseScrollingDeltas = false;
}
}
diff --git a/Source/WebCore/platform/mac/WidgetMac.mm b/Source/WebCore/platform/mac/WidgetMac.mm
index f3c951a..96bcde2 100644
--- a/Source/WebCore/platform/mac/WidgetMac.mm
+++ b/Source/WebCore/platform/mac/WidgetMac.mm
@@ -252,7 +252,7 @@ void Widget::paint(GraphicsContext* p, const IntRect& r)
IntRect dirtyRect = r;
dirtyRect.move(-transformOrigin.x(), -transformOrigin.y());
if (![view isFlipped])
- dirtyRect.setY([view bounds].size.height - dirtyRect.bottom());
+ dirtyRect.setY([view bounds].size.height - dirtyRect.maxY());
[view displayRectIgnoringOpacity:dirtyRect];
@@ -296,7 +296,7 @@ void Widget::paint(GraphicsContext* p, const IntRect& r)
IntRect dirtyRect = r;
dirtyRect.move(-transformOrigin.x(), -transformOrigin.y());
if (![view isFlipped])
- dirtyRect.setY([view bounds].size.height - dirtyRect.bottom());
+ dirtyRect.setY([view bounds].size.height - dirtyRect.maxY());
BEGIN_BLOCK_OBJC_EXCEPTIONS;
{
diff --git a/Source/WebCore/platform/network/BlobRegistryImpl.cpp b/Source/WebCore/platform/network/BlobRegistryImpl.cpp
index 2c4e8fa..83517f1 100644
--- a/Source/WebCore/platform/network/BlobRegistryImpl.cpp
+++ b/Source/WebCore/platform/network/BlobRegistryImpl.cpp
@@ -68,7 +68,9 @@ PassRefPtr<ResourceHandle> BlobRegistryImpl::createResourceHandle(const Resource
if (!shouldLoadResource(request))
return 0;
- return BlobResourceHandle::create(m_blobs.get(request.url().string()), request, client);
+ RefPtr<BlobResourceHandle> handle = BlobResourceHandle::create(m_blobs.get(request.url().string()), request, client);
+ handle->start();
+ return handle.release();
}
bool BlobRegistryImpl::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
diff --git a/Source/WebCore/platform/network/BlobResourceHandle.cpp b/Source/WebCore/platform/network/BlobResourceHandle.cpp
index 753052a..24c9088 100644
--- a/Source/WebCore/platform/network/BlobResourceHandle.cpp
+++ b/Source/WebCore/platform/network/BlobResourceHandle.cpp
@@ -138,11 +138,6 @@ void BlobResourceHandle::loadResourceSynchronously(PassRefPtr<BlobStorageData> b
handle->start();
}
-static void delayedStart(void* context)
-{
- static_cast<BlobResourceHandle*>(context)->start();
-}
-
BlobResourceHandle::BlobResourceHandle(PassRefPtr<BlobStorageData> blobData, const ResourceRequest& request, ResourceHandleClient* client, bool async)
: ResourceHandle(request, client, false, false)
, m_blobData(blobData)
@@ -158,11 +153,9 @@ BlobResourceHandle::BlobResourceHandle(PassRefPtr<BlobStorageData> blobData, con
, m_readItemCount(0)
, m_fileOpened(false)
{
- if (m_async) {
- // We need to take a ref.
+ if (m_async)
m_asyncStream = client->createAsyncFileStream(this);
- callOnMainThread(delayedStart, this);
- } else
+ else
m_stream = FileStream::create();
}
@@ -187,10 +180,32 @@ void BlobResourceHandle::cancel()
}
m_aborted = true;
+
+ ResourceHandle::cancel();
+}
+
+void delayedStartBlobResourceHandle(void* context)
+{
+ RefPtr<BlobResourceHandle> handle = adoptRef(static_cast<BlobResourceHandle*>(context));
+ handle->doStart();
}
void BlobResourceHandle::start()
{
+ if (m_async) {
+ // Keep BlobResourceHandle alive until delayedStartBlobResourceHandle runs.
+ ref();
+
+ // Finish this async call quickly and return.
+ callOnMainThread(delayedStartBlobResourceHandle, this);
+ return;
+ }
+
+ doStart();
+}
+
+void BlobResourceHandle::doStart()
+{
// Do not continue if the request is aborted or an error occurs.
if (m_aborted || m_errorCode)
return;
@@ -578,10 +593,23 @@ void BlobResourceHandle::notifyFail(int errorCode)
client()->didFail(this, ResourceError(String(), errorCode, firstRequest().url(), String()));
}
+static void doNotifyFinish(void* context)
+{
+ BlobResourceHandle* handle = static_cast<BlobResourceHandle*>(context);
+ if (handle->client())
+ handle->client()->didFinishLoading(handle, 0);
+}
+
void BlobResourceHandle::notifyFinish()
{
- if (client())
- client()->didFinishLoading(this, 0);
+ if (m_async) {
+ // Schedule to notify the client from a standalone function because the client might dispose the handle immediately from the callback function
+ // while we still have BlobResourceHandle calls in the stack.
+ callOnMainThread(doNotifyFinish, this);
+ return;
+ }
+
+ doNotifyFinish(this);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/BlobResourceHandle.h b/Source/WebCore/platform/network/BlobResourceHandle.h
index 63e8578..1e9e94a 100644
--- a/Source/WebCore/platform/network/BlobResourceHandle.h
+++ b/Source/WebCore/platform/network/BlobResourceHandle.h
@@ -69,9 +69,12 @@ public:
int readSync(char*, int);
private:
+ friend void delayedStartBlobResourceHandle(void*);
+
BlobResourceHandle(PassRefPtr<BlobStorageData>, const ResourceRequest&, ResourceHandleClient*, bool async);
virtual ~BlobResourceHandle();
+ void doStart();
void getSizeForNext();
void seek();
void consumeData(const char* data, int bytesRead);
diff --git a/Source/WebCore/platform/network/FormData.cpp b/Source/WebCore/platform/network/FormData.cpp
index 16f98ad..9784b7f 100644
--- a/Source/WebCore/platform/network/FormData.cpp
+++ b/Source/WebCore/platform/network/FormData.cpp
@@ -209,14 +209,16 @@ void FormData::appendKeyValuePairItems(const FormDataList& list, const TextEncod
name = file->webkitRelativePath().isEmpty() ? file->name() : file->webkitRelativePath();
#else
name = file->name();
-#endif
-
+#endif
// Let the application specify a filename if it's going to generate a replacement file for the upload.
- if (Page* page = document->page()) {
- String generatedFileName;
- shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(file->path(), generatedFileName);
- if (shouldGenerateFile)
- name = generatedFileName;
+ const String& path = file->path();
+ if (!path.isEmpty()) {
+ if (Page* page = document->page()) {
+ String generatedFileName;
+ shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(path, generatedFileName);
+ if (shouldGenerateFile)
+ name = generatedFileName;
+ }
}
} else {
// For non-file blob, use the identifier part of the URL as the name.
@@ -364,7 +366,9 @@ static void encode(Encoder& encoder, const FormDataElement& element)
static bool decode(Decoder& decoder, FormDataElement& element)
{
- uint32_t type = element.m_type;
+ uint32_t type;
+ if (!decoder.decodeUInt32(type))
+ return false;
switch (type) {
case FormDataElement::data: {
@@ -432,7 +436,7 @@ void FormData::encodeForBackForward(Encoder& encoder) const
encoder.encodeBool(m_hasGeneratedFiles);
- encoder.encodeBool(m_identifier);
+ encoder.encodeInt64(m_identifier);
}
PassRefPtr<FormData> FormData::decodeForBackForward(Decoder& decoder)
diff --git a/Source/WebCore/platform/network/FormDataBuilder.cpp b/Source/WebCore/platform/network/FormDataBuilder.cpp
index da28fc2..e973f99 100644
--- a/Source/WebCore/platform/network/FormDataBuilder.cpp
+++ b/Source/WebCore/platform/network/FormDataBuilder.cpp
@@ -94,10 +94,7 @@ TextEncoding FormDataBuilder::encodingFromAcceptCharset(const String& acceptChar
return encoding;
}
- if (Frame* frame = document->frame())
- return frame->loader()->writer()->encoding();
-
- return Latin1Encoding();
+ return document->inputEncoding();
}
Vector<char> FormDataBuilder::generateUniqueBoundaryString()
diff --git a/Source/WebCore/platform/network/ProtectionSpaceHash.h b/Source/WebCore/platform/network/ProtectionSpaceHash.h
index 08716b5..9934321 100644
--- a/Source/WebCore/platform/network/ProtectionSpaceHash.h
+++ b/Source/WebCore/platform/network/ProtectionSpaceHash.h
@@ -42,11 +42,11 @@ struct ProtectionSpaceHash {
protectionSpace.realm().impl() ? protectionSpace.realm().impl()->hash() : 0
};
- unsigned codeCount = sizeof(hashCodes) / sizeof(UChar);
+ unsigned codeCount = sizeof(hashCodes);
// Ignore realm for proxies.
if (protectionSpace.isProxy())
- codeCount -= sizeof(hashCodes[0]) / sizeof(UChar);
- return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), codeCount);
+ codeCount -= sizeof(hashCodes[0]);
+ return WTF::StringHasher::createBlobHash(hashCodes, codeCount);
}
static bool equal(const ProtectionSpace& a, const ProtectionSpace& b) { return a == b; }
diff --git a/Source/WebCore/platform/network/ResourceHandle.h b/Source/WebCore/platform/network/ResourceHandle.h
index bb94b59..c2a0b8e 100644
--- a/Source/WebCore/platform/network/ResourceHandle.h
+++ b/Source/WebCore/platform/network/ResourceHandle.h
@@ -41,7 +41,7 @@ typedef struct _SoupSession SoupSession;
typedef const struct __CFData * CFDataRef;
#endif
-#if PLATFORM(WIN)
+#if USE(WININET)
typedef unsigned long DWORD;
typedef unsigned long DWORD_PTR;
typedef void* LPVOID;
@@ -173,7 +173,7 @@ public:
bool hasAuthenticationChallenge() const;
void clearAuthentication();
- void cancel();
+ virtual void cancel();
// The client may be 0, in which case no callbacks will be made.
ResourceHandleClient* client() const;
diff --git a/Source/WebCore/platform/network/ResourceHandleInternal.h b/Source/WebCore/platform/network/ResourceHandleInternal.h
index ed66944..5512062 100644
--- a/Source/WebCore/platform/network/ResourceHandleInternal.h
+++ b/Source/WebCore/platform/network/ResourceHandleInternal.h
@@ -46,8 +46,9 @@
#endif
#if USE(SOUP)
-#include "soup-requester.h"
#include <GRefPtr.h>
+#define LIBSOUP_USE_UNSTABLE_REQUEST_API
+#include <libsoup/soup-request.h>
#include <libsoup/soup.h>
class Frame;
#endif
@@ -114,6 +115,8 @@ namespace WebCore {
, m_cancelled(false)
, m_buffer(0)
, m_total(0)
+ , m_bodySize(0)
+ , m_bodyDataSent(0)
, m_idleHandler(0)
, m_gotChunkHandler(0)
#endif
@@ -132,9 +135,6 @@ namespace WebCore {
m_user = url.user();
m_pass = url.pass();
m_firstRequest.removeCredentials();
-#if USE(SOUP)
- m_requester = adoptGRef(webkit_soup_requester_new());
-#endif
}
~ResourceHandleInternal();
@@ -190,12 +190,13 @@ namespace WebCore {
GRefPtr<SoupMessage> m_soupMessage;
ResourceResponse m_response;
bool m_cancelled;
- GRefPtr<WebKitSoupRequest> m_soupRequest;
- GRefPtr<WebKitSoupRequester> m_requester;
+ GRefPtr<SoupRequest> m_soupRequest;
GRefPtr<GInputStream> m_inputStream;
GRefPtr<GCancellable> m_cancellable;
char* m_buffer;
gsize m_total;
+ unsigned long m_bodySize;
+ unsigned long m_bodyDataSent;
guint m_idleHandler;
RefPtr<NetworkingContext> m_context;
gulong m_gotChunkHandler;
diff --git a/Source/WebCore/platform/network/ResourceRequestBase.cpp b/Source/WebCore/platform/network/ResourceRequestBase.cpp
index ae8316a..ba58461 100644
--- a/Source/WebCore/platform/network/ResourceRequestBase.cpp
+++ b/Source/WebCore/platform/network/ResourceRequestBase.cpp
@@ -45,6 +45,7 @@ PassOwnPtr<ResourceRequest> ResourceRequestBase::adopt(PassOwnPtr<CrossThreadRes
request->setTimeoutInterval(data->m_timeoutInterval);
request->setFirstPartyForCookies(data->m_firstPartyForCookies);
request->setHTTPMethod(data->m_httpMethod);
+ request->setPriority(data->m_priority);
request->setTargetType(data->m_targetType);
request->updateResourceRequest();
@@ -78,6 +79,7 @@ PassOwnPtr<CrossThreadResourceRequestData> ResourceRequestBase::copyData() const
data->m_firstPartyForCookies = firstPartyForCookies().copy();
data->m_httpMethod = httpMethod().crossThreadString();
data->m_httpHeaders = httpHeaderFields().copyData();
+ data->m_priority = priority();
data->m_targetType = m_targetType;
data->m_responseContentDispositionEncodingFallbackArray.reserveInitialCapacity(m_responseContentDispositionEncodingFallbackArray.size());
@@ -314,6 +316,23 @@ void ResourceRequestBase::setAllowCookies(bool allowCookies)
m_platformRequestUpdated = false;
}
+ResourceLoadPriority ResourceRequestBase::priority() const
+{
+ updateResourceRequest();
+
+ return m_priority;
+}
+
+void ResourceRequestBase::setPriority(ResourceLoadPriority priority)
+{
+ updateResourceRequest();
+
+ m_priority = priority;
+
+ if (url().protocolInHTTPFamily())
+ m_platformRequestUpdated = false;
+}
+
void ResourceRequestBase::addHTTPHeaderField(const AtomicString& name, const String& value)
{
updateResourceRequest();
@@ -352,6 +371,9 @@ bool equalIgnoringHeaderFields(const ResourceRequestBase& a, const ResourceReque
if (a.allowCookies() != b.allowCookies())
return false;
+ if (a.priority() != b.priority())
+ return false;
+
FormData* formDataA = a.httpBody();
FormData* formDataB = b.httpBody();
diff --git a/Source/WebCore/platform/network/ResourceRequestBase.h b/Source/WebCore/platform/network/ResourceRequestBase.h
index dce33db..9cc9148 100644
--- a/Source/WebCore/platform/network/ResourceRequestBase.h
+++ b/Source/WebCore/platform/network/ResourceRequestBase.h
@@ -29,8 +29,9 @@
#define ResourceRequestBase_h
#include "FormData.h"
-#include "KURL.h"
#include "HTTPHeaderMap.h"
+#include "KURL.h"
+#include "ResourceLoadPriority.h"
#include <wtf/OwnPtr.h>
@@ -128,6 +129,9 @@ namespace WebCore {
bool allowCookies() const;
void setAllowCookies(bool allowCookies);
+ ResourceLoadPriority priority() const;
+ void setPriority(ResourceLoadPriority);
+
bool isConditional() const;
// Whether the associated ResourceHandleClient needs to be notified of
@@ -157,6 +161,7 @@ namespace WebCore {
, m_reportUploadProgress(false)
, m_reportLoadTiming(false)
, m_reportRawHeaders(false)
+ , m_priority(ResourceLoadPriorityLow)
, m_targetType(TargetIsSubresource)
{
}
@@ -172,6 +177,7 @@ namespace WebCore {
, m_reportUploadProgress(false)
, m_reportLoadTiming(false)
, m_reportRawHeaders(false)
+ , m_priority(ResourceLoadPriorityLow)
, m_targetType(TargetIsSubresource)
{
}
@@ -197,6 +203,7 @@ namespace WebCore {
bool m_reportUploadProgress;
bool m_reportLoadTiming;
bool m_reportRawHeaders;
+ ResourceLoadPriority m_priority;
TargetType m_targetType;
private:
@@ -223,11 +230,20 @@ namespace WebCore {
Vector<String> m_responseContentDispositionEncodingFallbackArray;
RefPtr<FormData> m_httpBody;
bool m_allowCookies;
+ ResourceLoadPriority m_priority;
ResourceRequestBase::TargetType m_targetType;
};
unsigned initializeMaximumHTTPConnectionCountPerHost();
+#if PLATFORM(CF)
+ bool isHTTPPipeliningEnabled();
+ bool shouldForceHTTPPipeliningPriorityHigh();
+#else
+ inline bool isHTTPPipeliningEnabled() { return false; }
+ inline bool shouldForceHTTPPipeliningPriorityHigh() { return false; }
+#endif
+
} // namespace WebCore
#endif // ResourceRequestBase_h
diff --git a/Source/WebCore/platform/network/cf/DNSCFNet.cpp b/Source/WebCore/platform/network/cf/DNSCFNet.cpp
index 166abbf..b6f9922 100644
--- a/Source/WebCore/platform/network/cf/DNSCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/DNSCFNet.cpp
@@ -36,6 +36,7 @@
#if PLATFORM(WIN)
#include "LoaderRunLoopCF.h"
+#include <CFNetwork/CFNetwork.h>
#endif
#if defined(BUILDING_ON_LEOPARD)
diff --git a/Source/WebCore/platform/network/cf/DownloadBundle.h b/Source/WebCore/platform/network/cf/DownloadBundle.h
new file mode 100644
index 0000000..cf90908
--- /dev/null
+++ b/Source/WebCore/platform/network/cf/DownloadBundle.h
@@ -0,0 +1,43 @@
+/*
+ * 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 DownloadBundle_h
+#define DownloadBundle_h
+
+#include <wtf/Forward.h>
+
+typedef const struct __CFData* CFDataRef;
+
+namespace WebCore {
+namespace DownloadBundle {
+
+bool appendResumeData(CFDataRef resumeData, const String& bundlePath);
+CFDataRef extractResumeData(const String& bundlePath);
+const String& fileExtension();
+
+} // namespace DownloadBundle
+} // namespace WebCore
+
+#endif // DownloadBundle_h
diff --git a/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp b/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp
index eb0ec3a..8bc8f08 100644
--- a/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp
@@ -145,17 +145,8 @@ static void advanceCurrentStream(FormStreamFields *form)
char* data = nextInput.m_data.releaseBuffer();
form->currentStream = CFReadStreamCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data), size, kCFAllocatorNull);
form->currentData = data;
- } else {
- CFStringRef filename = nextInput.m_filename.createCFString();
-#if PLATFORM(WIN)
- CFURLRef fileURL = CFURLCreateWithFileSystemPath(0, filename, kCFURLWindowsPathStyle, FALSE);
-#else
- CFURLRef fileURL = CFURLCreateWithFileSystemPath(0, filename, kCFURLPOSIXPathStyle, FALSE);
-#endif
- CFRelease(filename);
- form->currentStream = CFReadStreamCreateWithFile(0, fileURL);
- CFRelease(fileURL);
- }
+ } else
+ form->currentStream = CFReadStreamCreateWithFile(0, pathAsURL(nextInput.m_filename).get());
form->remainingElements.removeLast();
// Set up the callback.
diff --git a/Source/WebCore/platform/network/cf/LoaderRunLoopCF.cpp b/Source/WebCore/platform/network/cf/LoaderRunLoopCF.cpp
index 249fe43..a7cc639 100644
--- a/Source/WebCore/platform/network/cf/LoaderRunLoopCF.cpp
+++ b/Source/WebCore/platform/network/cf/LoaderRunLoopCF.cpp
@@ -28,6 +28,7 @@
#if USE(CFNETWORK)
+#include <CoreFoundation/CoreFoundation.h>
#include <wtf/Threading.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/network/cf/LoaderRunLoopCF.h b/Source/WebCore/platform/network/cf/LoaderRunLoopCF.h
index f66128c..e0d3ba4 100644
--- a/Source/WebCore/platform/network/cf/LoaderRunLoopCF.h
+++ b/Source/WebCore/platform/network/cf/LoaderRunLoopCF.h
@@ -32,6 +32,8 @@
#error This code is not needed on platforms other than Windows, because main thread's CFRunLoop can be used.
#endif
+typedef struct __CFRunLoop* CFRunLoopRef;
+
namespace WebCore {
CFRunLoopRef loaderRunLoop();
diff --git a/Source/WebCore/platform/network/cf/ProxyServerCFNet.cpp b/Source/WebCore/platform/network/cf/ProxyServerCFNet.cpp
index 3bef808..57d714b 100644
--- a/Source/WebCore/platform/network/cf/ProxyServerCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/ProxyServerCFNet.cpp
@@ -29,6 +29,10 @@
#include "KURL.h"
#include <wtf/RetainPtr.h>
+#if PLATFORM(WIN)
+#include <CFNetwork/CFNetwork.h>
+#endif
+
namespace WebCore {
#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
diff --git a/Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp b/Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
index 66ae5a0..52b100f 100644
--- a/Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
@@ -126,12 +126,7 @@ static void setDefaultMIMEType(CFURLResponseRef response)
static String encodeBasicAuthorization(const String& user, const String& password)
{
- CString unencodedString = (user + ":" + password).utf8();
- Vector<char> unencoded(unencodedString.length());
- std::copy(unencodedString.data(), unencodedString.data() + unencodedString.length(), unencoded.begin());
- Vector<char> encoded;
- base64Encode(unencoded, encoded);
- return String(encoded.data(), encoded.size());
+ return base64Encode((user + ":" + password).utf8());
}
CFURLRequestRef willSendRequest(CFURLConnectionRef conn, CFURLRequestRef cfRequest, CFURLResponseRef cfRedirectResponse, const void* clientInfo)
diff --git a/Source/WebCore/platform/network/cf/ResourceRequestCFNet.cpp b/Source/WebCore/platform/network/cf/ResourceRequestCFNet.cpp
index 410a649..7a1dfd5 100644
--- a/Source/WebCore/platform/network/cf/ResourceRequestCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/ResourceRequestCFNet.cpp
@@ -26,16 +26,22 @@
#include "config.h"
#include "ResourceRequestCFNet.h"
-#if USE(CFNETWORK)
-
-#include "FormDataStreamCFNet.h"
#include "ResourceRequest.h"
+#if PLATFORM(MAC)
+#include "WebCoreSystemInterface.h"
+#endif
+
+#if USE(CFNETWORK)
+#include "FormDataStreamCFNet.h"
#include <CFNetwork/CFURLRequestPriv.h>
#include <WebKitSystemInterface/WebKitSystemInterface.h>
+#endif
namespace WebCore {
+#if USE(CFNETWORK)
+
typedef void (*CFURLRequestSetContentDispositionEncodingFallbackArrayFunction)(CFMutableURLRequestRef, CFArrayRef);
typedef CFArrayRef (*CFURLRequestCopyContentDispositionEncodingFallbackArrayFunction)(CFURLRequestRef);
@@ -189,12 +195,43 @@ void ResourceRequest::doUpdateResourceRequest()
m_httpBody = httpBodyFromRequest(m_cfRequest.get());
}
+#endif // USE(CFNETWORK)
+
unsigned initializeMaximumHTTPConnectionCountPerHost()
{
static const unsigned preferredConnectionCount = 6;
- return wkInitializeMaximumHTTPConnectionCountPerHost(preferredConnectionCount);
+ static const unsigned unlimitedConnectionCount = 10000;
+
+ // Always set the connection count per host, even when pipelining.
+ unsigned maximumHTTPConnectionCountPerHost = wkInitializeMaximumHTTPConnectionCountPerHost(preferredConnectionCount);
+
+#if PLATFORM(MAC)
+ if (isHTTPPipeliningEnabled()) {
+ // When pipelining do not rate-limit requests sent from WebCore since CFNetwork handles that.
+ return unlimitedConnectionCount;
+ }
+#endif
+
+ return maximumHTTPConnectionCountPerHost;
}
-} // namespace WebCore
+static inline bool readBooleanPreference(CFStringRef key)
+{
+ Boolean keyExistsAndHasValidFormat;
+ Boolean result = CFPreferencesGetAppBooleanValue(key, kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat);
+ return keyExistsAndHasValidFormat ? result : false;
+}
-#endif // USE(CFNETWORK)
+bool isHTTPPipeliningEnabled()
+{
+ static bool isEnabled = readBooleanPreference(CFSTR("WebKitEnableHTTPPipelining"));
+ return isEnabled;
+}
+
+bool shouldForceHTTPPipeliningPriorityHigh()
+{
+ static bool shouldForcePriorityHigh = readBooleanPreference(CFSTR("WebKitForceHTTPPipeliningPriorityHigh"));
+ return shouldForcePriorityHigh;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/network/cf/ResourceRequestCFNet.h b/Source/WebCore/platform/network/cf/ResourceRequestCFNet.h
index 39587a4..09f4cea 100644
--- a/Source/WebCore/platform/network/cf/ResourceRequestCFNet.h
+++ b/Source/WebCore/platform/network/cf/ResourceRequestCFNet.h
@@ -26,18 +26,55 @@
#ifndef ResourceRequestCFNet_h
#define ResourceRequestCFNet_h
-#if USE(CFNETWORK)
+#include "ResourceLoadPriority.h"
+#if USE(CFNETWORK)
typedef const struct _CFURLRequest* CFURLRequestRef;
+#endif
namespace WebCore {
- class ResourceRequest;
+class ResourceRequest;
+
+#if USE(CFNETWORK)
+void getResourceRequest(ResourceRequest&, CFURLRequestRef);
+CFURLRequestRef cfURLRequest(const ResourceRequest&);
+#endif
+
+inline ResourceLoadPriority mapHTTPPipeliningPriorityToResourceLoadPriority(int priority)
+{
+ switch (priority) {
+ case 0:
+ return ResourceLoadPriorityLow;
+ case 1:
+ return ResourceLoadPriorityMedium;
+ case 2:
+ return ResourceLoadPriorityHigh;
+ default:
+ ASSERT_NOT_REACHED();
+ return ResourceLoadPriorityLowest;
+ }
+}
+
+inline int mapResourceLoadPriorityToHTTPPipeliningPriority(ResourceLoadPriority priority)
+{
+ switch (priority) {
+ case ResourceLoadPriorityVeryLow:
+ case ResourceLoadPriorityLow:
+ return 0;
+ case ResourceLoadPriorityMedium:
+ return 1;
+ case ResourceLoadPriorityHigh:
+ return 2;
+ case ResourceLoadPriorityUnresolved:
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
- void getResourceRequest(ResourceRequest&, CFURLRequestRef);
- CFURLRequestRef cfURLRequest(const ResourceRequest&);
+ ASSERT_NOT_REACHED();
+ return 0;
}
-#endif // USE(CFNETWORK)
+} // namespace WebCore
#endif // ResourceRequestCFNet_h
diff --git a/Source/WebCore/platform/network/cf/SocketStreamHandle.h b/Source/WebCore/platform/network/cf/SocketStreamHandle.h
index df1d4a3..fbda3bc 100644
--- a/Source/WebCore/platform/network/cf/SocketStreamHandle.h
+++ b/Source/WebCore/platform/network/cf/SocketStreamHandle.h
@@ -36,6 +36,7 @@
#include "SocketStreamHandleBase.h"
#include <wtf/RetainPtr.h>
+typedef struct __CFHTTPMessage* CFHTTPMessageRef;
namespace WebCore {
diff --git a/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp b/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp
index 821b1ca..06454a7 100644
--- a/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp
@@ -47,6 +47,7 @@
#if PLATFORM(WIN)
#include "LoaderRunLoopCF.h"
+#include <CFNetwork/CFNetwork.h>
#include <WebKitSystemInterface/WebKitSystemInterface.h>
#else
#include "WebCoreSystemInterface.h"
diff --git a/Source/WebCore/platform/network/chromium/ResourceRequest.cpp b/Source/WebCore/platform/network/chromium/ResourceRequest.cpp
index 69591c1..519c63f 100644
--- a/Source/WebCore/platform/network/chromium/ResourceRequest.cpp
+++ b/Source/WebCore/platform/network/chromium/ResourceRequest.cpp
@@ -43,6 +43,7 @@ PassOwnPtr<CrossThreadResourceRequestData> ResourceRequest::doPlatformCopyData(P
data->m_requestorProcessID = m_requestorProcessID;
data->m_appCacheHostID = m_appCacheHostID;
data->m_hasUserGesture = m_hasUserGesture;
+ data->m_downloadToFile = m_downloadToFile;
return data;
}
@@ -52,6 +53,7 @@ void ResourceRequest::doPlatformAdopt(PassOwnPtr<CrossThreadResourceRequestData>
m_requestorProcessID = data->m_requestorProcessID;
m_appCacheHostID = data->m_appCacheHostID;
m_hasUserGesture = data->m_hasUserGesture;
+ m_downloadToFile = data->m_downloadToFile;
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/chromium/ResourceRequest.h b/Source/WebCore/platform/network/chromium/ResourceRequest.h
index 41ad6e0..07b31eb 100644
--- a/Source/WebCore/platform/network/chromium/ResourceRequest.h
+++ b/Source/WebCore/platform/network/chromium/ResourceRequest.h
@@ -42,6 +42,7 @@ namespace WebCore {
, m_requestorProcessID(0)
, m_appCacheHostID(0)
, m_hasUserGesture(false)
+ , m_downloadToFile(false)
{
}
@@ -51,6 +52,7 @@ namespace WebCore {
, m_requestorProcessID(0)
, m_appCacheHostID(0)
, m_hasUserGesture(false)
+ , m_downloadToFile(false)
{
}
@@ -60,6 +62,7 @@ namespace WebCore {
, m_requestorProcessID(0)
, m_appCacheHostID(0)
, m_hasUserGesture(false)
+ , m_downloadToFile(false)
{
setHTTPReferrer(referrer);
}
@@ -70,6 +73,7 @@ namespace WebCore {
, m_requestorProcessID(0)
, m_appCacheHostID(0)
, m_hasUserGesture(false)
+ , m_downloadToFile(false)
{
}
@@ -92,6 +96,10 @@ namespace WebCore {
bool hasUserGesture() const { return m_hasUserGesture; }
void setHasUserGesture(bool hasUserGesture) { m_hasUserGesture = hasUserGesture; }
+ // True if request should be downloaded to file.
+ bool downloadToFile() const { return m_downloadToFile; }
+ void setDownloadToFile(bool downloadToFile) { m_downloadToFile = downloadToFile; }
+
private:
friend class ResourceRequestBase;
@@ -105,6 +113,7 @@ namespace WebCore {
int m_requestorProcessID;
int m_appCacheHostID;
bool m_hasUserGesture;
+ bool m_downloadToFile;
};
struct CrossThreadResourceRequestData : public CrossThreadResourceRequestDataBase {
@@ -112,6 +121,7 @@ namespace WebCore {
int m_requestorProcessID;
int m_appCacheHostID;
bool m_hasUserGesture;
+ bool m_downloadToFile;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/chromium/ResourceResponse.cpp b/Source/WebCore/platform/network/chromium/ResourceResponse.cpp
index acd44d3..fc8ac62 100644
--- a/Source/WebCore/platform/network/chromium/ResourceResponse.cpp
+++ b/Source/WebCore/platform/network/chromium/ResourceResponse.cpp
@@ -39,6 +39,8 @@ PassOwnPtr<CrossThreadResourceResponseData> ResourceResponse::doPlatformCopyData
data->m_wasAlternateProtocolAvailable = m_wasAlternateProtocolAvailable;
data->m_wasFetchedViaProxy = m_wasFetchedViaProxy;
data->m_responseTime = m_responseTime;
+ data->m_socketAddress = m_socketAddress;
+ data->m_downloadFilePath = m_downloadFilePath;
return data;
}
@@ -53,6 +55,8 @@ void ResourceResponse::doPlatformAdopt(PassOwnPtr<CrossThreadResourceResponseDat
m_wasAlternateProtocolAvailable = data->m_wasAlternateProtocolAvailable;
m_wasFetchedViaProxy = data->m_wasFetchedViaProxy;
m_responseTime = data->m_responseTime;
+ m_socketAddress = data->m_socketAddress;
+ m_downloadFilePath = data->m_downloadFilePath;
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/chromium/ResourceResponse.h b/Source/WebCore/platform/network/chromium/ResourceResponse.h
index 5e99994..35f13d1 100644
--- a/Source/WebCore/platform/network/chromium/ResourceResponse.h
+++ b/Source/WebCore/platform/network/chromium/ResourceResponse.h
@@ -96,6 +96,12 @@ namespace WebCore {
double responseTime() const { return m_responseTime; }
void setResponseTime(double responseTime) { m_responseTime = responseTime; }
+ const String& socketAddress() const { return m_socketAddress; }
+ void setSocketAddress(const String& value) { m_socketAddress = value; }
+
+ const String& downloadFilePath() const { return m_downloadFilePath; }
+ void setDownloadFilePath(const String& downloadFilePath) { m_downloadFilePath = downloadFilePath; }
+
private:
friend class ResourceResponseBase;
@@ -143,6 +149,13 @@ namespace WebCore {
// The time at which the response headers were received. For cached
// responses, this time could be "far" in the past.
double m_responseTime;
+
+ // Remote address of the socket which fetched this resource, for presenting
+ // to inquisitive users. Can be "ipv4:port", "[ipv6]:port", or empty.
+ String m_socketAddress;
+
+ // The path to the downloaded file.
+ String m_downloadFilePath;
};
struct CrossThreadResourceResponseData : public CrossThreadResourceResponseDataBase {
@@ -155,6 +168,8 @@ namespace WebCore {
bool m_wasAlternateProtocolAvailable;
bool m_wasFetchedViaProxy;
double m_responseTime;
+ String m_socketAddress;
+ String m_downloadFilePath;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/mac/AuthenticationMac.mm b/Source/WebCore/platform/network/mac/AuthenticationMac.mm
index efa42d9..a187187 100644
--- a/Source/WebCore/platform/network/mac/AuthenticationMac.mm
+++ b/Source/WebCore/platform/network/mac/AuthenticationMac.mm
@@ -31,6 +31,7 @@
#import "AuthenticationClient.h"
#import "Credential.h"
#import "ProtectionSpace.h"
+#import <wtf/UnusedParam.h>
#import <Foundation/NSURLAuthenticationChallenge.h>
#import <Foundation/NSURLCredential.h>
@@ -86,6 +87,20 @@ using namespace WebCore;
m_client->receivedCancellation(core(challenge));
}
+- (void)performDefaultHandlingForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
+{
+ // FIXME: <rdar://problem/8995483> Determine what, if anything, we should do here.
+ ASSERT_NOT_REACHED();
+ UNUSED_PARAM(challenge);
+}
+
+- (void)rejectProtectionSpaceAndContinueWithChallenge:(NSURLAuthenticationChallenge *)challenge
+{
+ // FIXME: <rdar://problem/8995483> Determine what, if anything, we should do here.
+ ASSERT_NOT_REACHED();
+ UNUSED_PARAM(challenge);
+}
+
@end
namespace WebCore {
diff --git a/Source/WebCore/platform/network/mac/FormDataStreamMac.mm b/Source/WebCore/platform/network/mac/FormDataStreamMac.mm
index 03f4579..eb6f601 100644
--- a/Source/WebCore/platform/network/mac/FormDataStreamMac.mm
+++ b/Source/WebCore/platform/network/mac/FormDataStreamMac.mm
@@ -185,9 +185,7 @@ static bool advanceCurrentStream(FormStreamFields* form)
}
#endif
const String& path = nextInput.m_shouldGenerateFile ? nextInput.m_generatedFilename : nextInput.m_filename;
- RetainPtr<CFStringRef> filename(AdoptCF, path.createCFString());
- RetainPtr<CFURLRef> fileURL(AdoptCF, CFURLCreateWithFileSystemPath(0, filename.get(), kCFURLPOSIXPathStyle, FALSE));
- form->currentStream = CFReadStreamCreateWithFile(0, fileURL.get());
+ form->currentStream = CFReadStreamCreateWithFile(0, pathAsURL(path).get());
if (!form->currentStream) {
// The file must have been removed or become unreadable.
return false;
diff --git a/Source/WebCore/platform/network/mac/ResourceHandleMac.mm b/Source/WebCore/platform/network/mac/ResourceHandleMac.mm
index 84b656c..2d687c0 100644
--- a/Source/WebCore/platform/network/mac/ResourceHandleMac.mm
+++ b/Source/WebCore/platform/network/mac/ResourceHandleMac.mm
@@ -164,12 +164,7 @@ public:
#ifndef BUILDING_ON_TIGER
static String encodeBasicAuthorization(const String& user, const String& password)
{
- CString unencodedString = (user + ":" + password).utf8();
- Vector<char> unencoded(unencodedString.length());
- std::copy(unencodedString.data(), unencodedString.data() + unencodedString.length(), unencoded.begin());
- Vector<char> encoded;
- base64Encode(unencoded, encoded);
- return String(encoded.data(), encoded.size());
+ return base64Encode((user + ":" + password).utf8());
}
#endif
diff --git a/Source/WebCore/platform/network/mac/ResourceRequestMac.mm b/Source/WebCore/platform/network/mac/ResourceRequestMac.mm
index f0357e5..640d237 100644
--- a/Source/WebCore/platform/network/mac/ResourceRequestMac.mm
+++ b/Source/WebCore/platform/network/mac/ResourceRequestMac.mm
@@ -31,6 +31,8 @@
#import "WebCoreSystemInterface.h"
#import "FormDataStreamMac.h"
+#import "ResourceRequestCFNet.h"
+#import "WebCoreSystemInterface.h"
#import <Foundation/Foundation.h>
@@ -65,7 +67,12 @@ void ResourceRequest::doUpdateResourceRequest()
if (NSString* method = [m_nsRequest.get() HTTPMethod])
m_httpMethod = method;
m_allowCookies = [m_nsRequest.get() HTTPShouldHandleCookies];
-
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+ if (isHTTPPipeliningEnabled() && !shouldForceHTTPPipeliningPriorityHigh())
+ m_priority = mapHTTPPipeliningPriorityToResourceLoadPriority(wkGetHTTPPipeliningPriority(m_nsRequest.get()));
+#endif
+
NSDictionary *headers = [m_nsRequest.get() allHTTPHeaderFields];
NSEnumerator *e = [headers keyEnumerator];
NSString *name;
@@ -111,6 +118,13 @@ void ResourceRequest::doUpdatePlatformRequest()
wkSupportsMultipartXMixedReplace(nsRequest);
#endif
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+ if (isHTTPPipeliningEnabled()) {
+ int priority = mapResourceLoadPriorityToHTTPPipeliningPriority(m_priority);
+ wkSetHTTPPipeliningPriority(nsRequest, shouldForceHTTPPipeliningPriorityHigh() ? 2 : priority);
+ }
+#endif
+
[nsRequest setCachePolicy:(NSURLRequestCachePolicy)cachePolicy()];
if (timeoutInterval() != unspecifiedTimeoutInterval)
[nsRequest setTimeoutInterval:timeoutInterval()];
@@ -154,12 +168,6 @@ void ResourceRequest::applyWebArchiveHackForMail()
// Hack because Mail checks for this property to detect data / archive loads
[NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)nsURLRequest()];
}
-
-unsigned initializeMaximumHTTPConnectionCountPerHost()
-{
- static const unsigned preferredConnectionCount = 6;
- return wkInitializeMaximumHTTPConnectionCountPerHost(preferredConnectionCount);
-}
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.cpp b/Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.cpp
index e0d6e69..a98b4f4 100644
--- a/Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.cpp
+++ b/Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.cpp
@@ -35,6 +35,18 @@ QtNAMThreadSafeProxy::QtNAMThreadSafeProxy(QNetworkAccessManager *manager)
connect(this, SIGNAL(localSetCookiesRequested(const QUrl&, const QString&)), SLOT(localSetCookies(const QUrl&, const QString&)));
connect(this, SIGNAL(localCookiesForUrlRequested(const QUrl&, bool*, QList<QNetworkCookie>*)), SLOT(localCookiesForUrl(const QUrl&, bool*, QList<QNetworkCookie>*)));
connect(this, SIGNAL(localWillLoadFromCacheRequested(const QUrl&, bool*, bool*)), SLOT(localWillLoadFromCache(const QUrl&, bool*, bool*)));
+ connect(this, SIGNAL(hasCookieJarRequested(bool*, bool*)), SLOT(hasCookieJar(bool*, bool*)));
+}
+
+bool QtNAMThreadSafeProxy::hasCookieJar()
+{
+ bool result;
+ bool done = false;
+ emit hasCookieJarRequested(&done, &result);
+ QMutexLocker lock(&m_resultMutex);
+ while (!done)
+ m_resultWaitCondition.wait(&m_resultMutex);
+ return result;
}
void QtNAMThreadSafeProxy::localSetCookies(const QUrl& url, const QString& cookies)
@@ -69,6 +81,14 @@ void QtNAMThreadSafeProxy::localWillLoadFromCache(const QUrl& url, bool* done, b
m_resultWaitCondition.wakeAll();
}
+void QtNAMThreadSafeProxy::hasCookieJar(bool* done, bool* result)
+{
+ QMutexLocker lock(&m_resultMutex);
+ *result = !!m_manager->cookieJar();
+ *done = true;
+ m_resultWaitCondition.wakeAll();
+}
+
QtNetworkReplyThreadSafeProxy::QtNetworkReplyThreadSafeProxy(QNetworkAccessManager *manager)
: m_manager(manager)
, m_reply(0)
diff --git a/Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.h b/Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.h
index ae963cf..4906fe2 100644
--- a/Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.h
+++ b/Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.h
@@ -67,15 +67,19 @@ public:
return result;
}
+ bool hasCookieJar();
+
signals:
void localSetCookiesRequested(const QUrl&, const QString& cookies);
void localCookiesForUrlRequested(const QUrl&, bool* done, QList<QNetworkCookie>* result);
void localWillLoadFromCacheRequested(const QUrl&, bool* done, bool* result);
+ void hasCookieJarRequested(bool* done, bool* result);
private slots:
void localSetCookies(const QUrl&, const QString& cookies);
void localCookiesForUrl(const QUrl&, bool* done, QList<QNetworkCookie>* result);
void localWillLoadFromCache(const QUrl&, bool* done, bool* result);
+ void hasCookieJar(bool* done, bool* result);
private:
QNetworkAccessManager* m_manager;
diff --git a/Source/WebCore/platform/network/soup/CookieJarSoup.cpp b/Source/WebCore/platform/network/soup/CookieJarSoup.cpp
index ba29622..e2c2f05 100644
--- a/Source/WebCore/platform/network/soup/CookieJarSoup.cpp
+++ b/Source/WebCore/platform/network/soup/CookieJarSoup.cpp
@@ -38,9 +38,7 @@ SoupCookieJar* defaultCookieJar()
cookiesInitialized = true;
cookieJar = soup_cookie_jar_new();
-#ifdef HAVE_LIBSOUP_2_29_90
soup_cookie_jar_set_accept_policy(cookieJar, SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY);
-#endif
}
return cookieJar;
@@ -67,18 +65,12 @@ void setCookies(Document* document, const KURL& url, const String& value)
GOwnPtr<SoupURI> origin(soup_uri_new(url.string().utf8().data()));
-#ifdef HAVE_LIBSOUP_2_29_90
GOwnPtr<SoupURI> firstParty(soup_uri_new(document->firstPartyForCookies().string().utf8().data()));
soup_cookie_jar_set_cookie_with_first_party(jar,
origin.get(),
firstParty.get(),
value.utf8().data());
-#else
- soup_cookie_jar_set_cookie(jar,
- origin.get(),
- value.utf8().data());
-#endif
}
String cookies(const Document* /*document*/, const KURL& url)
diff --git a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
index a7170fe..3b1f157 100644
--- a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
+++ b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
@@ -45,12 +45,14 @@
#include "ResourceHandleInternal.h"
#include "ResourceResponse.h"
#include "SharedBuffer.h"
-#include "soup-request-http.h"
#include "TextEncoding.h"
#include <errno.h>
#include <fcntl.h>
#include <gio/gio.h>
#include <glib.h>
+#define LIBSOUP_USE_UNSTABLE_REQUEST_API
+#include <libsoup/soup-request-http.h>
+#include <libsoup/soup-requester.h>
#include <libsoup/soup.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -127,7 +129,7 @@ static void cleanupSoupRequestOperation(ResourceHandle*, bool isDestroying);
static void sendRequestCallback(GObject*, GAsyncResult*, gpointer);
static void readCallback(GObject*, GAsyncResult*, gpointer);
static void closeCallback(GObject*, GAsyncResult*, gpointer);
-static bool startGio(ResourceHandle*, KURL);
+static bool startNonHTTPRequest(ResourceHandle*, KURL);
ResourceHandleInternal::~ResourceHandleInternal()
{
@@ -145,14 +147,48 @@ ResourceHandle::~ResourceHandle()
cleanupSoupRequestOperation(this, true);
}
+static void ensureSessionIsInitialized(SoupSession* session)
+{
+ // Values taken from http://stevesouders.com/ua/index.php following
+ // the rule "Do What Every Other Modern Browser Is Doing". They seem
+ // to significantly improve page loading time compared to soup's
+ // default values.
+ static const int maxConnections = 60;
+ static const int maxConnectionsPerHost = 6;
+
+ if (g_object_get_data(G_OBJECT(session), "webkit-init"))
+ return;
+
+ SoupCookieJar* jar = SOUP_COOKIE_JAR(soup_session_get_feature(session, SOUP_TYPE_COOKIE_JAR));
+ if (!jar)
+ soup_session_add_feature(session, SOUP_SESSION_FEATURE(defaultCookieJar()));
+ else
+ setDefaultCookieJar(jar);
+
+ if (!soup_session_get_feature(session, SOUP_TYPE_LOGGER) && LogNetwork.state == WTFLogChannelOn) {
+ SoupLogger* logger = soup_logger_new(static_cast<SoupLoggerLogLevel>(SOUP_LOGGER_LOG_BODY), -1);
+ soup_session_add_feature(session, SOUP_SESSION_FEATURE(logger));
+ g_object_unref(logger);
+ }
+
+ SoupRequester* requester = soup_requester_new();
+ soup_session_add_feature(session, SOUP_SESSION_FEATURE(requester));
+ g_object_unref(requester);
+
+ g_object_set(session,
+ SOUP_SESSION_MAX_CONNS, maxConnections,
+ SOUP_SESSION_MAX_CONNS_PER_HOST, maxConnectionsPerHost,
+ NULL);
+
+ g_object_set_data(G_OBJECT(session), "webkit-init", reinterpret_cast<void*>(0xdeadbeef));
+}
+
void ResourceHandle::prepareForURL(const KURL &url)
{
-#ifdef HAVE_LIBSOUP_2_29_90
GOwnPtr<SoupURI> soupURI(soup_uri_new(url.prettyURL().utf8().data()));
if (!soupURI)
return;
soup_session_prepare_for_uri(ResourceHandle::defaultSession(), soupURI.get());
-#endif
}
// All other kinds of redirections, except for the *304* status code
@@ -206,14 +242,12 @@ static void restartedCallback(SoupMessage* msg, gpointer data)
if (d->m_cancelled)
return;
-#ifdef HAVE_LIBSOUP_2_29_90
// Update the first party in case the base URL changed with the redirect
String firstPartyString = request.firstPartyForCookies().string();
if (!firstPartyString.isEmpty()) {
GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data()));
soup_message_set_first_party(d->m_soupMessage.get(), firstParty.get());
}
-#endif
}
static void contentSniffedCallback(SoupMessage*, const char*, GHashTable*, gpointer);
@@ -263,7 +297,26 @@ static void gotHeadersCallback(SoupMessage* msg, gpointer data)
client->didReceiveResponse(handle.get(), d->m_response);
}
-// This callback will not be called if the content sniffer is disabled in startHttp.
+static void wroteBodyDataCallback(SoupMessage*, SoupBuffer* buffer, gpointer data)
+{
+ RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data);
+ if (!handle)
+ return;
+
+ ASSERT(buffer);
+ ResourceHandleInternal* internal = handle->getInternal();
+ internal->m_bodyDataSent += buffer->length;
+
+ if (internal->m_cancelled)
+ return;
+ ResourceHandleClient* client = handle->client();
+ if (!client)
+ return;
+
+ client->didSendData(handle.get(), internal->m_bodyDataSent, internal->m_bodySize);
+}
+
+// This callback will not be called if the content sniffer is disabled in startHTTPRequest.
static void contentSniffedCallback(SoupMessage* msg, const char* sniffedType, GHashTable *params, gpointer data)
{
if (sniffedType) {
@@ -312,136 +365,11 @@ static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data)
client->didReceiveData(handle.get(), chunk->data, chunk->length, false);
}
-static gboolean parseDataUrl(gpointer callbackData)
-{
- ResourceHandle* handle = static_cast<ResourceHandle*>(callbackData);
- ResourceHandleClient* client = handle->client();
- ResourceHandleInternal* d = handle->getInternal();
- if (d->m_cancelled)
- return false;
-
- d->m_idleHandler = 0;
-
- ASSERT(client);
- if (!client)
- return false;
-
- String url = handle->firstRequest().url().string();
- ASSERT(url.startsWith("data:", false));
-
- int index = url.find(',');
- if (index == -1) {
- client->cannotShowURL(handle);
- return false;
- }
-
- String mediaType = url.substring(5, index - 5);
-
- bool isBase64 = mediaType.endsWith(";base64", false);
- if (isBase64)
- mediaType = mediaType.left(mediaType.length() - 7);
-
- if (mediaType.isEmpty())
- mediaType = "text/plain;charset=US-ASCII";
-
- String mimeType = extractMIMETypeFromMediaType(mediaType);
- String charset = extractCharsetFromMediaType(mediaType);
-
- ASSERT(d->m_response.isNull());
-
- d->m_response.setURL(handle->firstRequest().url());
- d->m_response.setMimeType(mimeType);
-
- // For non base64 encoded data we have to convert to UTF-16 early
- // due to limitations in KURL
- d->m_response.setTextEncodingName(isBase64 ? charset : "UTF-16");
- client->didReceiveResponse(handle, d->m_response);
-
- // The load may be cancelled, and the client may be destroyed
- // by any of the client reporting calls, so we check, and bail
- // out in either of those cases.
- if (d->m_cancelled || !handle->client())
- return false;
-
- SoupSession* session = handle->defaultSession();
- GOwnPtr<GError> error;
- d->m_soupRequest = adoptGRef(webkit_soup_requester_request(d->m_requester.get(), handle->firstRequest().url().string().utf8().data(), session, &error.outPtr()));
- if (error) {
- d->m_soupRequest = 0;
- client->didFinishLoading(handle, 0);
- return false;
- }
-
- d->m_inputStream = adoptGRef(webkit_soup_request_send(d->m_soupRequest.get(), 0, &error.outPtr()));
- if (error) {
- d->m_inputStream = 0;
- client->didFinishLoading(handle, 0);
- return false;
- }
-
- d->m_buffer = static_cast<char*>(g_slice_alloc0(READ_BUFFER_SIZE));
- d->m_total = 0;
-
- g_object_set_data(G_OBJECT(d->m_inputStream.get()), "webkit-resource", handle);
- // balanced by a deref() in cleanupSoupRequestOperation, which should always run
- handle->ref();
-
- d->m_cancellable = adoptGRef(g_cancellable_new());
- g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, READ_BUFFER_SIZE, G_PRIORITY_DEFAULT,
- d->m_cancellable.get(), readCallback, GINT_TO_POINTER(!isBase64));
-
- return false;
-}
-
-static bool startData(ResourceHandle* handle, String urlString)
-{
- ASSERT(handle);
-
- ResourceHandleInternal* d = handle->getInternal();
-
- // If parseDataUrl is called synchronously the job is not yet effectively started
- // and webkit won't never know that the data has been parsed even didFinishLoading is called.
- d->m_idleHandler = g_timeout_add(0, parseDataUrl, handle);
- return true;
-}
-
static SoupSession* createSoupSession()
{
return soup_session_async_new();
}
-// Values taken from http://stevesouders.com/ua/index.php following
-// the rule "Do What Every Other Modern Browser Is Doing". They seem
-// to significantly improve page loading time compared to soup's
-// default values.
-#define MAX_CONNECTIONS 60
-#define MAX_CONNECTIONS_PER_HOST 6
-
-static void ensureSessionIsInitialized(SoupSession* session)
-{
- if (g_object_get_data(G_OBJECT(session), "webkit-init"))
- return;
-
- SoupCookieJar* jar = reinterpret_cast<SoupCookieJar*>(soup_session_get_feature(session, SOUP_TYPE_COOKIE_JAR));
- if (!jar)
- soup_session_add_feature(session, SOUP_SESSION_FEATURE(defaultCookieJar()));
- else
- setDefaultCookieJar(jar);
-
- if (!soup_session_get_feature(session, SOUP_TYPE_LOGGER) && LogNetwork.state == WTFLogChannelOn) {
- SoupLogger* logger = soup_logger_new(static_cast<SoupLoggerLogLevel>(SOUP_LOGGER_LOG_BODY), -1);
- soup_logger_attach(logger, session);
- g_object_unref(logger);
- }
-
- g_object_set(session,
- SOUP_SESSION_MAX_CONNS, MAX_CONNECTIONS,
- SOUP_SESSION_MAX_CONNS_PER_HOST, MAX_CONNECTIONS_PER_HOST,
- NULL);
-
- g_object_set_data(G_OBJECT(session), "webkit-init", reinterpret_cast<void*>(0xdeadbeef));
-}
-
static void cleanupSoupRequestOperation(ResourceHandle* handle, bool isDestroying = false)
{
ResourceHandleInternal* d = handle->getInternal();
@@ -495,14 +423,14 @@ static void sendRequestCallback(GObject* source, GAsyncResult* res, gpointer use
}
GOwnPtr<GError> error;
- GInputStream* in = webkit_soup_request_send_finish(d->m_soupRequest.get(), res, &error.outPtr());
+ GInputStream* in = soup_request_send_finish(d->m_soupRequest.get(), res, &error.outPtr());
if (error) {
SoupMessage* soupMsg = d->m_soupMessage.get();
gboolean isTransportError = d->m_soupMessage && SOUP_STATUS_IS_TRANSPORT_ERROR(soupMsg->status_code);
if (isTransportError || (error->domain == G_IO_ERROR)) {
- SoupURI* uri = webkit_soup_request_get_uri(d->m_soupRequest.get());
+ SoupURI* uri = soup_request_get_uri(d->m_soupRequest.get());
GOwnPtr<char> uriStr(soup_uri_to_string(uri, false));
gint errorCode = isTransportError ? static_cast<gint>(soupMsg->status_code) : error->code;
const gchar* errorMsg = isTransportError ? soupMsg->reason_phrase : error->message;
@@ -550,13 +478,14 @@ static void sendRequestCallback(GObject* source, GAsyncResult* res, gpointer use
// readCallback needs it
g_object_set_data(G_OBJECT(d->m_inputStream.get()), "webkit-resource", handle.get());
- // Ensure a response is sent for any protocols that don't explicitly support responses
- // through got-headers signal or content sniffing.
- // (e.g. file and GIO based protocol).
- if (!handle->shouldContentSniff() && d->m_response.isNull()) {
+ // If not using SoupMessage we need to call didReceiveResponse now.
+ // (This will change later when SoupRequest supports content sniffing.)
+ if (!d->m_soupMessage) {
d->m_response.setURL(handle->firstRequest().url());
- d->m_response.setMimeType(webkit_soup_request_get_content_type(d->m_soupRequest.get()));
- d->m_response.setExpectedContentLength(webkit_soup_request_get_content_length(d->m_soupRequest.get()));
+ const gchar* contentType = soup_request_get_content_type(d->m_soupRequest.get());
+ d->m_response.setMimeType(extractMIMETypeFromMediaType(contentType));
+ d->m_response.setTextEncodingName(extractCharsetFromMediaType(contentType));
+ d->m_response.setExpectedContentLength(soup_request_get_content_length(d->m_soupRequest.get()));
client->didReceiveResponse(handle.get(), d->m_response);
if (d->m_cancelled) {
@@ -572,12 +501,56 @@ static void sendRequestCallback(GObject* source, GAsyncResult* res, gpointer use
G_PRIORITY_DEFAULT, d->m_cancellable.get(), readCallback, 0);
}
-static bool startHttp(ResourceHandle* handle)
+static bool addFormElementsToSoupMessage(SoupMessage* message, const char* contentType, FormData* httpBody, unsigned long& totalBodySize)
+{
+ size_t numElements = httpBody->elements().size();
+ if (numElements < 2) { // No file upload is the most common case.
+ Vector<char> body;
+ httpBody->flatten(body);
+ totalBodySize = body.size();
+ soup_message_set_request(message, contentType, SOUP_MEMORY_COPY, body.data(), body.size());
+ return true;
+ }
+
+ // We have more than one element to upload, and some may be large files,
+ // which we will want to mmap instead of copying into memory
+ soup_message_body_set_accumulate(message->request_body, FALSE);
+ for (size_t i = 0; i < numElements; i++) {
+ const FormDataElement& element = httpBody->elements()[i];
+
+ if (element.m_type == FormDataElement::data) {
+ totalBodySize += element.m_data.size();
+ soup_message_body_append(message->request_body, SOUP_MEMORY_TEMPORARY,
+ element.m_data.data(), element.m_data.size());
+ continue;
+ }
+
+ // This technique is inspired by libsoup's simple-httpd test.
+ GOwnPtr<GError> error;
+ CString fileName = fileSystemRepresentation(element.m_filename);
+ GMappedFile* fileMapping = g_mapped_file_new(fileName.data(), false, &error.outPtr());
+ if (error)
+ return false;
+
+ gsize mappedFileSize = g_mapped_file_get_length(fileMapping);
+ totalBodySize += mappedFileSize;
+ SoupBuffer* soupBuffer = soup_buffer_new_with_owner(g_mapped_file_get_contents(fileMapping),
+ mappedFileSize, fileMapping,
+ reinterpret_cast<GDestroyNotify>(g_mapped_file_unref));
+ soup_message_body_append_buffer(message->request_body, soupBuffer);
+ soup_buffer_free(soupBuffer);
+ }
+
+ return true;
+}
+
+static bool startHTTPRequest(ResourceHandle* handle)
{
ASSERT(handle);
SoupSession* session = handle->defaultSession();
ensureSessionIsInitialized(session);
+ SoupRequester* requester = SOUP_REQUESTER(soup_session_get_feature(session, SOUP_TYPE_REQUESTER));
ResourceHandleInternal* d = handle->getInternal();
@@ -587,7 +560,7 @@ static bool startHttp(ResourceHandle* handle)
request.setURL(url);
GOwnPtr<GError> error;
- d->m_soupRequest = adoptGRef(webkit_soup_requester_request(d->m_requester.get(), url.string().utf8().data(), session, &error.outPtr()));
+ d->m_soupRequest = adoptGRef(soup_requester_request(requester, url.string().utf8().data(), &error.outPtr()));
if (error) {
d->m_soupRequest = 0;
return false;
@@ -595,7 +568,7 @@ static bool startHttp(ResourceHandle* handle)
g_object_set_data(G_OBJECT(d->m_soupRequest.get()), "webkit-resource", handle);
- d->m_soupMessage = adoptGRef(webkit_soup_request_http_get_message(WEBKIT_SOUP_REQUEST_HTTP(d->m_soupRequest.get())));
+ d->m_soupMessage = adoptGRef(soup_request_http_get_message(SOUP_REQUEST_HTTP(d->m_soupRequest.get())));
if (!d->m_soupMessage)
return false;
@@ -609,65 +582,23 @@ static bool startHttp(ResourceHandle* handle)
g_signal_connect(soupMessage, "restarted", G_CALLBACK(restartedCallback), handle);
g_signal_connect(soupMessage, "got-headers", G_CALLBACK(gotHeadersCallback), handle);
+ g_signal_connect(soupMessage, "wrote-body-data", G_CALLBACK(wroteBodyDataCallback), handle);
d->m_gotChunkHandler = g_signal_connect(soupMessage, "got-chunk", G_CALLBACK(gotChunkCallback), handle);
-#ifdef HAVE_LIBSOUP_2_29_90
String firstPartyString = request.firstPartyForCookies().string();
if (!firstPartyString.isEmpty()) {
GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data()));
soup_message_set_first_party(soupMessage, firstParty.get());
}
-#endif
FormData* httpBody = d->m_firstRequest.httpBody();
- if (httpBody && !httpBody->isEmpty()) {
- size_t numElements = httpBody->elements().size();
-
- // handle the most common case (i.e. no file upload)
- if (numElements < 2) {
- Vector<char> body;
- httpBody->flatten(body);
- soup_message_set_request(soupMessage, d->m_firstRequest.httpContentType().utf8().data(),
- SOUP_MEMORY_COPY, body.data(), body.size());
- } else {
- /*
- * we have more than one element to upload, and some may
- * be (big) files, which we will want to mmap instead of
- * copying into memory; TODO: support upload of non-local
- * (think sftp://) files by using GIO?
- */
- soup_message_body_set_accumulate(soupMessage->request_body, FALSE);
- for (size_t i = 0; i < numElements; i++) {
- const FormDataElement& element = httpBody->elements()[i];
-
- if (element.m_type == FormDataElement::data)
- soup_message_body_append(soupMessage->request_body, SOUP_MEMORY_TEMPORARY, element.m_data.data(), element.m_data.size());
- else {
- /*
- * mapping for uploaded files code inspired by technique used in
- * libsoup's simple-httpd test
- */
- GOwnPtr<GError> error;
- CString fileName = fileSystemRepresentation(element.m_filename);
- GMappedFile* fileMapping = g_mapped_file_new(fileName.data(), false, &error.outPtr());
-
- if (error) {
- g_signal_handlers_disconnect_matched(soupMessage, G_SIGNAL_MATCH_DATA,
- 0, 0, 0, 0, handle);
- d->m_soupMessage.clear();
-
- return false;
- }
-
- SoupBuffer* soupBuffer = soup_buffer_new_with_owner(g_mapped_file_get_contents(fileMapping),
- g_mapped_file_get_length(fileMapping),
- fileMapping,
- reinterpret_cast<GDestroyNotify>(g_mapped_file_unref));
- soup_message_body_append_buffer(soupMessage->request_body, soupBuffer);
- soup_buffer_free(soupBuffer);
- }
- }
- }
+ CString contentType = d->m_firstRequest.httpContentType().utf8().data();
+ if (httpBody && !httpBody->isEmpty()
+ && !addFormElementsToSoupMessage(soupMessage, contentType.data(), httpBody, d->m_bodySize)) {
+ // We failed to prepare the body data, so just fail this load.
+ g_signal_handlers_disconnect_matched(soupMessage, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, handle);
+ d->m_soupMessage.clear();
+ return false;
}
// balanced by a deref() in cleanupSoupRequestOperation, which should always run
@@ -681,7 +612,7 @@ static bool startHttp(ResourceHandle* handle)
// Send the request only if it's not been explicitely deferred.
if (!d->m_defersLoading) {
d->m_cancellable = adoptGRef(g_cancellable_new());
- webkit_soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
+ soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
}
return true;
@@ -715,19 +646,13 @@ bool ResourceHandle::start(NetworkingContext* context)
// Used to set the authentication dialog toplevel; may be NULL
d->m_context = context;
- if (equalIgnoringCase(protocol, "data"))
- return startData(this, urlString);
-
if (equalIgnoringCase(protocol, "http") || equalIgnoringCase(protocol, "https")) {
- if (startHttp(this))
+ if (startHTTPRequest(this))
return true;
}
- if (equalIgnoringCase(protocol, "file") || equalIgnoringCase(protocol, "ftp") || equalIgnoringCase(protocol, "ftps")) {
- // FIXME: should we be doing any other protocols here?
- if (startGio(this, url))
- return true;
- }
+ if (startNonHTTPRequest(this, url))
+ return true;
// Error must not be reported immediately
this->scheduleFailure(InvalidURLFailure);
@@ -764,7 +689,7 @@ void ResourceHandle::platformSetDefersLoading(bool defersLoading)
if (!defersLoading && !d->m_cancellable && d->m_soupRequest.get()) {
d->m_cancellable = adoptGRef(g_cancellable_new());
- webkit_soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
+ soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
return;
}
@@ -795,11 +720,13 @@ bool ResourceHandle::willLoadFromCache(ResourceRequest&, Frame*)
void ResourceHandle::loadResourceSynchronously(NetworkingContext* context, const ResourceRequest& request, StoredCredentials /*storedCredentials*/, ResourceError& error, ResourceResponse& response, Vector<char>& data)
{
WebCoreSynchronousLoader syncLoader(error, response, data);
- // FIXME: we should use the ResourceHandle::create method here,
- // but it makes us timeout in a couple of tests. See
- // https://bugs.webkit.org/show_bug.cgi?id=41823
- RefPtr<ResourceHandle> handle = adoptRef(new ResourceHandle(request, &syncLoader, false /*defersLoading*/, false /*shouldContentSniff*/));
- handle->start(context);
+ RefPtr<ResourceHandle> handle = create(context, request, &syncLoader, false /*defersLoading*/, false /*shouldContentSniff*/);
+ if (!handle)
+ return;
+
+ // If the request has already failed, do not run the main loop, or else we'll block indefinitely.
+ if (handle->d->m_scheduledFailureType != NoFailure)
+ return;
syncLoader.run();
}
@@ -811,18 +738,8 @@ static void closeCallback(GObject* source, GAsyncResult* res, gpointer)
return;
ResourceHandleInternal* d = handle->getInternal();
- ResourceHandleClient* client = handle->client();
-
g_input_stream_close_finish(d->m_inputStream.get(), res, 0);
cleanupSoupRequestOperation(handle.get());
-
- // The load may have been cancelled, the client may have been
- // destroyed already. In such cases calling didFinishLoading is a
- // bad idea.
- if (d->m_cancelled || !client)
- return;
-
- client->didFinishLoading(handle.get(), 0);
}
static void readCallback(GObject* source, GAsyncResult* asyncResult, gpointer data)
@@ -844,7 +761,7 @@ static void readCallback(GObject* source, GAsyncResult* asyncResult, gpointer da
gssize bytesRead = g_input_stream_read_finish(d->m_inputStream.get(), asyncResult, &error.outPtr());
if (error) {
- SoupURI* uri = webkit_soup_request_get_uri(d->m_soupRequest.get());
+ SoupURI* uri = soup_request_get_uri(d->m_soupRequest.get());
GOwnPtr<char> uriStr(soup_uri_to_string(uri, false));
ResourceError resourceError(g_quark_to_string(G_IO_ERROR), error->code, uriStr.get(),
error ? String::fromUTF8(error->message) : String());
@@ -854,6 +771,10 @@ static void readCallback(GObject* source, GAsyncResult* asyncResult, gpointer da
}
if (!bytesRead) {
+ // Finish the load. We do not wait for the stream to
+ // close. Instead we better notify WebCore as soon as possible
+ client->didFinishLoading(handle.get(), 0);
+
g_input_stream_close_async(d->m_inputStream.get(), G_PRIORITY_DEFAULT,
0, closeCallback, 0);
return;
@@ -881,7 +802,7 @@ static void readCallback(GObject* source, GAsyncResult* asyncResult, gpointer da
d->m_cancellable.get(), readCallback, data);
}
-static bool startGio(ResourceHandle* handle, KURL url)
+static bool startNonHTTPRequest(ResourceHandle* handle, KURL url)
{
ASSERT(handle);
@@ -889,18 +810,14 @@ static bool startGio(ResourceHandle* handle, KURL url)
return false;
SoupSession* session = handle->defaultSession();
+ ensureSessionIsInitialized(session);
+ SoupRequester* requester = SOUP_REQUESTER(soup_session_get_feature(session, SOUP_TYPE_REQUESTER));
ResourceHandleInternal* d = handle->getInternal();
- // GIO doesn't know how to handle refs and queries, so remove them
- // TODO: use KURL.fileSystemPath after KURLGtk and FileSystemGtk are
- // using GIO internally, and providing URIs instead of file paths
- url.removeFragmentIdentifier();
- url.setQuery(String());
- url.removePort();
CString urlStr = url.string().utf8();
GOwnPtr<GError> error;
- d->m_soupRequest = adoptGRef(webkit_soup_requester_request(d->m_requester.get(), urlStr.data(), session, &error.outPtr()));
+ d->m_soupRequest = adoptGRef(soup_requester_request(requester, urlStr.data(), &error.outPtr()));
if (error) {
d->m_soupRequest = 0;
return false;
@@ -912,7 +829,7 @@ static bool startGio(ResourceHandle* handle, KURL url)
handle->ref();
d->m_cancellable = adoptGRef(g_cancellable_new());
- webkit_soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
+ soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
return true;
}
diff --git a/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp b/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp
index d46e47b..5016bf1 100644
--- a/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp
+++ b/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp
@@ -46,13 +46,11 @@ void ResourceRequest::updateSoupMessage(SoupMessage* soupMessage) const
soup_message_headers_append(soupHeaders, it->first.string().utf8().data(), it->second.utf8().data());
}
-#ifdef HAVE_LIBSOUP_2_29_90
String firstPartyString = firstPartyForCookies().string();
if (!firstPartyString.isEmpty()) {
GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data()));
soup_message_set_first_party(soupMessage, firstParty.get());
}
-#endif
soup_message_set_flags(soupMessage, m_soupFlags);
}
@@ -71,13 +69,11 @@ SoupMessage* ResourceRequest::toSoupMessage() const
soup_message_headers_append(soupHeaders, it->first.string().utf8().data(), it->second.utf8().data());
}
-#ifdef HAVE_LIBSOUP_2_29_90
String firstPartyString = firstPartyForCookies().string();
if (!firstPartyString.isEmpty()) {
GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data()));
soup_message_set_first_party(soupMessage, firstParty.get());
}
-#endif
soup_message_set_flags(soupMessage, m_soupFlags);
@@ -104,11 +100,9 @@ void ResourceRequest::updateFromSoupMessage(SoupMessage* soupMessage)
if (soupMessage->request_body->data)
m_httpBody = FormData::create(soupMessage->request_body->data, soupMessage->request_body->length);
-#ifdef HAVE_LIBSOUP_2_29_90
SoupURI* firstParty = soup_message_get_first_party(soupMessage);
if (firstParty)
m_firstPartyForCookies = soupURIToKURL(firstParty);
-#endif
m_soupFlags = soup_message_get_flags(soupMessage);
diff --git a/Source/WebCore/platform/network/soup/SocketStreamHandle.h b/Source/WebCore/platform/network/soup/SocketStreamHandle.h
index 3168fae..c8fe3b3 100644
--- a/Source/WebCore/platform/network/soup/SocketStreamHandle.h
+++ b/Source/WebCore/platform/network/soup/SocketStreamHandle.h
@@ -60,7 +60,7 @@ namespace WebCore {
private:
GRefPtr<GSocketConnection> m_socketConnection;
GRefPtr<GInputStream> m_inputStream;
- GRefPtr<GOutputStream> m_outputStream;
+ GRefPtr<GPollableOutputStream> m_outputStream;
GRefPtr<GSource> m_writeReadySource;
char* m_readBuffer;
void* m_id;
diff --git a/Source/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp b/Source/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp
index 841e209..34382dd 100644
--- a/Source/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp
+++ b/Source/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp
@@ -50,7 +50,7 @@ namespace WebCore {
// These functions immediately call the similarly named SocketStreamHandle methods.
static void connectedCallback(GSocketClient*, GAsyncResult*, void*);
static void readReadyCallback(GInputStream*, GAsyncResult*, void*);
-static gboolean writeReadyCallback(GSocket*, GIOCondition, void*);
+static gboolean writeReadyCallback(GPollableOutputStream*, void*);
// Having a list of active handles means that we do not have to worry about WebCore
// reference counting in GLib callbacks. Once the handle is off the active handles list
@@ -82,13 +82,12 @@ SocketStreamHandle::SocketStreamHandle(const KURL& url, SocketStreamHandleClient
: SocketStreamHandleBase(url, client)
, m_readBuffer(0)
{
- // No support for SSL sockets yet.
- if (url.protocolIs("wss"))
- return;
- unsigned int port = url.hasPort() ? url.port() : 80;
+ unsigned int port = url.hasPort() ? url.port() : (url.protocolIs("wss") ? 443 : 80);
m_id = activateHandle(this);
GRefPtr<GSocketClient> socketClient = adoptGRef(g_socket_client_new());
+ if (url.protocolIs("wss"))
+ g_socket_client_set_tls(socketClient.get(), TRUE);
g_socket_client_connect_to_host_async(socketClient.get(), url.host().utf8().data(), port, 0,
reinterpret_cast<GAsyncReadyCallback>(connectedCallback), m_id);
}
@@ -108,7 +107,7 @@ void SocketStreamHandle::connected(GSocketConnection* socketConnection, GError*
}
m_socketConnection = adoptGRef(socketConnection);
- m_outputStream = g_io_stream_get_output_stream(G_IO_STREAM(m_socketConnection.get()));
+ m_outputStream = G_POLLABLE_OUTPUT_STREAM(g_io_stream_get_output_stream(G_IO_STREAM(m_socketConnection.get())));
m_inputStream = g_io_stream_get_input_stream(G_IO_STREAM(m_socketConnection.get()));
m_readBuffer = new char[READ_BUFFER_SIZE];
@@ -156,14 +155,14 @@ void SocketStreamHandle::writeReady()
int SocketStreamHandle::platformSend(const char* data, int length)
{
- if (!g_socket_condition_check(g_socket_connection_get_socket(m_socketConnection.get()), G_IO_OUT)) {
+ if (!g_pollable_output_stream_is_writable(m_outputStream.get())) {
beginWaitingForSocketWritability();
return 0;
}
GOwnPtr<GError> error;
- gssize written = g_output_stream_write(m_outputStream.get(), data, length, 0, &error.outPtr());
- if (error) {
+ gssize written = g_pollable_output_stream_write_nonblocking(m_outputStream.get(), data, length, 0, &error.outPtr());
+ if (error && !g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
m_client->didFail(this, SocketStreamError(error->code)); // FIXME: Provide a sensible error.
return 0;
}
@@ -222,8 +221,7 @@ void SocketStreamHandle::beginWaitingForSocketWritability()
if (m_writeReadySource) // Already waiting.
return;
- m_writeReadySource = adoptGRef(g_socket_create_source(
- g_socket_connection_get_socket(m_socketConnection.get()), static_cast<GIOCondition>(G_IO_OUT), 0));
+ m_writeReadySource = adoptGRef(g_pollable_output_stream_create_source(m_outputStream.get(), 0));
g_source_set_callback(m_writeReadySource.get(), reinterpret_cast<GSourceFunc>(writeReadyCallback), m_id, 0);
g_source_attach(m_writeReadySource.get(), 0);
}
@@ -266,24 +264,13 @@ static void readReadyCallback(GInputStream* stream, GAsyncResult* result, void*
handle->readBytes(bytesRead, error.get());
}
-static gboolean writeReadyCallback(GSocket*, GIOCondition condition, void* id)
+static gboolean writeReadyCallback(GPollableOutputStream*, void* id)
{
SocketStreamHandle* handle = getHandleFromId(id);
if (!handle)
return FALSE;
- // G_IO_HUP and G_IO_ERR are are always active. See:
- // http://library.gnome.org/devel/gio/stable/GSocket.html#g-socket-create-source
- if (condition & G_IO_HUP) {
- handle->close();
- return FALSE;
- }
- if (condition & G_IO_ERR) {
- handle->client()->didFail(handle, SocketStreamError(0)); // FIXME: Provide a sensible error.
- return FALSE;
- }
- if (condition & G_IO_OUT)
- handle->writeReady();
+ handle->writeReady();
return TRUE;
}
diff --git a/Source/WebCore/platform/network/soup/cache/soup-directory-input-stream.c b/Source/WebCore/platform/network/soup/cache/soup-directory-input-stream.c
deleted file mode 100644
index c14863b..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-directory-input-stream.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2008 Red Hat, Inc.
- * Copyright (C) 2010 Igalia, S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "soup-directory-input-stream.h"
-
-#include <libsoup/soup.h>
-#include <stdio.h>
-#include <string.h>
-
-#define INIT_STRING "<html><head><title>OMG!</title></head><body><table>"
-#define EXIT_STRING "</table></html>"
-
-G_DEFINE_TYPE (WebKitSoupDirectoryInputStream, webkit_soup_directory_input_stream, G_TYPE_INPUT_STREAM)
-
-static SoupBuffer *
-webkit_soup_directory_input_stream_parse_info (WebKitSoupDirectoryInputStream * stream,
- GFileInfo * info)
-{
- SoupBuffer *buffer;
- GString *string;
- const char *s;
- char *escaped, *path, *xml_string;
-
- if (!g_file_info_get_name (info))
- return NULL;
-
- s = g_file_info_get_display_name (info);
- if (!s) {
- s = g_file_info_get_name (info);
- /* FIXME: convert somehow? */
- if (!g_utf8_validate (s, -1, NULL))
- return NULL;
- }
- string = g_string_new ("<tr>");
-
- xml_string = g_markup_escape_text (s, -1);
- escaped = g_uri_escape_string (g_file_info_get_name (info), NULL, FALSE);
- path = g_strconcat (stream->uri, "/", escaped, NULL);
- g_free (escaped);
- g_string_append_printf (string, "<td><a href=\"%s\">%s</a></td>", path, xml_string);
- g_free (path);
- g_free (xml_string);
- g_string_append (string, "</tr>");
-
- buffer = soup_buffer_new (SOUP_MEMORY_TAKE, string->str, string->len);
- g_string_free (string, FALSE);
-
- return buffer;
-}
-
-static SoupBuffer *
-webkit_soup_directory_input_stream_read_next_file (WebKitSoupDirectoryInputStream *stream,
- GCancellable *cancellable,
- GError **error)
-{
- GFileInfo *info;
- SoupBuffer *buffer;
- GError *err = NULL;
-
- do {
- info = g_file_enumerator_next_file (stream->enumerator, cancellable, &err);
- if (info == NULL) {
- if (err) {
- g_propagate_error (error, err);
- return NULL;
- } else if (!stream->done) {
- stream->done = TRUE;
- return soup_buffer_new (SOUP_MEMORY_STATIC,
- EXIT_STRING,
- sizeof (EXIT_STRING));
- } else {
- return NULL;
- }
- }
-
- buffer = webkit_soup_directory_input_stream_parse_info (stream, info);
- } while (buffer == NULL);
-
- return buffer;
-}
-
-static gssize
-webkit_soup_directory_input_stream_read (GInputStream *input,
- void *buffer,
- gsize count,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupDirectoryInputStream *stream = WEBKIT_SOUP_DIRECTORY_INPUT_STREAM (input);
- gsize total, size;
-
- for (total = 0; total < count; total += size) {
- if (stream->buffer == NULL) {
- stream->buffer = webkit_soup_directory_input_stream_read_next_file (stream, cancellable, error);
- if (stream->buffer == NULL) {
- /* FIXME: Is this correct or should we forward the error? */
- if (total)
- g_clear_error (error);
- return total;
- }
- }
-
- size = MIN (stream->buffer->length, count - total);
- memcpy ((char *)buffer + total, stream->buffer->data, size);
- if (size == stream->buffer->length) {
- soup_buffer_free (stream->buffer);
- stream->buffer = NULL;
- } else {
- SoupBuffer *sub = soup_buffer_new_subbuffer (stream->buffer,
- size,
- stream->buffer->length - size);
- soup_buffer_free (stream->buffer);
- stream->buffer = sub;
- }
- }
-
- return total;
-}
-
-static gboolean
-webkit_soup_directory_input_stream_close (GInputStream *input,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupDirectoryInputStream *stream = WEBKIT_SOUP_DIRECTORY_INPUT_STREAM (input);
- gboolean result;
-
- if (stream->buffer) {
- soup_buffer_free (stream->buffer);
- stream->buffer = NULL;
- }
-
- result = g_file_enumerator_close (stream->enumerator,
- cancellable,
- error);
- g_object_unref (stream->enumerator);
- stream->enumerator = NULL;
-
- g_free (stream->uri);
- stream->uri = NULL;
-
- return result;
-}
-
-static void
-webkit_soup_directory_input_stream_class_init (WebKitSoupDirectoryInputStreamClass *stream_class)
-{
- GInputStreamClass *inputstream_class = G_INPUT_STREAM_CLASS (stream_class);
-
- inputstream_class->read_fn = webkit_soup_directory_input_stream_read;
- inputstream_class->close_fn = webkit_soup_directory_input_stream_close;
-}
-
-static void
-webkit_soup_directory_input_stream_init (WebKitSoupDirectoryInputStream *stream)
-{
- stream->buffer = soup_buffer_new (SOUP_MEMORY_STATIC,
- INIT_STRING,
- sizeof (INIT_STRING));
-}
-
-GInputStream *
-webkit_soup_directory_input_stream_new (GFileEnumerator *enumerator,
- SoupURI *uri)
-{
- GInputStream *stream;
-
- g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
- g_return_val_if_fail (uri != NULL, NULL);
-
- stream = g_object_new (WEBKIT_TYPE_SOUP_DIRECTORY_INPUT_STREAM, NULL);
-
- WEBKIT_SOUP_DIRECTORY_INPUT_STREAM (stream)->enumerator = g_object_ref (enumerator);
- WEBKIT_SOUP_DIRECTORY_INPUT_STREAM (stream)->uri = soup_uri_to_string (uri, FALSE);
-
- return stream;
-}
-
diff --git a/Source/WebCore/platform/network/soup/cache/soup-directory-input-stream.h b/Source/WebCore/platform/network/soup/cache/soup-directory-input-stream.h
deleted file mode 100644
index 0c5b0be..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-directory-input-stream.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2010 Red Hat, Inc.
- * Copyright (C) 2010 Igalia, S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef WEBKIT_SOUP_DIRECTORY_INPUT_STREAM_H
-#define WEBKIT_SOUP_DIRECTORY_INPUT_STREAM_H 1
-
-#include <gio/gio.h>
-#include <libsoup/soup-types.h>
-#include <libsoup/soup-message-body.h>
-
-G_BEGIN_DECLS
-
-#define WEBKIT_TYPE_SOUP_DIRECTORY_INPUT_STREAM (webkit_soup_directory_input_stream_get_type ())
-#define WEBKIT_SOUP_DIRECTORY_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WEBKIT_TYPE_SOUP_DIRECTORY_INPUT_STREAM, WebKitSoupDirectoryInputStream))
-#define WEBKIT_SOUP_DIRECTORY_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_SOUP_DIRECTORY_INPUT_STREAM, WebKitSoupDirectoryInputStreamClass))
-#define WEBKIT_IS_SOUP_DIRECTORY_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEBKIT_TYPE_SOUP_DIRECTORY_INPUT_STREAM))
-#define WEBKIT_IS_SOUP_DIRECTORY_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), WEBKIT_TYPE_SOUP_DIRECTORY_INPUT_STREAM))
-#define WEBKIT_SOUP_DIRECTORY_INPUT_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WEBKIT_TYPE_SOUP_DIRECTORY_INPUT_STREAM, WebKitSoupDirectoryInputStreamClass))
-
-typedef struct _WebKitSoupDirectoryInputStream WebKitSoupDirectoryInputStream;
-typedef struct _WebKitSoupDirectoryInputStreamClass WebKitSoupDirectoryInputStreamClass;
-
-struct _WebKitSoupDirectoryInputStream {
- GInputStream parent;
-
- GFileEnumerator *enumerator;
- char *uri;
- SoupBuffer *buffer;
- gboolean done;
-};
-
-struct _WebKitSoupDirectoryInputStreamClass {
- GInputStreamClass parent_class;
-};
-
-GType webkit_soup_directory_input_stream_get_type (void);
-
-GInputStream *webkit_soup_directory_input_stream_new (GFileEnumerator *enumerator,
- SoupURI *uri);
-
-
-G_END_DECLS
-
-#endif /* WEBKIT_SOUP_DIRECTORY_INPUT_STREAM_H */
diff --git a/Source/WebCore/platform/network/soup/cache/soup-http-input-stream.c b/Source/WebCore/platform/network/soup/cache/soup-http-input-stream.c
deleted file mode 100644
index 2a5d995..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-http-input-stream.c
+++ /dev/null
@@ -1,922 +0,0 @@
-/* soup-input-stream.c, based on gsocketinputstream.c
- *
- * Copyright (C) 2006-2007 Red Hat, Inc.
- * Copyright (C) 2010 Igalia, S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <config.h>
-
-#include <string.h>
-
-#include <glib.h>
-#include <gio/gio.h>
-
-#include <libsoup/soup.h>
-
-#include "soup-http-input-stream.h"
-
-static void webkit_soup_http_input_stream_seekable_iface_init (GSeekableIface *seekable_iface);
-
-G_DEFINE_TYPE_WITH_CODE (WebKitSoupHTTPInputStream, webkit_soup_http_input_stream, G_TYPE_INPUT_STREAM,
- G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
- webkit_soup_http_input_stream_seekable_iface_init))
-
-typedef void (*WebKitSoupHTTPInputStreamCallback)(GInputStream *);
-
-typedef struct {
- SoupSession *session;
- GMainContext *async_context;
- SoupMessage *msg;
- gboolean got_headers, finished;
- goffset offset;
-
- GCancellable *cancellable;
- GSource *cancel_watch;
- WebKitSoupHTTPInputStreamCallback got_headers_cb;
- WebKitSoupHTTPInputStreamCallback got_chunk_cb;
- WebKitSoupHTTPInputStreamCallback finished_cb;
- WebKitSoupHTTPInputStreamCallback cancelled_cb;
-
- guchar *leftover_buffer;
- gsize leftover_bufsize, leftover_offset;
-
- guchar *caller_buffer;
- gsize caller_bufsize, caller_nread;
- GAsyncReadyCallback outstanding_callback;
- GSimpleAsyncResult *result;
-} WebKitSoupHTTPInputStreamPrivate;
-#define WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), WEBKIT_TYPE_SOUP_HTTP_INPUT_STREAM, WebKitSoupHTTPInputStreamPrivate))
-
-
-static gssize webkit_soup_http_input_stream_read (GInputStream *stream,
- void *buffer,
- gsize count,
- GCancellable *cancellable,
- GError **error);
-static gboolean webkit_soup_http_input_stream_close (GInputStream *stream,
- GCancellable *cancellable,
- GError **error);
-static void webkit_soup_http_input_stream_read_async (GInputStream *stream,
- void *buffer,
- gsize count,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer data);
-static gssize webkit_soup_http_input_stream_read_finish (GInputStream *stream,
- GAsyncResult *result,
- GError **error);
-static void webkit_soup_http_input_stream_close_async (GInputStream *stream,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer data);
-static gboolean webkit_soup_http_input_stream_close_finish (GInputStream *stream,
- GAsyncResult *result,
- GError **error);
-
-static goffset webkit_soup_http_input_stream_tell (GSeekable *seekable);
-
-static gboolean webkit_soup_http_input_stream_can_seek (GSeekable *seekable);
-static gboolean webkit_soup_http_input_stream_seek (GSeekable *seekable,
- goffset offset,
- GSeekType type,
- GCancellable *cancellable,
- GError **error);
-
-static gboolean webkit_soup_http_input_stream_can_truncate (GSeekable *seekable);
-static gboolean webkit_soup_http_input_stream_truncate (GSeekable *seekable,
- goffset offset,
- GCancellable *cancellable,
- GError **error);
-
-static void webkit_soup_http_input_stream_got_headers (SoupMessage *msg, gpointer stream);
-static void webkit_soup_http_input_stream_got_chunk (SoupMessage *msg, SoupBuffer *chunk, gpointer stream);
-static void webkit_soup_http_input_stream_finished (SoupMessage *msg, gpointer stream);
-
-static void
-webkit_soup_http_input_stream_finalize (GObject *object)
-{
- WebKitSoupHTTPInputStream *stream = WEBKIT_SOUP_HTTP_INPUT_STREAM (object);
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- g_object_unref (priv->session);
-
- g_signal_handlers_disconnect_by_func (priv->msg, G_CALLBACK (webkit_soup_http_input_stream_got_headers), stream);
- g_signal_handlers_disconnect_by_func (priv->msg, G_CALLBACK (webkit_soup_http_input_stream_got_chunk), stream);
- g_signal_handlers_disconnect_by_func (priv->msg, G_CALLBACK (webkit_soup_http_input_stream_finished), stream);
- g_object_unref (priv->msg);
- g_free (priv->leftover_buffer);
-
- if (G_OBJECT_CLASS (webkit_soup_http_input_stream_parent_class)->finalize)
- (*G_OBJECT_CLASS (webkit_soup_http_input_stream_parent_class)->finalize)(object);
-}
-
-static void
-webkit_soup_http_input_stream_class_init (WebKitSoupHTTPInputStreamClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (WebKitSoupHTTPInputStreamPrivate));
-
- gobject_class->finalize = webkit_soup_http_input_stream_finalize;
-
- stream_class->read_fn = webkit_soup_http_input_stream_read;
- stream_class->close_fn = webkit_soup_http_input_stream_close;
- stream_class->read_async = webkit_soup_http_input_stream_read_async;
- stream_class->read_finish = webkit_soup_http_input_stream_read_finish;
- stream_class->close_async = webkit_soup_http_input_stream_close_async;
- stream_class->close_finish = webkit_soup_http_input_stream_close_finish;
-}
-
-static void
-webkit_soup_http_input_stream_seekable_iface_init (GSeekableIface *seekable_iface)
-{
- seekable_iface->tell = webkit_soup_http_input_stream_tell;
- seekable_iface->can_seek = webkit_soup_http_input_stream_can_seek;
- seekable_iface->seek = webkit_soup_http_input_stream_seek;
- seekable_iface->can_truncate = webkit_soup_http_input_stream_can_truncate;
- seekable_iface->truncate_fn = webkit_soup_http_input_stream_truncate;
-}
-
-static void
-webkit_soup_http_input_stream_init (WebKitSoupHTTPInputStream *stream)
-{
- ;
-}
-
-static void
-webkit_soup_http_input_stream_queue_message (WebKitSoupHTTPInputStream *stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- priv->got_headers = priv->finished = FALSE;
-
- /* Add an extra ref since soup_session_queue_message steals one */
- g_object_ref (priv->msg);
- soup_session_queue_message (priv->session, priv->msg, NULL, NULL);
-}
-
-/**
- * webkit_soup_http_input_stream_new:
- * @session: the #SoupSession to use
- * @msg: the #SoupMessage whose response will be streamed
- *
- * Prepares to send @msg over @session, and returns a #GInputStream
- * that can be used to read the response.
- *
- * @msg may not be sent until the first read call; if you need to look
- * at the status code or response headers before reading the body, you
- * can use webkit_soup_http_input_stream_send() or webkit_soup_http_input_stream_send_async()
- * to force the message to be sent and the response headers read.
- *
- * If @msg gets a non-2xx result, the first read (or send) will return
- * an error with type %WEBKIT_SOUP_HTTP_INPUT_STREAM_HTTP_ERROR.
- *
- * Internally, #WebKitSoupHTTPInputStream is implemented using asynchronous I/O,
- * so if you are using the synchronous API (eg,
- * g_input_stream_read()), you should create a new #GMainContext and
- * set it as the %SOUP_SESSION_ASYNC_CONTEXT property on @session. (If
- * you don't, then synchronous #GInputStream calls will cause the main
- * loop to be run recursively.) The async #GInputStream API works fine
- * with %SOUP_SESSION_ASYNC_CONTEXT either set or unset.
- *
- * Returns: a new #GInputStream.
- **/
-WebKitSoupHTTPInputStream *
-webkit_soup_http_input_stream_new (SoupSession *session, SoupMessage *msg)
-{
- WebKitSoupHTTPInputStream *stream;
- WebKitSoupHTTPInputStreamPrivate *priv;
-
- g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
-
- stream = g_object_new (WEBKIT_TYPE_SOUP_HTTP_INPUT_STREAM, NULL);
- priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- priv->session = g_object_ref (session);
- priv->async_context = soup_session_get_async_context (session);
- priv->msg = g_object_ref (msg);
-
- g_signal_connect (msg, "got_headers",
- G_CALLBACK (webkit_soup_http_input_stream_got_headers), stream);
- g_signal_connect (msg, "got_chunk",
- G_CALLBACK (webkit_soup_http_input_stream_got_chunk), stream);
- g_signal_connect (msg, "finished",
- G_CALLBACK (webkit_soup_http_input_stream_finished), stream);
-
- webkit_soup_http_input_stream_queue_message (stream);
- return stream;
-}
-
-static void
-webkit_soup_http_input_stream_got_headers (SoupMessage *msg, gpointer stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- /* If the status is unsuccessful, we just ignore the signal and let
- * libsoup keep going (eventually either it will requeue the request
- * (after handling authentication/redirection), or else the
- * "finished" handler will run).
- */
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
- return;
-
- priv->got_headers = TRUE;
- if (!priv->caller_buffer) {
- /* Not ready to read the body yet */
- soup_session_pause_message (priv->session, msg);
- }
-
- if (priv->got_headers_cb)
- priv->got_headers_cb (stream);
-}
-
-static void
-webkit_soup_http_input_stream_got_chunk (SoupMessage *msg, SoupBuffer *chunk_buffer,
- gpointer stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
- const gchar *chunk = chunk_buffer->data;
- gsize chunk_size = chunk_buffer->length;
-
- /* We only pay attention to the chunk if it's part of a successful
- * response.
- */
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
- return;
-
- /* Sanity check */
- if (priv->caller_bufsize == 0 || priv->leftover_bufsize != 0)
- g_warning ("webkit_soup_http_input_stream_got_chunk called again before previous chunk was processed");
-
- /* Copy what we can into priv->caller_buffer */
- if (priv->caller_bufsize > priv->caller_nread) {
- gsize nread = MIN (chunk_size, priv->caller_bufsize - priv->caller_nread);
-
- memcpy (priv->caller_buffer + priv->caller_nread, chunk, nread);
- priv->caller_nread += nread;
- priv->offset += nread;
- chunk += nread;
- chunk_size -= nread;
- }
-
- if (chunk_size > 0) {
- /* Copy the rest into priv->leftover_buffer. If
- * there's already some data there, realloc and
- * append. Otherwise just copy.
- */
- if (priv->leftover_bufsize) {
- priv->leftover_buffer = g_realloc (priv->leftover_buffer,
- priv->leftover_bufsize + chunk_size);
- memcpy (priv->leftover_buffer + priv->leftover_bufsize,
- chunk, chunk_size);
- priv->leftover_bufsize += chunk_size;
- } else {
- priv->leftover_bufsize = chunk_size;
- priv->leftover_buffer = g_memdup (chunk, chunk_size);
- priv->leftover_offset = 0;
- }
- }
-
- soup_session_pause_message (priv->session, msg);
- if (priv->got_chunk_cb)
- priv->got_chunk_cb (stream);
-}
-
-static void
-webkit_soup_http_input_stream_finished (SoupMessage *msg, gpointer stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- priv->finished = TRUE;
-
- if (priv->finished_cb)
- priv->finished_cb (stream);
-}
-
-static gboolean
-webkit_soup_http_input_stream_cancelled (GIOChannel *chan, GIOCondition condition,
- gpointer stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- priv->cancel_watch = NULL;
-
- soup_session_pause_message (priv->session, priv->msg);
- if (priv->cancelled_cb)
- priv->cancelled_cb (stream);
-
- return FALSE;
-}
-
-static void
-webkit_soup_http_input_stream_prepare_for_io (GInputStream *stream,
- GCancellable *cancellable,
- guchar *buffer,
- gsize count)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
- int cancel_fd;
-
- priv->cancellable = cancellable;
- cancel_fd = g_cancellable_get_fd (cancellable);
- if (cancel_fd != -1) {
- GIOChannel *chan = g_io_channel_unix_new (cancel_fd);
- priv->cancel_watch = soup_add_io_watch (priv->async_context, chan,
- G_IO_IN | G_IO_ERR | G_IO_HUP,
- webkit_soup_http_input_stream_cancelled,
- stream);
- g_io_channel_unref (chan);
- }
-
- priv->caller_buffer = buffer;
- priv->caller_bufsize = count;
- priv->caller_nread = 0;
-
- if (priv->got_headers)
- soup_session_unpause_message (priv->session, priv->msg);
-}
-
-static void
-webkit_soup_http_input_stream_done_io (GInputStream *stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- if (priv->cancel_watch) {
- g_source_destroy (priv->cancel_watch);
- priv->cancel_watch = NULL;
- g_cancellable_release_fd (priv->cancellable);
- }
- priv->cancellable = NULL;
-
- priv->caller_buffer = NULL;
- priv->caller_bufsize = 0;
-}
-
-static gboolean
-set_error_if_http_failed (SoupMessage *msg, GError **error)
-{
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- g_set_error_literal (error, SOUP_HTTP_ERROR,
- msg->status_code, msg->reason_phrase);
- return TRUE;
- }
- return FALSE;
-}
-
-static gsize
-read_from_leftover (WebKitSoupHTTPInputStreamPrivate *priv,
- gpointer buffer, gsize bufsize)
-{
- gsize nread;
-
- if (priv->leftover_bufsize - priv->leftover_offset <= bufsize) {
- nread = priv->leftover_bufsize - priv->leftover_offset;
- memcpy (buffer, priv->leftover_buffer + priv->leftover_offset, nread);
-
- g_free (priv->leftover_buffer);
- priv->leftover_buffer = NULL;
- priv->leftover_bufsize = priv->leftover_offset = 0;
- } else {
- nread = bufsize;
- memcpy (buffer, priv->leftover_buffer + priv->leftover_offset, nread);
- priv->leftover_offset += nread;
- }
-
- priv->offset += nread;
- return nread;
-}
-
-/* This does the work of webkit_soup_http_input_stream_send(), assuming that the
- * GInputStream pending flag has already been set. It is also used by
- * webkit_soup_http_input_stream_send_async() in some circumstances.
- */
-static gboolean
-webkit_soup_http_input_stream_send_internal (GInputStream *stream,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- webkit_soup_http_input_stream_prepare_for_io (stream, cancellable, NULL, 0);
- while (!priv->finished && !priv->got_headers &&
- !g_cancellable_is_cancelled (cancellable))
- g_main_context_iteration (priv->async_context, TRUE);
- webkit_soup_http_input_stream_done_io (stream);
-
- if (g_cancellable_set_error_if_cancelled (cancellable, error))
- return FALSE;
- else if (set_error_if_http_failed (priv->msg, error))
- return FALSE;
- return TRUE;
-}
-
-static void
-send_sync_finished (GInputStream *stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
- GError *error = NULL;
-
- if (!g_cancellable_set_error_if_cancelled (priv->cancellable, &error))
- set_error_if_http_failed (priv->msg, &error);
-
- priv->got_headers_cb = NULL;
- priv->finished_cb = NULL;
-
- /* Wake up the main context iteration */
- g_source_attach (g_idle_source_new (), NULL);
-}
-
-/**
- * webkit_soup_http_input_stream_send:
- * @httpstream: a #WebKitSoupHTTPInputStream
- * @cancellable: optional #GCancellable object, %NULL to ignore.
- * @error: location to store the error occuring, or %NULL to ignore
- *
- * Synchronously sends the HTTP request associated with @stream, and
- * reads the response headers. Call this after webkit_soup_http_input_stream_new()
- * and before the first g_input_stream_read() if you want to check the
- * HTTP status code before you start reading.
- *
- * Return value: %TRUE if msg has a successful (2xx) status, %FALSE if
- * not.
- **/
-gboolean
-webkit_soup_http_input_stream_send (WebKitSoupHTTPInputStream *httpstream,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (httpstream);
- GInputStream *istream = (GInputStream *)httpstream;
- gboolean result;
-
- g_return_val_if_fail (WEBKIT_IS_SOUP_HTTP_INPUT_STREAM (httpstream), FALSE);
-
- if (!g_input_stream_set_pending (istream, error))
- return FALSE;
-
- priv->got_headers_cb = send_sync_finished;
- priv->finished_cb = send_sync_finished;
-
- result = webkit_soup_http_input_stream_send_internal (istream, cancellable, error);
- g_input_stream_clear_pending (istream);
-
- return result;
-}
-
-static gssize
-webkit_soup_http_input_stream_read (GInputStream *stream,
- void *buffer,
- gsize count,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- if (priv->finished)
- return 0;
-
- /* If there is data leftover from a previous read, return it. */
- if (priv->leftover_bufsize)
- return read_from_leftover (priv, buffer, count);
-
- /* No leftover data, accept one chunk from the network */
- webkit_soup_http_input_stream_prepare_for_io (stream, cancellable, buffer, count);
- while (!priv->finished && priv->caller_nread == 0 &&
- !g_cancellable_is_cancelled (cancellable))
- g_main_context_iteration (priv->async_context, TRUE);
- webkit_soup_http_input_stream_done_io (stream);
-
- if (priv->caller_nread > 0)
- return priv->caller_nread;
-
- if (g_cancellable_set_error_if_cancelled (cancellable, error))
- return -1;
- else if (set_error_if_http_failed (priv->msg, error))
- return -1;
- else
- return 0;
-}
-
-static gboolean
-webkit_soup_http_input_stream_close (GInputStream *stream,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- if (!priv->finished)
- soup_session_cancel_message (priv->session, priv->msg, SOUP_STATUS_CANCELLED);
-
- return TRUE;
-}
-
-static void
-wrapper_callback (GObject *source_object, GAsyncResult *res,
- gpointer user_data)
-{
- GInputStream *stream = G_INPUT_STREAM (source_object);
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- g_input_stream_clear_pending (stream);
- if (priv->outstanding_callback)
- (*priv->outstanding_callback)(source_object, res, user_data);
- priv->outstanding_callback = NULL;
- g_object_unref (stream);
-}
-
-static void
-send_async_thread (GSimpleAsyncResult *res,
- GObject *object,
- GCancellable *cancellable)
-{
- GError *error = NULL;
- gboolean success;
-
- success = webkit_soup_http_input_stream_send_internal (G_INPUT_STREAM (object),
- cancellable, &error);
- g_simple_async_result_set_op_res_gboolean (res, success);
- if (error) {
- g_simple_async_result_set_from_error (res, error);
- g_error_free (error);
- }
-}
-
-static void
-webkit_soup_http_input_stream_send_async_in_thread (GInputStream *stream,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSimpleAsyncResult *res;
-
- res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data,
- webkit_soup_http_input_stream_send_async_in_thread);
- g_simple_async_result_run_in_thread (res, send_async_thread,
- io_priority, cancellable);
- g_object_unref (res);
-}
-
-static void
-send_async_finished (GInputStream *stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
- GSimpleAsyncResult *result;
- GError *error = NULL;
-
- if (!g_cancellable_set_error_if_cancelled (priv->cancellable, &error))
- set_error_if_http_failed (priv->msg, &error);
-
- priv->got_headers_cb = NULL;
- priv->finished_cb = NULL;
- webkit_soup_http_input_stream_done_io (stream);
-
- result = priv->result;
- priv->result = NULL;
-
- g_simple_async_result_set_op_res_gboolean (result, error == NULL);
- if (error) {
- g_simple_async_result_set_from_error (result, error);
- g_error_free (error);
- }
- g_simple_async_result_complete (result);
- g_object_unref (result);
-}
-
-static void
-webkit_soup_http_input_stream_send_async_internal (GInputStream *stream,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- g_object_ref (stream);
- priv->outstanding_callback = callback;
-
- /* If the session uses the default GMainContext, then we can do
- * async I/O directly. But if it has its own main context, it's
- * easier to just run it in another thread.
- */
- if (soup_session_get_async_context (priv->session)) {
- webkit_soup_http_input_stream_send_async_in_thread (stream, io_priority, cancellable,
- wrapper_callback, user_data);
- return;
- }
-
- priv->got_headers_cb = send_async_finished;
- priv->finished_cb = send_async_finished;
-
- webkit_soup_http_input_stream_prepare_for_io (stream, cancellable, NULL, 0);
- priv->result = g_simple_async_result_new (G_OBJECT (stream),
- wrapper_callback, user_data,
- webkit_soup_http_input_stream_send_async);
-}
-
-/**
- * webkit_soup_http_input_stream_send_async:
- * @httpstream: a #WebKitSoupHTTPInputStream
- * @io_priority: the io priority of the request.
- * @cancellable: optional #GCancellable object, %NULL to ignore.
- * @callback: callback to call when the request is satisfied
- * @user_data: the data to pass to callback function
- *
- * Asynchronously sends the HTTP request associated with @stream, and
- * reads the response headers. Call this after webkit_soup_http_input_stream_new()
- * and before the first g_input_stream_read_async() if you want to
- * check the HTTP status code before you start reading.
- **/
-void
-webkit_soup_http_input_stream_send_async (WebKitSoupHTTPInputStream *httpstream,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GInputStream *istream = (GInputStream *)httpstream;
- GError *error = NULL;
-
- g_return_if_fail (WEBKIT_IS_SOUP_HTTP_INPUT_STREAM (httpstream));
-
- if (!g_input_stream_set_pending (istream, &error)) {
- g_simple_async_report_gerror_in_idle (G_OBJECT (httpstream),
- callback,
- user_data,
- error);
- g_error_free (error);
- return;
- }
- webkit_soup_http_input_stream_send_async_internal (istream, io_priority, cancellable,
- callback, user_data);
-}
-
-/**
- * webkit_soup_http_input_stream_send_finish:
- * @httpstream: a #WebKitSoupHTTPInputStream
- * @result: a #GAsyncResult.
- * @error: a #GError location to store the error occuring, or %NULL to
- * ignore.
- *
- * Finishes a webkit_soup_http_input_stream_send_async() operation.
- *
- * Return value: %TRUE if the message was sent successfully and
- * received a successful status code, %FALSE if not.
- **/
-gboolean
-webkit_soup_http_input_stream_send_finish (WebKitSoupHTTPInputStream *httpstream,
- GAsyncResult *result,
- GError **error)
-{
- GSimpleAsyncResult *simple;
-
- g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
- simple = G_SIMPLE_ASYNC_RESULT (result);
-
- g_return_val_if_fail (g_simple_async_result_get_source_tag (simple) == webkit_soup_http_input_stream_send_async, FALSE);
-
- if (g_simple_async_result_propagate_error (simple, error))
- return FALSE;
-
- return g_simple_async_result_get_op_res_gboolean (simple);
-}
-
-static void
-read_async_done (GInputStream *stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
- GSimpleAsyncResult *result;
- GError *error = NULL;
-
- result = priv->result;
- priv->result = NULL;
-
- if (g_cancellable_set_error_if_cancelled (priv->cancellable, &error) ||
- set_error_if_http_failed (priv->msg, &error)) {
- g_simple_async_result_set_from_error (result, error);
- g_error_free (error);
- } else
- g_simple_async_result_set_op_res_gssize (result, priv->caller_nread);
-
- priv->got_chunk_cb = NULL;
- priv->finished_cb = NULL;
- priv->cancelled_cb = NULL;
- webkit_soup_http_input_stream_done_io (stream);
-
- g_simple_async_result_complete (result);
- g_object_unref (result);
-}
-
-static void
-webkit_soup_http_input_stream_read_async (GInputStream *stream,
- void *buffer,
- gsize count,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
- GSimpleAsyncResult *result;
-
- /* If the session uses the default GMainContext, then we can do
- * async I/O directly. But if it has its own main context, we fall
- * back to the async-via-sync-in-another-thread implementation.
- */
- if (soup_session_get_async_context (priv->session)) {
- G_INPUT_STREAM_CLASS (webkit_soup_http_input_stream_parent_class)->
- read_async (stream, buffer, count, io_priority,
- cancellable, callback, user_data);
- return;
- }
-
- result = g_simple_async_result_new (G_OBJECT (stream),
- callback, user_data,
- webkit_soup_http_input_stream_read_async);
-
- if (priv->finished) {
- g_simple_async_result_set_op_res_gssize (result, 0);
- g_simple_async_result_complete_in_idle (result);
- g_object_unref (result);
- return;
- }
-
- if (priv->leftover_bufsize) {
- gsize nread = read_from_leftover (priv, buffer, count);
- g_simple_async_result_set_op_res_gssize (result, nread);
- g_simple_async_result_complete_in_idle (result);
- g_object_unref (result);
- return;
- }
-
- priv->result = result;
-
- priv->got_chunk_cb = read_async_done;
- priv->finished_cb = read_async_done;
- priv->cancelled_cb = read_async_done;
- webkit_soup_http_input_stream_prepare_for_io (stream, cancellable, buffer, count);
-}
-
-static gssize
-webkit_soup_http_input_stream_read_finish (GInputStream *stream,
- GAsyncResult *result,
- GError **error)
-{
- GSimpleAsyncResult *simple;
-
- g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), -1);
- simple = G_SIMPLE_ASYNC_RESULT (result);
- g_return_val_if_fail (g_simple_async_result_get_source_tag (simple) == webkit_soup_http_input_stream_read_async, -1);
-
- return g_simple_async_result_get_op_res_gssize (simple);
-}
-
-static void
-webkit_soup_http_input_stream_close_async (GInputStream *stream,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSimpleAsyncResult *result;
- gboolean success;
- GError *error = NULL;
-
- result = g_simple_async_result_new (G_OBJECT (stream),
- callback, user_data,
- webkit_soup_http_input_stream_close_async);
- success = webkit_soup_http_input_stream_close (stream, cancellable, &error);
- g_simple_async_result_set_op_res_gboolean (result, success);
- if (error) {
- g_simple_async_result_set_from_error (result, error);
- g_error_free (error);
- }
-
- g_simple_async_result_complete_in_idle (result);
- g_object_unref (result);
-}
-
-static gboolean
-webkit_soup_http_input_stream_close_finish (GInputStream *stream,
- GAsyncResult *result,
- GError **error)
-{
- /* Failures handled in generic close_finish code */
- return TRUE;
-}
-
-static goffset
-webkit_soup_http_input_stream_tell (GSeekable *seekable)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (seekable);
-
- return priv->offset;
-}
-
-static gboolean
-webkit_soup_http_input_stream_can_seek (GSeekable *seekable)
-{
- return TRUE;
-}
-
-extern void soup_message_io_cleanup (SoupMessage *msg);
-
-static gboolean
-webkit_soup_http_input_stream_seek (GSeekable *seekable,
- goffset offset,
- GSeekType type,
- GCancellable *cancellable,
- GError **error)
-{
- GInputStream *stream = G_INPUT_STREAM (seekable);
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (seekable);
- char *range;
-
- if (type == G_SEEK_END) {
- /* FIXME: we could send "bytes=-offset", but unless we
- * know the Content-Length, we wouldn't be able to
- * answer a tell() properly. We could find the
- * Content-Length by doing a HEAD...
- */
-
- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
- "G_SEEK_END not currently supported");
- return FALSE;
- }
-
- if (!g_input_stream_set_pending (stream, error))
- return FALSE;
-
- soup_session_cancel_message (priv->session, priv->msg, SOUP_STATUS_CANCELLED);
- soup_message_io_cleanup (priv->msg);
-
- switch (type) {
- case G_SEEK_CUR:
- offset += priv->offset;
- /* fall through */
-
- case G_SEEK_SET:
- range = g_strdup_printf ("bytes=%" G_GUINT64_FORMAT "-", (guint64)offset);
- priv->offset = offset;
- break;
-
- case G_SEEK_END:
- range = NULL; /* keep compilers happy */
- g_return_val_if_reached (FALSE);
- break;
-
- default:
- g_return_val_if_reached (FALSE);
- }
-
- soup_message_headers_remove (priv->msg->request_headers, "Range");
- soup_message_headers_append (priv->msg->request_headers, "Range", range);
- g_free (range);
-
- webkit_soup_http_input_stream_queue_message (WEBKIT_SOUP_HTTP_INPUT_STREAM (stream));
-
- g_input_stream_clear_pending (stream);
- return TRUE;
-}
-
-static gboolean
-webkit_soup_http_input_stream_can_truncate (GSeekable *seekable)
-{
- return FALSE;
-}
-
-static gboolean
-webkit_soup_http_input_stream_truncate (GSeekable *seekable,
- goffset offset,
- GCancellable *cancellable,
- GError **error)
-{
- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
- "Truncate not allowed on input stream");
- return FALSE;
-}
-
-SoupMessage *
-webkit_soup_http_input_stream_get_message (WebKitSoupHTTPInputStream *httpstream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (httpstream);
- return priv->msg ? g_object_ref (priv->msg) : NULL;
-}
diff --git a/Source/WebCore/platform/network/soup/cache/soup-http-input-stream.h b/Source/WebCore/platform/network/soup/cache/soup-http-input-stream.h
deleted file mode 100644
index 6b98559..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-http-input-stream.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2006, 2007, 2009 Red Hat, Inc.
- * Copyright (C) 2010 Igalia, S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __WEBKIT_SOUP_HTTP_INPUT_STREAM_H__
-#define __WEBKIT_SOUP_HTTP_INPUT_STREAM_H__
-
-#include <gio/gio.h>
-#include <libsoup/soup-types.h>
-
-G_BEGIN_DECLS
-
-#define WEBKIT_TYPE_SOUP_HTTP_INPUT_STREAM (webkit_soup_http_input_stream_get_type ())
-#define WEBKIT_SOUP_HTTP_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), WEBKIT_TYPE_SOUP_HTTP_INPUT_STREAM, WebKitSoupHTTPInputStream))
-#define WEBKIT_SOUP_HTTP_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), WEBKIT_TYPE_SOUP_HTTP_INPUT_STREAM, WebKitSoupHTTPInputStreamClass))
-#define WEBKIT_IS_SOUP_HTTP_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), WEBKIT_TYPE_SOUP_HTTP_INPUT_STREAM))
-#define WEBKIT_IS_SOUP_HTTP_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), WEBKIT_TYPE_SOUP_HTTP_INPUT_STREAM))
-#define WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), WEBKIT_TYPE_SOUP_HTTP_INPUT_STREAM, WebKitSoupHTTPInputStreamClass))
-
-typedef struct WebKitSoupHTTPInputStream WebKitSoupHTTPInputStream;
-typedef struct WebKitSoupHTTPInputStreamClass WebKitSoupHTTPInputStreamClass;
-
-struct WebKitSoupHTTPInputStream {
- GInputStream parent;
-};
-
-struct WebKitSoupHTTPInputStreamClass {
- GInputStreamClass parent_class;
-
- /* Padding for future expansion */
- void (*_g_reserved1)(void);
- void (*_g_reserved2)(void);
- void (*_g_reserved3)(void);
- void (*_g_reserved4)(void);
- void (*_g_reserved5)(void);
-};
-
-GType webkit_soup_http_input_stream_get_type (void) G_GNUC_CONST;
-
-WebKitSoupHTTPInputStream *webkit_soup_http_input_stream_new (SoupSession *session,
- SoupMessage *msg);
-
-gboolean webkit_soup_http_input_stream_send (WebKitSoupHTTPInputStream *httpstream,
- GCancellable *cancellable,
- GError **error);
-
-void webkit_soup_http_input_stream_send_async (WebKitSoupHTTPInputStream *httpstream,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean webkit_soup_http_input_stream_send_finish (WebKitSoupHTTPInputStream *httpstream,
- GAsyncResult *result,
- GError **error);
-
-SoupMessage *webkit_soup_http_input_stream_get_message (WebKitSoupHTTPInputStream *httpstream);
-
-G_END_DECLS
-
-#endif /* __WEBKIT_SOUP_HTTP_INPUT_STREAM_H__ */
diff --git a/Source/WebCore/platform/network/soup/cache/soup-request-data.c b/Source/WebCore/platform/network/soup/cache/soup-request-data.c
deleted file mode 100644
index ced5c4a..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-request-data.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-request-data.c: data: URI request object
- *
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2010 Igalia, S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "soup-request-data.h"
-
-#include "soup-requester.h"
-#include <libsoup/soup.h>
-#include <glib/gi18n.h>
-
-G_DEFINE_TYPE (WebKitSoupRequestData, webkit_soup_request_data, WEBKIT_TYPE_SOUP_REQUEST)
-
-struct _WebKitSoupRequestDataPrivate {
- gsize content_length;
- char *content_type;
-};
-
-static void
-webkit_soup_request_data_init (WebKitSoupRequestData *data)
-{
- data->priv = G_TYPE_INSTANCE_GET_PRIVATE (data, WEBKIT_TYPE_SOUP_REQUEST_DATA, WebKitSoupRequestDataPrivate);
-}
-
-static void
-webkit_soup_request_data_finalize (GObject *object)
-{
- WebKitSoupRequestData *data = WEBKIT_SOUP_REQUEST_DATA (object);
-
- g_free (data->priv->content_type);
-
- G_OBJECT_CLASS (webkit_soup_request_data_parent_class)->finalize (object);
-}
-
-static gboolean
-webkit_soup_request_data_check_uri (WebKitSoupRequest *request,
- SoupURI *uri,
- GError **error)
-{
- return uri->host == NULL;
-}
-
-static GInputStream *
-webkit_soup_request_data_send (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupRequestData *data = WEBKIT_SOUP_REQUEST_DATA (request);
- SoupURI *uri = webkit_soup_request_get_uri (request);
- GInputStream *memstream;
- const char *comma, *semi, *start, *end;
- gboolean base64 = FALSE;
-
- gchar *uristr = soup_uri_to_string (uri, FALSE);
- comma = strchr (uristr, ',');
- if (comma && comma != uristr) {
- /* Deal with MIME type / params */
- semi = memchr (uristr, ';', comma - uristr);
- end = semi ? semi : comma;
-
- if (semi && !g_ascii_strncasecmp (semi, ";base64", MAX ((size_t) (comma - semi), strlen (";base64"))))
- base64 = TRUE;
-
- if (end != uristr)
- if (base64)
- data->priv->content_type = g_strndup (uristr, end - uristr);
- else
- data->priv->content_type =
- webkit_soup_request_uri_decoded_copy (uristr, end - uristr);
- }
-
- memstream = g_memory_input_stream_new ();
-
- start = comma ? comma + 1 : uristr;
-
- if (*start) {
- guchar *buf;
-
- if (base64) {
- int inlen, state = 0;
- guint save = 0;
-
- inlen = strlen (start);
- buf = g_malloc0 (inlen * 3 / 4 + 3);
- data->priv->content_length =
- g_base64_decode_step (start, inlen, buf,
- &state, &save);
- if (state != 0) {
- g_free (buf);
- goto fail;
- }
- } else {
- /* Cannot use g_uri_unescape_string nor
- soup_uri_decode because we don't want to
- fail for things like "%3E%%3C" -> ">%<" */
- buf = (guchar *)webkit_soup_request_uri_decoded_copy (start, strlen (start));
- if (!buf)
- goto fail;
- data->priv->content_length = strlen ((char *)buf);
- }
-
- g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (memstream),
- buf, data->priv->content_length,
- g_free);
- }
- g_free (uristr);
-
- return memstream;
-
- fail:
- g_free (uristr);
- g_set_error (error, WEBKIT_SOUP_ERROR, WEBKIT_SOUP_ERROR_BAD_URI,
- _ ("Unable to decode URI: %s"), start);
- g_object_unref (memstream);
- return NULL;
-}
-
-static goffset
-webkit_soup_request_data_get_content_length (WebKitSoupRequest *request)
-{
- WebKitSoupRequestData *data = WEBKIT_SOUP_REQUEST_DATA (request);
-
- return data->priv->content_length;
-}
-
-static const char *
-webkit_soup_request_data_get_content_type (WebKitSoupRequest *request)
-{
- WebKitSoupRequestData *data = WEBKIT_SOUP_REQUEST_DATA (request);
-
- return data->priv->content_type;
-}
-
-static void
-webkit_soup_request_data_class_init (WebKitSoupRequestDataClass *request_data_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (request_data_class);
- WebKitSoupRequestClass *request_class =
- WEBKIT_SOUP_REQUEST_CLASS (request_data_class);
-
- g_type_class_add_private (request_data_class, sizeof (WebKitSoupRequestDataPrivate));
-
- object_class->finalize = webkit_soup_request_data_finalize;
-
- request_class->check_uri = webkit_soup_request_data_check_uri;
- request_class->send = webkit_soup_request_data_send;
- request_class->get_content_length = webkit_soup_request_data_get_content_length;
- request_class->get_content_type = webkit_soup_request_data_get_content_type;
-}
diff --git a/Source/WebCore/platform/network/soup/cache/soup-request-data.h b/Source/WebCore/platform/network/soup/cache/soup-request-data.h
deleted file mode 100644
index c9631a4..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-request-data.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2010 Igalia, S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef WEBKIT_SOUP_REQUEST_DATA_H
-#define WEBKIT_SOUP_REQUEST_DATA_H 1
-
-#include "soup-request.h"
-
-G_BEGIN_DECLS
-
-#define WEBKIT_TYPE_SOUP_REQUEST_DATA (webkit_soup_request_data_get_type ())
-#define WEBKIT_SOUP_REQUEST_DATA(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), WEBKIT_TYPE_SOUP_REQUEST_DATA, WebKitSoupRequestData))
-#define WEBKIT_SOUP_REQUEST_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_SOUP_REQUEST_DATA, WebKitSoupRequestDataClass))
-#define WEBKIT_IS_SOUP_REQUEST_DATA(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), WEBKIT_TYPE_SOUP_REQUEST_DATA))
-#define WEBKIT_IS_SOUP_REQUEST_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEBKIT_TYPE_SOUP_REQUEST_DATA))
-#define WEBKIT_SOUP_REQUEST_DATA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WEBKIT_TYPE_SOUP_REQUEST_DATA, WebKitSoupRequestDataClass))
-
-typedef struct _WebKitSoupRequestDataPrivate WebKitSoupRequestDataPrivate;
-
-typedef struct {
- WebKitSoupRequest parent;
-
- WebKitSoupRequestDataPrivate *priv;
-} WebKitSoupRequestData;
-
-typedef struct {
- WebKitSoupRequestClass parent;
-} WebKitSoupRequestDataClass;
-
-GType webkit_soup_request_data_get_type (void);
-
-G_END_DECLS
-
-#endif /* WEBKIT_SOUP_REQUEST_DATA_H */
diff --git a/Source/WebCore/platform/network/soup/cache/soup-request-file.c b/Source/WebCore/platform/network/soup/cache/soup-request-file.c
deleted file mode 100644
index 24ccb10..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-request-file.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-request-file.c: file: URI request object
- *
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2010 Igalia, S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "soup-request-file.h"
-#include "soup-directory-input-stream.h"
-#include "soup-requester.h"
-#include <glib/gi18n.h>
-
-G_DEFINE_TYPE (WebKitSoupRequestFile, webkit_soup_request_file, WEBKIT_TYPE_SOUP_REQUEST)
-
-struct _WebKitSoupRequestFilePrivate {
- GFile *gfile;
-
- char *mime_type;
- goffset size;
-};
-
-GFile *
-webkit_soup_request_file_get_file (WebKitSoupRequestFile *file)
-{
- return g_object_ref (file->priv->gfile);
-}
-
-static void
-webkit_soup_request_file_init (WebKitSoupRequestFile *file)
-{
- file->priv = G_TYPE_INSTANCE_GET_PRIVATE (file, WEBKIT_TYPE_SOUP_REQUEST_FILE, WebKitSoupRequestFilePrivate);
-
- file->priv->size = -1;
-}
-
-static void
-webkit_soup_request_file_finalize (GObject *object)
-{
- WebKitSoupRequestFile *file = WEBKIT_SOUP_REQUEST_FILE (object);
-
- if (file->priv->gfile)
- g_object_unref (file->priv->gfile);
- g_free (file->priv->mime_type);
-
- G_OBJECT_CLASS (webkit_soup_request_file_parent_class)->finalize (object);
-}
-
-static gboolean
-webkit_soup_request_file_check_uri (WebKitSoupRequest *request,
- SoupURI *uri,
- GError **error)
-{
- /* "file:/foo" is not valid */
- if (!uri->host)
- return FALSE;
-
- /* but it must be "file:///..." or "file://localhost/..." */
- if (uri->scheme == SOUP_URI_SCHEME_FILE &&
- *uri->host &&
- g_ascii_strcasecmp (uri->host, "localhost") != 0)
- return FALSE;
-
- return TRUE;
-}
-
-static void
-webkit_soup_request_file_ftp_main_loop_quit (GObject *object,
- GAsyncResult *result,
- gpointer loop)
-{
- g_main_loop_quit (loop);
-}
-
-/* This is a somewhat hacky way to get FTP to almost work. The proper way to
- * get FTP to _really_ work involves hacking GIO to have APIs to handle
- * canoncial URLs.
- */
-static GFile *
-webkit_soup_request_file_ensure_file_ftp (SoupURI *uri,
- GCancellable *cancellable,
- GError **error)
-{
- SoupURI *host;
- char *s;
- GFile *file, *result;
- GMount *mount;
-
- host = soup_uri_copy_host (uri);
- s = soup_uri_to_string (host, FALSE);
- file = g_file_new_for_uri (s);
- soup_uri_free (host);
- g_free (s);
-
- mount = g_file_find_enclosing_mount (file, cancellable, error);
- if (mount == NULL && g_file_supports_thread_contexts (file)) {
- GMainContext *context = g_main_context_new ();
- GMainLoop *loop = g_main_loop_new (context, FALSE);
-
- g_clear_error (error);
- g_main_context_push_thread_default (context);
- g_file_mount_enclosing_volume (file,
- G_MOUNT_MOUNT_NONE,
- NULL, /* FIXME! */
- cancellable,
- webkit_soup_request_file_ftp_main_loop_quit,
- loop);
- g_main_loop_run (loop);
- g_main_context_pop_thread_default (context);
- g_main_loop_unref (loop);
- g_main_context_unref (context);
- mount = g_file_find_enclosing_mount (file, cancellable, error);
- }
- if (mount == NULL)
- return NULL;
- g_object_unref (file);
-
- file = g_mount_get_default_location (mount);
- g_object_unref (mount);
-
- s = g_strdup (uri->path);
- if (strchr (s, ';'))
- *strchr (s, ';') = 0;
-
- result = g_file_resolve_relative_path (file, s);
- g_free (s);
- g_object_unref (file);
-
- return result;
-}
-
-static gboolean
-webkit_soup_request_file_ensure_file (WebKitSoupRequestFile *file,
- GCancellable *cancellable,
- GError **error)
-{
- SoupURI *uri;
-
- if (file->priv->gfile)
- return TRUE;
-
- uri = webkit_soup_request_get_uri (WEBKIT_SOUP_REQUEST (file));
- if (uri->scheme == SOUP_URI_SCHEME_FILE) {
- /* We cannot use soup_uri_decode as it incorrectly
- * returns NULL for incorrectly encoded URIs (that
- * could be valid filenames). This will be hopefully
- * shipped in libsoup 2.32.1 but we want to land this
- * first. TODO: replace uri_decoded_copy by
- * soup_uri_decode when the required libsoup version
- * is bumped out to 2.32.1
- */
- gchar *decoded_uri = webkit_soup_request_uri_decoded_copy (uri->path, strlen (uri->path));
-
- if (decoded_uri) {
- /* Do not use new_for_uri() as the decoded URI
- * could not be a valid URI
- */
- file->priv->gfile = g_file_new_for_path (decoded_uri);
- g_free (decoded_uri);
- }
-
- return TRUE;
- } else if (uri->scheme == SOUP_URI_SCHEME_FTP) {
- file->priv->gfile = webkit_soup_request_file_ensure_file_ftp (uri,
- cancellable,
- error);
- return file->priv->gfile != NULL;
- }
-
- g_set_error (error, WEBKIT_SOUP_ERROR, WEBKIT_SOUP_ERROR_UNSUPPORTED_URI_SCHEME,
- _ ("Unsupported URI scheme '%s'"), uri->scheme);
- return FALSE;
-}
-
-static GInputStream *
-webkit_soup_request_file_send (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupRequestFile *file = WEBKIT_SOUP_REQUEST_FILE (request);
- GInputStream *stream;
- GError *my_error = NULL;
-
- if (!webkit_soup_request_file_ensure_file (file, cancellable, error))
- return NULL;
-
- stream = G_INPUT_STREAM (g_file_read (file->priv->gfile,
- cancellable, &my_error));
- if (stream == NULL) {
- if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY)) {
- GFileEnumerator *enumerator;
- g_clear_error (&my_error);
- enumerator = g_file_enumerate_children (file->priv->gfile,
- "*",
- G_FILE_QUERY_INFO_NONE,
- cancellable,
- error);
- if (enumerator) {
- stream = webkit_soup_directory_input_stream_new (enumerator,
- webkit_soup_request_get_uri (request));
- g_object_unref (enumerator);
- file->priv->mime_type = g_strdup ("text/html");
- }
- } else {
- g_propagate_error (error, my_error);
- }
- } else {
- GFileInfo *info = g_file_query_info (file->priv->gfile,
- G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
- G_FILE_ATTRIBUTE_STANDARD_SIZE,
- 0, cancellable, NULL);
- if (info) {
- const char *content_type;
- file->priv->size = g_file_info_get_size (info);
- content_type = g_file_info_get_content_type (info);
-
- if (content_type)
- file->priv->mime_type = g_content_type_get_mime_type (content_type);
- g_object_unref (info);
- }
- }
-
- return stream;
-}
-
-static void
-webkit_soup_request_file_send_async_thread (GSimpleAsyncResult *res,
- GObject *object,
- GCancellable *cancellable)
-{
- GInputStream *stream;
- WebKitSoupRequest *request;
- GError *error = NULL;
-
- request = WEBKIT_SOUP_REQUEST (object);
-
- stream = webkit_soup_request_file_send (request, cancellable, &error);
-
- if (stream == NULL) {
- g_simple_async_result_set_from_error (res, error);
- g_error_free (error);
- } else {
- g_simple_async_result_set_op_res_gpointer (res, stream, g_object_unref);
- }
-}
-
-static void
-webkit_soup_request_file_send_async (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSimpleAsyncResult *res;
-
- res = g_simple_async_result_new (G_OBJECT (request), callback, user_data, webkit_soup_request_file_send_async);
-
- g_simple_async_result_run_in_thread (res, webkit_soup_request_file_send_async_thread, G_PRIORITY_DEFAULT, cancellable);
- g_object_unref (res);
-}
-
-static GInputStream *
-webkit_soup_request_file_send_finish (WebKitSoupRequest *request,
- GAsyncResult *result,
- GError **error)
-{
- GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
-
- g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == webkit_soup_request_file_send_async);
-
- if (g_simple_async_result_propagate_error (simple, error))
- return NULL;
-
- return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
-}
-
-static goffset
-webkit_soup_request_file_get_content_length (WebKitSoupRequest *request)
-{
- WebKitSoupRequestFile *file = WEBKIT_SOUP_REQUEST_FILE (request);
-
- return file->priv->size;
-}
-
-static const char *
-webkit_soup_request_file_get_content_type (WebKitSoupRequest *request)
-{
- WebKitSoupRequestFile *file = WEBKIT_SOUP_REQUEST_FILE (request);
-
- if (!file->priv->mime_type)
- return "application/octet-stream";
-
- return file->priv->mime_type;
-}
-
-static void
-webkit_soup_request_file_class_init (WebKitSoupRequestFileClass *request_file_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (request_file_class);
- WebKitSoupRequestClass *request_class =
- WEBKIT_SOUP_REQUEST_CLASS (request_file_class);
-
- g_type_class_add_private (request_file_class, sizeof (WebKitSoupRequestFilePrivate));
-
- object_class->finalize = webkit_soup_request_file_finalize;
-
- request_class->check_uri = webkit_soup_request_file_check_uri;
- request_class->send = webkit_soup_request_file_send;
- request_class->send_async = webkit_soup_request_file_send_async;
- request_class->send_finish = webkit_soup_request_file_send_finish;
- request_class->get_content_length = webkit_soup_request_file_get_content_length;
- request_class->get_content_type = webkit_soup_request_file_get_content_type;
-}
diff --git a/Source/WebCore/platform/network/soup/cache/soup-request-file.h b/Source/WebCore/platform/network/soup/cache/soup-request-file.h
deleted file mode 100644
index 459e82a..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-request-file.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2010 Igalia, S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef WEBKIT_SOUP_REQUEST_FILE_H
-#define WEBKIT_SOUP_REQUEST_FILE_H 1
-
-#include "soup-request.h"
-
-G_BEGIN_DECLS
-
-#define WEBKIT_TYPE_SOUP_REQUEST_FILE (webkit_soup_request_file_get_type ())
-#define WEBKIT_SOUP_REQUEST_FILE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), WEBKIT_TYPE_SOUP_REQUEST_FILE, WebKitSoupRequestFile))
-#define WEBKIT_SOUP_REQUEST_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_SOUP_REQUEST_FILE, WebKitSoupRequestFileClass))
-#define WEBKIT_IS_SOUP_REQUEST_FILE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), WEBKIT_TYPE_SOUP_REQUEST_FILE))
-#define WEBKIT_IS_SOUP_REQUEST_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEBKIT_TYPE_SOUP_REQUEST_FILE))
-#define WEBKIT_SOUP_REQUEST_FILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WEBKIT_TYPE_SOUP_REQUEST_FILE, WebKitSoupRequestFileClass))
-
-typedef struct _WebKitSoupRequestFilePrivate WebKitSoupRequestFilePrivate;
-
-typedef struct {
- WebKitSoupRequest parent;
-
- WebKitSoupRequestFilePrivate *priv;
-} WebKitSoupRequestFile;
-
-typedef struct {
- WebKitSoupRequestClass parent;
-} WebKitSoupRequestFileClass;
-
-GType webkit_soup_request_file_get_type (void);
-
-GFile *webkit_soup_request_file_get_file (WebKitSoupRequestFile *file);
-
-G_END_DECLS
-
-#endif /* WEBKIT_SOUP_REQUEST_FILE_H */
diff --git a/Source/WebCore/platform/network/soup/cache/soup-request-http.c b/Source/WebCore/platform/network/soup/cache/soup-request-http.c
deleted file mode 100644
index 777fd72..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-request-http.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-request-http.c: http: URI request object
- *
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2010 Igalia, S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib/gi18n.h>
-
-#include "soup-cache.h"
-#include "soup-cache-private.h"
-#include "soup-http-input-stream.h"
-#include "soup-request-http.h"
-
-G_DEFINE_TYPE (WebKitSoupRequestHTTP, webkit_soup_request_http, WEBKIT_TYPE_SOUP_REQUEST)
-
-struct _WebKitSoupRequestHTTPPrivate {
- SoupMessage *msg;
-};
-
-/**
- * webkit_soup_request_http_get_message:
- * @http: a #WebKitSoupRequestHTTP object
- *
- * Gets a new reference to the #SoupMessage associated to this SoupRequest
- *
- * Returns: a new reference to the #SoupMessage
- **/
-SoupMessage *
-webkit_soup_request_http_get_message (WebKitSoupRequestHTTP *http)
-{
- g_return_val_if_fail (WEBKIT_IS_SOUP_REQUEST_HTTP (http), NULL);
-
- return g_object_ref (http->priv->msg);
-}
-
-static void
-webkit_soup_request_http_init (WebKitSoupRequestHTTP *http)
-{
- http->priv = G_TYPE_INSTANCE_GET_PRIVATE (http, WEBKIT_TYPE_SOUP_REQUEST_HTTP, WebKitSoupRequestHTTPPrivate);
-}
-
-static gboolean
-webkit_soup_request_http_check_uri (WebKitSoupRequest *request,
- SoupURI *uri,
- GError **error)
-{
- WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (request);
-
- if (!SOUP_URI_VALID_FOR_HTTP (uri))
- return FALSE;
-
- http->priv->msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri);
- return TRUE;
-}
-
-static void
-webkit_soup_request_http_finalize (GObject *object)
-{
- WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (object);
-
- if (http->priv->msg)
- g_object_unref (http->priv->msg);
-
- G_OBJECT_CLASS (webkit_soup_request_http_parent_class)->finalize (object);
-}
-
-static GInputStream *
-webkit_soup_request_http_send (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupHTTPInputStream *httpstream;
- WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (request);
-
- httpstream = webkit_soup_http_input_stream_new (webkit_soup_request_get_session (request), http->priv->msg);
- if (!webkit_soup_http_input_stream_send (httpstream, cancellable, error)) {
- g_object_unref (httpstream);
- return NULL;
- }
- return (GInputStream *)httpstream;
-}
-
-
-static void
-sent_async (GObject *source, GAsyncResult *result, gpointer user_data)
-{
- WebKitSoupHTTPInputStream *httpstream = WEBKIT_SOUP_HTTP_INPUT_STREAM (source);
- GSimpleAsyncResult *simple = user_data;
- GError *error = NULL;
-
- if (webkit_soup_http_input_stream_send_finish (httpstream, result, &error)) {
- g_simple_async_result_set_op_res_gpointer (simple, httpstream, g_object_unref);
- } else {
- g_simple_async_result_set_from_error (simple, error);
- g_error_free (error);
- g_object_unref (httpstream);
- }
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
-}
-
-
-typedef struct {
- WebKitSoupRequestHTTP *req;
- SoupMessage *original;
- GCancellable *cancellable;
- GAsyncReadyCallback callback;
- gpointer user_data;
-} ConditionalHelper;
-
-
-static void
-conditional_get_ready_cb (SoupSession *session, SoupMessage *msg, gpointer user_data)
-{
- ConditionalHelper *helper = (ConditionalHelper *)user_data;
- GSimpleAsyncResult *simple;
- WebKitSoupHTTPInputStream *httpstream;
-
- simple = g_simple_async_result_new (G_OBJECT (helper->req),
- helper->callback, helper->user_data,
- conditional_get_ready_cb);
-
- if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) {
- WebKitSoupCache *cache = (WebKitSoupCache *)soup_session_get_feature (session, WEBKIT_TYPE_SOUP_CACHE);
-
- httpstream = (WebKitSoupHTTPInputStream *)webkit_soup_cache_send_response (cache, msg);
- if (httpstream) {
- const gchar *content_type;
-
- g_simple_async_result_set_op_res_gpointer (simple, httpstream, g_object_unref);
-
- soup_message_got_headers (helper->original);
-
- /* FIXME: Uncomment this when this becomes part of libsoup
- * if (!soup_message_disables_feature(helper->original, SOUP_TYPE_CONTENT_SNIFFER)) {
- * const gchar *content_type = soup_message_headers_get_content_type (msg->response_headers, NULL);
- * soup_message_content_sniffed (helper->original, content_type, NULL);
- * }
- */
- content_type = soup_message_headers_get_content_type (msg->response_headers, NULL);
- soup_message_content_sniffed (helper->original, content_type, NULL);
-
- g_simple_async_result_complete (simple);
-
- soup_message_finished (helper->original);
-
- g_object_unref (simple);
- } else {
- /* Ask again for the resource, somehow the cache cannot locate it */
- httpstream = webkit_soup_http_input_stream_new (session, helper->original);
- webkit_soup_http_input_stream_send_async (httpstream, G_PRIORITY_DEFAULT,
- helper->cancellable, sent_async, simple);
- }
- } else {
- /* It is in the cache but it was modified remotely */
- httpstream = webkit_soup_http_input_stream_new (session, helper->original);
- webkit_soup_http_input_stream_send_async (httpstream, G_PRIORITY_DEFAULT,
- helper->cancellable, sent_async, simple);
- }
-
- g_object_unref (helper->req);
- g_object_unref (helper->original);
- g_slice_free (ConditionalHelper, helper);
-}
-
-typedef struct {
- WebKitSoupRequestHTTP *http;
- GAsyncReadyCallback callback;
- gpointer user_data;
- WebKitSoupHTTPInputStream *httpstream;
-} SendAsyncHelper;
-
-static void webkit_soup_request_http_send_async (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-
-static gboolean
-send_async_cb (gpointer data)
-{
- GSimpleAsyncResult *simple;
- SendAsyncHelper *helper = (SendAsyncHelper *)data;
- const gchar *content_type;
-
- simple = g_simple_async_result_new (G_OBJECT (helper->http),
- helper->callback, helper->user_data,
- webkit_soup_request_http_send_async);
- g_simple_async_result_set_op_res_gpointer (simple, helper->httpstream, g_object_unref);
-
- /* Update message status */
- soup_message_set_status (helper->http->priv->msg, SOUP_STATUS_OK);
-
- /* Issue signals */
- soup_message_got_headers (helper->http->priv->msg);
-
- /* FIXME: Uncomment this when this becomes part of libsoup
- * if (!soup_message_disables_feature(helper->http->priv->msg, SOUP_TYPE_CONTENT_SNIFFER)) {
- * const gchar *content_type = soup_message_headers_get_content_type (helper->http->priv->msg->response_headers, NULL);
- * soup_message_content_sniffed (helper->http->priv->msg, content_type, NULL);
- * }
- */
- content_type = soup_message_headers_get_content_type (helper->http->priv->msg->response_headers, NULL);
- soup_message_content_sniffed (helper->http->priv->msg, content_type, NULL);
-
- g_simple_async_result_complete (simple);
-
- soup_message_finished (helper->http->priv->msg);
-
- g_object_unref (simple);
-
- g_object_unref (helper->http);
- g_slice_free (SendAsyncHelper, helper);
-
- return FALSE;
-}
-
-static void
-webkit_soup_request_http_send_async (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (request);
- WebKitSoupHTTPInputStream *httpstream;
- GSimpleAsyncResult *simple;
- SoupSession *session;
- WebKitSoupCache *cache;
-
- session = webkit_soup_request_get_session (request);
- cache = (WebKitSoupCache *)soup_session_get_feature (session, WEBKIT_TYPE_SOUP_CACHE);
-
- if (cache) {
- WebKitSoupCacheResponse response;
-
- response = webkit_soup_cache_has_response (cache, http->priv->msg);
- if (response == WEBKIT_SOUP_CACHE_RESPONSE_FRESH) {
- WebKitSoupHTTPInputStream *httpstream;
-
- httpstream = (WebKitSoupHTTPInputStream *)
- webkit_soup_cache_send_response (cache, SOUP_MESSAGE (http->priv->msg));
-
- /* Cached resource file could have been deleted outside
- */
- if (httpstream) {
- /* Do return the stream asynchronously as in
- * the other cases. It's not enough to use
- * g_simple_async_result_complete_in_idle as
- * the signals must be also emitted
- * asynchronously
- */
- SendAsyncHelper *helper = g_slice_new (SendAsyncHelper);
- helper->http = g_object_ref (http);
- helper->callback = callback;
- helper->user_data = user_data;
- helper->httpstream = httpstream;
- g_timeout_add (0, send_async_cb, helper);
- return;
- }
- } else if (response == WEBKIT_SOUP_CACHE_RESPONSE_NEEDS_VALIDATION) {
- SoupMessage *conditional_msg;
- ConditionalHelper *helper;
-
- conditional_msg = webkit_soup_cache_generate_conditional_request (cache, http->priv->msg);
-
- helper = g_slice_new0 (ConditionalHelper);
- helper->req = g_object_ref (http);
- helper->original = g_object_ref (http->priv->msg);
- helper->cancellable = cancellable;
- helper->callback = callback;
- helper->user_data = user_data;
- soup_session_queue_message (session, conditional_msg,
- conditional_get_ready_cb,
- helper);
- return;
- }
- }
-
- simple = g_simple_async_result_new (G_OBJECT (http),
- callback, user_data,
- webkit_soup_request_http_send_async);
- httpstream = webkit_soup_http_input_stream_new (webkit_soup_request_get_session (request),
- http->priv->msg);
- webkit_soup_http_input_stream_send_async (httpstream, G_PRIORITY_DEFAULT,
- cancellable, sent_async, simple);
-}
-
-static GInputStream *
-webkit_soup_request_http_send_finish (WebKitSoupRequest *request,
- GAsyncResult *result,
- GError **error)
-{
- GSimpleAsyncResult *simple;
-
- g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (request), webkit_soup_request_http_send_async) || g_simple_async_result_is_valid (result, G_OBJECT (request), conditional_get_ready_cb), NULL);
-
- simple = G_SIMPLE_ASYNC_RESULT (result);
- if (g_simple_async_result_propagate_error (simple, error))
- return NULL;
- return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
-}
-
-static goffset
-webkit_soup_request_http_get_content_length (WebKitSoupRequest *request)
-{
- WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (request);
-
- return soup_message_headers_get_content_length (http->priv->msg->response_headers);
-}
-
-static const char *
-webkit_soup_request_http_get_content_type (WebKitSoupRequest *request)
-{
- WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (request);
-
- return soup_message_headers_get_content_type (http->priv->msg->response_headers, NULL);
-}
-
-static void
-webkit_soup_request_http_class_init (WebKitSoupRequestHTTPClass *request_http_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (request_http_class);
- WebKitSoupRequestClass *request_class =
- WEBKIT_SOUP_REQUEST_CLASS (request_http_class);
-
- g_type_class_add_private (request_http_class, sizeof (WebKitSoupRequestHTTPPrivate));
-
- object_class->finalize = webkit_soup_request_http_finalize;
-
- request_class->check_uri = webkit_soup_request_http_check_uri;
- request_class->send = webkit_soup_request_http_send;
- request_class->send_async = webkit_soup_request_http_send_async;
- request_class->send_finish = webkit_soup_request_http_send_finish;
- request_class->get_content_length = webkit_soup_request_http_get_content_length;
- request_class->get_content_type = webkit_soup_request_http_get_content_type;
-}
diff --git a/Source/WebCore/platform/network/soup/cache/soup-request-http.h b/Source/WebCore/platform/network/soup/cache/soup-request-http.h
deleted file mode 100644
index a06a821..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-request-http.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2010 Igalia, S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef WEBKIT_SOUP_REQUEST_HTTP_H
-#define WEBKIT_SOUP_REQUEST_HTTP_H 1
-
-#include "soup-request.h"
-
-G_BEGIN_DECLS
-
-#define WEBKIT_TYPE_SOUP_REQUEST_HTTP (webkit_soup_request_http_get_type ())
-#define WEBKIT_SOUP_REQUEST_HTTP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), WEBKIT_TYPE_SOUP_REQUEST_HTTP, WebKitSoupRequestHTTP))
-#define WEBKIT_SOUP_REQUEST_HTTP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_SOUP_REQUEST_HTTP, WebKitSoupRequestHTTPClass))
-#define WEBKIT_IS_SOUP_REQUEST_HTTP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), WEBKIT_TYPE_SOUP_REQUEST_HTTP))
-#define WEBKIT_IS_SOUP_REQUEST_HTTP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEBKIT_TYPE_SOUP_REQUEST_HTTP))
-#define WEBKIT_SOUP_REQUEST_HTTP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WEBKIT_TYPE_SOUP_REQUEST_HTTP, WebKitSoupRequestHTTPClass))
-
-typedef struct _WebKitSoupRequestHTTPPrivate WebKitSoupRequestHTTPPrivate;
-
-typedef struct {
- WebKitSoupRequest parent;
-
- WebKitSoupRequestHTTPPrivate *priv;
-} WebKitSoupRequestHTTP;
-
-typedef struct {
- WebKitSoupRequestClass parent;
-} WebKitSoupRequestHTTPClass;
-
-GType webkit_soup_request_http_get_type (void);
-
-SoupMessage *webkit_soup_request_http_get_message (WebKitSoupRequestHTTP *http);
-
-G_END_DECLS
-
-#endif /* WEBKIT_SOUP_REQUEST_HTTP_H */
diff --git a/Source/WebCore/platform/network/soup/cache/soup-request.c b/Source/WebCore/platform/network/soup/cache/soup-request.c
deleted file mode 100644
index 46b9f5a..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-request.c
+++ /dev/null
@@ -1,312 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-request.c: Protocol-independent streaming request interface
- *
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2010, Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib/gi18n.h>
-
-#include "soup-request.h"
-#include "soup-requester.h"
-
-/**
- * SECTION:soup-request
- * @short_description: Protocol-independent streaming request interface
- *
- * FIXME
- **/
-
-/**
- * WebKitSoupRequest:
- *
- * FIXME
- *
- * Since: 2.30
- **/
-
-static void webkit_soup_request_initable_interface_init (GInitableIface *initable_interface);
-
-G_DEFINE_TYPE_WITH_CODE (WebKitSoupRequest, webkit_soup_request, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
- webkit_soup_request_initable_interface_init))
-
-enum {
- PROP_0,
- PROP_URI,
- PROP_SESSION
-};
-
-struct _WebKitSoupRequestPrivate {
- SoupURI *uri;
- SoupSession *session;
-};
-
-static void
-webkit_soup_request_init (WebKitSoupRequest *request)
-{
- request->priv = G_TYPE_INSTANCE_GET_PRIVATE (request, WEBKIT_TYPE_SOUP_REQUEST, WebKitSoupRequestPrivate);
-}
-
-static void
-webkit_soup_request_finalize (GObject *object)
-{
- WebKitSoupRequest *request = WEBKIT_SOUP_REQUEST (object);
-
- if (request->priv->uri)
- soup_uri_free (request->priv->uri);
- if (request->priv->session)
- g_object_unref (request->priv->session);
-
- G_OBJECT_CLASS (webkit_soup_request_parent_class)->finalize (object);
-}
-
-static void
-webkit_soup_request_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- WebKitSoupRequest *request = WEBKIT_SOUP_REQUEST (object);
-
- switch (prop_id) {
- case PROP_URI:
- if (request->priv->uri)
- soup_uri_free (request->priv->uri);
- request->priv->uri = g_value_dup_boxed (value);
- break;
- case PROP_SESSION:
- if (request->priv->session)
- g_object_unref (request->priv->session);
- request->priv->session = g_value_dup_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-webkit_soup_request_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- WebKitSoupRequest *request = WEBKIT_SOUP_REQUEST (object);
-
- switch (prop_id) {
- case PROP_URI:
- g_value_set_boxed (value, request->priv->uri);
- break;
- case PROP_SESSION:
- g_value_set_object (value, request->priv->session);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static gboolean
-webkit_soup_request_initable_init (GInitable *initable,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupRequest *request = WEBKIT_SOUP_REQUEST (initable);
- gboolean ok;
-
- if (!request->priv->uri) {
- g_set_error (error, WEBKIT_SOUP_ERROR, WEBKIT_SOUP_ERROR_BAD_URI,
- _ ("No URI provided"));
- return FALSE;
- }
-
- ok = WEBKIT_SOUP_REQUEST_GET_CLASS (initable)->
- check_uri (request, request->priv->uri, error);
-
- if (!ok && error) {
- char *uri_string = soup_uri_to_string (request->priv->uri, FALSE);
- g_set_error (error, WEBKIT_SOUP_ERROR, WEBKIT_SOUP_ERROR_BAD_URI,
- _ ("Invalid '%s' URI: %s"),
- request->priv->uri->scheme,
- uri_string);
- g_free (uri_string);
- }
-
- return ok;
-}
-
-static gboolean
-webkit_soup_request_default_check_uri (WebKitSoupRequest *request,
- SoupURI *uri,
- GError **error)
-{
- return TRUE;
-}
-
-/* Default implementation: assume the sync implementation doesn't block */
-static void
-webkit_soup_request_default_send_async (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSimpleAsyncResult *simple;
-
- simple = g_simple_async_result_new (G_OBJECT (request),
- callback, user_data,
- webkit_soup_request_default_send_async);
- g_simple_async_result_complete_in_idle (simple);
- g_object_unref (simple);
-}
-
-static GInputStream *
-webkit_soup_request_default_send_finish (WebKitSoupRequest *request,
- GAsyncResult *result,
- GError **error)
-{
- g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (request), webkit_soup_request_default_send_async), NULL);
-
- return webkit_soup_request_send (request, NULL, error);
-}
-
-GInputStream *
-webkit_soup_request_send (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GError **error)
-{
- return WEBKIT_SOUP_REQUEST_GET_CLASS (request)->
- send (request, cancellable, error);
-}
-
-void
-webkit_soup_request_send_async (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- WEBKIT_SOUP_REQUEST_GET_CLASS (request)->
- send_async (request, cancellable, callback, user_data);
-}
-
-GInputStream *
-webkit_soup_request_send_finish (WebKitSoupRequest *request,
- GAsyncResult *result,
- GError **error)
-{
- return WEBKIT_SOUP_REQUEST_GET_CLASS (request)->
- send_finish (request, result, error);
-}
-
-static void
-webkit_soup_request_class_init (WebKitSoupRequestClass *request_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (request_class);
-
- g_type_class_add_private (request_class, sizeof (WebKitSoupRequestPrivate));
-
- request_class->check_uri = webkit_soup_request_default_check_uri;
- request_class->send_async = webkit_soup_request_default_send_async;
- request_class->send_finish = webkit_soup_request_default_send_finish;
-
- object_class->finalize = webkit_soup_request_finalize;
- object_class->set_property = webkit_soup_request_set_property;
- object_class->get_property = webkit_soup_request_get_property;
-
- g_object_class_install_property (
- object_class, PROP_URI,
- g_param_spec_boxed (WEBKIT_SOUP_REQUEST_URI,
- "URI",
- "The request URI",
- SOUP_TYPE_URI,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
- g_object_class_install_property (
- object_class, PROP_SESSION,
- g_param_spec_object (WEBKIT_SOUP_REQUEST_SESSION,
- "Session",
- "The request's session",
- SOUP_TYPE_SESSION,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-}
-
-static void
-webkit_soup_request_initable_interface_init (GInitableIface *initable_interface)
-{
- initable_interface->init = webkit_soup_request_initable_init;
-}
-
-SoupURI *
-webkit_soup_request_get_uri (WebKitSoupRequest *request)
-{
- return request->priv->uri;
-}
-
-SoupSession *
-webkit_soup_request_get_session (WebKitSoupRequest *request)
-{
- return request->priv->session;
-}
-
-goffset
-webkit_soup_request_get_content_length (WebKitSoupRequest *request)
-{
- return WEBKIT_SOUP_REQUEST_GET_CLASS (request)->get_content_length (request);
-}
-
-const char *
-webkit_soup_request_get_content_type (WebKitSoupRequest *request)
-{
- return WEBKIT_SOUP_REQUEST_GET_CLASS (request)->get_content_type (request);
-}
-
-#define XDIGIT(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - 'A' + 10)
-#define HEXCHAR(s) ((XDIGIT (s[1]) << 4) + XDIGIT (s[2]))
-
-/* Copy&pasted from libsoup's soup-uri.c after applying the patch in
- * https://bugzilla.gnome.org/show_bug.cgi?id=630540. We need this
- * instead of soup_uri_decode() as it incorrectly returns NULL for
- * incorrectly encoded URLs. TODO: remove this when required libsoup
- * version is bumped out to 2.32.1
- */
-gchar *
-webkit_soup_request_uri_decoded_copy (const char *part, int length)
-{
- unsigned char *s, *d;
- char *decoded = g_strndup (part, length);
-
- s = d = (unsigned char *)decoded;
- do {
- if (*s == '%') {
- if (!g_ascii_isxdigit (s[1]) ||
- !g_ascii_isxdigit (s[2])) {
- *d++ = *s;
- continue;
- }
- *d++ = HEXCHAR (s);
- s += 2;
- } else
- *d++ = *s;
- } while (*s++);
-
- return decoded;
-}
diff --git a/Source/WebCore/platform/network/soup/cache/soup-request.h b/Source/WebCore/platform/network/soup/cache/soup-request.h
deleted file mode 100644
index 837d8f4..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-request.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2010 Igalia, S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef WEBKIT_SOUP_REQUEST_H
-#define WEBKIT_SOUP_REQUEST_H 1
-
-#include <libsoup/soup.h>
-#include <gio/gio.h>
-
-G_BEGIN_DECLS
-
-#define WEBKIT_TYPE_SOUP_REQUEST (webkit_soup_request_get_type ())
-#define WEBKIT_SOUP_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WEBKIT_TYPE_SOUP_REQUEST, WebKitSoupRequest))
-#define WEBKIT_SOUP_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_SOUP_REQUEST, WebKitSoupRequestClass))
-#define WEBKIT_IS_SOUP_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEBKIT_TYPE_SOUP_REQUEST))
-#define WEBKIT_IS_SOUP_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEBKIT_TYPE_SOUP_REQUEST))
-#define WEBKIT_SOUP_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WEBKIT_TYPE_SOUP_REQUEST, WebKitSoupRequestClass))
-
-typedef struct _WebKitSoupRequest WebKitSoupRequest;
-typedef struct _WebKitSoupRequestPrivate WebKitSoupRequestPrivate;
-typedef struct _WebKitSoupRequestClass WebKitSoupRequestClass;
-
-struct _WebKitSoupRequest {
- GObject parent;
-
- WebKitSoupRequestPrivate *priv;
-};
-
-struct _WebKitSoupRequestClass {
- GObjectClass parent;
-
- gboolean (*check_uri)(WebKitSoupRequest *req_base,
- SoupURI *uri,
- GError **error);
-
- GInputStream * (*send)(WebKitSoupRequest *request,
- GCancellable *cancellable,
- GError **error);
- void (*send_async)(WebKitSoupRequest *request,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
- GInputStream * (*send_finish)(WebKitSoupRequest *request,
- GAsyncResult *result,
- GError **error);
-
- goffset (*get_content_length)(WebKitSoupRequest *request);
- const char * (*get_content_type)(WebKitSoupRequest *request);
-};
-
-GType webkit_soup_request_get_type (void);
-
-#define WEBKIT_SOUP_REQUEST_URI "uri"
-#define WEBKIT_SOUP_REQUEST_SESSION "session"
-
-GInputStream *webkit_soup_request_send (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GError **error);
-void webkit_soup_request_send_async (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-GInputStream *webkit_soup_request_send_finish (WebKitSoupRequest *request,
- GAsyncResult *result,
- GError **error);
-
-SoupURI *webkit_soup_request_get_uri (WebKitSoupRequest *request);
-SoupSession *webkit_soup_request_get_session (WebKitSoupRequest *request);
-
-goffset webkit_soup_request_get_content_length (WebKitSoupRequest *request);
-const char *webkit_soup_request_get_content_type (WebKitSoupRequest *request);
-
-/* Used by WebKitSoupRequestFile and WebKitSoupRequestData. Ideally
- * should be located in some util file but I'll place it here as it
- * will be removed with libsoup 2.32.1 that will ship fixed versions
- * of soup_uri_decode/normalize
- */
-gchar *webkit_soup_request_uri_decoded_copy (const char *part, int length);
-
-G_END_DECLS
-
-#endif /* WEBKIT_SOUP_REQUEST_H */
diff --git a/Source/WebCore/platform/network/soup/cache/soup-requester.c b/Source/WebCore/platform/network/soup/cache/soup-requester.c
deleted file mode 100644
index 4d8a860..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-requester.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-requester.c:
- *
- * Copyright (C) 2010, Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "soup-requester.h"
-
-#include "soup-request-data.h"
-#include "soup-request-file.h"
-#include "soup-request-http.h"
-#include <glib/gi18n.h>
-#include <libsoup/soup.h>
-
-struct _WebKitSoupRequesterPrivate {
- GHashTable *request_types;
-};
-
-#define WEBKIT_SOUP_REQUESTER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), WEBKIT_TYPE_SOUP_REQUESTER, WebKitSoupRequesterPrivate))
-
-G_DEFINE_TYPE (WebKitSoupRequester, webkit_soup_requester, G_TYPE_OBJECT)
-
-static void webkit_soup_requester_init (WebKitSoupRequester *requester)
-{
- requester->priv = WEBKIT_SOUP_REQUESTER_GET_PRIVATE (requester);
-
- requester->priv->request_types = 0;
-}
-
-static void finalize (GObject *object)
-{
- WebKitSoupRequester *requester = WEBKIT_SOUP_REQUESTER (object);
-
- if (requester->priv->request_types)
- g_hash_table_destroy (requester->priv->request_types);
-
- G_OBJECT_CLASS (webkit_soup_requester_parent_class)->finalize (object);
-}
-
-static void webkit_soup_requester_class_init (WebKitSoupRequesterClass *requester_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (requester_class);
-
- g_type_class_add_private (requester_class, sizeof (WebKitSoupRequesterPrivate));
-
- /* virtual method override */
- object_class->finalize = finalize;
-}
-
-static void init_request_types (WebKitSoupRequesterPrivate *priv)
-{
- if (priv->request_types)
- return;
-
- priv->request_types = g_hash_table_new_full (soup_str_case_hash,
- soup_str_case_equal,
- g_free, 0);
- g_hash_table_insert (priv->request_types, g_strdup ("file"),
- GSIZE_TO_POINTER (WEBKIT_TYPE_SOUP_REQUEST_FILE));
- g_hash_table_insert (priv->request_types, g_strdup ("data"),
- GSIZE_TO_POINTER (WEBKIT_TYPE_SOUP_REQUEST_DATA));
- g_hash_table_insert (priv->request_types, g_strdup ("http"),
- GSIZE_TO_POINTER (WEBKIT_TYPE_SOUP_REQUEST_HTTP));
- g_hash_table_insert (priv->request_types, g_strdup ("https"),
- GSIZE_TO_POINTER (WEBKIT_TYPE_SOUP_REQUEST_HTTP));
- g_hash_table_insert (priv->request_types, g_strdup ("ftp"),
- GSIZE_TO_POINTER (WEBKIT_TYPE_SOUP_REQUEST_FILE));
-}
-
-WebKitSoupRequester *webkit_soup_requester_new (void)
-{
- return (WebKitSoupRequester *)g_object_new (WEBKIT_TYPE_SOUP_REQUESTER, NULL);
-}
-
-WebKitSoupRequest *webkit_soup_requester_request (WebKitSoupRequester *requester, const char *uriString, SoupSession *session, GError **error)
-{
- SoupURI *uri = NULL;
- WebKitSoupRequest *req;
-
- uri = soup_uri_new (uriString);
- if (!uri) {
- g_set_error (error, WEBKIT_SOUP_ERROR, WEBKIT_SOUP_ERROR_BAD_URI,
- _ ("Could not parse URI '%s'"), uriString);
- return 0;
- }
-
- req = webkit_soup_requester_request_uri (requester, uri, session, error);
- soup_uri_free (uri);
- return req;
-}
-
-WebKitSoupRequest *webkit_soup_requester_request_uri (WebKitSoupRequester *requester, SoupURI *uri, SoupSession *session, GError **error)
-{
- GType requestType;
-
- g_return_val_if_fail (WEBKIT_IS_SOUP_REQUESTER (requester), 0);
-
- init_request_types (requester->priv);
- requestType = (GType)GPOINTER_TO_SIZE (g_hash_table_lookup (requester->priv->request_types, uri->scheme));
- if (!requestType) {
- g_set_error (error, WEBKIT_SOUP_ERROR, WEBKIT_SOUP_ERROR_UNSUPPORTED_URI_SCHEME,
- _ ("Unsupported URI scheme '%s'"), uri->scheme);
- return 0;
- }
-
- if (g_type_is_a (requestType, G_TYPE_INITABLE)) {
- return (WebKitSoupRequest *)g_initable_new (requestType, 0, error,
- "uri", uri,
- "session", session,
- NULL);
- } else {
- return (WebKitSoupRequest *)g_object_new (requestType,
- "uri", uri,
- "session", session,
- NULL);
- }
-}
-
-/* RFC 2396, 3.1 */
-static gboolean
-soup_scheme_is_valid (const char *scheme)
-{
- if (scheme == NULL ||
- !g_ascii_isalpha (*scheme))
- return FALSE;
-
- scheme++;
- while (*scheme) {
- if (!g_ascii_isalpha (*scheme) &&
- !g_ascii_isdigit (*scheme) &&
- *scheme != '+' &&
- *scheme != '-' &&
- *scheme != '.')
- return FALSE;
- scheme++;
- }
- return TRUE;
-}
-
-void
-webkit_soup_requester_add_protocol (WebKitSoupRequester *requester,
- const char *scheme,
- GType request_type)
-{
- g_return_if_fail (WEBKIT_IS_SOUP_REQUESTER (requester));
- g_return_if_fail (soup_scheme_is_valid (scheme));
-
- init_request_types (requester->priv);
- g_hash_table_insert (requester->priv->request_types, g_strdup (scheme),
- GSIZE_TO_POINTER (request_type));
-}
-
-void
-webkit_soup_requester_remove_protocol (WebKitSoupRequester *requester,
- const char *scheme)
-{
- g_return_if_fail (WEBKIT_IS_SOUP_REQUESTER (requester));
- g_return_if_fail (soup_scheme_is_valid (scheme));
-
- init_request_types (requester->priv);
- g_hash_table_remove (requester->priv->request_types, scheme);
-}
-
-GQuark
-webkit_soup_error_quark (void)
-{
- static GQuark error;
- if (!error)
- error = g_quark_from_static_string ("webkit_soup_error_quark");
- return error;
-}
diff --git a/Source/WebCore/platform/network/soup/cache/soup-requester.h b/Source/WebCore/platform/network/soup/cache/soup-requester.h
deleted file mode 100644
index 71ff103..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-requester.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2010 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef WEBKIT_SOUP_REQUESTER_H
-#define WEBKIT_SOUP_REQUESTER_H 1
-
-#include "soup-request.h"
-#include <libsoup/soup.h>
-
-G_BEGIN_DECLS
-
-#define WEBKIT_TYPE_SOUP_REQUESTER (webkit_soup_requester_get_type ())
-#define WEBKIT_SOUP_REQUESTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WEBKIT_TYPE_SOUP_REQUESTER, WebKitSoupRequester))
-#define WEBKIT_SOUP_REQUESTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_SOUP_REQUESTER, WebKitSoupRequesterClass))
-#define WEBKIT_IS_SOUP_REQUESTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEBKIT_TYPE_SOUP_REQUESTER))
-#define WEBKIT_IS_SOUP_REQUESTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), WEBKIT_TYPE_SOUP_REQUESTER))
-#define WEBKIT_SOUP_REQUESTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WEBKIT_TYPE_SOUP_REQUESTER, WebKitSoupRequesterClass))
-
-#define WEBKIT_SOUP_ERROR webkit_soup_error_quark ()
-
-typedef enum {
- WEBKIT_SOUP_ERROR_BAD_URI,
- WEBKIT_SOUP_ERROR_UNSUPPORTED_URI_SCHEME
-} WebKitSoupError;
-
-typedef struct _WebKitSoupRequester WebKitSoupRequester;
-typedef struct _WebKitSoupRequesterPrivate WebKitSoupRequesterPrivate;
-
-struct _WebKitSoupRequester {
- GObject parent;
-
- WebKitSoupRequesterPrivate *priv;
-};
-
-typedef struct {
- GObjectClass parent_class;
-} WebKitSoupRequesterClass;
-
-GType webkit_soup_requester_get_type (void);
-
-WebKitSoupRequester *webkit_soup_requester_new (void);
-
-GQuark webkit_soup_error_quark (void);
-
-WebKitSoupRequest *webkit_soup_requester_request (WebKitSoupRequester *requester,
- const char *uriString,
- SoupSession *session,
- GError **error);
-
-WebKitSoupRequest *webkit_soup_requester_request_uri (WebKitSoupRequester *requester,
- SoupURI *uri,
- SoupSession *session,
- GError **error);
-
-void webkit_soup_requester_add_protocol (WebKitSoupRequester *requester,
- const char *scheme,
- GType request_type);
-
-void webkit_soup_requester_remove_protocol (WebKitSoupRequester *requester,
- const char *scheme);
-
-G_END_DECLS
-
-#endif /* WEBKIT_SOUP_REQUESTER_H */
diff --git a/Source/WebCore/platform/network/soup/cache/webkit/soup-cache-private.h b/Source/WebCore/platform/network/soup/cache/webkit/soup-cache-private.h
deleted file mode 100644
index 8af8de2..0000000
--- a/Source/WebCore/platform/network/soup/cache/webkit/soup-cache-private.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-cache-private.h:
- *
- * Copyright (C) 2010 Igalia, S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef WEBKIT_SOUP_CACHE_PRIVATE_H
-#define WEBKIT_SOUP_CACHE_PRIVATE_H 1
-
-#include "soup-cache.h"
-#include <libsoup/soup-message.h>
-
-G_BEGIN_DECLS
-
-WebKitSoupCacheResponse webkit_soup_cache_has_response (WebKitSoupCache *cache,
- SoupMessage *msg);
-GInputStream *webkit_soup_cache_send_response (WebKitSoupCache *cache,
- SoupMessage *msg);
-WebKitSoupCacheability webkit_soup_cache_get_cacheability (WebKitSoupCache *cache,
- SoupMessage *msg);
-SoupMessage *webkit_soup_cache_generate_conditional_request (WebKitSoupCache *cache,
- SoupMessage *original);
-
-G_END_DECLS
-
-#endif /* WEBKIT_SOUP_CACHE_PRIVATE_H */
diff --git a/Source/WebCore/platform/network/soup/cache/webkit/soup-cache.c b/Source/WebCore/platform/network/soup/cache/webkit/soup-cache.c
deleted file mode 100644
index b96428d..0000000
--- a/Source/WebCore/platform/network/soup/cache/webkit/soup-cache.c
+++ /dev/null
@@ -1,1677 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-cache.c
- *
- * Copyright (C) 2009, 2010 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* TODO:
- * - Need to hook the feature in the sync SoupSession.
- * - Need more tests.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "soup-cache.h"
-#include "soup-cache-private.h"
-#include <libsoup/soup.h>
-#include <gio/gio.h>
-#include <stdlib.h>
-
-static SoupSessionFeatureInterface *webkit_soup_cache_default_feature_interface;
-static void webkit_soup_cache_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data);
-
-#define DEFAULT_MAX_SIZE 50 * 1024 * 1024
-#define MAX_ENTRY_DATA_PERCENTAGE 10 /* Percentage of the total size
- of the cache that can be
- filled by a single entry */
-
-typedef struct _WebKitSoupCacheEntry {
- char *key;
- char *filename;
- guint freshness_lifetime;
- gboolean must_revalidate;
- GString *data;
- gsize pos;
- gsize length;
- time_t corrected_initial_age;
- time_t response_time;
- gboolean writing;
- gboolean dirty;
- gboolean got_body;
- gboolean being_validated;
- SoupMessageHeaders *headers;
- GOutputStream *stream;
- GError *error;
- guint hits;
- GCancellable *cancellable;
-} WebKitSoupCacheEntry;
-
-struct _WebKitSoupCachePrivate {
- char *cache_dir;
- GHashTable *cache;
- guint n_pending;
- SoupSession *session;
- WebKitSoupCacheType cache_type;
- guint size;
- guint max_size;
- guint max_entry_data_size; /* Computed value. Here for performance reasons */
- GList *lru_start;
-};
-
-typedef struct {
- WebKitSoupCache *cache;
- WebKitSoupCacheEntry *entry;
- SoupMessage *msg;
- gulong got_chunk_handler;
- gulong got_body_handler;
- gulong restarted_handler;
-} WebKitSoupCacheWritingFixture;
-
-enum {
- PROP_0,
- PROP_CACHE_DIR,
- PROP_CACHE_TYPE
-};
-
-#define WEBKIT_SOUP_CACHE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), WEBKIT_TYPE_SOUP_CACHE, WebKitSoupCachePrivate))
-
-G_DEFINE_TYPE_WITH_CODE (WebKitSoupCache, webkit_soup_cache, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE,
- webkit_soup_cache_session_feature_init))
-
-static gboolean webkit_soup_cache_entry_remove (WebKitSoupCache *cache, WebKitSoupCacheEntry *entry);
-static void make_room_for_new_entry (WebKitSoupCache *cache, guint length_to_add);
-static gboolean cache_accepts_entries_of_size (WebKitSoupCache *cache, guint length_to_add);
-
-static WebKitSoupCacheability
-get_cacheability (WebKitSoupCache *cache, SoupMessage *msg)
-{
- WebKitSoupCacheability cacheability;
- const char *cache_control;
-
- /* 1. The request method must be cacheable */
- if (msg->method == SOUP_METHOD_GET)
- cacheability = WEBKIT_SOUP_CACHE_CACHEABLE;
- else if (msg->method == SOUP_METHOD_HEAD ||
- msg->method == SOUP_METHOD_TRACE ||
- msg->method == SOUP_METHOD_CONNECT)
- return WEBKIT_SOUP_CACHE_UNCACHEABLE;
- else
- return (WEBKIT_SOUP_CACHE_UNCACHEABLE | WEBKIT_SOUP_CACHE_INVALIDATES);
-
- cache_control = soup_message_headers_get (msg->response_headers, "Cache-Control");
- if (cache_control) {
- GHashTable *hash;
- WebKitSoupCachePrivate *priv = WEBKIT_SOUP_CACHE_GET_PRIVATE (cache);
-
- hash = soup_header_parse_param_list (cache_control);
-
- /* Shared caches MUST NOT store private resources */
- if (priv->cache_type == WEBKIT_SOUP_CACHE_SHARED) {
- if (g_hash_table_lookup_extended (hash, "private", NULL, NULL)) {
- soup_header_free_param_list (hash);
- return WEBKIT_SOUP_CACHE_UNCACHEABLE;
- }
- }
-
- /* 2. The 'no-store' cache directive does not appear in the
- * headers
- */
- if (g_hash_table_lookup_extended (hash, "no-store", NULL, NULL)) {
- soup_header_free_param_list (hash);
- return WEBKIT_SOUP_CACHE_UNCACHEABLE;
- }
-
- /* This does not appear in section 2.1, but I think it makes
- * sense to check it too?
- */
- if (g_hash_table_lookup_extended (hash, "no-cache", NULL, NULL)) {
- soup_header_free_param_list (hash);
- return WEBKIT_SOUP_CACHE_UNCACHEABLE;
- }
-
- soup_header_free_param_list (hash);
- }
-
- switch (msg->status_code) {
- case SOUP_STATUS_PARTIAL_CONTENT:
- /* We don't cache partial responses, but they only
- * invalidate cached full responses if the headers
- * don't match.
- */
- cacheability = WEBKIT_SOUP_CACHE_UNCACHEABLE;
- break;
-
- case SOUP_STATUS_NOT_MODIFIED:
- /* A 304 response validates an existing cache entry */
- cacheability = WEBKIT_SOUP_CACHE_VALIDATES;
- break;
-
- case SOUP_STATUS_MULTIPLE_CHOICES:
- case SOUP_STATUS_MOVED_PERMANENTLY:
- case SOUP_STATUS_GONE:
- /* FIXME: cacheable unless indicated otherwise */
- cacheability = WEBKIT_SOUP_CACHE_UNCACHEABLE;
- break;
-
- case SOUP_STATUS_FOUND:
- case SOUP_STATUS_TEMPORARY_REDIRECT:
- /* FIXME: cacheable if explicitly indicated */
- cacheability = WEBKIT_SOUP_CACHE_UNCACHEABLE;
- break;
-
- case SOUP_STATUS_SEE_OTHER:
- case SOUP_STATUS_FORBIDDEN:
- case SOUP_STATUS_NOT_FOUND:
- case SOUP_STATUS_METHOD_NOT_ALLOWED:
- return (WEBKIT_SOUP_CACHE_UNCACHEABLE | WEBKIT_SOUP_CACHE_INVALIDATES);
-
- default:
- /* Any 5xx status or any 4xx status not handled above
- * is uncacheable but doesn't break the cache.
- */
- if ((msg->status_code >= SOUP_STATUS_BAD_REQUEST &&
- msg->status_code <= SOUP_STATUS_FAILED_DEPENDENCY) ||
- msg->status_code >= SOUP_STATUS_INTERNAL_SERVER_ERROR)
- return WEBKIT_SOUP_CACHE_UNCACHEABLE;
-
- /* An unrecognized 2xx, 3xx, or 4xx response breaks
- * the cache.
- */
- if ((msg->status_code > SOUP_STATUS_PARTIAL_CONTENT &&
- msg->status_code < SOUP_STATUS_MULTIPLE_CHOICES) ||
- (msg->status_code > SOUP_STATUS_TEMPORARY_REDIRECT &&
- msg->status_code < SOUP_STATUS_INTERNAL_SERVER_ERROR))
- return (WEBKIT_SOUP_CACHE_UNCACHEABLE | WEBKIT_SOUP_CACHE_INVALIDATES);
- break;
- }
-
- return cacheability;
-}
-
-static void
-webkit_soup_cache_entry_free (WebKitSoupCacheEntry *entry, gboolean purge)
-{
- if (purge) {
- GFile *file = g_file_new_for_path (entry->filename);
- g_file_delete (file, NULL, NULL);
- g_object_unref (file);
- }
-
- g_free (entry->filename);
- entry->filename = NULL;
- g_free (entry->key);
- entry->key = NULL;
-
- if (entry->headers) {
- soup_message_headers_free (entry->headers);
- entry->headers = NULL;
- }
-
- if (entry->data) {
- g_string_free (entry->data, TRUE);
- entry->data = NULL;
- }
- if (entry->error) {
- g_error_free (entry->error);
- entry->error = NULL;
- }
- if (entry->cancellable) {
- g_object_unref (entry->cancellable);
- entry->cancellable = NULL;
- }
-
- g_slice_free (WebKitSoupCacheEntry, entry);
-}
-
-static void
-copy_headers (const char *name, const char *value, SoupMessageHeaders *headers)
-{
- soup_message_headers_append (headers, name, value);
-}
-
-static void
-update_headers (const char *name, const char *value, SoupMessageHeaders *headers)
-{
- if (soup_message_headers_get (headers, name))
- soup_message_headers_replace (headers, name, value);
- else
- soup_message_headers_append (headers, name, value);
-}
-
-static guint
-webkit_soup_cache_entry_get_current_age (WebKitSoupCacheEntry *entry)
-{
- time_t now = time (NULL);
- time_t resident_time;
-
- resident_time = now - entry->response_time;
- return entry->corrected_initial_age + resident_time;
-}
-
-static gboolean
-webkit_soup_cache_entry_is_fresh_enough (WebKitSoupCacheEntry *entry, gint min_fresh)
-{
- guint limit = (min_fresh == -1) ? webkit_soup_cache_entry_get_current_age (entry) : (guint) min_fresh;
- return entry->freshness_lifetime > limit;
-}
-
-static char *
-soup_message_get_cache_key (SoupMessage *msg)
-{
- SoupURI *uri = soup_message_get_uri (msg);
- return soup_uri_to_string (uri, FALSE);
-}
-
-static void
-webkit_soup_cache_entry_set_freshness (WebKitSoupCacheEntry *entry, SoupMessage *msg, WebKitSoupCache *cache)
-{
- const char *cache_control;
- const char *expires, *date, *last_modified;
-
- cache_control = soup_message_headers_get (entry->headers, "Cache-Control");
- if (cache_control) {
- const char *max_age, *s_maxage;
- gint64 freshness_lifetime = 0;
- GHashTable *hash;
- WebKitSoupCachePrivate *priv = WEBKIT_SOUP_CACHE_GET_PRIVATE (cache);
-
- hash = soup_header_parse_param_list (cache_control);
-
- /* Should we re-validate the entry when it goes stale */
- entry->must_revalidate = g_hash_table_lookup_extended (hash, "must-revalidate", NULL, NULL);
-
- /* Section 2.3.1 */
- if (priv->cache_type == WEBKIT_SOUP_CACHE_SHARED) {
- s_maxage = g_hash_table_lookup (hash, "s-maxage");
- if (s_maxage) {
- freshness_lifetime = g_ascii_strtoll (s_maxage, NULL, 10);
- if (freshness_lifetime) {
- /* Implies proxy-revalidate. TODO: is it true? */
- entry->must_revalidate = TRUE;
- soup_header_free_param_list (hash);
- return;
- }
- }
- }
-
- /* If 'max-age' cache directive is present, use that */
- max_age = g_hash_table_lookup (hash, "max-age");
- if (max_age)
- freshness_lifetime = g_ascii_strtoll (max_age, NULL, 10);
-
- if (freshness_lifetime) {
- entry->freshness_lifetime = (guint)MIN (freshness_lifetime, G_MAXUINT32);
- soup_header_free_param_list (hash);
- return;
- }
-
- soup_header_free_param_list (hash);
- }
-
- /* If the 'Expires' response header is present, use its value
- * minus the value of the 'Date' response header
- */
- expires = soup_message_headers_get (entry->headers, "Expires");
- date = soup_message_headers_get (entry->headers, "Date");
- if (expires && date) {
- SoupDate *expires_d, *date_d;
- time_t expires_t, date_t;
-
- expires_d = soup_date_new_from_string (expires);
- if (expires_d) {
- date_d = soup_date_new_from_string (date);
-
- expires_t = soup_date_to_time_t (expires_d);
- date_t = soup_date_to_time_t (date_d);
-
- soup_date_free (expires_d);
- soup_date_free (date_d);
-
- if (expires_t && date_t) {
- entry->freshness_lifetime = (guint)MAX (expires_t - date_t, 0);
- return;
- }
- } else {
- /* If Expires is not a valid date we should
- treat it as already expired, see section
- 3.3 */
- entry->freshness_lifetime = 0;
- return;
- }
- }
-
- /* Otherwise an heuristic may be used */
-
- /* Heuristics MUST NOT be used with these status codes
- (section 2.3.1.1) */
- if (msg->status_code != SOUP_STATUS_OK &&
- msg->status_code != SOUP_STATUS_NON_AUTHORITATIVE &&
- msg->status_code != SOUP_STATUS_PARTIAL_CONTENT &&
- msg->status_code != SOUP_STATUS_MULTIPLE_CHOICES &&
- msg->status_code != SOUP_STATUS_MOVED_PERMANENTLY &&
- msg->status_code != SOUP_STATUS_GONE)
- goto expire;
-
- /* TODO: attach warning 113 if response's current_age is more
- than 24h (section 2.3.1.1) when using heuristics */
-
- /* Last-Modified based heuristic */
- last_modified = soup_message_headers_get (entry->headers, "Last-Modified");
- if (last_modified) {
- SoupDate *soup_date;
- time_t now, last_modified_t;
-
- soup_date = soup_date_new_from_string (last_modified);
- last_modified_t = soup_date_to_time_t (soup_date);
- now = time (NULL);
-
-#define HEURISTIC_FACTOR 0.1 /* From Section 2.3.1.1 */
-
- entry->freshness_lifetime = MAX (0, (now - last_modified_t) * HEURISTIC_FACTOR);
- soup_date_free (soup_date);
- }
-
- return;
-
- expire:
- /* If all else fails, make the entry expire immediately */
- entry->freshness_lifetime = 0;
-}
-
-static WebKitSoupCacheEntry *
-webkit_soup_cache_entry_new (WebKitSoupCache *cache, SoupMessage *msg, time_t request_time, time_t response_time)
-{
- WebKitSoupCacheEntry *entry;
- SoupMessageHeaders *headers;
- const char *date;
- char *md5;
-
- entry = g_slice_new0 (WebKitSoupCacheEntry);
- entry->dirty = FALSE;
- entry->writing = FALSE;
- entry->got_body = FALSE;
- entry->being_validated = FALSE;
- entry->data = g_string_new (NULL);
- entry->pos = 0;
- entry->error = NULL;
-
- /* key & filename */
- entry->key = soup_message_get_cache_key (msg);
- md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, entry->key, -1);
- entry->filename = g_build_filename (cache->priv->cache_dir, md5, NULL);
- g_free (md5);
-
- /* Headers */
- headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE);
- soup_message_headers_foreach (msg->response_headers,
- (SoupMessageHeadersForeachFunc)copy_headers,
- headers);
- entry->headers = headers;
-
- /* LRU list */
- entry->hits = 0;
-
- /* Section 2.3.1, Freshness Lifetime */
- webkit_soup_cache_entry_set_freshness (entry, msg, cache);
-
- /* Section 2.3.2, Calculating Age */
- date = soup_message_headers_get (entry->headers, "Date");
-
- if (date) {
- SoupDate *soup_date;
- const char *age;
- time_t date_value, apparent_age, corrected_received_age, response_delay, age_value = 0;
-
- soup_date = soup_date_new_from_string (date);
- date_value = soup_date_to_time_t (soup_date);
- soup_date_free (soup_date);
-
- age = soup_message_headers_get (entry->headers, "Age");
- if (age)
- age_value = g_ascii_strtoll (age, NULL, 10);
-
- entry->response_time = response_time;
- apparent_age = MAX (0, entry->response_time - date_value);
- corrected_received_age = MAX (apparent_age, age_value);
- response_delay = entry->response_time - request_time;
- entry->corrected_initial_age = corrected_received_age + response_delay;
- } else {
- /* Is this correct ? */
- entry->corrected_initial_age = time (NULL);
- }
-
- return entry;
-}
-
-static void
-webkit_soup_cache_writing_fixture_free (WebKitSoupCacheWritingFixture *fixture)
-{
- /* Free fixture. And disconnect signals, we don't want to
- listen to more SoupMessage events as we're finished with
- this resource */
- if (g_signal_handler_is_connected (fixture->msg, fixture->got_chunk_handler))
- g_signal_handler_disconnect (fixture->msg, fixture->got_chunk_handler);
- if (g_signal_handler_is_connected (fixture->msg, fixture->got_body_handler))
- g_signal_handler_disconnect (fixture->msg, fixture->got_body_handler);
- if (g_signal_handler_is_connected (fixture->msg, fixture->restarted_handler))
- g_signal_handler_disconnect (fixture->msg, fixture->restarted_handler);
- g_object_unref (fixture->msg);
- g_object_unref (fixture->cache);
- g_slice_free (WebKitSoupCacheWritingFixture, fixture);
-}
-
-static void
-close_ready_cb (GObject *source, GAsyncResult *result, WebKitSoupCacheWritingFixture *fixture)
-{
- WebKitSoupCacheEntry *entry = fixture->entry;
- WebKitSoupCache *cache = fixture->cache;
- GOutputStream *stream = G_OUTPUT_STREAM (source);
- goffset content_length;
-
- g_warn_if_fail (entry->error == NULL);
-
- /* FIXME: what do we do on error ? */
-
- if (stream) {
- g_output_stream_close_finish (stream, result, NULL);
- g_object_unref (stream);
- }
- entry->stream = NULL;
-
- content_length = soup_message_headers_get_content_length (entry->headers);
-
- /* If the process was cancelled, then delete the entry from
- the cache. Do it also if the size of a chunked resource is
- too much for the cache */
- if (g_cancellable_is_cancelled (entry->cancellable)) {
- entry->dirty = FALSE;
- webkit_soup_cache_entry_remove (cache, entry);
- webkit_soup_cache_entry_free (entry, TRUE);
- entry = NULL;
- } else if ((soup_message_headers_get_encoding (entry->headers) == SOUP_ENCODING_CHUNKED) ||
- entry->length != (gsize) content_length) {
- /** Two options here:
- *
- * 1. "chunked" data, entry was temporarily added to
- * cache (as content-length is 0) and now that we have
- * the actual size we have to evaluate if we want it
- * in the cache or not
- *
- * 2. Content-Length has a different value than actual
- * length, means that the content was encoded for
- * transmission (typically compressed) and thus we
- * have to substract the content-length value that was
- * added to the cache and add the unencoded length
- **/
- gint length_to_add = entry->length - content_length;
-
- /* Make room in cache if needed */
- if (cache_accepts_entries_of_size (cache, length_to_add)) {
- make_room_for_new_entry (cache, length_to_add);
-
- cache->priv->size += length_to_add;
- } else {
- entry->dirty = FALSE;
- webkit_soup_cache_entry_remove (cache, entry);
- webkit_soup_cache_entry_free (entry, TRUE);
- entry = NULL;
- }
- }
-
- if (entry) {
- /* Get rid of the GString in memory for the resource now */
- if (entry->data) {
- g_string_free (entry->data, TRUE);
- entry->data = NULL;
- }
-
- entry->dirty = FALSE;
- entry->writing = FALSE;
- entry->got_body = FALSE;
- entry->pos = 0;
-
- g_object_unref (entry->cancellable);
- entry->cancellable = NULL;
- }
-
- cache->priv->n_pending--;
-
- /* Frees */
- webkit_soup_cache_writing_fixture_free (fixture);
-}
-
-static void
-write_ready_cb (GObject *source, GAsyncResult *result, WebKitSoupCacheWritingFixture *fixture)
-{
- GOutputStream *stream = G_OUTPUT_STREAM (source);
- GError *error = NULL;
- gssize write_size;
- WebKitSoupCacheEntry *entry = fixture->entry;
-
- if (g_cancellable_is_cancelled (entry->cancellable)) {
- g_output_stream_close_async (stream,
- G_PRIORITY_LOW,
- entry->cancellable,
- (GAsyncReadyCallback)close_ready_cb,
- fixture);
- return;
- }
-
- write_size = g_output_stream_write_finish (stream, result, &error);
- if (write_size <= 0 || error) {
- if (error)
- entry->error = error;
- g_output_stream_close_async (stream,
- G_PRIORITY_LOW,
- entry->cancellable,
- (GAsyncReadyCallback)close_ready_cb,
- fixture);
- /* FIXME: We should completely stop caching the
- resource at this point */
- } else {
- entry->pos += write_size;
-
- /* Are we still writing and is there new data to write
- already ? */
- if (entry->data && entry->pos < entry->data->len) {
- g_output_stream_write_async (entry->stream,
- entry->data->str + entry->pos,
- entry->data->len - entry->pos,
- G_PRIORITY_LOW,
- entry->cancellable,
- (GAsyncReadyCallback)write_ready_cb,
- fixture);
- } else {
- entry->writing = FALSE;
-
- if (entry->got_body) {
- /* If we already received 'got-body'
- and we have written all the data,
- we can close the stream */
- g_output_stream_close_async (entry->stream,
- G_PRIORITY_LOW,
- entry->cancellable,
- (GAsyncReadyCallback)close_ready_cb,
- fixture);
- }
- }
- }
-}
-
-static void
-msg_got_chunk_cb (SoupMessage *msg, SoupBuffer *chunk, WebKitSoupCacheWritingFixture *fixture)
-{
- WebKitSoupCacheEntry *entry = fixture->entry;
-
- g_return_if_fail (chunk->data && chunk->length);
- g_return_if_fail (entry);
-
- /* Ignore this if the writing or appending was cancelled */
- if (!g_cancellable_is_cancelled (entry->cancellable)) {
- g_string_append_len (entry->data, chunk->data, chunk->length);
- entry->length = entry->data->len;
-
- if (!cache_accepts_entries_of_size (fixture->cache, entry->length)) {
- /* Quickly cancel the caching of the resource */
- g_cancellable_cancel (entry->cancellable);
- }
- }
-
- /* FIXME: remove the error check when we cancel the caching at
- the first write error */
- /* Only write if the entry stream is ready */
- if (entry->writing == FALSE && entry->error == NULL && entry->stream) {
- GString *data = entry->data;
- entry->writing = TRUE;
- g_output_stream_write_async (entry->stream,
- data->str + entry->pos,
- data->len - entry->pos,
- G_PRIORITY_LOW,
- entry->cancellable,
- (GAsyncReadyCallback)write_ready_cb,
- fixture);
- }
-}
-
-static void
-msg_got_body_cb (SoupMessage *msg, WebKitSoupCacheWritingFixture *fixture)
-{
- WebKitSoupCacheEntry *entry = fixture->entry;
- g_return_if_fail (entry);
-
- entry->got_body = TRUE;
-
- if (!entry->stream && entry->pos != entry->length)
- /* The stream is not ready to be written but we still
- have data to write, we'll write it when the stream
- is opened for writing */
- return;
-
-
- if (entry->pos != entry->length) {
- /* If we still have data to write, write it,
- write_ready_cb will close the stream */
- if (entry->writing == FALSE && entry->error == NULL && entry->stream) {
- g_output_stream_write_async (entry->stream,
- entry->data->str + entry->pos,
- entry->data->len - entry->pos,
- G_PRIORITY_LOW,
- entry->cancellable,
- (GAsyncReadyCallback)write_ready_cb,
- fixture);
- }
- return;
- }
-
- if (entry->stream && !entry->writing)
- g_output_stream_close_async (entry->stream,
- G_PRIORITY_LOW,
- entry->cancellable,
- (GAsyncReadyCallback)close_ready_cb,
- fixture);
-}
-
-static gboolean
-webkit_soup_cache_entry_remove (WebKitSoupCache *cache, WebKitSoupCacheEntry *entry)
-{
- GList *lru_item;
-
- /* if (entry->dirty && !g_cancellable_is_cancelled (entry->cancellable)) { */
- if (entry->dirty) {
- g_cancellable_cancel (entry->cancellable);
- return FALSE;
- }
-
- g_assert (!entry->dirty);
- g_assert (g_list_length (cache->priv->lru_start) == g_hash_table_size (cache->priv->cache));
-
- /* Remove from cache */
- if (!g_hash_table_remove (cache->priv->cache, entry->key))
- return FALSE;
-
- /* Remove from LRU */
- lru_item = g_list_find (cache->priv->lru_start, entry);
- cache->priv->lru_start = g_list_delete_link (cache->priv->lru_start, lru_item);
-
- /* Adjust cache size */
- cache->priv->size -= entry->length;
-
- g_assert (g_list_length (cache->priv->lru_start) == g_hash_table_size (cache->priv->cache));
-
- return TRUE;
-}
-
-static gint
-lru_compare_func (gconstpointer a, gconstpointer b)
-{
- WebKitSoupCacheEntry *entry_a = (WebKitSoupCacheEntry *)a;
- WebKitSoupCacheEntry *entry_b = (WebKitSoupCacheEntry *)b;
-
- /** The rationale of this sorting func is
- *
- * 1. sort by hits -> LRU algorithm, then
- *
- * 2. sort by freshness lifetime, we better discard first
- * entries that are close to expire
- *
- * 3. sort by size, replace first small size resources as they
- * are cheaper to download
- **/
-
- /* Sort by hits */
- if (entry_a->hits != entry_b->hits)
- return entry_a->hits - entry_b->hits;
-
- /* Sort by freshness_lifetime */
- if (entry_a->freshness_lifetime != entry_b->freshness_lifetime)
- return entry_a->freshness_lifetime - entry_b->freshness_lifetime;
-
- /* Sort by size */
- return entry_a->length - entry_b->length;
-}
-
-static gboolean
-cache_accepts_entries_of_size (WebKitSoupCache *cache, guint length_to_add)
-{
- /* We could add here some more heuristics. TODO: review how
- this is done by other HTTP caches */
-
- return length_to_add <= cache->priv->max_entry_data_size;
-}
-
-static void
-make_room_for_new_entry (WebKitSoupCache *cache, guint length_to_add)
-{
- GList *lru_entry = cache->priv->lru_start;
-
- /* Check that there is enough room for the new entry. This is
- an approximation as we're not working out the size of the
- cache file or the size of the headers for performance
- reasons. TODO: check if that would be really that expensive */
-
- while (lru_entry &&
- (length_to_add + cache->priv->size > cache->priv->max_size)) {
- WebKitSoupCacheEntry *old_entry = (WebKitSoupCacheEntry *)lru_entry->data;
-
- /* Discard entries. Once cancelled resources will be
- * freed in close_ready_cb
- */
- if (webkit_soup_cache_entry_remove (cache, old_entry)) {
- webkit_soup_cache_entry_free (old_entry, TRUE);
- lru_entry = cache->priv->lru_start;
- } else
- lru_entry = g_list_next (lru_entry);
- }
-}
-
-static gboolean
-webkit_soup_cache_entry_insert_by_key (WebKitSoupCache *cache,
- const char *key,
- WebKitSoupCacheEntry *entry,
- gboolean sort)
-{
- guint length_to_add = 0;
-
- if (soup_message_headers_get_encoding (entry->headers) != SOUP_ENCODING_CHUNKED)
- length_to_add = soup_message_headers_get_content_length (entry->headers);
-
- /* Check if we are going to store the resource depending on its size */
- if (length_to_add) {
- if (!cache_accepts_entries_of_size (cache, length_to_add))
- return FALSE;
-
- /* Make room for new entry if needed */
- make_room_for_new_entry (cache, length_to_add);
- }
-
- g_hash_table_insert (cache->priv->cache, g_strdup (key), entry);
-
- /* Compute new cache size */
- cache->priv->size += length_to_add;
-
- /* Update LRU */
- if (sort)
- cache->priv->lru_start = g_list_insert_sorted (cache->priv->lru_start, entry, lru_compare_func);
- else
- cache->priv->lru_start = g_list_prepend (cache->priv->lru_start, entry);
-
- g_assert (g_list_length (cache->priv->lru_start) == g_hash_table_size (cache->priv->cache));
-
- return TRUE;
-}
-
-static void
-msg_restarted_cb (SoupMessage *msg, WebKitSoupCacheEntry *entry)
-{
- /* FIXME: What should we do here exactly? */
-}
-
-static void
-append_to_ready_cb (GObject *source, GAsyncResult *result, WebKitSoupCacheWritingFixture *fixture)
-{
- GFile *file = (GFile *)source;
- GOutputStream *stream;
- WebKitSoupCacheEntry *entry = fixture->entry;
-
- stream = (GOutputStream *)g_file_append_to_finish (file, result, &entry->error);
-
- if (g_cancellable_is_cancelled (entry->cancellable) || entry->error) {
- fixture->cache->priv->n_pending--;
- entry->dirty = FALSE;
- webkit_soup_cache_entry_remove (fixture->cache, entry);
- webkit_soup_cache_entry_free (entry, TRUE);
- webkit_soup_cache_writing_fixture_free (fixture);
- return;
- }
-
- entry->stream = g_object_ref (stream);
- g_object_unref (file);
-
- /* If we already got all the data we have to initiate the
- writing here, since we won't get more 'got-chunk'
- signals */
- if (entry->got_body) {
- GString *data = entry->data;
-
- /* It could happen that reading the data from server
- was completed before this happens. In that case
- there is no data */
- if (data) {
- entry->writing = TRUE;
- g_output_stream_write_async (entry->stream,
- data->str + entry->pos,
- data->len - entry->pos,
- G_PRIORITY_LOW,
- entry->cancellable,
- (GAsyncReadyCallback)write_ready_cb,
- fixture);
- }
- }
-}
-
-typedef struct {
- time_t request_time;
- SoupSessionFeature *feature;
- gulong got_headers_handler;
-} RequestHelper;
-
-static void
-msg_got_headers_cb (SoupMessage *msg, gpointer user_data)
-{
- WebKitSoupCache *cache;
- WebKitSoupCacheability cacheable;
- RequestHelper *helper;
- time_t request_time, response_time;
-
- response_time = time (NULL);
-
- helper = (RequestHelper *)user_data;
- cache = WEBKIT_SOUP_CACHE (helper->feature);
- request_time = helper->request_time;
- g_signal_handlers_disconnect_by_func (msg, msg_got_headers_cb, user_data);
- g_slice_free (RequestHelper, helper);
-
- cacheable = webkit_soup_cache_get_cacheability (cache, msg);
-
- if (cacheable & WEBKIT_SOUP_CACHE_CACHEABLE) {
- WebKitSoupCacheEntry *entry;
- char *key;
- GFile *file;
- WebKitSoupCacheWritingFixture *fixture;
-
- /* Check if we are already caching this resource */
- key = soup_message_get_cache_key (msg);
- entry = g_hash_table_lookup (cache->priv->cache, key);
- g_free (key);
-
- if (entry && entry->dirty)
- return;
-
- /* Create a new entry, deleting any old one if present */
- if (entry) {
- webkit_soup_cache_entry_remove (cache, entry);
- webkit_soup_cache_entry_free (entry, TRUE);
- }
-
- entry = webkit_soup_cache_entry_new (cache, msg, request_time, response_time);
- entry->hits = 1;
-
- /* Do not continue if it can not be stored */
- if (!webkit_soup_cache_entry_insert_by_key (cache, (const gchar *)entry->key, entry, TRUE)) {
- webkit_soup_cache_entry_free (entry, TRUE);
- return;
- }
-
- fixture = g_slice_new0 (WebKitSoupCacheWritingFixture);
- fixture->cache = g_object_ref (cache);
- fixture->entry = entry;
- fixture->msg = g_object_ref (msg);
-
- /* We connect now to these signals and buffer the data
- if it comes before the file is ready for writing */
- fixture->got_chunk_handler =
- g_signal_connect (msg, "got-chunk", G_CALLBACK (msg_got_chunk_cb), fixture);
- fixture->got_body_handler =
- g_signal_connect (msg, "got-body", G_CALLBACK (msg_got_body_cb), fixture);
- fixture->restarted_handler =
- g_signal_connect (msg, "restarted", G_CALLBACK (msg_restarted_cb), entry);
-
- /* Prepare entry */
- file = g_file_new_for_path (entry->filename);
- cache->priv->n_pending++;
-
- entry->dirty = TRUE;
- entry->cancellable = g_cancellable_new ();
- g_file_append_to_async (file, 0,
- G_PRIORITY_LOW, entry->cancellable,
- (GAsyncReadyCallback)append_to_ready_cb,
- fixture);
- } else if (cacheable & WEBKIT_SOUP_CACHE_INVALIDATES) {
- char *key;
- WebKitSoupCacheEntry *entry;
-
- key = soup_message_get_cache_key (msg);
- entry = g_hash_table_lookup (cache->priv->cache, key);
- g_free (key);
-
- if (entry) {
- if (webkit_soup_cache_entry_remove (cache, entry))
- webkit_soup_cache_entry_free (entry, TRUE);
- }
- } else if (cacheable & WEBKIT_SOUP_CACHE_VALIDATES) {
- char *key;
- WebKitSoupCacheEntry *entry;
-
- key = soup_message_get_cache_key (msg);
- entry = g_hash_table_lookup (cache->priv->cache, key);
- g_free (key);
-
- /* It's possible to get a CACHE_VALIDATES with no
- * entry in the hash table. This could happen if for
- * example the soup client is the one creating the
- * conditional request.
- */
- if (entry) {
- entry->being_validated = FALSE;
-
- /* We update the headers of the existing cache item,
- plus its age */
- soup_message_headers_foreach (msg->response_headers,
- (SoupMessageHeadersForeachFunc)update_headers,
- entry->headers);
- webkit_soup_cache_entry_set_freshness (entry, msg, cache);
- }
- }
-}
-
-GInputStream *
-webkit_soup_cache_send_response (WebKitSoupCache *cache, SoupMessage *msg)
-{
- char *key;
- WebKitSoupCacheEntry *entry;
- char *current_age;
- GInputStream *stream = NULL;
- GFile *file;
-
- g_return_val_if_fail (WEBKIT_IS_SOUP_CACHE (cache), NULL);
- g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
-
- key = soup_message_get_cache_key (msg);
- entry = g_hash_table_lookup (cache->priv->cache, key);
- g_free (key);
- g_return_val_if_fail (entry, NULL);
-
- /* If we are told to send a response from cache any validation
- in course is over by now */
- entry->being_validated = FALSE;
-
- /* Headers */
- soup_message_headers_foreach (entry->headers,
- (SoupMessageHeadersForeachFunc)update_headers,
- msg->response_headers);
-
- /* Add 'Age' header with the current age */
- current_age = g_strdup_printf ("%d", webkit_soup_cache_entry_get_current_age (entry));
- soup_message_headers_replace (msg->response_headers,
- "Age",
- current_age);
- g_free (current_age);
-
- /* TODO: the original idea was to save reads, but current code
- assumes that a stream is always returned. Need to reach
- some agreement here. Also we have to handle the situation
- were the file was no longer there (for example files
- removed without notifying the cache */
- file = g_file_new_for_path (entry->filename);
- stream = (GInputStream *)g_file_read (file, NULL, NULL);
-
- return stream;
-}
-
-static void
-request_started (SoupSessionFeature *feature, SoupSession *session,
- SoupMessage *msg, SoupSocket *socket)
-{
- RequestHelper *helper = g_slice_new0 (RequestHelper);
- helper->request_time = time (NULL);
- helper->feature = feature;
- helper->got_headers_handler = g_signal_connect (msg, "got-headers",
- G_CALLBACK (msg_got_headers_cb),
- helper);
-}
-
-static void
-attach (SoupSessionFeature *feature, SoupSession *session)
-{
- WebKitSoupCache *cache = WEBKIT_SOUP_CACHE (feature);
- cache->priv->session = session;
-
- webkit_soup_cache_default_feature_interface->attach (feature, session);
-}
-
-static void
-webkit_soup_cache_session_feature_init (SoupSessionFeatureInterface *feature_interface,
- gpointer interface_data)
-{
- webkit_soup_cache_default_feature_interface =
- g_type_default_interface_peek (SOUP_TYPE_SESSION_FEATURE);
-
- feature_interface->attach = attach;
- feature_interface->request_started = request_started;
-}
-
-static void
-webkit_soup_cache_init (WebKitSoupCache *cache)
-{
- WebKitSoupCachePrivate *priv;
-
- priv = cache->priv = WEBKIT_SOUP_CACHE_GET_PRIVATE (cache);
-
- priv->cache = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- (GDestroyNotify)g_free,
- NULL);
-
- /* LRU */
- priv->lru_start = NULL;
-
- /* */
- priv->n_pending = 0;
-
- /* Cache size */
- priv->max_size = DEFAULT_MAX_SIZE;
- priv->max_entry_data_size = priv->max_size / MAX_ENTRY_DATA_PERCENTAGE;
- priv->size = 0;
-}
-
-static void
-remove_cache_item (gpointer data,
- gpointer user_data)
-{
- WebKitSoupCache *cache = (WebKitSoupCache *) user_data;
- WebKitSoupCacheEntry *entry = (WebKitSoupCacheEntry *) data;
-
- if (webkit_soup_cache_entry_remove (cache, entry))
- webkit_soup_cache_entry_free (entry, FALSE);
-}
-
-static void
-webkit_soup_cache_finalize (GObject *object)
-{
- WebKitSoupCachePrivate *priv;
- GList *entries;
-
- priv = WEBKIT_SOUP_CACHE (object)->priv;
-
- // Cannot use g_hash_table_foreach as callbacks must not modify the hash table
- entries = g_hash_table_get_values (priv->cache);
- g_list_foreach (entries, remove_cache_item, object);
- g_list_free (entries);
-
- g_hash_table_destroy (priv->cache);
- g_free (priv->cache_dir);
-
- g_list_free (priv->lru_start);
- priv->lru_start = NULL;
-
- G_OBJECT_CLASS (webkit_soup_cache_parent_class)->finalize (object);
-}
-
-static void
-webkit_soup_cache_set_property (GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec)
-{
- WebKitSoupCachePrivate *priv = WEBKIT_SOUP_CACHE (object)->priv;
-
- switch (prop_id) {
- case PROP_CACHE_DIR:
- priv->cache_dir = g_value_dup_string (value);
- /* Create directory if it does not exist (FIXME: should we?) */
- if (!g_file_test (priv->cache_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
- g_mkdir_with_parents (priv->cache_dir, 0700);
- break;
- case PROP_CACHE_TYPE:
- priv->cache_type = g_value_get_enum (value);
- /* TODO: clear private entries and issue a warning if moving to shared? */
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-webkit_soup_cache_get_property (GObject *object, guint prop_id,
- GValue *value, GParamSpec *pspec)
-{
- WebKitSoupCachePrivate *priv = WEBKIT_SOUP_CACHE (object)->priv;
-
- switch (prop_id) {
- case PROP_CACHE_DIR:
- g_value_set_string (value, priv->cache_dir);
- break;
- case PROP_CACHE_TYPE:
- g_value_set_enum (value, priv->cache_type);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-webkit_soup_cache_constructed (GObject *object)
-{
- WebKitSoupCachePrivate *priv;
-
- priv = WEBKIT_SOUP_CACHE (object)->priv;
-
- if (!priv->cache_dir) {
- /* Set a default cache dir, different for each user */
- priv->cache_dir = g_build_filename (g_get_user_cache_dir (),
- "httpcache",
- NULL);
- if (!g_file_test (priv->cache_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
- g_mkdir_with_parents (priv->cache_dir, 0700);
- }
-
- if (G_OBJECT_CLASS (webkit_soup_cache_parent_class)->constructed)
- G_OBJECT_CLASS (webkit_soup_cache_parent_class)->constructed (object);
-}
-
-#define WEBKIT_SOUP_CACHE_TYPE_TYPE (webkit_soup_cache_type_get_type ())
-static GType
-webkit_soup_cache_type_get_type (void)
-{
- static GType cache_type = 0;
-
- static const GEnumValue cache_types[] = {
- { WEBKIT_SOUP_CACHE_SINGLE_USER, "Single user cache", "user" },
- { WEBKIT_SOUP_CACHE_SHARED, "Shared cache", "shared" },
- { 0, NULL, NULL }
- };
-
- if (!cache_type) {
- cache_type = g_enum_register_static ("WebKitSoupCacheTypeType", cache_types);
- }
- return cache_type;
-}
-
-static void
-webkit_soup_cache_class_init (WebKitSoupCacheClass *cache_class)
-{
- GObjectClass *gobject_class = (GObjectClass *)cache_class;
-
- gobject_class->finalize = webkit_soup_cache_finalize;
- gobject_class->constructed = webkit_soup_cache_constructed;
- gobject_class->set_property = webkit_soup_cache_set_property;
- gobject_class->get_property = webkit_soup_cache_get_property;
-
- cache_class->get_cacheability = get_cacheability;
-
- g_object_class_install_property (gobject_class, PROP_CACHE_DIR,
- g_param_spec_string ("cache-dir",
- "Cache directory",
- "The directory to store the cache files",
- NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- g_object_class_install_property (gobject_class, PROP_CACHE_TYPE,
- g_param_spec_enum ("cache-type",
- "Cache type",
- "Whether the cache is private or shared",
- WEBKIT_SOUP_CACHE_TYPE_TYPE,
- WEBKIT_SOUP_CACHE_SINGLE_USER,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- g_type_class_add_private (cache_class, sizeof (WebKitSoupCachePrivate));
-}
-
-/**
- * webkit_soup_cache_new:
- * @cache_dir: the directory to store the cached data, or %NULL to use the default one
- * @cache_type: the #WebKitSoupCacheType of the cache
- *
- * Creates a new #WebKitSoupCache.
- *
- * Returns: a new #WebKitSoupCache
- *
- * Since: 2.28
- **/
-WebKitSoupCache *
-webkit_soup_cache_new (const char *cache_dir, WebKitSoupCacheType cache_type)
-{
- return g_object_new (WEBKIT_TYPE_SOUP_CACHE,
- "cache-dir", cache_dir,
- "cache-type", cache_type,
- NULL);
-}
-
-/**
- * webkit_soup_cache_has_response:
- * @cache: a #WebKitSoupCache
- * @msg: a #SoupMessage
- *
- * This function calculates whether the @cache object has a proper
- * response for the request @msg given the flags both in the request
- * and the cached reply and the time ellapsed since it was cached.
- *
- * Returns: whether or not the @cache has a valid response for @msg
- **/
-WebKitSoupCacheResponse
-webkit_soup_cache_has_response (WebKitSoupCache *cache, SoupMessage *msg)
-{
- char *key;
- WebKitSoupCacheEntry *entry;
- const char *cache_control;
- gpointer value;
- gboolean must_revalidate;
- int max_age, max_stale, min_fresh;
- GList *lru_item, *item;
-
- key = soup_message_get_cache_key (msg);
- entry = g_hash_table_lookup (cache->priv->cache, key);
- g_free (key);
-
- /* 1. The presented Request-URI and that of stored response
- * match
- */
- if (!entry)
- return WEBKIT_SOUP_CACHE_RESPONSE_STALE;
-
- /* Increase hit count. Take sorting into account */
- entry->hits++;
- lru_item = g_list_find (cache->priv->lru_start, entry);
- item = lru_item;
- while (item->next && lru_compare_func (item->data, item->next->data) > 0)
- item = g_list_next (item);
-
- if (item != lru_item) {
- cache->priv->lru_start = g_list_remove_link (cache->priv->lru_start, lru_item);
- item = g_list_insert_sorted (item, lru_item->data, lru_compare_func);
- g_list_free (lru_item);
- }
-
- if (entry->dirty || entry->being_validated)
- return WEBKIT_SOUP_CACHE_RESPONSE_STALE;
-
- /* 2. The request method associated with the stored response
- * allows it to be used for the presented request
- */
-
- /* In practice this means we only return our resource for GET,
- * cacheability for other methods is a TODO in the RFC
- * (TODO: although we could return the headers for HEAD
- * probably).
- */
- if (msg->method != SOUP_METHOD_GET)
- return WEBKIT_SOUP_CACHE_RESPONSE_STALE;
-
- /* 3. Selecting request-headers nominated by the stored
- * response (if any) match those presented.
- */
-
- /* TODO */
-
- /* 4. The request is a conditional request issued by the client.
- */
- if (soup_message_headers_get (msg->request_headers, "If-Modified-Since") ||
- soup_message_headers_get (msg->request_headers, "If-None-Match"))
- return WEBKIT_SOUP_CACHE_RESPONSE_STALE;
-
- /* 5. The presented request and stored response are free from
- * directives that would prevent its use.
- */
-
- must_revalidate = FALSE;
- max_age = max_stale = min_fresh = -1;
-
- cache_control = soup_message_headers_get (msg->request_headers, "Cache-Control");
- if (cache_control) {
- GHashTable *hash = soup_header_parse_param_list (cache_control);
-
- if (g_hash_table_lookup_extended (hash, "no-store", NULL, NULL)) {
- soup_header_free_param_list (hash);
- return WEBKIT_SOUP_CACHE_RESPONSE_STALE;
- }
-
- if (g_hash_table_lookup_extended (hash, "no-cache", NULL, NULL)) {
- entry->must_revalidate = TRUE;
- }
-
- if (g_hash_table_lookup_extended (hash, "max-age", NULL, &value)) {
- max_age = (int)MIN (g_ascii_strtoll (value, NULL, 10), G_MAXINT32);
- }
-
- /* max-stale can have no value set, we need to use _extended */
- if (g_hash_table_lookup_extended (hash, "max-stale", NULL, &value)) {
- if (value)
- max_stale = (int)MIN (g_ascii_strtoll (value, NULL, 10), G_MAXINT32);
- else
- max_stale = G_MAXINT32;
- }
-
- value = g_hash_table_lookup (hash, "min-fresh");
- if (value)
- min_fresh = (int)MIN (g_ascii_strtoll (value, NULL, 10), G_MAXINT32);
-
- soup_header_free_param_list (hash);
-
- if (max_age != -1) {
- guint current_age = webkit_soup_cache_entry_get_current_age (entry);
-
- /* If we are over max-age and max-stale is not
- set, do not use the value from the cache
- without validation */
- if ((guint) max_age <= current_age && max_stale == -1)
- return WEBKIT_SOUP_CACHE_RESPONSE_NEEDS_VALIDATION;
- }
- }
-
- /* 6. The stored response is either: fresh, allowed to be
- * served stale or succesfully validated
- */
- /* TODO consider also proxy-revalidate & s-maxage */
- if (entry->must_revalidate)
- return WEBKIT_SOUP_CACHE_RESPONSE_NEEDS_VALIDATION;
-
- if (!webkit_soup_cache_entry_is_fresh_enough (entry, min_fresh)) {
- /* Not fresh, can it be served stale? */
- if (max_stale != -1) {
- /* G_MAXINT32 means we accept any staleness */
- if (max_stale == G_MAXINT32)
- return WEBKIT_SOUP_CACHE_RESPONSE_FRESH;
-
- if ((webkit_soup_cache_entry_get_current_age (entry) - entry->freshness_lifetime) <= (guint) max_stale)
- return WEBKIT_SOUP_CACHE_RESPONSE_FRESH;
- }
-
- return WEBKIT_SOUP_CACHE_RESPONSE_NEEDS_VALIDATION;
- }
-
- return WEBKIT_SOUP_CACHE_RESPONSE_FRESH;
-}
-
-/**
- * webkit_soup_cache_get_cacheability:
- * @cache: a #WebKitSoupCache
- * @msg: a #SoupMessage
- *
- * Calculates whether the @msg can be cached or not.
- *
- * Returns: a #WebKitSoupCacheability value indicating whether the @msg can be cached or not.
- **/
-WebKitSoupCacheability
-webkit_soup_cache_get_cacheability (WebKitSoupCache *cache, SoupMessage *msg)
-{
- g_return_val_if_fail (WEBKIT_IS_SOUP_CACHE (cache), WEBKIT_SOUP_CACHE_UNCACHEABLE);
- g_return_val_if_fail (SOUP_IS_MESSAGE (msg), WEBKIT_SOUP_CACHE_UNCACHEABLE);
-
- return WEBKIT_SOUP_CACHE_GET_CLASS (cache)->get_cacheability (cache, msg);
-}
-
-static gboolean
-force_flush_timeout (gpointer data)
-{
- gboolean *forced = (gboolean *)data;
- *forced = TRUE;
-
- return FALSE;
-}
-
-/**
- * webkit_soup_cache_flush:
- * @cache: a #WebKitSoupCache
- * @session: the #SoupSession associated with the @cache
- *
- * This function will force all pending writes in the @cache to be
- * committed to disk. For doing so it will iterate the #GMainContext
- * associated with the @session (which can be the default one) as long
- * as needed.
- **/
-void
-webkit_soup_cache_flush (WebKitSoupCache *cache)
-{
- GMainContext *async_context;
- SoupSession *session;
- guint timeout_id;
- gboolean forced = FALSE;
-
- g_return_if_fail (WEBKIT_IS_SOUP_CACHE (cache));
-
- session = cache->priv->session;
- g_return_if_fail (SOUP_IS_SESSION (session));
- async_context = soup_session_get_async_context (session);
-
- /* We give cache 10 secs to finish */
- timeout_id = g_timeout_add (10000, force_flush_timeout, &forced);
-
- while (!forced && cache->priv->n_pending > 0)
- g_main_context_iteration (async_context, FALSE);
-
- if (!forced)
- g_source_remove (timeout_id);
- else
- g_warning ("Cache flush finished despite %d pending requests", cache->priv->n_pending);
-}
-
-static void
-clear_cache_item (gpointer data,
- gpointer user_data)
-{
- WebKitSoupCache *cache = (WebKitSoupCache *) user_data;
- WebKitSoupCacheEntry *entry = (WebKitSoupCacheEntry *) data;
-
- if (webkit_soup_cache_entry_remove (cache, entry))
- webkit_soup_cache_entry_free (entry, TRUE);
-}
-
-/**
- * webkit_soup_cache_clear:
- * @cache: a #WebKitSoupCache
- *
- * Will remove all entries in the @cache plus all the cache files
- * associated with them.
- **/
-void
-webkit_soup_cache_clear (WebKitSoupCache *cache)
-{
- GHashTable *hash;
- GList *entries;
-
- g_return_if_fail (WEBKIT_IS_SOUP_CACHE (cache));
-
- hash = cache->priv->cache;
- g_return_if_fail (hash);
-
- // Cannot use g_hash_table_foreach as callbacks must not modify the hash table
- entries = g_hash_table_get_values (hash);
- g_list_foreach (entries, clear_cache_item, cache);
- g_list_free (entries);
-}
-
-SoupMessage *
-webkit_soup_cache_generate_conditional_request (WebKitSoupCache *cache, SoupMessage *original)
-{
- SoupMessage *msg;
- SoupURI *uri;
- WebKitSoupCacheEntry *entry;
- char *key;
- const char *value;
-
- g_return_val_if_fail (WEBKIT_IS_SOUP_CACHE (cache), NULL);
- g_return_val_if_fail (SOUP_IS_MESSAGE (original), NULL);
-
- /* First copy the data we need from the original message */
- uri = soup_message_get_uri (original);
- msg = soup_message_new_from_uri (original->method, uri);
-
- soup_message_headers_foreach (original->request_headers,
- (SoupMessageHeadersForeachFunc)copy_headers,
- msg->request_headers);
-
- /* Now add the validator entries in the header from the cached
- data */
- key = soup_message_get_cache_key (original);
- entry = g_hash_table_lookup (cache->priv->cache, key);
- g_free (key);
-
- g_return_val_if_fail (entry, NULL);
-
- entry->being_validated = TRUE;
-
- value = soup_message_headers_get (entry->headers, "Last-Modified");
- if (value)
- soup_message_headers_append (msg->request_headers,
- "If-Modified-Since",
- value);
- value = soup_message_headers_get (entry->headers, "ETag");
- if (value)
- soup_message_headers_append (msg->request_headers,
- "If-None-Match",
- value);
- return msg;
-}
-
-#define WEBKIT_SOUP_CACHE_FILE "soup.cache"
-
-#define WEBKIT_SOUP_CACHE_HEADERS_FORMAT "{ss}"
-#define WEBKIT_SOUP_CACHE_PHEADERS_FORMAT "(ssbuuuuua" WEBKIT_SOUP_CACHE_HEADERS_FORMAT ")"
-#define WEBKIT_SOUP_CACHE_ENTRIES_FORMAT "a" WEBKIT_SOUP_CACHE_PHEADERS_FORMAT
-
-/* Basically the same format than above except that some strings are
- prepended with &. This way the GVariant returns a pointer to the
- data instead of duplicating the string */
-#define WEBKIT_SOUP_CACHE_DECODE_HEADERS_FORMAT "{&s&s}"
-
-static void
-pack_entry (gpointer data,
- gpointer user_data)
-{
- WebKitSoupCacheEntry *entry = (WebKitSoupCacheEntry *) data;
- SoupMessageHeadersIter iter;
- const gchar *header_key, *header_value;
- GVariantBuilder *headers_builder;
- GVariantBuilder *entries_builder = (GVariantBuilder *)user_data;
-
- /* Do not store non-consolidated entries */
- if (entry->dirty || entry->writing || !entry->key)
- return;
-
- /* Pack headers */
- headers_builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
- soup_message_headers_iter_init (&iter, entry->headers);
- while (soup_message_headers_iter_next (&iter, &header_key, &header_value)) {
- if (g_utf8_validate (header_value, -1, NULL))
- g_variant_builder_add (headers_builder, WEBKIT_SOUP_CACHE_HEADERS_FORMAT,
- header_key, header_value);
- }
-
- /* Entry data */
- g_variant_builder_add (entries_builder, WEBKIT_SOUP_CACHE_PHEADERS_FORMAT,
- entry->key, entry->filename, entry->must_revalidate,
- entry->freshness_lifetime, entry->corrected_initial_age,
- entry->response_time, entry->hits, entry->length, headers_builder);
-
- g_variant_builder_unref (headers_builder);
-}
-
-void
-webkit_soup_cache_dump (WebKitSoupCache *cache)
-{
- WebKitSoupCachePrivate *priv = WEBKIT_SOUP_CACHE_GET_PRIVATE (cache);
- gchar *filename;
- GVariantBuilder *entries_builder;
- GVariant *cache_variant;
-
- if (!g_list_length (cache->priv->lru_start))
- return;
-
- /* Create the builder and iterate over all entries */
- entries_builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
- g_list_foreach (cache->priv->lru_start, pack_entry, entries_builder);
-
- /* Serialize and dump */
- cache_variant = g_variant_new (WEBKIT_SOUP_CACHE_ENTRIES_FORMAT, entries_builder);
- g_variant_builder_unref (entries_builder);
-
- filename = g_build_filename (priv->cache_dir, WEBKIT_SOUP_CACHE_FILE, NULL);
- g_file_set_contents (filename, (const gchar *)g_variant_get_data (cache_variant),
- g_variant_get_size (cache_variant), NULL);
- g_free (filename);
- g_variant_unref (cache_variant);
-}
-
-void
-webkit_soup_cache_load (WebKitSoupCache *cache)
-{
- gchar *filename = NULL, *contents = NULL;
- GVariant *cache_variant;
- GVariantIter *entries_iter, *headers_iter;
- GVariantType *variant_format;
- gsize length;
- WebKitSoupCacheEntry *entry;
- WebKitSoupCachePrivate *priv = cache->priv;
-
- filename = g_build_filename (priv->cache_dir, WEBKIT_SOUP_CACHE_FILE, NULL);
- if (!g_file_get_contents (filename, &contents, &length, NULL)) {
- g_free (filename);
- g_free (contents);
- return;
- }
- g_free (filename);
-
- variant_format = g_variant_type_new (WEBKIT_SOUP_CACHE_ENTRIES_FORMAT);
- cache_variant = g_variant_new_from_data (variant_format, (const gchar *)contents, length, FALSE, g_free, contents);
- g_variant_type_free (variant_format);
-
- g_variant_get (cache_variant, WEBKIT_SOUP_CACHE_ENTRIES_FORMAT, &entries_iter);
- entry = g_slice_new0 (WebKitSoupCacheEntry);
-
- while (g_variant_iter_loop (entries_iter, WEBKIT_SOUP_CACHE_PHEADERS_FORMAT,
- &entry->key, &entry->filename, &entry->must_revalidate,
- &entry->freshness_lifetime, &entry->corrected_initial_age,
- &entry->response_time, &entry->hits, &entry->length,
- &headers_iter)) {
- const gchar *header_key, *header_value;
-
- /* SoupMessage Headers */
- entry->headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE);
- while (g_variant_iter_loop (headers_iter, WEBKIT_SOUP_CACHE_DECODE_HEADERS_FORMAT, &header_key, &header_value))
- soup_message_headers_append (entry->headers, header_key, header_value);
-
- /* Insert in cache */
- if (!webkit_soup_cache_entry_insert_by_key (cache, (const gchar *)entry->key, entry, FALSE))
- webkit_soup_cache_entry_free (entry, TRUE);
-
- /* New entry for the next iteration. This creates an
- extra object the last iteration but it's worth it
- as we save several if's */
- entry = g_slice_new0 (WebKitSoupCacheEntry);
- }
- /* Remove last created entry */
- g_slice_free (WebKitSoupCacheEntry, entry);
-
- /* Sort LRU (shouldn't be needed). First reverse as elements
- * are always prepended when inserting
- */
- cache->priv->lru_start = g_list_reverse (cache->priv->lru_start);
- cache->priv->lru_start = g_list_sort (cache->priv->lru_start, lru_compare_func);
-
- /* frees */
- g_variant_iter_free (entries_iter);
- g_variant_unref (cache_variant);
-}
-
-void
-webkit_soup_cache_set_max_size (WebKitSoupCache *cache,
- guint max_size)
-{
- cache->priv->max_size = max_size;
- cache->priv->max_entry_data_size = cache->priv->max_size / MAX_ENTRY_DATA_PERCENTAGE;
-}
-
-guint
-webkit_soup_cache_get_max_size (WebKitSoupCache *cache)
-{
- return cache->priv->max_size;
-}
diff --git a/Source/WebCore/platform/network/soup/cache/webkit/soup-cache.h b/Source/WebCore/platform/network/soup/cache/webkit/soup-cache.h
deleted file mode 100644
index a926f98..0000000
--- a/Source/WebCore/platform/network/soup/cache/webkit/soup-cache.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-cache.h:
- *
- * Copyright (C) 2009, 2010 Igalia, S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef WEBKIT_SOUP_CACHE_H
-#define WEBKIT_SOUP_CACHE_H 1
-
-#ifdef G_OS_WIN32
- #ifdef BUILDING_WEBKIT
- #define WEBKIT_API __declspec(dllexport)
- #else
- #define WEBKIT_API __declspec(dllimport)
- #endif
- #define WEBKIT_OBSOLETE_API WEBKIT_API
-#else
- #define WEBKIT_API __attribute__((visibility("default")))
- #define WEBKIT_OBSOLETE_API WEBKIT_API __attribute__((deprecated))
-#endif
-
-#include <libsoup/soup-types.h>
-#include <gio/gio.h>
-
-G_BEGIN_DECLS
-
-#define WEBKIT_TYPE_SOUP_CACHE (webkit_soup_cache_get_type ())
-#define WEBKIT_SOUP_CACHE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WEBKIT_TYPE_SOUP_CACHE, WebKitSoupCache))
-#define WEBKIT_SOUP_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_SOUP_CACHE, WebKitSoupCacheClass))
-#define WEBKIT_IS_SOUP_CACHE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEBKIT_TYPE_SOUP_CACHE))
-#define WEBKIT_IS_SOUP_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), WEBKIT_TYPE_SOUP_CACHE))
-#define WEBKIT_SOUP_CACHE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WEBKIT_TYPE_SOUP_CACHE, WebKitSoupCacheClass))
-
-typedef struct _WebKitSoupCache WebKitSoupCache;
-typedef struct _WebKitSoupCachePrivate WebKitSoupCachePrivate;
-
-typedef enum {
- WEBKIT_SOUP_CACHE_CACHEABLE = (1 << 0),
- WEBKIT_SOUP_CACHE_UNCACHEABLE = (1 << 1),
- WEBKIT_SOUP_CACHE_INVALIDATES = (1 << 2),
- WEBKIT_SOUP_CACHE_VALIDATES = (1 << 3)
-} WebKitSoupCacheability;
-
-typedef enum {
- WEBKIT_SOUP_CACHE_RESPONSE_FRESH,
- WEBKIT_SOUP_CACHE_RESPONSE_NEEDS_VALIDATION,
- WEBKIT_SOUP_CACHE_RESPONSE_STALE
-} WebKitSoupCacheResponse;
-
-typedef enum {
- WEBKIT_SOUP_CACHE_SINGLE_USER,
- WEBKIT_SOUP_CACHE_SHARED
-} WebKitSoupCacheType;
-
-struct _WebKitSoupCache {
- GObject parent_instance;
-
- WebKitSoupCachePrivate *priv;
-};
-
-typedef struct {
- GObjectClass parent_class;
-
- /* methods */
- WebKitSoupCacheability (*get_cacheability)(WebKitSoupCache *cache, SoupMessage *msg);
-
- /* Padding for future expansion */
- void (*_libsoup_reserved1)(void);
- void (*_libsoup_reserved2)(void);
- void (*_libsoup_reserved3)(void);
-} WebKitSoupCacheClass;
-
-WEBKIT_API GType webkit_soup_cache_get_type (void);
-WEBKIT_API WebKitSoupCache *webkit_soup_cache_new (const char *cache_dir,
- WebKitSoupCacheType cache_type);
-WEBKIT_API void webkit_soup_cache_flush (WebKitSoupCache *cache);
-WEBKIT_API void webkit_soup_cache_clear (WebKitSoupCache *cache);
-
-WEBKIT_API void webkit_soup_cache_dump (WebKitSoupCache *cache);
-WEBKIT_API void webkit_soup_cache_load (WebKitSoupCache *cache);
-
-WEBKIT_API void webkit_soup_cache_set_max_size (WebKitSoupCache *cache,
- guint max_size);
-WEBKIT_API guint webkit_soup_cache_get_max_size (WebKitSoupCache *cache);
-
-G_END_DECLS
-
-
-#endif /* WEBKIT_SOUP_CACHE_H */
-
diff --git a/Source/WebCore/platform/network/win/DownloadBundleWin.cpp b/Source/WebCore/platform/network/win/DownloadBundleWin.cpp
new file mode 100644
index 0000000..f0f3027
--- /dev/null
+++ b/Source/WebCore/platform/network/win/DownloadBundleWin.cpp
@@ -0,0 +1,196 @@
+/*
+ * 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"
+#include "DownloadBundle.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <io.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+namespace DownloadBundle {
+
+static UInt32 magicNumber()
+{
+ return 0xDECAF4EA;
+}
+
+const String& fileExtension()
+{
+ DEFINE_STATIC_LOCAL(const String, extension, (".download"));
+ return extension;
+}
+
+bool appendResumeData(CFDataRef resumeData, const String& bundlePath)
+{
+ if (!resumeData) {
+ LOG_ERROR("Invalid resume data to write to bundle path");
+ return false;
+ }
+ if (bundlePath.isEmpty()) {
+ LOG_ERROR("Cannot write resume data to empty download bundle path");
+ return false;
+ }
+
+ String nullifiedPath = bundlePath;
+ FILE* bundle = 0;
+ if (_wfopen_s(&bundle, nullifiedPath.charactersWithNullTermination(), TEXT("ab")) || !bundle) {
+ LOG_ERROR("Failed to open file %s to append resume data", bundlePath.ascii().data());
+ return false;
+ }
+
+ bool result = false;
+
+ const UInt8* resumeBytes = CFDataGetBytePtr(resumeData);
+ ASSERT(resumeBytes);
+ if (!resumeBytes)
+ goto exit;
+
+ CFIndex resumeLength = CFDataGetLength(resumeData);
+ ASSERT(resumeLength > 0);
+ if (resumeLength < 1)
+ goto exit;
+
+ if (fwrite(resumeBytes, 1, resumeLength, bundle) != resumeLength) {
+ LOG_ERROR("Failed to write resume data to the bundle - errno(%i)", errno);
+ goto exit;
+ }
+
+ if (fwrite(&resumeLength, 4, 1, bundle) != 1) {
+ LOG_ERROR("Failed to write footer length to the bundle - errno(%i)", errno);
+ goto exit;
+ }
+
+ const UInt32& magic = magicNumber();
+ if (fwrite(&magic, 4, 1, bundle) != 1) {
+ LOG_ERROR("Failed to write footer magic number to the bundle - errno(%i)", errno);
+ goto exit;
+ }
+
+ result = true;
+exit:
+ fclose(bundle);
+ return result;
+}
+
+CFDataRef extractResumeData(const String& bundlePath)
+{
+ if (bundlePath.isEmpty()) {
+ LOG_ERROR("Cannot create resume data from empty download bundle path");
+ return 0;
+ }
+
+ // Open a handle to the bundle file
+ String nullifiedPath = bundlePath;
+ FILE* bundle = 0;
+ if (_wfopen_s(&bundle, nullifiedPath.charactersWithNullTermination(), TEXT("r+b")) || !bundle) {
+ LOG_ERROR("Failed to open file %s to get resume data", bundlePath.ascii().data());
+ return 0;
+ }
+
+ CFDataRef result = 0;
+ Vector<UInt8> footerBuffer;
+
+ // Stat the file to get its size
+ struct _stat64 fileStat;
+ if (_fstat64(_fileno(bundle), &fileStat))
+ goto exit;
+
+ // Check for the bundle magic number at the end of the file
+ fpos_t footerMagicNumberPosition = fileStat.st_size - 4;
+ ASSERT(footerMagicNumberPosition >= 0);
+ if (footerMagicNumberPosition < 0)
+ goto exit;
+ if (fsetpos(bundle, &footerMagicNumberPosition))
+ goto exit;
+
+ UInt32 footerMagicNumber = 0;
+ if (fread(&footerMagicNumber, 4, 1, bundle) != 1) {
+ LOG_ERROR("Failed to read footer magic number from the bundle - errno(%i)", errno);
+ goto exit;
+ }
+
+ if (footerMagicNumber != magicNumber()) {
+ LOG_ERROR("Footer's magic number does not match 0x%X - errno(%i)", magicNumber(), errno);
+ goto exit;
+ }
+
+ // Now we're *reasonably* sure this is a .download bundle we actually wrote.
+ // Get the length of the resume data
+ fpos_t footerLengthPosition = fileStat.st_size - 8;
+ ASSERT(footerLengthPosition >= 0);
+ if (footerLengthPosition < 0)
+ goto exit;
+
+ if (fsetpos(bundle, &footerLengthPosition))
+ goto exit;
+
+ UInt32 footerLength = 0;
+ if (fread(&footerLength, 4, 1, bundle) != 1) {
+ LOG_ERROR("Failed to read ResumeData length from the bundle - errno(%i)", errno);
+ goto exit;
+ }
+
+ // Make sure theres enough bytes to read in for the resume data, and perform the read
+ fpos_t footerStartPosition = fileStat.st_size - 8 - footerLength;
+ ASSERT(footerStartPosition >= 0);
+ if (footerStartPosition < 0)
+ goto exit;
+ if (fsetpos(bundle, &footerStartPosition))
+ goto exit;
+
+ footerBuffer.resize(footerLength);
+ if (fread(footerBuffer.data(), 1, footerLength, bundle) != footerLength) {
+ LOG_ERROR("Failed to read ResumeData from the bundle - errno(%i)", errno);
+ goto exit;
+ }
+
+ // CFURLDownload will seek to the appropriate place in the file (before our footer) and start overwriting from there
+ // However, say we were within a few hundred bytes of the end of a download when it was paused -
+ // The additional footer extended the length of the file beyond its final length, and there will be junk data leftover
+ // at the end. Therefore, now that we've retrieved the footer data, we need to truncate it.
+ if (errno_t resizeError = _chsize_s(_fileno(bundle), footerStartPosition)) {
+ LOG_ERROR("Failed to truncate the resume footer off the end of the file - errno(%i)", resizeError);
+ goto exit;
+ }
+
+ // Finally, make the resume data. Now, it is possible by some twist of fate the bundle magic number
+ // was naturally at the end of the file and its not actually a valid bundle. That, or someone engineered
+ // it that way to try to attack us. In that cause, this CFData will successfully create but when we
+ // actually try to start the CFURLDownload using this bogus data, it will fail and we will handle that gracefully
+ result = CFDataCreate(0, footerBuffer.data(), footerLength);
+exit:
+ fclose(bundle);
+ return result;
+}
+
+} // namespace DownloadBundle
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/qt/ClipboardQt.h b/Source/WebCore/platform/qt/ClipboardQt.h
index fb5abef..8d78634 100644
--- a/Source/WebCore/platform/qt/ClipboardQt.h
+++ b/Source/WebCore/platform/qt/ClipboardQt.h
@@ -26,8 +26,8 @@
#ifndef ClipboardQt_h
#define ClipboardQt_h
-#include "Clipboard.h"
#include "CachedResourceClient.h"
+#include "Clipboard.h"
QT_BEGIN_NAMESPACE
class QMimeData;
@@ -35,56 +35,56 @@ QT_END_NAMESPACE
namespace WebCore {
- class CachedImage;
+class CachedImage;
- // State available during IE's events for drag and drop and copy/paste
- class ClipboardQt : public Clipboard, public CachedResourceClient {
- WTF_MAKE_FAST_ALLOCATED;
- public:
- static PassRefPtr<ClipboardQt> create(ClipboardAccessPolicy policy, const QMimeData* readableClipboard)
- {
- return adoptRef(new ClipboardQt(policy, readableClipboard));
- }
- static PassRefPtr<ClipboardQt> create(ClipboardAccessPolicy policy, ClipboardType clipboardType = CopyAndPaste)
- {
- return adoptRef(new ClipboardQt(policy, clipboardType));
- }
- virtual ~ClipboardQt();
+// State available during IE's events for drag and drop and copy/paste
+class ClipboardQt : public Clipboard, public CachedResourceClient {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ static PassRefPtr<ClipboardQt> create(ClipboardAccessPolicy policy, const QMimeData* readableClipboard)
+ {
+ return adoptRef(new ClipboardQt(policy, readableClipboard));
+ }
+ static PassRefPtr<ClipboardQt> create(ClipboardAccessPolicy policy, ClipboardType clipboardType = CopyAndPaste)
+ {
+ return adoptRef(new ClipboardQt(policy, clipboardType));
+ }
+ virtual ~ClipboardQt();
- void clearData(const String& type);
- void clearAllData();
- String getData(const String& type, bool& success) const;
- bool setData(const String& type, const String& data);
+ void clearData(const String& type);
+ void clearAllData();
+ String getData(const String& type, bool& success) const;
+ bool setData(const String& type, const String& data);
- // extensions beyond IE's API
- virtual HashSet<String> types() const;
- virtual PassRefPtr<FileList> files() const;
+ // extensions beyond IE's API
+ virtual HashSet<String> types() const;
+ virtual PassRefPtr<FileList> files() const;
- void setDragImage(CachedImage*, const IntPoint&);
- void setDragImageElement(Node*, const IntPoint&);
+ void setDragImage(CachedImage*, const IntPoint&);
+ void setDragImageElement(Node*, const IntPoint&);
- virtual DragImageRef createDragImage(IntPoint& dragLoc) const;
- virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*);
- virtual void writeURL(const KURL&, const String&, Frame*);
- virtual void writeRange(Range*, Frame*);
- virtual void writePlainText(const String&);
+ virtual DragImageRef createDragImage(IntPoint& dragLoc) const;
+ virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*);
+ virtual void writeURL(const KURL&, const String&, Frame*);
+ virtual void writeRange(Range*, Frame*);
+ virtual void writePlainText(const String&);
- virtual bool hasData();
+ virtual bool hasData();
- QMimeData* clipboardData() const { return m_writableData; }
- void invalidateWritableData() { m_writableData = 0; }
+ QMimeData* clipboardData() const { return m_writableData; }
+ void invalidateWritableData() { m_writableData = 0; }
- private:
- ClipboardQt(ClipboardAccessPolicy, const QMimeData* readableClipboard);
+private:
+ ClipboardQt(ClipboardAccessPolicy, const QMimeData* readableClipboard);
- // Clipboard is writable so it will create its own QMimeData object
- ClipboardQt(ClipboardAccessPolicy, ClipboardType);
+ // Clipboard is writable so it will create its own QMimeData object
+ ClipboardQt(ClipboardAccessPolicy, ClipboardType);
- void setDragImage(CachedImage*, Node*, const IntPoint& loc);
+ void setDragImage(CachedImage*, Node*, const IntPoint& loc);
- const QMimeData* m_readableData;
- QMimeData* m_writableData;
- };
+ const QMimeData* m_readableData;
+ QMimeData* m_writableData;
+};
}
#endif // ClipboardQt_h
diff --git a/Source/WebCore/platform/qt/CookieJarQt.cpp b/Source/WebCore/platform/qt/CookieJarQt.cpp
index b7ff5d1..e5a2dcd 100644
--- a/Source/WebCore/platform/qt/CookieJarQt.cpp
+++ b/Source/WebCore/platform/qt/CookieJarQt.cpp
@@ -114,10 +114,12 @@ String cookieRequestHeaderFieldValue(const Document* document, const KURL &url)
bool cookiesEnabled(const Document* document)
{
- if (QNetworkAccessManager* manager = networkAccessManager(document))
- return !!manager->cookieJar();
+ QNetworkAccessManager* manager = networkAccessManager(document);
+ if (!manager)
+ return false;
- return false;
+ QtNAMThreadSafeProxy managerProxy(manager);
+ return managerProxy.hasCookieJar();
}
bool getRawCookies(const Document*, const KURL&, Vector<Cookie>& rawCookies)
diff --git a/Source/WebCore/platform/qt/DragDataQt.cpp b/Source/WebCore/platform/qt/DragDataQt.cpp
index f68ad1d..2554df4 100644
--- a/Source/WebCore/platform/qt/DragDataQt.cpp
+++ b/Source/WebCore/platform/qt/DragDataQt.cpp
@@ -125,7 +125,8 @@ String DragData::asURL(Frame*, FilenameConversionPolicy filenamePolicy, String*)
if (urls.isEmpty())
return String();
- return encodeWithURLEscapeSequences(urls.first().toString());
+ QByteArray encodedUrl = urls.first().toEncoded();
+ return String(encodedUrl.constData(), encodedUrl.length());
}
PassRefPtr<DocumentFragment> DragData::asFragment(Frame* frame, PassRefPtr<Range>, bool, bool&) const
diff --git a/Source/WebCore/platform/qt/MIMETypeRegistryQt.cpp b/Source/WebCore/platform/qt/MIMETypeRegistryQt.cpp
index 12db891..01cef12 100644
--- a/Source/WebCore/platform/qt/MIMETypeRegistryQt.cpp
+++ b/Source/WebCore/platform/qt/MIMETypeRegistryQt.cpp
@@ -29,6 +29,9 @@
#include "config.h"
#include "MIMETypeRegistry.h"
+#include <wtf/Assertions.h>
+#include <wtf/MainThread.h>
+
namespace WebCore {
struct ExtensionMap {
@@ -70,6 +73,8 @@ static const ExtensionMap extensionMap[] = {
String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
{
+ ASSERT(isMainThread());
+
String s = ext.lower();
const ExtensionMap *e = extensionMap;
diff --git a/Source/WebCore/platform/qt/RenderThemeQt.cpp b/Source/WebCore/platform/qt/RenderThemeQt.cpp
index 8d5cfcd..d4688cf 100644
--- a/Source/WebCore/platform/qt/RenderThemeQt.cpp
+++ b/Source/WebCore/platform/qt/RenderThemeQt.cpp
@@ -726,7 +726,7 @@ bool RenderThemeQt::paintMenuList(RenderObject* o, const PaintInfo& i, const Int
initStyleOption(p.widget, opt);
initializeCommonQStyleOptions(opt, o);
- const QPoint topLeft = r.topLeft();
+ const QPoint topLeft = r.location();
p.painter->translate(topLeft);
opt.rect.moveTo(QPoint(0, 0));
opt.rect.setSize(r.size());
@@ -825,7 +825,7 @@ bool RenderThemeQt::paintProgressBar(RenderObject* o, const PaintInfo& pi, const
option.minimum = 0;
option.progress = (renderProgress->position() * std::numeric_limits<int>::max());
- const QPoint topLeft = r.topLeft();
+ const QPoint topLeft = r.location();
p.painter->translate(topLeft);
option.rect.moveTo(QPoint(0, 0));
option.rect.setSize(r.size());
@@ -887,7 +887,7 @@ bool RenderThemeQt::paintSliderTrack(RenderObject* o, const PaintInfo& pi,
option.state |= QStyle::State_Sunken;
}
- const QPoint topLeft = r.topLeft();
+ const QPoint topLeft = r.location();
p.painter->translate(topLeft);
option.rect.moveTo(QPoint(0, 0));
option.rect.setSize(r.size());
@@ -1174,7 +1174,26 @@ QColor RenderThemeQt::getMediaControlForegroundColor(RenderObject* o) const
bool RenderThemeQt::paintMediaFullscreenButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
- return RenderTheme::paintMediaFullscreenButton(o, paintInfo, r);
+ HTMLMediaElement* mediaElement = getMediaElementFromRenderObject(o);
+ if (!mediaElement)
+ return false;
+
+ StylePainter p(this, paintInfo);
+ if (!p.isValid())
+ return true;
+
+ p.painter->setRenderHint(QPainter::Antialiasing, true);
+
+ paintMediaBackground(p.painter, r);
+
+ WorldMatrixTransformer transformer(p.painter, o, r);
+ const QPointF arrowPolygon[9] = { QPointF(20, 0), QPointF(100, 0), QPointF(100, 80),
+ QPointF(80, 80), QPointF(80, 30), QPointF(10, 100), QPointF(0, 90), QPointF(70, 20), QPointF(20, 20)};
+
+ p.painter->setBrush(getMediaControlForegroundColor(o));
+ p.painter->drawPolygon(arrowPolygon, 9);
+
+ return false;
}
bool RenderThemeQt::paintMediaMuteButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
diff --git a/Source/WebCore/platform/qt/ScrollbarQt.cpp b/Source/WebCore/platform/qt/ScrollbarQt.cpp
index dda82e9..5afb1ae6 100644
--- a/Source/WebCore/platform/qt/ScrollbarQt.cpp
+++ b/Source/WebCore/platform/qt/ScrollbarQt.cpp
@@ -74,6 +74,11 @@ bool Scrollbar::contextMenu(const PlatformMouseEvent& event)
QAction* actionSelected = menu.exec(globalPos);
if (actionSelected == actScrollHere) {
+ // Set the pressed position to the middle of the thumb so that when we
+ // do move, the delta will be from the current pixel position of the
+ // thumb to the new position
+ int position = theme()->trackPosition(this) + theme()->thumbPosition(this) + theme()->thumbLength(this) / 2;
+ setPressedPos(position);
const QPoint pos = convertFromContainingWindow(event.pos());
moveThumb(horizontal ? pos.x() : pos.y());
} else if (actionSelected == actScrollTop)
diff --git a/Source/WebCore/platform/sql/SQLiteStatement.cpp b/Source/WebCore/platform/sql/SQLiteStatement.cpp
index af9518a..d9186dc 100644
--- a/Source/WebCore/platform/sql/SQLiteStatement.cpp
+++ b/Source/WebCore/platform/sql/SQLiteStatement.cpp
@@ -176,6 +176,20 @@ int SQLiteStatement::bindBlob(int index, const void* blob, int size)
return sqlite3_bind_blob(m_statement, index, blob, size, SQLITE_TRANSIENT);
}
+int SQLiteStatement::bindBlob(int index, const String& text)
+{
+ // String::characters() returns 0 for the empty string, which SQLite
+ // treats as a null, so we supply a non-null pointer for that case.
+ UChar anyCharacter = 0;
+ const UChar* characters;
+ if (text.isEmpty() && !text.isNull())
+ characters = &anyCharacter;
+ else
+ characters = text.characters();
+
+ return bindBlob(index, characters, text.length() * sizeof(UChar));
+}
+
int SQLiteStatement::bindText(int index, const String& text)
{
ASSERT(m_isPrepared);
@@ -355,7 +369,29 @@ int64_t SQLiteStatement::getColumnInt64(int col)
return 0;
return sqlite3_column_int64(m_statement, col);
}
-
+
+String SQLiteStatement::getColumnBlobAsString(int col)
+{
+ ASSERT(col >= 0);
+
+ if (!m_statement && prepareAndStep() != SQLITE_ROW)
+ return String();
+
+ if (columnCount() <= col)
+ return String();
+
+ const void* blob = sqlite3_column_blob(m_statement, col);
+ if (!blob)
+ return String();
+
+ int size = sqlite3_column_bytes(m_statement, col);
+ if (size < 0)
+ return String();
+
+ ASSERT(!(size % sizeof(UChar)));
+ return String(static_cast<const UChar*>(blob), size / sizeof(UChar));
+}
+
void SQLiteStatement::getColumnBlobAsVector(int col, Vector<char>& result)
{
ASSERT(col >= 0);
@@ -379,7 +415,7 @@ void SQLiteStatement::getColumnBlobAsVector(int col, Vector<char>& result)
int size = sqlite3_column_bytes(m_statement, col);
result.resize((size_t)size);
for (int i = 0; i < size; ++i)
- result[i] = ((const unsigned char*)blob)[i];
+ result[i] = (static_cast<const unsigned char*>(blob))[i];
}
const void* SQLiteStatement::getColumnBlob(int col, int& size)
diff --git a/Source/WebCore/platform/sql/SQLiteStatement.h b/Source/WebCore/platform/sql/SQLiteStatement.h
index fd1abfb..35dcecf 100644
--- a/Source/WebCore/platform/sql/SQLiteStatement.h
+++ b/Source/WebCore/platform/sql/SQLiteStatement.h
@@ -42,6 +42,7 @@ public:
int prepare();
int bindBlob(int index, const void* blob, int size);
+ int bindBlob(int index, const String&);
int bindText(int index, const String&);
int bindInt(int index, int);
int bindInt64(int index, int64_t);
@@ -80,6 +81,7 @@ public:
int getColumnInt(int col);
int64_t getColumnInt64(int col);
const void* getColumnBlob(int col, int& size);
+ String getColumnBlobAsString(int col);
void getColumnBlobAsVector(int col, Vector<char>&);
bool returnTextResults(int col, Vector<String>&);
diff --git a/Source/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumPosix.cpp b/Source/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumPosix.cpp
index 37f96be..6dbc384 100644
--- a/Source/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumPosix.cpp
+++ b/Source/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumPosix.cpp
@@ -34,938 +34,23 @@
#include "PlatformBridge.h"
#include <sqlite3.h>
-#include <errno.h>
#include <fcntl.h>
#include <string.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
#include <unistd.h>
using namespace WebCore;
-// Chromium's Posix implementation of SQLite VFS.
-// This is heavily based on SQLite's os_unix.c,
-// without parts we don't need.
-
-// Identifies a file by its device number and inode.
-struct ChromiumFileId {
- dev_t dev; // Device number.
- ino_t ino; // Inode number.
-};
-
-// Information about file locks (one per open inode). Note that many open
-// file descriptors may refer to the same inode.
-struct ChromiumLockInfo {
- ChromiumFileId lockKey; // File identifier.
- int cnt; // Number of shared locks held.
- int locktype; // Type of the lock.
- int nRef; // Reference count.
-
- // Double-linked list pointers.
- ChromiumLockInfo* pNext;
- ChromiumLockInfo* pPrev;
-};
-
-// Information about a file descriptor that cannot be closed immediately.
-struct ChromiumUnusedFd {
- int fd; // File descriptor.
- int flags; // Flags this file descriptor was opened with.
- ChromiumUnusedFd* pNext; // Next unused file descriptor on the same file.
-};
-
-// Information about an open inode. When we want to close an inode
-// that still has locks, we defer the close until all locks are cleared.
-struct ChromiumOpenInfo {
- ChromiumFileId fileId; // The lookup key.
- int nRef; // Reference count.
- int nLock; // Number of outstanding locks.
- ChromiumUnusedFd* pUnused; // List of file descriptors to close.
-
- // Double-linked list pointers.
- ChromiumOpenInfo* pNext;
- ChromiumOpenInfo* pPrev;
-};
-
-// Keep track of locks and inodes in double-linked lists.
-static struct ChromiumLockInfo* lockList = 0;
-static struct ChromiumOpenInfo* openList = 0;
-
-// Extension of sqlite3_file specific to the chromium VFS.
-struct ChromiumFile {
- sqlite3_io_methods const* pMethod; // Implementation of sqlite3_file.
- ChromiumOpenInfo* pOpen; // Information about all open file descriptors for this file.
- ChromiumLockInfo* pLock; // Information about all locks for this file.
- int h; // File descriptor.
- int dirfd; // File descriptor for the file directory.
- unsigned char locktype; // Type of the lock used for this file.
- int lastErrno; // Value of errno for last operation on this file.
- ChromiumUnusedFd* pUnused; // Information about unused file descriptors for this file.
-};
-
-// The following constants specify the range of bytes used for locking.
-// SQLiteSharedSize is the number of bytes available in the pool from which
-// a random byte is selected for a shared lock. The pool of bytes for
-// shared locks begins at SQLiteSharedFirstByte.
-// The values are the same as used by SQLite for compatibility.
-static const off_t SQLitePendingByte = 0x40000000;
-static const off_t SQLiteReservedByte = SQLitePendingByte + 1;
-static const off_t SQLiteSharedFirstByte = SQLitePendingByte + 2;
-static const off_t SQLiteSharedSize = 510;
-
-// Maps a POSIX error code to an SQLite error code.
-static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr)
-{
- switch (posixError) {
- case 0:
- return SQLITE_OK;
- case EAGAIN:
- case ETIMEDOUT:
- case EBUSY:
- case EINTR:
- case ENOLCK:
- return SQLITE_BUSY;
- case EACCES:
- // EACCES is like EAGAIN during locking operations.
- if ((sqliteIOErr == SQLITE_IOERR_LOCK) ||
- (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
- (sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
- (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK))
- return SQLITE_BUSY;
- return SQLITE_PERM;
- case EPERM:
- return SQLITE_PERM;
- case EDEADLK:
- return SQLITE_IOERR_BLOCKED;
- default:
- return sqliteIOErr;
- }
-}
-
-// Releases a ChromiumLockInfo structure previously allocated by findLockInfo().
-static void releaseLockInfo(ChromiumLockInfo* pLock)
-{
- if (!pLock)
- return;
-
- pLock->nRef--;
- if (pLock->nRef > 0)
- return;
-
- if (pLock->pPrev) {
- ASSERT(pLock->pPrev->pNext == pLock);
- pLock->pPrev->pNext = pLock->pNext;
- } else {
- ASSERT(lockList == pLock);
- lockList = pLock->pNext;
- }
- if (pLock->pNext) {
- ASSERT(pLock->pNext->pPrev == pLock);
- pLock->pNext->pPrev = pLock->pPrev;
- }
-
- sqlite3_free(pLock);
-}
-
-// Releases a ChromiumOpenInfo structure previously allocated by findLockInfo().
-static void releaseOpenInfo(ChromiumOpenInfo* pOpen)
-{
- if (!pOpen)
- return;
-
- pOpen->nRef--;
- if (pOpen->nRef > 0)
- return;
-
- if (pOpen->pPrev) {
- ASSERT(pOpen->pPrev->pNext == pOpen);
- pOpen->pPrev->pNext = pOpen->pNext;
- } else {
- ASSERT(openList == pOpen);
- openList = pOpen->pNext;
- }
- if (pOpen->pNext) {
- ASSERT(pOpen->pNext->pPrev == pOpen);
- pOpen->pNext->pPrev = pOpen->pPrev;
- }
-
- ASSERT(!pOpen->pUnused); // Make sure we're not leaking memory and file descriptors.
-
- sqlite3_free(pOpen);
-}
-
-// Locates ChromiumLockInfo and ChromiumOpenInfo for given file descriptor (creating new ones if needed).
-// Returns a SQLite error code.
-static int findLockInfo(ChromiumFile* pFile, ChromiumLockInfo** ppLock, ChromiumOpenInfo** ppOpen)
-{
- int fd = pFile->h;
- struct stat statbuf;
- int rc = fstat(fd, &statbuf);
- if (rc) {
- pFile->lastErrno = errno;
-#ifdef EOVERFLOW
- if (pFile->lastErrno == EOVERFLOW)
- return SQLITE_NOLFS;
-#endif
- return SQLITE_IOERR;
- }
-
-#if OS(DARWIN)
- // On OS X on an msdos/fat filesystems, the inode number is reported
- // incorrectly for zero-size files. See http://www.sqlite.org/cvstrac/tktview?tn=3260.
- // To work around this problem we always increase the file size to 1 by writing a single byte
- // prior to accessing the inode number. The one byte written is an ASCII 'S' character which
- // also happens to be the first byte in the header of every SQLite database. In this way,
- // if there is a race condition such that another thread has already populated the first page
- // of the database, no damage is done.
- if (!statbuf.st_size) {
- rc = write(fd, "S", 1);
- if (rc != 1)
- return SQLITE_IOERR;
- rc = fstat(fd, &statbuf);
- if (rc) {
- pFile->lastErrno = errno;
- return SQLITE_IOERR;
- }
- }
-#endif
-
- ChromiumFileId fileId;
- memset(&fileId, 0, sizeof(fileId));
- fileId.dev = statbuf.st_dev;
- fileId.ino = statbuf.st_ino;
-
- ChromiumLockInfo* pLock = 0;
-
- if (ppLock) {
- pLock = lockList;
- while (pLock && memcmp(&fileId, &pLock->lockKey, sizeof(fileId)))
- pLock = pLock->pNext;
- if (pLock)
- pLock->nRef++;
- else {
- pLock = static_cast<ChromiumLockInfo*>(sqlite3_malloc(sizeof(*pLock)));
- if (!pLock)
- return SQLITE_NOMEM;
- pLock->lockKey = fileId;
- pLock->nRef = 1;
- pLock->cnt = 0;
- pLock->locktype = 0;
- pLock->pNext = lockList;
- pLock->pPrev = 0;
- if (lockList)
- lockList->pPrev = pLock;
- lockList = pLock;
- }
- *ppLock = pLock;
- }
-
- if (ppOpen) {
- ChromiumOpenInfo* pOpen = openList;
- while (pOpen && memcmp(&fileId, &pOpen->fileId, sizeof(fileId)))
- pOpen = pOpen->pNext;
- if (pOpen)
- pOpen->nRef++;
- else {
- pOpen = static_cast<ChromiumOpenInfo*>(sqlite3_malloc(sizeof(*pOpen)));
- if (!pOpen) {
- releaseLockInfo(pLock);
- return SQLITE_NOMEM;
- }
- memset(pOpen, 0, sizeof(*pOpen));
- pOpen->fileId = fileId;
- pOpen->nRef = 1;
- pOpen->pNext = openList;
- if (openList)
- openList->pPrev = pOpen;
- openList = pOpen;
- }
- *ppOpen = pOpen;
- }
-
- return rc;
-}
-
-// Checks if there is a RESERVED lock held on the specified file by this or any other process.
-// If the lock is held, sets pResOut to a non-zero value. Returns a SQLite error code.
-static int chromiumCheckReservedLock(sqlite3_file* id, int* pResOut)
-{
- ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
- ASSERT(pFile);
-
- // Look for locks held by this process.
- int reserved = 0;
- if (pFile->pLock->locktype > SQLITE_LOCK_SHARED)
- reserved = 1;
-
- // Look for locks held by other processes.
- int rc = SQLITE_OK;
- if (!reserved) {
- struct flock lock;
- lock.l_whence = SEEK_SET;
- lock.l_start = SQLiteReservedByte;
- lock.l_len = 1;
- lock.l_type = F_WRLCK;
- if (-1 == fcntl(pFile->h, F_GETLK, &lock)) {
- int tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
- pFile->lastErrno = tErrno;
- } else if (lock.l_type != F_UNLCK)
- reserved = 1;
- }
-
- *pResOut = reserved;
- return rc;
-}
-
-// Performs a file locking operation on a range of bytes in a file.
-// The |op| parameter should be one of F_RFLCK, F_WRLCK or F_UNLCK.
-// Returns a Unix error code, and also writes it to pErrcode.
-static int rangeLock(ChromiumFile* pFile, int op, int* pErrcode)
-{
- struct flock lock;
- lock.l_type = op;
- lock.l_start = SQLiteSharedFirstByte;
- lock.l_whence = SEEK_SET;
- lock.l_len = SQLiteSharedSize;
- int rc = fcntl(pFile->h, F_SETLK, &lock);
- *pErrcode = errno;
- return rc;
-}
-
-// Locks the file with the lock specified by parameter locktype - one
-// of the following:
-//
-// (1) SQLITE_LOCK_SHARED
-// (2) SQLITE_LOCK_RESERVED
-// (3) SQLITE_LOCK_PENDING
-// (4) SQLITE_LOCK_EXCLUSIVE
-//
-// Sometimes when requesting one lock state, additional lock states
-// are inserted in between. The locking might fail on one of the later
-// transitions leaving the lock state different from what it started but
-// still short of its goal. The following chart shows the allowed
-// transitions and the inserted intermediate states:
-//
-// UNLOCKED -> SHARED
-// SHARED -> RESERVED
-// SHARED -> (PENDING) -> EXCLUSIVE
-// RESERVED -> (PENDING) -> EXCLUSIVE
-// PENDING -> EXCLUSIVE
-static int chromiumLock(sqlite3_file* id, int locktype)
-{
- // To obtain a SHARED lock, a read-lock is obtained on the 'pending
- // byte'. If this is successful, a random byte from the 'shared byte
- // range' is read-locked and the lock on the 'pending byte' released.
- //
- // A process may only obtain a RESERVED lock after it has a SHARED lock.
- // A RESERVED lock is implemented by grabbing a write-lock on the
- // 'reserved byte'.
- //
- // A process may only obtain a PENDING lock after it has obtained a
- // SHARED lock. A PENDING lock is implemented by obtaining a write-lock
- // on the 'pending byte'. This ensures that no new SHARED locks can be
- // obtained, but existing SHARED locks are allowed to persist. A process
- // does not have to obtain a RESERVED lock on the way to a PENDING lock.
- // This property is used by the algorithm for rolling back a journal file
- // after a crash.
- //
- // An EXCLUSIVE lock, obtained after a PENDING lock is held, is
- // implemented by obtaining a write-lock on the entire 'shared byte
- // range'. Since all other locks require a read-lock on one of the bytes
- // within this range, this ensures that no other locks are held on the
- // database.
-
- int rc = SQLITE_OK;
- struct flock lock;
- int s = 0;
- int tErrno;
-
- ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
- ASSERT(pFile);
-
- ChromiumLockInfo* pLock = pFile->pLock;
-
- // If there is already a lock of this type or more restrictive, do nothing.
- if (pFile->locktype >= locktype)
- return SQLITE_OK;
-
- // Make sure we never move from unlocked to anything higher than shared lock.
- ASSERT(pFile->locktype != SQLITE_LOCK_NONE || locktype == SQLITE_LOCK_SHARED);
-
- // Make sure we never request a pending lock.
- ASSERT(locktype != SQLITE_LOCK_PENDING);
-
- // Make sure a shared lock is always held when a RESERVED lock is requested.
- ASSERT(locktype != SQLITE_LOCK_RESERVED || pFile->locktype == SQLITE_LOCK_SHARED);
-
- // If some thread using this PID has a lock via a different ChromiumFile
- // handle that precludes the requested lock, return BUSY.
- if (pFile->locktype != pLock->locktype &&
- (pLock->locktype >= SQLITE_LOCK_PENDING || locktype > SQLITE_LOCK_SHARED))
- return SQLITE_BUSY;
-
- // If a SHARED lock is requested, and some thread using this PID already
- // has a SHARED or RESERVED lock, then just increment reference counts.
- if (locktype == SQLITE_LOCK_SHARED &&
- (pLock->locktype == SQLITE_LOCK_SHARED || pLock->locktype == SQLITE_LOCK_RESERVED)) {
- ASSERT(!pFile->locktype);
- ASSERT(pLock->cnt > 0);
- pFile->locktype = SQLITE_LOCK_SHARED;
- pLock->cnt++;
- pFile->pOpen->nLock++;
- return SQLITE_OK;
- }
-
- // A PENDING lock is needed before acquiring a SHARED lock and before
- // acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will
- // be released.
- lock.l_len = 1;
- lock.l_whence = SEEK_SET;
- if (locktype == SQLITE_LOCK_SHARED ||
- (locktype == SQLITE_LOCK_EXCLUSIVE && pFile->locktype < SQLITE_LOCK_PENDING)) {
- lock.l_type = (locktype == SQLITE_LOCK_SHARED ? F_RDLCK : F_WRLCK);
- lock.l_start = SQLitePendingByte;
- s = fcntl(pFile->h, F_SETLK, &lock);
- if (s == -1) {
- tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
- pFile->lastErrno = tErrno;
- return rc;
- }
- }
-
- if (locktype == SQLITE_LOCK_SHARED) {
- ASSERT(!pLock->cnt);
- ASSERT(!pLock->locktype);
-
- s = rangeLock(pFile, F_RDLCK, &tErrno);
-
- // Drop the temporary PENDING lock.
- lock.l_start = SQLitePendingByte;
- lock.l_len = 1;
- lock.l_type = F_UNLCK;
- if (fcntl(pFile->h, F_SETLK, &lock)) {
- if (s != -1) {
- tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
- if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
- pFile->lastErrno = tErrno;
- return rc;
- }
- }
- if (s == -1) {
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
- pFile->lastErrno = tErrno;
- } else {
- pFile->locktype = SQLITE_LOCK_SHARED;
- pFile->pOpen->nLock++;
- pLock->cnt = 1;
- }
- } else if (locktype == SQLITE_LOCK_EXCLUSIVE && pLock->cnt > 1) {
- // We are trying for an exclusive lock but another thread in the
- // same process is still holding a shared lock.
- rc = SQLITE_BUSY;
- } else {
- // The request was for a RESERVED or EXCLUSIVE lock. It is
- // assumed that there is a SHARED or greater lock on the file
- // already.
- ASSERT(pFile->locktype);
- lock.l_type = F_WRLCK;
- switch (locktype) {
- case SQLITE_LOCK_RESERVED:
- lock.l_start = SQLiteReservedByte;
- s = fcntl(pFile->h, F_SETLK, &lock);
- tErrno = errno;
- break;
- case SQLITE_LOCK_EXCLUSIVE:
- s = rangeLock(pFile, F_WRLCK, &tErrno);
- break;
- default:
- ASSERT_NOT_REACHED();
- }
- if (s == -1) {
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
- pFile->lastErrno = tErrno;
- }
- }
-
- if (rc == SQLITE_OK) {
- pFile->locktype = locktype;
- pLock->locktype = locktype;
- } else if (locktype == SQLITE_LOCK_EXCLUSIVE) {
- pFile->locktype = SQLITE_LOCK_PENDING;
- pLock->locktype = SQLITE_LOCK_PENDING;
- }
-
- return rc;
-}
-
-// Closes all file descriptors for given ChromiumFile for which the close has been deferred.
-// Returns a SQLite error code.
-static int closePendingFds(ChromiumFile* pFile)
-{
- int rc = SQLITE_OK;
- ChromiumOpenInfo* pOpen = pFile->pOpen;
- ChromiumUnusedFd* pError = 0;
- ChromiumUnusedFd* pNext;
- for (ChromiumUnusedFd* p = pOpen->pUnused; p; p = pNext) {
- pNext = p->pNext;
- if (close(p->fd)) {
- pFile->lastErrno = errno;
- rc = SQLITE_IOERR_CLOSE;
- p->pNext = pError;
- pError = p;
- } else
- sqlite3_free(p);
- }
- pOpen->pUnused = pError;
- return rc;
-}
-
-// Lowers the locking level on file descriptor.
-// locktype must be either SQLITE_LOCK_NONE or SQLITE_LOCK_SHARED.
-static int chromiumUnlock(sqlite3_file* id, int locktype)
-{
- ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
- ASSERT(pFile);
- ASSERT(locktype <= SQLITE_LOCK_SHARED);
-
- if (pFile->locktype <= locktype)
- return SQLITE_OK;
-
- ChromiumLockInfo* pLock = pFile->pLock;
- ASSERT(pLock->cnt);
-
- struct flock lock;
- int rc = SQLITE_OK;
- int h = pFile->h;
- int tErrno;
-
- if (pFile->locktype > SQLITE_LOCK_SHARED) {
- ASSERT(pLock->locktype == pFile->locktype);
-
- if (locktype == SQLITE_LOCK_SHARED && rangeLock(pFile, F_RDLCK, &tErrno) == -1) {
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
- if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
- pFile->lastErrno = tErrno;
- if (rc == SQLITE_OK)
- pFile->locktype = locktype;
- return rc;
- }
- lock.l_type = F_UNLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = SQLitePendingByte;
- lock.l_len = 2;
- if (fcntl(h, F_SETLK, &lock) != -1)
- pLock->locktype = SQLITE_LOCK_SHARED;
- else {
- tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
- if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
- pFile->lastErrno = tErrno;
- if (rc == SQLITE_OK)
- pFile->locktype = locktype;
- return rc;
- }
- }
- if (locktype == SQLITE_LOCK_NONE) {
- struct ChromiumOpenInfo *pOpen;
-
- pLock->cnt--;
-
- // Release the lock using an OS call only when all threads in this same process have released the lock.
- if (!pLock->cnt) {
- lock.l_type = F_UNLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = lock.l_len = 0L;
- if (fcntl(h, F_SETLK, &lock) != -1)
- pLock->locktype = SQLITE_LOCK_NONE;
- else {
- tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
- if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
- pFile->lastErrno = tErrno;
- pLock->locktype = SQLITE_LOCK_NONE;
- pFile->locktype = SQLITE_LOCK_NONE;
- }
- }
-
- pOpen = pFile->pOpen;
- pOpen->nLock--;
- ASSERT(pOpen->nLock >= 0);
- if (!pOpen->nLock) {
- int rc2 = closePendingFds(pFile);
- if (rc == SQLITE_OK)
- rc = rc2;
- }
- }
-
- if (rc == SQLITE_OK)
- pFile->locktype = locktype;
- return rc;
+// Defined in Chromium's codebase in third_party/sqlite/src/os_unix.c
+extern "C" {
+void chromium_sqlite3_initialize_unix_sqlite3_file(sqlite3_file* file);
+int chromium_sqlite3_fill_in_unix_sqlite3_file(sqlite3_vfs* vfs, int fd, int dirfd, sqlite3_file* file, const char* fileName, int noLock);
+int chromium_sqlite3_get_reusable_file_handle(sqlite3_file* file, const char* fileName, int flags, int* fd);
+void chromium_sqlite3_update_reusable_file_handle(sqlite3_file* file, int fd, int flags);
+void chromium_sqlite3_destroy_reusable_file_handle(sqlite3_file* file);
}
-// Closes all file handles for given ChromiumFile and sets all its fields to 0.
-// Returns a SQLite error code.
-static int chromiumCloseNoLock(sqlite3_file* id)
-{
- ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
- if (!pFile)
- return SQLITE_OK;
- if (pFile->dirfd >= 0) {
- if (close(pFile->dirfd)) {
- pFile->lastErrno = errno;
- return SQLITE_IOERR_DIR_CLOSE;
- }
- pFile->dirfd = -1;
- }
- if (pFile->h >= 0 && close(pFile->h)) {
- pFile->lastErrno = errno;
- return SQLITE_IOERR_CLOSE;
- }
- sqlite3_free(pFile->pUnused);
- memset(pFile, 0, sizeof(ChromiumFile));
- return SQLITE_OK;
-}
-
-// Closes a ChromiumFile, including locking operations. Returns a SQLite error code.
-static int chromiumClose(sqlite3_file* id)
-{
- if (!id)
- return SQLITE_OK;
-
- ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
- chromiumUnlock(id, SQLITE_LOCK_NONE);
- if (pFile->pOpen && pFile->pOpen->nLock) {
- // If there are outstanding locks, do not actually close the file just
- // yet because that would clear those locks.
- ChromiumOpenInfo* pOpen = pFile->pOpen;
- ChromiumUnusedFd* p = pFile->pUnused;
- p->pNext = pOpen->pUnused;
- pOpen->pUnused = p;
- pFile->h = -1;
- pFile->pUnused = 0;
- }
- releaseLockInfo(pFile->pLock);
- releaseOpenInfo(pFile->pOpen);
- return chromiumCloseNoLock(id);
-}
-
-static int chromiumCheckReservedLockNoop(sqlite3_file*, int* pResOut)
-{
- *pResOut = 0;
- return SQLITE_OK;
-}
-
-static int chromiumLockNoop(sqlite3_file*, int)
-{
- return SQLITE_OK;
-}
-
-static int chromiumUnlockNoop(sqlite3_file*, int)
-{
- return SQLITE_OK;
-}
-
-// Seeks to the requested offset and reads up to |cnt| bytes into |pBuf|. Returns number of bytes actually read.
-static int seekAndRead(ChromiumFile* id, sqlite3_int64 offset, void* pBuf, int cnt)
-{
- sqlite_int64 newOffset = lseek(id->h, offset, SEEK_SET);
- if (newOffset != offset) {
- id->lastErrno = (newOffset == -1) ? errno : 0;
- return -1;
- }
- int got = read(id->h, pBuf, cnt);
- if (got < 0)
- id->lastErrno = errno;
- return got;
-}
-
-// Reads data from file into a buffer. Returns a SQLite error code.
-static int chromiumRead(sqlite3_file* id, void* pBuf, int amt, sqlite3_int64 offset)
-{
- ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
- ASSERT(pFile);
-
- // The bytes in the locking range should never be read.
- ASSERT(!pFile->pUnused || offset >= SQLitePendingByte + 512 || offset + amt <= SQLitePendingByte);
-
- int got = seekAndRead(pFile, offset, pBuf, amt);
- if (got == amt)
- return SQLITE_OK;
-
- if (got < 0)
- return SQLITE_IOERR_READ;
-
- // Unread parts of the buffer must be zero-filled.
- memset(&(reinterpret_cast<char*>(pBuf))[got], 0, amt - got);
- pFile->lastErrno = 0;
- return SQLITE_IOERR_SHORT_READ;
-}
-
-// Seeks to the requested offset and writes up to |cnt| bytes. Returns number of bytes actually written.
-static int seekAndWrite(ChromiumFile* id, sqlite_int64 offset, const void* pBuf, int cnt)
-{
- sqlite_int64 newOffset = lseek(id->h, offset, SEEK_SET);
- if (newOffset != offset) {
- id->lastErrno = (newOffset == -1) ? errno : 0;
- return -1;
- }
- int got = write(id->h, pBuf, cnt);
- if (got < 0)
- id->lastErrno = errno;
- return got;
-}
-
-// Writes data from buffer into a file. Returns a SQLite error code.
-static int chromiumWrite(sqlite3_file* id, const void* pBuf, int amt, sqlite3_int64 offset)
-{
- ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
- ASSERT(pFile);
- ASSERT(amt > 0);
-
- // The bytes in the locking range should never be written.
- ASSERT(!pFile->pUnused || offset >= SQLitePendingByte + 512 || offset + amt <= SQLitePendingByte);
-
- int wrote = 0;
- while (amt > 0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt)) > 0) {
- amt -= wrote;
- offset += wrote;
- pBuf = &(reinterpret_cast<const char*>(pBuf))[wrote];
- }
- if (amt > 0) {
- if (wrote < 0)
- return SQLITE_IOERR_WRITE;
- pFile->lastErrno = 0;
- return SQLITE_FULL;
- }
- return SQLITE_OK;
-}
-
-static bool syncWrapper(int fd, bool fullSync)
-{
-#if OS(DARWIN)
- bool success = false;
- if (fullSync)
- success = !fcntl(fd, F_FULLFSYNC, 0);
- if (!success)
- success = !fsync(fd);
- return success;
-#else
- return !fdatasync(fd);
-#endif
-}
-
-// Makes sure all writes to a particular file are committed to disk. Returns a SQLite error code.
-static int chromiumSync(sqlite3_file* id, int flags)
-{
- ASSERT((flags & 0x0F) == SQLITE_SYNC_NORMAL || (flags & 0x0F) == SQLITE_SYNC_FULL);
-
- ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
- ASSERT(pFile);
-
- bool isFullSync = ((flags & 0x0F) == SQLITE_SYNC_FULL);
-
- if (!syncWrapper(pFile->h, isFullSync)) {
- pFile->lastErrno = errno;
- return SQLITE_IOERR_FSYNC;
- }
-
- if (pFile->dirfd >= 0) {
-#if !OS(DARWIN)
- if (!isFullSync) {
- // Ignore directory sync failures, see http://www.sqlite.org/cvstrac/tktview?tn=1657.
- syncWrapper(pFile->dirfd, false);
- }
-#endif
- if (!close(pFile->dirfd))
- pFile->dirfd = -1;
- else {
- pFile->lastErrno = errno;
- return SQLITE_IOERR_DIR_CLOSE;
- }
- }
-
- return SQLITE_OK;
-}
-
-// Truncates an open file to the specified size. Returns a SQLite error code.
-static int chromiumTruncate(sqlite3_file* id, sqlite_int64 nByte)
-{
- ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
- ASSERT(pFile);
-
- if (ftruncate(pFile->h, nByte)) {
- pFile->lastErrno = errno;
- return SQLITE_IOERR_TRUNCATE;
- }
-
- return SQLITE_OK;
-}
-
-// Determines the size of a file in bytes. Returns a SQLite error code.
-static int chromiumFileSize(sqlite3_file* id, sqlite_int64* pSize)
-{
- ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
- ASSERT(pFile);
-
- struct stat buf;
- if (fstat(pFile->h, &buf)) {
- pFile->lastErrno = errno;
- return SQLITE_IOERR_FSTAT;
- }
- *pSize = buf.st_size;
-
- // When opening a zero-size database, findLockInfo writes a single byte into that file
- // in order to work around a bug in the OS X msdos filesystem. In order to avoid problems
- // with upper layers, we need to report this file size as zero even though it is really 1.
- // See http://www.sqlite.org/cvstrac/tktview?tn=3260.
- if (*pSize == 1)
- *pSize = 0;
-
- return SQLITE_OK;
-}
-
-static int chromiumFileControl(sqlite3_file* id, int op, void* pArg)
-{
- ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
- ASSERT(pFile);
-
- switch (op) {
- case SQLITE_FCNTL_LOCKSTATE:
- *reinterpret_cast<int*>(pArg) = pFile->locktype;
- return SQLITE_OK;
- case SQLITE_LAST_ERRNO:
- *reinterpret_cast<int*>(pArg) = pFile->lastErrno;
- return SQLITE_OK;
- }
- return SQLITE_ERROR;
-}
-
-// Same as SQLITE_DEFAULT_SECTOR_SIZE from sqlite's os.h.
-static const int SQLiteDefaultSectorSize = 512;
-
-static int chromiumSectorSize(sqlite3_file*)
-{
- return SQLiteDefaultSectorSize;
-}
-
-static int chromiumDeviceCharacteristics(sqlite3_file*)
-{
- return 0;
-}
-
-static const sqlite3_io_methods posixIoMethods = {
- 1,
- chromiumClose,
- chromiumRead,
- chromiumWrite,
- chromiumTruncate,
- chromiumSync,
- chromiumFileSize,
- chromiumLock,
- chromiumUnlock,
- chromiumCheckReservedLock,
- chromiumFileControl,
- chromiumSectorSize,
- chromiumDeviceCharacteristics
-};
-
-static const sqlite3_io_methods nolockIoMethods = {
- 1,
- chromiumCloseNoLock,
- chromiumRead,
- chromiumWrite,
- chromiumTruncate,
- chromiumSync,
- chromiumFileSize,
- chromiumLockNoop,
- chromiumUnlockNoop,
- chromiumCheckReservedLockNoop,
- chromiumFileControl,
- chromiumSectorSize,
- chromiumDeviceCharacteristics
-};
-
-// Initializes a ChromiumFile. Returns a SQLite error code.
-static int fillInChromiumFile(sqlite3_vfs* pVfs, int h, int dirfd, sqlite3_file* pId, const char* zFilename, int noLock)
-{
- ChromiumFile* pNew = reinterpret_cast<ChromiumFile*>(pId);
-
- ASSERT(!pNew->pLock);
- ASSERT(!pNew->pOpen);
-
- pNew->h = h;
- pNew->dirfd = dirfd;
-
- int rc = SQLITE_OK;
- const sqlite3_io_methods* pLockingStyle;
- if (noLock)
- pLockingStyle = &nolockIoMethods;
- else {
- pLockingStyle = &posixIoMethods;
- rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
- if (rc != SQLITE_OK) {
- // If an error occured in findLockInfo(), close the file descriptor
- // immediately. This can happen in two scenarios:
- //
- // (a) A call to fstat() failed.
- // (b) A malloc failed.
- //
- // Scenario (b) may only occur if the process is holding no other
- // file descriptors open on the same file. If there were other file
- // descriptors on this file, then no malloc would be required by
- // findLockInfo(). If this is the case, it is quite safe to close
- // handle h - as it is guaranteed that no posix locks will be released
- // by doing so.
- //
- // If scenario (a) caused the error then things are not so safe. The
- // implicit assumption here is that if fstat() fails, things are in
- // such bad shape that dropping a lock or two doesn't matter much.
- close(h);
- h = -1;
- }
- }
-
- pNew->lastErrno = 0;
- if (rc != SQLITE_OK) {
- if (dirfd >= 0)
- close(dirfd);
- if (h >= 0)
- close(h);
- } else
- pNew->pMethod = pLockingStyle;
- return rc;
-}
-
-// Searches for an unused file descriptor that was opened on the database
-// file identified by zPath with matching flags. Returns 0 if not found.
-static ChromiumUnusedFd* findReusableFd(const char* zPath, int flags)
-{
- ChromiumUnusedFd* pUnused = 0;
-
- struct stat sStat;
- if (!stat(zPath, &sStat)) {
- ChromiumFileId id;
- id.dev = sStat.st_dev;
- id.ino = sStat.st_ino;
-
- ChromiumOpenInfo* pO = 0;
- for (pO = openList; pO && memcmp(&id, &pO->fileId, sizeof(id)); pO = pO->pNext) { }
- if (pO) {
- ChromiumUnusedFd** pp;
- for (pp = &pO->pUnused; *pp && (*pp)->flags != flags; pp = &((*pp)->pNext)) { }
- pUnused = *pp;
- if (pUnused)
- *pp = pUnused->pNext;
- }
- }
- return pUnused;
-}
+// Chromium's Posix implementation of SQLite VFS
+namespace {
// Opens a file.
//
@@ -974,26 +59,14 @@ static ChromiumUnusedFd* findReusableFd(const char* zPath, int flags)
// id - the structure that will manipulate the newly opened file.
// desiredFlags - the desired open mode flags.
// usedFlags - the actual open mode flags that were used.
-static int chromiumOpen(sqlite3_vfs* vfs, const char* fileName,
- sqlite3_file* id, int desiredFlags, int* usedFlags)
+int chromiumOpen(sqlite3_vfs* vfs, const char* fileName,
+ sqlite3_file* id, int desiredFlags, int* usedFlags)
{
- // The mask 0x00007F00 gives us the 7 bits that determine the type of the file SQLite is trying to open.
- int fileType = desiredFlags & 0x00007F00;
-
- memset(id, 0, sizeof(ChromiumFile));
- ChromiumFile* chromiumFile = reinterpret_cast<ChromiumFile*>(id);
+ chromium_sqlite3_initialize_unix_sqlite3_file(id);
int fd = -1;
- if (fileType == SQLITE_OPEN_MAIN_DB) {
- ChromiumUnusedFd* unusedFd = findReusableFd(fileName, desiredFlags);
- if (unusedFd)
- fd = unusedFd->fd;
- else {
- unusedFd = static_cast<ChromiumUnusedFd*>(sqlite3_malloc(sizeof(*unusedFd)));
- if (!unusedFd)
- return SQLITE_NOMEM;
- }
- chromiumFile->pUnused = unusedFd;
- }
+ int result = chromium_sqlite3_get_reusable_file_handle(id, fileName, desiredFlags, &fd);
+ if (result != SQLITE_OK)
+ return result;
if (fd < 0) {
fd = PlatformBridge::databaseOpenFile(fileName, desiredFlags);
@@ -1003,24 +76,23 @@ static int chromiumOpen(sqlite3_vfs* vfs, const char* fileName,
}
}
if (fd < 0) {
- sqlite3_free(chromiumFile->pUnused);
+ chromium_sqlite3_destroy_reusable_file_handle(id);
return SQLITE_CANTOPEN;
}
if (usedFlags)
*usedFlags = desiredFlags;
- if (chromiumFile->pUnused) {
- chromiumFile->pUnused->fd = fd;
- chromiumFile->pUnused->flags = desiredFlags;
- }
+ chromium_sqlite3_update_reusable_file_handle(id, fd, desiredFlags);
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+ // The mask 0x00007F00 gives us the 7 bits that determine the type of the file SQLite is trying to open.
+ int fileType = desiredFlags & 0x00007F00;
int noLock = (fileType != SQLITE_OPEN_MAIN_DB);
- int rc = fillInChromiumFile(vfs, fd, -1, id, fileName, noLock);
- if (rc != SQLITE_OK)
- sqlite3_free(chromiumFile->pUnused);
- return rc;
+ result = chromium_sqlite3_fill_in_unix_sqlite3_file(vfs, fd, -1, id, fileName, noLock);
+ if (result != SQLITE_OK)
+ chromium_sqlite3_destroy_reusable_file_handle(id);
+ return result;
}
// Deletes the given file.
@@ -1029,7 +101,7 @@ static int chromiumOpen(sqlite3_vfs* vfs, const char* fileName,
// fileName - the name of the file.
// syncDir - determines if the directory to which this file belongs
// should be synched after the file is deleted.
-static int chromiumDelete(sqlite3_vfs*, const char* fileName, int syncDir)
+int chromiumDelete(sqlite3_vfs*, const char* fileName, int syncDir)
{
return PlatformBridge::databaseDeleteFile(fileName, syncDir);
}
@@ -1040,7 +112,7 @@ static int chromiumDelete(sqlite3_vfs*, const char* fileName, int syncDir)
// fileName - the name of the file.
// flag - the type of test to make on this file.
// res - the result.
-static int chromiumAccess(sqlite3_vfs*, const char* fileName, int flag, int* res)
+int chromiumAccess(sqlite3_vfs*, const char* fileName, int flag, int* res)
{
int attr = static_cast<int>(PlatformBridge::databaseGetFileAttributes(fileName));
if (attr < 0) {
@@ -1050,7 +122,7 @@ static int chromiumAccess(sqlite3_vfs*, const char* fileName, int flag, int* res
switch (flag) {
case SQLITE_ACCESS_EXISTS:
- *res = 1; // if the file doesn't exist, attr < 0
+ *res = 1; // if the file doesn't exist, attr < 0
break;
case SQLITE_ACCESS_READWRITE:
*res = (attr & W_OK) && (attr & R_OK);
@@ -1071,8 +143,8 @@ static int chromiumAccess(sqlite3_vfs*, const char* fileName, int flag, int* res
// relativePath - the relative path.
// bufSize - the size of the output buffer in bytes.
// absolutePath - the output buffer where the absolute path will be stored.
-static int chromiumFullPathname(sqlite3_vfs* vfs, const char* relativePath,
- int, char* absolutePath)
+int chromiumFullPathname(sqlite3_vfs* vfs, const char* relativePath,
+ int, char* absolutePath)
{
// The renderer process doesn't need to know the absolute path of the file
sqlite3_snprintf(vfs->mxPathname, absolutePath, "%s", relativePath);
@@ -1080,107 +152,44 @@ static int chromiumFullPathname(sqlite3_vfs* vfs, const char* relativePath,
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
-// We disallow loading DSOs inside the renderer process, so the following procedures are no-op.
-static void* chromiumDlOpen(sqlite3_vfs*, const char*)
-{
- return 0;
-}
-
-static void chromiumDlError(sqlite3_vfs*, int, char*)
-{
-}
-
-static void (*chromiumDlSym(sqlite3_vfs*, void*, const char*))()
+// Returns NULL, thus disallowing loading libraries in the renderer process.
+//
+// vfs - pointer to the sqlite3_vfs object.
+// fileName - the name of the shared library file.
+void* chromiumDlOpen(sqlite3_vfs*, const char*)
{
return 0;
}
-
-static void chromiumDlClose(sqlite3_vfs*, void*)
-{
-}
#else
#define chromiumDlOpen 0
-#define chromiumDlError 0
-#define chromiumDlSym 0
-#define chromiumDlClose 0
#endif // SQLITE_OMIT_LOAD_EXTENSION
-// Generates a seed for SQLite's PRNG.
-static int chromiumRandomness(sqlite3_vfs*, int nBuf, char *zBuf)
-{
- ASSERT(static_cast<size_t>(nBuf) >= (sizeof(time_t) + sizeof(int)));
-
- memset(zBuf, 0, nBuf);
- int fd = open("/dev/urandom", O_RDONLY);
- if (fd < 0) {
- time_t t;
- time(&t);
- memcpy(zBuf, &t, sizeof(t));
- int pid = getpid();
- memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
- return sizeof(t) + sizeof(pid);
- }
- nBuf = read(fd, zBuf, nBuf);
- close(fd);
- return nBuf;
-}
-
-// Sleeps for at least |microseconds|, and returns the actual
-// amount of time spent sleeping (in microseconds).
-static int chromiumSleep(sqlite3_vfs*, int microseconds)
-{
-#if OS(DARWIN)
- usleep(microseconds);
- return microseconds;
-#else
- // Round to the nearest second.
- int seconds = (microseconds + 999999) / 1000000;
- sleep(seconds);
- return seconds * 1000000;
-#endif
-}
-
-// Retrieves the current system time (UTC).
-static int chromiumCurrentTime(sqlite3_vfs*, double* now)
-{
- struct timeval timeval;
- gettimeofday(&timeval, 0);
- *now = 2440587.5 + timeval.tv_sec / 86400.0 + timeval.tv_usec / 86400000000.0;
- return 0;
-}
-
-// This is not yet implemented in SQLite core.
-static int chromiumGetLastError(sqlite3_vfs*, int, char*)
-{
- return 0;
-}
-
-// Same as MAX_PATHNAME from sqlite's os_unix.c.
-static const int chromiumMaxPathname = 512;
+} // namespace
namespace WebCore {
void SQLiteFileSystem::registerSQLiteVFS()
{
+ sqlite3_vfs* unix_vfs = sqlite3_vfs_find("unix");
static sqlite3_vfs chromium_vfs = {
1,
- sizeof(ChromiumFile),
- chromiumMaxPathname,
+ unix_vfs->szOsFile,
+ unix_vfs->mxPathname,
0,
"chromium_vfs",
- 0,
+ unix_vfs->pAppData,
chromiumOpen,
chromiumDelete,
chromiumAccess,
chromiumFullPathname,
chromiumDlOpen,
- chromiumDlError,
- chromiumDlSym,
- chromiumDlClose,
- chromiumRandomness,
- chromiumSleep,
- chromiumCurrentTime,
- chromiumGetLastError
+ unix_vfs->xDlError,
+ unix_vfs->xDlSym,
+ unix_vfs->xDlClose,
+ unix_vfs->xRandomness,
+ unix_vfs->xSleep,
+ unix_vfs->xCurrentTime,
+ unix_vfs->xGetLastError
};
sqlite3_vfs_register(&chromium_vfs, 0);
}
diff --git a/Source/WebCore/platform/text/Base64.cpp b/Source/WebCore/platform/text/Base64.cpp
index 98b537a..bf706f6 100644
--- a/Source/WebCore/platform/text/Base64.cpp
+++ b/Source/WebCore/platform/text/Base64.cpp
@@ -60,9 +60,11 @@ static const char base64DecMap[128] = {
0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00
};
-void base64Encode(const Vector<char>& in, Vector<char>& out, bool insertLFs)
+String base64Encode(const char* data, unsigned length, bool insertLFs)
{
- base64Encode(in.data(), in.size(), out, insertLFs);
+ Vector<char> result;
+ base64Encode(data, length, result, insertLFs);
+ return String(result.data(), result.size());
}
void base64Encode(const char* data, unsigned len, Vector<char>& out, bool insertLFs)
diff --git a/Source/WebCore/platform/text/Base64.h b/Source/WebCore/platform/text/Base64.h
index 211bd3c..70855de 100644
--- a/Source/WebCore/platform/text/Base64.h
+++ b/Source/WebCore/platform/text/Base64.h
@@ -27,20 +27,45 @@
#ifndef Base64_h
#define Base64_h
-#include <wtf/Forward.h>
#include <wtf/Vector.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
namespace WebCore {
enum Base64DecodePolicy { FailOnInvalidCharacter, IgnoreWhitespace, IgnoreInvalidCharacters };
-void base64Encode(const Vector<char>&, Vector<char>&, bool insertLFs = false);
void base64Encode(const char*, unsigned, Vector<char>&, bool insertLFs = false);
+void base64Encode(const Vector<char>&, Vector<char>&, bool insertLFs = false);
+void base64Encode(const CString&, Vector<char>&, bool insertLFs = false);
+String base64Encode(const char*, unsigned, bool insertLFs = false);
+String base64Encode(const Vector<char>&, bool insertLFs = false);
+String base64Encode(const CString&, bool insertLFs = false);
bool base64Decode(const String&, Vector<char>&, Base64DecodePolicy = FailOnInvalidCharacter);
bool base64Decode(const Vector<char>&, Vector<char>&, Base64DecodePolicy = FailOnInvalidCharacter);
bool base64Decode(const char*, unsigned, Vector<char>&, Base64DecodePolicy = FailOnInvalidCharacter);
+inline void base64Encode(const Vector<char>& in, Vector<char>& out, bool insertLFs)
+{
+ base64Encode(in.data(), in.size(), out, insertLFs);
}
+inline void base64Encode(const CString& in, Vector<char>& out, bool insertLFs)
+{
+ base64Encode(in.data(), in.length(), out, insertLFs);
+}
+
+inline String base64Encode(const Vector<char>& in, bool insertLFs)
+{
+ return base64Encode(in.data(), in.size(), insertLFs);
+}
+
+inline String base64Encode(const CString& in, bool insertLFs)
+{
+ return base64Encode(in.data(), in.length(), insertLFs);
+}
+
+} // namespace WebCore
+
#endif // Base64_h
diff --git a/Source/WebCore/platform/text/BidiResolver.h b/Source/WebCore/platform/text/BidiResolver.h
index 8abd698..72d163c 100644
--- a/Source/WebCore/platform/text/BidiResolver.h
+++ b/Source/WebCore/platform/text/BidiResolver.h
@@ -161,7 +161,7 @@ public :
MidpointState<Iterator>& midpointState() { return m_midpointState; }
void embed(WTF::Unicode::Direction);
- void commitExplicitEmbedding();
+ bool commitExplicitEmbedding();
void createBidiRunsForLine(const Iterator& end, bool visualOrder = false, bool hardLineBreak = false);
@@ -400,7 +400,7 @@ void BidiResolver<Iterator, Run>::raiseExplicitEmbeddingLevel(WTF::Unicode::Dire
}
template <class Iterator, class Run>
-void BidiResolver<Iterator, Run>::commitExplicitEmbedding()
+bool BidiResolver<Iterator, Run>::commitExplicitEmbedding()
{
using namespace WTF::Unicode;
@@ -440,6 +440,8 @@ void BidiResolver<Iterator, Run>::commitExplicitEmbedding()
setContext(toContext);
m_currentExplicitEmbeddingSequence.clear();
+
+ return fromLevel != toLevel;
}
template <class Iterator, class Run>
@@ -881,8 +883,8 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, boo
increment();
if (!m_currentExplicitEmbeddingSequence.isEmpty()) {
- commitExplicitEmbedding();
- if (pastEnd) {
+ bool committed = commitExplicitEmbedding();
+ if (committed && pastEnd) {
current = end;
m_status = stateAtEnd.m_status;
sor = stateAtEnd.sor;
diff --git a/Source/WebCore/platform/text/CharacterNames.h b/Source/WebCore/platform/text/CharacterNames.h
deleted file mode 100644
index c4b496e..0000000
--- a/Source/WebCore/platform/text/CharacterNames.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2007, 2009, 2010 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CharacterNames_h
-#define CharacterNames_h
-
-#include <wtf/unicode/Unicode.h>
-
-namespace WebCore {
-
-// Names here are taken from the Unicode standard.
-
-// Most of these are UChar constants, not UChar32, which makes them
-// more convenient for WebCore code that mostly uses UTF-16.
-
-const UChar32 aegeanWordSeparatorLine = 0x10100;
-const UChar32 aegeanWordSeparatorDot = 0x10101;
-const UChar blackCircle = 0x25CF;
-const UChar blackSquare = 0x25A0;
-const UChar blackUpPointingTriangle = 0x25B2;
-const UChar bullet = 0x2022;
-const UChar bullseye = 0x25CE;
-const UChar carriageReturn = 0x000D;
-const UChar ethiopicPrefaceColon = 0x1366;
-const UChar ethiopicWordspace = 0x1361;
-const UChar fisheye = 0x25C9;
-const UChar hebrewPunctuationGeresh = 0x05F3;
-const UChar hebrewPunctuationGershayim = 0x05F4;
-const UChar horizontalEllipsis = 0x2026;
-const UChar hyphen = 0x2010;
-const UChar hyphenMinus = 0x002D;
-const UChar ideographicComma = 0x3001;
-const UChar ideographicFullStop = 0x3002;
-const UChar ideographicSpace = 0x3000;
-const UChar leftDoubleQuotationMark = 0x201C;
-const UChar leftSingleQuotationMark = 0x2018;
-const UChar leftToRightEmbed = 0x202A;
-const UChar leftToRightMark = 0x200E;
-const UChar leftToRightOverride = 0x202D;
-const UChar minusSign = 0x2212;
-const UChar newlineCharacter = 0x000A;
-const UChar noBreakSpace = 0x00A0;
-const UChar objectReplacementCharacter = 0xFFFC;
-const UChar popDirectionalFormatting = 0x202C;
-const UChar replacementCharacter = 0xFFFD;
-const UChar rightDoubleQuotationMark = 0x201D;
-const UChar rightSingleQuotationMark = 0x2019;
-const UChar rightToLeftEmbed = 0x202B;
-const UChar rightToLeftMark = 0x200F;
-const UChar rightToLeftOverride = 0x202E;
-const UChar sesameDot = 0xFE45;
-const UChar softHyphen = 0x00AD;
-const UChar space = 0x0020;
-const UChar tibetanMarkIntersyllabicTsheg = 0x0F0B;
-const UChar tibetanMarkDelimiterTshegBstar = 0x0F0C;
-const UChar32 ugariticWordDivider = 0x1039F;
-const UChar whiteBullet = 0x25E6;
-const UChar whiteCircle = 0x25CB;
-const UChar whiteSesameDot = 0xFE46;
-const UChar whiteUpPointingTriangle = 0x25B3;
-const UChar yenSign = 0x00A5;
-const UChar zeroWidthJoiner = 0x200D;
-const UChar zeroWidthNonJoiner = 0x200C;
-const UChar zeroWidthSpace = 0x200B;
-
-}
-
-#endif // CharacterNames_h
diff --git a/Source/WebCore/platform/graphics/chromium/IconChromiumMac.cpp b/Source/WebCore/platform/text/LocalizedNumber.h
index a24afb2..45873b8 100644
--- a/Source/WebCore/platform/graphics/chromium/IconChromiumMac.cpp
+++ b/Source/WebCore/platform/text/LocalizedNumber.h
@@ -1,10 +1,10 @@
/*
- * Copyright (c) 2008, 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
* met:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -28,23 +28,32 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config.h"
-#include "Icon.h"
+#ifndef LocalizedNumber_h
+#define LocalizedNumber_h
-#include "PassRefPtr.h"
+#include <wtf/text/WTFString.h>
-// FIXME: These are temporary stubs, we need real implementations which
-// may come in the form of IconChromium.cpp. The Windows Chromium
-// implementation is currently in IconWin.cpp.
-
namespace WebCore {
-Icon::~Icon()
-{
-}
+// Parses a string representation of a floating point number localized
+// for the browser's current locale. If the input string is not valid
+// or an implementation doesn't support localized numbers, this
+// function returns NaN. This function doesn't need to support
+// scientific notation, NaN, +Infinity and -Infinity, and doesn't need
+// to support the standard representations of ECMAScript and HTML5.
+double parseLocalizedNumber(const String&);
-void Icon::paint(GraphicsContext*, const IntRect&)
-{
-}
+// Serializes the specified floating point number for the browser's
+// current locale. If an implementation doesn't support localized
+// numbers or the input value is NaN or Infinitiy, the function should
+// return an empty string.
+String formatLocalizedNumber(double);
-}
+// Returns true if the input character can be used to represent a
+// number in the browser locale. For example, this should return true for 0-9 .
+// , + - for en-US locale.
+bool isLocalizedNumberCharacter(UChar32);
+
+} // namespace WebCore
+
+#endif // LocalizedNumber_h
diff --git a/Source/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp b/Source/WebCore/platform/text/LocalizedNumberNone.cpp
index 16f55e2..6f017e9 100644
--- a/Source/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp
+++ b/Source/WebCore/platform/text/LocalizedNumberNone.cpp
@@ -1,10 +1,10 @@
/*
- * 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
* met:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -29,26 +29,27 @@
*/
#include "config.h"
-#include "Icon.h"
+#include "LocalizedNumber.h"
-#include "GraphicsContext.h"
-#include "NotImplemented.h"
-#include "PlatformString.h"
+#include <limits>
+
+using namespace std;
namespace WebCore {
-Icon::Icon(const PlatformIcon& icon)
- : m_icon(icon)
+double parseLocalizedNumber(const String&)
{
+ return numeric_limits<double>::quiet_NaN();
}
-Icon::~Icon()
+String formatLocalizedNumber(double)
{
+ return String();
}
-void Icon::paint(GraphicsContext*, const IntRect&)
+bool isLocalizedNumberCharacter(UChar32)
{
- notImplemented();
+ return false;
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/text/RegularExpression.cpp b/Source/WebCore/platform/text/RegularExpression.cpp
index 9b063c9..e020b91 100644
--- a/Source/WebCore/platform/text/RegularExpression.cpp
+++ b/Source/WebCore/platform/text/RegularExpression.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2004, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2008 Collabora Ltd.
+ * Copyright (C) 2011 Peter Varga (pvarga@webkit.org), University of Szeged
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,52 +28,48 @@
#include "config.h"
#include "RegularExpression.h"
+#include <wtf/BumpPointerAllocator.h>
+#include <yarr/Yarr.h>
#include "Logging.h"
-#include <pcre/pcre.h>
namespace WebCore {
class RegularExpression::Private : public RefCounted<RegularExpression::Private> {
public:
- static PassRefPtr<Private> create(const String& pattern, TextCaseSensitivity);
- ~Private();
+ static PassRefPtr<Private> create(const String& pattern, TextCaseSensitivity caseSensitivity)
+ {
+ return adoptRef(new Private(pattern, caseSensitivity));
+ }
- JSRegExp* regexp() const { return m_regexp; }
- int lastMatchLength;
+ int lastMatchLength;
-private:
- Private(const String& pattern, TextCaseSensitivity);
- static JSRegExp* compile(const String& pattern, TextCaseSensitivity);
+ unsigned m_numSubpatterns;
+ OwnPtr<JSC::Yarr::BytecodePattern> m_regExpByteCode;
- JSRegExp* m_regexp;
-};
+private:
+ Private(const String& pattern, TextCaseSensitivity caseSensitivity)
+ : lastMatchLength(-1)
+ , m_regExpByteCode(compile(pattern, caseSensitivity))
+ , m_constructionError(0)
+ {
+ }
-inline JSRegExp* RegularExpression::Private::compile(const String& pattern, TextCaseSensitivity caseSensitivity)
-{
- const char* errorMessage;
- JSRegExp* regexp = jsRegExpCompile(pattern.characters(), pattern.length(),
- caseSensitivity == TextCaseSensitive ? JSRegExpDoNotIgnoreCase : JSRegExpIgnoreCase, JSRegExpSingleLine,
- 0, &errorMessage);
- if (!regexp)
- LOG_ERROR("RegularExpression: pcre_compile failed with '%s'", errorMessage);
- return regexp;
-}
+ PassOwnPtr<JSC::Yarr::BytecodePattern> compile(const String& patternString, TextCaseSensitivity caseSensitivity)
+ {
+ JSC::Yarr::YarrPattern pattern(JSC::UString(patternString.impl()), (caseSensitivity == TextCaseInsensitive), false, &m_constructionError);
+ if (m_constructionError) {
+ LOG_ERROR("RegularExpression: YARR compile failed with '%s'", m_constructionError);
+ return PassOwnPtr<JSC::Yarr::BytecodePattern>();
+ }
-inline RegularExpression::Private::Private(const String& pattern, TextCaseSensitivity caseSensitivity)
- : lastMatchLength(-1)
- , m_regexp(compile(pattern, caseSensitivity))
-{
-}
+ m_numSubpatterns = pattern.m_numSubpatterns;
-inline PassRefPtr<RegularExpression::Private> RegularExpression::Private::create(const String& pattern, TextCaseSensitivity caseSensitivity)
-{
- return adoptRef(new Private(pattern, caseSensitivity));
-}
+ return JSC::Yarr::byteCompile(pattern, &m_regexAllocator);
+ }
-RegularExpression::Private::~Private()
-{
- jsRegExpFree(m_regexp);
-}
+ BumpPointerAllocator m_regexAllocator;
+ const char* m_constructionError;
+};
RegularExpression::RegularExpression(const String& pattern, TextCaseSensitivity caseSensitivity)
: d(Private::create(pattern, caseSensitivity))
@@ -96,28 +93,36 @@ RegularExpression& RegularExpression::operator=(const RegularExpression& re)
int RegularExpression::match(const String& str, int startFrom, int* matchLength) const
{
- if (!d->regexp())
+ if (!d->m_regExpByteCode)
return -1;
if (str.isNull())
return -1;
- // First 2 offsets are start and end offsets; 3rd entry is used internally by pcre
- static const size_t maxOffsets = 3;
- int offsets[maxOffsets];
- int result = jsRegExpExecute(d->regexp(), str.characters(), str.length(), startFrom, offsets, maxOffsets);
+ int offsetVectorSize = (d->m_numSubpatterns + 1) * 2;
+ int* offsetVector;
+ Vector<int, 32> nonReturnedOvector;
+
+ nonReturnedOvector.resize(offsetVectorSize);
+ offsetVector = nonReturnedOvector.data();
+
+ ASSERT(offsetVector);
+ for (unsigned j = 0, i = 0; i < d->m_numSubpatterns + 1; j += 2, i++)
+ offsetVector[j] = -1;
+
+ int result = JSC::Yarr::interpret(d->m_regExpByteCode.get(), str.characters(), startFrom, str.length(), offsetVector);
+ ASSERT(result >= -1);
+
if (result < 0) {
- if (result != JSRegExpErrorNoMatch)
- LOG_ERROR("RegularExpression: pcre_exec() failed with result %d", result);
d->lastMatchLength = -1;
return -1;
}
- // 1 means 1 match; 0 means more than one match. First match is recorded in offsets.
- d->lastMatchLength = offsets[1] - offsets[0];
+ // 1 means 1 match; 0 means more than one match. First match is recorded in offsetVector.
+ d->lastMatchLength = offsetVector[1] - offsetVector[0];
if (matchLength)
*matchLength = d->lastMatchLength;
- return offsets[0];
+ return offsetVector[0];
}
int RegularExpression::searchRev(const String& str) const
diff --git a/Source/WebCore/platform/text/SegmentedString.cpp b/Source/WebCore/platform/text/SegmentedString.cpp
index 5e9755b..7c859dc 100644
--- a/Source/WebCore/platform/text/SegmentedString.cpp
+++ b/Source/WebCore/platform/text/SegmentedString.cpp
@@ -186,17 +186,6 @@ void SegmentedString::advanceSubstring()
}
}
-int SegmentedString::numberOfCharactersConsumedSlow() const
-{
- int result = m_numberOfCharactersConsumedPriorToCurrentString + m_currentString.numberOfCharactersConsumed();
- if (m_pushedChar1) {
- --result;
- if (m_pushedChar2)
- --result;
- }
- return result;
-}
-
String SegmentedString::toString() const
{
String result;
@@ -262,14 +251,14 @@ WTF::ZeroBasedNumber SegmentedString::currentLine() const
WTF::ZeroBasedNumber SegmentedString::currentColumn() const
{
- int zeroBasedColumn = numberOfCharactersConsumedSlow() - m_numberOfCharactersConsumedPriorToCurrentLine;
+ int zeroBasedColumn = numberOfCharactersConsumed() - m_numberOfCharactersConsumedPriorToCurrentLine;
return WTF::ZeroBasedNumber::fromZeroBasedInt(zeroBasedColumn);
}
void SegmentedString::setCurrentPosition(WTF::ZeroBasedNumber line, WTF::ZeroBasedNumber columnAftreProlog, int prologLength)
{
m_currentLine = line.zeroBasedInt();
- m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumedSlow() + prologLength - columnAftreProlog.zeroBasedInt();
+ m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + prologLength - columnAftreProlog.zeroBasedInt();
}
}
diff --git a/Source/WebCore/platform/text/SegmentedString.h b/Source/WebCore/platform/text/SegmentedString.h
index 30c899d..3784b50 100644
--- a/Source/WebCore/platform/text/SegmentedString.h
+++ b/Source/WebCore/platform/text/SegmentedString.h
@@ -206,13 +206,15 @@ public:
int numberOfCharactersConsumed() const
{
- // We don't currently handle the case when there are pushed character.
- ASSERT(!m_pushedChar1);
- return m_numberOfCharactersConsumedPriorToCurrentString + m_currentString.numberOfCharactersConsumed();
+ int numberOfPushedCharacters = 0;
+ if (m_pushedChar1) {
+ ++numberOfPushedCharacters;
+ if (m_pushedChar2)
+ ++numberOfPushedCharacters;
+ }
+ return m_numberOfCharactersConsumedPriorToCurrentString + m_currentString.numberOfCharactersConsumed() - numberOfPushedCharacters;
}
- int numberOfCharactersConsumedSlow() const;
-
String toString() const;
const UChar& operator*() const { return *current(); }
diff --git a/Source/WebCore/platform/text/TextCodecICU.cpp b/Source/WebCore/platform/text/TextCodecICU.cpp
index 6a579f9..92a158a 100644
--- a/Source/WebCore/platform/text/TextCodecICU.cpp
+++ b/Source/WebCore/platform/text/TextCodecICU.cpp
@@ -27,7 +27,6 @@
#include "config.h"
#include "TextCodecICU.h"
-#include "CharacterNames.h"
#include "PlatformString.h"
#include "ThreadGlobalData.h"
#include <unicode/ucnv.h>
@@ -37,6 +36,7 @@
#include <wtf/PassOwnPtr.h>
#include <wtf/StringExtras.h>
#include <wtf/Threading.h>
+#include <wtf/unicode/CharacterNames.h>
using std::min;
diff --git a/Source/WebCore/platform/text/TextCodecUTF16.cpp b/Source/WebCore/platform/text/TextCodecUTF16.cpp
index e88e83b..4ceed23 100644
--- a/Source/WebCore/platform/text/TextCodecUTF16.cpp
+++ b/Source/WebCore/platform/text/TextCodecUTF16.cpp
@@ -71,6 +71,8 @@ String TextCodecUTF16::decode(const char* bytes, size_t length, bool, bool, bool
if (!length)
return String();
+ // FIXME: This should generate an error if there is an unpaired surrogate.
+
const unsigned char* p = reinterpret_cast<const unsigned char*>(bytes);
size_t numBytes = length + m_haveBufferedByte;
size_t numChars = numBytes / 2;
diff --git a/Source/WebCore/platform/text/TextCodecUTF8.cpp b/Source/WebCore/platform/text/TextCodecUTF8.cpp
new file mode 100644
index 0000000..8944d68
--- /dev/null
+++ b/Source/WebCore/platform/text/TextCodecUTF8.cpp
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2004, 2006, 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 COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "TextCodecUTF8.h"
+
+#include <wtf/text/CString.h>
+#include <wtf/text/StringBuffer.h>
+#include <wtf/unicode/UTF8.h>
+
+using namespace WTF::Unicode;
+using namespace std;
+
+namespace WebCore {
+
+// Assuming that a pointer is the size of a "machine word", then
+// uintptr_t is an integer type that is also a machine word.
+typedef uintptr_t MachineWord;
+
+// This constant has type uintptr_t since we will use it to align
+// pointers. Not because MachineWord is uintptr_t.
+const uintptr_t machineWordAlignmentMask = sizeof(MachineWord) - 1;
+
+template<size_t size> struct NonASCIIMask;
+template<> struct NonASCIIMask<4> {
+ static unsigned value() { return 0x80808080U; }
+};
+template<> struct NonASCIIMask<8> {
+ static unsigned long long value() { return 0x8080808080808080ULL; }
+};
+
+template<size_t size> struct UCharByteFiller;
+template<> struct UCharByteFiller<4> {
+ static void copy(UChar* destination, const uint8_t* source)
+ {
+ destination[0] = source[0];
+ destination[1] = source[1];
+ destination[2] = source[2];
+ destination[3] = source[3];
+ }
+};
+template<> struct UCharByteFiller<8> {
+ static void copy(UChar* destination, const uint8_t* source)
+ {
+ destination[0] = source[0];
+ destination[1] = source[1];
+ destination[2] = source[2];
+ destination[3] = source[3];
+ destination[4] = source[4];
+ destination[5] = source[5];
+ destination[6] = source[6];
+ destination[7] = source[7];
+ }
+};
+
+static inline bool isAlignedToMachineWord(const void* pointer)
+{
+ return !(reinterpret_cast<uintptr_t>(pointer) & machineWordAlignmentMask);
+}
+
+template<typename T> static inline T* alignToMachineWord(T* pointer)
+{
+ return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(pointer) & ~machineWordAlignmentMask);
+}
+
+PassOwnPtr<TextCodec> TextCodecUTF8::create(const TextEncoding&, const void*)
+{
+ return adoptPtr(new TextCodecUTF8);
+}
+
+void TextCodecUTF8::registerEncodingNames(EncodingNameRegistrar registrar)
+{
+ registrar("UTF-8", "UTF-8");
+}
+
+void TextCodecUTF8::registerCodecs(TextCodecRegistrar registrar)
+{
+ registrar("UTF-8", create, 0);
+}
+
+static inline int nonASCIISequenceLength(unsigned char firstByte)
+{
+ ASSERT(!isASCII(firstByte));
+ switch (firstByte >> 4) {
+ case 0xF:
+ return 4;
+ case 0xE:
+ return 3;
+ }
+ return 2;
+}
+
+static inline int decodeNonASCIISequence(const unsigned char* sequence, unsigned length)
+{
+ ASSERT(!isASCII(sequence[0]));
+ if (length == 2) {
+ ASSERT(sequence[0] <= 0xDF);
+ if (sequence[0] < 0xC2)
+ return -1;
+ if (sequence[1] < 0x80 || sequence[1] > 0xBF)
+ return -1;
+ return ((sequence[0] << 6) + sequence[1]) - 0x00003080;
+ }
+ if (length == 3) {
+ ASSERT(sequence[0] >= 0xE0 && sequence[0] <= 0xEF);
+ switch (sequence[0]) {
+ case 0xE0:
+ if (sequence[1] < 0xA0 || sequence[1] > 0xBF)
+ return -1;
+ break;
+ case 0xED:
+ if (sequence[1] < 0x80 || sequence[1] > 0x9F)
+ return -1;
+ break;
+ default:
+ if (sequence[1] < 0x80 || sequence[1] > 0xBF)
+ return -1;
+ }
+ if (sequence[2] < 0x80 || sequence[2] > 0xBF)
+ return -1;
+ return ((sequence[0] << 12) + (sequence[1] << 6) + sequence[2]) - 0x000E2080;
+ }
+ ASSERT(length == 4);
+ ASSERT(sequence[0] >= 0xF0 && sequence[0] <= 0xF4);
+ switch (sequence[0]) {
+ case 0xF0:
+ if (sequence[1] < 0x90 || sequence[1] > 0xBF)
+ return -1;
+ break;
+ case 0xF4:
+ if (sequence[1] < 0x80 || sequence[1] > 0x8F)
+ return -1;
+ break;
+ default:
+ if (sequence[1] < 0x80 || sequence[1] > 0xBF)
+ return -1;
+ }
+ if (sequence[2] < 0x80 || sequence[2] > 0xBF)
+ return -1;
+ if (sequence[3] < 0x80 || sequence[3] > 0xBF)
+ return -1;
+ return ((sequence[0] << 18) + (sequence[1] << 12) + (sequence[2] << 6) + sequence[3]) - 0x03C82080;
+}
+
+String TextCodecUTF8::decode(const char* bytes, size_t length, bool flush, bool stopOnError, bool& sawError)
+{
+ StringBuffer buffer(length);
+
+ const uint8_t* source = reinterpret_cast<const uint8_t*>(bytes);
+ const uint8_t* end = source + length;
+ const uint8_t* alignedEnd = alignToMachineWord(end);
+ UChar* destination = buffer.characters();
+
+ int count;
+ int character;
+
+ if (m_partialSequenceSize) {
+ count = nonASCIISequenceLength(m_partialSequence[0]);
+ ASSERT(count > m_partialSequenceSize);
+ if (count - m_partialSequenceSize > end - source) {
+ memcpy(m_partialSequence + m_partialSequenceSize, source, end - source);
+ m_partialSequenceSize += end - source;
+ source = end;
+ } else {
+ uint8_t completeSequence[U8_MAX_LENGTH];
+ memcpy(completeSequence, m_partialSequence, m_partialSequenceSize);
+ memcpy(completeSequence + m_partialSequenceSize, source, count - m_partialSequenceSize);
+ source += count - m_partialSequenceSize;
+ m_partialSequenceSize = 0;
+ character = decodeNonASCIISequence(completeSequence, count);
+ goto decodedNonASCII;
+ }
+ }
+
+ while (source < end) {
+ if (isASCII(*source)) {
+ // Fast path for ASCII. Most UTF-8 text will be ASCII.
+ if (isAlignedToMachineWord(source)) {
+ while (source < alignedEnd) {
+ MachineWord chunk = *reinterpret_cast_ptr<const MachineWord*>(source);
+ if (chunk & NonASCIIMask<sizeof(MachineWord)>::value()) {
+ if (isASCII(*source))
+ break;
+ goto nonASCII;
+ }
+ UCharByteFiller<sizeof(MachineWord)>::copy(destination, source);
+ source += sizeof(MachineWord);
+ destination += sizeof(MachineWord);
+ }
+ if (source == end)
+ break;
+ }
+ *destination++ = *source++;
+ } else {
+nonASCII:
+ count = nonASCIISequenceLength(*source);
+ ASSERT(count >= 2);
+ ASSERT(count <= 4);
+ if (count > end - source) {
+ ASSERT(end - source <= static_cast<ptrdiff_t>(sizeof(m_partialSequence)));
+ ASSERT(!m_partialSequenceSize);
+ m_partialSequenceSize = end - source;
+ memcpy(m_partialSequence, source, m_partialSequenceSize);
+ break;
+ }
+ character = decodeNonASCIISequence(source, count);
+ source += count;
+decodedNonASCII:
+ if (character < 0) {
+ if (stopOnError) {
+ sawError = true;
+ break;
+ }
+ } else {
+ ASSERT(!U_IS_SURROGATE(character));
+ if (U_IS_BMP(character))
+ *destination++ = character;
+ else {
+ *destination++ = U16_LEAD(character);
+ *destination++ = U16_TRAIL(character);
+ }
+ }
+ }
+ }
+
+ buffer.shrink(destination - buffer.characters());
+
+ if (flush && m_partialSequenceSize)
+ sawError = true;
+
+ return String::adopt(buffer);
+}
+
+CString TextCodecUTF8::encode(const UChar* characters, size_t length, UnencodableHandling)
+{
+ // The maximum number of UTF-8 bytes needed per UTF-16 code unit is 3.
+ // BMP characters take only one UTF-16 code unit and can take up to 3 bytes (3x).
+ // Non-BMP characters take two UTF-16 code units and can take up to 4 bytes (2x).
+ if (length > numeric_limits<size_t>::max() / 3)
+ CRASH();
+ Vector<uint8_t> bytes(length * 3);
+
+ size_t i = 0;
+ size_t bytesWritten = 0;
+ while (i < length) {
+ UChar32 character;
+ U16_NEXT(characters, i, length, character);
+ U8_APPEND_UNSAFE(bytes.data(), bytesWritten, character);
+ }
+
+ return CString(reinterpret_cast<char*>(bytes.data()), bytesWritten);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/text/TextCodecUTF8.h b/Source/WebCore/platform/text/TextCodecUTF8.h
new file mode 100644
index 0000000..f3b6b7a
--- /dev/null
+++ b/Source/WebCore/platform/text/TextCodecUTF8.h
@@ -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 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 TextCodecUTF8_h
+#define TextCodecUTF8_h
+
+#include "TextCodec.h"
+
+namespace WebCore {
+
+class TextCodecUTF8 : public TextCodec {
+public:
+ static void registerEncodingNames(EncodingNameRegistrar);
+ static void registerCodecs(TextCodecRegistrar);
+
+ virtual String decode(const char*, size_t length, bool flush, bool stopOnError, bool& sawError);
+ virtual CString encode(const UChar*, size_t length, UnencodableHandling);
+
+private:
+ static PassOwnPtr<TextCodec> create(const TextEncoding&, const void*);
+ TextCodecUTF8() : m_partialSequenceSize(0) { }
+
+ int m_partialSequenceSize;
+ char m_partialSequence[U8_MAX_LENGTH - 1];
+
+};
+
+} // namespace WebCore
+
+#endif // TextCodecUTF8_h
diff --git a/Source/WebCore/platform/text/TextEncodingRegistry.cpp b/Source/WebCore/platform/text/TextEncodingRegistry.cpp
index c0c0255..1dc09ee 100644
--- a/Source/WebCore/platform/text/TextEncodingRegistry.cpp
+++ b/Source/WebCore/platform/text/TextEncodingRegistry.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2011 Apple Inc. All rights reserved.
* Copyright (C) 2007-2009 Torch Mobile, Inc.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,14 +27,12 @@
#include "config.h"
#include "TextEncodingRegistry.h"
-#include "PlatformString.h"
#include "TextCodecLatin1.h"
#include "TextCodecUserDefined.h"
#include "TextCodecUTF16.h"
+#include "TextCodecUTF8.h"
#include "TextEncoding.h"
#include <wtf/ASCIICType.h>
-#include <wtf/Assertions.h>
-#include <wtf/HashFunctions.h>
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/StdLibExtras.h>
@@ -68,7 +66,6 @@ const size_t maxEncodingNameLength = 63;
// Hash for all-ASCII strings that does case folding.
struct TextEncodingNameHash {
-
static bool equal(const char* s1, const char* s2)
{
char c1;
@@ -129,9 +126,7 @@ static bool didExtendTextCodecMaps;
static HashSet<const char*>* japaneseEncodings;
static HashSet<const char*>* nonBackslashEncodings;
-static const char* const textEncodingNameBlacklist[] = {
- "UTF-7"
-};
+static const char* const textEncodingNameBlacklist[] = { "UTF-7" };
#if ERROR_DISABLED
@@ -268,7 +263,7 @@ static void buildQuirksSets()
ASSERT(!japaneseEncodings);
ASSERT(!nonBackslashEncodings);
- japaneseEncodings = new HashSet<const char*>();
+ japaneseEncodings = new HashSet<const char*>;
addEncodingName(japaneseEncodings, "EUC-JP");
addEncodingName(japaneseEncodings, "ISO-2022-JP");
addEncodingName(japaneseEncodings, "ISO-2022-JP-1");
@@ -284,7 +279,7 @@ static void buildQuirksSets()
addEncodingName(japaneseEncodings, "cp932");
addEncodingName(japaneseEncodings, "x-mac-japanese");
- nonBackslashEncodings = new HashSet<const char*>();
+ nonBackslashEncodings = new HashSet<const char*>;
// The text encodings below treat backslash as a currency symbol for IE compatibility.
// See http://blogs.msdn.com/michkap/archive/2005/09/17/469941.aspx for more information.
addEncodingName(nonBackslashEncodings, "x-mac-japanese");
diff --git a/Source/WebCore/platform/text/mac/TextCodecMac.cpp b/Source/WebCore/platform/text/mac/TextCodecMac.cpp
index b743f3d..64d0485 100644
--- a/Source/WebCore/platform/text/mac/TextCodecMac.cpp
+++ b/Source/WebCore/platform/text/mac/TextCodecMac.cpp
@@ -27,15 +27,15 @@
#include "config.h"
#include "TextCodecMac.h"
-#include "CharacterNames.h"
#include "CharsetData.h"
#include "PlatformString.h"
#include "ThreadGlobalData.h"
#include <wtf/Assertions.h>
-#include <wtf/text/CString.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/RetainPtr.h>
#include <wtf/Threading.h>
+#include <wtf/text/CString.h>
+#include <wtf/unicode/CharacterNames.h>
using namespace std;
diff --git a/Source/WebCore/platform/text/transcoder/FontTranscoder.cpp b/Source/WebCore/platform/text/transcoder/FontTranscoder.cpp
index 68601f9..4e07f50 100644
--- a/Source/WebCore/platform/text/transcoder/FontTranscoder.cpp
+++ b/Source/WebCore/platform/text/transcoder/FontTranscoder.cpp
@@ -31,9 +31,9 @@
#include "config.h"
#include "FontTranscoder.h"
-#include "CharacterNames.h"
#include "FontDescription.h"
#include "TextEncoding.h"
+#include <wtf/unicode/CharacterNames.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/win/BString.cpp b/Source/WebCore/platform/win/BString.cpp
index 4d6d11e..6622f96 100644
--- a/Source/WebCore/platform/win/BString.cpp
+++ b/Source/WebCore/platform/win/BString.cpp
@@ -28,9 +28,8 @@
#include "KURL.h"
#include "PlatformString.h"
-#include <wtf/text/AtomicString.h>
-#include <tchar.h>
#include <windows.h>
+#include <wtf/text/AtomicString.h>
#if PLATFORM(CF)
#include <CoreFoundation/CoreFoundation.h>
@@ -102,7 +101,7 @@ BString::BString(CFStringRef cfstr)
const UniChar* uniChars = CFStringGetCharactersPtr(cfstr);
if (uniChars) {
- m_bstr = SysAllocStringLen((LPCTSTR)uniChars, CFStringGetLength(cfstr));
+ m_bstr = SysAllocStringLen((LPCWSTR)uniChars, CFStringGetLength(cfstr));
return;
}
@@ -158,7 +157,7 @@ bool operator ==(const BString& a, const BString& b)
return true;
if (!(BSTR)a || !(BSTR)b)
return false;
- return !_tcscmp((BSTR)a, (BSTR)b);
+ return !wcscmp((BSTR)a, (BSTR)b);
}
bool operator !=(const BString& a, const BString& b)
@@ -174,7 +173,7 @@ bool operator ==(const BString& a, BSTR b)
return true;
if (!(BSTR)a || !b)
return false;
- return !_tcscmp((BSTR)a, b);
+ return !wcscmp((BSTR)a, b);
}
bool operator !=(const BString& a, BSTR b)
@@ -190,7 +189,7 @@ bool operator ==(BSTR a, const BString& b)
return true;
if (!a || !(BSTR)b)
return false;
- return !_tcscmp(a, (BSTR)b);
+ return !wcscmp(a, (BSTR)b);
}
bool operator !=(BSTR a, const BString& b)
diff --git a/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp b/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp
index eb1e659..77b95ef 100644
--- a/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp
+++ b/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp
@@ -31,6 +31,7 @@
#include "PlatformString.h"
#include "TextEncoding.h"
#include "markup.h"
+#include <shlobj.h>
#include <shlwapi.h>
#include <wininet.h> // for INTERNET_MAX_URL_LENGTH
#include <wtf/StringExtras.h>
@@ -70,6 +71,15 @@ static bool urlFromPath(CFStringRef path, String& url)
}
#endif
+static bool getDataMapItem(const DragDataMap* dataObject, FORMATETC* format, String& item)
+{
+ DragDataMap::const_iterator found = dataObject->find(format->cfFormat);
+ if (found == dataObject->end())
+ return false;
+ item = found->second[0];
+ return true;
+}
+
static bool getWebLocData(IDataObject* dataObject, String& url, String* title)
{
bool succeeded = false;
@@ -111,6 +121,34 @@ exit:
return succeeded;
}
+static bool getWebLocData(const DragDataMap* dataObject, String& url, String* title)
+{
+#if PLATFORM(CF)
+ WCHAR filename[MAX_PATH];
+ WCHAR urlBuffer[INTERNET_MAX_URL_LENGTH];
+
+ if (!dataObject->contains(cfHDropFormat()->cfFormat))
+ return false;
+
+ wcscpy(filename, dataObject->get(cfHDropFormat()->cfFormat)[0].characters());
+ if (_wcsicmp(PathFindExtensionW(filename), L".url"))
+ return false;
+
+ if (!GetPrivateProfileStringW(L"InternetShortcut", L"url", 0, urlBuffer, WTF_ARRAY_LENGTH(urlBuffer), filename))
+ return false;
+
+ if (title) {
+ PathRemoveExtension(filename);
+ *title = filename;
+ }
+
+ url = urlBuffer;
+ return true;
+#else
+ return false;
+#endif
+}
+
static String extractURL(const String &inURL, String* title)
{
String url = inURL;
@@ -386,6 +424,33 @@ String getURL(IDataObject* dataObject, DragData::FilenameConversionPolicy filena
return url;
}
+String getURL(const DragDataMap* data, DragData::FilenameConversionPolicy filenamePolicy, String* title)
+{
+ String url;
+
+ if (getWebLocData(data, url, title))
+ return url;
+ if (getDataMapItem(data, urlWFormat(), url))
+ return extractURL(url, title);
+ if (getDataMapItem(data, urlFormat(), url))
+ return extractURL(url, title);
+#if PLATFORM(CF)
+ if (filenamePolicy != DragData::ConvertFilenames)
+ return url;
+
+ String stringData;
+ if (!getDataMapItem(data, filenameWFormat(), stringData))
+ getDataMapItem(data, filenameFormat(), stringData);
+
+ if (stringData.isEmpty() || (!PathFileExists(stringData.charactersWithNullTermination()) && !PathIsUNC(stringData.charactersWithNullTermination())))
+ return url;
+ RetainPtr<CFStringRef> pathAsCFString(AdoptCF, CFStringCreateWithCharacters(kCFAllocatorDefault, (const UniChar *)stringData.charactersWithNullTermination(), stringData.length()));
+ if (urlFromPath(pathAsCFString.get(), url) && title)
+ *title = url;
+#endif
+ return url;
+}
+
String getPlainText(IDataObject* dataObject, bool& success)
{
STGMEDIUM store;
@@ -415,6 +480,17 @@ String getPlainText(IDataObject* dataObject, bool& success)
return text;
}
+String getPlainText(const DragDataMap* data)
+{
+ String text;
+
+ if (getDataMapItem(data, plainTextWFormat(), text))
+ return text;
+ if (getDataMapItem(data, plainTextFormat(), text))
+ return text;
+ return getURL(data, DragData::DoNotConvertFilenames);
+}
+
String getTextHTML(IDataObject* data, bool& success)
{
STGMEDIUM store;
@@ -430,6 +506,13 @@ String getTextHTML(IDataObject* data, bool& success)
return html;
}
+String getTextHTML(const DragDataMap* data)
+{
+ String text;
+ getDataMapItem(data, texthtmlFormat(), text);
+ return text;
+}
+
String getCFHTML(IDataObject* data, bool& success)
{
String cfhtml = getFullCFHTML(data, success);
@@ -438,18 +521,37 @@ String getCFHTML(IDataObject* data, bool& success)
return String();
}
+String getCFHTML(const DragDataMap* dataMap)
+{
+ String cfhtml;
+ getDataMapItem(dataMap, htmlFormat(), cfhtml);
+ return extractMarkupFromCFHTML(cfhtml);
+}
+
PassRefPtr<DocumentFragment> fragmentFromFilenames(Document*, const IDataObject*)
{
// FIXME: We should be able to create fragments from files
return 0;
}
+PassRefPtr<DocumentFragment> fragmentFromFilenames(Document*, const DragDataMap*)
+{
+ // FIXME: We should be able to create fragments from files
+ return 0;
+}
+
bool containsFilenames(const IDataObject*)
{
// FIXME: We'll want to update this once we can produce fragments from files
return false;
}
+bool containsFilenames(const DragDataMap*)
+{
+ // FIXME: We'll want to update this once we can produce fragments from files
+ return false;
+}
+
// Convert a String containing CF_HTML formatted text to a DocumentFragment
PassRefPtr<DocumentFragment> fragmentFromCFHTML(Document* doc, const String& cfhtml)
{
@@ -477,8 +579,8 @@ PassRefPtr<DocumentFragment> fragmentFromHTML(Document* doc, IDataObject* data)
bool success = false;
String cfhtml = getFullCFHTML(data, success);
if (success) {
- if (PassRefPtr<DocumentFragment> fragment = fragmentFromCFHTML(doc, cfhtml))
- return fragment;
+ if (RefPtr<DocumentFragment> fragment = fragmentFromCFHTML(doc, cfhtml))
+ return fragment.release();
}
String html = getTextHTML(data, success);
@@ -489,9 +591,180 @@ PassRefPtr<DocumentFragment> fragmentFromHTML(Document* doc, IDataObject* data)
return 0;
}
+PassRefPtr<DocumentFragment> fragmentFromHTML(Document* document, const DragDataMap* data)
+{
+ if (!document || !data || data->isEmpty())
+ return 0;
+
+ String stringData;
+ if (getDataMapItem(data, htmlFormat(), stringData)) {
+ if (RefPtr<DocumentFragment> fragment = fragmentFromCFHTML(document, stringData))
+ return fragment.release();
+ }
+
+ String srcURL;
+ if (getDataMapItem(data, texthtmlFormat(), stringData))
+ return createFragmentFromMarkup(document, stringData, srcURL, FragmentScriptingNotAllowed);
+
+ return 0;
+}
+
bool containsHTML(IDataObject* data)
{
return SUCCEEDED(data->QueryGetData(texthtmlFormat())) || SUCCEEDED(data->QueryGetData(htmlFormat()));
}
+bool containsHTML(const DragDataMap* data)
+{
+ return data->contains(texthtmlFormat()->cfFormat) || data->contains(htmlFormat()->cfFormat);
+}
+
+typedef void (*GetStringFunction)(IDataObject*, FORMATETC*, Vector<String>&);
+typedef void (*SetStringFunction)(IDataObject*, FORMATETC*, const Vector<String>&);
+
+struct ClipboardDataItem {
+ GetStringFunction getString;
+ SetStringFunction setString;
+ FORMATETC* format;
+
+ ClipboardDataItem(FORMATETC* format, GetStringFunction getString, SetStringFunction setString): format(format), getString(getString), setString(setString) { }
+};
+
+typedef HashMap<UINT, ClipboardDataItem*> ClipboardFormatMap;
+
+// Getter functions.
+
+template<typename T> void getStringData(IDataObject* data, FORMATETC* format, Vector<String>& dataStrings)
+{
+ STGMEDIUM store;
+ if (FAILED(data->GetData(format, &store)))
+ return;
+ dataStrings.append(String(static_cast<T*>(GlobalLock(store.hGlobal)), ::GlobalSize(store.hGlobal) / sizeof(T)));
+ GlobalUnlock(store.hGlobal);
+ ReleaseStgMedium(&store);
+}
+
+void getUtf8Data(IDataObject* data, FORMATETC* format, Vector<String>& dataStrings)
+{
+ STGMEDIUM store;
+ if (FAILED(data->GetData(format, &store)))
+ return;
+ dataStrings.append(String(UTF8Encoding().decode(static_cast<char*>(GlobalLock(store.hGlobal)), GlobalSize(store.hGlobal))));
+ GlobalUnlock(store.hGlobal);
+ ReleaseStgMedium(&store);
+}
+
+#if PLATFORM(CF)
+void getCFData(IDataObject* data, FORMATETC* format, Vector<String>& dataStrings)
+{
+ STGMEDIUM store;
+ if (FAILED(data->GetData(format, &store)))
+ return;
+
+ HDROP hdrop = reinterpret_cast<HDROP>(GlobalLock(store.hGlobal));
+ if (!hdrop)
+ return;
+
+ WCHAR filename[MAX_PATH];
+ UINT fileCount = DragQueryFileW(hdrop, 0xFFFFFFFF, 0, 0);
+ for (UINT i = 0; i < fileCount; i++) {
+ if (!DragQueryFileW(hdrop, i, filename, WTF_ARRAY_LENGTH(filename)))
+ continue;
+ dataStrings.append(static_cast<UChar*>(filename));
+ }
+
+ GlobalUnlock(store.hGlobal);
+ ReleaseStgMedium(&store);
+}
+#endif
+
+// Setter functions.
+
+void setUCharData(IDataObject* data, FORMATETC* format, const Vector<String>& dataStrings)
+{
+ STGMEDIUM medium = {0};
+ medium.tymed = TYMED_HGLOBAL;
+
+ medium.hGlobal = createGlobalData(dataStrings.first());
+ if (!medium.hGlobal)
+ return;
+ data->SetData(format, &medium, FALSE);
+ ::GlobalFree(medium.hGlobal);
+}
+
+void setUtf8Data(IDataObject* data, FORMATETC* format, const Vector<String>& dataStrings)
+{
+ STGMEDIUM medium = {0};
+ medium.tymed = TYMED_HGLOBAL;
+
+ CString charString = dataStrings.first().utf8();
+ size_t stringLength = charString.length();
+ medium.hGlobal = ::GlobalAlloc(GPTR, stringLength + 1);
+ if (!medium.hGlobal)
+ return;
+ char* buffer = static_cast<char*>(GlobalLock(medium.hGlobal));
+ memcpy(buffer, charString.data(), stringLength);
+ buffer[stringLength] = 0;
+ GlobalUnlock(medium.hGlobal);
+ data->SetData(format, &medium, FALSE);
+ ::GlobalFree(medium.hGlobal);
+}
+
+#if PLATFORM(CF)
+void setCFData(IDataObject* data, FORMATETC* format, const Vector<String>& dataStrings)
+{
+ STGMEDIUM medium = {0};
+ SIZE_T dropFilesSize = sizeof(DROPFILES) + (sizeof(WCHAR) * (dataStrings.first().length() + 2));
+ medium.hGlobal = ::GlobalAlloc(GHND | GMEM_SHARE, dropFilesSize);
+ if (!medium.hGlobal)
+ return;
+
+ DROPFILES* dropFiles = reinterpret_cast<DROPFILES *>(GlobalLock(medium.hGlobal));
+ dropFiles->pFiles = sizeof(DROPFILES);
+ dropFiles->fWide = TRUE;
+ String filename = dataStrings.first();
+ wcscpy(reinterpret_cast<LPWSTR>(dropFiles + 1), filename.charactersWithNullTermination());
+ GlobalUnlock(medium.hGlobal);
+ data->SetData(format, &medium, FALSE);
+ ::GlobalFree(medium.hGlobal);
+}
+#endif
+
+static const ClipboardFormatMap& getClipboardMap()
+{
+ static ClipboardFormatMap formatMap;
+ if (formatMap.isEmpty()) {
+ formatMap.add(htmlFormat()->cfFormat, new ClipboardDataItem(htmlFormat(), getUtf8Data, setUtf8Data));
+ formatMap.add(texthtmlFormat()->cfFormat, new ClipboardDataItem(texthtmlFormat(), getStringData<UChar>, setUCharData));
+ formatMap.add(plainTextFormat()->cfFormat, new ClipboardDataItem(plainTextFormat(), getStringData<char>, setUtf8Data));
+ formatMap.add(plainTextWFormat()->cfFormat, new ClipboardDataItem(plainTextWFormat(), getStringData<UChar>, setUCharData));
+#if PLATFORM(CF)
+ formatMap.add(cfHDropFormat()->cfFormat, new ClipboardDataItem(cfHDropFormat(), getCFData, setCFData));
+#endif
+ formatMap.add(filenameFormat()->cfFormat, new ClipboardDataItem(filenameFormat(), getStringData<char>, setUtf8Data));
+ formatMap.add(filenameWFormat()->cfFormat, new ClipboardDataItem(filenameWFormat(), getStringData<UChar>, setUCharData));
+ formatMap.add(urlFormat()->cfFormat, new ClipboardDataItem(urlFormat(), getStringData<char>, setUtf8Data));
+ formatMap.add(urlWFormat()->cfFormat, new ClipboardDataItem(urlWFormat(), getStringData<UChar>, setUCharData));
+ }
+ return formatMap;
+}
+
+void getClipboardData(IDataObject* dataObject, FORMATETC* format, Vector<String>& dataStrings)
+{
+ const ClipboardFormatMap& formatMap = getClipboardMap();
+ ClipboardFormatMap::const_iterator found = formatMap.find(format->cfFormat);
+ if (found == formatMap.end())
+ return;
+ found->second->getString(dataObject, found->second->format, dataStrings);
+}
+
+void setClipboardData(IDataObject* dataObject, UINT format, const Vector<String>& dataStrings)
+{
+ const ClipboardFormatMap& formatMap = getClipboardMap();
+ ClipboardFormatMap::const_iterator found = formatMap.find(format);
+ if (found == formatMap.end())
+ return;
+ found->second->setString(dataObject, found->second->format, dataStrings);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/win/ClipboardUtilitiesWin.h b/Source/WebCore/platform/win/ClipboardUtilitiesWin.h
index 1a29e7e..36508d4 100644
--- a/Source/WebCore/platform/win/ClipboardUtilitiesWin.h
+++ b/Source/WebCore/platform/win/ClipboardUtilitiesWin.h
@@ -55,16 +55,27 @@ void replaceNewlinesWithWindowsStyleNewlines(String&);
void replaceNBSPWithSpace(String&);
bool containsFilenames(const IDataObject*);
+bool containsFilenames(const DragDataMap*);
bool containsHTML(IDataObject*);
+bool containsHTML(const DragDataMap*);
PassRefPtr<DocumentFragment> fragmentFromFilenames(Document*, const IDataObject*);
+PassRefPtr<DocumentFragment> fragmentFromFilenames(Document*, const DragDataMap*);
PassRefPtr<DocumentFragment> fragmentFromHTML(Document*, IDataObject*);
+PassRefPtr<DocumentFragment> fragmentFromHTML(Document*, const DragDataMap*);
PassRefPtr<DocumentFragment> fragmentFromCFHTML(Document*, const String& cfhtml);
String getURL(IDataObject*, DragData::FilenameConversionPolicy, bool& success, String* title = 0);
+String getURL(const DragDataMap*, DragData::FilenameConversionPolicy, String* title = 0);
String getPlainText(IDataObject*, bool& success);
+String getPlainText(const DragDataMap*);
String getTextHTML(IDataObject*, bool& success);
+String getTextHTML(const DragDataMap*);
String getCFHTML(IDataObject*, bool& success);
+String getCFHTML(const DragDataMap*);
+
+void getClipboardData(IDataObject*, FORMATETC* fetc, Vector<String>& dataStrings);
+void setClipboardData(IDataObject*, UINT format, const Vector<String>& dataStrings);
} // namespace WebCore
diff --git a/Source/WebCore/platform/win/ClipboardWin.cpp b/Source/WebCore/platform/win/ClipboardWin.cpp
index 58cfe44..c0af712 100644
--- a/Source/WebCore/platform/win/ClipboardWin.cpp
+++ b/Source/WebCore/platform/win/ClipboardWin.cpp
@@ -115,7 +115,7 @@ static inline void pathRemoveBadFSCharacters(PWSTR psz, size_t length)
}
#endif
-static String filesystemPathFromUrlOrTitle(const String& url, const String& title, TCHAR* extension, bool isLink)
+static String filesystemPathFromUrlOrTitle(const String& url, const String& title, const UChar* extension, bool isLink)
{
#if OS(WINCE)
notImplemented();
@@ -163,7 +163,7 @@ static String filesystemPathFromUrlOrTitle(const String& url, const String& titl
}
String result(static_cast<UChar*>(fsPathBuffer));
- result += String(static_cast<UChar*>(extension));
+ result += String(extension);
return result;
#endif
}
@@ -195,7 +195,7 @@ static HGLOBAL createGlobalHDropContent(const KURL& url, String& fileName, Share
// windows does not enjoy a leading slash on paths
if (localPath[0] == '/')
localPath = localPath.substring(1);
- LPCTSTR localPathStr = localPath.charactersWithNullTermination();
+ LPCWSTR localPathStr = localPath.charactersWithNullTermination();
if (wcslen(localPathStr) + 1 < MAX_PATH)
wcscpy_s(filePath, MAX_PATH, localPathStr);
else
@@ -277,7 +277,7 @@ static HGLOBAL createGlobalImageFileDescriptor(const String& url, const String&
return 0;
}
extension.insert(".", 0);
- fsPath = filesystemPathFromUrlOrTitle(url, preferredTitle, (TCHAR*)extension.charactersWithNullTermination(), false);
+ fsPath = filesystemPathFromUrlOrTitle(url, preferredTitle, extension.charactersWithNullTermination(), false);
if (fsPath.length() <= 0) {
GlobalUnlock(memObj);
@@ -340,7 +340,9 @@ exit:
PassRefPtr<Clipboard> Clipboard::create(ClipboardAccessPolicy policy, DragData* dragData, Frame* frame)
{
- return ClipboardWin::create(DragAndDrop, dragData->platformData(), policy, frame);
+ if (dragData->platformData())
+ return ClipboardWin::create(DragAndDrop, dragData->platformData(), policy, frame);
+ return ClipboardWin::create(DragAndDrop, dragData->dragDataMap(), policy, frame);
}
ClipboardWin::ClipboardWin(ClipboardType clipboardType, IDataObject* dataObject, ClipboardAccessPolicy policy, Frame* frame)
@@ -359,6 +361,15 @@ ClipboardWin::ClipboardWin(ClipboardType clipboardType, WCDataObject* dataObject
{
}
+ClipboardWin::ClipboardWin(ClipboardType clipboardType, const DragDataMap& dataMap, ClipboardAccessPolicy policy, Frame* frame)
+ : Clipboard(policy, clipboardType)
+ , m_dataObject(0)
+ , m_writableDataObject(0)
+ , m_frame(frame)
+ , m_dragDataMap(dataMap)
+{
+}
+
ClipboardWin::~ClipboardWin()
{
}
@@ -442,19 +453,19 @@ void ClipboardWin::clearAllData()
String ClipboardWin::getData(const String& type, bool& success) const
{
success = false;
- if (policy() != ClipboardReadable || !m_dataObject)
+ if (policy() != ClipboardReadable || (!m_dataObject && m_dragDataMap.isEmpty()))
return "";
ClipboardDataType dataType = clipboardTypeFromMIMEType(type);
if (dataType == ClipboardDataTypeText)
- return getPlainText(m_dataObject.get(), success);
+ return m_dataObject ? getPlainText(m_dataObject.get(), success) : getPlainText(&m_dragDataMap);
if (dataType == ClipboardDataTypeURL)
- return getURL(m_dataObject.get(), DragData::DoNotConvertFilenames, success);
+ return m_dataObject ? getURL(m_dataObject.get(), DragData::DoNotConvertFilenames, success) : getURL(&m_dragDataMap, DragData::DoNotConvertFilenames);
else if (dataType == ClipboardDataTypeTextHTML) {
- String data = getTextHTML(m_dataObject.get(), success);
+ String data = m_dataObject ? getTextHTML(m_dataObject.get(), success) : getTextHTML(&m_dragDataMap);
if (success)
return data;
- return getCFHTML(m_dataObject.get(), success);
+ return m_dataObject ? getCFHTML(m_dataObject.get(), success) : getCFHTML(&m_dragDataMap);
}
return "";
@@ -510,22 +521,30 @@ HashSet<String> ClipboardWin::types() const
if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable)
return results;
- if (!m_dataObject)
+ if (!m_dataObject && m_dragDataMap.isEmpty())
return results;
- COMPtr<IEnumFORMATETC> itr;
+ if (m_dataObject) {
+ COMPtr<IEnumFORMATETC> itr;
- if (FAILED(m_dataObject->EnumFormatEtc(DATADIR_GET, &itr)))
- return results;
+ if (FAILED(m_dataObject->EnumFormatEtc(DATADIR_GET, &itr)))
+ return results;
- if (!itr)
- return results;
+ if (!itr)
+ return results;
- FORMATETC data;
+ FORMATETC data;
- // IEnumFORMATETC::Next returns S_FALSE if there are no more items.
- while (itr->Next(1, &data, 0) == S_OK)
- addMimeTypesForFormat(results, data);
+ // IEnumFORMATETC::Next returns S_FALSE if there are no more items.
+ while (itr->Next(1, &data, 0) == S_OK)
+ addMimeTypesForFormat(results, data);
+ } else {
+ for (DragDataMap::const_iterator it = m_dragDataMap.begin(); it != m_dragDataMap.end(); ++it) {
+ FORMATETC data;
+ data.cfFormat = (*it).first;
+ addMimeTypesForFormat(results, data);
+ }
+ }
return results;
}
@@ -540,27 +559,35 @@ PassRefPtr<FileList> ClipboardWin::files() const
if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable)
return files.release();
- if (!m_dataObject)
+ if (!m_dataObject && m_dragDataMap.isEmpty())
return files.release();
- STGMEDIUM medium;
- if (FAILED(m_dataObject->GetData(cfHDropFormat(), &medium)))
- return files.release();
+ if (m_dataObject) {
+ STGMEDIUM medium;
+ if (FAILED(m_dataObject->GetData(cfHDropFormat(), &medium)))
+ return files.release();
+
+ HDROP hdrop = reinterpret_cast<HDROP>(GlobalLock(medium.hGlobal));
+ if (!hdrop)
+ return files.release();
+
+ WCHAR filename[MAX_PATH];
+ UINT fileCount = DragQueryFileW(hdrop, 0xFFFFFFFF, 0, 0);
+ for (UINT i = 0; i < fileCount; i++) {
+ if (!DragQueryFileW(hdrop, i, filename, WTF_ARRAY_LENGTH(filename)))
+ continue;
+ files->append(File::create(reinterpret_cast<UChar*>(filename)));
+ }
- HDROP hdrop = reinterpret_cast<HDROP>(GlobalLock(medium.hGlobal));
- if (!hdrop)
+ GlobalUnlock(medium.hGlobal);
+ ReleaseStgMedium(&medium);
return files.release();
-
- WCHAR filename[MAX_PATH];
- UINT fileCount = DragQueryFileW(hdrop, 0xFFFFFFFF, 0, 0);
- for (UINT i = 0; i < fileCount; i++) {
- if (!DragQueryFileW(hdrop, i, filename, WTF_ARRAY_LENGTH(filename)))
- continue;
- files->append(File::create(reinterpret_cast<UChar*>(filename)));
}
-
- GlobalUnlock(medium.hGlobal);
- ReleaseStgMedium(&medium);
+ if (!m_dragDataMap.contains(cfHDropFormat()->cfFormat))
+ return files.release();
+ Vector<String> filesVector = m_dragDataMap.get(cfHDropFormat()->cfFormat);
+ for (Vector<String>::iterator it = filesVector.begin(); it != filesVector.end(); ++it)
+ files->append(File::create((*it).characters()));
return files.release();
#endif
}
@@ -778,25 +805,28 @@ void ClipboardWin::writePlainText(const String& text)
bool ClipboardWin::hasData()
{
- if (!m_dataObject)
+ if (!m_dataObject && m_dragDataMap.isEmpty())
return false;
- COMPtr<IEnumFORMATETC> itr;
- if (FAILED(m_dataObject->EnumFormatEtc(DATADIR_GET, &itr)))
- return false;
+ if (m_dataObject) {
+ COMPtr<IEnumFORMATETC> itr;
+ if (FAILED(m_dataObject->EnumFormatEtc(DATADIR_GET, &itr)))
+ return false;
- if (!itr)
- return false;
+ if (!itr)
+ return false;
- FORMATETC data;
+ FORMATETC data;
- // IEnumFORMATETC::Next returns S_FALSE if there are no more items.
- if (itr->Next(1, &data, 0) == S_OK) {
- // There is at least one item in the IDataObject
- return true;
- }
+ // IEnumFORMATETC::Next returns S_FALSE if there are no more items.
+ if (itr->Next(1, &data, 0) == S_OK) {
+ // There is at least one item in the IDataObject
+ return true;
+ }
- return false;
+ return false;
+ }
+ return !m_dragDataMap.isEmpty();
}
void ClipboardWin::setExternalDataObject(IDataObject *dataObject)
diff --git a/Source/WebCore/platform/win/ClipboardWin.h b/Source/WebCore/platform/win/ClipboardWin.h
index 779da26..7530eeb 100644
--- a/Source/WebCore/platform/win/ClipboardWin.h
+++ b/Source/WebCore/platform/win/ClipboardWin.h
@@ -29,6 +29,7 @@
#include "COMPtr.h"
#include "CachedResourceClient.h"
#include "Clipboard.h"
+#include "DragData.h"
struct IDataObject;
@@ -51,6 +52,10 @@ public:
{
return adoptRef(new ClipboardWin(clipboardType, dataObject, policy, frame));
}
+ static PassRefPtr<ClipboardWin> create(ClipboardType clipboardType, const DragDataMap& dataMap, ClipboardAccessPolicy policy, Frame* frame)
+ {
+ return adoptRef(new ClipboardWin(clipboardType, dataMap, policy, frame));
+ }
~ClipboardWin();
void clearData(const String& type);
@@ -80,12 +85,14 @@ public:
private:
ClipboardWin(ClipboardType, IDataObject*, ClipboardAccessPolicy, Frame*);
ClipboardWin(ClipboardType, WCDataObject*, ClipboardAccessPolicy, Frame*);
+ ClipboardWin(ClipboardType, const DragDataMap&, ClipboardAccessPolicy, Frame*);
void resetFromClipboard();
void setDragImage(CachedImage*, Node*, const IntPoint&);
COMPtr<IDataObject> m_dataObject;
COMPtr<WCDataObject> m_writableDataObject;
+ DragDataMap m_dragDataMap;
Frame* m_frame;
};
diff --git a/Source/WebCore/platform/win/ContextMenuWin.cpp b/Source/WebCore/platform/win/ContextMenuWin.cpp
index ed1b895..dad0f2e 100644
--- a/Source/WebCore/platform/win/ContextMenuWin.cpp
+++ b/Source/WebCore/platform/win/ContextMenuWin.cpp
@@ -31,7 +31,6 @@
#include "FrameView.h"
#include "Node.h"
#include "NotImplemented.h"
-#include <tchar.h>
#include <windows.h>
#include <wtf/Vector.h>
#include <wtf/text/CString.h>
@@ -73,7 +72,7 @@ void ContextMenu::getContextMenuItems(HMENU menu, Vector<ContextMenuItem>& items
}
int menuStringLength = info.cch + 1;
- OwnArrayPtr<WCHAR> menuString(new WCHAR[menuStringLength]);
+ OwnArrayPtr<WCHAR> menuString = adoptArrayPtr(new WCHAR[menuStringLength]);
info.dwTypeData = menuString.get();
info.cch = menuStringLength;
diff --git a/Source/WebCore/platform/win/CursorWin.cpp b/Source/WebCore/platform/win/CursorWin.cpp
index 2dd1452..0036388 100644
--- a/Source/WebCore/platform/win/CursorWin.cpp
+++ b/Source/WebCore/platform/win/CursorWin.cpp
@@ -123,9 +123,9 @@ static PassRefPtr<SharedCursor> createSharedCursor(Image* img, const IntPoint& h
return impl.release();
}
-static PassRefPtr<SharedCursor> loadSharedCursor(HINSTANCE hInstance, LPCTSTR lpCursorName)
+static PassRefPtr<SharedCursor> loadSharedCursor(HINSTANCE hInstance, LPCWSTR lpCursorName)
{
- return SharedCursor::create(::LoadCursor(hInstance, lpCursorName));
+ return SharedCursor::create(::LoadCursorW(hInstance, lpCursorName));
}
static PassRefPtr<SharedCursor> loadCursorByName(char* name, int x, int y)
diff --git a/Source/WebCore/platform/win/DragDataWin.cpp b/Source/WebCore/platform/win/DragDataWin.cpp
index 906119d..c5b99ea 100644
--- a/Source/WebCore/platform/win/DragDataWin.cpp
+++ b/Source/WebCore/platform/win/DragDataWin.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "DragData.h"
+#include "COMPtr.h"
#include "ClipboardUtilitiesWin.h"
#include "Frame.h"
#include "DocumentFragment.h"
@@ -35,65 +36,109 @@
#include <objidl.h>
#include <shlwapi.h>
#include <wininet.h>
+#include <wtf/Forward.h>
+#include <wtf/Hashmap.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
namespace WebCore {
+DragData::DragData(const DragDataMap& data, const IntPoint& clientPosition, const IntPoint& globalPosition,
+ DragOperation sourceOperationMask, DragApplicationFlags flags)
+ : m_clientPosition(clientPosition)
+ , m_globalPosition(globalPosition)
+ , m_platformDragData(0)
+ , m_draggingSourceOperationMask(sourceOperationMask)
+ , m_applicationFlags(flags)
+ , m_dragDataMap(data)
+{
+}
+
bool DragData::containsURL(Frame*, FilenameConversionPolicy filenamePolicy) const
{
- return SUCCEEDED(m_platformDragData->QueryGetData(urlWFormat()))
- || SUCCEEDED(m_platformDragData->QueryGetData(urlFormat()))
- || (filenamePolicy == ConvertFilenames
- && (SUCCEEDED(m_platformDragData->QueryGetData(filenameWFormat()))
- || SUCCEEDED(m_platformDragData->QueryGetData(filenameFormat()))));
+ if (m_platformDragData)
+ return SUCCEEDED(m_platformDragData->QueryGetData(urlWFormat()))
+ || SUCCEEDED(m_platformDragData->QueryGetData(urlFormat()))
+ || (filenamePolicy == ConvertFilenames
+ && (SUCCEEDED(m_platformDragData->QueryGetData(filenameWFormat()))
+ || SUCCEEDED(m_platformDragData->QueryGetData(filenameFormat()))));
+ return m_dragDataMap.contains(urlWFormat()->cfFormat) || m_dragDataMap.contains(urlFormat()->cfFormat)
+ || (filenamePolicy == ConvertFilenames && (m_dragDataMap.contains(filenameWFormat()->cfFormat) || m_dragDataMap.contains(filenameFormat()->cfFormat)));
+}
+
+const DragDataMap& DragData::dragDataMap()
+{
+ if (!m_dragDataMap.isEmpty() || !m_platformDragData)
+ return m_dragDataMap;
+ // Enumerate clipboard content and load it in the map.
+ COMPtr<IEnumFORMATETC> itr;
+
+ if (FAILED(m_platformDragData->EnumFormatEtc(DATADIR_GET, &itr)) || !itr)
+ return m_dragDataMap;
+
+ FORMATETC dataFormat;
+ while (itr->Next(1, &dataFormat, 0) == S_OK) {
+ Vector<String> dataStrings;
+ getClipboardData(m_platformDragData, &dataFormat, dataStrings);
+ if (!dataStrings.isEmpty())
+ m_dragDataMap.set(dataFormat.cfFormat, dataStrings);
+ }
+ return m_dragDataMap;
}
String DragData::asURL(Frame*, FilenameConversionPolicy filenamePolicy, String* title) const
{
bool success;
- return getURL(m_platformDragData, filenamePolicy, success, title);
+ return (m_platformDragData) ? getURL(m_platformDragData, filenamePolicy, success, title) : getURL(&m_dragDataMap, filenamePolicy, title);
}
bool DragData::containsFiles() const
{
- return SUCCEEDED(m_platformDragData->QueryGetData(cfHDropFormat()));
+ return (m_platformDragData) ? SUCCEEDED(m_platformDragData->QueryGetData(cfHDropFormat())) : m_dragDataMap.contains(cfHDropFormat()->cfFormat);
}
void DragData::asFilenames(Vector<String>& result) const
{
- WCHAR filename[MAX_PATH];
-
- STGMEDIUM medium;
- if (FAILED(m_platformDragData->GetData(cfHDropFormat(), &medium)))
- return;
-
- HDROP hdrop = (HDROP)GlobalLock(medium.hGlobal);
-
- if (!hdrop)
- return;
+ if (m_platformDragData) {
+ WCHAR filename[MAX_PATH];
+
+ STGMEDIUM medium;
+ if (FAILED(m_platformDragData->GetData(cfHDropFormat(), &medium)))
+ return;
+
+ HDROP hdrop = (HDROP)GlobalLock(medium.hGlobal);
+
+ if (!hdrop)
+ return;
- const unsigned numFiles = DragQueryFileW(hdrop, 0xFFFFFFFF, 0, 0);
- for (unsigned i = 0; i < numFiles; i++) {
- if (!DragQueryFileW(hdrop, 0, filename, WTF_ARRAY_LENGTH(filename)))
- continue;
- result.append((UChar*)filename);
- }
+ const unsigned numFiles = DragQueryFileW(hdrop, 0xFFFFFFFF, 0, 0);
+ for (unsigned i = 0; i < numFiles; i++) {
+ if (!DragQueryFileW(hdrop, 0, filename, WTF_ARRAY_LENGTH(filename)))
+ continue;
+ result.append((UChar*)filename);
+ }
- // Free up memory from drag
- DragFinish(hdrop);
+ // Free up memory from drag
+ DragFinish(hdrop);
- GlobalUnlock(medium.hGlobal);
+ GlobalUnlock(medium.hGlobal);
+ return;
+ }
+ result = m_dragDataMap.get(cfHDropFormat()->cfFormat);
}
bool DragData::containsPlainText() const
{
- return SUCCEEDED(m_platformDragData->QueryGetData(plainTextWFormat()))
- || SUCCEEDED(m_platformDragData->QueryGetData(plainTextFormat()));
+ if (m_platformDragData)
+ return SUCCEEDED(m_platformDragData->QueryGetData(plainTextWFormat()))
+ || SUCCEEDED(m_platformDragData->QueryGetData(plainTextFormat()));
+ return m_dragDataMap.contains(plainTextWFormat()->cfFormat) || m_dragDataMap.contains(plainTextFormat()->cfFormat);
}
String DragData::asPlainText(Frame*) const
{
bool success;
- return getPlainText(m_platformDragData, success);
+ return (m_platformDragData) ? getPlainText(m_platformDragData, success) : getPlainText(&m_dragDataMap);
}
bool DragData::containsColor() const
@@ -103,14 +148,16 @@ bool DragData::containsColor() const
bool DragData::canSmartReplace() const
{
- return SUCCEEDED(m_platformDragData->QueryGetData(smartPasteFormat()));
+ if (m_platformDragData)
+ return SUCCEEDED(m_platformDragData->QueryGetData(smartPasteFormat()));
+ return m_dragDataMap.contains(smartPasteFormat()->cfFormat);
}
bool DragData::containsCompatibleContent() const
{
return containsPlainText() || containsURL(0)
- || containsHTML(m_platformDragData)
- || containsFilenames(m_platformDragData)
+ || ((m_platformDragData) ? (containsHTML(m_platformDragData) || containsFilenames(m_platformDragData))
+ : (containsHTML(&m_dragDataMap) || containsFilenames(&m_dragDataMap)))
|| containsColor();
}
@@ -125,16 +172,29 @@ PassRefPtr<DocumentFragment> DragData::asFragment(Frame* frame, PassRefPtr<Range
* * TIFF
* * PICT
*/
-
- if (containsFilenames(m_platformDragData))
- if (PassRefPtr<DocumentFragment> fragment = fragmentFromFilenames(frame->document(), m_platformDragData))
- return fragment;
-
- if (containsHTML(m_platformDragData))
- if (PassRefPtr<DocumentFragment> fragment = fragmentFromHTML(frame->document(), m_platformDragData))
- return fragment;
-
- return 0;
+
+ if (m_platformDragData) {
+ if (containsFilenames(m_platformDragData)) {
+ if (PassRefPtr<DocumentFragment> fragment = fragmentFromFilenames(frame->document(), m_platformDragData))
+ return fragment;
+ }
+
+ if (containsHTML(m_platformDragData)) {
+ if (PassRefPtr<DocumentFragment> fragment = fragmentFromHTML(frame->document(), m_platformDragData))
+ return fragment;
+ }
+ } else {
+ if (containsFilenames(&m_dragDataMap)) {
+ if (PassRefPtr<DocumentFragment> fragment = fragmentFromFilenames(frame->document(), &m_dragDataMap))
+ return fragment;
+ }
+
+ if (containsHTML(&m_dragDataMap)) {
+ if (PassRefPtr<DocumentFragment> fragment = fragmentFromHTML(frame->document(), &m_dragDataMap))
+ return fragment;
+ }
+ }
+ return 0;
}
Color DragData::asColor() const
@@ -143,4 +203,3 @@ Color DragData::asColor() const
}
}
-
diff --git a/Source/WebCore/platform/win/DragImageWin.cpp b/Source/WebCore/platform/win/DragImageWin.cpp
index 135e9d0..4e5d168 100644
--- a/Source/WebCore/platform/win/DragImageWin.cpp
+++ b/Source/WebCore/platform/win/DragImageWin.cpp
@@ -27,14 +27,25 @@
#include "DragImage.h"
#include "CachedImage.h"
+#include "Font.h"
+#include "FontDescription.h"
+#include "FontSelector.h"
+#include "Frame.h"
#include "GraphicsContext.h"
#include "Image.h"
#include "RetainPtr.h"
+#include "Settings.h"
+#include "StringTruncator.h"
+#include "TextRun.h"
+#include "WebCoreTextRenderer.h"
#include <windows.h>
namespace WebCore {
+HBITMAP allocImage(HDC, IntSize, PlatformGraphicsContext** targetRef);
+void deallocContext(PlatformGraphicsContext* target);
+
IntSize dragImageSize(DragImageRef image)
{
if (!image)
@@ -79,5 +90,141 @@ DragImageRef createDragImageIconForCachedImage(CachedImage* image)
return iconInfo.hbmColor;
}
+
+const float DragLabelBorderX = 4;
+// Keep border_y in synch with DragController::LinkDragBorderInset.
+const float DragLabelBorderY = 2;
+const float DragLabelRadius = 5;
+const float LabelBorderYOffset = 2;
+
+const float MinDragLabelWidthBeforeClip = 120;
+const float MaxDragLabelWidth = 200;
+const float MaxDragLabelStringWidth = (MaxDragLabelWidth - 2 * DragLabelBorderX);
+
+const float DragLinkLabelFontsize = 11;
+const float DragLinkUrlFontSize = 10;
+
+static Font dragLabelFont(int size, bool bold, FontRenderingMode renderingMode)
+{
+ NONCLIENTMETRICS metrics;
+ metrics.cbSize = sizeof(metrics);
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0);
+
+ FontDescription description;
+ description.setWeight(bold ? FontWeightBold : FontWeightNormal);
+
+ FontFamily family;
+ family.setFamily(metrics.lfSmCaptionFont.lfFaceName);
+ description.setFamily(family);
+ description.setSpecifiedSize((float)size);
+ description.setComputedSize((float)size);
+ description.setRenderingMode(renderingMode);
+ Font result = Font(description, 0, 0);
+ result.update(0);
+ return result;
+}
+
+DragImageRef createDragImageForLink(KURL& url, const String& inLabel, Frame* frame)
+{
+ // This is more or less an exact match for the Mac OS X code.
+
+ const Font* labelFont;
+ const Font* urlFont;
+
+ if (frame->settings() && frame->settings()->fontRenderingMode() == AlternateRenderingMode) {
+ static const Font alternateRenderingModeLabelFont = dragLabelFont(DragLinkLabelFontsize, true, AlternateRenderingMode);
+ static const Font alternateRenderingModeURLFont = dragLabelFont(DragLinkUrlFontSize, false, AlternateRenderingMode);
+ labelFont = &alternateRenderingModeLabelFont;
+ urlFont = &alternateRenderingModeURLFont;
+ } else {
+ static const Font normalRenderingModeLabelFont = dragLabelFont(DragLinkLabelFontsize, true, NormalRenderingMode);
+ static const Font normalRenderingModeURLFont = dragLabelFont(DragLinkUrlFontSize, false, NormalRenderingMode);
+ labelFont = &normalRenderingModeLabelFont;
+ urlFont = &normalRenderingModeURLFont;
+ }
+
+ bool drawURLString = true;
+ bool clipURLString = false;
+ bool clipLabelString = false;
+
+ String urlString = url.string();
+ String label = inLabel;
+ if (label.isEmpty()) {
+ drawURLString = false;
+ label = urlString;
+ }
+
+ // First step in drawing the link drag image width.
+ TextRun labelRun(label.impl());
+ TextRun urlRun(urlString.impl());
+ IntSize labelSize(labelFont->width(labelRun), labelFont->fontMetrics().ascent() + labelFont->fontMetrics().descent());
+
+ if (labelSize.width() > MaxDragLabelStringWidth) {
+ labelSize.setWidth(MaxDragLabelStringWidth);
+ clipLabelString = true;
+ }
+
+ IntSize urlStringSize;
+ IntSize imageSize(labelSize.width() + DragLabelBorderX * 2, labelSize.height() + DragLabelBorderY * 2);
+
+ if (drawURLString) {
+ urlStringSize.setWidth(urlFont->width(urlRun));
+ urlStringSize.setHeight(urlFont->fontMetrics().ascent() + urlFont->fontMetrics().descent());
+ imageSize.setHeight(imageSize.height() + urlStringSize.height());
+ if (urlStringSize.width() > MaxDragLabelStringWidth) {
+ imageSize.setWidth(MaxDragLabelWidth);
+ clipURLString = true;
+ } else
+ imageSize.setWidth(std::max(labelSize.width(), urlStringSize.width()) + DragLabelBorderX * 2);
+ }
+
+ // We now know how big the image needs to be, so we create and
+ // fill the background
+ HBITMAP image = 0;
+ HDC dc = GetDC(0);
+ HDC workingDC = CreateCompatibleDC(dc);
+ if (!workingDC) {
+ ReleaseDC(0, dc);
+ return 0;
+ }
+
+ PlatformGraphicsContext* contextRef;
+ image = allocImage(workingDC, imageSize, &contextRef);
+ if (!image) {
+ DeleteDC(workingDC);
+ ReleaseDC(0, dc);
+ return 0;
+ }
+
+ SelectObject(workingDC, image);
+ GraphicsContext context(contextRef);
+ // On Mac alpha is {0.7, 0.7, 0.7, 0.8}, however we can't control alpha
+ // for drag images on win, so we use 1
+ static const Color backgroundColor(140, 140, 140);
+ static const IntSize radii(DragLabelRadius, DragLabelRadius);
+ IntRect rect(0, 0, imageSize.width(), imageSize.height());
+ context.fillRoundedRect(rect, radii, radii, radii, radii, backgroundColor, ColorSpaceDeviceRGB);
+
+ // Draw the text
+ static const Color topColor(0, 0, 0, 255); // original alpha = 0.75
+ static const Color bottomColor(255, 255, 255, 127); // original alpha = 0.5
+ if (drawURLString) {
+ if (clipURLString)
+ urlString = StringTruncator::rightTruncate(urlString, imageSize.width() - (DragLabelBorderX * 2.0f), *urlFont, false);
+ IntPoint textPos(DragLabelBorderX, imageSize.height() - (LabelBorderYOffset + urlFont->fontMetrics().descent()));
+ WebCoreDrawDoubledTextAtPoint(context, urlString, textPos, *urlFont, topColor, bottomColor);
+ }
+ if (clipLabelString)
+ label = StringTruncator::rightTruncate(label, imageSize.width() - (DragLabelBorderX * 2.0f), *labelFont, false);
+
+ IntPoint textPos(DragLabelBorderX, DragLabelBorderY + labelFont->pixelSize());
+ WebCoreDrawDoubledTextAtPoint(context, label, textPos, *labelFont, topColor, bottomColor);
+
+ deallocContext(contextRef);
+ DeleteDC(workingDC);
+ ReleaseDC(0, dc);
+ return image;
+}
+
}
diff --git a/Source/WebCore/platform/win/FileChooserWin.cpp b/Source/WebCore/platform/win/FileChooserWin.cpp
index 7d07b5d..195b8eb 100644
--- a/Source/WebCore/platform/win/FileChooserWin.cpp
+++ b/Source/WebCore/platform/win/FileChooserWin.cpp
@@ -29,7 +29,6 @@
#include "LocalizedStrings.h"
#include "StringTruncator.h"
#include <shlwapi.h>
-#include <tchar.h>
#include <windows.h>
namespace WebCore {
@@ -44,7 +43,7 @@ String FileChooser::basenameForWidth(const Font& font, int width) const
string = fileButtonNoFileSelectedLabel();
else if (m_filenames.size() == 1) {
String tmpFilename = m_filenames[0];
- LPTSTR basename = PathFindFileName(tmpFilename.charactersWithNullTermination());
+ LPWSTR basename = PathFindFileNameW(tmpFilename.charactersWithNullTermination());
string = String(basename);
} else
return StringTruncator::rightTruncate(String::number(m_filenames.size()) + " files", width, font, false);
diff --git a/Source/WebCore/platform/win/LoggingWin.cpp b/Source/WebCore/platform/win/LoggingWin.cpp
index fe237e5..1d051ae 100644
--- a/Source/WebCore/platform/win/LoggingWin.cpp
+++ b/Source/WebCore/platform/win/LoggingWin.cpp
@@ -37,7 +37,7 @@ static inline void initializeWithUserDefault(WTFLogChannel& channel)
if (!length)
return;
- OwnArrayPtr<char> buffer(new char[length]);
+ OwnArrayPtr<char> buffer = adoptArrayPtr(new char[length]);
if (!GetEnvironmentVariableA(channel.defaultName, buffer.get(), length))
return;
diff --git a/Source/WebCore/platform/win/MIMETypeRegistryWin.cpp b/Source/WebCore/platform/win/MIMETypeRegistryWin.cpp
index 980742a..56ddab1 100644
--- a/Source/WebCore/platform/win/MIMETypeRegistryWin.cpp
+++ b/Source/WebCore/platform/win/MIMETypeRegistryWin.cpp
@@ -27,7 +27,9 @@
#include "MIMETypeRegistry.h"
#include <shlwapi.h>
+#include <wtf/Assertions.h>
#include <wtf/HashMap.h>
+#include <wtf/MainThread.h>
namespace WebCore
{
@@ -64,6 +66,8 @@ String MIMETypeRegistry::getPreferredExtensionForMIMEType(const String& type)
String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
{
+ ASSERT(isMainThread());
+
if (ext.isEmpty())
return String();
diff --git a/Source/WebCore/platform/win/PopupMenuWin.cpp b/Source/WebCore/platform/win/PopupMenuWin.cpp
index 15871e6..3f3afa2 100644
--- a/Source/WebCore/platform/win/PopupMenuWin.cpp
+++ b/Source/WebCore/platform/win/PopupMenuWin.cpp
@@ -42,7 +42,6 @@
#include "SimpleFontData.h"
#include "TextRun.h"
#include "WebCoreInstanceHandle.h"
-#include <tchar.h>
#include <windows.h>
#include <windowsx.h>
#if OS(WINCE)
@@ -64,7 +63,7 @@ static const int maxPopupHeight = 320;
const int optionSpacingMiddle = 1;
const int popupWindowBorderWidth = 1;
-static LPCTSTR kPopupWindowClassName = _T("PopupWindowClass");
+static LPCWSTR kPopupWindowClassName = L"PopupWindowClass";
// This is used from within our custom message pump when we want to send a
// message to the web view and not have our message stolen and sent to
@@ -121,7 +120,7 @@ void PopupMenuWin::disconnectClient()
m_popupClient = 0;
}
-LPCTSTR PopupMenuWin::popupClassName()
+LPCWSTR PopupMenuWin::popupClassName()
{
return kPopupWindowClassName;
}
@@ -145,7 +144,7 @@ void PopupMenuWin::show(const IntRect& r, FrameView* view, int index)
DWORD exStyle = WS_EX_LTRREADING;
- m_popup = ::CreateWindowEx(exStyle, kPopupWindowClassName, _T("PopupMenu"),
+ m_popup = ::CreateWindowExW(exStyle, kPopupWindowClassName, L"PopupMenu",
WS_POPUP | WS_BORDER,
m_windowRect.x(), m_windowRect.y(), m_windowRect.width(), m_windowRect.height(),
hostWindow, 0, WebCore::instanceHandle(), this);
@@ -306,7 +305,7 @@ void PopupMenuWin::calculatePositionAndSize(const IntRect& r, FrameView* v)
// First, determine the popup's height
int itemCount = client()->listSize();
- m_itemHeight = client()->menuStyle().font().height() + optionSpacingMiddle;
+ m_itemHeight = client()->menuStyle().font().fontMetrics().height() + optionSpacingMiddle;
int naturalHeight = m_itemHeight * itemCount;
int popupHeight = min(maxPopupHeight, naturalHeight);
// The popup should show an integral number of items (i.e. no partial items should be visible)
@@ -347,13 +346,13 @@ void PopupMenuWin::calculatePositionAndSize(const IntRect& r, FrameView* v)
// Always left-align items in the popup. This matches popup menus on the mac.
int popupX = rScreenCoords.x() + client()->clientInsetLeft();
- IntRect popupRect(popupX, rScreenCoords.bottom(), popupWidth, popupHeight);
+ IntRect popupRect(popupX, rScreenCoords.maxY(), popupWidth, popupHeight);
// The popup needs to stay within the bounds of the screen and not overlap any toolbars
FloatRect screen = screenAvailableRect(v);
// Check that we don't go off the screen vertically
- if (popupRect.bottom() > screen.height()) {
+ if (popupRect.maxY() > screen.height()) {
// The popup will go off the screen, so try placing it above the client
if (rScreenCoords.y() - popupRect.height() < 0) {
// The popup won't fit above, either, so place it whereever's bigger and resize it to fit
@@ -602,7 +601,7 @@ void PopupMenuWin::paint(const IntRect& damageRect, HDC hdc)
IntRect listRect = damageRect;
listRect.move(IntSize(0, m_scrollOffset * m_itemHeight));
- for (int y = listRect.y(); y < listRect.bottom(); y += m_itemHeight) {
+ for (int y = listRect.y(); y < listRect.maxY(); y += m_itemHeight) {
int index = y / m_itemHeight;
Color optionBackgroundColor, optionTextColor;
@@ -632,7 +631,7 @@ void PopupMenuWin::paint(const IntRect& damageRect, HDC hdc)
unsigned length = itemText.length();
const UChar* string = itemText.characters();
- TextRun textRun(string, length, false, 0, 0, itemText.defaultWritingDirection() == WTF::Unicode::RightToLeft);
+ TextRun textRun(string, length, false, 0, 0, TextRun::AllowTrailingExpansion, itemText.defaultWritingDirection() == WTF::Unicode::RightToLeft);
context.setFillColor(optionTextColor, ColorSpaceDeviceRGB);
@@ -649,7 +648,7 @@ void PopupMenuWin::paint(const IntRect& damageRect, HDC hdc)
int textX = max(0, client()->clientPaddingLeft() - client()->clientInsetLeft());
if (RenderTheme::defaultTheme()->popupOptionSupportsTextIndent() && itemStyle.textDirection() == LTR)
textX += itemStyle.textIndent().calcMinValue(itemRect.width());
- int textY = itemRect.y() + itemFont.ascent() + (itemRect.height() - itemFont.height()) / 2;
+ int textY = itemRect.y() + itemFont.fontMetrics().ascent() + (itemRect.height() - itemFont.fontMetrics().height()) / 2;
context.drawBidiText(itemFont, textRun, IntPoint(textX, textY));
}
}
diff --git a/Source/WebCore/platform/win/PopupMenuWin.h b/Source/WebCore/platform/win/PopupMenuWin.h
index 0d7630c..05edb07 100644
--- a/Source/WebCore/platform/win/PopupMenuWin.h
+++ b/Source/WebCore/platform/win/PopupMenuWin.h
@@ -49,7 +49,7 @@ public:
virtual void updateFromElement();
virtual void disconnectClient();
- static LPCTSTR popupClassName();
+ static LPCWSTR popupClassName();
private:
PopupMenuClient* client() const { return m_popupClient; }
diff --git a/Source/WebCore/platform/win/SystemTimeWin.cpp b/Source/WebCore/platform/win/SystemTimeWin.cpp
index 451262d..547decc 100644
--- a/Source/WebCore/platform/win/SystemTimeWin.cpp
+++ b/Source/WebCore/platform/win/SystemTimeWin.cpp
@@ -26,13 +26,9 @@
#include "config.h"
#include "SystemTime.h"
+#include <limits>
#include <windows.h>
-#if COMPILER(MINGW) || (PLATFORM(QT) && COMPILER(MSVC))
-#include <float.h>
-#define FLOAT_MAX FLT_MAX
-#endif
-
namespace WebCore {
float userIdleTime()
@@ -43,7 +39,8 @@ float userIdleTime()
if (::GetLastInputInfo(&lastInputInfo))
return (GetTickCount() - lastInputInfo.dwTime) * 0.001; // ::GetTickCount returns ms of uptime valid for up to 49.7 days.
#endif
- return FLT_MAX; // return an arbitrarily high userIdleTime so that releasing pages from the page cache isn't postponed.
+ // Return an arbitrarily high userIdleTime so that releasing pages from the page cache isn't postponed.
+ return std::numeric_limits<float>::max();
}
-}
+} // namespace WebCore
diff --git a/Source/WebCore/platform/win/WCDataObject.cpp b/Source/WebCore/platform/win/WCDataObject.cpp
index 6b4c859..0c03ce0 100644
--- a/Source/WebCore/platform/win/WCDataObject.cpp
+++ b/Source/WebCore/platform/win/WCDataObject.cpp
@@ -26,6 +26,8 @@
#include "config.h"
#include "WCDataObject.h"
+#include "ClipboardUtilitiesWin.h"
+#include "DragData.h"
#include "PlatformString.h"
namespace WebCore {
@@ -160,6 +162,17 @@ HRESULT WCDataObject::createInstance(WCDataObject** result)
return S_OK;
}
+HRESULT WCDataObject::createInstance(WCDataObject** result, const DragDataMap& dataMap)
+{
+ if (!result)
+ return E_POINTER;
+ *result = new WCDataObject;
+
+ for (DragDataMap::const_iterator it = dataMap.begin(); it != dataMap.end(); ++it)
+ setClipboardData(*result, it->first, it->second);
+ return S_OK;
+}
+
WCDataObject::WCDataObject()
: m_ref(1)
{
@@ -380,5 +393,4 @@ void WCDataObject::clearData(CLIPFORMAT format)
}
}
-
}
diff --git a/Source/WebCore/platform/win/WCDataObject.h b/Source/WebCore/platform/win/WCDataObject.h
index 133115d..e5fa298 100644
--- a/Source/WebCore/platform/win/WCDataObject.h
+++ b/Source/WebCore/platform/win/WCDataObject.h
@@ -26,10 +26,11 @@
#ifndef WCDataObject_h
#define WCDataObject_h
-#include <wtf/Forward.h>
-#include <wtf/Vector.h>
+#include "DragData.h"
#include <ShlObj.h>
#include <objidl.h>
+#include <wtf/Forward.h>
+#include <wtf/Vector.h>
namespace WebCore {
@@ -56,6 +57,7 @@ public:
void clearData(CLIPFORMAT);
static HRESULT createInstance(WCDataObject**);
+ static HRESULT createInstance(WCDataObject**, const DragDataMap&);
private:
WCDataObject();
virtual ~WCDataObject();
diff --git a/Source/WebCore/platform/wince/DragDataWinCE.cpp b/Source/WebCore/platform/wince/DragDataWinCE.cpp
index 8f531c7..679229d 100644
--- a/Source/WebCore/platform/wince/DragDataWinCE.cpp
+++ b/Source/WebCore/platform/wince/DragDataWinCE.cpp
@@ -32,6 +32,11 @@ bool DragData::containsURL(Frame*, FilenameConversionPolicy filenamePolicy) cons
return false;
}
+const DragDataMap& DragData::dragDataMap()
+{
+ return m_dragDataMap;
+}
+
String DragData::asURL(Frame*, FilenameConversionPolicy filenamePolicy, String* title) const
{
return String();
diff --git a/Source/WebCore/platform/wince/KeygenWinCE.cpp b/Source/WebCore/platform/wince/KeygenWinCE.cpp
index 0c1b3c6..8537f44 100644
--- a/Source/WebCore/platform/wince/KeygenWinCE.cpp
+++ b/Source/WebCore/platform/wince/KeygenWinCE.cpp
@@ -80,10 +80,7 @@ String WebCore::signedPublicKeyAndChallengeString(unsigned index, const String&
if (!CryptSignAndEncodeCertificate(hContext, AT_KEYEXCHANGE, X509_ASN_ENCODING, X509_KEYGEN_REQUEST_TO_BE_SIGNED, &requestInfo, &signAlgo, 0, reinterpret_cast<LPBYTE>(binary.data()), &dwEncodedLength))
break;
- Vector<char> base64;
- base64Encode(binary, base64);
- keyString = String(base64.data(), base64.size());
-
+ keyString = base64Encode(binary);
} while(0);
if (pPubInfo)
diff --git a/Source/WebCore/platform/wince/MIMETypeRegistryWinCE.cpp b/Source/WebCore/platform/wince/MIMETypeRegistryWinCE.cpp
index 7534b91..8a7ac8f 100644
--- a/Source/WebCore/platform/wince/MIMETypeRegistryWinCE.cpp
+++ b/Source/WebCore/platform/wince/MIMETypeRegistryWinCE.cpp
@@ -27,7 +27,9 @@
#include "config.h"
#include "MIMETypeRegistry.h"
+#include <wtf/Assertions.h>
#include <wtf/HashMap.h>
+#include <wtf/MainThread.h>
#include <windows.h>
#include <winreg.h>
@@ -119,6 +121,8 @@ String MIMETypeRegistry::getPreferredExtensionForMIMEType(const String& type)
String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
{
+ ASSERT(isMainThread());
+
if (ext.isEmpty())
return String();
diff --git a/Source/WebCore/platform/wx/MimeTypeRegistryWx.cpp b/Source/WebCore/platform/wx/MimeTypeRegistryWx.cpp
index e7cc0e2..94a815e 100644
--- a/Source/WebCore/platform/wx/MimeTypeRegistryWx.cpp
+++ b/Source/WebCore/platform/wx/MimeTypeRegistryWx.cpp
@@ -28,6 +28,9 @@
#include "config.h"
#include "MIMETypeRegistry.h"
+#include <wtf/Assertions.h>
+#include <wtf/MainThread.h>
+
namespace WebCore {
struct ExtensionMap {
@@ -59,6 +62,8 @@ static const ExtensionMap extensionMap [] = {
String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
{
+ ASSERT(isMainThread());
+
String s = ext.lower();
const ExtensionMap *e = extensionMap;
while (e->extension) {
diff --git a/Source/WebCore/platform/wx/RenderThemeWx.cpp b/Source/WebCore/platform/wx/RenderThemeWx.cpp
index c68bde9..a34e2d4 100644
--- a/Source/WebCore/platform/wx/RenderThemeWx.cpp
+++ b/Source/WebCore/platform/wx/RenderThemeWx.cpp
@@ -31,6 +31,7 @@
#include "GraphicsContext.h"
#include "HostWindow.h"
#include "NotImplemented.h"
+#include "PaintInfo.h"
#include "RenderView.h"
#include <wx/defs.h>
diff --git a/Source/WebCore/platform/wx/SystemTimeWx.cpp b/Source/WebCore/platform/wx/SystemTimeWx.cpp
index f607cba..668ec00 100644
--- a/Source/WebCore/platform/wx/SystemTimeWx.cpp
+++ b/Source/WebCore/platform/wx/SystemTimeWx.cpp
@@ -26,18 +26,16 @@
#include "config.h"
#include "SystemTime.h"
-#include <float.h>
-
#include "NotImplemented.h"
+#include <limits>
namespace WebCore {
float userIdleTime()
{
notImplemented();
- // return an arbitrarily high userIdleTime so that releasing pages from the page cache isn't postponed
- return FLT_MAX;
-}
-
+ // Return an arbitrarily high userIdleTime so that releasing pages from the page cache isn't postponed.
+ return std::numeric_limits<float>::max();
}
+} // namespace WebCore