summaryrefslogtreecommitdiffstats
path: root/WebCore/platform
diff options
context:
space:
mode:
authorFeng Qian <fqian@google.com>2009-06-18 18:20:56 -0700
committerFeng Qian <fqian@google.com>2009-06-18 18:20:56 -0700
commit1edef79f87f9c52c21d69c87c19f8e2b140a9119 (patch)
treecad337ef493b0d9710bf3ae478cb87cb534f598d /WebCore/platform
parentb83fc086000e27bc227580bd0e35b9d7bee1179a (diff)
parentc9c4d65c1547996ed3748026904d6e7f09aec2b4 (diff)
downloadexternal_webkit-1edef79f87f9c52c21d69c87c19f8e2b140a9119.zip
external_webkit-1edef79f87f9c52c21d69c87c19f8e2b140a9119.tar.gz
external_webkit-1edef79f87f9c52c21d69c87c19f8e2b140a9119.tar.bz2
Merge commit 'goog/master-webkit-merge' into webkit-merge-44544
Diffstat (limited to 'WebCore/platform')
-rw-r--r--WebCore/platform/ContextMenu.cpp119
-rw-r--r--WebCore/platform/ContextMenu.h1
-rw-r--r--WebCore/platform/ContextMenuItem.h15
-rw-r--r--WebCore/platform/CookieJar.h2
-rw-r--r--WebCore/platform/Cursor.h7
-rw-r--r--WebCore/platform/FileSystem.h5
-rw-r--r--WebCore/platform/HostWindow.h7
-rw-r--r--WebCore/platform/KURL.cpp19
-rw-r--r--WebCore/platform/KURL.h3
-rw-r--r--WebCore/platform/KURLGoogle.cpp18
-rw-r--r--WebCore/platform/KeyboardCodes.h (renamed from WebCore/platform/qt/KeyboardCodes.h)13
-rw-r--r--WebCore/platform/LinkHash.cpp25
-rw-r--r--WebCore/platform/LinkHash.h6
-rw-r--r--WebCore/platform/LocalizedStrings.h13
-rw-r--r--WebCore/platform/Logging.cpp30
-rw-r--r--WebCore/platform/Logging.h3
-rw-r--r--WebCore/platform/MIMETypeRegistry.cpp120
-rw-r--r--WebCore/platform/MIMETypeRegistry.h3
-rw-r--r--WebCore/platform/PlatformMouseEvent.h72
-rw-r--r--WebCore/platform/PlatformWheelEvent.h38
-rw-r--r--WebCore/platform/ScrollView.cpp170
-rw-r--r--WebCore/platform/ScrollView.h17
-rw-r--r--WebCore/platform/Scrollbar.cpp69
-rw-r--r--WebCore/platform/Scrollbar.h5
-rw-r--r--WebCore/platform/ScrollbarTheme.h1
-rw-r--r--WebCore/platform/SharedBuffer.h1
-rw-r--r--WebCore/platform/SuddenTermination.h43
-rw-r--r--WebCore/platform/ThreadGlobalData.cpp16
-rw-r--r--WebCore/platform/ThreadGlobalData.h8
-rw-r--r--WebCore/platform/Timer.cpp11
-rw-r--r--WebCore/platform/Timer.h5
-rw-r--r--WebCore/platform/Widget.h1
-rw-r--r--WebCore/platform/android/RenderThemeAndroid.cpp10
-rw-r--r--WebCore/platform/android/TemporaryLinkStubs.cpp19
-rw-r--r--WebCore/platform/cf/BinaryPropertyList.cpp831
-rw-r--r--WebCore/platform/cf/BinaryPropertyList.h108
-rw-r--r--WebCore/platform/cf/SharedBufferCF.cpp5
-rw-r--r--WebCore/platform/chromium/ChromiumBridge.h7
-rw-r--r--WebCore/platform/chromium/ClipboardChromium.cpp4
-rw-r--r--WebCore/platform/chromium/ClipboardChromium.h1
-rw-r--r--WebCore/platform/chromium/KeyCodeConversionGtk.cpp5
-rw-r--r--WebCore/platform/chromium/MimeTypeRegistryChromium.cpp5
-rw-r--r--WebCore/platform/chromium/PopupMenuChromium.cpp144
-rw-r--r--WebCore/platform/chromium/PopupMenuChromium.h30
-rw-r--r--WebCore/platform/chromium/ScrollbarThemeChromium.cpp64
-rw-r--r--WebCore/platform/chromium/ScrollbarThemeChromium.h34
-rw-r--r--WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp41
-rw-r--r--WebCore/platform/chromium/ScrollbarThemeChromiumLinux.h51
-rw-r--r--WebCore/platform/chromium/ScrollbarThemeChromiumWin.cpp95
-rw-r--r--WebCore/platform/chromium/ScrollbarThemeChromiumWin.h56
-rw-r--r--WebCore/platform/chromium/SuddenTerminationChromium.cpp48
-rw-r--r--WebCore/platform/graphics/BitmapImage.cpp2
-rw-r--r--WebCore/platform/graphics/BitmapImage.h10
-rw-r--r--WebCore/platform/graphics/Color.cpp35
-rw-r--r--WebCore/platform/graphics/Color.h1
-rw-r--r--WebCore/platform/graphics/FloatQuad.cpp39
-rw-r--r--WebCore/platform/graphics/FloatQuad.h8
-rw-r--r--WebCore/platform/graphics/Font.cpp30
-rw-r--r--WebCore/platform/graphics/Font.h21
-rw-r--r--WebCore/platform/graphics/FontCache.cpp7
-rw-r--r--WebCore/platform/graphics/FontCache.h1
-rw-r--r--WebCore/platform/graphics/FontDescription.h6
-rw-r--r--WebCore/platform/graphics/FontFallbackList.cpp4
-rw-r--r--WebCore/platform/graphics/FontFallbackList.h2
-rw-r--r--WebCore/platform/graphics/FontFastPath.cpp20
-rw-r--r--WebCore/platform/graphics/GeneratedImage.cpp2
-rw-r--r--WebCore/platform/graphics/GlyphPageTreeNode.cpp27
-rw-r--r--WebCore/platform/graphics/GlyphPageTreeNode.h67
-rw-r--r--WebCore/platform/graphics/Gradient.cpp1
-rw-r--r--WebCore/platform/graphics/GraphicsContext.cpp3
-rw-r--r--WebCore/platform/graphics/GraphicsContext.h1
-rw-r--r--WebCore/platform/graphics/GraphicsLayer.h6
-rw-r--r--WebCore/platform/graphics/Image.h9
-rw-r--r--WebCore/platform/graphics/ImageBuffer.h14
-rw-r--r--WebCore/platform/graphics/ImageSource.h5
-rw-r--r--WebCore/platform/graphics/IntPoint.h1
-rw-r--r--WebCore/platform/graphics/IntSize.h6
-rw-r--r--WebCore/platform/graphics/MediaPlayer.cpp36
-rw-r--r--WebCore/platform/graphics/MediaPlayer.h15
-rw-r--r--WebCore/platform/graphics/MediaPlayerPrivate.h6
-rw-r--r--WebCore/platform/graphics/Path.cpp2
-rw-r--r--WebCore/platform/graphics/SimpleFontData.cpp62
-rw-r--r--WebCore/platform/graphics/SimpleFontData.h37
-rw-r--r--WebCore/platform/graphics/WidthIterator.cpp35
-rw-r--r--WebCore/platform/graphics/WidthIterator.h5
-rw-r--r--WebCore/platform/graphics/android/FontAndroid.cpp7
-rw-r--r--WebCore/platform/graphics/android/FontDataAndroid.cpp15
-rw-r--r--WebCore/platform/graphics/cairo/FontCairo.cpp26
-rw-r--r--WebCore/platform/graphics/cairo/GradientCairo.cpp4
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp1
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h2
-rw-r--r--WebCore/platform/graphics/cairo/ImageBufferCairo.cpp1
-rw-r--r--WebCore/platform/graphics/cairo/ImageCairo.cpp31
-rw-r--r--WebCore/platform/graphics/cairo/ImageSourceCairo.cpp4
-rw-r--r--WebCore/platform/graphics/cairo/PathCairo.cpp1
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextCG.cpp42
-rw-r--r--WebCore/platform/graphics/cg/ImageSourceCG.cpp43
-rw-r--r--WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp15
-rw-r--r--WebCore/platform/graphics/chromium/FontCacheLinux.cpp42
-rw-r--r--WebCore/platform/graphics/chromium/FontChromiumWin.cpp45
-rw-r--r--WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp6
-rw-r--r--WebCore/platform/graphics/chromium/FontLinux.cpp7
-rw-r--r--WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp5
-rw-r--r--WebCore/platform/graphics/chromium/FontPlatformDataLinux.h7
-rw-r--r--WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp94
-rw-r--r--WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp10
-rw-r--r--WebCore/platform/graphics/chromium/MediaPlayerPrivateChromium.h59
-rw-r--r--WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp19
-rw-r--r--WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp51
-rw-r--r--WebCore/platform/graphics/chromium/TransparencyWin.cpp2
-rw-r--r--WebCore/platform/graphics/chromium/VDMXParser.cpp203
-rw-r--r--WebCore/platform/graphics/chromium/VDMXParser.h (renamed from WebCore/platform/chromium/KeyboardCodes.h)22
-rw-r--r--WebCore/platform/graphics/filters/FEBlend.cpp8
-rw-r--r--WebCore/platform/graphics/filters/FEBlend.h10
-rw-r--r--WebCore/platform/graphics/filters/FEColorMatrix.cpp8
-rw-r--r--WebCore/platform/graphics/filters/FEColorMatrix.h10
-rw-r--r--WebCore/platform/graphics/filters/FEComponentTransfer.cpp8
-rw-r--r--WebCore/platform/graphics/filters/FEComponentTransfer.h11
-rw-r--r--WebCore/platform/graphics/filters/FEComposite.cpp8
-rw-r--r--WebCore/platform/graphics/filters/FEComposite.h10
-rw-r--r--WebCore/platform/graphics/filters/Filter.h52
-rw-r--r--WebCore/platform/graphics/filters/FilterEffect.cpp46
-rw-r--r--WebCore/platform/graphics/filters/FilterEffect.h81
-rw-r--r--WebCore/platform/graphics/filters/SourceAlpha.cpp54
-rw-r--r--WebCore/platform/graphics/filters/SourceAlpha.h47
-rw-r--r--WebCore/platform/graphics/filters/SourceGraphic.cpp54
-rw-r--r--WebCore/platform/graphics/filters/SourceGraphic.h48
-rw-r--r--WebCore/platform/graphics/gtk/FontCacheGtk.cpp2
-rw-r--r--WebCore/platform/graphics/gtk/FontGtk.cpp16
-rw-r--r--WebCore/platform/graphics/gtk/FontPlatformData.h2
-rw-r--r--WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp6
-rw-r--r--WebCore/platform/graphics/gtk/GlyphPageTreeNodeGtk.cpp4
-rw-r--r--WebCore/platform/graphics/gtk/GlyphPageTreeNodePango.cpp4
-rw-r--r--WebCore/platform/graphics/gtk/IconGtk.cpp1
-rw-r--r--WebCore/platform/graphics/gtk/ImageGtk.cpp73
-rw-r--r--WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp30
-rw-r--r--WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp26
-rw-r--r--WebCore/platform/graphics/mac/ColorMac.h2
-rw-r--r--WebCore/platform/graphics/mac/ColorMac.mm48
-rw-r--r--WebCore/platform/graphics/mac/CoreTextController.cpp32
-rw-r--r--WebCore/platform/graphics/mac/CoreTextController.h4
-rw-r--r--WebCore/platform/graphics/mac/FontCacheMac.mm16
-rw-r--r--WebCore/platform/graphics/mac/FontMac.mm16
-rw-r--r--WebCore/platform/graphics/mac/FontMacATSUI.mm49
-rw-r--r--WebCore/platform/graphics/mac/FontMacCoreText.cpp4
-rw-r--r--WebCore/platform/graphics/mac/FontPlatformData.h2
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContextMac.mm11
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.h3
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.mm98
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h6
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm294
-rw-r--r--WebCore/platform/graphics/mac/SimpleFontDataMac.mm105
-rw-r--r--WebCore/platform/graphics/mac/WebLayer.mm1
-rw-r--r--WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp46
-rw-r--r--WebCore/platform/graphics/opentype/OpenTypeUtilities.h21
-rw-r--r--WebCore/platform/graphics/qt/FontCacheQt.cpp35
-rw-r--r--WebCore/platform/graphics/qt/FontFallbackListQt.cpp12
-rw-r--r--WebCore/platform/graphics/qt/FontQt.cpp2
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContextQt.cpp26
-rw-r--r--WebCore/platform/graphics/qt/IconQt.cpp1
-rw-r--r--WebCore/platform/graphics/qt/ImageBufferQt.cpp19
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.cpp13
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.h3
-rw-r--r--WebCore/platform/graphics/qt/ImageQt.cpp8
-rw-r--r--WebCore/platform/graphics/qt/ImageSourceQt.cpp1
-rw-r--r--WebCore/platform/graphics/qt/PathQt.cpp5
-rw-r--r--WebCore/platform/graphics/qt/SimpleFontDataQt.cpp11
-rw-r--r--WebCore/platform/graphics/skia/GradientSkia.cpp4
-rw-r--r--WebCore/platform/graphics/skia/GraphicsContextSkia.cpp40
-rw-r--r--WebCore/platform/graphics/skia/ImageBufferSkia.cpp1
-rw-r--r--WebCore/platform/graphics/skia/ImageSkia.cpp16
-rw-r--r--WebCore/platform/graphics/skia/PathSkia.cpp12
-rw-r--r--WebCore/platform/graphics/skia/PlatformContextSkia.cpp13
-rw-r--r--WebCore/platform/graphics/skia/PlatformContextSkia.h1
-rw-r--r--WebCore/platform/graphics/skia/SkiaFontWin.cpp12
-rw-r--r--WebCore/platform/graphics/skia/SkiaFontWin.h6
-rw-r--r--WebCore/platform/graphics/skia/SkiaUtils.cpp9
-rw-r--r--WebCore/platform/graphics/transforms/TransformationMatrix.cpp65
-rw-r--r--WebCore/platform/graphics/transforms/TransformationMatrix.h21
-rw-r--r--WebCore/platform/graphics/win/ColorSafari.cpp1
-rw-r--r--WebCore/platform/graphics/win/FontCGWin.cpp26
-rw-r--r--WebCore/platform/graphics/win/FontCustomPlatformData.cpp6
-rw-r--r--WebCore/platform/graphics/win/FontWin.cpp10
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextCGWin.cpp1
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp180
-rw-r--r--WebCore/platform/graphics/win/ImageCairoWin.cpp20
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp54
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h3
-rw-r--r--WebCore/platform/graphics/win/QTMovieWin.cpp94
-rw-r--r--WebCore/platform/graphics/win/QTMovieWin.h4
-rw-r--r--WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp26
-rw-r--r--WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp30
-rw-r--r--WebCore/platform/graphics/win/SimpleFontDataWin.cpp22
-rw-r--r--WebCore/platform/graphics/win/UniscribeController.cpp25
-rw-r--r--WebCore/platform/graphics/win/UniscribeController.h3
-rw-r--r--WebCore/platform/graphics/wx/FontWx.cpp7
-rw-r--r--WebCore/platform/graphics/wx/ImageSourceWx.cpp10
-rw-r--r--WebCore/platform/graphics/wx/ImageWx.cpp46
-rw-r--r--WebCore/platform/graphics/wx/PathWx.cpp5
-rw-r--r--WebCore/platform/graphics/wx/SimpleFontDataWx.cpp15
-rw-r--r--WebCore/platform/graphics/wx/TransformationMatrixWx.cpp2
-rw-r--r--WebCore/platform/gtk/ContextMenuItemGtk.cpp2
-rw-r--r--WebCore/platform/gtk/CursorGtk.cpp40
-rw-r--r--WebCore/platform/gtk/CursorGtk.h230
-rw-r--r--WebCore/platform/gtk/FileChooserGtk.cpp1
-rw-r--r--WebCore/platform/gtk/FileSystemGtk.cpp14
-rw-r--r--WebCore/platform/gtk/GeolocationServiceGtk.cpp4
-rw-r--r--WebCore/platform/gtk/GtkPluginWidget.cpp105
-rw-r--r--WebCore/platform/gtk/GtkPluginWidget.h (renamed from WebCore/platform/network/cf/ResourceResponseCFNet.h)25
-rw-r--r--WebCore/platform/gtk/KeyEventGtk.cpp13
-rw-r--r--WebCore/platform/gtk/KeyboardCodes.h543
-rw-r--r--WebCore/platform/gtk/LocalizedStringsGtk.cpp16
-rw-r--r--WebCore/platform/gtk/MouseEventGtk.cpp8
-rw-r--r--WebCore/platform/gtk/PasteboardGtk.cpp24
-rw-r--r--WebCore/platform/gtk/PasteboardHelper.h3
-rw-r--r--WebCore/platform/gtk/PlatformScreenGtk.cpp1
-rw-r--r--WebCore/platform/gtk/PopupMenuGtk.cpp6
-rw-r--r--WebCore/platform/gtk/RenderThemeGtk.cpp8
-rw-r--r--WebCore/platform/gtk/RenderThemeGtk.h1
-rw-r--r--WebCore/platform/gtk/ScrollViewGtk.cpp123
-rw-r--r--WebCore/platform/gtk/ScrollbarGtk.cpp44
-rw-r--r--WebCore/platform/gtk/ScrollbarGtk.h5
-rw-r--r--WebCore/platform/gtk/TemporaryLinkStubs.cpp16
-rw-r--r--WebCore/platform/gtk/WheelEventGtk.cpp8
-rw-r--r--WebCore/platform/gtk/WidgetGtk.cpp17
-rw-r--r--WebCore/platform/gtk/gtk2drawing.c158
-rw-r--r--WebCore/platform/gtk/gtkdrawing.h4
-rw-r--r--WebCore/platform/gtk/guriescape.c219
-rw-r--r--WebCore/platform/gtk/guriescape.h44
-rw-r--r--WebCore/platform/image-decoders/ImageDecoder.h269
-rw-r--r--WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp6
-rw-r--r--WebCore/platform/image-decoders/bmp/BMPImageDecoder.h25
-rw-r--r--WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp92
-rw-r--r--WebCore/platform/image-decoders/gif/GIFImageDecoder.h87
-rw-r--r--WebCore/platform/image-decoders/gif/GIFImageReader.cpp4
-rw-r--r--WebCore/platform/image-decoders/gif/GIFImageReader.h7
-rw-r--r--WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp6
-rw-r--r--WebCore/platform/image-decoders/ico/ICOImageDecoder.h25
-rw-r--r--WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp27
-rw-r--r--WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h59
-rw-r--r--WebCore/platform/image-decoders/png/PNGImageDecoder.cpp38
-rw-r--r--WebCore/platform/image-decoders/png/PNGImageDecoder.h51
-rw-r--r--WebCore/platform/image-decoders/skia/GIFImageDecoder.cpp4
-rw-r--r--WebCore/platform/image-decoders/skia/GIFImageReader.h10
-rw-r--r--WebCore/platform/image-decoders/skia/ImageDecoder.h93
-rw-r--r--WebCore/platform/image-decoders/skia/JPEGImageDecoder.cpp4
-rw-r--r--WebCore/platform/image-decoders/skia/PNGImageDecoder.cpp17
-rw-r--r--WebCore/platform/image-decoders/skia/XBMImageDecoder.h1
-rw-r--r--WebCore/platform/image-decoders/xbm/XBMImageDecoder.cpp6
-rw-r--r--WebCore/platform/image-decoders/xbm/XBMImageDecoder.h25
-rw-r--r--WebCore/platform/mac/ClipboardMac.mm126
-rw-r--r--WebCore/platform/mac/CookieJar.mm5
-rw-r--r--WebCore/platform/mac/DragDataMac.mm2
-rw-r--r--WebCore/platform/mac/GeolocationServiceMac.mm18
-rw-r--r--WebCore/platform/mac/LocalizedStringsMac.mm104
-rw-r--r--WebCore/platform/mac/PasteboardMac.mm4
-rw-r--r--WebCore/platform/mac/PlatformMouseEventMac.mm21
-rw-r--r--WebCore/platform/mac/RuntimeApplicationChecks.h36
-rw-r--r--WebCore/platform/mac/RuntimeApplicationChecks.mm44
-rw-r--r--WebCore/platform/mac/ScrollbarThemeMac.mm16
-rw-r--r--WebCore/platform/mac/SuddenTermination.mm (renamed from WebCore/platform/mac/WebCoreTextRenderer.h)40
-rw-r--r--WebCore/platform/mac/WebCoreSystemInterface.h4
-rw-r--r--WebCore/platform/mac/WebCoreSystemInterface.mm4
-rw-r--r--WebCore/platform/mac/WebCoreTextRenderer.mm94
-rw-r--r--WebCore/platform/mac/WebFontCache.h2
-rw-r--r--WebCore/platform/mac/WebFontCache.mm12
-rw-r--r--WebCore/platform/mac/WheelEventMac.mm4
-rw-r--r--WebCore/platform/mac/WidgetMac.mm8
-rw-r--r--WebCore/platform/network/HTTPParsers.cpp41
-rw-r--r--WebCore/platform/network/HTTPParsers.h1
-rw-r--r--WebCore/platform/network/ResourceHandle.cpp26
-rw-r--r--WebCore/platform/network/ResourceHandle.h9
-rw-r--r--WebCore/platform/network/ResourceHandleClient.h2
-rw-r--r--WebCore/platform/network/ResourceHandleInternal.h12
-rw-r--r--WebCore/platform/network/ResourceRequestBase.cpp33
-rw-r--r--WebCore/platform/network/ResourceRequestBase.h12
-rw-r--r--WebCore/platform/network/ResourceResponseBase.cpp232
-rw-r--r--WebCore/platform/network/ResourceResponseBase.h80
-rw-r--r--WebCore/platform/network/android/Cookie.cpp4
-rw-r--r--WebCore/platform/network/android/CookieClient.h2
-rw-r--r--WebCore/platform/network/android/ResourceHandleAndroid.cpp3
-rw-r--r--WebCore/platform/network/cf/AuthenticationCF.cpp2
-rw-r--r--WebCore/platform/network/cf/AuthenticationCF.h19
-rw-r--r--WebCore/platform/network/cf/ResourceHandleCFNet.cpp298
-rw-r--r--WebCore/platform/network/cf/ResourceRequestCFNet.cpp19
-rw-r--r--WebCore/platform/network/cf/ResourceResponseCFNet.cpp12
-rw-r--r--WebCore/platform/network/chromium/CookieJarChromium.cpp8
-rw-r--r--WebCore/platform/network/chromium/ResourceRequest.h15
-rw-r--r--WebCore/platform/network/chromium/ResourceResponse.h16
-rw-r--r--WebCore/platform/network/curl/CookieJarCurl.cpp3
-rw-r--r--WebCore/platform/network/curl/ResourceHandleCurl.cpp2
-rw-r--r--WebCore/platform/network/curl/ResourceHandleManager.cpp29
-rw-r--r--WebCore/platform/network/mac/AuthenticationMac.h18
-rw-r--r--WebCore/platform/network/mac/AuthenticationMac.mm2
-rw-r--r--WebCore/platform/network/mac/ResourceHandleMac.mm334
-rw-r--r--WebCore/platform/network/mac/ResourceRequestMac.mm12
-rw-r--r--WebCore/platform/network/mac/ResourceResponseMac.mm6
-rw-r--r--WebCore/platform/network/qt/QNetworkReplyHandler.cpp6
-rw-r--r--WebCore/platform/network/qt/QNetworkReplyHandler.h1
-rw-r--r--WebCore/platform/network/qt/ResourceHandleQt.cpp2
-rw-r--r--WebCore/platform/network/qt/ResourceRequestQt.cpp16
-rw-r--r--WebCore/platform/network/soup/CookieJarSoup.cpp3
-rw-r--r--WebCore/platform/network/soup/ResourceHandleSoup.cpp200
-rw-r--r--WebCore/platform/network/soup/ResourceRequest.h17
-rw-r--r--WebCore/platform/network/soup/ResourceRequestSoup.cpp76
-rw-r--r--WebCore/platform/network/win/CookieJarCFNetWin.cpp6
-rw-r--r--WebCore/platform/network/win/CookieJarWin.cpp4
-rw-r--r--WebCore/platform/posix/FileSystemPOSIX.cpp1
-rw-r--r--WebCore/platform/qt/ContextMenuQt.cpp1
-rw-r--r--WebCore/platform/qt/CookieJarQt.cpp6
-rw-r--r--WebCore/platform/qt/DragDataQt.cpp7
-rw-r--r--WebCore/platform/qt/FileSystemQt.cpp1
-rw-r--r--WebCore/platform/qt/Localizations.cpp5
-rw-r--r--WebCore/platform/qt/MenuEventProxy.h54
-rw-r--r--WebCore/platform/qt/PopupMenuQt.cpp1
-rw-r--r--WebCore/platform/qt/QWebPopup.cpp4
-rw-r--r--WebCore/platform/qt/RenderThemeQt.cpp30
-rw-r--r--WebCore/platform/qt/RenderThemeQt.h3
-rw-r--r--WebCore/platform/qt/ScrollViewQt.cpp20
-rw-r--r--WebCore/platform/qt/TemporaryLinkStubs.cpp33
-rw-r--r--WebCore/platform/text/AtomicString.cpp4
-rw-r--r--WebCore/platform/text/AtomicString.h20
-rw-r--r--WebCore/platform/text/BidiContext.cpp31
-rw-r--r--WebCore/platform/text/BidiContext.h33
-rw-r--r--WebCore/platform/text/BidiResolver.h2
-rw-r--r--WebCore/platform/text/CharacterNames.h2
-rw-r--r--WebCore/platform/text/PlatformString.h5
-rw-r--r--WebCore/platform/text/String.cpp75
-rw-r--r--WebCore/platform/text/StringBuilder.cpp9
-rw-r--r--WebCore/platform/text/StringImpl.cpp196
-rw-r--r--WebCore/platform/text/StringImpl.h30
-rw-r--r--WebCore/platform/text/TextBoundaries.h5
-rw-r--r--WebCore/platform/text/TextBoundariesICU.cpp1
-rw-r--r--WebCore/platform/text/TextCodec.h3
-rw-r--r--WebCore/platform/text/TextCodecICU.cpp6
-rw-r--r--WebCore/platform/text/TextCodecICU.h2
-rw-r--r--WebCore/platform/text/TextCodecLatin1.cpp14
-rw-r--r--WebCore/platform/text/TextCodecUTF16.cpp11
-rw-r--r--WebCore/platform/text/TextCodecUserDefined.cpp12
-rw-r--r--WebCore/platform/text/TextEncoding.cpp22
-rw-r--r--WebCore/platform/text/TextEncoding.h1
-rw-r--r--WebCore/platform/text/TextEncodingDetectorICU.cpp2
-rw-r--r--WebCore/platform/text/TextEncodingDetectorNone.cpp9
-rw-r--r--WebCore/platform/text/TextEncodingRegistry.cpp8
-rw-r--r--WebCore/platform/text/TextEncodingRegistry.h3
-rw-r--r--WebCore/platform/text/mac/TextBoundaries.mm2
-rw-r--r--WebCore/platform/text/mac/TextCodecMac.cpp6
-rw-r--r--WebCore/platform/text/qt/TextBreakIteratorQt.cpp1
-rw-r--r--WebCore/platform/text/qt/TextCodecQt.cpp4
-rw-r--r--WebCore/platform/text/win/TextBreakIteratorInternalICUWin.cpp6
-rw-r--r--WebCore/platform/win/ClipboardUtilitiesWin.cpp7
-rw-r--r--WebCore/platform/win/EditorWin.cpp1
-rw-r--r--WebCore/platform/win/Language.cpp6
-rw-r--r--WebCore/platform/win/PasteboardWin.cpp1
-rw-r--r--WebCore/platform/win/PopupMenuWin.cpp4
-rw-r--r--WebCore/platform/win/ScrollbarThemeWin.cpp61
-rw-r--r--WebCore/platform/win/ScrollbarThemeWin.h1
-rw-r--r--WebCore/platform/win/SystemInfo.cpp50
-rw-r--r--WebCore/platform/win/SystemInfo.h35
-rw-r--r--WebCore/platform/win/WidgetWin.cpp34
-rw-r--r--WebCore/platform/wx/KeyboardEventWx.cpp32
-rw-r--r--WebCore/platform/wx/LoggingWx.cpp30
-rw-r--r--WebCore/platform/wx/MouseEventWx.cpp4
-rw-r--r--WebCore/platform/wx/PopupMenuWx.cpp1
-rw-r--r--WebCore/platform/wx/RenderThemeWx.cpp4
-rw-r--r--WebCore/platform/wx/ScrollViewWx.cpp8
-rw-r--r--WebCore/platform/wx/SharedTimerWx.cpp25
-rw-r--r--WebCore/platform/wx/TemporaryLinkStubs.cpp5
-rw-r--r--WebCore/platform/wx/WidgetWx.cpp29
-rw-r--r--WebCore/platform/wx/wxcode/mac/carbon/fontprops.cpp15
-rw-r--r--WebCore/platform/wx/wxcode/mac/carbon/non-kerned-drawing.cpp89
-rw-r--r--WebCore/platform/wx/wxcode/win/fontprops.cpp2
-rw-r--r--WebCore/platform/wx/wxcode/win/non-kerned-drawing.cpp1
373 files changed, 7903 insertions, 3915 deletions
diff --git a/WebCore/platform/ContextMenu.cpp b/WebCore/platform/ContextMenu.cpp
index f66a891..362e334 100644
--- a/WebCore/platform/ContextMenu.cpp
+++ b/WebCore/platform/ContextMenu.cpp
@@ -112,11 +112,21 @@ static void createAndAppendSpellingAndGrammarSubMenu(const HitTestResult& result
contextMenuItemTagCheckSpellingWhileTyping());
ContextMenuItem grammarWithSpelling(CheckableActionType, ContextMenuItemTagCheckGrammarWithSpelling,
contextMenuItemTagCheckGrammarWithSpelling());
+#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ ContextMenuItem correctSpelling(CheckableActionType, ContextMenuItemTagCorrectSpellingAutomatically,
+ contextMenuItemTagCorrectSpellingAutomatically());
+#endif
spellingAndGrammarMenu.appendItem(showSpellingPanel);
spellingAndGrammarMenu.appendItem(checkSpelling);
+#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ spellingAndGrammarMenu.appendItem(*separatorItem());
+#endif
spellingAndGrammarMenu.appendItem(checkAsYouType);
spellingAndGrammarMenu.appendItem(grammarWithSpelling);
+#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ spellingAndGrammarMenu.appendItem(correctSpelling);
+#endif
spellingAndGrammarMenuItem.setSubMenu(&spellingAndGrammarMenu);
}
@@ -189,6 +199,45 @@ static void createAndAppendTextDirectionSubMenu(const HitTestResult& result, Con
}
#endif
+#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+static void createAndAppendSubstitutionsSubMenu(const HitTestResult& result, ContextMenuItem& substitutionsMenuItem)
+{
+ ContextMenu substitutionsMenu(result);
+
+ ContextMenuItem showSubstitutions(ActionType, ContextMenuItemTagShowSubstitutions, contextMenuItemTagShowSubstitutions(true));
+ ContextMenuItem smartCopyPaste(CheckableActionType, ContextMenuItemTagSmartCopyPaste, contextMenuItemTagSmartCopyPaste());
+ ContextMenuItem smartQuotes(CheckableActionType, ContextMenuItemTagSmartQuotes, contextMenuItemTagSmartQuotes());
+ ContextMenuItem smartDashes(CheckableActionType, ContextMenuItemTagSmartDashes, contextMenuItemTagSmartDashes());
+ ContextMenuItem smartLinks(CheckableActionType, ContextMenuItemTagSmartLinks, contextMenuItemTagSmartLinks());
+ ContextMenuItem textReplacement(CheckableActionType, ContextMenuItemTagTextReplacement, contextMenuItemTagTextReplacement());
+
+ substitutionsMenu.appendItem(showSubstitutions);
+ substitutionsMenu.appendItem(*separatorItem());
+ substitutionsMenu.appendItem(smartCopyPaste);
+ substitutionsMenu.appendItem(smartQuotes);
+ substitutionsMenu.appendItem(smartDashes);
+ substitutionsMenu.appendItem(smartLinks);
+ substitutionsMenu.appendItem(textReplacement);
+
+ substitutionsMenuItem.setSubMenu(&substitutionsMenu);
+}
+
+static void createAndAppendTransformationsSubMenu(const HitTestResult& result, ContextMenuItem& transformationsMenuItem)
+{
+ ContextMenu transformationsMenu(result);
+
+ ContextMenuItem makeUpperCase(ActionType, ContextMenuItemTagMakeUpperCase, contextMenuItemTagMakeUpperCase());
+ ContextMenuItem makeLowerCase(ActionType, ContextMenuItemTagMakeLowerCase, contextMenuItemTagMakeLowerCase());
+ ContextMenuItem capitalize(ActionType, ContextMenuItemTagCapitalize, contextMenuItemTagCapitalize());
+
+ transformationsMenu.appendItem(makeUpperCase);
+ transformationsMenu.appendItem(makeLowerCase);
+ transformationsMenu.appendItem(capitalize);
+
+ transformationsMenuItem.setSubMenu(&transformationsMenu);
+}
+#endif
+
static bool selectionContainsPossibleWord(Frame* frame)
{
// Current algorithm: look for a character that's not just a separator.
@@ -357,6 +406,16 @@ void ContextMenu::populate()
} else
appendItem(IgnoreGrammarItem);
appendItem(*separatorItem());
+#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ } else {
+ // If the string was autocorrected, generate a contextual menu item allowing it to be changed back.
+ String replacedString = result.replacedString();
+ if (!replacedString.isEmpty()) {
+ ContextMenuItem item(ActionType, ContextMenuItemTagChangeBack, contextMenuItemTagChangeBack(replacedString));
+ appendItem(item);
+ appendItem(*separatorItem());
+ }
+#endif
}
}
@@ -407,6 +466,16 @@ void ContextMenu::populate()
createAndAppendSpellingSubMenu(m_hitTestResult, SpellingMenuItem);
appendItem(SpellingMenuItem);
#endif
+#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ ContextMenuItem substitutionsMenuItem(SubmenuType, ContextMenuItemTagSubstitutionsMenu,
+ contextMenuItemTagSubstitutionsMenu());
+ createAndAppendSubstitutionsSubMenu(m_hitTestResult, substitutionsMenuItem);
+ appendItem(substitutionsMenuItem);
+ ContextMenuItem transformationsMenuItem(SubmenuType, ContextMenuItemTagTransformationsMenu,
+ contextMenuItemTagTransformationsMenu());
+ createAndAppendTransformationsSubMenu(m_hitTestResult, transformationsMenuItem);
+ appendItem(transformationsMenuItem);
+#endif
ContextMenuItem FontMenuItem(SubmenuType, ContextMenuItemTagFontMenu,
contextMenuItemTagFontMenu());
createAndAppendFontSubMenu(m_hitTestResult, FontMenuItem);
@@ -584,6 +653,56 @@ void ContextMenu::checkOrEnableIfNeeded(ContextMenuItem& item) const
case ContextMenuItemTagCheckSpellingWhileTyping:
shouldCheck = frame->editor()->isContinuousSpellCheckingEnabled();
break;
+#if PLATFORM(MAC)
+ case ContextMenuItemTagSubstitutionsMenu:
+ case ContextMenuItemTagTransformationsMenu:
+ break;
+ case ContextMenuItemTagShowSubstitutions:
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ if (frame->editor()->substitutionsPanelIsShowing())
+ item.setTitle(contextMenuItemTagShowSubstitutions(false));
+ else
+ item.setTitle(contextMenuItemTagShowSubstitutions(true));
+ shouldEnable = frame->editor()->canEdit();
+#endif
+ break;
+ case ContextMenuItemTagMakeUpperCase:
+ case ContextMenuItemTagMakeLowerCase:
+ case ContextMenuItemTagCapitalize:
+ case ContextMenuItemTagChangeBack:
+ shouldEnable = frame->editor()->canEdit();
+ break;
+ case ContextMenuItemTagCorrectSpellingAutomatically:
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ shouldCheck = frame->editor()->isAutomaticSpellingCorrectionEnabled();
+#endif
+ break;
+ case ContextMenuItemTagSmartCopyPaste:
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ shouldCheck = frame->editor()->smartInsertDeleteEnabled();
+#endif
+ break;
+ case ContextMenuItemTagSmartQuotes:
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ shouldCheck = frame->editor()->isAutomaticQuoteSubstitutionEnabled();
+#endif
+ break;
+ case ContextMenuItemTagSmartDashes:
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ shouldCheck = frame->editor()->isAutomaticDashSubstitutionEnabled();
+#endif
+ break;
+ case ContextMenuItemTagSmartLinks:
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ shouldCheck = frame->editor()->isAutomaticLinkDetectionEnabled();
+#endif
+ break;
+ case ContextMenuItemTagTextReplacement:
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ shouldCheck = frame->editor()->isAutomaticTextReplacementEnabled();
+#endif
+ break;
+#endif
#if PLATFORM(GTK)
case ContextMenuItemTagGoBack:
shouldEnable = frame->loader()->canGoBackOrForward(-1);
diff --git a/WebCore/platform/ContextMenu.h b/WebCore/platform/ContextMenu.h
index 9418ff5..75899ba 100644
--- a/WebCore/platform/ContextMenu.h
+++ b/WebCore/platform/ContextMenu.h
@@ -39,7 +39,6 @@
#endif
namespace WebCore {
-class MenuEventProxy;
class ContextMenuController;
diff --git a/WebCore/platform/ContextMenuItem.h b/WebCore/platform/ContextMenuItem.h
index 52c4d1b..3a4cdfa 100644
--- a/WebCore/platform/ContextMenuItem.h
+++ b/WebCore/platform/ContextMenuItem.h
@@ -124,6 +124,21 @@ namespace WebCore {
ContextMenuItemTagTextDirectionDefault,
ContextMenuItemTagTextDirectionLeftToRight,
ContextMenuItemTagTextDirectionRightToLeft,
+#if PLATFORM(MAC)
+ ContextMenuItemTagCorrectSpellingAutomatically,
+ ContextMenuItemTagSubstitutionsMenu,
+ ContextMenuItemTagShowSubstitutions,
+ ContextMenuItemTagSmartCopyPaste,
+ ContextMenuItemTagSmartQuotes,
+ ContextMenuItemTagSmartDashes,
+ ContextMenuItemTagSmartLinks,
+ ContextMenuItemTagTextReplacement,
+ ContextMenuItemTagTransformationsMenu,
+ ContextMenuItemTagMakeUpperCase,
+ ContextMenuItemTagMakeLowerCase,
+ ContextMenuItemTagCapitalize,
+ ContextMenuItemTagChangeBack,
+#endif
ContextMenuItemBaseApplicationTag = 10000
};
diff --git a/WebCore/platform/CookieJar.h b/WebCore/platform/CookieJar.h
index 178ee79..6159386 100644
--- a/WebCore/platform/CookieJar.h
+++ b/WebCore/platform/CookieJar.h
@@ -33,7 +33,7 @@ namespace WebCore {
class Document;
String cookies(const Document*, const KURL&);
- void setCookies(Document*, const KURL&, const KURL& policyBaseURL, const String&);
+ void setCookies(Document*, const KURL&, const String&);
bool cookiesEnabled(const Document*);
}
diff --git a/WebCore/platform/Cursor.h b/WebCore/platform/Cursor.h
index 3ab694c..ea75191 100644
--- a/WebCore/platform/Cursor.h
+++ b/WebCore/platform/Cursor.h
@@ -70,18 +70,25 @@ namespace WebCore {
HCURSOR m_nativeCursor;
};
typedef RefPtr<SharedCursor> PlatformCursor;
+ typedef HCURSOR PlatformCursorHandle;
#elif PLATFORM(MAC)
typedef NSCursor* PlatformCursor;
+ typedef NSCursor* PlatformCursorHandle;
#elif PLATFORM(GTK)
typedef GdkCursor* PlatformCursor;
+ typedef GdkCursor* PlatformCursorHandle;
#elif PLATFORM(QT) && !defined(QT_NO_CURSOR)
typedef QCursor PlatformCursor;
+ typedef QCursor* PlatformCursorHandle;
#elif PLATFORM(WX)
typedef wxCursor* PlatformCursor;
+ typedef wxCursor* PlatformCursorHandle;
#elif PLATFORM(CHROMIUM)
// See PlatformCursor.h
+ typedef void* PlatformCursorHandle;
#else
typedef void* PlatformCursor;
+ typedef void* PlatformCursorHandle;
#endif
class Cursor {
diff --git a/WebCore/platform/FileSystem.h b/WebCore/platform/FileSystem.h
index 8ccefab..16afe8f 100644
--- a/WebCore/platform/FileSystem.h
+++ b/WebCore/platform/FileSystem.h
@@ -39,11 +39,10 @@
#if defined(Q_OS_WIN32)
#include <windows.h>
#endif
-#endif
-
-#if PLATFORM(DARWIN)
+#if defined(Q_WS_MAC)
#include <CoreFoundation/CFBundle.h>
#endif
+#endif
#include <time.h>
diff --git a/WebCore/platform/HostWindow.h b/WebCore/platform/HostWindow.h
index 7007ac5..3e982e1 100644
--- a/WebCore/platform/HostWindow.h
+++ b/WebCore/platform/HostWindow.h
@@ -27,18 +27,13 @@
#define HostWindow_h
#include <wtf/Noncopyable.h>
-#include "IntRect.h"
#include "Widget.h"
namespace WebCore {
-class IntPoint;
-class IntRect;
-
class HostWindow : Noncopyable {
public:
- HostWindow() {}
- virtual ~HostWindow() {}
+ virtual ~HostWindow() { }
// The repaint method asks the host window to repaint a rect in the window's coordinate space. The
// contentChanged boolean indicates whether or not the Web page content actually changed (or if a repaint
diff --git a/WebCore/platform/KURL.cpp b/WebCore/platform/KURL.cpp
index 6901782..4b75046 100644
--- a/WebCore/platform/KURL.cpp
+++ b/WebCore/platform/KURL.cpp
@@ -310,8 +310,6 @@ KURL::KURL(const char* url)
KURL::KURL(const String& url)
{
- checkEncodedString(url);
-
parse(url);
ASSERT(url == m_string);
}
@@ -343,7 +341,7 @@ void KURL::init(const KURL& base, const String& relative, const TextEncoding& en
// For compatibility with Win IE, treat backslashes as if they were slashes,
// as long as we're not dealing with javascript: or data: URLs.
String rel = relative;
- if (rel.contains('\\') && !(protocolIs(rel, "javascript") || protocolIs(rel, "data")))
+ if (rel.contains('\\') && !(protocolIsJavaScript(rel) || protocolIs(rel, "data")))
rel = substituteBackslashes(rel);
String* originalString = &rel;
@@ -631,10 +629,16 @@ static void assertProtocolIsGood(const char* protocol)
bool KURL::protocolIs(const char* protocol) const
{
- // Do the comparison without making a new string object.
assertProtocolIsGood(protocol);
+
+ // JavaScript URLs are "valid" and should be executed even if KURL decides they are invalid.
+ // The free function protocolIsJavaScript() should be used instead.
+ ASSERT(strcmp(protocol, "javascript") != 0);
+
if (!m_isValid)
return false;
+
+ // Do the comparison without making a new string object.
for (int i = 0; i < m_schemeEnd; ++i) {
if (!protocol[i] || toASCIILower(m_string[i]) != protocol[i])
return false;
@@ -1549,7 +1553,7 @@ static void encodeRelativeString(const String& rel, const TextEncoding& encoding
TextEncoding pathEncoding(UTF8Encoding()); // Path is always encoded as UTF-8; other parts may depend on the scheme.
int pathEnd = -1;
- if (encoding != pathEncoding && encoding.isValid() && !protocolIs(rel, "mailto") && !protocolIs(rel, "data") && !protocolIs(rel, "javascript")) {
+ if (encoding != pathEncoding && encoding.isValid() && !protocolIs(rel, "mailto") && !protocolIs(rel, "data") && !protocolIsJavaScript(rel)) {
// Find the first instance of either # or ?, keep pathEnd at -1 otherwise.
pathEnd = findFirstOf(s.data(), s.size(), 0, "#?");
}
@@ -1615,6 +1619,11 @@ bool protocolIs(const String& url, const char* protocol)
}
}
+bool protocolIsJavaScript(const String& url)
+{
+ return protocolIs(url, "javascript");
+}
+
String mimeTypeFromDataURL(const String& url)
{
ASSERT(protocolIs(url, "data"));
diff --git a/WebCore/platform/KURL.h b/WebCore/platform/KURL.h
index 46b72c7..e419d16 100644
--- a/WebCore/platform/KURL.h
+++ b/WebCore/platform/KURL.h
@@ -251,8 +251,11 @@ const KURL& blankURL();
// Functions to do URL operations on strings.
// These are operations that aren't faster on a parsed URL.
+// These are also different from the KURL functions in that they don't require the string to be a valid and parsable URL.
+// This is especially important because valid javascript URLs are not necessarily considered valid by KURL.
bool protocolIs(const String& url, const char* protocol);
+bool protocolIsJavaScript(const String& url);
String mimeTypeFromDataURL(const String& url);
diff --git a/WebCore/platform/KURLGoogle.cpp b/WebCore/platform/KURLGoogle.cpp
index c2e8272..d8b87e5 100644
--- a/WebCore/platform/KURLGoogle.cpp
+++ b/WebCore/platform/KURLGoogle.cpp
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2004, 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2008, 2009 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -235,6 +236,7 @@ void KURLGooglePrivate::init(const KURL& base, const UChar* rel, int relLength,
charsetConverter,
&output, &m_parsed);
+
if (m_isValid || output.length()) {
if (m_parsed.ref.is_nonempty())
setUtf8(CString(output.data(), output.length()));
@@ -521,6 +523,12 @@ bool KURL::hasRef() const
return m_url.m_parsed.ref.len >= 0;
}
+String KURL::baseAsString() const
+{
+ // FIXME: There is probably a more efficient way to do this?
+ return string().left(pathAfterLastSlash());
+}
+
String KURL::query() const
{
if (m_url.m_parsed.query.len >= 0)
@@ -685,6 +693,11 @@ String KURL::prettyURL() const
return m_url.string();
}
+bool protocolIsJavaScript(const String& url)
+{
+ return protocolIs(url, "javascript");
+}
+
// We copied the KURL version here on Sept 12, 2008 while doing a WebKit
// merge.
//
@@ -800,6 +813,11 @@ String decodeURLEscapeSequences(const String& str, const TextEncoding& encoding)
bool KURL::protocolIs(const char* protocol) const
{
assertProtocolIsGood(protocol);
+
+ // JavaScript URLs are "valid" and should be executed even if KURL decides they are invalid.
+ // The free function protocolIsJavaScript() should be used instead.
+ // FIXME: Chromium code needs to be fixed for this assert to be enabled. ASSERT(strcmp(protocol, "javascript"));
+
if (m_url.m_parsed.scheme.len <= 0)
return !protocol;
return lowerCaseEqualsASCII(
diff --git a/WebCore/platform/qt/KeyboardCodes.h b/WebCore/platform/KeyboardCodes.h
index 61bc9fe..c2c3b54 100644
--- a/WebCore/platform/qt/KeyboardCodes.h
+++ b/WebCore/platform/KeyboardCodes.h
@@ -30,6 +30,17 @@
#include <wtf/Platform.h>
+// FIXME: We should get rid of these Chromium-related ifdefs.
+#if PLATFORM(CHROMIUM)
+
+#if PLATFORM(WIN_OS)
+#include "KeyboardCodesWin.h"
+#else
+#include "KeyboardCodesPosix.h"
+#endif
+
+#else
+
namespace WebCore {
#if !PLATFORM(WIN_OS)
@@ -558,4 +569,6 @@ const int VK_UNKNOWN = 0;
}
+#endif // PLATFORM(CHROMIUM)
+
#endif
diff --git a/WebCore/platform/LinkHash.cpp b/WebCore/platform/LinkHash.cpp
index 793a65d..878933a 100644
--- a/WebCore/platform/LinkHash.cpp
+++ b/WebCore/platform/LinkHash.cpp
@@ -152,12 +152,12 @@ LinkHash visitedLinkHash(const UChar* url, unsigned length)
return AlreadyHashed::avoidDeletedValue(StringImpl::computeHash(url, length));
}
-LinkHash visitedLinkHash(const KURL& base, const AtomicString& attributeURL)
+void visitedURL(const KURL& base, const AtomicString& attributeURL, Vector<UChar, 512>& buffer)
{
const UChar* characters = attributeURL.characters();
unsigned length = attributeURL.length();
if (!length)
- return 0;
+ return;
// This is a poor man's completeURL. Faster with less memory allocation.
// FIXME: It's missing a lot of what completeURL does and a lot of what KURL does.
@@ -172,17 +172,18 @@ LinkHash visitedLinkHash(const KURL& base, const AtomicString& attributeURL)
bool hasColonSlashSlash = containsColonSlashSlash(characters, length);
- if (hasColonSlashSlash && !needsTrailingSlash(characters, length))
- return visitedLinkHash(attributeURL.characters(), attributeURL.length());
+ if (hasColonSlashSlash && !needsTrailingSlash(characters, length)) {
+ buffer.append(attributeURL.characters(), attributeURL.length());
+ return;
+ }
- Vector<UChar, 512> buffer;
if (hasColonSlashSlash) {
// FIXME: This is incorrect for URLs that have a query or anchor; the "/" needs to go at the
// end of the path, *before* the query or anchor.
buffer.append(characters, length);
buffer.append('/');
- return visitedLinkHash(buffer.data(), buffer.size());
+ return;
}
switch (characters[0]) {
@@ -204,7 +205,17 @@ LinkHash visitedLinkHash(const KURL& base, const AtomicString& attributeURL)
buffer.append('/');
}
- return visitedLinkHash(buffer.data(), buffer.size());
+ return;
+}
+
+LinkHash visitedLinkHash(const KURL& base, const AtomicString& attributeURL)
+{
+ Vector<UChar, 512> url;
+ visitedURL(base, attributeURL, url);
+ if (url.isEmpty())
+ return 0;
+
+ return visitedLinkHash(url.data(), url.size());
}
} // namespace WebCore
diff --git a/WebCore/platform/LinkHash.h b/WebCore/platform/LinkHash.h
index 1ec1e16..2756654 100644
--- a/WebCore/platform/LinkHash.h
+++ b/WebCore/platform/LinkHash.h
@@ -62,6 +62,12 @@ LinkHash visitedLinkHash(const UChar* url, unsigned length);
// look like a relative URL.
LinkHash visitedLinkHash(const KURL& base, const AtomicString& attributeURL);
+// Resolves the potentially relative URL "attributeURL" relative to the given
+// base URL, and returns the hash of the string that will be used for visited.
+// It will return an empty Vector in case of errors.
+void visitedURL(const KURL& base, const AtomicString& attributeURL, Vector<UChar, 512>&);
+
+
} // namespace WebCore
#endif // LinkHash_h
diff --git a/WebCore/platform/LocalizedStrings.h b/WebCore/platform/LocalizedStrings.h
index 085c6e1..b6ec878 100644
--- a/WebCore/platform/LocalizedStrings.h
+++ b/WebCore/platform/LocalizedStrings.h
@@ -88,6 +88,19 @@ namespace WebCore {
String contextMenuItemTagSpeechMenu();
String contextMenuItemTagStartSpeaking();
String contextMenuItemTagStopSpeaking();
+ String contextMenuItemTagCorrectSpellingAutomatically();
+ String contextMenuItemTagSubstitutionsMenu();
+ String contextMenuItemTagShowSubstitutions(bool show);
+ String contextMenuItemTagSmartCopyPaste();
+ String contextMenuItemTagSmartQuotes();
+ String contextMenuItemTagSmartDashes();
+ String contextMenuItemTagSmartLinks();
+ String contextMenuItemTagTextReplacement();
+ String contextMenuItemTagTransformationsMenu();
+ String contextMenuItemTagMakeUpperCase();
+ String contextMenuItemTagMakeLowerCase();
+ String contextMenuItemTagCapitalize();
+ String contextMenuItemTagChangeBack(const String& replacedString);
#endif
String contextMenuItemTagInspectElement();
diff --git a/WebCore/platform/Logging.cpp b/WebCore/platform/Logging.cpp
index a1aa3d6..9c3f324 100644
--- a/WebCore/platform/Logging.cpp
+++ b/WebCore/platform/Logging.cpp
@@ -25,6 +25,7 @@
#include "config.h"
#include "Logging.h"
+#include "PlatformString.h"
namespace WebCore {
@@ -59,4 +60,33 @@ WTFLogChannel LogMedia = { 0x01000000, "WebCoreLogLevel", WTFLogChan
WTFLogChannel LogPlugin = { 0x02000000, "WebCoreLogLevel", WTFLogChannelOff };
WTFLogChannel LogArchives = { 0x04000000, "WebCoreLogLevel", WTFLogChannelOff };
+WTFLogChannel* getChannelFromName(const String& channelName)
+{
+ if (!(channelName.length() >= 2))
+ return 0;
+
+ if (channelName == String("BackForward")) return &LogBackForward;
+ if (channelName == String("Editing")) return &LogEditing;
+ if (channelName == String("Events")) return &LogEvents;
+ if (channelName == String("Frames")) return &LogFrames;
+ if (channelName == String("FTP")) return &LogFTP;
+ if (channelName == String("History")) return &LogHistory;
+ if (channelName == String("IconDatabase")) return &LogIconDatabase;
+ if (channelName == String("Loading")) return &LogLoading;
+ if (channelName == String("Media")) return &LogMedia;
+ if (channelName == String("Network")) return &LogNetwork;
+ if (channelName == String("NotYetImplemented")) return &LogNotYetImplemented;
+ if (channelName == String("PageCache")) return &LogPageCache;
+ if (channelName == String("PlatformLeaks")) return &LogPlatformLeaks;
+ if (channelName == String("Plugin")) return &LogPlugin;
+ if (channelName == String("PopupBlocking")) return &LogPopupBlocking;
+ if (channelName == String("SpellingAndGrammar")) return &LogSpellingAndGrammar;
+ if (channelName == String("SQLDatabase")) return &LogSQLDatabase;
+ if (channelName == String("StorageAPI")) return &LogStorageAPI;
+ if (channelName == String("TextConversion")) return &LogTextConversion;
+ if (channelName == String("Threading")) return &LogThreading;
+
+ return 0;
+}
+
}
diff --git a/WebCore/platform/Logging.h b/WebCore/platform/Logging.h
index 844ac3a..c1461e7 100644
--- a/WebCore/platform/Logging.h
+++ b/WebCore/platform/Logging.h
@@ -34,6 +34,8 @@
namespace WebCore {
+ class String;
+
extern WTFLogChannel LogNotYetImplemented;
extern WTFLogChannel LogFrames;
extern WTFLogChannel LogLoading;
@@ -57,6 +59,7 @@ namespace WebCore {
extern WTFLogChannel LogArchives;
void InitializeLoggingChannelsIfNecessary();
+ WTFLogChannel* getChannelFromName(const String& channelName);
}
#endif // Logging_h
diff --git a/WebCore/platform/MIMETypeRegistry.cpp b/WebCore/platform/MIMETypeRegistry.cpp
index 14becb5..1819e1d 100644
--- a/WebCore/platform/MIMETypeRegistry.cpp
+++ b/WebCore/platform/MIMETypeRegistry.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,6 +34,7 @@
#include "StringHash.h"
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
+#include <wtf/StdLibExtras.h>
#if PLATFORM(CG)
#include "ImageSourceCG.h"
@@ -53,6 +54,7 @@ static HashSet<String>* supportedImageMIMETypesForEncoding;
static HashSet<String>* supportedJavaScriptMIMETypes;
static HashSet<String>* supportedNonImageMIMETypes;
static HashSet<String>* supportedMediaMIMETypes;
+static HashMap<String, String, CaseFoldingHash>* mediaMIMETypeForExtensionMap;
static void initializeSupportedImageMIMETypes()
{
@@ -73,7 +75,9 @@ static void initializeSupportedImageMIMETypes()
supportedImageResourceMIMETypes->add("image/bmp");
// Favicons don't have a MIME type in the registry either.
+ supportedImageMIMETypes->add("image/vnd.microsoft.icon");
supportedImageMIMETypes->add("image/x-icon");
+ supportedImageResourceMIMETypes->add("image/vnd.microsoft.icon");
supportedImageResourceMIMETypes->add("image/x-icon");
// We only get one MIME type per UTI, hence our need to add these manually
@@ -102,6 +106,9 @@ static void initializeSupportedImageMIMETypes()
supportedImageMIMETypes->add(mimeType);
supportedImageResourceMIMETypes->add(mimeType);
}
+
+ supportedImageMIMETypes->remove("application/octet-stream");
+ supportedImageResourceMIMETypes->remove("application/octet-stream");
#elif PLATFORM(ANDROID)
static const char* types[] = {
"image/jpeg",
@@ -132,6 +139,7 @@ static void initializeSupportedImageMIMETypes()
"image/png",
"image/gif",
"image/bmp",
+ "image/vnd.microsoft.icon", // ico
"image/x-icon", // ico
"image/x-xbitmap" // xbm
};
@@ -169,6 +177,8 @@ static void initializeSupportedImageMIMETypesForEncoding()
String mimeType = MIMETypeRegistry::getMIMETypeForExtension(formats.at(i).constData());
supportedImageMIMETypesForEncoding->add(mimeType);
}
+
+ supportedImageMIMETypesForEncoding->remove("application/octet-stream");
#elif PLATFORM(CAIRO)
supportedImageMIMETypesForEncoding->add("image/png");
#endif
@@ -214,6 +224,9 @@ static void initializeSupportedNonImageMimeTypes()
"text/",
"application/xml",
"application/xhtml+xml",
+#if ENABLE(XHTMLMP)
+ "application/vnd.wap.xhtml+xml",
+#endif
"application/rss+xml",
"application/atom+xml",
#if ENABLE(SVG)
@@ -232,6 +245,103 @@ static void initializeSupportedNonImageMimeTypes()
#endif
}
+static void initializeMediaTypeMaps()
+{
+ struct TypeExtensionPair {
+ const char* type;
+ const char* extension;
+ };
+
+ // A table of common media MIME types and file extenstions used when a platform's
+ // specific MIME type lookup doens't have a match for a media file extension. While some
+ // file extensions are claimed by multiple MIME types, this table only includes one
+ // for each because it is currently only used by getMediaMIMETypeForExtension. If we
+ // ever add a MIME type -> file extension mapping, the alternate MIME types will need
+ // to be added.
+ static const TypeExtensionPair pairs[] = {
+
+ // Ogg
+ { "application/ogg", "ogg" },
+ { "application/ogg", "ogx" },
+ { "audio/ogg", "oga" },
+ { "video/ogg", "ogv" },
+
+ // Annodex
+ { "application/annodex", "anx" },
+ { "audio/annodex", "axa" },
+ { "video/annodex", "axv" },
+ { "audio/speex", "spx" },
+
+ // MPEG
+ { "audio/mpeg", "m1a" },
+ { "audio/mpeg", "m2a" },
+ { "audio/mpeg", "m1s" },
+ { "audio/mpeg", "mpa" },
+ { "video/mpeg", "mpg" },
+ { "video/mpeg", "m15" },
+ { "video/mpeg", "m1s" },
+ { "video/mpeg", "m1v" },
+ { "video/mpeg", "m75" },
+ { "video/mpeg", "mpa" },
+ { "video/mpeg", "mpeg" },
+ { "video/mpeg", "mpm" },
+ { "video/mpeg", "mpv" },
+
+ // MPEG playlist
+ { "audio/x-mpegurl", "m3url" },
+ { "application/x-mpegurl", "m3u8" },
+
+ // MPEG-4
+ { "video/x-m4v", "m4v" },
+ { "audio/x-m4a", "m4a" },
+ { "audio/x-m4b", "m4b" },
+ { "audio/x-m4p", "m4p" },
+
+ // MP3
+ { "audio/mp3", "mp3" },
+
+ // MPEG-2
+ { "video/x-mpeg2", "mp2" },
+ { "video/mpeg2", "vob" },
+ { "video/mpeg2", "mod" },
+ { "video/m2ts", "m2ts" },
+ { "video/x-m2ts", "m2t" },
+ { "video/x-m2ts", "ts" },
+
+ // 3GP/3GP2
+ { "audio/3gpp", "3gpp" },
+ { "audio/3gpp2", "3g2" },
+ { "application/x-mpeg", "amc" },
+
+ // AAC
+ { "audio/aac", "aac" },
+ { "audio/aac", "adts" },
+ { "audio/x-aac", "m4r" },
+
+ // CoreAudio File
+ { "audio/x-caf", "caf" },
+ { "audio/x-gsm", "gsm" }
+ };
+
+ mediaMIMETypeForExtensionMap = new HashMap<String, String, CaseFoldingHash>;
+ const unsigned numPairs = sizeof(pairs) / sizeof(pairs[0]);
+ for (unsigned ndx = 0; ndx < numPairs; ++ndx)
+ mediaMIMETypeForExtensionMap->set(pairs[ndx].extension, pairs[ndx].type);
+}
+
+String MIMETypeRegistry::getMediaMIMETypeForExtension(const String& ext)
+{
+ // Check with system specific implementation first.
+ String mimeType = getMIMETypeForExtension(ext);
+ if (!mimeType.isEmpty())
+ return mimeType;
+
+ // No match, look in the static mapping.
+ if (!mediaMIMETypeForExtensionMap)
+ initializeMediaTypeMaps();
+ return mediaMIMETypeForExtensionMap->get(ext);
+}
+
static void initializeSupportedMediaMIMETypes()
{
supportedMediaMIMETypes = new HashSet<String>;
@@ -365,4 +475,10 @@ HashSet<String>& MIMETypeRegistry::getSupportedMediaMIMETypes()
return *supportedMediaMIMETypes;
}
+const String& defaultMIMEType()
+{
+ DEFINE_STATIC_LOCAL(const String, defaultMIMEType, ("application/octet-stream"));
+ return defaultMIMEType;
+}
+
} // namespace WebCore
diff --git a/WebCore/platform/MIMETypeRegistry.h b/WebCore/platform/MIMETypeRegistry.h
index fca467f..8801ac1 100644
--- a/WebCore/platform/MIMETypeRegistry.h
+++ b/WebCore/platform/MIMETypeRegistry.h
@@ -38,6 +38,7 @@ public:
static String getMIMETypeForExtension(const String& ext);
static Vector<String> getExtensionsForMIMEType(const String& type);
static String getPreferredExtensionForMIMEType(const String& type);
+ static String getMediaMIMETypeForExtension(const String& ext);
static String getMIMETypeForPath(const String& path);
@@ -73,6 +74,8 @@ public:
static HashSet<String>& getSupportedMediaMIMETypes();
};
+const String& defaultMIMEType();
+
} // namespace WebCore
#endif // MIMETypeRegistry_h
diff --git a/WebCore/platform/PlatformMouseEvent.h b/WebCore/platform/PlatformMouseEvent.h
index 9f6bea9..2543d40 100644
--- a/WebCore/platform/PlatformMouseEvent.h
+++ b/WebCore/platform/PlatformMouseEvent.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,26 +27,6 @@
#define PlatformMouseEvent_h
#include "IntPoint.h"
-#include <wtf/Platform.h>
-
-#if PLATFORM(MAC)
-#ifdef __OBJC__
-@class NSEvent;
-@class NSScreen;
-@class NSWindow;
-#else
-class NSEvent;
-class NSScreen;
-class NSWindow;
-#endif
-#endif
-
-#if PLATFORM(WIN)
-typedef struct HWND__* HWND;
-typedef unsigned UINT;
-typedef unsigned WPARAM;
-typedef long LPARAM;
-#endif
#if PLATFORM(GTK)
typedef struct _GdkEventButton GdkEventButton;
@@ -59,6 +39,13 @@ class QInputEvent;
QT_END_NAMESPACE
#endif
+#if PLATFORM(WIN)
+typedef struct HWND__* HWND;
+typedef unsigned UINT;
+typedef unsigned WPARAM;
+typedef long LPARAM;
+#endif
+
#if PLATFORM(WX)
class wxMouseEvent;
#endif
@@ -84,9 +71,11 @@ namespace WebCore {
{
}
- PlatformMouseEvent(const IntPoint& pos, const IntPoint& globalPos, MouseButton button, MouseEventType eventType,
+ PlatformMouseEvent(const IntPoint& position, const IntPoint& globalPosition, MouseButton button, MouseEventType eventType,
int clickCount, bool shift, bool ctrl, bool alt, bool meta, double timestamp)
- : m_position(pos), m_globalPosition(globalPos), m_button(button)
+ : m_position(position)
+ , m_globalPosition(globalPosition)
+ , m_button(button)
, m_eventType(eventType)
, m_clickCount(clickCount)
, m_shiftKey(shift)
@@ -112,29 +101,32 @@ namespace WebCore {
bool metaKey() const { return m_metaKey; }
unsigned modifierFlags() const { return m_modifierFlags; }
- //time in seconds
+ // Time in seconds.
double timestamp() const { return m_timestamp; }
-#if PLATFORM(MAC)
- PlatformMouseEvent(NSEvent*);
- int eventNumber() const { return m_eventNumber; }
-#endif
-#if PLATFORM(WIN)
- PlatformMouseEvent(HWND, UINT, WPARAM, LPARAM, bool activatedWebView = false);
- void setClickCount(int count) { m_clickCount = count; }
- bool activatedWebView() const { return m_activatedWebView; }
-#endif
#if PLATFORM(GTK)
PlatformMouseEvent(GdkEventButton*);
PlatformMouseEvent(GdkEventMotion*);
#endif
+
+#if PLATFORM(MAC) && defined(__OBJC__)
+ PlatformMouseEvent(NSEvent *, NSView *windowView);
+ int eventNumber() const { return m_eventNumber; }
+#endif
+
#if PLATFORM(QT)
PlatformMouseEvent(QInputEvent*, int clickCount);
#endif
-#if PLATFORM(WX)
- PlatformMouseEvent(const wxMouseEvent&, const wxPoint& globalPoint);
+
+#if PLATFORM(WIN)
+ PlatformMouseEvent(HWND, UINT, WPARAM, LPARAM, bool activatedWebView = false);
+ void setClickCount(int count) { m_clickCount = count; }
+ bool activatedWebView() const { return m_activatedWebView; }
#endif
+#if PLATFORM(WX)
+ PlatformMouseEvent(const wxMouseEvent&, const wxPoint& globalPoint, int clickCount);
+#endif
protected:
IntPoint m_position;
@@ -148,18 +140,20 @@ namespace WebCore {
bool m_metaKey;
double m_timestamp; // unit: seconds
unsigned m_modifierFlags;
+
#if PLATFORM(MAC)
int m_eventNumber;
#endif
+
#if PLATFORM(WIN)
bool m_activatedWebView;
#endif
};
-#if PLATFORM(MAC)
- IntPoint globalPoint(const NSPoint& windowPoint, NSWindow *window);
- IntPoint pointForEvent(NSEvent *event);
- IntPoint globalPointForEvent(NSEvent *event);
+#if PLATFORM(MAC) && defined(__OBJC__)
+ IntPoint globalPoint(const NSPoint& windowPoint, NSWindow *);
+ IntPoint pointForEvent(NSEvent *, NSView *windowView);
+ IntPoint globalPointForEvent(NSEvent *);
#endif
} // namespace WebCore
diff --git a/WebCore/platform/PlatformWheelEvent.h b/WebCore/platform/PlatformWheelEvent.h
index 9395e93..037c4b7 100644
--- a/WebCore/platform/PlatformWheelEvent.h
+++ b/WebCore/platform/PlatformWheelEvent.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,20 +28,6 @@
#include "IntPoint.h"
-#if PLATFORM(MAC)
-#ifdef __OBJC__
-@class NSEvent;
-#else
-class NSEvent;
-#endif
-#endif
-
-#if PLATFORM(WIN)
-typedef struct HWND__* HWND;
-typedef unsigned WPARAM;
-typedef long LPARAM;
-#endif
-
#if PLATFORM(GTK)
typedef struct _GdkEventScroll GdkEventScroll;
#endif
@@ -52,6 +38,12 @@ class QWheelEvent;
QT_END_NAMESPACE
#endif
+#if PLATFORM(WIN)
+typedef struct HWND__* HWND;
+typedef unsigned WPARAM;
+typedef long LPARAM;
+#endif
+
#if PLATFORM(WX)
class wxMouseEvent;
class wxPoint;
@@ -93,18 +85,22 @@ namespace WebCore {
void accept() { m_isAccepted = true; }
void ignore() { m_isAccepted = false; }
-#if PLATFORM(MAC)
- PlatformWheelEvent(NSEvent*);
-#endif
-#if PLATFORM(WIN)
- PlatformWheelEvent(HWND, WPARAM, LPARAM, bool isMouseHWheel);
-#endif
#if PLATFORM(GTK)
PlatformWheelEvent(GdkEventScroll*);
#endif
+
+#if PLATFORM(MAC) && defined(__OBJC__)
+ PlatformWheelEvent(NSEvent *, NSView *windowView);
+#endif
+
#if PLATFORM(QT)
PlatformWheelEvent(QWheelEvent*);
#endif
+
+#if PLATFORM(WIN)
+ PlatformWheelEvent(HWND, WPARAM, LPARAM, bool isMouseHWheel);
+#endif
+
#if PLATFORM(WX)
PlatformWheelEvent(const wxMouseEvent&, const wxPoint&);
#endif
diff --git a/WebCore/platform/ScrollView.cpp b/WebCore/platform/ScrollView.cpp
index 5a12304..f0db95a 100644
--- a/WebCore/platform/ScrollView.cpp
+++ b/WebCore/platform/ScrollView.cpp
@@ -47,6 +47,7 @@ ScrollView::ScrollView()
, m_scrollbarsAvoidingResizer(0)
, m_scrollbarsSuppressed(false)
, m_inUpdateScrollbars(false)
+ , m_updateScrollbarsPass(0)
, m_drawPanScrollIcon(false)
, m_useFixedLayout(false)
{
@@ -78,7 +79,7 @@ void ScrollView::removeChild(Widget* child)
void ScrollView::setHasHorizontalScrollbar(bool hasBar)
{
- if (hasBar && !m_horizontalScrollbar && !platformHasHorizontalAdjustment()) {
+ if (hasBar && !m_horizontalScrollbar) {
m_horizontalScrollbar = createScrollbar(HorizontalScrollbar);
addChild(m_horizontalScrollbar.get());
} else if (!hasBar && m_horizontalScrollbar) {
@@ -89,7 +90,7 @@ void ScrollView::setHasHorizontalScrollbar(bool hasBar)
void ScrollView::setHasVerticalScrollbar(bool hasBar)
{
- if (hasBar && !m_verticalScrollbar && !platformHasVerticalAdjustment()) {
+ if (hasBar && !m_verticalScrollbar) {
m_verticalScrollbar = createScrollbar(VerticalScrollbar);
addChild(m_verticalScrollbar.get());
} else if (!hasBar && m_verticalScrollbar) {
@@ -98,10 +99,12 @@ void ScrollView::setHasVerticalScrollbar(bool hasBar)
}
}
+#if !PLATFORM(GTK)
PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientation)
{
return Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
}
+#endif
void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode)
{
@@ -238,9 +241,9 @@ void ScrollView::valueChanged(Scrollbar* scrollbar)
// Figure out if we really moved.
IntSize newOffset = m_scrollOffset;
if (scrollbar) {
- if (scrollbar == m_horizontalScrollbar)
+ if (scrollbar->orientation() == HorizontalScrollbar)
newOffset.setWidth(scrollbar->value());
- else if (scrollbar == m_verticalScrollbar)
+ else if (scrollbar->orientation() == VerticalScrollbar)
newOffset.setHeight(scrollbar->value());
}
@@ -318,62 +321,99 @@ bool ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity
return false;
}
+static const unsigned cMaxUpdateScrollbarsPass = 2;
+
void ScrollView::updateScrollbars(const IntSize& desiredOffset)
{
- // Don't allow re-entrancy into this function.
if (m_inUpdateScrollbars || prohibitsScrolling() || platformWidget())
return;
- m_inUpdateScrollbars = true;
-
- bool hasVerticalScrollbar = m_verticalScrollbar;
bool hasHorizontalScrollbar = m_horizontalScrollbar;
- bool oldHasVertical = hasVerticalScrollbar;
- bool oldHasHorizontal = hasHorizontalScrollbar;
+ bool hasVerticalScrollbar = m_verticalScrollbar;
+
+ bool newHasHorizontalScrollbar = hasHorizontalScrollbar;
+ bool newHasVerticalScrollbar = hasVerticalScrollbar;
+
ScrollbarMode hScroll = m_horizontalScrollbarMode;
ScrollbarMode vScroll = m_verticalScrollbarMode;
- const int scrollbarThickness = ScrollbarTheme::nativeTheme()->scrollbarThickness();
+ if (hScroll != ScrollbarAuto)
+ newHasHorizontalScrollbar = (hScroll == ScrollbarAlwaysOn);
+ if (vScroll != ScrollbarAuto)
+ newHasVerticalScrollbar = (vScroll == ScrollbarAlwaysOn);
- for (int pass = 0; pass < 2; pass++) {
- bool scrollsVertically;
- bool scrollsHorizontally;
+ if (m_scrollbarsSuppressed || (hScroll != ScrollbarAuto && vScroll != ScrollbarAuto)) {
+ if (hasHorizontalScrollbar != newHasHorizontalScrollbar)
+ setHasHorizontalScrollbar(newHasHorizontalScrollbar);
+ if (hasVerticalScrollbar != newHasVerticalScrollbar)
+ setHasVerticalScrollbar(newHasVerticalScrollbar);
+ } else {
+ // If we came in here with the view already needing a layout, then go ahead and do that
+ // first. (This will be the common case, e.g., when the page changes due to window resizing for example).
+ // This layout will not re-enter updateScrollers and does not count towards our max layout pass total.
+ m_inUpdateScrollbars = true;
+ visibleContentsResized();
+ m_inUpdateScrollbars = false;
+
+ bool sendContentResizedNotification = false;
+
+ IntSize docSize = contentsSize();
+ IntSize frameSize = frameRect().size();
- if (!m_scrollbarsSuppressed && (hScroll == ScrollbarAuto || vScroll == ScrollbarAuto)) {
- // Do a layout if pending before checking if scrollbars are needed.
- if (hasVerticalScrollbar != oldHasVertical || hasHorizontalScrollbar != oldHasHorizontal)
- visibleContentsResized();
+ if (hScroll == ScrollbarAuto) {
+ newHasHorizontalScrollbar = docSize.width() > visibleWidth();
+ if (newHasHorizontalScrollbar && !m_updateScrollbarsPass && docSize.width() <= frameSize.width() && docSize.height() <= frameSize.height())
+ newHasHorizontalScrollbar = false;
+ }
+ if (vScroll == ScrollbarAuto) {
+ newHasVerticalScrollbar = docSize.height() > visibleHeight();
+ if (newHasVerticalScrollbar && !m_updateScrollbarsPass && docSize.width() <= frameSize.width() && docSize.height() <= frameSize.height())
+ newHasVerticalScrollbar = false;
+ }
- scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() > height());
- if (scrollsVertically)
- scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() + scrollbarThickness > width());
- else {
- scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() > width());
- if (scrollsHorizontally)
- scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() + scrollbarThickness > height());
- }
- } else {
- scrollsHorizontally = (hScroll == ScrollbarAuto) ? hasHorizontalScrollbar : (hScroll == ScrollbarAlwaysOn);
- scrollsVertically = (vScroll == ScrollbarAuto) ? hasVerticalScrollbar : (vScroll == ScrollbarAlwaysOn);
+ // If we ever turn one scrollbar off, always turn the other one off too. Never ever
+ // try to both gain/lose a scrollbar in the same pass.
+ if (!newHasHorizontalScrollbar && hasHorizontalScrollbar && vScroll != ScrollbarAlwaysOn)
+ newHasVerticalScrollbar = false;
+ if (!newHasVerticalScrollbar && hasVerticalScrollbar && hScroll != ScrollbarAlwaysOn)
+ newHasHorizontalScrollbar = false;
+
+ if (hasHorizontalScrollbar != newHasHorizontalScrollbar) {
+ setHasHorizontalScrollbar(newHasHorizontalScrollbar);
+ sendContentResizedNotification = true;
}
-
- if (hasVerticalScrollbar != scrollsVertically) {
- setHasVerticalScrollbar(scrollsVertically);
- hasVerticalScrollbar = scrollsVertically;
+
+ if (hasVerticalScrollbar != newHasVerticalScrollbar) {
+ setHasVerticalScrollbar(newHasVerticalScrollbar);
+ sendContentResizedNotification = true;
}
- if (hasHorizontalScrollbar != scrollsHorizontally) {
- setHasHorizontalScrollbar(scrollsHorizontally);
- hasHorizontalScrollbar = scrollsHorizontally;
+ if (sendContentResizedNotification && m_updateScrollbarsPass < cMaxUpdateScrollbarsPass) {
+ m_updateScrollbarsPass++;
+ contentsResized();
+ visibleContentsResized();
+ IntSize newDocSize = contentsSize();
+ if (newDocSize == docSize) {
+ // The layout with the new scroll state had no impact on
+ // the document's overall size, so updateScrollbars didn't get called.
+ // Recur manually.
+ updateScrollbars(desiredOffset);
+ }
+ m_updateScrollbarsPass--;
}
}
- // Set up the range (and page step/line step).
+ // Set up the range (and page step/line step), but only do this if we're not in a nested call (to avoid
+ // doing it multiple times).
+ if (m_updateScrollbarsPass)
+ return;
+
+ m_inUpdateScrollbars = true;
IntSize maxScrollPosition(contentsWidth() - visibleWidth(), contentsHeight() - visibleHeight());
IntSize scroll = desiredOffset.shrunkTo(maxScrollPosition);
scroll.clampNegativeToZero();
- if (!platformHandleHorizontalAdjustment(scroll) && m_horizontalScrollbar) {
+ if (m_horizontalScrollbar) {
int clientWidth = visibleWidth();
m_horizontalScrollbar->setEnabled(contentsWidth() > clientWidth);
int pageStep = (clientWidth - cAmountToKeepWhenPaging);
@@ -397,7 +437,7 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset)
m_horizontalScrollbar->setSuppressInvalidation(false);
}
- if (!platformHandleVerticalAdjustment(scroll) && m_verticalScrollbar) {
+ if (m_verticalScrollbar) {
int clientHeight = visibleHeight();
m_verticalScrollbar->setEnabled(contentsHeight() > clientHeight);
int pageStep = (clientHeight - cAmountToKeepWhenPaging);
@@ -421,7 +461,7 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset)
m_verticalScrollbar->setSuppressInvalidation(false);
}
- if (oldHasVertical != (m_verticalScrollbar != 0) || oldHasHorizontal != (m_horizontalScrollbar != 0))
+ if (hasHorizontalScrollbar != (m_horizontalScrollbar != 0) || hasVerticalScrollbar != (m_verticalScrollbar != 0))
frameRectsChanged();
// See if our offset has changed in a situation where we might not have scrollbars.
@@ -467,7 +507,7 @@ void ScrollView::scrollContents(const IntSize& scrollDelta)
hostWindow()->scroll(-scrollDelta, scrollViewRect, clipRect);
} else {
// We need to go ahead and repaint the entire backing store. Do it now before moving the
- // plugins.
+ // windowed plugins.
hostWindow()->repaint(updateRect, true, false, true); // Invalidate the backing store and repaint it synchronously
}
@@ -548,8 +588,16 @@ void ScrollView::setParent(ScrollView* parentView)
if (m_scrollbarsAvoidingResizer && parent())
parent()->adjustScrollbarsAvoidingResizerCount(-m_scrollbarsAvoidingResizer);
+#if PLATFORM(QT)
+ if (m_widgetsPreventingBlitting && parent())
+ parent()->adjustWidgetsPreventingBlittingCount(-m_widgetsPreventingBlitting);
+
+ if (m_widgetsPreventingBlitting && parentView)
+ parentView->adjustWidgetsPreventingBlittingCount(m_widgetsPreventingBlitting);
+#endif
+
Widget::setParent(parentView);
-
+
if (m_scrollbarsAvoidingResizer && parent())
parent()->adjustScrollbarsAvoidingResizerCount(m_scrollbarsAvoidingResizer);
}
@@ -606,8 +654,13 @@ Scrollbar* ScrollView::scrollbarUnderMouse(const PlatformMouseEvent& mouseEvent)
void ScrollView::wheelEvent(PlatformWheelEvent& e)
{
// We don't allow mouse wheeling to happen in a ScrollView that has had its scrollbars explicitly disabled.
- if (!canHaveScrollbars() || platformWidget())
+#if PLATFORM(WX)
+ if (!canHaveScrollbars()) {
+#else
+ if (!canHaveScrollbars() || platformWidget()) {
+#endif
return;
+ }
// Determine how much we want to scroll. If we can move at all, we will accept the event.
IntSize maxScrollDelta = maximumScrollPosition() - scrollPosition();
@@ -817,6 +870,7 @@ void ScrollView::removePanScrollIcon()
}
#if !PLATFORM(WX) && !PLATFORM(GTK) && !PLATFORM(QT)
+
void ScrollView::platformInit()
{
}
@@ -824,9 +878,11 @@ void ScrollView::platformInit()
void ScrollView::platformDestroy()
{
}
+
#endif
#if !PLATFORM(WX) && !PLATFORM(GTK) && !PLATFORM(QT) && !PLATFORM(MAC)
+
void ScrollView::platformAddChild(Widget*)
{
}
@@ -834,15 +890,19 @@ void ScrollView::platformAddChild(Widget*)
void ScrollView::platformRemoveChild(Widget*)
{
}
+
#endif
#if !PLATFORM(MAC)
+
void ScrollView::platformSetScrollbarsSuppressed(bool repaintOnUnsuppress)
{
}
+
#endif
#if !PLATFORM(MAC) && !PLATFORM(WX)
+
void ScrollView::platformSetScrollbarModes()
{
}
@@ -850,6 +910,8 @@ void ScrollView::platformSetScrollbarModes()
#if !PLATFORM(ANDROID)
void ScrollView::platformScrollbarModes(ScrollbarMode& horizontal, ScrollbarMode& vertical) const
{
+ horizontal = ScrollbarAuto;
+ vertical = ScrollbarAuto;
}
#endif
@@ -917,28 +979,6 @@ bool ScrollView::platformIsOffscreen() const
{
return false;
}
-#endif
-
-#if !PLATFORM(GTK)
-bool ScrollView::platformHandleHorizontalAdjustment(const IntSize&)
-{
- return false;
-}
-
-bool ScrollView::platformHandleVerticalAdjustment(const IntSize&)
-{
- return false;
-}
-
-bool ScrollView::platformHasHorizontalAdjustment() const
-{
- return false;
-}
-
-bool ScrollView::platformHasVerticalAdjustment() const
-{
- return false;
-}
#endif
diff --git a/WebCore/platform/ScrollView.h b/WebCore/platform/ScrollView.h
index f7bfbe8..9847350 100644
--- a/WebCore/platform/ScrollView.h
+++ b/WebCore/platform/ScrollView.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2004, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Holger Hans Peter Freyther
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -46,9 +47,6 @@ typedef struct _GtkAdjustment GtkAdjustment;
class wxScrollWinEvent;
#endif
-// DANGER WILL ROBINSON! THIS FILE IS UNDERGOING HEAVY REFACTORING.
-// Everything is changing!
-// Port authors should wait until this refactoring is complete before attempting to implement this interface.
namespace WebCore {
class HostWindow;
@@ -125,7 +123,7 @@ public:
// Methods for getting/setting the size of the document contained inside the ScrollView (as an IntSize or as individual width and height
// values).
- IntSize contentsSize() const;
+ IntSize contentsSize() const; // Always at least as big as the visibleWidth()/visibleHeight().
int contentsWidth() const { return contentsSize().width(); }
int contentsHeight() const { return contentsSize().height(); }
virtual void setContentsSize(const IntSize&);
@@ -254,6 +252,7 @@ private:
bool m_scrollbarsSuppressed;
bool m_inUpdateScrollbars;
+ unsigned m_updateScrollbarsPass;
IntPoint m_panScrollIconPoint;
bool m_drawPanScrollIcon;
@@ -283,10 +282,6 @@ private:
void platformSetScrollbarsSuppressed(bool repaintOnUnsuppress);
void platformRepaintContentRectangle(const IntRect&, bool now);
bool platformIsOffscreen() const;
- bool platformHandleHorizontalAdjustment(const IntSize&);
- bool platformHandleVerticalAdjustment(const IntSize&);
- bool platformHasHorizontalAdjustment() const;
- bool platformHasVerticalAdjustment() const;
#if PLATFORM(MAC) && defined __OBJC__
public:
@@ -297,9 +292,11 @@ private:
#endif
#if PLATFORM(QT)
+public:
+ void adjustWidgetsPreventingBlittingCount(int delta);
private:
- bool rootPreventsBlitting() const { return root()->m_widgetsThatPreventBlitting > 0; }
- unsigned m_widgetsThatPreventBlitting;
+ bool rootPreventsBlitting() const { return root()->m_widgetsPreventingBlitting > 0; }
+ unsigned m_widgetsPreventingBlitting;
#else
bool rootPreventsBlitting() const { return false; }
#endif
diff --git a/WebCore/platform/Scrollbar.cpp b/WebCore/platform/Scrollbar.cpp
index 13bb0c9..babf3d4 100644
--- a/WebCore/platform/Scrollbar.cpp
+++ b/WebCore/platform/Scrollbar.cpp
@@ -57,6 +57,7 @@ Scrollbar::Scrollbar(ScrollbarClient* client, ScrollbarOrientation orientation,
, m_visibleSize(0)
, m_totalSize(0)
, m_currentPos(0)
+ , m_dragOrigin(0)
, m_lineStep(0)
, m_pageStep(0)
, m_pixelStep(1)
@@ -92,13 +93,7 @@ bool Scrollbar::setValue(int v)
v = max(min(v, m_totalSize - m_visibleSize), 0);
if (value() == v)
return false; // Our value stayed the same.
- m_currentPos = v;
-
- updateThumbPosition();
-
- if (client())
- client()->valueChanged(this);
-
+ setCurrentPos(v);
return true;
}
@@ -139,20 +134,7 @@ bool Scrollbar::scroll(ScrollDirection direction, ScrollGranularity granularity,
float newPos = m_currentPos + step * multiplier;
float maxPos = m_totalSize - m_visibleSize;
- newPos = max(min(newPos, maxPos), 0.0f);
-
- if (newPos == m_currentPos)
- return false;
-
- int oldValue = value();
- m_currentPos = newPos;
- updateThumbPosition();
-
- if (value() != oldValue && client())
- client()->valueChanged(this);
-
- // return true even if the integer value did not change so that scroll event gets eaten
- return true;
+ return setCurrentPos(max(min(newPos, maxPos), 0.0f));
}
void Scrollbar::updateThumbPosition()
@@ -269,15 +251,30 @@ void Scrollbar::moveThumb(int pos)
int thumbLen = theme()->thumbLength(this);
int trackLen = theme()->trackLength(this);
int maxPos = trackLen - thumbLen;
- int delta = pos - pressedPos();
+ int delta = pos - m_pressedPos;
if (delta > 0)
delta = min(maxPos - thumbPos, delta);
else if (delta < 0)
delta = max(-thumbPos, delta);
- if (delta) {
- setValue(static_cast<int>(static_cast<float>(thumbPos + delta) * maximum() / (trackLen - thumbLen)));
- setPressedPos(pressedPos() + theme()->thumbPosition(this) - thumbPos);
- }
+ if (delta)
+ setCurrentPos(static_cast<float>(thumbPos + delta) * maximum() / (trackLen - thumbLen));
+}
+
+bool Scrollbar::setCurrentPos(float pos)
+{
+ if (pos == m_currentPos)
+ return false;
+
+ int oldValue = value();
+ int oldThumbPos = theme()->thumbPosition(this);
+ m_currentPos = pos;
+ updateThumbPosition();
+ if (m_pressedPart == ThumbPart)
+ setPressedPos(m_pressedPos + theme()->thumbPosition(this) - oldThumbPos);
+
+ if (value() != oldValue && client())
+ client()->valueChanged(this);
+ return true;
}
void Scrollbar::setHoveredPart(ScrollbarPart part)
@@ -287,7 +284,7 @@ void Scrollbar::setHoveredPart(ScrollbarPart part)
if ((m_hoveredPart == NoPart || part == NoPart) && theme()->invalidateOnMouseEnterExit())
invalidate(); // Just invalidate the whole scrollbar, since the buttons at either end change anyway.
- else if (m_pressedPart == NoPart) {
+ else if (m_pressedPart == NoPart) { // When there's a pressed part, we don't draw a hovered state, so there's no reason to invalidate.
theme()->invalidatePart(this, part);
theme()->invalidatePart(this, m_hoveredPart);
}
@@ -301,14 +298,20 @@ void Scrollbar::setPressedPart(ScrollbarPart part)
m_pressedPart = part;
if (m_pressedPart != NoPart)
theme()->invalidatePart(this, m_pressedPart);
+ else if (m_hoveredPart != NoPart) // When we no longer have a pressed part, we can start drawing a hovered state on the hovered part.
+ theme()->invalidatePart(this, m_hoveredPart);
}
bool Scrollbar::mouseMoved(const PlatformMouseEvent& evt)
{
if (m_pressedPart == ThumbPart) {
- moveThumb(m_orientation == HorizontalScrollbar ?
- convertFromContainingWindow(evt.pos()).x() :
- convertFromContainingWindow(evt.pos()).y());
+ if (theme()->shouldSnapBackToDragOrigin(this, evt))
+ setCurrentPos(m_dragOrigin);
+ else {
+ moveThumb(m_orientation == HorizontalScrollbar ?
+ convertFromContainingWindow(evt.pos()).x() :
+ convertFromContainingWindow(evt.pos()).y());
+ }
return true;
}
@@ -364,9 +367,10 @@ bool Scrollbar::mouseDown(const PlatformMouseEvent& evt)
setPressedPart(theme()->hitTest(this, evt));
int pressedPos = (orientation() == HorizontalScrollbar ? convertFromContainingWindow(evt.pos()).x() : convertFromContainingWindow(evt.pos()).y());
- if ((pressedPart() == BackTrackPart || pressedPart() == ForwardTrackPart) && theme()->shouldCenterOnThumb(this, evt)) {
+ if ((m_pressedPart == BackTrackPart || m_pressedPart == ForwardTrackPart) && theme()->shouldCenterOnThumb(this, evt)) {
setHoveredPart(ThumbPart);
setPressedPart(ThumbPart);
+ m_dragOrigin = m_currentPos;
int thumbLen = theme()->thumbLength(this);
int desiredPos = pressedPos;
// Set the pressed position to the middle of the thumb so that when we do the move, the delta
@@ -374,7 +378,8 @@ bool Scrollbar::mouseDown(const PlatformMouseEvent& evt)
m_pressedPos = theme()->trackPosition(this) + theme()->thumbPosition(this) + thumbLen / 2;
moveThumb(desiredPos);
return true;
- }
+ } else if (m_pressedPart == ThumbPart)
+ m_dragOrigin = m_currentPos;
m_pressedPos = pressedPos;
diff --git a/WebCore/platform/Scrollbar.h b/WebCore/platform/Scrollbar.h
index 2c5b274..19d95d7 100644
--- a/WebCore/platform/Scrollbar.h
+++ b/WebCore/platform/Scrollbar.h
@@ -125,6 +125,9 @@ public:
virtual void styleChanged() { }
+private:
+ virtual bool isScrollbar() const { return true; }
+
protected:
virtual void updateThumbPosition();
virtual void updateThumbProportion();
@@ -137,6 +140,7 @@ protected:
ScrollGranularity pressedPartScrollGranularity();
void moveThumb(int pos);
+ bool setCurrentPos(float pos);
ScrollbarClient* m_client;
ScrollbarOrientation m_orientation;
@@ -146,6 +150,7 @@ protected:
int m_visibleSize;
int m_totalSize;
float m_currentPos;
+ float m_dragOrigin;
int m_lineStep;
int m_pageStep;
float m_pixelStep;
diff --git a/WebCore/platform/ScrollbarTheme.h b/WebCore/platform/ScrollbarTheme.h
index e2aebc6..9327dc6 100644
--- a/WebCore/platform/ScrollbarTheme.h
+++ b/WebCore/platform/ScrollbarTheme.h
@@ -76,6 +76,7 @@ public:
virtual void paintScrollCorner(ScrollView*, GraphicsContext* context, const IntRect& cornerRect) { context->fillRect(cornerRect, Color::white); }
virtual bool shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent&) { return false; }
+ virtual bool shouldSnapBackToDragOrigin(Scrollbar*, const PlatformMouseEvent&) { return false; }
virtual int thumbPosition(Scrollbar*) { return 0; } // The position of the thumb relative to the track.
virtual int thumbLength(Scrollbar*) { return 0; } // The length of the thumb along the axis of the scrollbar.
virtual int trackPosition(Scrollbar*) { return 0; } // The position of the track relative to the scrollbar.
diff --git a/WebCore/platform/SharedBuffer.h b/WebCore/platform/SharedBuffer.h
index 3675a3b..3404a0c 100644
--- a/WebCore/platform/SharedBuffer.h
+++ b/WebCore/platform/SharedBuffer.h
@@ -70,6 +70,7 @@ public:
#endif
#if PLATFORM(CF)
CFDataRef createCFData();
+ static PassRefPtr<SharedBuffer> wrapCFData(CFDataRef);
#endif
const char* data() const;
diff --git a/WebCore/platform/SuddenTermination.h b/WebCore/platform/SuddenTermination.h
new file mode 100644
index 0000000..7171102
--- /dev/null
+++ b/WebCore/platform/SuddenTermination.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SuddenTermination_h
+#define SuddenTermination_h
+
+#include <wtf/Platform.h>
+
+namespace WebCore {
+
+ void disableSuddenTermination();
+ void enableSuddenTermination();
+
+#if (!PLATFORM(MAC) || defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)) && !PLATFORM(CHROMIUM)
+ inline void disableSuddenTermination() { }
+ inline void enableSuddenTermination() { }
+#endif
+
+} // namespace WebCore
+
+#endif // SuddenTermination_h
diff --git a/WebCore/platform/ThreadGlobalData.cpp b/WebCore/platform/ThreadGlobalData.cpp
index 903af66..a43e9bd 100644
--- a/WebCore/platform/ThreadGlobalData.cpp
+++ b/WebCore/platform/ThreadGlobalData.cpp
@@ -32,7 +32,7 @@
#include "ThreadTimers.h"
#include <wtf/UnusedParam.h>
-#if USE(ICU_UNICODE)
+#if USE(ICU_UNICODE) || USE(GLIB_ICU_UNICODE_HYBRID)
#include "TextCodecICU.h"
#endif
@@ -72,7 +72,10 @@ ThreadGlobalData::ThreadGlobalData()
, m_atomicStringTable(new HashSet<StringImpl*>)
, m_eventNames(new EventNames)
, m_threadTimers(new ThreadTimers)
-#if USE(ICU_UNICODE)
+#ifndef NDEBUG
+ , m_isMainThread(isMainThread())
+#endif
+#if USE(ICU_UNICODE) || USE(GLIB_ICU_UNICODE_HYBRID)
, m_cachedConverterICU(new ICUConverterWrapper)
#endif
#if PLATFORM(MAC)
@@ -86,7 +89,7 @@ ThreadGlobalData::~ThreadGlobalData()
#if PLATFORM(MAC)
delete m_cachedConverterTEC;
#endif
-#if USE(ICU_UNICODE)
+#if USE(ICU_UNICODE) || USE(GLIB_ICU_UNICODE_HYBRID)
delete m_cachedConverterICU;
#endif
@@ -94,7 +97,12 @@ ThreadGlobalData::~ThreadGlobalData()
delete m_atomicStringTable;
delete m_threadTimers;
- ASSERT(isMainThread() || m_emptyString->hasOneRef()); // We intentionally don't clean up static data on application quit, so there will be many strings remaining on the main thread.
+ // Using member variable m_isMainThread instead of calling WTF::isMainThread() directly
+ // to avoid issues described in https://bugs.webkit.org/show_bug.cgi?id=25973.
+ // In short, some pthread-based platforms and ports can not use WTF::CurrentThread() and WTF::isMainThread()
+ // in destructors of thread-specific data.
+ ASSERT(m_isMainThread || m_emptyString->hasOneRef()); // We intentionally don't clean up static data on application quit, so there will be many strings remaining on the main thread.
+
delete m_emptyString;
}
diff --git a/WebCore/platform/ThreadGlobalData.h b/WebCore/platform/ThreadGlobalData.h
index 7faca36..e0aa092 100644
--- a/WebCore/platform/ThreadGlobalData.h
+++ b/WebCore/platform/ThreadGlobalData.h
@@ -48,7 +48,7 @@ namespace WebCore {
HashSet<StringImpl*>& atomicStringTable() { return *m_atomicStringTable; }
ThreadTimers& threadTimers() { return *m_threadTimers; }
-#if USE(ICU_UNICODE)
+#if USE(ICU_UNICODE) || USE(GLIB_ICU_UNICODE_HYBRID)
ICUConverterWrapper& cachedConverterICU() { return *m_cachedConverterICU; }
#endif
@@ -62,7 +62,11 @@ namespace WebCore {
EventNames* m_eventNames;
ThreadTimers* m_threadTimers;
-#if USE(ICU_UNICODE)
+#ifndef NDEBUG
+ bool m_isMainThread;
+#endif
+
+#if USE(ICU_UNICODE) || USE(GLIB_ICU_UNICODE_HYBRID)
ICUConverterWrapper* m_cachedConverterICU;
#endif
diff --git a/WebCore/platform/Timer.cpp b/WebCore/platform/Timer.cpp
index 353a2a7..d4235d9 100644
--- a/WebCore/platform/Timer.cpp
+++ b/WebCore/platform/Timer.cpp
@@ -169,6 +169,9 @@ TimerBase::TimerBase()
: m_nextFireTime(0)
, m_repeatInterval(0)
, m_heapIndex(-1)
+#ifndef NDEBUG
+ , m_thread(currentThread())
+#endif
{
}
@@ -180,12 +183,16 @@ TimerBase::~TimerBase()
void TimerBase::start(double nextFireInterval, double repeatInterval)
{
+ ASSERT(m_thread == currentThread());
+
m_repeatInterval = repeatInterval;
setNextFireTime(currentTime() + nextFireInterval);
}
void TimerBase::stop()
{
+ ASSERT(m_thread == currentThread());
+
m_repeatInterval = 0;
setNextFireTime(0);
@@ -196,6 +203,8 @@ void TimerBase::stop()
bool TimerBase::isActive() const
{
+ ASSERT(m_thread == currentThread());
+
return m_nextFireTime || timersReadyToFire().contains(this);
}
@@ -284,6 +293,8 @@ void TimerBase::heapPopMin()
void TimerBase::setNextFireTime(double newTime)
{
+ ASSERT(m_thread == currentThread());
+
// Keep heap valid while changing the next-fire time.
timersReadyToFire().remove(this);
diff --git a/WebCore/platform/Timer.h b/WebCore/platform/Timer.h
index aab52c2..8723515 100644
--- a/WebCore/platform/Timer.h
+++ b/WebCore/platform/Timer.h
@@ -27,6 +27,7 @@
#define Timer_h
#include <wtf/Noncopyable.h>
+#include <wtf/Threading.h>
namespace WebCore {
@@ -77,6 +78,10 @@ private:
int m_heapIndex; // -1 if not in heap
unsigned m_heapInsertionOrder; // Used to keep order among equal-fire-time timers
+#ifndef NDEBUG
+ ThreadIdentifier m_thread;
+#endif
+
friend class TimerHeapElement;
friend class ThreadTimers;
friend bool operator<(const TimerHeapElement&, const TimerHeapElement&);
diff --git a/WebCore/platform/Widget.h b/WebCore/platform/Widget.h
index 459d615..50d17b2 100644
--- a/WebCore/platform/Widget.h
+++ b/WebCore/platform/Widget.h
@@ -155,6 +155,7 @@ public:
virtual bool isFrameView() const { return false; }
virtual bool isPluginView() const { return false; }
+ virtual bool isScrollbar() const { return false; }
void removeFromParent();
virtual void setParent(ScrollView* view);
diff --git a/WebCore/platform/android/RenderThemeAndroid.cpp b/WebCore/platform/android/RenderThemeAndroid.cpp
index a1e8bf6..3910b7a 100644
--- a/WebCore/platform/android/RenderThemeAndroid.cpp
+++ b/WebCore/platform/android/RenderThemeAndroid.cpp
@@ -27,7 +27,6 @@
#include "RenderThemeAndroid.h"
#include "Color.h"
-#include "FormControlElement.h"
#include "GraphicsContext.h"
#include "PlatformGraphicsContext.h"
#include "RenderSkinAndroid.h"
@@ -181,8 +180,8 @@ bool RenderThemeAndroid::paintButton(RenderObject* obj, const RenderObject::Pain
{
// If it is a disabled button, simply paint it to the master picture.
Node* node = obj->node();
- FormControlElement* formControlElement = toFormControlElement(static_cast<Element*>(node));
- if (formControlElement && !formControlElement->isEnabled())
+ if (node && node->isElementNode() &&
+ static_cast<Element*>(node)->isEnabledFormControl())
RenderSkinButton::Draw(getCanvasFromInfo(info), rect, RenderSkinAndroid::kDisabled);
else
// Store all the important information in the platform context.
@@ -255,10 +254,7 @@ static void adjustMenuListStyleCommon(RenderStyle* style, Element* e)
style->setPaddingRight(Length(RenderSkinCombo::extraWidth(), Fixed));
// Code copied from RenderThemeMac.mm
// Makes sure that the text shows up on our treatment
- bool isEnabled = true;
- if (FormControlElement* formControlElement = toFormControlElement(e))
- isEnabled = formControlElement->isEnabled();
- style->setColor(isEnabled ? Color::black : Color::darkGray);
+ style->setColor(e->isEnabledFormControl() ? Color::black : Color::darkGray);
}
void RenderThemeAndroid::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, Element* e) const
diff --git a/WebCore/platform/android/TemporaryLinkStubs.cpp b/WebCore/platform/android/TemporaryLinkStubs.cpp
index b00f321..b48f006 100644
--- a/WebCore/platform/android/TemporaryLinkStubs.cpp
+++ b/WebCore/platform/android/TemporaryLinkStubs.cpp
@@ -59,6 +59,7 @@
#include "Icon.h"
#include "IconDatabase.h"
#include "IconLoader.h"
+#include "InspectorFrontend.h"
#include "IntPoint.h"
#if USE(JSC)
@@ -459,7 +460,7 @@ PassRefPtr<SharedBuffer> SharedBuffer::createWithContentsOfFile(const String&)
#if USE(JSC)
namespace JSC { namespace Bindings {
bool dispatchJNICall(ExecState*, const void* targetAppletView, jobject obj, bool isStatic, JNIType returnType,
- jmethodID methodID, jvalue* args, jvalue& result, const char* callingURL, JSValuePtr& exceptionDescription)
+ jmethodID methodID, jvalue* args, jvalue& result, const char* callingURL, JSValue& exceptionDescription)
{
notImplemented();
return false;
@@ -539,6 +540,11 @@ void AXObjectCache::remove(RenderObject*)
notImplemented();
}
+InspectorFrontend::~InspectorFrontend()
+{
+ notImplemented();
+}
+
#if USE(JSC)
using namespace JSC;
@@ -555,15 +561,9 @@ OpaqueJSClassContextData::~OpaqueJSClassContextData()
// as we don't use inspector/*.cpp, add stub here.
+/*
namespace WebCore {
-
-JSValuePtr toJS(ExecState*, Profile*)
-{
- notImplemented();
- return jsNull();
-}
-
-JSValuePtr JavaScriptCallFrame::evaluate(const UString& script, JSValuePtr& exception) const
+JSValue JavaScriptCallFrame::evaluate(const UString& script, JSValue& exception) const
{
notImplemented();
return jsNull();
@@ -663,4 +663,5 @@ void JavaScriptDebugServer::willExecuteProgram(const DebuggerCallFrame&, int, in
{
notImplemented();
}
+*/
#endif
diff --git a/WebCore/platform/cf/BinaryPropertyList.cpp b/WebCore/platform/cf/BinaryPropertyList.cpp
new file mode 100644
index 0000000..c0fda3d
--- /dev/null
+++ b/WebCore/platform/cf/BinaryPropertyList.cpp
@@ -0,0 +1,831 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "BinaryPropertyList.h"
+
+#include "StringHash.h"
+#include <wtf/HashSet.h>
+#include <limits>
+
+using namespace std;
+
+namespace WebCore {
+
+static const size_t headerSize = 8;
+static const size_t trailerSize = 32;
+
+static const UInt8 booleanTrueMarkerByte = 0x09;
+static const UInt8 oneByteIntegerMarkerByte = 0x10;
+static const UInt8 twoByteIntegerMarkerByte = 0x11;
+static const UInt8 fourByteIntegerMarkerByte = 0x12;
+static const UInt8 eightByteIntegerMarkerByte = 0x13;
+static const UInt8 asciiStringMarkerByte = 0x50;
+static const UInt8 asciiStringWithSeparateLengthMarkerByte = 0x5F;
+static const UInt8 unicodeStringMarkerByte = 0x60;
+static const UInt8 unicodeStringWithSeparateLengthMarkerByte = 0x6F;
+static const UInt8 arrayMarkerByte = 0xA0;
+static const UInt8 arrayWithSeparateLengthMarkerByte = 0xAF;
+static const UInt8 dictionaryMarkerByte = 0xD0;
+static const UInt8 dictionaryWithSeparateLengthMarkerByte = 0xDF;
+static const size_t maxLengthInMarkerByte = 0xE;
+
+class IntegerArray {
+public:
+ IntegerArray() : m_integers(0), m_size(0) { }
+ IntegerArray(const int* integers, size_t size) : m_integers(integers), m_size(size) { ASSERT(integers); ASSERT(size); }
+
+ void markDeleted() { m_integers = 0; m_size = deletedValueSize(); }
+ bool isDeletedValue() const { return m_size == deletedValueSize(); }
+
+ const int* integers() const { ASSERT(!isDeletedValue()); return m_integers; }
+ size_t size() const { ASSERT(!isDeletedValue()); return m_size; }
+
+private:
+ static size_t deletedValueSize() { return numeric_limits<size_t>::max(); }
+
+ friend bool operator==(const IntegerArray&, const IntegerArray&);
+
+ const int* m_integers;
+ size_t m_size;
+};
+
+inline bool operator==(const IntegerArray& a, const IntegerArray& b)
+{
+ return a.m_integers == b.m_integers && a.m_size == b.m_size;
+}
+
+struct IntegerArrayHashTraits : WTF::GenericHashTraits<IntegerArray> {
+ static const bool needsDestruction = false;
+ static void constructDeletedValue(IntegerArray& slot) { slot.markDeleted(); }
+ static bool isDeletedValue(const IntegerArray& array) { return array.isDeletedValue(); }
+};
+
+struct IntegerArrayHash {
+ static unsigned hash(const IntegerArray&);
+ static bool equal(const IntegerArray&, const IntegerArray&);
+ static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+unsigned IntegerArrayHash::hash(const IntegerArray& array)
+{
+ return StringImpl::computeHash(reinterpret_cast<const UChar*>(array.integers()), array.size() / (sizeof(int) / sizeof(UChar)));
+}
+
+bool IntegerArrayHash::equal(const IntegerArray& a, const IntegerArray& b)
+{
+ if (a.isDeletedValue() || b.isDeletedValue())
+ return a.isDeletedValue() == b.isDeletedValue();
+ if (a.size() != b.size())
+ return false;
+ for (size_t i = 0; i < a.size(); ++i) {
+ if (a.integers()[i] != b.integers()[i])
+ return false;
+ }
+ return true;
+}
+
+typedef size_t ObjectReference;
+
+class BinaryPropertyListPlan : private BinaryPropertyListObjectStream {
+public:
+ BinaryPropertyListPlan(BinaryPropertyListWriter&);
+
+ ObjectReference booleanTrueObjectReference() const;
+ ObjectReference integerObjectReference(int) const;
+ ObjectReference stringObjectReference(const String&) const;
+ ObjectReference integerArrayObjectReference(const int*, size_t) const;
+
+ ObjectReference objectCount() const { return m_currentObjectReference; }
+
+ ObjectReference byteCount() const { return m_byteCount; }
+ ObjectReference objectReferenceCount() const { return m_objectReferenceCount; }
+
+private:
+ virtual void writeBooleanTrue();
+ virtual void writeInteger(int);
+ virtual void writeString(const String&);
+ virtual void writeIntegerArray(const int*, size_t);
+ virtual void writeUniqueString(const String&);
+ virtual void writeUniqueString(const char*);
+ virtual size_t writeArrayStart();
+ virtual void writeArrayEnd(size_t);
+ virtual size_t writeDictionaryStart();
+ virtual void writeDictionaryEnd(size_t);
+
+ void writeArrayObject(size_t);
+ void writeDictionaryObject(size_t);
+ void writeStringObject(const String&);
+ void writeStringObject(const char*);
+
+ static ObjectReference invalidObjectReference() { return numeric_limits<ObjectReference>::max(); }
+
+ typedef HashMap<IntegerArray, ObjectReference, IntegerArrayHash, IntegerArrayHashTraits> IntegerArrayMap;
+
+ ObjectReference m_booleanTrueObjectReference;
+ ObjectReference m_integerZeroObjectReference;
+ HashMap<int, ObjectReference> m_integers;
+ HashMap<String, ObjectReference> m_strings;
+ IntegerArrayMap m_integerArrays;
+
+ ObjectReference m_currentObjectReference;
+
+ size_t m_currentAggregateSize;
+
+ size_t m_byteCount;
+ size_t m_objectReferenceCount;
+};
+
+BinaryPropertyListPlan::BinaryPropertyListPlan(BinaryPropertyListWriter& client)
+ : m_booleanTrueObjectReference(invalidObjectReference())
+ , m_integerZeroObjectReference(invalidObjectReference())
+ , m_currentObjectReference(0)
+ , m_currentAggregateSize(0)
+ , m_byteCount(0)
+ , m_objectReferenceCount(0)
+{
+ client.writeObjects(*this);
+ ASSERT(m_currentAggregateSize == 1);
+}
+
+void BinaryPropertyListPlan::writeBooleanTrue()
+{
+ ++m_currentAggregateSize;
+ if (m_booleanTrueObjectReference != invalidObjectReference())
+ return;
+ m_booleanTrueObjectReference = m_currentObjectReference++;
+ ++m_byteCount;
+}
+
+static inline int integerByteCount(size_t integer)
+{
+ if (integer <= 0xFF)
+ return 2;
+ if (integer <= 0xFFFF)
+ return 3;
+#ifdef __LP64__
+ if (integer <= 0xFFFFFFFFULL)
+ return 5;
+ return 9;
+#else
+ return 5;
+#endif
+}
+
+void BinaryPropertyListPlan::writeInteger(int integer)
+{
+ ASSERT(integer >= 0);
+ ++m_currentAggregateSize;
+ if (!integer) {
+ if (m_integerZeroObjectReference != invalidObjectReference())
+ return;
+ m_integerZeroObjectReference = m_currentObjectReference;
+ } else {
+ if (!m_integers.add(integer, m_currentObjectReference).second)
+ return;
+ }
+ ++m_currentObjectReference;
+ m_byteCount += integerByteCount(integer);
+}
+
+void BinaryPropertyListPlan::writeString(const String& string)
+{
+ ++m_currentAggregateSize;
+ if (!m_strings.add(string, m_currentObjectReference).second)
+ return;
+ ++m_currentObjectReference;
+ writeStringObject(string);
+}
+
+void BinaryPropertyListPlan::writeIntegerArray(const int* integers, size_t size)
+{
+ size_t savedAggregateSize = ++m_currentAggregateSize;
+ ASSERT(size);
+ pair<IntegerArrayMap::iterator, bool> addResult = m_integerArrays.add(IntegerArray(integers, size), 0);
+ if (!addResult.second)
+ return;
+ for (size_t i = 0; i < size; ++i)
+ writeInteger(integers[i]);
+ addResult.first->second = m_currentObjectReference++;
+ writeArrayObject(size);
+ m_currentAggregateSize = savedAggregateSize;
+}
+
+void BinaryPropertyListPlan::writeUniqueString(const String& string)
+{
+ ++m_currentAggregateSize;
+ ++m_currentObjectReference;
+ writeStringObject(string);
+}
+
+void BinaryPropertyListPlan::writeUniqueString(const char* string)
+{
+ ++m_currentAggregateSize;
+ ++m_currentObjectReference;
+ writeStringObject(string);
+}
+
+size_t BinaryPropertyListPlan::writeArrayStart()
+{
+ size_t savedAggregateSize = m_currentAggregateSize;
+ m_currentAggregateSize = 0;
+ return savedAggregateSize;
+}
+
+void BinaryPropertyListPlan::writeArrayEnd(size_t savedAggregateSize)
+{
+ ++m_currentObjectReference;
+ writeArrayObject(m_currentAggregateSize);
+ m_currentAggregateSize = savedAggregateSize + 1;
+}
+
+size_t BinaryPropertyListPlan::writeDictionaryStart()
+{
+ size_t savedAggregateSize = m_currentAggregateSize;
+ m_currentAggregateSize = 0;
+ return savedAggregateSize;
+}
+
+void BinaryPropertyListPlan::writeDictionaryEnd(size_t savedAggregateSize)
+{
+ ++m_currentObjectReference;
+ writeDictionaryObject(m_currentAggregateSize);
+ m_currentAggregateSize = savedAggregateSize + 1;
+}
+
+static size_t markerPlusLengthByteCount(size_t length)
+{
+ if (length <= maxLengthInMarkerByte)
+ return 1;
+ return 1 + integerByteCount(length);
+}
+
+void BinaryPropertyListPlan::writeStringObject(const String& string)
+{
+ const UChar* characters = string.characters();
+ unsigned length = string.length();
+ m_byteCount += markerPlusLengthByteCount(length) + length;
+ if (!charactersAreAllASCII(characters, length))
+ m_byteCount += length;
+}
+
+void BinaryPropertyListPlan::writeStringObject(const char* string)
+{
+ unsigned length = strlen(string);
+ m_byteCount += markerPlusLengthByteCount(length) + length;
+}
+
+void BinaryPropertyListPlan::writeArrayObject(size_t size)
+{
+ ASSERT(size);
+ m_byteCount += markerPlusLengthByteCount(size);
+ m_objectReferenceCount += size;
+}
+
+void BinaryPropertyListPlan::writeDictionaryObject(size_t size)
+{
+ ASSERT(size);
+ ASSERT(!(size & 1));
+ m_byteCount += markerPlusLengthByteCount(size / 2);
+ m_objectReferenceCount += size;
+}
+
+ObjectReference BinaryPropertyListPlan::booleanTrueObjectReference() const
+{
+ ASSERT(m_booleanTrueObjectReference != invalidObjectReference());
+ return m_booleanTrueObjectReference;
+}
+
+ObjectReference BinaryPropertyListPlan::integerObjectReference(int integer) const
+{
+ ASSERT(integer >= 0);
+ if (!integer) {
+ ASSERT(m_integerZeroObjectReference != invalidObjectReference());
+ return m_integerZeroObjectReference;
+ }
+ ASSERT(m_integers.contains(integer));
+ return m_integers.get(integer);
+}
+
+ObjectReference BinaryPropertyListPlan::stringObjectReference(const String& string) const
+{
+ ASSERT(m_strings.contains(string));
+ return m_strings.get(string);
+}
+
+ObjectReference BinaryPropertyListPlan::integerArrayObjectReference(const int* integers, size_t size) const
+{
+ ASSERT(m_integerArrays.contains(IntegerArray(integers, size)));
+ return m_integerArrays.get(IntegerArray(integers, size));
+}
+
+class BinaryPropertyListSerializer : private BinaryPropertyListObjectStream {
+public:
+ BinaryPropertyListSerializer(BinaryPropertyListWriter&);
+
+private:
+ virtual void writeBooleanTrue();
+ virtual void writeInteger(int);
+ virtual void writeString(const String&);
+ virtual void writeIntegerArray(const int*, size_t);
+ virtual void writeUniqueString(const String&);
+ virtual void writeUniqueString(const char*);
+ virtual size_t writeArrayStart();
+ virtual void writeArrayEnd(size_t);
+ virtual size_t writeDictionaryStart();
+ virtual void writeDictionaryEnd(size_t);
+
+ ObjectReference writeIntegerWithoutAddingAggregateObjectReference(int);
+
+ void appendIntegerObject(int);
+ void appendStringObject(const String&);
+ void appendStringObject(const char*);
+ void appendIntegerArrayObject(const int*, size_t);
+
+ void appendByte(unsigned char);
+ void appendByte(unsigned);
+ void appendByte(unsigned long);
+ void appendByte(int);
+
+ void appendInteger(size_t);
+
+ void appendObjectReference(ObjectReference);
+
+ void addAggregateObjectReference(ObjectReference);
+
+ void startObject();
+
+ const BinaryPropertyListPlan m_plan;
+ const int m_objectReferenceSize;
+ const size_t m_offsetTableStart;
+ const int m_offsetSize;
+ const size_t m_bufferSize;
+ UInt8* const m_buffer;
+
+ UInt8* m_currentByte;
+ ObjectReference m_currentObjectReference;
+ UInt8* m_currentAggregateBufferByte;
+};
+
+inline void BinaryPropertyListSerializer::appendByte(unsigned char byte)
+{
+ *m_currentByte++ = byte;
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+}
+
+inline void BinaryPropertyListSerializer::appendByte(unsigned byte)
+{
+ *m_currentByte++ = byte;
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+}
+
+inline void BinaryPropertyListSerializer::appendByte(unsigned long byte)
+{
+ *m_currentByte++ = byte;
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+}
+
+inline void BinaryPropertyListSerializer::appendByte(int byte)
+{
+ *m_currentByte++ = byte;
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+}
+
+static int bytesNeeded(size_t count)
+{
+ ASSERT(count);
+ int bytesNeeded = 1;
+ for (size_t mask = numeric_limits<size_t>::max() << 8; count & mask; mask <<= 8)
+ ++bytesNeeded;
+ return bytesNeeded;
+}
+
+static inline void storeLength(UInt8* destination, size_t length)
+{
+#ifdef __LP64__
+ destination[0] = length >> 56;
+ destination[1] = length >> 48;
+ destination[2] = length >> 40;
+ destination[3] = length >> 32;
+#else
+ destination[0] = 0;
+ destination[1] = 0;
+ destination[2] = 0;
+ destination[3] = 0;
+#endif
+ destination[4] = length >> 24;
+ destination[5] = length >> 16;
+ destination[6] = length >> 8;
+ destination[7] = length;
+}
+
+// Like memmove, but reverses the bytes.
+static void moveAndReverseBytes(UInt8* destination, const UInt8* source, size_t length)
+{
+ ASSERT(length);
+ memmove(destination, source, length);
+ UInt8* start = destination;
+ UInt8* end = destination + length;
+ while (end - start > 1)
+ std::swap(*start++, *--end);
+}
+
+// The serializer uses a single buffer for the property list.
+// The buffer contains:
+//
+// 8-byte header
+// object data
+// offset table
+// 32-byte trailer
+//
+// While serializing object, the offset table entry for each object is written just before
+// the object data for that object is written. Aggregates, arrays and dictionaries, are a
+// special case. The objects that go into an aggregate are written before the aggregate is.
+// As each object is written, the object reference is put in the aggregate buffer. Then,
+// when the aggregate is written, the aggregate buffer is copied into place in the object
+// data. Finally, the header and trailer are written.
+//
+// The aggregate buffer shares space with the object data, like this:
+//
+// 8-byte header
+// object data
+// >>> aggregate buffer <<<
+// offset table
+// 32-byte trailer
+//
+// To make it easy to build it incrementally, the buffer starts at the end of the object
+// data space, and grows backwards. We're guaranteed the aggregate buffer will never collide
+// with the object data pointer because we know that the object data is correctly sized
+// based on our plan, and all the data in the aggregate buffer will be used to create the
+// actual aggregate objects; in the worst case the aggregate buffer will already be in
+// exactly the right place, but backwards.
+
+BinaryPropertyListSerializer::BinaryPropertyListSerializer(BinaryPropertyListWriter& client)
+ : m_plan(client)
+ , m_objectReferenceSize(bytesNeeded(m_plan.objectCount()))
+ , m_offsetTableStart(headerSize + m_plan.byteCount() + m_plan.objectReferenceCount() * m_objectReferenceSize)
+ , m_offsetSize(bytesNeeded(m_offsetTableStart))
+ , m_bufferSize(m_offsetTableStart + m_plan.objectCount() * m_offsetSize + trailerSize)
+ , m_buffer(client.buffer(m_bufferSize))
+ , m_currentObjectReference(0)
+{
+ ASSERT(m_objectReferenceSize > 0);
+ ASSERT(m_offsetSize > 0);
+
+#ifdef __LP64__
+ ASSERT(m_objectReferenceSize <= 8);
+ ASSERT(m_offsetSize <= 8);
+#else
+ ASSERT(m_objectReferenceSize <= 4);
+ ASSERT(m_offsetSize <= 4);
+#endif
+
+ if (!m_buffer)
+ return;
+
+ // Write objects and offset table.
+ m_currentByte = m_buffer + headerSize;
+ m_currentAggregateBufferByte = m_buffer + m_offsetTableStart;
+ client.writeObjects(*this);
+ ASSERT(m_currentObjectReference == m_plan.objectCount());
+ ASSERT(m_currentAggregateBufferByte == m_buffer + m_offsetTableStart);
+ ASSERT(m_currentByte == m_buffer + m_offsetTableStart);
+
+ // Write header.
+ memcpy(m_buffer, "bplist00", headerSize);
+
+ // Write trailer.
+ UInt8* trailer = m_buffer + m_bufferSize - trailerSize;
+ memset(trailer, 0, 6);
+ trailer[6] = m_offsetSize;
+ trailer[7] = m_objectReferenceSize;
+ storeLength(trailer + 8, m_plan.objectCount());
+ storeLength(trailer + 16, m_plan.objectCount() - 1);
+ storeLength(trailer + 24, m_offsetTableStart);
+}
+
+void BinaryPropertyListSerializer::writeBooleanTrue()
+{
+ ObjectReference reference = m_plan.booleanTrueObjectReference();
+ if (m_currentObjectReference != reference)
+ ASSERT(reference < m_currentObjectReference);
+ else {
+ startObject();
+ appendByte(booleanTrueMarkerByte);
+ }
+ addAggregateObjectReference(reference);
+}
+
+inline ObjectReference BinaryPropertyListSerializer::writeIntegerWithoutAddingAggregateObjectReference(int integer)
+{
+ ObjectReference reference = m_plan.integerObjectReference(integer);
+ if (m_currentObjectReference != reference)
+ ASSERT(reference < m_currentObjectReference);
+ else
+ appendIntegerObject(integer);
+ return reference;
+}
+
+void BinaryPropertyListSerializer::writeInteger(int integer)
+{
+ addAggregateObjectReference(writeIntegerWithoutAddingAggregateObjectReference(integer));
+}
+
+void BinaryPropertyListSerializer::writeString(const String& string)
+{
+ ObjectReference reference = m_plan.stringObjectReference(string);
+ if (m_currentObjectReference != reference)
+ ASSERT(reference < m_currentObjectReference);
+ else
+ appendStringObject(string);
+ addAggregateObjectReference(reference);
+}
+
+void BinaryPropertyListSerializer::writeIntegerArray(const int* integers, size_t size)
+{
+ ObjectReference reference = m_plan.integerArrayObjectReference(integers, size);
+ for (size_t i = 0; i < size; ++i)
+ writeIntegerWithoutAddingAggregateObjectReference(integers[i]);
+ if (m_currentObjectReference != reference)
+ ASSERT(reference < m_currentObjectReference);
+ else
+ appendIntegerArrayObject(integers, size);
+ addAggregateObjectReference(reference);
+}
+
+void BinaryPropertyListSerializer::writeUniqueString(const char* string)
+{
+ addAggregateObjectReference(m_currentObjectReference);
+ appendStringObject(string);
+}
+
+void BinaryPropertyListSerializer::writeUniqueString(const String& string)
+{
+ addAggregateObjectReference(m_currentObjectReference);
+ appendStringObject(string);
+}
+
+size_t BinaryPropertyListSerializer::writeArrayStart()
+{
+ return m_currentAggregateBufferByte - m_buffer;
+}
+
+void BinaryPropertyListSerializer::writeArrayEnd(size_t savedAggregateBufferOffset)
+{
+ ObjectReference reference = m_currentObjectReference;
+ startObject();
+ size_t aggregateBufferByteCount = savedAggregateBufferOffset - (m_currentAggregateBufferByte - m_buffer);
+ ASSERT(aggregateBufferByteCount);
+ ASSERT(!(aggregateBufferByteCount % m_objectReferenceSize));
+ size_t size = aggregateBufferByteCount / m_objectReferenceSize;
+ if (size <= maxLengthInMarkerByte)
+ appendByte(arrayMarkerByte | size);
+ else {
+ appendByte(arrayWithSeparateLengthMarkerByte);
+ appendInteger(size);
+ }
+ m_currentAggregateBufferByte = m_buffer + savedAggregateBufferOffset;
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+ moveAndReverseBytes(m_currentByte, m_currentAggregateBufferByte - aggregateBufferByteCount, aggregateBufferByteCount);
+ m_currentByte += aggregateBufferByteCount;
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+ if (m_currentObjectReference < m_plan.objectCount())
+ addAggregateObjectReference(reference);
+ else
+ ASSERT(m_currentObjectReference == m_plan.objectCount());
+}
+
+size_t BinaryPropertyListSerializer::writeDictionaryStart()
+{
+ return m_currentAggregateBufferByte - m_buffer;
+}
+
+void BinaryPropertyListSerializer::writeDictionaryEnd(size_t savedAggregateBufferOffset)
+{
+ ObjectReference reference = m_currentObjectReference;
+ startObject();
+ size_t aggregateBufferByteCount = savedAggregateBufferOffset - (m_currentAggregateBufferByte - m_buffer);
+ ASSERT(aggregateBufferByteCount);
+ ASSERT(!(aggregateBufferByteCount % (m_objectReferenceSize * 2)));
+ size_t size = aggregateBufferByteCount / (m_objectReferenceSize * 2);
+ if (size <= maxLengthInMarkerByte)
+ appendByte(dictionaryMarkerByte | size);
+ else {
+ appendByte(dictionaryWithSeparateLengthMarkerByte);
+ appendInteger(size);
+ }
+ m_currentAggregateBufferByte = m_buffer + savedAggregateBufferOffset;
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+ moveAndReverseBytes(m_currentByte, m_currentAggregateBufferByte - aggregateBufferByteCount, aggregateBufferByteCount);
+ m_currentByte += aggregateBufferByteCount;
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+ if (m_currentObjectReference != m_plan.objectCount())
+ addAggregateObjectReference(reference);
+ else
+ ASSERT(m_currentObjectReference == m_plan.objectCount());
+}
+
+void BinaryPropertyListSerializer::appendIntegerObject(int integer)
+{
+ startObject();
+ ASSERT(integer >= 0);
+ appendInteger(integer);
+}
+
+void BinaryPropertyListSerializer::appendInteger(size_t integer)
+{
+ if (integer <= 0xFF) {
+ appendByte(oneByteIntegerMarkerByte);
+ appendByte(integer);
+ return;
+ }
+ if (integer <= 0xFFFF) {
+ appendByte(twoByteIntegerMarkerByte);
+ appendByte(integer >> 8);
+ appendByte(integer);
+ return;
+ }
+#ifdef __LP64__
+ if (integer <= 0xFFFFFFFFULL) {
+#endif
+ appendByte(fourByteIntegerMarkerByte);
+ appendByte(integer >> 24);
+ appendByte(integer >> 16);
+ appendByte(integer >> 8);
+ appendByte(integer);
+#ifdef __LP64__
+ return;
+ }
+ appendByte(eightByteIntegerMarkerByte);
+ appendByte(integer >> 56);
+ appendByte(integer >> 48);
+ appendByte(integer >> 40);
+ appendByte(integer >> 32);
+ appendByte(integer >> 24);
+ appendByte(integer >> 16);
+ appendByte(integer >> 8);
+ appendByte(integer);
+#endif
+}
+
+void BinaryPropertyListSerializer::appendStringObject(const String& string)
+{
+ startObject();
+ const UChar* characters = string.characters();
+ unsigned length = string.length();
+ if (charactersAreAllASCII(characters, length)) {
+ if (length <= maxLengthInMarkerByte)
+ appendByte(asciiStringMarkerByte | length);
+ else {
+ appendByte(asciiStringWithSeparateLengthMarkerByte);
+ appendInteger(length);
+ }
+ for (unsigned i = 0; i < length; ++i)
+ appendByte(characters[i]);
+ } else {
+ if (length <= maxLengthInMarkerByte)
+ appendByte(unicodeStringMarkerByte | length);
+ else {
+ appendByte(unicodeStringWithSeparateLengthMarkerByte);
+ appendInteger(length);
+ }
+ for (unsigned i = 0; i < length; ++i) {
+ appendByte(characters[i] >> 8);
+ appendByte(characters[i]);
+ }
+ }
+}
+
+void BinaryPropertyListSerializer::appendStringObject(const char* string)
+{
+ startObject();
+ unsigned length = strlen(string);
+ if (length <= maxLengthInMarkerByte)
+ appendByte(asciiStringMarkerByte | length);
+ else {
+ appendByte(asciiStringWithSeparateLengthMarkerByte);
+ appendInteger(length);
+ }
+ for (unsigned i = 0; i < length; ++i)
+ appendByte(string[i]);
+}
+
+void BinaryPropertyListSerializer::appendIntegerArrayObject(const int* integers, size_t size)
+{
+ startObject();
+ if (size <= maxLengthInMarkerByte)
+ appendByte(arrayMarkerByte | size);
+ else {
+ appendByte(arrayWithSeparateLengthMarkerByte);
+ appendInteger(size);
+ }
+ for (unsigned i = 0; i < size; ++i)
+ appendObjectReference(m_plan.integerObjectReference(integers[i]));
+}
+
+void BinaryPropertyListSerializer::appendObjectReference(ObjectReference reference)
+{
+ switch (m_objectReferenceSize) {
+#ifdef __LP64__
+ case 8:
+ appendByte(reference >> 56);
+ case 7:
+ appendByte(reference >> 48);
+ case 6:
+ appendByte(reference >> 40);
+ case 5:
+ appendByte(reference >> 32);
+#endif
+ case 4:
+ appendByte(reference >> 24);
+ case 3:
+ appendByte(reference >> 16);
+ case 2:
+ appendByte(reference >> 8);
+ case 1:
+ appendByte(reference);
+ }
+}
+
+void BinaryPropertyListSerializer::startObject()
+{
+ ObjectReference reference = m_currentObjectReference++;
+
+ size_t offset = m_currentByte - m_buffer;
+
+ UInt8* offsetTableEntry = m_buffer + m_offsetTableStart + reference * m_offsetSize + m_offsetSize;
+ switch (m_offsetSize) {
+#ifdef __LP64__
+ case 8:
+ offsetTableEntry[-8] = offset >> 56;
+ case 7:
+ offsetTableEntry[-7] = offset >> 48;
+ case 6:
+ offsetTableEntry[-6] = offset >> 40;
+ case 5:
+ offsetTableEntry[-5] = offset >> 32;
+#endif
+ case 4:
+ offsetTableEntry[-4] = offset >> 24;
+ case 3:
+ offsetTableEntry[-3] = offset >> 16;
+ case 2:
+ offsetTableEntry[-2] = offset >> 8;
+ case 1:
+ offsetTableEntry[-1] = offset;
+ }
+}
+
+void BinaryPropertyListSerializer::addAggregateObjectReference(ObjectReference reference)
+{
+ switch (m_objectReferenceSize) {
+#ifdef __LP64__
+ case 8:
+ *--m_currentAggregateBufferByte = reference >> 56;
+ case 7:
+ *--m_currentAggregateBufferByte = reference >> 48;
+ case 6:
+ *--m_currentAggregateBufferByte = reference >> 40;
+ case 5:
+ *--m_currentAggregateBufferByte = reference >> 32;
+#endif
+ case 4:
+ *--m_currentAggregateBufferByte = reference >> 24;
+ case 3:
+ *--m_currentAggregateBufferByte = reference >> 16;
+ case 2:
+ *--m_currentAggregateBufferByte = reference >> 8;
+ case 1:
+ *--m_currentAggregateBufferByte = reference;
+ }
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+}
+
+void BinaryPropertyListWriter::writePropertyList()
+{
+ BinaryPropertyListSerializer(*this);
+}
+
+}
diff --git a/WebCore/platform/cf/BinaryPropertyList.h b/WebCore/platform/cf/BinaryPropertyList.h
new file mode 100644
index 0000000..598aaa7
--- /dev/null
+++ b/WebCore/platform/cf/BinaryPropertyList.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BinaryPropertyList_h
+#define BinaryPropertyList_h
+
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class String;
+
+// Writes a limited subset of binary property lists.
+// Covers only what's needed for writing browser history as of this writing.
+class BinaryPropertyListObjectStream {
+public:
+ // Call writeBooleanTrue to write the boolean true value.
+ // A single shared object will be used in the serialized list.
+ virtual void writeBooleanTrue() = 0;
+
+ // Call writeInteger to write an integer value.
+ // A single shared object will be used for each integer in the serialized list.
+ virtual void writeInteger(int) = 0;
+
+ // Call writeString to write a string value.
+ // A single shared object will be used for each string in the serialized list.
+ virtual void writeString(const String&) = 0;
+
+ // Call writeUniqueString instead of writeString when it's unlikely the
+ // string will be written twice in the same property list; this saves hash
+ // table overhead for such strings. A separate object will be used for each
+ // of these strings in the serialized list.
+ virtual void writeUniqueString(const String&) = 0;
+ virtual void writeUniqueString(const char*) = 0;
+
+ // Call writeIntegerArray instead of writeArrayStart/writeArrayEnd for
+ // arrays entirely composed of integers. A single shared object will be used
+ // for each identical array in the serialized list. Warning: The integer
+ // pointer must remain valid until the writeBinaryPropertyList function
+ // returns, because these lists are put into a hash table without copying
+ // them -- that's OK if the client already has a Vector<int>.
+ virtual void writeIntegerArray(const int*, size_t) = 0;
+
+ // After calling writeArrayStart, write array elements.
+ // Then call writeArrayEnd, passing in the result from writeArrayStart.
+ // A separate object will be used for each of these arrays in the serialized list.
+ virtual size_t writeArrayStart() = 0;
+ virtual void writeArrayEnd(size_t resultFromWriteArrayStart) = 0;
+
+ // After calling writeDictionaryStart, write all keys, then all values.
+ // Then call writeDictionaryEnd, passing in the result from writeDictionaryStart.
+ // A separate object will be used for each dictionary in the serialized list.
+ virtual size_t writeDictionaryStart() = 0;
+ virtual void writeDictionaryEnd(size_t resultFromWriteDictionaryStart) = 0;
+
+protected:
+ virtual ~BinaryPropertyListObjectStream() { }
+};
+
+class BinaryPropertyListWriter {
+public:
+ // Calls writeObjects once to prepare for writing and determine how big a
+ // buffer is required. Then calls buffer to get the appropriately-sized
+ // buffer, then calls writeObjects a second time and writes the property list.
+ void writePropertyList();
+
+protected:
+ virtual ~BinaryPropertyListWriter() { }
+
+private:
+ // Called by writePropertyList.
+ // Must call the object stream functions for the objects to be written
+ // into the property list.
+ virtual void writeObjects(BinaryPropertyListObjectStream&) = 0;
+
+ // Called by writePropertyList.
+ // Returns the buffer that the writer should write into.
+ virtual UInt8* buffer(size_t) = 0;
+
+ friend class BinaryPropertyListPlan;
+ friend class BinaryPropertyListSerializer;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/cf/SharedBufferCF.cpp b/WebCore/platform/cf/SharedBufferCF.cpp
index 7213c7e..26fc07f 100644
--- a/WebCore/platform/cf/SharedBufferCF.cpp
+++ b/WebCore/platform/cf/SharedBufferCF.cpp
@@ -51,6 +51,11 @@ CFDataRef SharedBuffer::createCFData()
}
#endif
+PassRefPtr<SharedBuffer> SharedBuffer::wrapCFData(CFDataRef data)
+{
+ return adoptRef(new SharedBuffer(data));
+}
+
bool SharedBuffer::hasPlatformData() const
{
return m_cfData;
diff --git a/WebCore/platform/chromium/ChromiumBridge.h b/WebCore/platform/chromium/ChromiumBridge.h
index 3e5c404..75e9103 100644
--- a/WebCore/platform/chromium/ChromiumBridge.h
+++ b/WebCore/platform/chromium/ChromiumBridge.h
@@ -76,8 +76,8 @@ namespace WebCore {
static void clipboardWriteImage(const NativeImageSkia*, const KURL&, const String&);
// Cookies ------------------------------------------------------------
- static void setCookies(const KURL& url, const KURL& policyURL, const String& value);
- static String cookies(const KURL& url, const KURL& policyURL);
+ static void setCookies(const KURL& url, const KURL& firstPartyForCookies, const String& value);
+ static String cookies(const KURL& url, const KURL& firstPartyForCookies);
// DNS ----------------------------------------------------------------
static void prefetchDNS(const String& hostname);
@@ -135,6 +135,9 @@ namespace WebCore {
static void decrementStatsCounter(const char* name);
static void incrementStatsCounter(const char* name);
+ // Sudden Termination
+ static void suddenTerminationChanged(bool enabled);
+
// SystemTime ---------------------------------------------------------
static double currentTime();
diff --git a/WebCore/platform/chromium/ClipboardChromium.cpp b/WebCore/platform/chromium/ClipboardChromium.cpp
index b28503d..8f9ac7f 100644
--- a/WebCore/platform/chromium/ClipboardChromium.cpp
+++ b/WebCore/platform/chromium/ClipboardChromium.cpp
@@ -35,8 +35,10 @@
#include "Element.h"
#include "Frame.h"
#include "HTMLNames.h"
+#include "NamedAttrMap.h"
#include "MIMETypeRegistry.h"
#include "markup.h"
+#include "NamedNodeMap.h"
#include "PlatformString.h"
#include "Range.h"
#include "RenderImage.h"
@@ -216,7 +218,7 @@ static String imageToMarkup(const String& url, Element* element)
markup.append("\"");
// Copy over attributes. If we are dragging an image, we expect things like
// the id to be copied as well.
- NamedAttrMap* attrs = element->attributes();
+ NamedNodeMap* attrs = element->attributes();
unsigned length = attrs->length();
for (unsigned i = 0; i < length; ++i) {
Attribute* attr = attrs->attributeItem(i);
diff --git a/WebCore/platform/chromium/ClipboardChromium.h b/WebCore/platform/chromium/ClipboardChromium.h
index 53699da..0a83fd4 100644
--- a/WebCore/platform/chromium/ClipboardChromium.h
+++ b/WebCore/platform/chromium/ClipboardChromium.h
@@ -82,7 +82,6 @@ namespace WebCore {
void resetFromClipboard();
void setDragImage(CachedImage*, Node*, const IntPoint&);
RefPtr<ChromiumDataObject> m_dataObject;
- Frame* m_frame;
};
} // namespace WebCore
diff --git a/WebCore/platform/chromium/KeyCodeConversionGtk.cpp b/WebCore/platform/chromium/KeyCodeConversionGtk.cpp
index a3efe44..4fc7f32 100644
--- a/WebCore/platform/chromium/KeyCodeConversionGtk.cpp
+++ b/WebCore/platform/chromium/KeyCodeConversionGtk.cpp
@@ -150,9 +150,10 @@ int windowsKeyCodeForKeyEvent(unsigned keycode)
case GDK_Help:
return VKEY_HELP; // (2F) HELP key
case GDK_0:
- case GDK_parenleft:
+ case GDK_parenright:
return VKEY_0; // (30) 0) key
case GDK_1:
+ case GDK_exclam:
return VKEY_1; // (31) 1 ! key
case GDK_2:
case GDK_at:
@@ -176,7 +177,7 @@ int windowsKeyCodeForKeyEvent(unsigned keycode)
case GDK_asterisk:
return VKEY_8; // (38) 8 key '*'
case GDK_9:
- case GDK_parenright:
+ case GDK_parenleft:
return VKEY_9; // (39) 9 key '('
case GDK_a:
case GDK_A:
diff --git a/WebCore/platform/chromium/MimeTypeRegistryChromium.cpp b/WebCore/platform/chromium/MimeTypeRegistryChromium.cpp
index 1aac5ec..0f371b1 100644
--- a/WebCore/platform/chromium/MimeTypeRegistryChromium.cpp
+++ b/WebCore/platform/chromium/MimeTypeRegistryChromium.cpp
@@ -127,6 +127,11 @@ bool MIMETypeRegistry::isJavaAppletMIMEType(const String& mimeType)
|| mimeType.startsWith("application/x-java-vm", false);
}
+String MIMETypeRegistry::getMediaMIMETypeForExtension(const String&)
+{
+ return String();
+}
+
static HashSet<String>& dummyHashSet()
{
ASSERT_NOT_REACHED();
diff --git a/WebCore/platform/chromium/PopupMenuChromium.cpp b/WebCore/platform/chromium/PopupMenuChromium.cpp
index 53f565a..1be075d 100644
--- a/WebCore/platform/chromium/PopupMenuChromium.cpp
+++ b/WebCore/platform/chromium/PopupMenuChromium.cpp
@@ -136,32 +136,26 @@ public:
// Returns whether the popup wants to process events for the passed key.
bool isInterestedInEventForKey(int keyCode);
+ // Gets the height of a row.
+ int getRowHeight(int index);
+
+ // Returns true if the selection can be changed to index.
+ // Disabled items, or labels cannot be selected.
+ bool isSelectableItem(int index);
+
+ const Vector<PopupItem*>& items() const { return m_items; }
+
private:
friend class PopupContainer;
friend class RefCounted<PopupListBox>;
- // A type of List Item
- enum ListItemType {
- TypeOption,
- TypeGroup,
- TypeSeparator
- };
-
- // A item (represented by <option> or <optgroup>) in the <select> widget.
- struct ListItem {
- ListItem(const String& label, ListItemType type)
- : label(label.copy()), type(type), y(0) {}
- String label;
- ListItemType type;
- int y; // y offset of this item, relative to the top of the popup.
- };
-
PopupListBox(PopupMenuClient* client, const PopupContainerSettings& settings)
: m_settings(settings)
, m_originalIndex(0)
, m_selectedIndex(0)
- , m_willAcceptOnAbandon(false)
+ , m_acceptedIndexOnAbandon(-1)
, m_visibleRows(0)
+ , m_baseWidth(0)
, m_popupClient(client)
, m_repeatingChar(0)
, m_lastCharTime(0)
@@ -184,10 +178,6 @@ private:
// the web page, and closes the popup.
void acceptIndex(int index);
- // Returns true if the selection can be changed to index.
- // Disabled items, or labels cannot be selected.
- bool isSelectableItem(int index);
-
// Clears the selection (so no row appears selected).
void clearSelection();
@@ -198,8 +188,6 @@ private:
// Invalidates the row at the given index.
void invalidateRow(int index);
- // Gets the height of a row.
- int getRowHeight(int index);
// Get the bounds of a row.
IntRect getRowBounds(int index);
@@ -235,11 +223,11 @@ private:
// enter yet however.
int m_selectedIndex;
- // True if we should accept the selectedIndex as chosen, even if the popup
- // is "abandoned". This is used for keyboard navigation, where we want the
+ // If >= 0, this is the index we should accept if the popup is "abandoned".
+ // This is used for keyboard navigation, where we want the
// selection to change immediately, and is only used if the settings
// acceptOnAbandon field is true.
- bool m_willAcceptOnAbandon;
+ int m_acceptedIndexOnAbandon;
// This is the number of rows visible in the popup. The maximum number visible at a time is
// defined as being kMaxVisibleRows. For a scrolled popup, this can be thought of as the
@@ -250,7 +238,7 @@ private:
int m_baseWidth;
// A list of the options contained within the <select>
- Vector<ListItem*> m_items;
+ Vector<PopupItem*> m_items;
// The <select> PopupMenuClient that opened us.
PopupMenuClient* m_popupClient;
@@ -310,7 +298,8 @@ PassRefPtr<PopupContainer> PopupContainer::create(PopupMenuClient* client,
return adoptRef(new PopupContainer(client, settings));
}
-PopupContainer::PopupContainer(PopupMenuClient* client, const PopupContainerSettings& settings)
+PopupContainer::PopupContainer(PopupMenuClient* client,
+ const PopupContainerSettings& settings)
: m_listBox(PopupListBox::create(client, settings))
, m_settings(settings)
{
@@ -319,7 +308,7 @@ PopupContainer::PopupContainer(PopupMenuClient* client, const PopupContainerSett
PopupContainer::~PopupContainer()
{
- if (m_listBox)
+ if (m_listBox && m_listBox->parent())
removeChild(m_listBox.get());
}
@@ -342,7 +331,7 @@ void PopupContainer::showPopup(FrameView* view)
if (widgetRect.bottom() > static_cast<int>(screen.bottom()))
widgetRect.move(0, -(widgetRect.height() + selectHeight));
- chromeClient->popupOpened(this, widgetRect, m_settings.focusOnShow);
+ chromeClient->popupOpened(this, widgetRect, m_settings.focusOnShow, false);
}
if (!m_listBox->parent())
@@ -357,6 +346,29 @@ 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.
+ ChromeClientChromium* client = static_cast<ChromeClientChromium*>(
+ v->frame()->page()->chrome()->client());
+ client->popupOpened(this, popupRect, true, true);
+}
+
void PopupContainer::hidePopup()
{
if (client())
@@ -485,6 +497,16 @@ int PopupContainer::selectedIndex() const
return m_listBox->selectedIndex();
}
+int PopupContainer::menuItemHeight() const
+{
+ return m_listBox->getRowHeight(0);
+}
+
+const WTF::Vector<PopupItem*>& PopupContainer:: popupData() const
+{
+ return m_listBox->items();
+}
+
///////////////////////////////////////////////////////////////////////////////
// PopupListBox implementation
@@ -628,7 +650,7 @@ bool PopupListBox::handleKeyEvent(const PlatformKeyboardEvent& event)
// IE). We change the original index so we revert to that when the
// popup is closed.
if (m_settings.acceptOnAbandon)
- m_willAcceptOnAbandon = true;
+ m_acceptedIndexOnAbandon = m_selectedIndex;
setOriginalIndex(m_selectedIndex);
if (m_settings.setTextOnIndexChange)
@@ -797,7 +819,7 @@ void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowInd
Font PopupListBox::getRowFont(int rowIndex)
{
- Font itemFont = m_popupClient->itemStyle(rowIndex).font();
+ Font itemFont = m_popupClient->menuStyle().font();
if (m_popupClient->itemIsLabel(rowIndex)) {
// Bold-ify labels (ie, an <optgroup> heading).
FontDescription d = itemFont.fontDescription();
@@ -818,8 +840,10 @@ void PopupListBox::abandon()
m_popupClient->hidePopup();
- if (m_willAcceptOnAbandon)
- m_popupClient->valueChanged(m_selectedIndex);
+ if (m_acceptedIndexOnAbandon >= 0) {
+ m_popupClient->valueChanged(m_acceptedIndexOnAbandon);
+ m_acceptedIndexOnAbandon = -1;
+ }
}
int PopupListBox::pointToRowIndex(const IntPoint& point)
@@ -828,7 +852,7 @@ int PopupListBox::pointToRowIndex(const IntPoint& point)
// FIXME: binary search if perf matters.
for (int i = 0; i < numItems(); ++i) {
- if (y < m_items[i]->y)
+ if (y < m_items[i]->yOffset)
return i-1;
}
@@ -890,7 +914,7 @@ IntRect PopupListBox::getRowBounds(int index)
if (index < 0)
return IntRect(0, 0, visibleWidth(), getRowHeight(index));
- return IntRect(0, m_items[index]->y, visibleWidth(), getRowHeight(index));
+ return IntRect(0, m_items[index]->yOffset, visibleWidth(), getRowHeight(index));
}
void PopupListBox::invalidateRow(int index)
@@ -921,7 +945,7 @@ void PopupListBox::scrollToRevealRow(int index)
bool PopupListBox::isSelectableItem(int index)
{
- return m_items[index]->type == TypeOption && m_popupClient->itemIsEnabled(index);
+ return m_items[index]->type == PopupItem::TypeOption && m_popupClient->itemIsEnabled(index);
}
void PopupListBox::clearSelection()
@@ -998,26 +1022,19 @@ void PopupListBox::adjustSelectedIndex(int delta)
void PopupListBox::updateFromElement()
{
- // It happens when pressing a key to jump to an item, then use tab or
- // mouse to get away from the select box. In that case, updateFromElement
- // is called before abandon, which causes discarding of the select result.
- if (m_willAcceptOnAbandon) {
- m_popupClient->valueChanged(m_selectedIndex);
- m_willAcceptOnAbandon = false;
- }
-
clear();
int size = m_popupClient->listSize();
for (int i = 0; i < size; ++i) {
- ListItemType type;
+ PopupItem::Type type;
if (m_popupClient->itemIsSeparator(i))
- type = PopupListBox::TypeSeparator;
+ type = PopupItem::TypeSeparator;
else if (m_popupClient->itemIsLabel(i))
- type = PopupListBox::TypeGroup;
+ type = PopupItem::TypeGroup;
else
- type = PopupListBox::TypeOption;
- m_items.append(new ListItem(m_popupClient->itemText(i), type));
+ type = PopupItem::TypeOption;
+ m_items.append(new PopupItem(m_popupClient->itemText(i), type));
+ m_items[i]->enabled = isSelectableItem(i);
}
m_selectedIndex = m_popupClient->selectedIndex();
@@ -1036,7 +1053,7 @@ void PopupListBox::layout()
Font itemFont = getRowFont(i);
// Place the item vertically.
- m_items[i]->y = y;
+ m_items[i]->yOffset = y;
y += itemFont.height();
// Ensure the popup is wide enough to fit this item.
@@ -1051,13 +1068,26 @@ void PopupListBox::layout()
}
int windowHeight = 0;
+
+#if PLATFORM(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 !PLATFORM(DARWIN)
+ // Only clip the window height for non-Mac platforms.
if (windowHeight + rowHeight > kMaxHeight) {
m_visibleRows = i;
break;
}
+#endif
windowHeight += rowHeight;
}
@@ -1088,7 +1118,7 @@ void PopupListBox::layout()
void PopupListBox::clear()
{
- for (Vector<ListItem*>::iterator it = m_items.begin(); it != m_items.end(); ++it)
+ for (Vector<PopupItem*>::iterator it = m_items.begin(); it != m_items.end(); ++it)
delete *it;
m_items.clear();
}
@@ -1115,11 +1145,19 @@ PopupMenu::~PopupMenu()
hide();
}
-void PopupMenu::show(const IntRect& r, FrameView* v, int index)
+// 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 PopupMenu::show(const IntRect& r, FrameView* v, int index)
{
if (!p.popup)
p.popup = PopupContainer::create(client(), dropDownSettings);
+#if PLATFORM(DARWIN)
+ p.popup->showExternal(r, v, index);
+#else
p.popup->show(r, v, index);
+#endif
}
void PopupMenu::hide()
diff --git a/WebCore/platform/chromium/PopupMenuChromium.h b/WebCore/platform/chromium/PopupMenuChromium.h
index cd13c22..23003b1 100644
--- a/WebCore/platform/chromium/PopupMenuChromium.h
+++ b/WebCore/platform/chromium/PopupMenuChromium.h
@@ -42,6 +42,23 @@ namespace WebCore {
class FrameView;
class PopupListBox;
+ // A container for the data for each menu item (e.g. represented by <option>
+ // or <optgroup> in a <select> widget) and is used by PopupListBox.
+ struct PopupItem {
+ enum Type {
+ TypeOption,
+ TypeGroup,
+ TypeSeparator
+ };
+
+ PopupItem(const String& label, Type type)
+ : label(label), type(type), yOffset(0) { }
+ String label;
+ Type type;
+ int yOffset; // y offset of this item, relative to the top of the popup.
+ bool enabled;
+ };
+
// FIXME: Our FramelessScrollView classes should probably implement HostWindow!
// The PopupContainer class holds a PopupListBox (see cpp file). Its sole purpose is to be
@@ -94,9 +111,14 @@ namespace WebCore {
// 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.
+ // so WebViewImpl can create a PopupContainer. This method is used for
+ // displaying auto complete popup menus on Mac Chromium, and for all
+ // popups on other platforms.
void show(const IntRect&, FrameView*, int index);
// Hide the popup. Do not call this directly: use client->hidePopup().
@@ -114,6 +136,12 @@ namespace WebCore {
// Refresh the popup values from the PopupMenuClient.
void refresh();
+ // The menu per-item data.
+ const WTF::Vector<PopupItem*>& popupData() const;
+
+ // The height of a row in the menu.
+ int menuItemHeight() const;
+
private:
friend class WTF::RefCounted<PopupContainer>;
diff --git a/WebCore/platform/chromium/ScrollbarThemeChromium.cpp b/WebCore/platform/chromium/ScrollbarThemeChromium.cpp
index 426a078..78fc088 100644
--- a/WebCore/platform/chromium/ScrollbarThemeChromium.cpp
+++ b/WebCore/platform/chromium/ScrollbarThemeChromium.cpp
@@ -40,24 +40,6 @@
namespace WebCore {
-ScrollbarTheme* ScrollbarTheme::nativeTheme()
-{
- static ScrollbarThemeChromium theme;
- return &theme;
-}
-
-ScrollbarThemeChromium::ScrollbarThemeChromium()
-{
-}
-
-ScrollbarThemeChromium::~ScrollbarThemeChromium()
-{
-}
-
-void ScrollbarThemeChromium::themeChanged()
-{
-}
-
bool ScrollbarThemeChromium::hasThumb(Scrollbar* scrollbar)
{
// This method is just called as a paint-time optimization to see if
@@ -93,20 +75,6 @@ IntRect ScrollbarThemeChromium::forwardButtonRect(Scrollbar* scrollbar, Scrollba
return IntRect(x, y, size.width(), size.height());
}
-IntRect ScrollbarThemeChromium::trackRect(Scrollbar* scrollbar, bool)
-{
- IntSize bs = buttonSize(scrollbar);
- int thickness = scrollbarThickness(scrollbar->controlSize());
- if (scrollbar->orientation() == HorizontalScrollbar) {
- if (scrollbar->width() < 2 * thickness)
- return IntRect();
- return IntRect(scrollbar->x() + bs.width(), scrollbar->y(), scrollbar->width() - 2 * bs.width(), thickness);
- }
- if (scrollbar->height() < 2 * thickness)
- return IntRect();
- return IntRect(scrollbar->x(), scrollbar->y() + bs.height(), thickness, scrollbar->height() - 2 * bs.height());
-}
-
void ScrollbarThemeChromium::paintTrackBackground(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
{
// Just assume a forward track part. We only paint the track as a single piece when there is no thumb.
@@ -165,36 +133,4 @@ bool ScrollbarThemeChromium::shouldCenterOnThumb(Scrollbar*, const PlatformMouse
return evt.shiftKey() && evt.button() == LeftButton;
}
-IntSize ScrollbarThemeChromium::buttonSize(Scrollbar* scrollbar)
-{
-#if defined(__linux__)
- // On Linux, we don't use buttons
- return IntSize(0, 0);
-#endif
-
- // Our desired rect is essentially thickness by thickness.
-
- // Our actual rect will shrink to half the available space when we have < 2
- // times thickness pixels left. This allows the scrollbar to scale down
- // and function even at tiny sizes.
-
- int thickness = scrollbarThickness(scrollbar->controlSize());
-
- // In layout test mode, we force the button "girth" (i.e., the length of
- // the button along the axis of the scrollbar) to be a fixed size.
- // FIXME: This is retarded! scrollbarThickness is already fixed in layout
- // test mode so that should be enough to result in repeatable results, but
- // preserving this hack avoids having to rebaseline pixel tests.
- const int kLayoutTestModeGirth = 17;
- int girth = ChromiumBridge::layoutTestMode() ? kLayoutTestModeGirth : thickness;
-
- if (scrollbar->orientation() == HorizontalScrollbar) {
- int width = scrollbar->width() < 2 * girth ? scrollbar->width() / 2 : girth;
- return IntSize(width, thickness);
- }
-
- int height = scrollbar->height() < 2 * girth ? scrollbar->height() / 2 : girth;
- return IntSize(thickness, height);
-}
-
} // namespace WebCore
diff --git a/WebCore/platform/chromium/ScrollbarThemeChromium.h b/WebCore/platform/chromium/ScrollbarThemeChromium.h
index 87ffd44..71d4817 100644
--- a/WebCore/platform/chromium/ScrollbarThemeChromium.h
+++ b/WebCore/platform/chromium/ScrollbarThemeChromium.h
@@ -1,10 +1,10 @@
/*
* Copyright (c) 2008, 2009, Google Inc. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
@@ -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
@@ -37,22 +37,9 @@ namespace WebCore {
class PlatformMouseEvent;
- // This class contains the Chromium scrollbar implementations for Windows
- // and Linux. All of the symbols here in must be defined somewhere in the
- // code and we manage the platform specific parts by linking in different,
- // platform specific, files. Methods that we shared across platforms are
- // implemented in ScrollbarThemeChromium.cpp
+ // This class contains the scrollbar code which is shared between Chromium
+ // Windows and Linux.
class ScrollbarThemeChromium : public ScrollbarThemeComposite {
- public:
- ScrollbarThemeChromium();
- virtual ~ScrollbarThemeChromium();
-
- virtual int scrollbarThickness(ScrollbarControlSize = RegularScrollbar);
-
- virtual void themeChanged();
-
- virtual bool invalidateOnMouseEnterExit();
-
protected:
virtual bool hasButtons(Scrollbar*) { return true; }
virtual bool hasThumb(Scrollbar*);
@@ -65,19 +52,10 @@ namespace WebCore {
virtual bool shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent&);
virtual void paintTrackBackground(GraphicsContext*, Scrollbar*, const IntRect&);
- virtual void paintTrackPiece(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarPart);
- virtual void paintButton(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarPart);
- virtual void paintThumb(GraphicsContext*, Scrollbar*, const IntRect&);
virtual void paintTickmarks(GraphicsContext*, Scrollbar*, const IntRect&);
- private:
- IntSize buttonSize(Scrollbar*);
-
- int getThemeState(Scrollbar*, ScrollbarPart) const;
- int getThemeArrowState(Scrollbar*, ScrollbarPart) const;
- int getClassicThemeState(Scrollbar*, ScrollbarPart) const;
+ virtual IntSize buttonSize(Scrollbar*) = 0;
};
-
} // namespace WebCore
#endif
diff --git a/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp b/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp
index a99d778..6893dea 100644
--- a/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp
+++ b/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp
@@ -29,9 +29,8 @@
*/
#include "config.h"
-#include "ScrollbarThemeChromium.h"
+#include "ScrollbarThemeChromiumLinux.h"
-#include "NotImplemented.h"
#include "PlatformContextSkia.h"
#include "PlatformMouseEvent.h"
#include "Scrollbar.h"
@@ -39,14 +38,15 @@
namespace WebCore {
-int ScrollbarThemeChromium::scrollbarThickness(ScrollbarControlSize controlSize)
+ScrollbarTheme* ScrollbarTheme::nativeTheme()
{
- return 15;
+ static ScrollbarThemeChromiumLinux theme;
+ return &theme;
}
-bool ScrollbarThemeChromium::invalidateOnMouseEnterExit()
+int ScrollbarThemeChromiumLinux::scrollbarThickness(ScrollbarControlSize controlSize)
{
- return false;
+ return 15;
}
static void drawVertLine(SkCanvas* canvas, int x, int y1, int y2, const SkPaint& paint)
@@ -73,8 +73,16 @@ static void drawBox(SkCanvas* canvas, const IntRect& rect, const SkPaint& paint)
drawVertLine(canvas, rect.x(), rect.y(), bottom, paint);
}
-void ScrollbarThemeChromium::paintTrackPiece(GraphicsContext* gc, Scrollbar* scrollbar,
- const IntRect& rect, ScrollbarPart partType)
+IntRect ScrollbarThemeChromium::trackRect(Scrollbar* scrollbar, bool)
+{
+ IntSize bs = buttonSize(scrollbar);
+ int thickness = scrollbarThickness(scrollbar->controlSize());
+ if (scrollbar->orientation() == HorizontalScrollbar)
+ return IntRect(scrollbar->x() + bs.width(), scrollbar->y(), scrollbar->width(), thickness);
+ return IntRect(scrollbar->x(), scrollbar->y() + bs.height(), thickness, scrollbar->height());
+}
+
+void ScrollbarThemeChromiumLinux::paintTrackPiece(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart partType)
{
SkCanvas* const canvas = gc->platformContext()->canvas();
SkPaint paint;
@@ -88,13 +96,12 @@ void ScrollbarThemeChromium::paintTrackPiece(GraphicsContext* gc, Scrollbar* scr
drawBox(canvas, rect, paint);
}
-void ScrollbarThemeChromium::paintButton(GraphicsContext* gc, Scrollbar* scrollbar,
- const IntRect& rect, ScrollbarPart part)
+void ScrollbarThemeChromiumLinux::paintButton(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart part)
{
// We don't use buttons
}
-void ScrollbarThemeChromium::paintThumb(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect)
+void ScrollbarThemeChromiumLinux::paintThumb(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect)
{
const bool hovered = scrollbar->hoveredPart() == ThumbPart;
const int midx = rect.x() + rect.width() / 2;
@@ -139,4 +146,16 @@ void ScrollbarThemeChromium::paintThumb(GraphicsContext* gc, Scrollbar* scrollba
}
}
+IntSize ScrollbarThemeChromiumLinux::buttonSize(Scrollbar* scrollbar)
+{
+ // On Linux, we don't use buttons
+ return IntSize(0, 0);
+}
+
+int ScrollbarThemeChromiumLinux::minimumThumbLength(Scrollbar* scrollbar)
+{
+ // This matches Firefox on Linux.
+ return 2 * scrollbarThickness(scrollbar->controlSize());
+}
+
} // namespace WebCore
diff --git a/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.h b/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.h
new file mode 100644
index 0000000..4e08b07
--- /dev/null
+++ b/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ScrollbarThemeChromiumLinux_h
+#define ScrollbarThemeChromiumLinux_h
+
+#include "ScrollbarThemeChromium.h"
+
+namespace WebCore {
+ class ScrollbarThemeChromiumLinux : public ScrollbarThemeChromium {
+ public:
+ virtual int scrollbarThickness(ScrollbarControlSize);
+
+ protected:
+ virtual void paintTrackPiece(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarPart);
+ virtual void paintButton(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarPart);
+ virtual void paintThumb(GraphicsContext*, Scrollbar*, const IntRect&);
+
+ virtual IntSize buttonSize(Scrollbar*);
+ virtual int minimumThumbLength(Scrollbar*);
+ };
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/chromium/ScrollbarThemeChromiumWin.cpp b/WebCore/platform/chromium/ScrollbarThemeChromiumWin.cpp
index 0337f63..334b767 100644
--- a/WebCore/platform/chromium/ScrollbarThemeChromiumWin.cpp
+++ b/WebCore/platform/chromium/ScrollbarThemeChromiumWin.cpp
@@ -25,7 +25,7 @@
*/
#include "config.h"
-#include "ScrollbarThemeChromium.h"
+#include "ScrollbarThemeChromiumWin.h"
#include <windows.h>
#include <vsstyle.h>
@@ -39,12 +39,43 @@
namespace WebCore {
+ScrollbarTheme* ScrollbarTheme::nativeTheme()
+{
+ static ScrollbarThemeChromiumWin theme;
+ return &theme;
+}
+
// The scrollbar size in DumpRenderTree on the Mac - so we can match their
// layout results. Entries are for regular, small, and mini scrollbars.
// Metrics obtained using [NSScroller scrollerWidthForControlSize:]
static const int kMacScrollbarSize[3] = { 15, 11, 15 };
-int ScrollbarThemeChromium::scrollbarThickness(ScrollbarControlSize controlSize)
+// Constants used to figure the drag rect outside which we should snap the
+// scrollbar thumb back to its origin. These calculations are based on
+// observing the behavior of the MSVC8 main window scrollbar + some
+// guessing/extrapolation.
+static const int kOffEndMultiplier = 3;
+static const int kOffSideMultiplier = 8;
+
+IntRect ScrollbarThemeChromium::trackRect(Scrollbar* scrollbar, bool)
+{
+ IntSize bs = buttonSize(scrollbar);
+ // The buttons at the top and bottom of the scrollbar are square, so the
+ // thickness of the scrollbar is also their height.
+ int thickness = scrollbarThickness(scrollbar->controlSize());
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ // Once the scrollbar becomes smaller than the natural size of the
+ // two buttons, the track disappears.
+ if (scrollbar->width() < 2 * thickness)
+ return IntRect();
+ return IntRect(scrollbar->x() + bs.width(), scrollbar->y(), scrollbar->width() - 2 * bs.width(), thickness);
+ }
+ if (scrollbar->height() < 2 * thickness)
+ return IntRect();
+ return IntRect(scrollbar->x(), scrollbar->y() + bs.height(), thickness, scrollbar->height() - 2 * bs.height());
+}
+
+int ScrollbarThemeChromiumWin::scrollbarThickness(ScrollbarControlSize controlSize)
{
static int thickness;
if (!thickness) {
@@ -55,12 +86,30 @@ int ScrollbarThemeChromium::scrollbarThickness(ScrollbarControlSize controlSize)
return thickness;
}
-bool ScrollbarThemeChromium::invalidateOnMouseEnterExit()
+bool ScrollbarThemeChromiumWin::invalidateOnMouseEnterExit()
{
return isVistaOrNewer();
}
-void ScrollbarThemeChromium::paintTrackPiece(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart partType)
+bool ScrollbarThemeChromiumWin::shouldSnapBackToDragOrigin(Scrollbar* scrollbar, const PlatformMouseEvent& evt)
+{
+ // Find the rect within which we shouldn't snap, by expanding the track rect
+ // in both dimensions.
+ IntRect rect = trackRect(scrollbar);
+ const bool horz = scrollbar->orientation() == HorizontalScrollbar;
+ const int thickness = scrollbarThickness(scrollbar->controlSize());
+ rect.inflateX((horz ? kOffEndMultiplier : kOffSideMultiplier) * thickness);
+ rect.inflateY((horz ? kOffSideMultiplier : kOffEndMultiplier) * thickness);
+
+ // Convert the event to local coordinates.
+ IntPoint mousePosition = scrollbar->convertFromContainingWindow(evt.pos());
+ mousePosition.move(scrollbar->x(), scrollbar->y());
+
+ // We should snap iff the event is outside our calculated rect.
+ return !rect.contains(mousePosition);
+}
+
+void ScrollbarThemeChromiumWin::paintTrackPiece(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart partType)
{
bool horz = scrollbar->orientation() == HorizontalScrollbar;
@@ -82,7 +131,7 @@ void ScrollbarThemeChromium::paintTrackPiece(GraphicsContext* gc, Scrollbar* scr
alignRect);
}
-void ScrollbarThemeChromium::paintButton(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart part)
+void ScrollbarThemeChromiumWin::paintButton(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart part)
{
bool horz = scrollbar->orientation() == HorizontalScrollbar;
@@ -100,7 +149,7 @@ void ScrollbarThemeChromium::paintButton(GraphicsContext* gc, Scrollbar* scrollb
rect);
}
-void ScrollbarThemeChromium::paintThumb(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect)
+void ScrollbarThemeChromiumWin::paintThumb(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect)
{
bool horz = scrollbar->orientation() == HorizontalScrollbar;
@@ -121,7 +170,7 @@ void ScrollbarThemeChromium::paintThumb(GraphicsContext* gc, Scrollbar* scrollba
rect);
}
-int ScrollbarThemeChromium::getThemeState(Scrollbar* scrollbar, ScrollbarPart part) const
+int ScrollbarThemeChromiumWin::getThemeState(Scrollbar* scrollbar, ScrollbarPart part) const
{
// When dragging the thumb, draw thumb pressed and other segments normal
// regardless of where the cursor actually is. See also four places in
@@ -140,7 +189,7 @@ int ScrollbarThemeChromium::getThemeState(Scrollbar* scrollbar, ScrollbarPart pa
return (scrollbar->pressedPart() == part) ? SCRBS_PRESSED : SCRBS_NORMAL;
}
-int ScrollbarThemeChromium::getThemeArrowState(Scrollbar* scrollbar, ScrollbarPart part) const
+int ScrollbarThemeChromiumWin::getThemeArrowState(Scrollbar* scrollbar, ScrollbarPart part) const
{
// We could take advantage of knowing the values in the state enum to write
// some simpler code, but treating the state enum as a black box seems
@@ -190,7 +239,7 @@ int ScrollbarThemeChromium::getThemeArrowState(Scrollbar* scrollbar, ScrollbarPa
return (scrollbar->pressedPart() == part) ? ABS_DOWNPRESSED : ABS_DOWNNORMAL;
}
-int ScrollbarThemeChromium::getClassicThemeState(Scrollbar* scrollbar, ScrollbarPart part) const
+int ScrollbarThemeChromiumWin::getClassicThemeState(Scrollbar* scrollbar, ScrollbarPart part) const
{
// When dragging the thumb, draw the buttons normal even when hovered.
if (scrollbar->pressedPart() == ThumbPart)
@@ -204,4 +253,32 @@ int ScrollbarThemeChromium::getClassicThemeState(Scrollbar* scrollbar, Scrollbar
return (scrollbar->pressedPart() == part) ? (DFCS_PUSHED | DFCS_FLAT) : 0;
}
+IntSize ScrollbarThemeChromiumWin::buttonSize(Scrollbar* scrollbar)
+{
+ // Our desired rect is essentially thickness by thickness.
+
+ // Our actual rect will shrink to half the available space when we have < 2
+ // times thickness pixels left. This allows the scrollbar to scale down
+ // and function even at tiny sizes.
+
+ int thickness = scrollbarThickness(scrollbar->controlSize());
+
+ // In layout test mode, we force the button "girth" (i.e., the length of
+ // the button along the axis of the scrollbar) to be a fixed size.
+ // FIXME: This is retarded! scrollbarThickness is already fixed in layout
+ // test mode so that should be enough to result in repeatable results, but
+ // preserving this hack avoids having to rebaseline pixel tests.
+ const int kLayoutTestModeGirth = 17;
+ int girth = ChromiumBridge::layoutTestMode() ? kLayoutTestModeGirth : thickness;
+
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ int width = scrollbar->width() < 2 * girth ? scrollbar->width() / 2 : girth;
+ return IntSize(width, thickness);
+ }
+
+ int height = scrollbar->height() < 2 * girth ? scrollbar->height() / 2 : girth;
+ return IntSize(thickness, height);
+}
+
+
} // namespace WebCore
diff --git a/WebCore/platform/chromium/ScrollbarThemeChromiumWin.h b/WebCore/platform/chromium/ScrollbarThemeChromiumWin.h
new file mode 100644
index 0000000..5b4d0ea
--- /dev/null
+++ b/WebCore/platform/chromium/ScrollbarThemeChromiumWin.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ScrollbarThemeChromiumWin_h
+#define ScrollbarThemeChromiumWin_h
+
+#include "ScrollbarThemeChromium.h"
+
+namespace WebCore {
+ class ScrollbarThemeChromiumWin : public ScrollbarThemeChromium {
+ public:
+ virtual int scrollbarThickness(ScrollbarControlSize);
+ virtual bool invalidateOnMouseEnterExit();
+ virtual bool shouldSnapBackToDragOrigin(Scrollbar*, const PlatformMouseEvent&);
+
+ protected:
+ virtual void paintTrackPiece(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarPart);
+ virtual void paintButton(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarPart);
+ virtual void paintThumb(GraphicsContext*, Scrollbar*, const IntRect&);
+ virtual IntSize buttonSize(Scrollbar*);
+
+ private:
+ int getThemeState(Scrollbar*, ScrollbarPart) const;
+ int getThemeArrowState(Scrollbar*, ScrollbarPart) const;
+ int getClassicThemeState(Scrollbar*, ScrollbarPart) const;
+ };
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/chromium/SuddenTerminationChromium.cpp b/WebCore/platform/chromium/SuddenTerminationChromium.cpp
new file mode 100644
index 0000000..54b8304
--- /dev/null
+++ b/WebCore/platform/chromium/SuddenTerminationChromium.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SuddenTermination.h"
+
+#include "ChromiumBridge.h"
+
+namespace WebCore {
+
+void disableSuddenTermination()
+{
+ ChromiumBridge::suddenTerminationChanged(false);
+}
+
+void enableSuddenTermination()
+{
+ ChromiumBridge::suddenTerminationChanged(true);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/BitmapImage.cpp b/WebCore/platform/graphics/BitmapImage.cpp
index 1d97632..2f9412d 100644
--- a/WebCore/platform/graphics/BitmapImage.cpp
+++ b/WebCore/platform/graphics/BitmapImage.cpp
@@ -95,7 +95,7 @@ void BitmapImage::destroyDecodedDataIfNecessary(bool destroyAll)
// Animated images >5MB are considered large enough that we'll only hang on
// to one frame at a time.
static const unsigned cLargeAnimationCutoff = 5242880;
- if (frameCount() * frameBytes(m_size) > cLargeAnimationCutoff)
+ if (m_frames.size() * frameBytes(m_size) > cLargeAnimationCutoff)
destroyDecodedData(destroyAll);
}
diff --git a/WebCore/platform/graphics/BitmapImage.h b/WebCore/platform/graphics/BitmapImage.h
index db05d1c..a2de5d7 100644
--- a/WebCore/platform/graphics/BitmapImage.h
+++ b/WebCore/platform/graphics/BitmapImage.h
@@ -44,11 +44,6 @@ class NSImage;
typedef struct HBITMAP__ *HBITMAP;
#endif
-#if PLATFORM(SGL)
-class SkBitmap;
-class SkBitmapRef;
-#endif
-
namespace WebCore {
struct FrameData;
}
@@ -146,10 +141,13 @@ public:
#endif
#if PLATFORM(SGL)
-// virtual SkBitmapRef* getBitmap();
virtual void setURL(const String& str);
#endif
+#if PLATFORM(GTK)
+ virtual GdkPixbuf* getGdkPixbuf();
+#endif
+
virtual NativeImagePtr nativeImageForCurrentFrame() { return frameAtIndex(currentFrame()); }
protected:
diff --git a/WebCore/platform/graphics/Color.cpp b/WebCore/platform/graphics/Color.cpp
index e85ac00..d98b202 100644
--- a/WebCore/platform/graphics/Color.cpp
+++ b/WebCore/platform/graphics/Color.cpp
@@ -321,6 +321,41 @@ void Color::getRGBA(double& r, double& g, double& b, double& a) const
a = alpha() / 255.0;
}
+void Color::getHSL(double& hue, double& saturation, double& lightness) const
+{
+ // http://en.wikipedia.org/wiki/HSL_color_space. This is a direct copy of
+ // the algorithm therein, although it's 360^o based and we end up wanting
+ // [0...1) based. It's clearer if we stick to 360^o until the end.
+ double r = static_cast<double>(red()) / 255.0;
+ double g = static_cast<double>(green()) / 255.0;
+ double b = static_cast<double>(blue()) / 255.0;
+ double max = std::max(std::max(r, g), b);
+ double min = std::min(std::min(r, g), b);
+
+ if (max == min)
+ hue = 0.0;
+ else if (max == r)
+ hue = (60.0 * ((g - b) / (max - min))) + 360.0;
+ else if (max == g)
+ hue = (60.0 * ((b - r) / (max - min))) + 120.0;
+ else
+ hue = (60.0 * ((r - g) / (max - min))) + 240.0;
+
+ if (hue >= 360.0)
+ hue -= 360.0;
+
+ // makeRGBAFromHSLA assumes that hue is in [0...1).
+ hue /= 360.0;
+
+ lightness = 0.5 * (max + min);
+ if (max == min)
+ saturation = 0.0;
+ else if (lightness <= 0.5)
+ saturation = ((max - min) / (max + min));
+ else
+ saturation = ((max - min) / (2.0 - (max + min)));
+}
+
Color colorFromPremultipliedARGB(unsigned pixelColor)
{
RGBA32 rgba;
diff --git a/WebCore/platform/graphics/Color.h b/WebCore/platform/graphics/Color.h
index 3c889f9..3b815d2 100644
--- a/WebCore/platform/graphics/Color.h
+++ b/WebCore/platform/graphics/Color.h
@@ -94,6 +94,7 @@ public:
void setRGB(RGBA32 rgb) { m_color = rgb; m_valid = true; }
void getRGBA(float& r, float& g, float& b, float& a) const;
void getRGBA(double& r, double& g, double& b, double& a) const;
+ void getHSL(double& h, double& s, double& l) const;
Color light() const;
Color dark() const;
diff --git a/WebCore/platform/graphics/FloatQuad.cpp b/WebCore/platform/graphics/FloatQuad.cpp
index a32d8ab..427230d 100644
--- a/WebCore/platform/graphics/FloatQuad.cpp
+++ b/WebCore/platform/graphics/FloatQuad.cpp
@@ -46,6 +46,34 @@ static inline float max4(float a, float b, float c, float d)
return max(max(a, b), max(c, d));
}
+inline float dot(const FloatSize& a, const FloatSize& b)
+{
+ return a.width() * b.width() + a.height() * b.height();
+}
+
+inline bool isPointInTriangle(const FloatPoint& p, const FloatPoint& t1, const FloatPoint& t2, const FloatPoint& t3)
+{
+ // Compute vectors
+ FloatSize v0 = t3 - t1;
+ FloatSize v1 = t2 - t1;
+ FloatSize v2 = p - t1;
+
+ // Compute dot products
+ float dot00 = dot(v0, v0);
+ float dot01 = dot(v0, v1);
+ float dot02 = dot(v0, v2);
+ float dot11 = dot(v1, v1);
+ float dot12 = dot(v1, v2);
+
+ // Compute barycentric coordinates
+ float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01);
+ float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
+ float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
+
+ // Check if point is in triangle
+ return (u >= 0) && (v >= 0) && (u + v <= 1);
+}
+
FloatRect FloatQuad::boundingBox() const
{
float left = min4(m_p1.x(), m_p2.x(), m_p3.x(), m_p4.x());
@@ -57,4 +85,15 @@ FloatRect FloatQuad::boundingBox() const
return FloatRect(left, top, right - left, bottom - top);
}
+bool FloatQuad::containsPoint(const FloatPoint& p) const
+{
+ return isPointInTriangle(p, m_p1, m_p2, m_p3) || isPointInTriangle(p, m_p1, m_p3, m_p4);
+}
+
+// Note that we only handle convex quads here.
+bool FloatQuad::containsQuad(const FloatQuad& other) const
+{
+ return containsPoint(other.p1()) && containsPoint(other.p2()) && containsPoint(other.p3()) && containsPoint(other.p4());
+}
+
} // namespace WebCore
diff --git a/WebCore/platform/graphics/FloatQuad.h b/WebCore/platform/graphics/FloatQuad.h
index e05b27d..5982967 100644
--- a/WebCore/platform/graphics/FloatQuad.h
+++ b/WebCore/platform/graphics/FloatQuad.h
@@ -74,6 +74,14 @@ public:
// "slanted" empty quads.
bool isEmpty() const { return boundingBox().isEmpty(); }
+ // Tests whether the given point is inside, or on an edge or corner of this quad.
+ bool containsPoint(const FloatPoint&) const;
+
+ // Tests whether the four corners of other are inside, or coincident with the sides of this quad.
+ // Note that this only works for convex quads, but that includes all quads that originate
+ // from transformed rects.
+ bool containsQuad(const FloatQuad&) const;
+
FloatRect boundingBox() const;
IntRect enclosingBoundingBox() const
{
diff --git a/WebCore/platform/graphics/Font.cpp b/WebCore/platform/graphics/Font.cpp
index f8bec82..85fe882 100644
--- a/WebCore/platform/graphics/Font.cpp
+++ b/WebCore/platform/graphics/Font.cpp
@@ -32,6 +32,7 @@
#include "GlyphBuffer.h"
#include "WidthIterator.h"
#include <wtf/MathExtras.h>
+#include <wtf/UnusedParam.h>
using namespace WTF;
using namespace Unicode;
@@ -198,7 +199,7 @@ void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoi
return drawComplexText(context, run, point, from, to);
}
-float Font::floatWidth(const TextRun& run) const
+float Font::floatWidth(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
{
#if ENABLE(SVG_FONTS)
if (primaryFont()->isSVGFont())
@@ -206,16 +207,22 @@ float Font::floatWidth(const TextRun& run) const
#endif
#if USE(FONT_FAST_PATH)
- if (canUseGlyphCache(run))
- return floatWidthForSimpleText(run, 0);
+ if (canUseGlyphCache(run)) {
+ // If the complex text implementation cannot return fallback fonts, avoid
+ // returning them for simple text as well.
+ static bool returnFallbackFonts = canReturnFallbackFontsForComplexText();
+ return floatWidthForSimpleText(run, 0, returnFallbackFonts ? fallbackFonts : 0);
+ }
#endif
- return floatWidthForComplexText(run);
+ return floatWidthForComplexText(run, fallbackFonts);
}
float Font::floatWidth(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const
{
-#if ENABLE(SVG_FONTS)
+#if !ENABLE(SVG_FONTS)
+ UNUSED_PARAM(extraCharsAvailable);
+#else
if (primaryFont()->isSVGFont())
return floatWidthUsingSVGFont(run, extraCharsAvailable, charsConsumed, glyphName);
#endif
@@ -275,4 +282,17 @@ FontSelector* Font::fontSelector() const
return m_fontList ? m_fontList->fontSelector() : 0;
}
+static bool shouldUseFontSmoothing = true;
+
+void Font::setShouldUseSmoothing(bool shouldUseSmoothing)
+{
+ ASSERT(isMainThread());
+ shouldUseFontSmoothing = shouldUseSmoothing;
+}
+
+bool Font::shouldUseSmoothing()
+{
+ return shouldUseFontSmoothing;
+}
+
}
diff --git a/WebCore/platform/graphics/Font.h b/WebCore/platform/graphics/Font.h
index 1bfee8f..8d85d8b 100644
--- a/WebCore/platform/graphics/Font.h
+++ b/WebCore/platform/graphics/Font.h
@@ -78,8 +78,8 @@ public:
void drawText(GraphicsContext*, const TextRun&, const FloatPoint&, int from = 0, int to = -1) const;
- int width(const TextRun& run) const { return lroundf(floatWidth(run)); }
- float floatWidth(const TextRun&) const;
+ int width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts = 0) const { return lroundf(floatWidth(run, fallbackFonts)); }
+ float floatWidth(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0) const;
float floatWidth(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const;
int offsetForPosition(const TextRun&, int position, bool includePartialGlyphs) const;
@@ -112,17 +112,19 @@ public:
int lineGap() const { return primaryFont()->lineGap(); }
float xHeight() const { return primaryFont()->xHeight(); }
unsigned unitsPerEm() const { return primaryFont()->unitsPerEm(); }
- int spaceWidth() const { return (int)ceilf(primaryFont()->m_adjustedSpaceWidth + m_letterSpacing); }
+ int spaceWidth() const { return (int)ceilf(primaryFont()->adjustedSpaceWidth() + m_letterSpacing); }
int tabWidth() const { return 8 * spaceWidth(); }
- const SimpleFontData* primaryFont() const {
+ const SimpleFontData* primaryFont() const
+ {
+ ASSERT(isMainThread());
if (!m_cachedPrimaryFont)
cachePrimaryFont();
return m_cachedPrimaryFont;
}
const FontData* fontDataAt(unsigned) const;
- const GlyphData& glyphDataForCharacter(UChar32, bool mirror, bool forceSmallCaps = false) const;
+ GlyphData glyphDataForCharacter(UChar32, bool mirror, bool forceSmallCaps = false) const;
// Used for complex text, and does not utilize the glyph map cache.
const FontData* fontDataForCharacters(const UChar*, int length) const;
@@ -130,6 +132,9 @@ public:
QFont font() const;
#endif
+ static void setShouldUseSmoothing(bool);
+ static bool shouldUseSmoothing();
+
private:
#if ENABLE(SVG_FONTS)
void drawTextUsingSVGFont(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
@@ -144,13 +149,15 @@ private:
void drawSimpleText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const;
void drawGlyphBuffer(GraphicsContext*, const GlyphBuffer&, const TextRun&, const FloatPoint&) const;
- float floatWidthForSimpleText(const TextRun&, GlyphBuffer*) const;
+ float floatWidthForSimpleText(const TextRun&, GlyphBuffer*, HashSet<const SimpleFontData*>* fallbackFonts = 0) const;
int offsetForPositionForSimpleText(const TextRun&, int position, bool includePartialGlyphs) const;
FloatRect selectionRectForSimpleText(const TextRun&, const IntPoint&, int h, int from, int to) const;
+
+ static bool canReturnFallbackFontsForComplexText();
#endif
void drawComplexText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
- float floatWidthForComplexText(const TextRun&) const;
+ float floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0) const;
int offsetForPositionForComplexText(const TextRun&, int position, bool includePartialGlyphs) const;
FloatRect selectionRectForComplexText(const TextRun&, const IntPoint&, int h, int from, int to) const;
void cachePrimaryFont() const;
diff --git a/WebCore/platform/graphics/FontCache.cpp b/WebCore/platform/graphics/FontCache.cpp
index 130313d..d9b4b28 100644
--- a/WebCore/platform/graphics/FontCache.cpp
+++ b/WebCore/platform/graphics/FontCache.cpp
@@ -307,12 +307,13 @@ void FontCache::purgeInactiveFontData(int count)
isPurging = true;
+ Vector<const SimpleFontData*, 20> fontDataToDelete;
ListHashSet<const SimpleFontData*>::iterator end = gInactiveFontData->end();
ListHashSet<const SimpleFontData*>::iterator it = gInactiveFontData->begin();
for (int i = 0; i < count && it != end; ++it, ++i) {
const SimpleFontData* fontData = *it.get();
gFontDataCache->remove(fontData->platformData());
- delete fontData;
+ fontDataToDelete.append(fontData);
}
if (it == end) {
@@ -323,6 +324,10 @@ void FontCache::purgeInactiveFontData(int count)
gInactiveFontData->remove(gInactiveFontData->begin());
}
+ size_t fontDataToDeleteCount = fontDataToDelete.size();
+ for (size_t i = 0; i < fontDataToDeleteCount; ++i)
+ delete fontDataToDelete[i];
+
Vector<FontPlatformDataCacheKey> keysToRemove;
keysToRemove.reserveInitialCapacity(gFontPlatformDataCache->size());
FontPlatformDataCache::iterator platformDataEnd = gFontPlatformDataCache->end();
diff --git a/WebCore/platform/graphics/FontCache.h b/WebCore/platform/graphics/FontCache.h
index 8820045..3c0f2d9 100644
--- a/WebCore/platform/graphics/FontCache.h
+++ b/WebCore/platform/graphics/FontCache.h
@@ -85,6 +85,7 @@ public:
private:
FontCache();
+ ~FontCache();
// These methods are implemented by each platform.
FontPlatformData* getSimilarFontPlatformData(const Font&);
diff --git a/WebCore/platform/graphics/FontDescription.h b/WebCore/platform/graphics/FontDescription.h
index d13e86a..c893b8a 100644
--- a/WebCore/platform/graphics/FontDescription.h
+++ b/WebCore/platform/graphics/FontDescription.h
@@ -81,7 +81,7 @@ public:
GenericFamilyType genericFamily() const { return static_cast<GenericFamilyType>(m_genericFamily); }
bool usePrinterFont() const { return m_usePrinterFont; }
FontRenderingMode renderingMode() const { return static_cast<FontRenderingMode>(m_renderingMode); }
- int keywordSize() const { return m_keywordSize; }
+ unsigned keywordSize() const { return m_keywordSize; }
FontTraitsMask traitsMask() const;
@@ -95,7 +95,7 @@ public:
void setGenericFamily(GenericFamilyType genericFamily) { m_genericFamily = genericFamily; }
void setUsePrinterFont(bool p) { m_usePrinterFont = p; }
void setRenderingMode(FontRenderingMode mode) { m_renderingMode = mode; }
- void setKeywordSize(int s) { m_keywordSize = s; }
+ void setKeywordSize(unsigned s) { m_keywordSize = s; }
private:
FontFamily m_familyList; // The list of font families to be used.
@@ -114,7 +114,7 @@ private:
unsigned m_renderingMode : 1; // Used to switch between CG and GDI text on Windows.
- int m_keywordSize : 4; // We cache whether or not a font is currently represented by a CSS keyword (e.g., medium). If so,
+ unsigned m_keywordSize : 4; // We cache whether or not a font is currently represented by a CSS keyword (e.g., medium). If so,
// then we can accurately translate across different generic families to adjust for different preference settings
// (e.g., 13px monospace vs. 16px everything else). Sizes are 1-8 (like the HTML size values for <font>).
};
diff --git a/WebCore/platform/graphics/FontFallbackList.cpp b/WebCore/platform/graphics/FontFallbackList.cpp
index 06d52d7..decacc5 100644
--- a/WebCore/platform/graphics/FontFallbackList.cpp
+++ b/WebCore/platform/graphics/FontFallbackList.cpp
@@ -36,10 +36,10 @@
namespace WebCore {
FontFallbackList::FontFallbackList()
- : m_familyIndex(0)
+ : m_fontSelector(0)
+ , m_familyIndex(0)
, m_pitch(UnknownPitch)
, m_loadingCustomFonts(false)
- , m_fontSelector(0)
, m_generation(fontCache()->generation())
{
}
diff --git a/WebCore/platform/graphics/FontFallbackList.h b/WebCore/platform/graphics/FontFallbackList.h
index a23b32c..07938ae 100644
--- a/WebCore/platform/graphics/FontFallbackList.h
+++ b/WebCore/platform/graphics/FontFallbackList.h
@@ -66,10 +66,10 @@ private:
void releaseFontData();
mutable Vector<pair<const FontData*, bool>, 1> m_fontList;
+ RefPtr<FontSelector> m_fontSelector;
mutable int m_familyIndex;
mutable Pitch m_pitch;
mutable bool m_loadingCustomFonts;
- RefPtr<FontSelector> m_fontSelector;
unsigned m_generation;
friend class Font;
diff --git a/WebCore/platform/graphics/FontFastPath.cpp b/WebCore/platform/graphics/FontFastPath.cpp
index 635aba9..deac1b6 100644
--- a/WebCore/platform/graphics/FontFastPath.cpp
+++ b/WebCore/platform/graphics/FontFastPath.cpp
@@ -39,11 +39,13 @@ using namespace Unicode;
namespace WebCore {
-const GlyphData& Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCaps) const
+GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCaps) const
{
+ ASSERT(isMainThread());
+
bool useSmallCapsFont = forceSmallCaps;
if (m_fontDescription.smallCaps()) {
- UChar32 upperC = Unicode::toUpper(c);
+ UChar32 upperC = toUpper(c);
if (upperC != c) {
c = upperC;
useSmallCapsFont = true;
@@ -70,7 +72,7 @@ const GlyphData& Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceS
while (true) {
page = node->page();
if (page) {
- const GlyphData& data = page->glyphDataForCharacter(c);
+ GlyphData data = page->glyphDataForCharacter(c);
if (data.fontData)
return data;
if (node->isSystemFallback())
@@ -88,7 +90,7 @@ const GlyphData& Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceS
while (true) {
page = node->page();
if (page) {
- const GlyphData& data = page->glyphDataForCharacter(c);
+ GlyphData data = page->glyphDataForCharacter(c);
if (data.fontData) {
// The smallCapsFontData function should not normally return 0.
// But if it does, we will just render the capital letter big.
@@ -99,7 +101,7 @@ const GlyphData& Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceS
GlyphPageTreeNode* smallCapsNode = GlyphPageTreeNode::getRootChild(smallCapsFontData, pageNumber);
const GlyphPage* smallCapsPage = smallCapsNode->page();
if (smallCapsPage) {
- const GlyphData& data = smallCapsPage->glyphDataForCharacter(c);
+ GlyphData data = smallCapsPage->glyphDataForCharacter(c);
if (data.fontData)
return data;
}
@@ -150,7 +152,7 @@ const GlyphData& Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceS
if (characterFontData) {
// Got the fallback glyph and font.
GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData, pageNumber)->page();
- const GlyphData& data = fallbackPage && fallbackPage->glyphDataForCharacter(c).fontData ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
+ GlyphData data = fallbackPage && fallbackPage->fontDataForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
// Cache it so we don't have to do system fallback again next time.
if (!useSmallCapsFont)
page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
@@ -159,7 +161,7 @@ const GlyphData& Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceS
// Even system fallback can fail; use the missing glyph in that case.
// FIXME: It would be nicer to use the missing glyph from the last resort font instead.
- const GlyphData& data = primaryFont()->missingGlyphData();
+ GlyphData data = primaryFont()->missingGlyphData();
if (!useSmallCapsFont)
page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
return data;
@@ -296,9 +298,9 @@ void Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuf
drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
}
-float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer) const
+float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts) const
{
- WidthIterator it(this, run);
+ WidthIterator it(this, run, fallbackFonts);
it.advance(run.length(), glyphBuffer);
return it.m_runWidthSoFar;
}
diff --git a/WebCore/platform/graphics/GeneratedImage.cpp b/WebCore/platform/graphics/GeneratedImage.cpp
index 15e27d7..c40a40a 100644
--- a/WebCore/platform/graphics/GeneratedImage.cpp
+++ b/WebCore/platform/graphics/GeneratedImage.cpp
@@ -51,7 +51,7 @@ void GeneratedImage::drawPattern(GraphicsContext* context, const FloatRect& srcR
const FloatPoint& phase, CompositeOperator compositeOp, const FloatRect& destRect)
{
// Create a BitmapImage and call drawPattern on it.
- auto_ptr<ImageBuffer> imageBuffer = ImageBuffer::create(m_size, false);
+ OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(m_size, false);
ASSERT(imageBuffer.get());
// Fill with the gradient.
diff --git a/WebCore/platform/graphics/GlyphPageTreeNode.cpp b/WebCore/platform/graphics/GlyphPageTreeNode.cpp
index bd838de..a34a192 100644
--- a/WebCore/platform/graphics/GlyphPageTreeNode.cpp
+++ b/WebCore/platform/graphics/GlyphPageTreeNode.cpp
@@ -220,8 +220,8 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu
if (scratchPage) {
ASSERT(to <= static_cast<int>(GlyphPage::size));
for (int j = from; j < to; j++) {
- if (!m_page->m_glyphs[j].glyph && pageToFill->m_glyphs[j].glyph)
- m_page->m_glyphs[j] = pageToFill->m_glyphs[j];
+ if (!m_page->glyphAt(j) && pageToFill->glyphAt(j))
+ m_page->setGlyphDataForIndex(j, pageToFill->glyphDataForIndex(j));
}
}
}
@@ -265,15 +265,13 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu
// has added anything.
bool newGlyphs = false;
for (unsigned i = 0; i < GlyphPage::size; i++) {
- if (parentPage->m_glyphs[i].glyph)
- m_page->m_glyphs[i] = parentPage->m_glyphs[i];
- else if (fallbackPage->m_glyphs[i].glyph) {
- m_page->m_glyphs[i] = fallbackPage->m_glyphs[i];
+ if (parentPage->glyphAt(i))
+ m_page->setGlyphDataForIndex(i, parentPage->glyphDataForIndex(i));
+ else if (fallbackPage->glyphAt(i)) {
+ m_page->setGlyphDataForIndex(i, fallbackPage->glyphDataForIndex(i));
newGlyphs = true;
- } else {
- const GlyphData data = { 0, 0 };
- m_page->m_glyphs[i] = data;
- }
+ } else
+ m_page->setGlyphDataForIndex(i, 0, 0);
}
if (!newGlyphs)
@@ -288,12 +286,9 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu
// ever finds it needs a glyph out of the system fallback page, it will
// ask the system for the best font to use and fill that glyph in for us.
if (parentPage)
- memcpy(m_page->m_glyphs, parentPage->m_glyphs, GlyphPage::size * sizeof(m_page->m_glyphs[0]));
- else {
- const GlyphData data = { 0, 0 };
- for (unsigned i = 0; i < GlyphPage::size; i++)
- m_page->m_glyphs[i] = data;
- }
+ m_page->copyFrom(*parentPage);
+ else
+ m_page->clear();
}
}
diff --git a/WebCore/platform/graphics/GlyphPageTreeNode.h b/WebCore/platform/graphics/GlyphPageTreeNode.h
index 240b492..80e87aa 100644
--- a/WebCore/platform/graphics/GlyphPageTreeNode.h
+++ b/WebCore/platform/graphics/GlyphPageTreeNode.h
@@ -29,6 +29,7 @@
#ifndef GlyphPageTreeNode_h
#define GlyphPageTreeNode_h
+#include <string.h>
#include <wtf/HashMap.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
@@ -45,6 +46,11 @@ typedef unsigned short Glyph;
// Holds the glyph index and the corresponding SimpleFontData information for a given
// character.
struct GlyphData {
+ GlyphData(Glyph g = 0, const SimpleFontData* f = 0)
+ : glyph(g)
+ , fontData(f)
+ {
+ }
Glyph glyph;
const SimpleFontData* fontData;
};
@@ -54,30 +60,69 @@ struct GlyphData {
// starting from 0 and incrementing for each 256 glyphs.
//
// One page may actually include glyphs from other fonts if the characters are
-// missing in the parimary font. It is owned by exactly one GlyphPageTreeNode,
+// missing in the primary font. It is owned by exactly one GlyphPageTreeNode,
// although multiple nodes may reference it as their "page" if they are supposed
// to be overriding the parent's node, but provide no additional information.
-struct GlyphPage : public RefCounted<GlyphPage> {
+class GlyphPage : public RefCounted<GlyphPage> {
+public:
static PassRefPtr<GlyphPage> create(GlyphPageTreeNode* owner)
{
return adoptRef(new GlyphPage(owner));
}
static const size_t size = 256; // Covers Latin-1 in a single page.
- GlyphData m_glyphs[size];
- GlyphPageTreeNode* m_owner;
- const GlyphData& glyphDataForCharacter(UChar32 c) const { return m_glyphs[c % size]; }
+ unsigned indexForCharacter(UChar32 c) const { return c % size; }
+ GlyphData glyphDataForCharacter(UChar32 c) const
+ {
+ unsigned index = indexForCharacter(c);
+ return GlyphData(m_glyphs[index], m_glyphFontData[index]);
+ }
+
+ GlyphData glyphDataForIndex(unsigned index) const
+ {
+ ASSERT(index < size);
+ return GlyphData(m_glyphs[index], m_glyphFontData[index]);
+ }
+
+ Glyph glyphAt(unsigned index) const
+ {
+ ASSERT(index < size);
+ return m_glyphs[index];
+ }
+
+ const SimpleFontData* fontDataForCharacter(UChar32 c) const
+ {
+ return m_glyphFontData[indexForCharacter(c)];
+ }
+
void setGlyphDataForCharacter(UChar32 c, Glyph g, const SimpleFontData* f)
{
- setGlyphDataForIndex(c % size, g, f);
+ setGlyphDataForIndex(indexForCharacter(c), g, f);
}
void setGlyphDataForIndex(unsigned index, Glyph g, const SimpleFontData* f)
{
ASSERT(index < size);
- m_glyphs[index].glyph = g;
- m_glyphs[index].fontData = f;
+ m_glyphs[index] = g;
+ m_glyphFontData[index] = f;
+ }
+ void setGlyphDataForIndex(unsigned index, const GlyphData& glyphData)
+ {
+ setGlyphDataForIndex(index, glyphData.glyph, glyphData.fontData);
+ }
+
+ void copyFrom(const GlyphPage& other)
+ {
+ memcpy(m_glyphs, other.m_glyphs, sizeof(m_glyphs));
+ memcpy(m_glyphFontData, other.m_glyphFontData, sizeof(m_glyphFontData));
+ }
+
+ void clear()
+ {
+ memset(m_glyphs, 0, sizeof(m_glyphs));
+ memset(m_glyphFontData, 0, sizeof(m_glyphFontData));
}
+
GlyphPageTreeNode* owner() const { return m_owner; }
// Implemented by the platform.
@@ -88,6 +133,12 @@ private:
: m_owner(owner)
{
}
+
+ // Separate arrays, rather than array of GlyphData, to save space.
+ Glyph m_glyphs[size];
+ const SimpleFontData* m_glyphFontData[size];
+
+ GlyphPageTreeNode* m_owner;
};
// The glyph page tree is a data structure that maps (FontData, glyph page number)
diff --git a/WebCore/platform/graphics/Gradient.cpp b/WebCore/platform/graphics/Gradient.cpp
index 24e8bbf..51c7162 100644
--- a/WebCore/platform/graphics/Gradient.cpp
+++ b/WebCore/platform/graphics/Gradient.cpp
@@ -52,6 +52,7 @@ Gradient::Gradient(const FloatPoint& p0, float r0, const FloatPoint& p1, float r
, m_r1(r1)
, m_stopsSorted(false)
, m_lastStop(0)
+ , m_spreadMethod(SpreadMethodPad)
{
platformInit();
}
diff --git a/WebCore/platform/graphics/GraphicsContext.cpp b/WebCore/platform/graphics/GraphicsContext.cpp
index 8cad794..4dae3d2 100644
--- a/WebCore/platform/graphics/GraphicsContext.cpp
+++ b/WebCore/platform/graphics/GraphicsContext.cpp
@@ -30,7 +30,6 @@
#include "Generator.h"
#include "GraphicsContextPrivate.h"
#include "Font.h"
-#include "NotImplemented.h"
using namespace std;
@@ -337,7 +336,7 @@ void GraphicsContext::drawBidiText(const Font& font, const TextRun& run, const F
BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
WTF::Unicode::Direction paragraphDirection = run.ltr() ? WTF::Unicode::LeftToRight : WTF::Unicode::RightToLeft;
- bidiResolver.setStatus(BidiStatus(paragraphDirection, paragraphDirection, paragraphDirection, new BidiContext(run.ltr() ? 0 : 1, paragraphDirection, run.directionalOverride())));
+ bidiResolver.setStatus(BidiStatus(paragraphDirection, paragraphDirection, paragraphDirection, BidiContext::create(run.ltr() ? 0 : 1, paragraphDirection, run.directionalOverride())));
bidiResolver.setPosition(TextRunIterator(&run, 0));
bidiResolver.createBidiRunsForLine(TextRunIterator(&run, run.length()));
diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h
index 7c1c4b0..3fdafad 100644
--- a/WebCore/platform/graphics/GraphicsContext.h
+++ b/WebCore/platform/graphics/GraphicsContext.h
@@ -374,6 +374,7 @@ namespace WebCore {
#if PLATFORM(QT) && defined(Q_WS_WIN)
HDC getWindowsContext(const IntRect&, bool supportAlphaBlend = true, bool mayCreateBitmap = true);
void releaseWindowsContext(HDC, const IntRect&, bool supportAlphaBlend = true, bool mayCreateBitmap = true);
+ bool shouldIncludeChildWindows() const { return false; }
#endif
#if PLATFORM(QT)
diff --git a/WebCore/platform/graphics/GraphicsLayer.h b/WebCore/platform/graphics/GraphicsLayer.h
index f928ce8..ae51951 100644
--- a/WebCore/platform/graphics/GraphicsLayer.h
+++ b/WebCore/platform/graphics/GraphicsLayer.h
@@ -288,8 +288,10 @@ public:
int incrementRepaintCount() { return ++m_repaintCount; }
#endif
- // Platform behaviors
- static bool graphicsContextsFlipped();
+ // Report whether the underlying compositing system uses a top-down
+ // or a bottom-up coordinate system.
+ enum CompositingCoordinatesOrientation { CompositingCoordinatesTopDown, CompositingCoordinatesBottomUp };
+ static CompositingCoordinatesOrientation compositingCoordinatesOrientation();
#ifndef NDEBUG
static bool showDebugBorders();
diff --git a/WebCore/platform/graphics/Image.h b/WebCore/platform/graphics/Image.h
index 70f6d49..cff8b22 100644
--- a/WebCore/platform/graphics/Image.h
+++ b/WebCore/platform/graphics/Image.h
@@ -61,8 +61,8 @@ class NativeImageSkia;
#include <QPixmap>
#endif
-#if PLATFORM(SGL)
-class SkBitmapRef;
+#if PLATFORM(GTK)
+typedef struct _GdkPixbuf GdkPixbuf;
#endif
namespace WebCore {
@@ -147,10 +147,13 @@ public:
#endif
#if PLATFORM(SGL)
- virtual SkBitmapRef* getBitmap() { return 0; }
virtual void setURL(const String& str) {}
#endif
+#if PLATFORM(GTK)
+ virtual GdkPixbuf* getGdkPixbuf() { return 0; }
+#endif
+
protected:
Image(ImageObserver* = 0);
diff --git a/WebCore/platform/graphics/ImageBuffer.h b/WebCore/platform/graphics/ImageBuffer.h
index 14f7461..573e274 100644
--- a/WebCore/platform/graphics/ImageBuffer.h
+++ b/WebCore/platform/graphics/ImageBuffer.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,8 +32,8 @@
#include "IntSize.h"
#include "ImageBufferData.h"
#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
#include <wtf/PassRefPtr.h>
-#include <memory>
namespace WebCore {
@@ -46,13 +46,13 @@ namespace WebCore {
class ImageBuffer : Noncopyable {
public:
// Will return a null pointer on allocation failure.
- static std::auto_ptr<ImageBuffer> create(const IntSize& size, bool grayScale)
+ static PassOwnPtr<ImageBuffer> create(const IntSize& size, bool grayScale)
{
bool success = false;
- std::auto_ptr<ImageBuffer> buf(new ImageBuffer(size, grayScale, success));
+ OwnPtr<ImageBuffer> buf(new ImageBuffer(size, grayScale, success));
if (success)
- return buf;
- return std::auto_ptr<ImageBuffer>();
+ return buf.release();
+ return 0;
}
~ImageBuffer();
@@ -80,7 +80,7 @@ namespace WebCore {
OwnPtr<GraphicsContext> m_context;
mutable RefPtr<Image> m_image;
- // This constructor will place its succes into the given out-variable
+ // This constructor will place its success into the given out-variable
// so that create() knows when it should return failure.
ImageBuffer(const IntSize&, bool grayScale, bool& success);
};
diff --git a/WebCore/platform/graphics/ImageSource.h b/WebCore/platform/graphics/ImageSource.h
index 07cc2c2..d4a1658 100644
--- a/WebCore/platform/graphics/ImageSource.h
+++ b/WebCore/platform/graphics/ImageSource.h
@@ -31,6 +31,7 @@
#if PLATFORM(WX)
class wxBitmap;
+class wxGraphicsBitmap;
#elif PLATFORM(CG)
typedef struct CGImageSource* CGImageSourceRef;
typedef struct CGImage* CGImageRef;
@@ -61,7 +62,11 @@ class String;
class ImageDecoder;
typedef ImageDecoder* NativeImageSourcePtr;
typedef const Vector<char>* NativeBytePtr;
+#if USE(WXGC)
+typedef wxGraphicsBitmap* NativeImagePtr;
+#else
typedef wxBitmap* NativeImagePtr;
+#endif
#elif PLATFORM(CG)
typedef CGImageSourceRef NativeImageSourcePtr;
typedef CGImageRef NativeImagePtr;
diff --git a/WebCore/platform/graphics/IntPoint.h b/WebCore/platform/graphics/IntPoint.h
index a05b1f0..1bfeeaa 100644
--- a/WebCore/platform/graphics/IntPoint.h
+++ b/WebCore/platform/graphics/IntPoint.h
@@ -70,6 +70,7 @@ class IntPoint {
public:
IntPoint() : m_x(0), m_y(0) { }
IntPoint(int x, int y) : m_x(x), m_y(y) { }
+ explicit IntPoint(const IntSize& size) : m_x(size.width()), m_y(size.height()) { }
int x() const { return m_x; }
int y() const { return m_y; }
diff --git a/WebCore/platform/graphics/IntSize.h b/WebCore/platform/graphics/IntSize.h
index 4d36545..cac0bd1 100644
--- a/WebCore/platform/graphics/IntSize.h
+++ b/WebCore/platform/graphics/IntSize.h
@@ -73,6 +73,12 @@ public:
m_height += height;
}
+ void scale(float scale)
+ {
+ m_width = static_cast<int>(static_cast<float>(m_width) * scale);
+ m_height = static_cast<int>(static_cast<float>(m_height) * scale);
+ }
+
IntSize expandedTo(const IntSize& other) const
{
return IntSize(m_width > other.m_width ? m_width : other.m_width,
diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp
index 99d6aa4..b580474 100644
--- a/WebCore/platform/graphics/MediaPlayer.cpp
+++ b/WebCore/platform/graphics/MediaPlayer.cpp
@@ -183,6 +183,7 @@ MediaPlayer::MediaPlayer(MediaPlayerClient* client)
, m_visible(false)
, m_rate(1.0f)
, m_volume(1.0f)
+ , m_autobuffer(false)
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
, m_playerProxy(0)
#endif
@@ -206,11 +207,20 @@ void MediaPlayer::load(const String& url, const ContentType& contentType)
String type = contentType.type();
String codecs = contentType.parameter("codecs");
- // if we don't know the MIME type, see if the path can help
- if (type.isEmpty())
- type = MIMETypeRegistry::getMIMETypeForPath(url);
+ // if we don't know the MIME type, see if the extension can help
+ if (type.isEmpty() || type == "application/octet-stream" || type == "text/plain") {
+ int pos = url.reverseFind('.');
+ if (pos >= 0) {
+ String extension = url.substring(pos + 1);
+ String mediaType = MIMETypeRegistry::getMediaMIMETypeForExtension(extension);
+ if (!mediaType.isEmpty())
+ type = mediaType;
+ }
+ }
- MediaPlayerFactory* engine = chooseBestEngineForTypeAndCodecs(type, codecs);
+ MediaPlayerFactory* engine = 0;
+ if (!type.isEmpty())
+ engine = chooseBestEngineForTypeAndCodecs(type, codecs);
// if we didn't find an engine that claims the MIME type, just use the first engine
if (!engine)
@@ -260,6 +270,11 @@ float MediaPlayer::duration() const
return m_private->duration();
}
+float MediaPlayer::startTime() const
+{
+ return m_private->startTime();
+}
+
float MediaPlayer::currentTime() const
{
return m_private->currentTime();
@@ -382,6 +397,19 @@ void MediaPlayer::setVisible(bool b)
m_private->setVisible(b);
}
+bool MediaPlayer::autobuffer() const
+{
+ return m_autobuffer;
+}
+
+void MediaPlayer::setAutobuffer(bool b)
+{
+ if (m_autobuffer != b) {
+ m_autobuffer = b;
+ m_private->setAutobuffer(b);
+ }
+}
+
void MediaPlayer::paint(GraphicsContext* p, const IntRect& r)
{
m_private->paint(p, r);
diff --git a/WebCore/platform/graphics/MediaPlayer.h b/WebCore/platform/graphics/MediaPlayer.h
index 7d90e44..9b2f685 100644
--- a/WebCore/platform/graphics/MediaPlayer.h
+++ b/WebCore/platform/graphics/MediaPlayer.h
@@ -76,6 +76,11 @@ public:
// the movie size has changed
virtual void mediaPlayerSizeChanged(MediaPlayer*) { }
+
+ // The MediaPlayer has found potentially problematic media content.
+ // This is used internally to trigger swapping from a <video>
+ // element to an <embed> in standalone documents
+ virtual void mediaPlayerSawUnsupportedTracks(MediaPlayer*) { }
};
class MediaPlayer : Noncopyable {
@@ -88,7 +93,7 @@ public:
static MediaPlayer::SupportsType supportsType(ContentType contentType);
static void getSupportedTypes(HashSet<String>&);
static bool isAvailable();
-
+
IntSize naturalSize();
bool hasVideo();
@@ -114,6 +119,8 @@ public:
float duration() const;
float currentTime() const;
void seek(float time);
+
+ float startTime() const;
void setEndTime(float time);
@@ -131,7 +138,10 @@ public:
void setVolume(float);
int dataRate() const;
-
+
+ bool autobuffer() const;
+ void setAutobuffer(bool);
+
void paint(GraphicsContext*, const IntRect&);
enum NetworkState { Empty, Idle, Loading, Loaded, FormatError, NetworkError, DecodeError };
@@ -169,6 +179,7 @@ private:
bool m_visible;
float m_rate;
float m_volume;
+ bool m_autobuffer;
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
WebMediaPlayerProxy* m_playerProxy; // not owned or used, passed to m_private
#endif
diff --git a/WebCore/platform/graphics/MediaPlayerPrivate.h b/WebCore/platform/graphics/MediaPlayerPrivate.h
index 2e73e7e..e17259c 100644
--- a/WebCore/platform/graphics/MediaPlayerPrivate.h
+++ b/WebCore/platform/graphics/MediaPlayerPrivate.h
@@ -58,7 +58,9 @@ public:
virtual void seek(float time) = 0;
virtual bool seeking() const = 0;
- virtual void setEndTime(float time) = 0;
+ virtual float startTime() const { return 0; }
+
+ virtual void setEndTime(float) = 0;
virtual void setRate(float) = 0;
virtual bool paused() const = 0;
@@ -81,6 +83,8 @@ public:
virtual void paint(GraphicsContext*, const IntRect&) = 0 ;
+ virtual void setAutobuffer(bool) { };
+
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
virtual void setPoster(const String& url) = 0;
virtual void deliverNotification(MediaPlayerProxyNotificationType) = 0;
diff --git a/WebCore/platform/graphics/Path.cpp b/WebCore/platform/graphics/Path.cpp
index f3450be..e30703c 100644
--- a/WebCore/platform/graphics/Path.cpp
+++ b/WebCore/platform/graphics/Path.cpp
@@ -35,7 +35,7 @@
#include <math.h>
#include <wtf/MathExtras.h>
-const float QUARTER = 0.552f; // approximation of control point positions on a bezier
+static const float QUARTER = 0.552f; // approximation of control point positions on a bezier
// to simulate a quarter of a circle.
namespace WebCore {
diff --git a/WebCore/platform/graphics/SimpleFontData.cpp b/WebCore/platform/graphics/SimpleFontData.cpp
index 9f51037..bab7d99 100644
--- a/WebCore/platform/graphics/SimpleFontData.cpp
+++ b/WebCore/platform/graphics/SimpleFontData.cpp
@@ -32,18 +32,24 @@
#include "Font.h"
#include "FontCache.h"
+
#if ENABLE(SVG_FONTS)
#include "SVGFontData.h"
+#include "SVGFontElement.h"
#include "SVGFontFaceElement.h"
+#include "SVGGlyphElement.h"
#endif
#include <wtf/MathExtras.h>
+#include <wtf/UnusedParam.h>
+
+using namespace std;
namespace WebCore {
SimpleFontData::SimpleFontData(const FontPlatformData& f, bool customFont, bool loading, SVGFontData* svgFontData)
: m_unitsPerEm(defaultUnitsPerEm)
- , m_font(f)
+ , m_platformData(f)
, m_treatAsFixedPitch(false)
#if ENABLE(SVG_FONTS)
, m_svgFontData(svgFontData)
@@ -52,24 +58,40 @@ SimpleFontData::SimpleFontData(const FontPlatformData& f, bool customFont, bool
, m_isLoading(loading)
, m_smallCapsFontData(0)
{
-#if ENABLE(SVG_FONTS)
+#if !ENABLE(SVG_FONTS)
+ UNUSED_PARAM(svgFontData);
+#else
if (SVGFontFaceElement* svgFontFaceElement = svgFontData ? svgFontData->svgFontFaceElement() : 0) {
- m_unitsPerEm = svgFontFaceElement->unitsPerEm();
+ m_unitsPerEm = svgFontFaceElement->unitsPerEm();
- double scale = f.size();
- if (m_unitsPerEm)
- scale /= m_unitsPerEm;
+ double scale = f.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 * f.size();
m_lineSpacing = m_ascent + m_descent + m_lineGap;
-
+
+ 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);
+
+ Vector<SVGGlyphIdentifier> numeralZeroGlyphs;
+ associatedFontElement->getGlyphIdentifiersForString(String("0", 1), numeralZeroGlyphs);
+ m_avgCharWidth = numeralZeroGlyphs.isEmpty() ? m_spaceWidth : static_cast<float>(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);
+
+ // FIXME: is there a way we can get the space glyph from the SVGGlyphIdentifier above?
m_spaceGlyph = 0;
- m_spaceWidth = 0;
- m_adjustedSpaceWidth = 0;
determinePitch();
+ m_adjustedSpaceWidth = roundf(m_spaceWidth);
m_missingGlyphData.fontData = this;
m_missingGlyphData.glyph = 0;
return;
@@ -78,9 +100,31 @@ SimpleFontData::SimpleFontData(const FontPlatformData& f, bool customFont, bool
platformInit();
platformGlyphInit();
+ platformCharWidthInit();
}
#if !PLATFORM(QT)
+// Estimates of avgCharWidth and maxCharWidth for platforms that don't support accessing these values from the font.
+void SimpleFontData::initCharWidths()
+{
+ GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
+
+ // Treat the width of a '0' as the avgCharWidth.
+ if (m_avgCharWidth <= 0.f && glyphPageZero) {
+ static const UChar32 digitZeroChar = '0';
+ Glyph digitZeroGlyph = glyphPageZero->glyphDataForCharacter(digitZeroChar).glyph;
+ if (digitZeroGlyph)
+ m_avgCharWidth = widthForGlyph(digitZeroGlyph);
+ }
+
+ // 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;
+
+ if (m_maxCharWidth <= 0.f)
+ m_maxCharWidth = max<float>(m_avgCharWidth, m_ascent);
+}
+
void SimpleFontData::platformGlyphInit()
{
GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
diff --git a/WebCore/platform/graphics/SimpleFontData.h b/WebCore/platform/graphics/SimpleFontData.h
index d2dd0b9..aab6429 100644
--- a/WebCore/platform/graphics/SimpleFontData.h
+++ b/WebCore/platform/graphics/SimpleFontData.h
@@ -61,7 +61,7 @@ public:
virtual ~SimpleFontData();
public:
- const FontPlatformData& platformData() const { return m_font; }
+ const FontPlatformData& platformData() const { return m_platformData; }
SimpleFontData* smallCapsFontData(const FontDescription& fontDescription) const;
// vertical metrics
@@ -69,12 +69,23 @@ public:
int descent() const { return m_descent; }
int lineSpacing() const { return m_lineSpacing; }
int lineGap() const { return m_lineGap; }
+ float maxCharWidth() const { return m_maxCharWidth; }
+ float avgCharWidth() const { return m_avgCharWidth; }
float xHeight() const { return m_xHeight; }
unsigned unitsPerEm() const { return m_unitsPerEm; }
float widthForGlyph(Glyph) const;
float platformWidthForGlyph(Glyph) const;
+ float spaceWidth() const { return m_spaceWidth; }
+ float adjustedSpaceWidth() const { return m_adjustedSpaceWidth; }
+
+#if PLATFORM(CG) || PLATFORM(CAIRO)
+ float syntheticBoldOffset() const { return m_syntheticBoldOffset; }
+#endif
+
+ Glyph spaceGlyph() const { return m_spaceGlyph; }
+
virtual const SimpleFontData* fontDataForCharacter(UChar32) const;
virtual bool containsCharacters(const UChar*, int length) const;
@@ -95,7 +106,7 @@ public:
const GlyphData& missingGlyphData() const { return m_missingGlyphData; }
#if PLATFORM(MAC)
- NSFont* getNSFont() const { return m_font.font(); }
+ NSFont* getNSFont() const { return m_platformData.font(); }
#endif
#if USE(CORE_TEXT)
@@ -114,7 +125,7 @@ public:
#endif
#if PLATFORM(QT)
- QFont getQtFont() const { return m_font.font(); }
+ QFont getQtFont() const { return m_platformData.font(); }
#endif
#if PLATFORM(WIN)
@@ -131,14 +142,17 @@ public:
#endif
#if PLATFORM(WX)
- wxFont* getWxFont() const { return m_font.font(); }
+ wxFont* getWxFont() const { return m_platformData.font(); }
#endif
private:
void platformInit();
void platformGlyphInit();
+ void platformCharWidthInit();
void platformDestroy();
+ void initCharWidths();
+
void commonInit();
#if PLATFORM(WIN)
@@ -147,15 +161,16 @@ private:
float widthForGDIGlyph(Glyph glyph) const;
#endif
-public:
int m_ascent;
int m_descent;
int m_lineSpacing;
int m_lineGap;
+ float m_maxCharWidth;
+ float m_avgCharWidth;
float m_xHeight;
unsigned m_unitsPerEm;
- FontPlatformData m_font;
+ FontPlatformData m_platformData;
mutable GlyphWidthMap m_glyphToWidthMap;
@@ -176,22 +191,26 @@ public:
mutable SimpleFontData* m_smallCapsFontData;
-#if PLATFORM(CG) || PLATFORM(WIN)
+#if PLATFORM(CG) || PLATFORM(CAIRO)
float m_syntheticBoldOffset;
#endif
-#if PLATFORM(MAC)
#ifdef BUILDING_ON_TIGER
+public:
void* m_styleGroup;
-#endif
+
+private:
#endif
#if USE(ATSUI)
+public:
mutable ATSUStyle m_ATSUStyle;
mutable bool m_ATSUStyleInitialized;
mutable bool m_ATSUMirrors;
mutable bool m_checkedShapesArabic;
mutable bool m_shapesArabic;
+
+private:
#endif
#if USE(CORE_TEXT)
diff --git a/WebCore/platform/graphics/WidthIterator.cpp b/WebCore/platform/graphics/WidthIterator.cpp
index a16d739..9157310 100644
--- a/WebCore/platform/graphics/WidthIterator.cpp
+++ b/WebCore/platform/graphics/WidthIterator.cpp
@@ -39,13 +39,14 @@ namespace WebCore {
// According to http://www.unicode.org/Public/UNIDATA/UCD.html#Canonical_Combining_Class_Values
static const uint8_t hiraganaKatakanaVoicingMarksCombiningClass = 8;
-WidthIterator::WidthIterator(const Font* font, const TextRun& run)
+WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts)
: m_font(font)
, m_run(run)
, m_end(run.length())
, m_currentCharacter(0)
, m_runWidthSoFar(0)
, m_finalRoundingWidth(0)
+ , m_fallbackFonts(fallbackFonts)
{
// If the padding is non-zero, count the number of spaces in the run
// and divide that by the padding for per space addition.
@@ -78,7 +79,10 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
float runWidthSoFar = m_runWidthSoFar;
float lastRoundingWidth = m_finalRoundingWidth;
-
+
+ const SimpleFontData* primaryFont = m_font->primaryFont();
+ const SimpleFontData* lastFontData = primaryFont;
+
while (currentCharacter < offset) {
UChar32 c = *cp;
unsigned clusterLength = 1;
@@ -126,16 +130,29 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
// First, we round spaces to an adjusted width in all fonts.
// Second, in fixed-pitch fonts we ensure that all characters that
// match the width of the space character have the same width as the space character.
- if (width == fontData->m_spaceWidth && (fontData->m_treatAsFixedPitch || glyph == fontData->m_spaceGlyph) && m_run.applyWordRounding()) {
- width = fontData->m_adjustedSpaceWidth;
+ if (width == fontData->spaceWidth() && (fontData->pitch() == FixedPitch || glyph == fontData->spaceGlyph()) && m_run.applyWordRounding())
+ width = fontData->adjustedSpaceWidth();
+ }
+
+ if (fontData != lastFontData && width) {
+ lastFontData = fontData;
+ if (m_fallbackFonts && fontData != primaryFont) {
+ // FIXME: This does a little extra work that could be avoided if
+ // glyphDataForCharacter() returned whether it chose to use a small caps font.
+ if (!m_font->isSmallCaps() || c == toUpper(c))
+ m_fallbackFonts->add(fontData);
+ else {
+ const GlyphData& uppercaseGlyphData = m_font->glyphDataForCharacter(toUpper(c), rtl);
+ if (uppercaseGlyphData.fontData != primaryFont)
+ m_fallbackFonts->add(uppercaseGlyphData.fontData);
+ }
}
}
if (hasExtraSpacing) {
// Account for letter-spacing.
- if (width && m_font->letterSpacing()) {
+ if (width && m_font->letterSpacing())
width += m_font->letterSpacing();
- }
if (Font::treatAsSpace(c)) {
// Account for padding. WebCore uses space padding to justify text.
@@ -153,9 +170,8 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
// 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 (currentCharacter != 0 && !Font::treatAsSpace(cp[-1]) && m_font->wordSpacing())
width += m_font->wordSpacing();
- }
}
}
@@ -172,9 +188,8 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
// Force characters that are used to determine word boundaries for the rounding hack
// to be integer width, so following words will start on an integer boundary.
- if (m_run.applyWordRounding() && Font::isRoundingHackCharacter(c)) {
+ if (m_run.applyWordRounding() && Font::isRoundingHackCharacter(c))
width = ceilf(width);
- }
// Check to see if the next character is a "rounding hack character", if so, adjust
// width so that the total run width will be on an integer boundary.
diff --git a/WebCore/platform/graphics/WidthIterator.h b/WebCore/platform/graphics/WidthIterator.h
index 5706d1e..7ca4198 100644
--- a/WebCore/platform/graphics/WidthIterator.h
+++ b/WebCore/platform/graphics/WidthIterator.h
@@ -22,16 +22,18 @@
#ifndef WidthIterator_h
#define WidthIterator_h
+#include <wtf/HashSet.h>
#include <wtf/unicode/Unicode.h>
namespace WebCore {
class Font;
class GlyphBuffer;
+class SimpleFontData;
class TextRun;
struct WidthIterator {
- WidthIterator(const Font*, const TextRun&);
+ WidthIterator(const Font*, const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0);
void advance(int to, GlyphBuffer* = 0);
bool advanceOneCharacter(float& width, GlyphBuffer* = 0);
@@ -49,6 +51,7 @@ struct WidthIterator {
private:
UChar32 normalizeVoicingMarks(int currentCharacter);
+ HashSet<const SimpleFontData*>* m_fallbackFonts;
};
}
diff --git a/WebCore/platform/graphics/android/FontAndroid.cpp b/WebCore/platform/graphics/android/FontAndroid.cpp
index ca2fca1..a430b07 100644
--- a/WebCore/platform/graphics/android/FontAndroid.cpp
+++ b/WebCore/platform/graphics/android/FontAndroid.cpp
@@ -107,6 +107,11 @@ static bool setupForText(SkPaint* paint, GraphicsContext* gc,
return true;
}
+bool Font::canReturnFallbackFontsForComplexText()
+{
+ return false;
+}
+
void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
const GlyphBuffer& glyphBuffer, int from, int numGlyphs,
const FloatPoint& point) const
@@ -206,7 +211,7 @@ void Font::drawComplexText(GraphicsContext* gc, TextRun const& run,
paint);
}
-float Font::floatWidthForComplexText(const TextRun& run) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*) const
{
SkPaint paint;
diff --git a/WebCore/platform/graphics/android/FontDataAndroid.cpp b/WebCore/platform/graphics/android/FontDataAndroid.cpp
index 3d31eaf..2bb53e4 100644
--- a/WebCore/platform/graphics/android/FontDataAndroid.cpp
+++ b/WebCore/platform/graphics/android/FontDataAndroid.cpp
@@ -48,7 +48,7 @@ void SimpleFontData::platformInit()
SkPaint paint;
SkPaint::FontMetrics metrics;
- m_font.setupPaint(&paint);
+ m_platformData.setupPaint(&paint);
(void)paint.getFontMetrics(&metrics);
// use ceil instead of round to favor descent, given a lot of accidental
@@ -64,6 +64,13 @@ void SimpleFontData::platformInit()
m_lineGap = SkScalarRound(metrics.fLeading);
}
+void SimpleFontData::platformCharWidthInit()
+{
+ m_avgCharWidth = 0.f;
+ m_maxCharWidth = 0.f;
+ initCharWidths();
+}
+
void SimpleFontData::platformDestroy()
{
delete m_smallCapsFontData;
@@ -72,7 +79,7 @@ void SimpleFontData::platformDestroy()
SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
{
if (!m_smallCapsFontData) {
- m_smallCapsFontData = new SimpleFontData(FontPlatformData(m_font, fontDescription.computedSize() * 0.7f));
+ m_smallCapsFontData = new SimpleFontData(FontPlatformData(m_platformData, fontDescription.computedSize() * 0.7f));
}
return m_smallCapsFontData;
}
@@ -84,7 +91,7 @@ bool SimpleFontData::containsCharacters(const UChar* characters, int length) con
SkPaint paint;
uint16_t glyphs[kMaxBufferCount];
- m_font.setupPaint(&paint);
+ m_platformData.setupPaint(&paint);
paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
while (length > 0) {
@@ -114,7 +121,7 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
SkPaint paint;
- m_font.setupPaint(&paint);
+ m_platformData.setupPaint(&paint);
if (EmojiFont::IsEmojiGlyph(glyph))
return EmojiFont::GetAdvanceWidth(glyph, paint);
diff --git a/WebCore/platform/graphics/cairo/FontCairo.cpp b/WebCore/platform/graphics/cairo/FontCairo.cpp
index b23182d..0f7ae79 100644
--- a/WebCore/platform/graphics/cairo/FontCairo.cpp
+++ b/WebCore/platform/graphics/cairo/FontCairo.cpp
@@ -36,6 +36,8 @@
#include "SimpleFontData.h"
#include "TransformationMatrix.h"
+#define SYNTHETIC_OBLIQUE_ANGLE 14
+
namespace WebCore {
void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
@@ -48,15 +50,23 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
GlyphBufferGlyph* glyphs = (GlyphBufferGlyph*)glyphBuffer.glyphs(from);
- float offset = point.x();
+ float offset = 0.0f;
for (int i = 0; i < numGlyphs; i++) {
glyphs[i].x = offset;
- glyphs[i].y = point.y();
+ glyphs[i].y = 0.0f;
offset += glyphBuffer.advanceAt(from + i);
}
Color fillColor = context->fillColor();
+ // Synthetic Oblique
+ if(font->platformData().syntheticOblique()) {
+ cairo_matrix_t mat = {1, 0, -tanf(SYNTHETIC_OBLIQUE_ANGLE * acosf(0) / 90), 1, point.x(), point.y()};
+ cairo_transform(cr, &mat);
+ } else {
+ cairo_translate(cr, point.x(), point.y());
+ }
+
// Text shadow, inspired by FontMac
IntSize shadowSize;
int shadowBlur = 0;
@@ -77,6 +87,12 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
cairo_translate(cr, shadowSize.width(), shadowSize.height());
cairo_show_glyphs(cr, glyphs, numGlyphs);
+ if (font->syntheticBoldOffset()) {
+ cairo_save(cr);
+ cairo_translate(cr, font->syntheticBoldOffset(), 0);
+ cairo_show_glyphs(cr, glyphs, numGlyphs);
+ cairo_restore(cr);
+ }
cairo_restore(cr);
}
@@ -103,6 +119,12 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
cairo_set_source_rgba(cr, red, green, blue, alpha * context->getAlpha());
}
cairo_show_glyphs(cr, glyphs, numGlyphs);
+ if (font->syntheticBoldOffset()) {
+ cairo_save(cr);
+ cairo_translate(cr, font->syntheticBoldOffset(), 0);
+ cairo_show_glyphs(cr, glyphs, numGlyphs);
+ cairo_restore(cr);
+ }
}
if (context->textDrawingMode() & cTextStroke) {
diff --git a/WebCore/platform/graphics/cairo/GradientCairo.cpp b/WebCore/platform/graphics/cairo/GradientCairo.cpp
index 72fb0c5..0aada55 100644
--- a/WebCore/platform/graphics/cairo/GradientCairo.cpp
+++ b/WebCore/platform/graphics/cairo/GradientCairo.cpp
@@ -80,11 +80,11 @@ void Gradient::fill(GraphicsContext* context, const FloatRect& rect)
{
cairo_t* cr = context->platformContext();
- cairo_save(cr);
+ context->save();
cairo_set_source(cr, platformGradient());
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
cairo_fill(cr);
- cairo_restore(cr);
+ context->restore();
}
} //namespace
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index 35ebd3c..23f30f3 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -92,6 +92,7 @@ GraphicsContext::GraphicsContext(PlatformGraphicsContext* cr)
, m_data(new GraphicsContextPlatformPrivate)
{
m_data->cr = cairo_reference(cr);
+ m_data->syncContext(cr);
setPaintingDisabled(!cr);
}
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h b/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
index 55b2e25..531ebf4 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
+++ b/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
@@ -73,6 +73,7 @@ public:
void concatCTM(const TransformationMatrix&);
void beginTransparencyLayer() { m_transparencyCount++; }
void endTransparencyLayer() { m_transparencyCount--; }
+ void syncContext(PlatformGraphicsContext* cr);
#else
// On everything else, we do nothing.
void save() {}
@@ -85,6 +86,7 @@ public:
void concatCTM(const TransformationMatrix&) {}
void beginTransparencyLayer() {}
void endTransparencyLayer() {}
+ void syncContext(PlatformGraphicsContext* cr) {}
#endif
cairo_t* cr;
diff --git a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
index dff39b7..d2652d6 100644
--- a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
@@ -34,7 +34,6 @@
#include "GraphicsContext.h"
#include "ImageData.h"
#include "MIMETypeRegistry.h"
-#include "NotImplemented.h"
#include "Pattern.h"
#include "PlatformString.h"
diff --git a/WebCore/platform/graphics/cairo/ImageCairo.cpp b/WebCore/platform/graphics/cairo/ImageCairo.cpp
index 224154e..7c34e6f 100644
--- a/WebCore/platform/graphics/cairo/ImageCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageCairo.cpp
@@ -33,10 +33,12 @@
#include "Color.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
+#include "ImageBuffer.h"
#include "ImageObserver.h"
#include "TransformationMatrix.h"
#include <cairo.h>
#include <math.h>
+#include <wtf/OwnPtr.h>
namespace WebCore {
@@ -89,15 +91,19 @@ BitmapImage::BitmapImage(cairo_surface_t* surface, ImageObserver* observer)
void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, CompositeOperator op)
{
+ FloatRect srcRect(src);
+ FloatRect dstRect(dst);
+
+ if (dstRect.width() == 0.0f || dstRect.height() == 0.0f ||
+ srcRect.width() == 0.0f || srcRect.height() == 0.0f)
+ return;
+
startAnimation();
cairo_surface_t* image = frameAtIndex(m_currentFrame);
if (!image) // If it's too early we won't have an image yet.
return;
- FloatRect srcRect(src);
- FloatRect dstRect(dst);
-
if (mayFillWithSolidColor()) {
fillWithSolidColor(context, dstRect, solidColor(), op);
return;
@@ -106,7 +112,7 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo
IntSize selfSize = size();
cairo_t* cr = context->platformContext();
- cairo_save(cr);
+ context->save();
// Set the compositing operation.
if (op == CompositeSourceOver && !frameHasAlphaAtIndex(m_currentFrame))
@@ -138,7 +144,7 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo
cairo_clip(cr);
cairo_paint_with_alpha(cr, context->getAlpha());
- cairo_restore(cr);
+ context->restore();
if (imageObserver())
imageObserver()->didDraw(this);
@@ -154,7 +160,18 @@ void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, con
cairo_t* cr = context->platformContext();
context->save();
- // TODO: Make use of tileRect.
+ IntRect imageSize = enclosingIntRect(tileRect);
+ OwnPtr<ImageBuffer> imageSurface = ImageBuffer::create(imageSize.size(), false);
+
+ if (!imageSurface)
+ return;
+
+ if (tileRect.size() != size()) {
+ cairo_t* clippedImageContext = imageSurface->context()->platformContext();
+ cairo_set_source_surface(clippedImageContext, image, -tileRect.x(), -tileRect.y());
+ cairo_paint(clippedImageContext);
+ image = imageSurface->image()->nativeImageForCurrentFrame();
+ }
cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
@@ -163,7 +180,7 @@ void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, con
cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST);
cairo_matrix_t pattern_matrix = cairo_matrix_t(patternTransform);
- cairo_matrix_t phase_matrix = {1, 0, 0, 1, phase.x(), phase.y()};
+ cairo_matrix_t phase_matrix = {1, 0, 0, 1, phase.x() + tileRect.x() * patternTransform.a(), phase.y() + tileRect.y() * patternTransform.d()};
cairo_matrix_t combined;
cairo_matrix_multiply(&combined, &pattern_matrix, &phase_matrix);
cairo_matrix_invert(&combined);
diff --git a/WebCore/platform/graphics/cairo/ImageSourceCairo.cpp b/WebCore/platform/graphics/cairo/ImageSourceCairo.cpp
index c6d54f2..b51caf6 100644
--- a/WebCore/platform/graphics/cairo/ImageSourceCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageSourceCairo.cpp
@@ -190,13 +190,13 @@ NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
// Cairo does not like zero height images.
// If we have a zero height image, just pretend we don't have enough data yet.
- if (!buffer->height())
+ if (!size().height())
return 0;
return cairo_image_surface_create_for_data((unsigned char*)buffer->bytes().data(),
CAIRO_FORMAT_ARGB32,
size().width(),
- buffer->height(),
+ size().height(),
size().width()*4);
}
diff --git a/WebCore/platform/graphics/cairo/PathCairo.cpp b/WebCore/platform/graphics/cairo/PathCairo.cpp
index 24354d2..13ca1e2 100644
--- a/WebCore/platform/graphics/cairo/PathCairo.cpp
+++ b/WebCore/platform/graphics/cairo/PathCairo.cpp
@@ -29,7 +29,6 @@
#include "CairoPath.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
-#include "NotImplemented.h"
#include "PlatformString.h"
#include "StrokeStyleApplier.h"
diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index 4b8a555..ab8eb3c 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -116,10 +116,9 @@ void GraphicsContext::drawRect(const IntRect& rect)
CGContextRef context = platformContext();
- if (fillColor().alpha())
- CGContextFillRect(context, rect);
+ CGContextFillRect(context, rect);
- if (strokeStyle() != NoStroke && strokeColor().alpha()) {
+ if (strokeStyle() != NoStroke) {
// We do a fill of four rects to simulate the stroke of a border.
Color oldFillColor = fillColor();
if (oldFillColor != strokeColor())
@@ -142,7 +141,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
if (paintingDisabled())
return;
- if (strokeStyle() == NoStroke || !strokeColor().alpha())
+ if (strokeStyle() == NoStroke)
return;
float width = strokeThickness();
@@ -277,7 +276,7 @@ void GraphicsContext::drawEllipse(const IntRect& rect)
void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
{
- if (paintingDisabled() || strokeStyle() == NoStroke || strokeThickness() <= 0.0f || !strokeColor().alpha())
+ if (paintingDisabled() || strokeStyle() == NoStroke || strokeThickness() <= 0.0f)
return;
CGContextRef context = platformContext();
@@ -366,7 +365,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool antialiased)
{
- if (paintingDisabled() || !fillColor().alpha() && (strokeThickness() <= 0 || strokeStyle() == NoStroke))
+ if (paintingDisabled())
return;
if (npoints <= 1)
@@ -491,8 +490,7 @@ void GraphicsContext::fillPath()
CGContextRef context = platformContext();
switch (m_common->state.fillColorSpace) {
case SolidColorSpace:
- if (fillColor().alpha())
- fillPathWithFillRule(context, fillRule());
+ fillPathWithFillRule(context, fillRule());
break;
case PatternColorSpace:
applyFillPattern();
@@ -519,8 +517,7 @@ void GraphicsContext::strokePath()
CGContextRef context = platformContext();
switch (m_common->state.strokeColorSpace) {
case SolidColorSpace:
- if (strokeColor().alpha())
- CGContextStrokePath(context);
+ CGContextStrokePath(context);
break;
case PatternColorSpace:
applyStrokePattern();
@@ -544,8 +541,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
CGContextRef context = platformContext();
switch (m_common->state.fillColorSpace) {
case SolidColorSpace:
- if (fillColor().alpha())
- CGContextFillRect(context, rect);
+ CGContextFillRect(context, rect);
break;
case PatternColorSpace:
applyFillPattern();
@@ -565,20 +561,18 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
{
if (paintingDisabled())
return;
- if (color.alpha()) {
- CGContextRef context = platformContext();
- Color oldFillColor = fillColor();
- if (oldFillColor != color)
- setCGFillColor(context, color);
- CGContextFillRect(context, rect);
- if (oldFillColor != color)
- setCGFillColor(context, oldFillColor);
- }
+ CGContextRef context = platformContext();
+ Color oldFillColor = fillColor();
+ if (oldFillColor != color)
+ setCGFillColor(context, color);
+ CGContextFillRect(context, rect);
+ if (oldFillColor != color)
+ setCGFillColor(context, oldFillColor);
}
void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
{
- if (paintingDisabled() || !color.alpha())
+ if (paintingDisabled())
return;
CGContextRef context = platformContext();
@@ -782,8 +776,7 @@ void GraphicsContext::strokeRect(const FloatRect& r, float lineWidth)
CGContextRef context = platformContext();
switch (m_common->state.strokeColorSpace) {
case SolidColorSpace:
- if (strokeColor().alpha())
- CGContextStrokeRectWithWidth(context, r, lineWidth);
+ CGContextStrokeRectWithWidth(context, r, lineWidth);
break;
case PatternColorSpace:
applyStrokePattern();
@@ -1199,4 +1192,3 @@ void GraphicsContext::setCompositeOperation(CompositeOperator mode)
#endif
}
-
diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
index c059985..7cb8799 100644
--- a/WebCore/platform/graphics/cg/ImageSourceCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
@@ -33,10 +33,12 @@
#include "MIMETypeRegistry.h"
#include "SharedBuffer.h"
#include <ApplicationServices/ApplicationServices.h>
+#include <wtf/UnusedParam.h>
namespace WebCore {
static const CFStringRef kCGImageSourceShouldPreferRGB32 = CFSTR("kCGImageSourceShouldPreferRGB32");
+static const CFStringRef kCGImageSourceDoNotCacheImageBlocks = CFSTR("kCGImageSourceDoNotCacheImageBlocks");
ImageSource::ImageSource()
: m_decoder(0)
@@ -48,11 +50,24 @@ ImageSource::~ImageSource()
clear(true);
}
-void ImageSource::clear(bool, size_t, SharedBuffer* data, bool allDataReceived)
+void ImageSource::clear(bool destroyAllFrames, size_t, SharedBuffer* data, bool allDataReceived)
{
- // We always destroy the decoder, because there is no API to get it to
- // selectively release some of the frames it's holding, and if we don't
- // release any of them, we use too much memory on large images.
+#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ // Recent versions of ImageIO discard previously decoded image frames if the client
+ // application no longer holds references to them, so there's no need to throw away
+ // the decoder unless we're explicitly asked to destroy all of the frames.
+
+ if (!destroyAllFrames)
+ return;
+#else
+ // Older versions of ImageIO hold references to previously decoded image frames.
+ // There is no API to selectively release some of the frames it is holding, and
+ // if we don't release the frames we use too much memory on large images.
+ // Destroying the decoder is the only way to release previous frames.
+
+ UNUSED_PARAM(destroyAllFrames);
+#endif
+
if (m_decoder) {
CFRelease(m_decoder);
m_decoder = 0;
@@ -66,9 +81,9 @@ static CFDictionaryRef imageSourceOptions()
static CFDictionaryRef options;
if (!options) {
- const void* keys[2] = { kCGImageSourceShouldCache, kCGImageSourceShouldPreferRGB32 };
- const void* values[2] = { kCFBooleanTrue, kCFBooleanTrue };
- options = CFDictionaryCreate(NULL, keys, values, 2,
+ const void* keys[3] = { kCGImageSourceShouldCache, kCGImageSourceShouldPreferRGB32, kCGImageSourceDoNotCacheImageBlocks };
+ const void* values[3] = { kCFBooleanTrue, kCFBooleanTrue, kCFBooleanTrue };
+ options = CFDictionaryCreate(NULL, keys, values, 3,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
}
return options;
@@ -227,9 +242,17 @@ float ImageSource::frameDurationAtIndex(size_t index)
bool ImageSource::frameHasAlphaAtIndex(size_t)
{
- // Might be interesting to do this optimization on Mac some day, but for now we're just using this
- // for the Cairo source, since it uses our decoders, and our decoders can answer this question.
- // FIXME: Could return false for JPEG and other non-transparent image formats.
+ if (!m_decoder)
+ return false;
+
+ CFStringRef imageType = CGImageSourceGetType(m_decoder);
+
+ // Return false if there is no image type or the image type is JPEG, because
+ // JPEG does not support alpha transparency.
+ if (!imageType || CFEqual(imageType, CFSTR("public.jpeg")))
+ return false;
+
+ // FIXME: Could return false for other non-transparent image formats.
// FIXME: Could maybe return false for a GIF Frame if we have enough info in the GIF properties dictionary
// to determine whether or not a transparent color was defined.
return true;
diff --git a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
index 129776e..bf1cd2e 100644
--- a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
@@ -414,14 +414,6 @@ FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& description)
{
FontDescription::GenericFamilyType generic = description.genericFamily();
- // FIXME: Mapping webkit generic to GenericFamilyType needs to
- // be more intelligent.
- // This spot rarely gets reached. GetFontDataForCharacters() gets hit a lot
- // more often (see FIXME comment there).
- const wchar_t* family = getFontFamilyForScript(description.dominantScript(), generic);
-
- if (family)
- return getCachedFontPlatformData(description, AtomicString(family, wcslen(family)));
// FIXME: Would be even better to somehow get the user's default font here.
// For now we'll pick the default that the user would get without changing
@@ -455,13 +447,6 @@ static LONG toGDIFontWeight(FontWeight fontWeight)
return gdiFontWeights[fontWeight];
}
-// FIXME: This may not be the best place to put this function
-AtomicString FontCache::getGenericFontForScript(UScriptCode script, const FontDescription& description)
-{
- const wchar_t* scriptFont = getFontFamilyForScript( script, description.genericFamily());
- return scriptFont ? AtomicString(scriptFont, wcslen(scriptFont)) : emptyAtom;
-}
-
static void FillLogFont(const FontDescription& fontDescription, LOGFONT* winfont)
{
// The size here looks unusual. The negative number is intentional.
diff --git a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
index 89433e1..797825e 100644
--- a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
+++ b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
@@ -46,6 +46,8 @@
#include "SkTypeface.h"
#include "SkUtils.h"
+#include <wtf/Assertions.h>
+
namespace WebCore {
void FontCache::platformInit()
@@ -79,9 +81,8 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font,
if (match) {
FcChar8* family;
if (FcPatternGetString(match, FC_FAMILY, 0, &family) == FcResultMatch) {
- FontPlatformData* fpd =
- createFontPlatformData(font.fontDescription(), AtomicString((char*) family));
- ret = new SimpleFontData(*fpd);
+ AtomicString fontFamily(reinterpret_cast<char*>(family));
+ ret = getCachedFontData(getCachedFontPlatformData(font.fontDescription(), fontFamily, false));
}
FcPatternDestroy(match);
}
@@ -98,8 +99,26 @@ FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& description)
{
- static AtomicString arialStr("Arial");
- return getCachedFontPlatformData(description, arialStr);
+ static const AtomicString sansStr("Sans");
+ static const AtomicString serifStr("Serif");
+ static const AtomicString monospaceStr("Monospace");
+
+ FontPlatformData* fontPlatformData = 0;
+ switch (description.genericFamily()) {
+ case FontDescription::SerifFamily:
+ fontPlatformData = getCachedFontPlatformData(description, serifStr);
+ break;
+ case FontDescription::MonospaceFamily:
+ fontPlatformData = getCachedFontPlatformData(description, monospaceStr);
+ break;
+ case FontDescription::SansSerifFamily:
+ default:
+ fontPlatformData = getCachedFontPlatformData(description, sansStr);
+ break;
+ }
+
+ ASSERT(fontPlatformData);
+ return fontPlatformData;
}
void FontCache::getTraitsInFamily(const AtomicString& familyName,
@@ -146,7 +165,13 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
if (fontDescription.italic())
style |= SkTypeface::kItalic;
+ // FIXME: This #ifdef can go away once we're firmly using the new Skia.
+ // During the transition, this makes the code compatible with both versions.
+#ifdef SK_USE_OLD_255_TO_256
+ SkTypeface* tf = SkTypeface::CreateFromName(name, static_cast<SkTypeface::Style>(style));
+#else
SkTypeface* tf = SkTypeface::Create(name, static_cast<SkTypeface::Style>(style));
+#endif
if (!tf)
return 0;
@@ -159,11 +184,4 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
return result;
}
-AtomicString FontCache::getGenericFontForScript(UScriptCode script,
- const FontDescription& descript)
-{
- notImplemented();
- return AtomicString();
-}
-
} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
index 1b71946..4710245 100644
--- a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
@@ -249,10 +249,28 @@ bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs,
// 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());
+
+ // If there is a non-blur shadow and both the fill color and shadow color
+ // are opaque, handle without skia.
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ if (m_graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor)) {
+ // If there is a shadow and this code is reached, windowsCanHandleDrawTextShadow()
+ // will have already returned true during the ctor initiatization of m_useGDI
+ ASSERT(shadowColor.alpha() == 255);
+ ASSERT(m_graphicsContext->fillColor().alpha() == 255);
+ ASSERT(shadowBlur == 0);
+ COLORREF textColor = skia::SkColorToCOLORREF(SkColorSetARGB(255, shadowColor.red(), shadowColor.green(), shadowColor.blue()));
+ COLORREF savedTextColor = GetTextColor(m_hdc);
+ SetTextColor(m_hdc, textColor);
+ ExtTextOut(m_hdc, x + shadowSize.width(), y + shadowSize.height(), ETO_GLYPH_INDEX, 0, reinterpret_cast<const wchar_t*>(&glyphs[0]), numGlyphs, &advances[0]);
+ SetTextColor(m_hdc, savedTextColor);
+ }
+
return !!ExtTextOut(m_hdc, x, y, ETO_GLYPH_INDEX, 0, reinterpret_cast<const wchar_t*>(&glyphs[0]), numGlyphs, &advances[0]);
}
-
class TransparencyAwareUniscribePainter : public TransparencyAwareFontPainter {
public:
TransparencyAwareUniscribePainter(GraphicsContext*,
@@ -305,6 +323,10 @@ IntRect TransparencyAwareUniscribePainter::estimateTextBounds()
UniscribeHelperTextRun state(m_run, *m_font);
int left = lroundf(m_point.x()) + state.characterToX(m_from);
int right = lroundf(m_point.x()) + state.characterToX(m_to);
+
+ // Adjust for RTL script since we just want to know the text bounds.
+ if (left > right)
+ std::swap(left, right);
// This algorithm for estimating how much extra space we need (the text may
// go outside the selection rect) is based roughly on
@@ -317,6 +339,11 @@ IntRect TransparencyAwareUniscribePainter::estimateTextBounds()
} // namespace
+bool Font::canReturnFallbackFontsForComplexText()
+{
+ return false;
+}
+
void Font::drawGlyphs(GraphicsContext* graphicsContext,
const SimpleFontData* font,
const GlyphBuffer& glyphBuffer,
@@ -416,6 +443,20 @@ void Font::drawComplexText(GraphicsContext* graphicsContext,
SetTextColor(hdc, skia::SkColorToCOLORREF(color));
SetBkMode(hdc, TRANSPARENT);
+ // If there is a non-blur shadow and both the fill color and shadow color
+ // are opaque, handle without skia.
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ if (graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor) && windowsCanHandleDrawTextShadow(graphicsContext)) {
+ COLORREF textColor = skia::SkColorToCOLORREF(SkColorSetARGB(255, shadowColor.red(), shadowColor.green(), shadowColor.blue()));
+ COLORREF savedTextColor = GetTextColor(hdc);
+ SetTextColor(hdc, textColor);
+ state.draw(graphicsContext, hdc, static_cast<int>(point.x()) + shadowSize.width(),
+ static_cast<int>(point.y() - ascent()) + shadowSize.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()),
@@ -424,7 +465,7 @@ void Font::drawComplexText(GraphicsContext* graphicsContext,
context->canvas()->endPlatformPaint();
}
-float Font::floatWidthForComplexText(const TextRun& run) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */) const
{
UniscribeHelperTextRun state(run, *this);
return static_cast<float>(state.width());
diff --git a/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp b/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp
index 1e923ac..e99c12a 100644
--- a/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp
@@ -116,7 +116,7 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b
// Streams the concatenation of a header and font data.
class EOTStream {
public:
- EOTStream(const Vector<uint8_t, 512>& eotHeader, const SharedBuffer* fontData, size_t overlayDst, size_t overlaySrc, size_t overlayLength)
+ EOTStream(const EOTHeader& eotHeader, const SharedBuffer* fontData, size_t overlayDst, size_t overlaySrc, size_t overlayLength)
: m_eotHeader(eotHeader)
, m_fontData(fontData)
, m_overlayDst(overlayDst)
@@ -130,7 +130,7 @@ public:
size_t read(void* buffer, size_t count);
private:
- const Vector<uint8_t, 512>& m_eotHeader;
+ const EOTHeader& m_eotHeader;
const SharedBuffer* m_fontData;
size_t m_overlayDst;
size_t m_overlaySrc;
@@ -200,7 +200,7 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
// TTLoadEmbeddedFont works only with Embedded OpenType (.eot) data,
// so we need to create an EOT header and prepend it to the font data.
- Vector<uint8_t, 512> eotHeader;
+ EOTHeader eotHeader;
size_t overlayDst;
size_t overlaySrc;
size_t overlayLength;
diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp
index 2b7c562..a952685 100644
--- a/WebCore/platform/graphics/chromium/FontLinux.cpp
+++ b/WebCore/platform/graphics/chromium/FontLinux.cpp
@@ -46,6 +46,11 @@
namespace WebCore {
+bool Font::canReturnFallbackFontsForComplexText()
+{
+ return false;
+}
+
void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
const GlyphBuffer& glyphBuffer, int from, int numGlyphs,
const FloatPoint& point) const {
@@ -111,7 +116,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run,
notImplemented();
}
-float Font::floatWidthForComplexText(const TextRun& run) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */) const
{
notImplemented();
return 0;
diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
index 7b7d197..e6a61f6 100644
--- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
+++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
@@ -95,6 +95,11 @@ void FontPlatformData::setupPaint(SkPaint* paint) const
paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
}
+SkFontID FontPlatformData::uniqueID() const
+{
+ return m_typeface->uniqueID();
+}
+
bool FontPlatformData::operator==(const FontPlatformData& a) const
{
// If either of the typeface pointers are invalid (either NULL or the
diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
index ec7d837..c63a860 100644
--- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
+++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
@@ -36,6 +36,7 @@
class SkPaint;
class SkTypeface;
+typedef uint32_t SkFontID;
namespace WebCore {
@@ -90,6 +91,12 @@ public:
// -------------------------------------------------------------------------
void setupPaint(SkPaint*) const;
+ // -------------------------------------------------------------------------
+ // Return Skia's unique id for this font. This encodes both the style and
+ // the font's file name so refers to a single face.
+ // -------------------------------------------------------------------------
+ SkFontID uniqueID() const;
+
unsigned hash() const;
float size() const { return m_textSize; }
diff --git a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
index ed326c8..9596a4c 100644
--- a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
@@ -120,6 +120,52 @@ void initializeScriptFontMap(ScriptToFontMap& scriptFontMap)
scriptFontMap[USCRIPT_HAN] = localeFamily;
}
+// There are a lot of characters in USCRIPT_COMMON that can be covered
+// by fonts for scripts closely related to them. See
+// http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:Script=Common:]
+// FIXME: make this more efficient with a wider coverage
+UScriptCode getScriptBasedOnUnicodeBlock(int ucs4)
+{
+ UBlockCode block = ublock_getCode(ucs4);
+ switch (block) {
+ case UBLOCK_CJK_SYMBOLS_AND_PUNCTUATION:
+ return USCRIPT_HAN;
+ case UBLOCK_HIRAGANA:
+ case UBLOCK_KATAKANA:
+ return USCRIPT_HIRAGANA;
+ case UBLOCK_ARABIC:
+ return USCRIPT_ARABIC;
+ case UBLOCK_THAI:
+ return USCRIPT_THAI;
+ case UBLOCK_GREEK:
+ return USCRIPT_GREEK;
+ case UBLOCK_DEVANAGARI:
+ // For Danda and Double Danda (U+0964, U+0965), use a Devanagari
+ // font for now although they're used by other scripts as well.
+ // Without a context, we can't do any better.
+ return USCRIPT_DEVANAGARI;
+ case UBLOCK_ARMENIAN:
+ return USCRIPT_ARMENIAN;
+ case UBLOCK_GEORGIAN:
+ return USCRIPT_GEORGIAN;
+ case UBLOCK_KANNADA:
+ return USCRIPT_KANNADA;
+ default:
+ return USCRIPT_COMMON;
+ }
+}
+
+UScriptCode getScript(int ucs4)
+{
+ UErrorCode err = U_ZERO_ERROR;
+ UScriptCode script = uscript_getScript(ucs4, &err);
+ // If script is invalid, common or inherited or there's an error,
+ // infer a script based on the unicode block of a character.
+ if (script <= USCRIPT_INHERITED || U_FAILURE(err))
+ script = getScriptBasedOnUnicodeBlock(ucs4);
+ return script;
+}
+
const int kUndefinedAscent = std::numeric_limits<int>::min();
// Given an HFONT, return the ascent. If GetTextMetrics fails,
@@ -209,11 +255,9 @@ const UChar* getFallbackFamily(const UChar* characters,
// to get a font required to render the string.
int i = 0;
UChar32 ucs4 = 0;
- while (i < length && script == USCRIPT_COMMON || script == USCRIPT_INVALID_CODE) {
+ while (i < length && script == USCRIPT_COMMON) {
U16_NEXT(characters, i, length, ucs4);
- UErrorCode err = U_ZERO_ERROR;
- script = uscript_getScript(ucs4, &err);
- // silently ignore the error
+ script = getScript(ucs4);
}
// For the full-width ASCII characters (U+FF00 - U+FF5E), use the font for
@@ -223,46 +267,8 @@ const UChar* getFallbackFamily(const UChar* characters,
if (0xFF00 < ucs4 && ucs4 < 0xFF5F)
script = USCRIPT_HAN;
- // There are a lot of characters in USCRIPT_COMMON that can be covered
- // by fonts for scripts closely related to them. See
- // http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:Script=Common:]
- // FIXME: make this more efficient with a wider coverage
- if (script == USCRIPT_COMMON || script == USCRIPT_INHERITED) {
- UBlockCode block = ublock_getCode(ucs4);
- switch (block) {
- case UBLOCK_BASIC_LATIN:
- script = USCRIPT_LATIN;
- break;
- case UBLOCK_CJK_SYMBOLS_AND_PUNCTUATION:
- script = USCRIPT_HAN;
- break;
- case UBLOCK_HIRAGANA:
- case UBLOCK_KATAKANA:
- script = USCRIPT_HIRAGANA;
- break;
- case UBLOCK_ARABIC:
- script = USCRIPT_ARABIC;
- break;
- case UBLOCK_GREEK:
- script = USCRIPT_GREEK;
- break;
- case UBLOCK_DEVANAGARI:
- // For Danda and Double Danda (U+0964, U+0965), use a Devanagari
- // font for now although they're used by other scripts as well.
- // Without a context, we can't do any better.
- script = USCRIPT_DEVANAGARI;
- break;
- case UBLOCK_ARMENIAN:
- script = USCRIPT_ARMENIAN;
- break;
- case UBLOCK_GEORGIAN:
- script = USCRIPT_GEORGIAN;
- break;
- case UBLOCK_KANNADA:
- script = USCRIPT_KANNADA;
- break;
- }
- }
+ if (script == USCRIPT_COMMON)
+ script = getScriptBasedOnUnicodeBlock(ucs4);
// Another lame work-around to cover non-BMP characters.
const UChar* family = getFontFamilyForScript(script, generic);
diff --git a/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp b/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp
index 31c5256..2cb1cc5 100644
--- a/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp
@@ -72,7 +72,7 @@ static bool fillBMPGlyphs(unsigned offset,
bool recurse)
{
HDC dc = GetDC((HWND)0);
- HGDIOBJ oldFont = SelectObject(dc, fontData->m_font.hfont());
+ HGDIOBJ oldFont = SelectObject(dc, fontData->platformData().hfont());
TEXTMETRIC tm = {0};
if (!GetTextMetrics(dc, &tm)) {
@@ -80,7 +80,7 @@ static bool fillBMPGlyphs(unsigned offset,
ReleaseDC(0, dc);
if (recurse) {
- if (ChromiumBridge::ensureFontLoaded(fontData->m_font.hfont()))
+ if (ChromiumBridge::ensureFontLoaded(fontData->platformData().hfont()))
return fillBMPGlyphs(offset, length, buffer, page, fontData, false);
else {
fillEmptyGlyphs(page);
@@ -191,9 +191,9 @@ static bool fillNonBMPGlyphs(unsigned offset,
bool haveGlyphs = false;
UniscribeHelperTextRun state(buffer, length * 2, false,
- fontData->m_font.hfont(),
- fontData->m_font.scriptCache(),
- fontData->m_font.scriptFontProperties());
+ fontData->platformData().hfont(),
+ fontData->platformData().scriptCache(),
+ fontData->platformData().scriptFontProperties());
state.setInhibitLigate(true);
state.setDisableFontFallback(true);
state.init();
diff --git a/WebCore/platform/graphics/chromium/MediaPlayerPrivateChromium.h b/WebCore/platform/graphics/chromium/MediaPlayerPrivateChromium.h
index e8ba0ad..534244d 100644
--- a/WebCore/platform/graphics/chromium/MediaPlayerPrivateChromium.h
+++ b/WebCore/platform/graphics/chromium/MediaPlayerPrivateChromium.h
@@ -37,67 +37,12 @@
namespace WebCore {
-class MediaPlayerPrivate : public MediaPlayerPrivateInterface {
+class MediaPlayerPrivate {
public:
static void registerMediaEngine(MediaEngineRegistrar);
- ~MediaPlayerPrivate();
-
- IntSize naturalSize() const;
- bool hasVideo() const;
-
- void load(const String& url);
- void cancelLoad();
-
- void play();
- void pause();
-
- bool paused() const;
- bool seeking() const;
-
- float duration() const;
- float currentTime() const;
- void seek(float time);
- void setEndTime(float);
-
- void setRate(float);
- void setVolume(float);
-
- int dataRate() const;
-
- MediaPlayer::NetworkState networkState() const;
- MediaPlayer::ReadyState readyState() const;
-
- float maxTimeBuffered() const;
- float maxTimeSeekable() const;
- unsigned bytesLoaded() const;
- bool totalBytesKnown() const;
- unsigned totalBytes() const;
-
- void setVisible(bool);
- void setSize(const IntSize&);
-
- void paint(GraphicsContext*, const IntRect&);
-
- // Public methods to be called by WebMediaPlayer
- FrameView* frameView();
- void networkStateChanged();
- void readyStateChanged();
- void timeChanged();
- void volumeChanged();
- void repaint();
-
-private:
- MediaPlayerPrivate(MediaPlayer*);
- static MediaPlayerPrivateInterface* create(MediaPlayer* player);
- static void getSupportedTypes(HashSet<String>&);
- static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs);
- static bool isAvailable();
-
- MediaPlayer* m_player;
- void* m_data;
};
-} // namespace WebCore
+} // namespace WebCore
#endif
diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
index 06e997f..6f5ce90 100644
--- a/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
@@ -54,11 +54,11 @@ static inline float scaleEmToUnits(float x, int unitsPerEm)
void SimpleFontData::platformInit()
{
HDC dc = GetDC(0);
- HGDIOBJ oldFont = SelectObject(dc, m_font.hfont());
+ HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
TEXTMETRIC textMetric = {0};
if (!GetTextMetrics(dc, &textMetric)) {
- if (ChromiumBridge::ensureFontLoaded(m_font.hfont())) {
+ if (ChromiumBridge::ensureFontLoaded(m_platformData.hfont())) {
// Retry GetTextMetrics.
// FIXME: Handle gracefully the error if this call also fails.
// See http://crbug.com/6401.
@@ -91,6 +91,11 @@ void SimpleFontData::platformInit()
ReleaseDC(0, dc);
}
+void SimpleFontData::platformCharWidthInit()
+{
+ // charwidths are set in platformInit.
+}
+
void SimpleFontData::platformDestroy()
{
// We don't hash this on Win32, so it's effectively owned by us.
@@ -102,7 +107,7 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes
{
if (!m_smallCapsFontData) {
LOGFONT winFont;
- GetObject(m_font.hfont(), sizeof(LOGFONT), &winFont);
+ GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winFont);
float smallCapsSize = 0.70f * fontDescription.computedSize();
// Unlike WebKit trunk, we don't multiply the size by 32. That seems
// to be some kind of artifact of their CG backend, or something.
@@ -125,13 +130,13 @@ void SimpleFontData::determinePitch()
{
// TEXTMETRICS have this. Set m_treatAsFixedPitch based off that.
HDC dc = GetDC(0);
- HGDIOBJ oldFont = SelectObject(dc, m_font.hfont());
+ HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
// Yes, this looks backwards, but the fixed pitch bit is actually set if the font
// is *not* fixed pitch. Unbelievable but true.
TEXTMETRIC textMetric = {0};
if (!GetTextMetrics(dc, &textMetric)) {
- if (ChromiumBridge::ensureFontLoaded(m_font.hfont())) {
+ if (ChromiumBridge::ensureFontLoaded(m_platformData.hfont())) {
// Retry GetTextMetrics.
// FIXME: Handle gracefully the error if this call also fails.
// See http://crbug.com/6401.
@@ -149,12 +154,12 @@ void SimpleFontData::determinePitch()
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
HDC dc = GetDC(0);
- HGDIOBJ oldFont = SelectObject(dc, m_font.hfont());
+ HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
int width = 0;
if (!GetCharWidthI(dc, glyph, 1, 0, &width)) {
// Ask the browser to preload the font and retry.
- if (ChromiumBridge::ensureFontLoaded(m_font.hfont())) {
+ if (ChromiumBridge::ensureFontLoaded(m_platformData.hfont())) {
// FIXME: Handle gracefully the error if this call also fails.
// See http://crbug.com/6401.
if (!GetCharWidthI(dc, glyph, 1, 0, &width))
diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
index 8200175..3bff83f 100644
--- a/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
+++ b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
@@ -36,33 +36,54 @@
#include "FloatRect.h"
#include "FontDescription.h"
#include "Logging.h"
-#include "NotImplemented.h"
+#include "VDMXParser.h"
+#include "SkFontHost.h"
#include "SkPaint.h"
-#include "SkTypeface.h"
#include "SkTime.h"
+#include "SkTypeface.h"
+#include "SkTypes.h"
namespace WebCore {
// Smallcaps versions of fonts are 70% the size of the normal font.
static const float smallCapsFraction = 0.7f;
+// This is the largest VDMX table which we'll try to load and parse.
+static const size_t maxVDMXTableSize = 1024 * 1024; // 1 MB
void SimpleFontData::platformInit()
{
SkPaint paint;
SkPaint::FontMetrics metrics;
- m_font.setupPaint(&paint);
+ m_platformData.setupPaint(&paint);
paint.getFontMetrics(&metrics);
+ const SkFontID fontID = m_platformData.uniqueID();
+
+ static const uint32_t vdmxTag = SkSetFourByteTag('V', 'D', 'M', 'X');
+ int pixelSize = m_platformData.size() + 0.5;
+ int vdmxAscent, vdmxDescent;
+ bool isVDMXValid = false;
+
+ size_t vdmxSize = SkFontHost::GetTableSize(fontID, vdmxTag);
+ if (vdmxSize && vdmxSize < maxVDMXTableSize) {
+ uint8_t* vdmxTable = (uint8_t*) fastMalloc(vdmxSize);
+ if (vdmxTable
+ && SkFontHost::GetTableData(fontID, vdmxTag, 0, vdmxSize, vdmxTable) == vdmxSize
+ && parseVDMX(&vdmxAscent, &vdmxDescent, vdmxTable, vdmxSize, pixelSize))
+ isVDMXValid = true;
+ fastFree(vdmxTable);
+ }
// Beware those who step here: This code is designed to match Win32 font
// metrics *exactly*.
- if (metrics.fVDMXMetricsValid) {
- m_ascent = metrics.fVDMXAscent;
- m_descent = metrics.fVDMXDescent;
+ if (isVDMXValid) {
+ m_ascent = vdmxAscent;
+ m_descent = -vdmxDescent;
} else {
+ SkScalar height = -metrics.fAscent + metrics.fDescent + metrics.fLeading;
m_ascent = SkScalarRound(-metrics.fAscent);
- m_descent = SkScalarRound(metrics.fHeight) - m_ascent;
+ m_descent = SkScalarRound(height) - m_ascent;
}
if (metrics.fXHeight)
@@ -79,7 +100,8 @@ void SimpleFontData::platformInit()
// calculated for us, but we need to calculate m_maxCharWidth and
// m_avgCharWidth in order for text entry widgets to be sized correctly.
- m_maxCharWidth = SkScalarRound(metrics.fXRange * SkScalarRound(m_font.size()));
+ SkScalar xRange = metrics.fXMax - metrics.fXMin;
+ m_maxCharWidth = SkScalarRound(xRange * SkScalarRound(m_platformData.size()));
if (metrics.fAvgCharWidth)
m_avgCharWidth = SkScalarRound(metrics.fAvgCharWidth);
@@ -98,6 +120,11 @@ void SimpleFontData::platformInit()
}
}
+void SimpleFontData::platformCharWidthInit()
+{
+ // charwidths are set in platformInit.
+}
+
void SimpleFontData::platformDestroy()
{
delete m_smallCapsFontData;
@@ -108,7 +135,7 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes
{
if (!m_smallCapsFontData) {
const float smallCapsSize = lroundf(fontDescription.computedSize() * smallCapsFraction);
- m_smallCapsFontData = new SimpleFontData(FontPlatformData(m_font, smallCapsSize));
+ m_smallCapsFontData = new SimpleFontData(FontPlatformData(m_platformData, smallCapsSize));
}
return m_smallCapsFontData;
@@ -120,7 +147,7 @@ bool SimpleFontData::containsCharacters(const UChar* characters, int length) con
static const unsigned maxBufferCount = 64;
uint16_t glyphs[maxBufferCount];
- m_font.setupPaint(&paint);
+ m_platformData.setupPaint(&paint);
paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
while (length > 0) {
@@ -151,11 +178,11 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
SkPaint paint;
- m_font.setupPaint(&paint);
+ m_platformData.setupPaint(&paint);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
SkScalar width = paint.measureText(&glyph, 2);
-
+
return SkScalarToFloat(width);
}
diff --git a/WebCore/platform/graphics/chromium/TransparencyWin.cpp b/WebCore/platform/graphics/chromium/TransparencyWin.cpp
index 8c790af..d3ced81 100644
--- a/WebCore/platform/graphics/chromium/TransparencyWin.cpp
+++ b/WebCore/platform/graphics/chromium/TransparencyWin.cpp
@@ -109,7 +109,7 @@ class TransparencyWin::OwnedBuffers {
public:
OwnedBuffers(const IntSize& size, bool needReferenceBuffer)
{
- m_destBitmap.adopt(ImageBuffer::create(size, false));
+ m_destBitmap = ImageBuffer::create(size, false);
if (needReferenceBuffer) {
m_referenceBitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
diff --git a/WebCore/platform/graphics/chromium/VDMXParser.cpp b/WebCore/platform/graphics/chromium/VDMXParser.cpp
new file mode 100644
index 0000000..3347226
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/VDMXParser.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+// For htons/ntohs
+#include <arpa/inet.h>
+
+// Buffer helper class
+//
+// This class perform some trival buffer operations while checking for
+// out-of-bounds errors. As a family they return false if anything is amiss,
+// updating the current offset otherwise.
+class Buffer {
+public:
+ Buffer(const uint8_t* buffer, size_t length)
+ : m_buffer(buffer)
+ , m_length(length)
+ , m_offset(0) { }
+
+ bool skip(size_t numBytes)
+ {
+ if (m_offset + numBytes > m_length)
+ return false;
+ m_offset += numBytes;
+ return true;
+ }
+
+ bool readU8(uint8_t* value)
+ {
+ if (m_offset + sizeof(uint8_t) > m_length)
+ return false;
+ *value = m_buffer[m_offset];
+ m_offset += sizeof(uint8_t);
+ return true;
+ }
+
+ bool readU16(uint16_t* value)
+ {
+ if (m_offset + sizeof(uint16_t) > m_length)
+ return false;
+ memcpy(value, m_buffer + m_offset, sizeof(uint16_t));
+ *value = ntohs(*value);
+ m_offset += sizeof(uint16_t);
+ return true;
+ }
+
+ bool readS16(int16_t* value)
+ {
+ return readU16(reinterpret_cast<uint16_t*>(value));
+ }
+
+ size_t offset() const
+ {
+ return m_offset;
+ }
+
+ void setOffset(size_t newoffset)
+ {
+ m_offset = newoffset;
+ }
+
+private:
+ const uint8_t *const m_buffer;
+ const size_t m_length;
+ size_t m_offset;
+};
+
+// VDMX parsing code.
+//
+// VDMX tables are found in some TrueType/OpenType fonts and contain
+// ascender/descender overrides for certain (usually small) sizes. This is
+// needed in order to match font metrics on Windows.
+//
+// Freetype does not parse these tables so we do so here.
+
+namespace WebCore {
+
+// Parse a TrueType VDMX table.
+// yMax: (output) the ascender value from the table
+// yMin: (output) the descender value from the table (negative!)
+// vdmx: the table bytes
+// vdmxLength: length of @vdmx, in bytes
+// targetPixelSize: the pixel size of the font (e.g. 16)
+//
+// Returns true iff a suitable match are found. Otherwise, *yMax and *yMin are
+// untouched. size_t must be 32-bits to avoid overflow.
+//
+// See http://www.microsoft.com/opentype/otspec/vdmx.htm
+bool parseVDMX(int* yMax, int* yMin,
+ const uint8_t* vdmx, size_t vdmxLength,
+ unsigned targetPixelSize)
+{
+ Buffer buf(vdmx, vdmxLength);
+
+ // We ignore the version. Future tables should be backwards compatible with
+ // this layout.
+ uint16_t numRatios;
+ if (!buf.skip(4) || !buf.readU16(&numRatios))
+ return false;
+
+ // Now we have two tables. Firstly we have @numRatios Ratio records, then a
+ // matching array of @numRatios offsets. We save the offset of the beginning
+ // of this second table.
+ //
+ // Range 6 <= x <= 262146
+ unsigned long offsetTableOffset =
+ buf.offset() + 4 /* sizeof struct ratio */ * numRatios;
+
+ unsigned desiredRatio = 0xffffffff;
+ // We read 4 bytes per record, so the offset range is
+ // 6 <= x <= 524286
+ for (unsigned i = 0; i < numRatios; ++i) {
+ uint8_t xRatio, yRatio1, yRatio2;
+
+ if (!buf.skip(1)
+ || !buf.readU8(&xRatio)
+ || !buf.readU8(&yRatio1)
+ || !buf.readU8(&yRatio2))
+ return false;
+
+ // This either covers 1:1, or this is the default entry (0, 0, 0)
+ if ((xRatio == 1 && yRatio1 <= 1 && yRatio2 >= 1)
+ || (xRatio == 0 && yRatio1 == 0 && yRatio2 == 0)) {
+ desiredRatio = i;
+ break;
+ }
+ }
+
+ if (desiredRatio == 0xffffffff) // no ratio found
+ return false;
+
+ // Range 10 <= x <= 393216
+ buf.setOffset(offsetTableOffset + sizeof(uint16_t) * desiredRatio);
+
+ // Now we read from the offset table to get the offset of another array
+ uint16_t groupOffset;
+ if (!buf.readU16(&groupOffset))
+ return false;
+ // Range 0 <= x <= 65535
+ buf.setOffset(groupOffset);
+
+ uint16_t numRecords;
+ if (!buf.readU16(&numRecords) || !buf.skip(sizeof(uint16_t)))
+ return false;
+
+ // We read 6 bytes per record, so the offset range is
+ // 4 <= x <= 458749
+ for (unsigned i = 0; i < numRecords; ++i) {
+ uint16_t pixelSize;
+ if (!buf.readU16(&pixelSize))
+ return false;
+ // the entries are sorted, so we can abort early if need be
+ if (pixelSize > targetPixelSize)
+ return false;
+
+ if (pixelSize == targetPixelSize) {
+ int16_t tempYMax, tempYMin;
+ if (!buf.readS16(&tempYMax)
+ || !buf.readS16(&tempYMin))
+ return false;
+ *yMin = tempYMin;
+ *yMax = tempYMax;
+ return true;
+ }
+ if (!buf.skip(2 * sizeof(int16_t)))
+ return false;
+ }
+
+ return false;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/KeyboardCodes.h b/WebCore/platform/graphics/chromium/VDMXParser.h
index 10eb0cd..ef625b7 100644
--- a/WebCore/platform/chromium/KeyboardCodes.h
+++ b/WebCore/platform/graphics/chromium/VDMXParser.h
@@ -1,10 +1,10 @@
/*
- * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
- *
+ * Copyright (c) 2009, Google Inc. All rights reserved.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
@@ -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,13 +28,13 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef KeyboardCodes_h
-#define KeyboardCodes_h
+#ifndef VDMXParser_h
+#define VDMXParser_h
-#if PLATFORM(WIN_OS)
-#include "KeyboardCodesWin.h"
-#else
-#include "KeyboardCodesPosix.h"
-#endif
+namespace WebCore {
+ bool parseVDMX(int* ymax, int* ymin,
+ const uint8_t* vdmx, size_t vdmxLength,
+ unsigned targetPixelSize);
+} // namespace WebCore
#endif
diff --git a/WebCore/platform/graphics/filters/FEBlend.cpp b/WebCore/platform/graphics/filters/FEBlend.cpp
index 7210367..86b702f 100644
--- a/WebCore/platform/graphics/filters/FEBlend.cpp
+++ b/WebCore/platform/graphics/filters/FEBlend.cpp
@@ -21,9 +21,11 @@
#include "config.h"
-#if ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#if ENABLE(FILTERS)
#include "FEBlend.h"
+#include "Filter.h"
+
namespace WebCore {
FEBlend::FEBlend(FilterEffect* in, FilterEffect* in2, BlendModeType mode)
@@ -59,7 +61,7 @@ void FEBlend::setBlendMode(BlendModeType mode)
m_mode = mode;
}
-void FEBlend::apply()
+void FEBlend::apply(Filter*)
{
}
@@ -69,4 +71,4 @@ void FEBlend::dump()
} // namespace WebCore
-#endif // ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#endif // ENABLE(FILTERS)
diff --git a/WebCore/platform/graphics/filters/FEBlend.h b/WebCore/platform/graphics/filters/FEBlend.h
index b2835e8..dec04ac 100644
--- a/WebCore/platform/graphics/filters/FEBlend.h
+++ b/WebCore/platform/graphics/filters/FEBlend.h
@@ -22,9 +22,11 @@
#ifndef SVGFEBlend_h
#define SVGFEBlend_h
-#if ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#if ENABLE(FILTERS)
#include "FilterEffect.h"
+#include "Filter.h"
+
namespace WebCore {
enum BlendModeType {
@@ -46,8 +48,8 @@ namespace WebCore {
BlendModeType blendMode() const;
void setBlendMode(BlendModeType);
- virtual void apply();
- virtual void dump();
+ void apply(Filter*);
+ void dump();
private:
FEBlend(FilterEffect*, FilterEffect*, BlendModeType);
@@ -59,6 +61,6 @@ namespace WebCore {
} // namespace WebCore
-#endif // ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#endif // ENABLE(FILTERS)
#endif // SVGFEBlend_h
diff --git a/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
index f783106..8704e64 100644
--- a/WebCore/platform/graphics/filters/FEColorMatrix.cpp
+++ b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
@@ -21,9 +21,11 @@
#include "config.h"
-#if ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#if ENABLE(FILTERS)
#include "FEColorMatrix.h"
+#include "Filter.h"
+
namespace WebCore {
FEColorMatrix::FEColorMatrix(FilterEffect* in, ColorMatrixType type, const Vector<float>& values)
@@ -59,7 +61,7 @@ void FEColorMatrix::setValues(const Vector<float> &values)
m_values = values;
}
-void FEColorMatrix::apply()
+void FEColorMatrix::apply(Filter*)
{
}
@@ -69,4 +71,4 @@ void FEColorMatrix::dump()
} // namespace WebCore
-#endif // ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#endif // ENABLE(FILTERS)
diff --git a/WebCore/platform/graphics/filters/FEColorMatrix.h b/WebCore/platform/graphics/filters/FEColorMatrix.h
index d8193ed..eeb3557 100644
--- a/WebCore/platform/graphics/filters/FEColorMatrix.h
+++ b/WebCore/platform/graphics/filters/FEColorMatrix.h
@@ -22,8 +22,10 @@
#ifndef SVGFEColorMatrix_h
#define SVGFEColorMatrix_h
-#if ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#if ENABLE(FILTERS)
#include "FilterEffect.h"
+
+#include "Filter.h"
#include <wtf/Vector.h>
namespace WebCore {
@@ -46,8 +48,8 @@ namespace WebCore {
const Vector<float>& values() const;
void setValues(const Vector<float>&);
- virtual void apply();
- virtual void dump();
+ void apply(Filter*);
+ void dump();
private:
FEColorMatrix(FilterEffect*, ColorMatrixType, const Vector<float>&);
@@ -59,6 +61,6 @@ namespace WebCore {
} // namespace WebCore
-#endif // ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#endif // ENABLE(FILTERS)
#endif // SVGFEColorMatrix_h
diff --git a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
index 708ea3e..54ac123 100644
--- a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
+++ b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
@@ -21,9 +21,11 @@
#include "config.h"
-#if ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#if ENABLE(FILTERS)
#include "FEComponentTransfer.h"
+#include "Filter.h"
+
namespace WebCore {
FEComponentTransfer::FEComponentTransfer(FilterEffect* in, const ComponentTransferFunction& redFunc,
@@ -83,7 +85,7 @@ void FEComponentTransfer::setAlphaFunction(const ComponentTransferFunction& func
m_alphaFunc = func;
}
-void FEComponentTransfer::apply()
+void FEComponentTransfer::apply(Filter*)
{
}
@@ -93,4 +95,4 @@ void FEComponentTransfer::dump()
} // namespace WebCore
-#endif // ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#endif // ENABLE(FILTERS)
diff --git a/WebCore/platform/graphics/filters/FEComponentTransfer.h b/WebCore/platform/graphics/filters/FEComponentTransfer.h
index 20d70c0..cc1d1f8 100644
--- a/WebCore/platform/graphics/filters/FEComponentTransfer.h
+++ b/WebCore/platform/graphics/filters/FEComponentTransfer.h
@@ -22,10 +22,11 @@
#ifndef SVGFEComponentTransfer_h
#define SVGFEComponentTransfer_h
-#if ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#if ENABLE(FILTERS)
#include "FilterEffect.h"
-#include "SVGFEDisplacementMap.h"
+#include "SVGFEDisplacementMap.h"
+#include "Filter.h"
#include <wtf/Vector.h>
namespace WebCore {
@@ -78,8 +79,8 @@ namespace WebCore {
ComponentTransferFunction alphaFunction() const;
void setAlphaFunction(const ComponentTransferFunction&);
- virtual void apply();
- virtual void dump();
+ void apply(Filter*);
+ void dump();
private:
FEComponentTransfer(FilterEffect*,const ComponentTransferFunction&, const ComponentTransferFunction&,
@@ -94,6 +95,6 @@ namespace WebCore {
} // namespace WebCore
-#endif // ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#endif // ENABLE(FILTERS)
#endif // SVGFEComponentTransfer_h
diff --git a/WebCore/platform/graphics/filters/FEComposite.cpp b/WebCore/platform/graphics/filters/FEComposite.cpp
index 0b5ce94..0706358 100644
--- a/WebCore/platform/graphics/filters/FEComposite.cpp
+++ b/WebCore/platform/graphics/filters/FEComposite.cpp
@@ -21,9 +21,11 @@
#include "config.h"
-#if ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#if ENABLE(FILTERS)
#include "FEComposite.h"
+#include "Filter.h"
+
namespace WebCore {
FEComposite::FEComposite(FilterEffect* in, FilterEffect* in2, const CompositeOperationType& type,
@@ -95,7 +97,7 @@ void FEComposite::setK4(float k4)
m_k4 = k4;
}
-void FEComposite::apply()
+void FEComposite::apply(Filter*)
{
}
@@ -105,4 +107,4 @@ void FEComposite::dump()
} // namespace WebCore
-#endif // ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#endif // ENABLE(FILTERS)
diff --git a/WebCore/platform/graphics/filters/FEComposite.h b/WebCore/platform/graphics/filters/FEComposite.h
index d205395..b623cce 100644
--- a/WebCore/platform/graphics/filters/FEComposite.h
+++ b/WebCore/platform/graphics/filters/FEComposite.h
@@ -22,9 +22,11 @@
#ifndef SVGFEComposite_h
#define SVGFEComposite_h
-#if ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#if ENABLE(FILTERS)
#include "FilterEffect.h"
+
#include "PlatformString.h"
+#include "Filter.h"
namespace WebCore {
@@ -58,8 +60,8 @@ namespace WebCore {
float k4() const;
void setK4(float);
- virtual void apply();
- virtual void dump();
+ void apply(Filter*);
+ void dump();
private:
FEComposite(FilterEffect*, FilterEffect*, const CompositeOperationType&,
@@ -76,6 +78,6 @@ namespace WebCore {
} // namespace WebCore
-#endif // ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#endif // ENABLE(FILTERS)
#endif // SVGFEComposite_h
diff --git a/WebCore/platform/graphics/filters/Filter.h b/WebCore/platform/graphics/filters/Filter.h
new file mode 100644
index 0000000..84909da
--- /dev/null
+++ b/WebCore/platform/graphics/filters/Filter.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * aint 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 Filter_h
+#define Filter_h
+
+#if ENABLE(FILTERS)
+#include "Image.h"
+#include "StringHash.h"
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+ class FilterEffect;
+
+ class Filter : public RefCounted<Filter> {
+ public:
+ virtual ~Filter() { }
+
+ void setSourceImage(PassRefPtr<Image> image) { m_image = image; }
+ Image* sourceImage() { return m_image.get(); }
+
+ virtual void calculateEffectSubRegion(FilterEffect*) = 0;
+
+ private:
+ RefPtr<Image> m_image;
+ };
+
+} // namespace WebCore
+
+#endif // ENABLE(FILTERS)
+
+#endif // Filter_h
diff --git a/WebCore/platform/graphics/filters/FilterEffect.cpp b/WebCore/platform/graphics/filters/FilterEffect.cpp
new file mode 100644
index 0000000..cd74992
--- /dev/null
+++ b/WebCore/platform/graphics/filters/FilterEffect.cpp
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) Alex Mathews <possessedpenguinbob@gmail.com>
+
+ 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
+ aint with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#if ENABLE(FILTERS)
+#include "FilterEffect.h"
+
+namespace WebCore {
+
+FilterEffect::FilterEffect()
+ : m_xBBoxMode(false)
+ , m_yBBoxMode(false)
+ , m_widthBBoxMode(false)
+ , m_heightBBoxMode(false)
+{
+}
+
+FilterEffect::~FilterEffect()
+{
+}
+
+TextStream& FilterEffect::externalRepresentation(TextStream& ts) const
+{
+ return ts;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(FILTERS)
diff --git a/WebCore/platform/graphics/filters/FilterEffect.h b/WebCore/platform/graphics/filters/FilterEffect.h
new file mode 100644
index 0000000..e2a058d
--- /dev/null
+++ b/WebCore/platform/graphics/filters/FilterEffect.h
@@ -0,0 +1,81 @@
+/*
+ Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com>
+ 2009 Dirk Schulze <krit@webkit.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ aint 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 FilterEffect_h
+#define FilterEffect_h
+
+#if ENABLE(FILTERS)
+#include "Filter.h"
+#include "FloatRect.h"
+#include "ImageBuffer.h"
+#include "TextStream.h"
+
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+ class FilterEffect : public RefCounted<FilterEffect> {
+ public:
+ virtual ~FilterEffect();
+
+ bool xBoundingBoxMode() const { return m_xBBoxMode; }
+ void setXBoundingBoxMode(bool bboxMode) { m_xBBoxMode = bboxMode; }
+
+ bool yBoundingBoxMode() const { return m_yBBoxMode; }
+ void setYBoundingBoxMode(bool bboxMode) { m_yBBoxMode = bboxMode; }
+
+ bool widthBoundingBoxMode() const { return m_widthBBoxMode; }
+ void setWidthBoundingBoxMode(bool bboxMode) { m_widthBBoxMode = bboxMode; }
+
+ bool heightBoundingBoxMode() const { return m_heightBBoxMode; }
+ void setHeightBoundingBoxMode(bool bboxMode) { m_heightBBoxMode = bboxMode; }
+
+ FloatRect subRegion() const { return m_subRegion; }
+ void setSubRegion(const FloatRect& subRegion) { m_subRegion = subRegion; }
+
+ // The result is bounded by the size of the filter primitive to save resources
+ ImageBuffer* resultImage() { return m_effectBuffer.get(); }
+ void setEffectBuffer(ImageBuffer* effectBuffer) { m_effectBuffer.set(effectBuffer); }
+
+ virtual void apply(Filter*) = 0;
+ virtual void dump() = 0;
+
+ virtual TextStream& externalRepresentation(TextStream&) const;
+ protected:
+ FilterEffect();
+
+ private:
+
+ bool m_xBBoxMode : 1;
+ bool m_yBBoxMode : 1;
+ bool m_widthBBoxMode : 1;
+ bool m_heightBBoxMode : 1;
+
+ FloatRect m_subRegion;
+
+ mutable OwnPtr<ImageBuffer> m_effectBuffer;
+ };
+
+} // namespace WebCore
+
+#endif // ENABLE(FILTERS)
+
+#endif // FilterEffect_h
diff --git a/WebCore/platform/graphics/filters/SourceAlpha.cpp b/WebCore/platform/graphics/filters/SourceAlpha.cpp
new file mode 100644
index 0000000..646a57b
--- /dev/null
+++ b/WebCore/platform/graphics/filters/SourceAlpha.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * aint with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#if ENABLE(FILTERS)
+#include "SourceAlpha.h"
+
+#include "GraphicsContext.h"
+#include "PlatformString.h"
+#include "Filter.h"
+
+#include <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+PassRefPtr<SourceAlpha> SourceAlpha::create()
+{
+ return adoptRef(new SourceAlpha);
+}
+
+const AtomicString& SourceAlpha::effectName()
+{
+ DEFINE_STATIC_LOCAL(const AtomicString, s_effectName, ("SourceAlpha"));
+ return s_effectName;
+}
+
+void SourceAlpha::apply(Filter*)
+{
+}
+
+void SourceAlpha::dump()
+{
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(FILTERS)
diff --git a/WebCore/platform/graphics/filters/SourceAlpha.h b/WebCore/platform/graphics/filters/SourceAlpha.h
new file mode 100644
index 0000000..21497aa
--- /dev/null
+++ b/WebCore/platform/graphics/filters/SourceAlpha.h
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ aint 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 SourceAlpha_h
+#define SourceAlpha_h
+
+#if ENABLE(FILTERS)
+#include "FilterEffect.h"
+
+#include "PlatformString.h"
+#include "Filter.h"
+
+namespace WebCore {
+
+ class SourceAlpha : public FilterEffect {
+ public:
+ static PassRefPtr<SourceAlpha> create();
+
+ static const AtomicString& effectName();
+
+ void apply(Filter*);
+ void dump();
+
+ private:
+ SourceAlpha() { }
+ };
+} //namespace WebCore
+
+#endif // ENABLE(FILTERS)
+
+#endif // SourceAlpha_h
diff --git a/WebCore/platform/graphics/filters/SourceGraphic.cpp b/WebCore/platform/graphics/filters/SourceGraphic.cpp
new file mode 100644
index 0000000..39d4810
--- /dev/null
+++ b/WebCore/platform/graphics/filters/SourceGraphic.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * aint with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#if ENABLE(FILTERS)
+#include "SourceGraphic.h"
+
+#include "GraphicsContext.h"
+#include "PlatformString.h"
+#include "Filter.h"
+
+#include <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+PassRefPtr<SourceGraphic> SourceGraphic::create()
+{
+ return adoptRef(new SourceGraphic);
+}
+
+const AtomicString& SourceGraphic::effectName()
+{
+ DEFINE_STATIC_LOCAL(const AtomicString, s_effectName, ("SourceGraphic"));
+ return s_effectName;
+}
+
+void SourceGraphic::apply(Filter*)
+{
+}
+
+void SourceGraphic::dump()
+{
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(FILTERS)
diff --git a/WebCore/platform/graphics/filters/SourceGraphic.h b/WebCore/platform/graphics/filters/SourceGraphic.h
new file mode 100644
index 0000000..363fb97
--- /dev/null
+++ b/WebCore/platform/graphics/filters/SourceGraphic.h
@@ -0,0 +1,48 @@
+/*
+ Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com>
+ 2009 Dirk Schulze <krit@webkit.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ aint 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 SourceGraphic_h
+#define SourceGrahpic_h
+
+#if ENABLE(FILTERS)
+#include "FilterEffect.h"
+
+#include "PlatformString.h"
+#include "Filter.h"
+
+namespace WebCore {
+
+ class SourceGraphic : public FilterEffect {
+ public:
+ static PassRefPtr<SourceGraphic> create();
+
+ static const AtomicString& effectName();
+
+ void apply(Filter*);
+ void dump();
+
+ private:
+ SourceGraphic() { }
+ };
+} //namespace WebCore
+
+#endif // ENABLE(FILTERS)
+
+#endif // SourceGraphic_h
diff --git a/WebCore/platform/graphics/gtk/FontCacheGtk.cpp b/WebCore/platform/graphics/gtk/FontCacheGtk.cpp
index d2b43cc..e0b88da 100644
--- a/WebCore/platform/graphics/gtk/FontCacheGtk.cpp
+++ b/WebCore/platform/graphics/gtk/FontCacheGtk.cpp
@@ -37,7 +37,7 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons
{
#if defined(USE_FREETYPE)
FcResult fresult;
- FontPlatformData* prim = const_cast<FontPlatformData*>(&font.primaryFont()->m_font);
+ FontPlatformData* prim = const_cast<FontPlatformData*>(&font.primaryFont()->platformData());
if (!prim->m_fallbacks)
prim->m_fallbacks = FcFontSort(NULL, prim->m_pattern, FcTrue, NULL, &fresult);
diff --git a/WebCore/platform/graphics/gtk/FontGtk.cpp b/WebCore/platform/graphics/gtk/FontGtk.cpp
index 288ba91..6561f02 100644
--- a/WebCore/platform/graphics/gtk/FontGtk.cpp
+++ b/WebCore/platform/graphics/gtk/FontGtk.cpp
@@ -34,7 +34,6 @@
#include "Font.h"
#include "GraphicsContext.h"
-#include "NotImplemented.h"
#include "SimpleFontData.h"
#include <cairo.h>
@@ -145,14 +144,14 @@ static gchar* convertUniCharToUTF8(const UChar* characters, gint length, int fro
static void setPangoAttributes(const Font* font, const TextRun& run, PangoLayout* layout)
{
#if defined(USE_FREETYPE)
- if (font->primaryFont()->m_font.m_pattern) {
- PangoFontDescription* desc = pango_fc_font_description_from_pattern(font->primaryFont()->m_font.m_pattern, FALSE);
+ if (font->primaryFont()->platformData().m_pattern) {
+ PangoFontDescription* desc = pango_fc_font_description_from_pattern(font->primaryFont()->platformData().m_pattern, FALSE);
pango_layout_set_font_description(layout, desc);
pango_font_description_free(desc);
}
#elif defined(USE_PANGO)
- if (font->primaryFont()->m_font.m_font) {
- PangoFontDescription* desc = pango_font_describe(font->primaryFont()->m_font.m_font);
+ if (font->primaryFont()->platformData().m_font) {
+ PangoFontDescription* desc = pango_font_describe(font->primaryFont()->platformData().m_font);
pango_layout_set_font_description(layout, desc);
pango_font_description_free(desc);
}
@@ -183,6 +182,11 @@ static void setPangoAttributes(const Font* font, const TextRun& run, PangoLayout
pango_attr_list_unref(list);
}
+bool Font::canReturnFallbackFontsForComplexText()
+{
+ return false;
+}
+
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
{
cairo_t* cr = context->platformContext();
@@ -290,7 +294,7 @@ static PangoLayout* getDefaultPangoLayout(const TextRun& run)
return layout;
}
-float Font::floatWidthForComplexText(const TextRun& run) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */) const
{
if (run.length() == 0)
return 0.0f;
diff --git a/WebCore/platform/graphics/gtk/FontPlatformData.h b/WebCore/platform/graphics/gtk/FontPlatformData.h
index 20c52e5..ae1f134 100644
--- a/WebCore/platform/graphics/gtk/FontPlatformData.h
+++ b/WebCore/platform/graphics/gtk/FontPlatformData.h
@@ -82,6 +82,8 @@ public:
bool isFixedPitch();
float size() const { return m_size; }
+ bool syntheticBold() const { return m_syntheticBold; }
+ bool syntheticOblique() const { return m_syntheticOblique; }
void setFont(cairo_t*) const;
diff --git a/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp b/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp
index 68685e9..f0f0dd5 100644
--- a/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp
+++ b/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp
@@ -109,10 +109,9 @@ FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const
cairo_matrix_init_scale(&fontMatrix, fontDescription.computedPixelSize(), fontDescription.computedPixelSize());
cairo_matrix_init_identity(&ctm);
-#if GTK_CHECK_VERSION(2,10,0)
if (GdkScreen* screen = gdk_screen_get_default())
options = gdk_screen_get_font_options(screen);
-#endif
+
// gdk_screen_get_font_options() returns NULL if no default options are
// set, so we always have to check.
if (!options)
@@ -150,10 +149,9 @@ FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, int size, bool b
static const cairo_font_options_t* defaultOptions = cairo_font_options_create();
const cairo_font_options_t* options = NULL;
-#if GTK_CHECK_VERSION(2,10,0)
if (GdkScreen* screen = gdk_screen_get_default())
options = gdk_screen_get_font_options(screen);
-#endif
+
// gdk_screen_get_font_options() returns NULL if no default options are
// set, so we always have to check.
if (!options)
diff --git a/WebCore/platform/graphics/gtk/GlyphPageTreeNodeGtk.cpp b/WebCore/platform/graphics/gtk/GlyphPageTreeNodeGtk.cpp
index 24ad864..7c9ffe6 100644
--- a/WebCore/platform/graphics/gtk/GlyphPageTreeNodeGtk.cpp
+++ b/WebCore/platform/graphics/gtk/GlyphPageTreeNodeGtk.cpp
@@ -42,7 +42,7 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b
if (bufferLength > GlyphPage::size)
return false;
- FT_Face face = cairo_ft_scaled_font_lock_face(fontData->m_font.m_scaledFont);
+ FT_Face face = cairo_ft_scaled_font_lock_face(fontData->platformData().m_scaledFont);
if (!face)
return false;
@@ -57,7 +57,7 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b
}
}
- cairo_ft_scaled_font_unlock_face(fontData->m_font.m_scaledFont);
+ cairo_ft_scaled_font_unlock_face(fontData->platformData().m_scaledFont);
return haveGlyphs;
}
diff --git a/WebCore/platform/graphics/gtk/GlyphPageTreeNodePango.cpp b/WebCore/platform/graphics/gtk/GlyphPageTreeNodePango.cpp
index 8fada5c..8d0baa6 100644
--- a/WebCore/platform/graphics/gtk/GlyphPageTreeNodePango.cpp
+++ b/WebCore/platform/graphics/gtk/GlyphPageTreeNodePango.cpp
@@ -78,12 +78,12 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b
if (bufferLength > GlyphPage::size)
return false;
- if (!fontData->m_font.m_font || fontData->m_font.m_font == reinterpret_cast<PangoFont*>(-1))
+ if (!fontData->platformData().m_font || fontData->platformData().m_font == reinterpret_cast<PangoFont*>(-1))
return false;
bool haveGlyphs = false;
for (unsigned i = 0; i < length; i++) {
- Glyph glyph = pango_font_get_glyph(fontData->m_font.m_font, fontData->m_font.m_context, buffer[i]);
+ Glyph glyph = pango_font_get_glyph(fontData->platformData().m_font, fontData->platformData().m_context, buffer[i]);
if (!glyph)
setGlyphDataForIndex(offset + i, 0, 0);
else {
diff --git a/WebCore/platform/graphics/gtk/IconGtk.cpp b/WebCore/platform/graphics/gtk/IconGtk.cpp
index d8b38a0..e08c1ab 100644
--- a/WebCore/platform/graphics/gtk/IconGtk.cpp
+++ b/WebCore/platform/graphics/gtk/IconGtk.cpp
@@ -33,7 +33,6 @@
#include "CString.h"
#include "GraphicsContext.h"
#include "MIMETypeRegistry.h"
-#include "NotImplemented.h"
#include "PassRefPtr.h"
#include <gtk/gtk.h>
diff --git a/WebCore/platform/graphics/gtk/ImageGtk.cpp b/WebCore/platform/graphics/gtk/ImageGtk.cpp
index b745209..0e92d6c 100644
--- a/WebCore/platform/graphics/gtk/ImageGtk.cpp
+++ b/WebCore/platform/graphics/gtk/ImageGtk.cpp
@@ -26,12 +26,52 @@
#include "config.h"
#include "BitmapImage.h"
+#include "CString.h"
+#include "GOwnPtr.h"
-// This function loads resources from WebKit
-Vector<char> loadResourceIntoArray(const char*);
+#include <cairo.h>
+#include <gtk/gtk.h>
+
+namespace WTF {
+
+template <> void freeOwnedGPtr<GtkIconInfo>(GtkIconInfo* info)
+{
+ if (info)
+ gtk_icon_info_free(info);
+}
+
+}
namespace WebCore {
+static CString getIconFileNameOrFallback(const char* name, const char* fallback)
+{
+ GOwnPtr<GtkIconInfo> info(gtk_icon_theme_lookup_icon(gtk_icon_theme_get_default(),
+ name, 16, GTK_ICON_LOOKUP_NO_SVG));
+ if (!info)
+ return String::format("%s/webkit-1.0/images/%s.png", DATA_DIR, fallback).utf8();
+
+ return CString(gtk_icon_info_get_filename(info.get()));
+}
+
+static PassRefPtr<SharedBuffer> loadResourceSharedBuffer(const char* name)
+{
+ CString fileName;
+
+ // Find the path for the image
+ if (strcmp("missingImage", name) == 0)
+ fileName = getIconFileNameOrFallback(GTK_STOCK_MISSING_IMAGE, "missingImage");
+ else
+ fileName = String::format("%s/webkit-1.0/images/%s.png", DATA_DIR, name).utf8();
+
+ GOwnPtr<gchar> content;
+ gsize length;
+ if (!g_file_get_contents(fileName.data(), &content.outPtr(), &length, 0))
+ return SharedBuffer::create();
+
+ return SharedBuffer::create(content.get(), length);
+}
+
void BitmapImage::initPlatformData()
{
}
@@ -40,13 +80,34 @@ void BitmapImage::invalidatePlatformData()
{
}
-PassRefPtr<Image> Image::loadPlatformResource(const char *name)
+PassRefPtr<Image> Image::loadPlatformResource(const char* name)
{
- Vector<char> arr = loadResourceIntoArray(name);
RefPtr<BitmapImage> img = BitmapImage::create();
- RefPtr<SharedBuffer> buffer = SharedBuffer::create(arr.data(), arr.size());
- img->setData(buffer, true);
+ RefPtr<SharedBuffer> buffer = loadResourceSharedBuffer(name);
+ img->setData(buffer.release(), true);
return img.release();
}
+GdkPixbuf* BitmapImage::getGdkPixbuf()
+{
+ int width = cairo_image_surface_get_width(frameAtIndex(currentFrame()));
+ int height = cairo_image_surface_get_height(frameAtIndex(currentFrame()));
+
+ int bestDepth = gdk_visual_get_best_depth();
+ GdkColormap* cmap = gdk_colormap_new(gdk_visual_get_best_with_depth(bestDepth), true);
+
+ GdkPixmap* pixmap = gdk_pixmap_new(0, width, height, bestDepth);
+ gdk_drawable_set_colormap(GDK_DRAWABLE(pixmap), cmap);
+ cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(pixmap));
+ cairo_set_source_surface(cr, frameAtIndex(currentFrame()), 0, 0);
+ cairo_paint(cr);
+ cairo_destroy(cr);
+
+ GdkPixbuf* pixbuf = gdk_pixbuf_get_from_drawable(0, GDK_DRAWABLE(pixmap), 0, 0, 0, 0, 0, width, height);
+ g_object_unref(pixmap);
+ g_object_unref(cmap);
+
+ return pixbuf;
+}
+
}
diff --git a/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp b/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
index 4203a3c..6684108 100644
--- a/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
+++ b/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
@@ -49,7 +49,7 @@ void SimpleFontData::platformInit()
{
cairo_font_extents_t font_extents;
cairo_text_extents_t text_extents;
- cairo_scaled_font_extents(m_font.m_scaledFont, &font_extents);
+ cairo_scaled_font_extents(m_platformData.m_scaledFont, &font_extents);
m_ascent = static_cast<int>(font_extents.ascent);
m_descent = static_cast<int>(font_extents.descent);
m_lineSpacing = static_cast<int>(font_extents.height);
@@ -60,11 +60,19 @@ void SimpleFontData::platformInit()
// while we figure out what's going on.
if (m_lineSpacing < m_ascent + m_descent)
m_lineSpacing = m_ascent + m_descent;
- cairo_scaled_font_text_extents(m_font.m_scaledFont, "x", &text_extents);
+ cairo_scaled_font_text_extents(m_platformData.m_scaledFont, "x", &text_extents);
m_xHeight = text_extents.height;
- cairo_scaled_font_text_extents(m_font.m_scaledFont, " ", &text_extents);
+ cairo_scaled_font_text_extents(m_platformData.m_scaledFont, " ", &text_extents);
m_spaceWidth = static_cast<int>(text_extents.x_advance);
m_lineGap = m_lineSpacing - m_ascent - m_descent;
+ m_syntheticBoldOffset = m_platformData.syntheticBold() ? 1.0f : 0.f;
+}
+
+void SimpleFontData::platformCharWidthInit()
+{
+ m_avgCharWidth = 0.f;
+ m_maxCharWidth = 0.f;
+ initCharWidths();
}
void SimpleFontData::platformDestroy()
@@ -86,38 +94,38 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes
bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
{
- FT_Face face = cairo_ft_scaled_font_lock_face(m_font.m_scaledFont);
+ FT_Face face = cairo_ft_scaled_font_lock_face(m_platformData.m_scaledFont);
if (!face)
return false;
for (unsigned i = 0; i < length; i++) {
if (FcFreeTypeCharIndex(face, characters[i]) == 0) {
- cairo_ft_scaled_font_unlock_face(m_font.m_scaledFont);
+ cairo_ft_scaled_font_unlock_face(m_platformData.m_scaledFont);
return false;
}
}
- cairo_ft_scaled_font_unlock_face(m_font.m_scaledFont);
+ cairo_ft_scaled_font_unlock_face(m_platformData.m_scaledFont);
return true;
}
void SimpleFontData::determinePitch()
{
- m_treatAsFixedPitch = m_font.isFixedPitch();
+ m_treatAsFixedPitch = m_platformData.isFixedPitch();
}
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
- ASSERT(m_font.m_scaledFont);
+ ASSERT(m_platformData.m_scaledFont);
cairo_glyph_t cglyph = { glyph, 0, 0 };
cairo_text_extents_t extents;
- cairo_scaled_font_glyph_extents(m_font.m_scaledFont, &cglyph, 1, &extents);
+ cairo_scaled_font_glyph_extents(m_platformData.m_scaledFont, &cglyph, 1, &extents);
float w = (float)m_spaceWidth;
- if (cairo_scaled_font_status(m_font.m_scaledFont) == CAIRO_STATUS_SUCCESS && extents.x_advance != 0)
+ if (cairo_scaled_font_status(m_platformData.m_scaledFont) == CAIRO_STATUS_SUCCESS && extents.x_advance != 0)
w = (float)extents.x_advance;
return w;
}
@@ -125,7 +133,7 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
void SimpleFontData::setFont(cairo_t* cr) const
{
ASSERT(cr);
- m_font.setFont(cr);
+ m_platformData.setFont(cr);
}
}
diff --git a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp b/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp
index e345a8c..e57d9e6 100644
--- a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp
+++ b/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp
@@ -48,7 +48,7 @@ void SimpleFontData::platformInit()
{
cairo_font_extents_t font_extents;
cairo_text_extents_t text_extents;
- cairo_scaled_font_extents(m_font.m_scaledFont, &font_extents);
+ cairo_scaled_font_extents(m_platformData.m_scaledFont, &font_extents);
m_ascent = static_cast<int>(font_extents.ascent);
m_descent = static_cast<int>(font_extents.descent);
m_lineSpacing = static_cast<int>(font_extents.height);
@@ -59,11 +59,19 @@ void SimpleFontData::platformInit()
// while we figure out what's going on.
if (m_lineSpacing < m_ascent + m_descent)
m_lineSpacing = m_ascent + m_descent;
- cairo_scaled_font_text_extents(m_font.m_scaledFont, "x", &text_extents);
+ cairo_scaled_font_text_extents(m_platformData.m_scaledFont, "x", &text_extents);
m_xHeight = text_extents.height;
- cairo_scaled_font_text_extents(m_font.m_scaledFont, " ", &text_extents);
+ cairo_scaled_font_text_extents(m_platformData.m_scaledFont, " ", &text_extents);
m_spaceWidth = static_cast<int>(text_extents.x_advance);
m_lineGap = m_lineSpacing - m_ascent - m_descent;
+ m_syntheticBoldOffset = m_platformData.syntheticBold() ? 1.0f : 0.f;
+}
+
+void SimpleFontData::platformCharWidthInit()
+{
+ m_avgCharWidth = 0.f;
+ m_maxCharWidth = 0.f;
+ initCharWidths();
}
void SimpleFontData::platformDestroy()
@@ -87,7 +95,7 @@ bool SimpleFontData::containsCharacters(const UChar* characters, int length) con
{
bool result = true;
- PangoCoverage* coverage = pango_font_get_coverage(m_font.m_font, pango_language_get_default());
+ PangoCoverage* coverage = pango_font_get_coverage(m_platformData.m_font, pango_language_get_default());
for (int i = 0; i < length; i++) {
if (PANGO_COVERAGE_NONE == pango_coverage_get(coverage, characters[i])) {
@@ -108,19 +116,19 @@ void SimpleFontData::determinePitch()
return;
}
- m_treatAsFixedPitch = m_font.isFixedPitch();
+ m_treatAsFixedPitch = m_platformData.isFixedPitch();
}
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
- ASSERT(m_font.m_scaledFont);
+ ASSERT(m_platformData.m_scaledFont);
cairo_glyph_t cglyph = { glyph, 0, 0 };
cairo_text_extents_t extents;
- cairo_scaled_font_glyph_extents(m_font.m_scaledFont, &cglyph, 1, &extents);
+ cairo_scaled_font_glyph_extents(m_platformData.m_scaledFont, &cglyph, 1, &extents);
float w = (float)m_spaceWidth;
- if (cairo_scaled_font_status(m_font.m_scaledFont) == CAIRO_STATUS_SUCCESS && extents.x_advance != 0)
+ if (cairo_scaled_font_status(m_platformData.m_scaledFont) == CAIRO_STATUS_SUCCESS && extents.x_advance != 0)
w = (float)extents.x_advance;
return w;
}
@@ -128,7 +136,7 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
void SimpleFontData::setFont(cairo_t* cr) const
{
ASSERT(cr);
- m_font.setFont(cr);
+ m_platformData.setFont(cr);
}
}
diff --git a/WebCore/platform/graphics/mac/ColorMac.h b/WebCore/platform/graphics/mac/ColorMac.h
index 830e9d9..8a5ce31 100644
--- a/WebCore/platform/graphics/mac/ColorMac.h
+++ b/WebCore/platform/graphics/mac/ColorMac.h
@@ -41,7 +41,7 @@ namespace WebCore {
// These functions assume NSColors are in DeviceRGB colorspace
Color colorFromNSColor(NSColor *);
- NSColor* nsColor(const Color&);
+ NSColor *nsColor(const Color&);
bool usesTestModeFocusRingColor();
void setUsesTestModeFocusRingColor(bool);
diff --git a/WebCore/platform/graphics/mac/ColorMac.mm b/WebCore/platform/graphics/mac/ColorMac.mm
index 1c4350c..05dd78d 100644
--- a/WebCore/platform/graphics/mac/ColorMac.mm
+++ b/WebCore/platform/graphics/mac/ColorMac.mm
@@ -24,13 +24,10 @@
*/
#import "config.h"
-#import "Color.h"
#import "ColorMac.h"
-#import <AppKit/AppKit.h>
-#import <wtf/Assertions.h>
-#import <wtf/StdLibExtras.h>
#import <wtf/RetainPtr.h>
+#import <wtf/StdLibExtras.h>
@interface WebCoreControlTintObserver : NSObject
+ (void)controlTintDidChange;
@@ -47,7 +44,13 @@ static bool useOldAquaFocusRingColor;
static RGBA32 makeRGBAFromNSColor(NSColor *c)
{
- return makeRGBA((int)(255 * [c redComponent]), (int)(255 * [c greenComponent]), (int)(255 * [c blueComponent]), (int)(255 * [c alphaComponent]));
+ CGFloat redComponent;
+ CGFloat greenComponent;
+ CGFloat blueComponent;
+ CGFloat alpha;
+ [c getRed:&redComponent green:&greenComponent blue:&blueComponent alpha:&alpha];
+
+ return makeRGBA(255 * redComponent, 255 * greenComponent, 255 * blueComponent, 255 * alpha);
}
Color colorFromNSColor(NSColor *c)
@@ -55,21 +58,21 @@ Color colorFromNSColor(NSColor *c)
return Color(makeRGBAFromNSColor(c));
}
-NSColor* nsColor(const Color& color)
+NSColor *nsColor(const Color& color)
{
- unsigned c = color.rgb();
+ RGBA32 c = color.rgb();
switch (c) {
case 0: {
// Need this to avoid returning nil because cachedRGBAValues will default to 0.
- DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, clearColor, ([NSColor colorWithDeviceRed:0.0f green:0.0f blue:0.0f alpha:0.0f]));
+ DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, clearColor, ([NSColor colorWithDeviceRed:0 green:0 blue:0 alpha:0]));
return clearColor.get();
}
case Color::black: {
- DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, blackColor, ([NSColor colorWithDeviceRed:0.0f green:0.0f blue:0.0f alpha:1.0f]));
+ DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, blackColor, ([NSColor colorWithDeviceRed:0 green:0 blue:0 alpha:1]));
return blackColor.get();
}
case Color::white: {
- DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, whiteColor, ([NSColor colorWithDeviceRed:1.0f green:1.0f blue:1.0f alpha:1.0f]));
+ DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, whiteColor, ([NSColor colorWithDeviceRed:1 green:1 blue:1 alpha:1]));
return whiteColor.get();
}
default: {
@@ -81,10 +84,10 @@ NSColor* nsColor(const Color& color)
if (cachedRGBAValues[i] == c)
return cachedColors[i].get();
- NSColor* result = [NSColor colorWithDeviceRed:color.red() / 255.0f
- green:color.green() / 255.0f
- blue:color.blue() / 255.0f
- alpha:color.alpha() /255.0f];
+ NSColor *result = [NSColor colorWithDeviceRed:static_cast<CGFloat>(color.red()) / 255
+ green:static_cast<CGFloat>(color.green()) / 255
+ blue:static_cast<CGFloat>(color.blue()) / 255
+ alpha:static_cast<CGFloat>(color.alpha()) /255];
static int cursor;
cachedRGBAValues[cursor] = c;
@@ -96,16 +99,13 @@ NSColor* nsColor(const Color& color)
}
}
-static CGColorRef CGColorFromNSColor(NSColor* color)
+static CGColorRef CGColorFromNSColor(NSColor *color)
{
// This needs to always use device colorspace so it can de-calibrate the color for
// CGColor to possibly recalibrate it.
- NSColor* deviceColor = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
- CGFloat red = [deviceColor redComponent];
- CGFloat green = [deviceColor greenComponent];
- CGFloat blue = [deviceColor blueComponent];
- CGFloat alpha = [deviceColor alphaComponent];
- const CGFloat components[4] = { red, green, blue, alpha };
+ CGFloat components[4];
+ NSColor *deviceColor = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ [deviceColor getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]];
static CGColorSpaceRef deviceRGBColorSpace = CGColorSpaceCreateDeviceRGB();
CGColorRef cgColor = CGColorCreate(deviceRGBColorSpace, components);
return cgColor;
@@ -130,10 +130,10 @@ Color focusRingColor()
[WebCoreControlTintObserver controlTintDidChange];
tintIsKnown = true;
}
-
+
if (usesTestModeFocusRingColor())
return oldAquaFocusRingColor;
-
+
return systemFocusRingColor;
}
@@ -153,7 +153,7 @@ void setUsesTestModeFocusRingColor(bool newValue)
+ (void)controlTintDidChange
{
- NSColor* color = [[NSColor keyboardFocusIndicatorColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ NSColor *color = [[NSColor keyboardFocusIndicatorColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
WebCore::systemFocusRingColor = WebCore::makeRGBAFromNSColor(color);
}
diff --git a/WebCore/platform/graphics/mac/CoreTextController.cpp b/WebCore/platform/graphics/mac/CoreTextController.cpp
index 49e83c4..05f29b5 100644
--- a/WebCore/platform/graphics/mac/CoreTextController.cpp
+++ b/WebCore/platform/graphics/mac/CoreTextController.cpp
@@ -100,7 +100,7 @@ CoreTextController::CoreTextRun::CoreTextRun(const SimpleFontData* fontData, con
m_indices = reinterpret_cast<const CFIndex*>(CFDataGetBytePtr(m_indicesData.get()));
}
-CoreTextController::CoreTextController(const Font* font, const TextRun& run, bool mayUseNaturalWritingDirection)
+CoreTextController::CoreTextController(const Font* font, const TextRun& run, bool mayUseNaturalWritingDirection, HashSet<const SimpleFontData*>* fallbackFonts)
: m_font(*font)
, m_run(run)
, m_mayUseNaturalWritingDirection(mayUseNaturalWritingDirection)
@@ -112,6 +112,7 @@ CoreTextController::CoreTextController(const Font* font, const TextRun& run, boo
, m_currentRun(0)
, m_glyphInCurrentRun(0)
, m_finalRoundingWidth(0)
+ , m_fallbackFonts(fallbackFonts)
, m_lastRoundingGlyph(0)
{
m_padding = m_run.padding();
@@ -156,12 +157,12 @@ int CoreTextController::offsetForPosition(int h, bool includePartialGlyphs)
if (x <= adjustedAdvance) {
CFIndex hitIndex = coreTextRun.indexAt(j);
int stringLength = coreTextRun.stringLength();
- TextBreakIterator* characterIterator = characterBreakIterator(coreTextRun.characters(), stringLength);
+ TextBreakIterator* cursorPositionIterator = cursorMovementIterator(coreTextRun.characters(), stringLength);
int clusterStart;
- if (isTextBreak(characterIterator, hitIndex))
+ if (isTextBreak(cursorPositionIterator, hitIndex))
clusterStart = hitIndex;
else {
- clusterStart = textBreakPreceding(characterIterator, hitIndex);
+ clusterStart = textBreakPreceding(cursorPositionIterator, hitIndex);
if (clusterStart == TextBreakDone)
clusterStart = 0;
}
@@ -169,7 +170,7 @@ int CoreTextController::offsetForPosition(int h, bool includePartialGlyphs)
if (!includePartialGlyphs)
return coreTextRun.stringLocation() + clusterStart;
- int clusterEnd = textBreakFollowing(characterIterator, hitIndex);
+ int clusterEnd = textBreakFollowing(cursorPositionIterator, hitIndex);
if (clusterEnd == TextBreakDone)
clusterEnd = stringLength;
@@ -179,7 +180,7 @@ int CoreTextController::offsetForPosition(int h, bool includePartialGlyphs)
// reordering and on font fallback should occur within a CTLine.
if (clusterEnd - clusterStart > 1) {
int firstGlyphBeforeCluster = j - 1;
- while (firstGlyphBeforeCluster && coreTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && coreTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) {
+ while (firstGlyphBeforeCluster >= 0 && coreTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && coreTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) {
CGFloat width = m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphBeforeCluster].width;
clusterWidth += width;
x += width;
@@ -359,6 +360,9 @@ void CoreTextController::collectCoreTextRunsForCharacters(const UChar* cp, unsig
return;
}
+ if (m_fallbackFonts && fontData != m_font.primaryFont())
+ m_fallbackFonts->add(fontData);
+
RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(NULL, cp, length, kCFAllocatorNull));
RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(NULL, string.get(), fontData->getCFStringAttributes()));
@@ -426,7 +430,7 @@ void CoreTextController::adjustGlyphsAndAdvances()
bool lastRun = r + 1 == runCount;
const UChar* cp = coreTextRun.characters();
- CGFloat roundedSpaceWidth = roundCGFloat(fontData->m_spaceWidth);
+ 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();
@@ -444,29 +448,29 @@ void CoreTextController::adjustGlyphsAndAdvances()
nextCh = *(m_coreTextRuns[r + 1].characters() + m_coreTextRuns[r + 1].indexAt(0));
bool treatAsSpace = Font::treatAsSpace(ch);
- CGGlyph glyph = treatAsSpace ? fontData->m_spaceGlyph : glyphs[i];
- CGSize advance = treatAsSpace ? CGSizeMake(fontData->m_spaceWidth, advances[i].height) : advances[i];
+ CGGlyph glyph = treatAsSpace ? fontData->spaceGlyph() : glyphs[i];
+ CGSize advance = treatAsSpace ? CGSizeMake(fontData->spaceWidth(), advances[i].height) : advances[i];
if (ch == '\t' && m_run.allowTabs()) {
float tabWidth = m_font.tabWidth();
advance.width = tabWidth - fmodf(m_run.xPos() + m_totalWidth, tabWidth);
} else if (ch == zeroWidthSpace || Font::treatAsZeroWidthSpace(ch) && !treatAsSpace) {
advance.width = 0;
- glyph = fontData->m_spaceGlyph;
+ glyph = fontData->spaceGlyph();
}
float roundedAdvanceWidth = roundf(advance.width);
if (roundsAdvances)
advance.width = roundedAdvanceWidth;
- advance.width += fontData->m_syntheticBoldOffset;
+ advance.width += fontData->syntheticBoldOffset();
// We special case spaces in two ways when applying word rounding.
// First, we round spaces to an adjusted width in all fonts.
// Second, in fixed-pitch fonts we ensure that all glyphs that
// match the width of the space glyph have the same width as the space glyph.
- if (roundedAdvanceWidth == roundedSpaceWidth && (fontData->m_treatAsFixedPitch || glyph == fontData->m_spaceGlyph) && m_run.applyWordRounding())
- advance.width = fontData->m_adjustedSpaceWidth;
+ if (roundedAdvanceWidth == roundedSpaceWidth && (fontData->pitch() == FixedPitch || glyph == fontData->spaceGlyph()) && m_run.applyWordRounding())
+ advance.width = fontData->adjustedSpaceWidth();
if (hasExtraSpacing) {
// If we're a glyph with an advance, go ahead and add in letter-spacing.
@@ -475,7 +479,7 @@ void CoreTextController::adjustGlyphsAndAdvances()
advance.width += m_font.letterSpacing();
// Handle justification and word-spacing.
- if (glyph == fontData->m_spaceGlyph) {
+ if (glyph == fontData->spaceGlyph()) {
// 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) {
diff --git a/WebCore/platform/graphics/mac/CoreTextController.h b/WebCore/platform/graphics/mac/CoreTextController.h
index 8dbb7fb..4dd6f93 100644
--- a/WebCore/platform/graphics/mac/CoreTextController.h
+++ b/WebCore/platform/graphics/mac/CoreTextController.h
@@ -37,7 +37,7 @@ namespace WebCore {
class CoreTextController {
public:
- CoreTextController(const Font*, const TextRun&, bool mayUseNaturalWritingDirection = false);
+ CoreTextController(const Font*, const TextRun&, bool mayUseNaturalWritingDirection = false, HashSet<const SimpleFontData*>* fallbackFonts = 0);
// Advance and emit glyphs up to the specified character.
void advance(unsigned to, GlyphBuffer* = 0);
@@ -106,6 +106,8 @@ private:
float m_padding;
float m_padPerSpace;
+ HashSet<const SimpleFontData*>* m_fallbackFonts;
+
unsigned m_lastRoundingGlyph;
};
diff --git a/WebCore/platform/graphics/mac/FontCacheMac.mm b/WebCore/platform/graphics/mac/FontCacheMac.mm
index 2202459..2730d5a 100644
--- a/WebCore/platform/graphics/mac/FontCacheMac.mm
+++ b/WebCore/platform/graphics/mac/FontCacheMac.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
*
* Redistribution and use in source and binary forms, with or without
@@ -44,16 +44,30 @@ typedef int NSInteger;
namespace WebCore {
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+static void fontCacheRegisteredFontsChangedNotificationCallback(CFNotificationCenterRef, void* observer, CFStringRef name, const void *, CFDictionaryRef)
+{
+ ASSERT_UNUSED(observer, observer == fontCache());
+ ASSERT_UNUSED(name, CFEqual(name, kCTFontManagerRegisteredFontsChangedNotification));
+ fontCache()->invalidate();
+}
+#else
static void fontCacheATSNotificationCallback(ATSFontNotificationInfoRef, void*)
{
fontCache()->invalidate();
}
+#endif
void FontCache::platformInit()
{
wkSetUpFontCache();
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), this, fontCacheRegisteredFontsChangedNotificationCallback, kCTFontManagerRegisteredFontsChangedNotification, 0, CFNotificationSuspensionBehaviorDeliverImmediately);
+#else
+ // kCTFontManagerRegisteredFontsChangedNotification does not exist on Leopard and earlier.
// FIXME: Passing kATSFontNotifyOptionReceiveWhileSuspended may be an overkill and does not seem to work anyway.
ATSFontNotificationSubscribe(fontCacheATSNotificationCallback, kATSFontNotifyOptionReceiveWhileSuspended, 0, 0);
+#endif
}
static int toAppKitFontWeight(FontWeight fontWeight)
diff --git a/WebCore/platform/graphics/mac/FontMac.mm b/WebCore/platform/graphics/mac/FontMac.mm
index dc86c4b..df9494a 100644
--- a/WebCore/platform/graphics/mac/FontMac.mm
+++ b/WebCore/platform/graphics/mac/FontMac.mm
@@ -28,7 +28,6 @@
#import "Logging.h"
#import "SimpleFontData.h"
#import "WebCoreSystemInterface.h"
-#import "WebCoreTextRenderer.h"
#import <AppKit/AppKit.h>
#define SYNTHETIC_OBLIQUE_ANGLE 14
@@ -43,12 +42,17 @@ using namespace std;
namespace WebCore {
+bool Font::canReturnFallbackFontsForComplexText()
+{
+ return true;
+}
+
void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
{
CGContextRef cgContext = context->platformContext();
bool originalShouldUseFontSmoothing = wkCGContextGetShouldSmoothFonts(cgContext);
- bool newShouldUseFontSmoothing = WebCoreShouldUseFontSmoothing();
+ bool newShouldUseFontSmoothing = shouldUseSmoothing();
if (originalShouldUseFontSmoothing != newShouldUseFontSmoothing)
CGContextSetShouldSmoothFonts(cgContext, newShouldUseFontSmoothing);
@@ -99,8 +103,8 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
context->setFillColor(shadowFillColor);
CGContextSetTextPosition(cgContext, point.x() + shadowSize.width(), point.y() + shadowSize.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
- if (font->m_syntheticBoldOffset) {
- CGContextSetTextPosition(cgContext, point.x() + shadowSize.width() + font->m_syntheticBoldOffset, point.y() + shadowSize.height());
+ if (font->syntheticBoldOffset()) {
+ CGContextSetTextPosition(cgContext, point.x() + shadowSize.width() + font->syntheticBoldOffset(), point.y() + shadowSize.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
}
context->setFillColor(fillColor);
@@ -108,8 +112,8 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
CGContextSetTextPosition(cgContext, point.x(), point.y());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
- if (font->m_syntheticBoldOffset) {
- CGContextSetTextPosition(cgContext, point.x() + font->m_syntheticBoldOffset, point.y());
+ if (font->syntheticBoldOffset()) {
+ CGContextSetTextPosition(cgContext, point.x() + font->syntheticBoldOffset(), point.y());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
}
diff --git a/WebCore/platform/graphics/mac/FontMacATSUI.mm b/WebCore/platform/graphics/mac/FontMacATSUI.mm
index 3794149..051abb7 100644
--- a/WebCore/platform/graphics/mac/FontMacATSUI.mm
+++ b/WebCore/platform/graphics/mac/FontMacATSUI.mm
@@ -47,13 +47,15 @@ namespace WebCore {
struct ATSULayoutParameters : Noncopyable
{
- ATSULayoutParameters(const TextRun& run)
+ ATSULayoutParameters(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts = 0)
: m_run(run)
, m_font(0)
, m_hasSyntheticBold(false)
, m_syntheticBoldPass(false)
, m_padPerSpace(0)
- {}
+ , m_fallbackFonts(fallbackFonts)
+ {
+ }
~ATSULayoutParameters()
{
@@ -73,6 +75,7 @@ struct ATSULayoutParameters : Noncopyable
bool m_hasSyntheticBold;
bool m_syntheticBoldPass;
float m_padPerSpace;
+ HashSet<const SimpleFontData*>* m_fallbackFonts;
};
static TextRun copyRunForDirectionalOverrideIfNecessary(const TextRun& run, OwnArrayPtr<UChar>& charactersWithOverride)
@@ -124,7 +127,7 @@ static void initializeATSUStyle(const SimpleFontData* fontData)
ATSUFontID fontID = fontData->platformData().m_atsuFontID;
if (!fontID) {
- LOG_ERROR("unable to get ATSUFontID for %@", fontData->m_font.font());
+ LOG_ERROR("unable to get ATSUFontID for %@", fontData->platformData().font());
return;
}
@@ -134,7 +137,7 @@ static void initializeATSUStyle(const SimpleFontData* fontData)
LOG_ERROR("ATSUCreateStyle failed (%d)", status);
CGAffineTransform transform = CGAffineTransformMakeScale(1, -1);
- if (fontData->m_font.m_syntheticOblique)
+ if (fontData->platformData().m_syntheticOblique)
transform = CGAffineTransformConcat(transform, CGAffineTransformMake(1, 0, -tanf(SYNTHETIC_OBLIQUE_ANGLE * acosf(0) / 90), 1, 0, 0));
Fixed fontSize = FloatToFixed(fontData->platformData().m_size);
ByteCount styleSizes[4] = { sizeof(Fixed), sizeof(ATSUFontID), sizeof(CGAffineTransform), sizeof(Fract) };
@@ -180,7 +183,6 @@ static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef
bool shouldRound = false;
bool syntheticBoldPass = params->m_syntheticBoldPass;
Fixed syntheticBoldOffset = 0;
- ATSGlyphRef spaceGlyph = 0;
bool hasExtraSpacing = (params->m_font->letterSpacing() || params->m_font->wordSpacing() || params->m_run.padding()) && !params->m_run.spacingDisabled();
float padding = params->m_run.padding();
// In the CoreGraphics code path, the rounding hack is applied in logical order.
@@ -190,27 +192,28 @@ static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef
for (i = 1; i < count; i++) {
bool isLastChar = i == count - 1;
renderer = renderers[offset / 2];
- if (renderer != lastRenderer) {
- lastRenderer = renderer;
- spaceGlyph = renderer->m_spaceGlyph;
- // The CoreGraphics interpretation of NSFontAntialiasedIntegerAdvancementsRenderingMode seems
- // to be "round each glyph's width to the nearest integer". This is not the same as ATSUI
- // does in any of its device-metrics modes.
- shouldRound = renderer->platformData().roundsGlyphAdvances();
- if (syntheticBoldPass)
- syntheticBoldOffset = FloatToFixed(renderer->m_syntheticBoldOffset);
- }
float width;
if (nextCh == zeroWidthSpace || Font::treatAsZeroWidthSpace(nextCh) && !Font::treatAsSpace(nextCh)) {
width = 0;
- layoutRecords[i-1].glyphID = spaceGlyph;
+ layoutRecords[i-1].glyphID = renderer->spaceGlyph();
} else {
width = FixedToFloat(layoutRecords[i].realPos - lastNativePos);
+ if (renderer != lastRenderer && width) {
+ lastRenderer = renderer;
+ // The CoreGraphics interpretation of NSFontAntialiasedIntegerAdvancementsRenderingMode seems
+ // to be "round each glyph's width to the nearest integer". This is not the same as ATSUI
+ // does in any of its device-metrics modes.
+ shouldRound = renderer->platformData().roundsGlyphAdvances();
+ if (syntheticBoldPass)
+ syntheticBoldOffset = FloatToFixed(renderer->syntheticBoldOffset());
+ if (params->m_fallbackFonts && renderer != params->m_font->primaryFont())
+ params->m_fallbackFonts->add(renderer);
+ }
if (shouldRound)
width = roundf(width);
- width += renderer->m_syntheticBoldOffset;
- if (renderer->m_treatAsFixedPitch ? width == renderer->m_spaceWidth : (layoutRecords[i-1].flags & kATSGlyphInfoIsWhiteSpace))
- width = renderer->m_adjustedSpaceWidth;
+ width += renderer->syntheticBoldOffset();
+ if (renderer->pitch() == FixedPitch ? width == renderer->spaceWidth() : (layoutRecords[i-1].flags & kATSGlyphInfoIsWhiteSpace))
+ width = renderer->adjustedSpaceWidth();
}
lastNativePos = layoutRecords[i].realPos;
@@ -258,7 +261,7 @@ static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef
if (syntheticBoldOffset)
layoutRecords[i-1].realPos += syntheticBoldOffset;
else
- layoutRecords[i-1].glyphID = spaceGlyph;
+ layoutRecords[i-1].glyphID = renderer->spaceGlyph();
}
layoutRecords[i].realPos = FloatToFixed(lastAdjustedPos);
}
@@ -460,7 +463,7 @@ void ATSULayoutParameters::initialize(const Font* font, const GraphicsContext* g
}
} else
m_fonts[i] = r;
- if (m_fonts[i]->m_syntheticBoldOffset)
+ if (m_fonts[i]->syntheticBoldOffset())
m_hasSyntheticBold = true;
}
substituteOffset += substituteLength;
@@ -570,12 +573,12 @@ void Font::drawComplexText(GraphicsContext* graphicsContext, const TextRun& run,
graphicsContext->setShadow(shadowSize, shadowBlur, shadowColor);
}
-float Font::floatWidthForComplexText(const TextRun& run) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
{
if (run.length() == 0)
return 0;
- ATSULayoutParameters params(run);
+ ATSULayoutParameters params(run, fallbackFonts);
params.initialize(this);
OSStatus status;
diff --git a/WebCore/platform/graphics/mac/FontMacCoreText.cpp b/WebCore/platform/graphics/mac/FontMacCoreText.cpp
index 5fb9d5d..9dffc7a 100644
--- a/WebCore/platform/graphics/mac/FontMacCoreText.cpp
+++ b/WebCore/platform/graphics/mac/FontMacCoreText.cpp
@@ -86,9 +86,9 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
drawGlyphBuffer(context, glyphBuffer, run, startPoint);
}
-float Font::floatWidthForComplexText(const TextRun& run) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
{
- CoreTextController controller(this, run, true);
+ CoreTextController controller(this, run, true, fallbackFonts);
return controller.totalWidth();
}
diff --git a/WebCore/platform/graphics/mac/FontPlatformData.h b/WebCore/platform/graphics/mac/FontPlatformData.h
index e911867..1b7b884 100644
--- a/WebCore/platform/graphics/mac/FontPlatformData.h
+++ b/WebCore/platform/graphics/mac/FontPlatformData.h
@@ -82,6 +82,8 @@ struct FontPlatformData {
bool isHashTableDeletedValue() const { return m_font == hashTableDeletedFontValue(); }
float size() const { return m_size; }
+ bool syntheticBold() const { return m_syntheticBold; }
+ bool syntheticOblique() const { return m_syntheticOblique; }
bool m_syntheticBold;
bool m_syntheticOblique;
diff --git a/WebCore/platform/graphics/mac/GraphicsContextMac.mm b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
index 4e11602..2404319 100644
--- a/WebCore/platform/graphics/mac/GraphicsContextMac.mm
+++ b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
@@ -96,27 +96,28 @@ static NSColor* createPatternColor(NSString* name, NSColor* defaultColor, bool&
color = defaultColor;
return color;
}
-
+
+// WebKit on Mac is a standard platform component, so it must use the standard platform artwork for underline.
void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point, int width, bool grammar)
{
if (paintingDisabled())
return;
- // These are the same for misspelling or bad grammar
+ // These are the same for misspelling or bad grammar.
int patternHeight = cMisspellingLineThickness;
int patternWidth = cMisspellingLinePatternWidth;
bool usingDot;
NSColor *patternColor;
if (grammar) {
- // Constants for grammar pattern color
+ // Constants for grammar pattern color.
static bool usingDotForGrammar = false;
DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, grammarPatternColor, (createPatternColor(@"GrammarDot", [NSColor greenColor], usingDotForGrammar)));
usingDot = usingDotForGrammar;
patternColor = grammarPatternColor.get();
} else {
- // Constants for spelling pattern color
+ // Constants for spelling pattern color.
static bool usingDotForSpelling = false;
DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, spellingPatternColor, (createPatternColor(@"SpellingDot", [NSColor redColor], usingDotForSpelling)));
@@ -141,7 +142,7 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point,
// FIXME: This code should not be using wkSetPatternPhaseInUserSpace, as this approach is wrong
// for transforms.
- // Draw underline
+ // Draw underline.
NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
CGContextRef context = (CGContextRef)[currentContext graphicsPort];
CGContextSaveGState(context);
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.h b/WebCore/platform/graphics/mac/GraphicsLayerCA.h
index 3a692d3..50138d5 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.h
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.h
@@ -117,9 +117,8 @@ private:
bool requiresTiledLayer(const FloatSize&) const;
void swapFromOrToTiledLayer(bool useTiledLayer);
- void setHasContentsLayer(bool);
void setContentsLayer(WebLayer*);
- void setContentsLayerFlipped(bool);
+ WebLayer* contentsLayer() const { return m_contentsLayer.get(); }
RetainPtr<WebLayer> m_layer;
RetainPtr<WebLayer> m_transformLayer;
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
index f3f2d7f..f361437 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
@@ -271,9 +271,9 @@ static bool forceSoftwareAnimation()
return forceSoftwareAnimation;
}
-bool GraphicsLayer::graphicsContextsFlipped()
+GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation()
{
- return true;
+ return CompositingCoordinatesBottomUp;
}
#ifndef NDEBUG
@@ -746,8 +746,10 @@ void GraphicsLayerCA::setDrawsContent(bool drawsContent)
swapFromOrToTiledLayer(needTiledLayer);
BEGIN_BLOCK_OBJC_EXCEPTIONS
- // Clobber any existing content. If necessary, CA will create backing store on the next display.
- [m_layer.get() setContents:nil];
+ if (m_drawsContent)
+ [m_layer.get() setNeedsDisplay];
+ else
+ [m_layer.get() setContents:nil];
#ifndef NDEBUG
updateDebugIndicators();
@@ -761,7 +763,14 @@ void GraphicsLayerCA::setBackgroundColor(const Color& color, const Animation* tr
GraphicsLayer::setBackgroundColor(color, transition, beginTime);
BEGIN_BLOCK_OBJC_EXCEPTIONS
- setHasContentsLayer(true);
+
+ if (!m_contentsLayer.get()) {
+ WebLayer* colorLayer = [WebLayer layer];
+#ifndef NDEBUG
+ [colorLayer setName:@"Color Layer"];
+#endif
+ setContentsLayer(colorLayer);
+ }
if (transition && !transition->isEmptyOrZeroDuration()) {
CALayer* presLayer = [m_contentsLayer.get() presentationLayer];
@@ -777,7 +786,6 @@ void GraphicsLayerCA::setBackgroundColor(const Color& color, const Animation* tr
CGColorRelease(bgColor);
} else {
removeAllAnimationsForProperty(AnimatedPropertyBackgroundColor);
- setHasContentsLayer(true);
setLayerBackgroundColor(m_contentsLayer.get(), m_backgroundColor);
}
@@ -787,7 +795,7 @@ void GraphicsLayerCA::setBackgroundColor(const Color& color, const Animation* tr
void GraphicsLayerCA::clearBackgroundColor()
{
if (!m_contentLayerForImageOrVideo)
- setHasContentsLayer(false);
+ setContentsLayer(0);
else
clearLayerBackgroundColor(m_contentsLayer.get());
}
@@ -1082,35 +1090,27 @@ bool GraphicsLayerCA::animateFloat(AnimatedPropertyID property, const FloatValue
void GraphicsLayerCA::setContentsToImage(Image* image)
{
if (image) {
- setHasContentsLayer(true);
-
- // FIXME: is image flipping really a property of the graphics context?
- bool needToFlip = GraphicsLayer::graphicsContextsFlipped();
- CGPoint anchorPoint = needToFlip ? CGPointMake(0.0f, 1.0f) : CGPointZero;
-
BEGIN_BLOCK_OBJC_EXCEPTIONS
{
- CGImageRef theImage = image->nativeImageForCurrentFrame();
+ if (!m_contentsLayer.get()) {
+ WebLayer* imageLayer = [WebLayer layer];
+#ifndef NDEBUG
+ [imageLayer setName:@"Image Layer"];
+#endif
+ setContentsLayer(imageLayer);
+ }
+
// FIXME: maybe only do trilinear if the image is being scaled down,
// but then what if the layer size changes?
-#if HAVE_MODERN_QUARTZCORE
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
[m_contentsLayer.get() setMinificationFilter:kCAFilterTrilinear];
#endif
- if (needToFlip) {
- CATransform3D flipper = {
- 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, -1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f};
- [m_contentsLayer.get() setTransform:flipper];
- }
-
- [m_contentsLayer.get() setAnchorPoint:anchorPoint];
+ CGImageRef theImage = image->nativeImageForCurrentFrame();
[m_contentsLayer.get() setContents:(id)theImage];
}
END_BLOCK_OBJC_EXCEPTIONS
} else
- setHasContentsLayer(false);
+ setContentsLayer(0);
m_contentLayerForImageOrVideo = (image != 0);
}
@@ -1124,7 +1124,7 @@ void GraphicsLayerCA::setContentsToVideo(PlatformLayer* videoLayer)
void GraphicsLayerCA::clearContents()
{
if (m_contentLayerForImageOrVideo) {
- setHasContentsLayer(false);
+ setContentsLayer(0);
m_contentLayerForImageOrVideo = false;
}
}
@@ -1431,7 +1431,7 @@ void GraphicsLayerCA::swapFromOrToTiledLayer(bool userTiledLayer)
[tiledLayer setLevelsOfDetail:1];
[tiledLayer setLevelsOfDetailBias:0];
- if (GraphicsLayer::graphicsContextsFlipped())
+ if (GraphicsLayer::compositingCoordinatesOrientation() == GraphicsLayer::CompositingCoordinatesBottomUp)
[tiledLayer setContentsGravity:@"bottomLeft"];
else
[tiledLayer setContentsGravity:@"topLeft"];
@@ -1476,24 +1476,6 @@ void GraphicsLayerCA::swapFromOrToTiledLayer(bool userTiledLayer)
#endif
}
-void GraphicsLayerCA::setHasContentsLayer(bool hasLayer)
-{
- BEGIN_BLOCK_OBJC_EXCEPTIONS
-
- if (hasLayer && !m_contentsLayer) {
- // create the inner layer
- WebLayer* contentsLayer = [WebLayer layer];
-#ifndef NDEBUG
- [contentsLayer setName:@"Contents Layer"];
-#endif
- setContentsLayer(contentsLayer);
-
- } else if (!hasLayer && m_contentsLayer)
- setContentsLayer(0);
-
- END_BLOCK_OBJC_EXCEPTIONS
-}
-
void GraphicsLayerCA::setContentsLayer(WebLayer* contentsLayer)
{
if (contentsLayer == m_contentsLayer)
@@ -1511,14 +1493,26 @@ void GraphicsLayerCA::setContentsLayer(WebLayer* contentsLayer)
[contentsLayer setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]];
m_contentsLayer.adoptNS([contentsLayer retain]);
- [m_contentsLayer.get() setAnchorPoint:CGPointZero];
- [m_layer.get() addSublayer:m_contentsLayer.get()];
- updateContentsRect();
+ bool needToFlip = GraphicsLayer::compositingCoordinatesOrientation() == GraphicsLayer::CompositingCoordinatesBottomUp;
+ CGPoint anchorPoint = needToFlip ? CGPointMake(0.0f, 1.0f) : CGPointZero;
- // Set contents to nil if the layer does not draw its own content.
- if (m_client && !drawsContent())
- [m_layer.get() setContents:nil];
+ // If the layer world is flipped, we need to un-flip the contents layer
+ if (needToFlip) {
+ CATransform3D flipper = {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ [m_contentsLayer.get() setTransform:flipper];
+ }
+ [m_contentsLayer.get() setAnchorPoint:anchorPoint];
+
+ // Insert the content layer first. Video elements require this, because they have
+ // shadow content that must display in front of the video.
+ [m_layer.get() insertSublayer:m_contentsLayer.get() atIndex:0];
+
+ updateContentsRect();
#ifndef NDEBUG
if (showDebugBorders()) {
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
index 677c31a..f90f258 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
@@ -30,6 +30,7 @@
#include "MediaPlayerPrivate.h"
#include "Timer.h"
+#include "FloatSize.h"
#include <wtf/RetainPtr.h>
#ifdef __OBJC__
@@ -127,6 +128,8 @@ private:
float maxTimeLoaded() const;
void disableUnsupportedTracks();
+ void sawUnsupportedTracks();
+ void cacheMovieScale();
bool metaDataAvailable() const { return m_qtMovie && m_readyState >= MediaPlayer::HaveMetadata; }
MediaPlayer* m_player;
@@ -142,7 +145,10 @@ private:
bool m_isStreaming;
bool m_visible;
IntRect m_rect;
+ FloatSize m_scaleFactor;
unsigned m_enabledTrackCount;
+ unsigned m_totalTrackCount;
+ bool m_hasUnsupportedTracks;
float m_duration;
#if DRAW_FRAME_RATE
int m_frameCountWhilePlaying;
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
index 74a9ff9..dd41ed3 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
@@ -37,6 +37,7 @@
#import "FrameView.h"
#import "GraphicsContext.h"
#import "KURL.h"
+#import "MIMETypeRegistry.h"
#import "SoftLinking.h"
#import "WebCoreSystemInterface.h"
#import <QTKit/QTKit.h>
@@ -67,6 +68,7 @@ SOFT_LINK(QTKit, QTMakeTime, QTTime, (long long timeValue, long timeScale), (tim
SOFT_LINK_CLASS(QTKit, QTMovie)
SOFT_LINK_CLASS(QTKit, QTMovieView)
+SOFT_LINK_POINTER(QTKit, QTTrackMediaTypeAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMediaTypeAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMediaTypeBase, NSString *)
SOFT_LINK_POINTER(QTKit, QTMediaTypeMPEG, NSString *)
@@ -81,6 +83,7 @@ SOFT_LINK_POINTER(QTKit, QTMovieIsActiveAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieLoadStateAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieLoadStateDidChangeNotification, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieNaturalSizeAttribute, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieCurrentSizeAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMoviePreventExternalURLLinksAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieRateDidChangeNotification, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieSizeDidChangeNotification, NSString *)
@@ -90,10 +93,15 @@ SOFT_LINK_POINTER(QTKit, QTMovieURLAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieVolumeDidChangeNotification, NSString *)
SOFT_LINK_POINTER(QTKit, QTSecurityPolicyNoCrossSiteAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTVideoRendererWebKitOnlyNewImageAvailableNotification, NSString *)
+#ifndef BUILDING_ON_TIGER
+SOFT_LINK_POINTER(QTKit, QTMovieApertureModeClean, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieApertureModeAttribute, NSString *)
+#endif
#define QTMovie getQTMovieClass()
#define QTMovieView getQTMovieViewClass()
+#define QTTrackMediaTypeAttribute getQTTrackMediaTypeAttribute()
#define QTMediaTypeAttribute getQTMediaTypeAttribute()
#define QTMediaTypeBase getQTMediaTypeBase()
#define QTMediaTypeMPEG getQTMediaTypeMPEG()
@@ -108,6 +116,7 @@ SOFT_LINK_POINTER(QTKit, QTVideoRendererWebKitOnlyNewImageAvailableNotification,
#define QTMovieLoadStateAttribute getQTMovieLoadStateAttribute()
#define QTMovieLoadStateDidChangeNotification getQTMovieLoadStateDidChangeNotification()
#define QTMovieNaturalSizeAttribute getQTMovieNaturalSizeAttribute()
+#define QTMovieCurrentSizeAttribute getQTMovieCurrentSizeAttribute()
#define QTMoviePreventExternalURLLinksAttribute getQTMoviePreventExternalURLLinksAttribute()
#define QTMovieRateDidChangeNotification getQTMovieRateDidChangeNotification()
#define QTMovieSizeDidChangeNotification getQTMovieSizeDidChangeNotification()
@@ -117,6 +126,10 @@ SOFT_LINK_POINTER(QTKit, QTVideoRendererWebKitOnlyNewImageAvailableNotification,
#define QTMovieVolumeDidChangeNotification getQTMovieVolumeDidChangeNotification()
#define QTSecurityPolicyNoCrossSiteAttribute getQTSecurityPolicyNoCrossSiteAttribute()
#define QTVideoRendererWebKitOnlyNewImageAvailableNotification getQTVideoRendererWebKitOnlyNewImageAvailableNotification()
+#ifndef BUILDING_ON_TIGER
+#define QTMovieApertureModeClean getQTMovieApertureModeClean()
+#define QTMovieApertureModeAttribute getQTMovieApertureModeAttribute()
+#endif
// Older versions of the QTKit header don't have these constants.
#if !defined QTKIT_VERSION_MAX_ALLOWED || QTKIT_VERSION_MAX_ALLOWED <= QTKIT_VERSION_7_0
@@ -184,7 +197,10 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
, m_isStreaming(false)
, m_visible(false)
, m_rect()
+ , m_scaleFactor(1, 1)
, m_enabledTrackCount(0)
+ , m_totalTrackCount(0)
+ , m_hasUnsupportedTracks(false)
, m_duration(-1.0f)
#if DRAW_FRAME_RATE
, m_frameCountWhilePlaying(0)
@@ -221,10 +237,15 @@ void MediaPlayerPrivate::createQTMovie(const String& url)
[NSNumber numberWithBool:YES], QTMoviePreventExternalURLLinksAttribute,
[NSNumber numberWithBool:YES], QTSecurityPolicyNoCrossSiteAttribute,
[NSNumber numberWithBool:NO], QTMovieAskUnresolvedDataRefsAttribute,
- [NSNumber numberWithBool:YES], @"QTMovieOpenForPlaybackAttribute", // FIXME: Use defined attribute when required version of QT supports this attribute
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ [NSNumber numberWithBool:YES], @"QTMovieOpenForPlaybackAttribute",
+#endif
+#ifndef BUILDING_ON_TIGER
+ QTMovieApertureModeClean, QTMovieApertureModeAttribute,
+#endif
nil];
- NSError* error = nil;
+ NSError *error = nil;
m_qtMovie.adoptNS([[QTMovie alloc] initWithAttributes:movieAttributes error:&error]);
// FIXME: Find a proper way to detect streaming content.
@@ -239,6 +260,17 @@ void MediaPlayerPrivate::createQTMovie(const String& url)
selector:@selector(loadStateChanged:)
name:QTMovieLoadStateDidChangeNotification
object:m_qtMovie.get()];
+
+ // In updateState(), we track when maxTimeLoaded() == duration().
+ // In newer version of QuickTime, a notification is emitted when maxTimeLoaded changes.
+ // In older version of QuickTime, QTMovieLoadStateDidChangeNotification be fired.
+ if (NSString *maxTimeLoadedChangeNotification = wkQTMovieMaxTimeLoadedChangeNotification()) {
+ [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()
+ selector:@selector(loadStateChanged:)
+ name:maxTimeLoadedChangeNotification
+ object:m_qtMovie.get()];
+ }
+
[[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()
selector:@selector(rateChanged:)
name:QTMovieRateDidChangeNotification
@@ -545,7 +577,16 @@ IntSize MediaPlayerPrivate::naturalSize() const
{
if (!metaDataAvailable())
return IntSize();
- return IntSize([[m_qtMovie.get() attributeForKey:QTMovieNaturalSizeAttribute] sizeValue]);
+
+ // In spite of the name of this method, return QTMovieNaturalSizeAttribute transformed by the
+ // initial movie scale because the spec says intrinsic size is:
+ //
+ // ... the dimensions of the resource in CSS pixels after taking into account the resource's
+ // dimensions, aspect ratio, clean aperture, resolution, and so forth, as defined for the
+ // format used by the resource
+
+ NSSize naturalSize = [[m_qtMovie.get() attributeForKey:QTMovieNaturalSizeAttribute] sizeValue];
+ return IntSize(naturalSize.width * m_scaleFactor.width(), naturalSize.height * m_scaleFactor.height());
}
bool MediaPlayerPrivate::hasVideo() const
@@ -586,8 +627,14 @@ float MediaPlayerPrivate::maxTimeBuffered() const
float MediaPlayerPrivate::maxTimeSeekable() const
{
+ if (!metaDataAvailable())
+ return 0;
+
// infinite duration means live stream
- return isinf(duration()) ? 0 : maxTimeLoaded();
+ if (isinf(duration()))
+ return 0;
+
+ return wkQTMovieMaxTimeSeekable(m_qtMovie.get());
}
float MediaPlayerPrivate::maxTimeLoaded() const
@@ -629,6 +676,31 @@ void MediaPlayerPrivate::cancelLoad()
updateStates();
}
+void MediaPlayerPrivate::cacheMovieScale()
+{
+ NSSize initialSize = NSZeroSize;
+ NSSize naturalSize = [[m_qtMovie.get() attributeForKey:QTMovieNaturalSizeAttribute] sizeValue];
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ // QTMovieCurrentSizeAttribute is not allowed with instances of QTMovie that have been
+ // opened with QTMovieOpenForPlaybackAttribute, so ask for the display transform attribute instead.
+ NSAffineTransform *displayTransform = [m_qtMovie.get() attributeForKey:@"QTMoviePreferredTransformAttribute"];
+ if (displayTransform)
+ initialSize = [displayTransform transformSize:naturalSize];
+ else {
+ initialSize.width = naturalSize.width;
+ initialSize.height = naturalSize.height;
+ }
+#else
+ initialSize = [[m_qtMovie.get() attributeForKey:QTMovieCurrentSizeAttribute] sizeValue];
+#endif
+
+ if (naturalSize.width)
+ m_scaleFactor.setWidth(initialSize.width / naturalSize.width);
+ if (naturalSize.height)
+ m_scaleFactor.setHeight(initialSize.height / naturalSize.height);
+}
+
void MediaPlayerPrivate::updateStates()
{
MediaPlayer::NetworkState oldNetworkState = m_networkState;
@@ -636,18 +708,37 @@ void MediaPlayerPrivate::updateStates()
long loadState = m_qtMovie ? [[m_qtMovie.get() attributeForKey:QTMovieLoadStateAttribute] longValue] : static_cast<long>(QTMovieLoadStateError);
- if (loadState >= QTMovieLoadStateLoaded && m_readyState < MediaPlayer::HaveMetadata && !m_player->inMediaDocument()) {
+ if (loadState >= QTMovieLoadStateLoaded && m_readyState < MediaPlayer::HaveMetadata) {
disableUnsupportedTracks();
- if (!m_enabledTrackCount)
+ if (m_player->inMediaDocument()) {
+ if (!m_enabledTrackCount || m_enabledTrackCount != m_totalTrackCount) {
+ // This is a type of media that we do not handle directly with a <video>
+ // element, likely streamed media or QuickTime VR. Tell the MediaPlayerClient
+ // that we noticed.
+ sawUnsupportedTracks();
+ return;
+ }
+ } else if (!m_enabledTrackCount) {
loadState = QTMovieLoadStateError;
+ }
+
+ if (loadState != QTMovieLoadStateError)
+ cacheMovieScale();
}
- if (loadState >= QTMovieLoadStateComplete && !m_isStreaming) {
+ BOOL completelyLoaded = !m_isStreaming && (loadState >= QTMovieLoadStateComplete);
+
+ // Note: QT indicates that we are fully loaded with QTMovieLoadStateComplete.
+ // However newer versions of QT do not, so we check maxTimeLoaded against duration.
+ if (!completelyLoaded && !m_isStreaming && metaDataAvailable())
+ completelyLoaded = maxTimeLoaded() == duration();
+
+ if (completelyLoaded) {
// "Loaded" is reserved for fully buffered movies, never the case when streaming
m_networkState = MediaPlayer::Loaded;
m_readyState = MediaPlayer::HaveEnoughData;
} else if (loadState >= QTMovieLoadStatePlaythroughOK) {
- m_readyState = MediaPlayer::HaveFutureData;
+ m_readyState = MediaPlayer::HaveEnoughData;
m_networkState = MediaPlayer::Loading;
} else if (loadState >= QTMovieLoadStatePlayable) {
// FIXME: This might not work correctly in streaming case, <rdar://problem/5693967>
@@ -657,11 +748,17 @@ void MediaPlayerPrivate::updateStates()
m_readyState = MediaPlayer::HaveMetadata;
m_networkState = MediaPlayer::Loading;
} else if (loadState > QTMovieLoadStateError) {
- m_readyState = MediaPlayer::HaveNothing;
+ m_readyState = MediaPlayer::HaveNothing;
m_networkState = MediaPlayer::Loading;
} else {
- float loaded = maxTimeLoaded();
+ if (m_player->inMediaDocument()) {
+ // Something went wrong in the loading of media within a standalone file.
+ // This can occur with chained refmovies pointing to streamed media.
+ sawUnsupportedTracks();
+ return;
+ }
+ float loaded = maxTimeLoaded();
if (!loaded)
m_readyState = MediaPlayer::HaveNothing;
@@ -684,7 +781,7 @@ void MediaPlayerPrivate::updateStates()
if (m_readyState != oldReadyState)
m_player->readyStateChanged();
- if (loadState >= QTMovieLoadStateLoaded && oldReadyState < MediaPlayer::HaveMetadata && m_player->visible())
+ if (loadState >= QTMovieLoadStateLoaded && (!m_qtMovieView && !m_qtVideoRenderer) && m_player->visible())
setUpVideoRendering();
if (loadState >= QTMovieLoadStateLoaded) {
@@ -699,28 +796,39 @@ void MediaPlayerPrivate::updateStates()
void MediaPlayerPrivate::loadStateChanged()
{
- updateStates();
+ if (!m_hasUnsupportedTracks)
+ updateStates();
}
void MediaPlayerPrivate::rateChanged()
{
+ if (m_hasUnsupportedTracks)
+ return;
+
updateStates();
m_player->rateChanged();
}
void MediaPlayerPrivate::sizeChanged()
{
- m_player->sizeChanged();
+ if (!m_hasUnsupportedTracks)
+ m_player->sizeChanged();
}
void MediaPlayerPrivate::timeChanged()
{
+ if (m_hasUnsupportedTracks)
+ return;
+
updateStates();
m_player->timeChanged();
}
void MediaPlayerPrivate::didEnd()
{
+ if (m_hasUnsupportedTracks)
+ return;
+
m_startedPlaying = false;
#if DRAW_FRAME_RATE
m_timeStoppedPlaying = [NSDate timeIntervalSinceReferenceDate];
@@ -729,22 +837,15 @@ void MediaPlayerPrivate::didEnd()
m_player->timeChanged();
}
-void MediaPlayerPrivate::setSize(const IntSize& size)
+void MediaPlayerPrivate::setSize(const IntSize&)
{
- if (!m_qtMovieView)
- return;
-
- m_rect.setSize(size);
- if (m_player->inMediaDocument())
- // We need the QTMovieView to be placed in the proper location for document mode.
- [m_qtMovieView.get() setFrame:m_rect];
- else {
- // We don't really need the QTMovieView in any specific location so let's just get it out of the way
- // where it won't intercept events or try to bring up the context menu.
- IntRect farAwayButCorrectSize(m_rect);
- farAwayButCorrectSize.move(-1000000, -1000000);
- [m_qtMovieView.get() setFrame:farAwayButCorrectSize];
- }
+ // Don't resize the view now because [view setFrame] also resizes the movie itself, and because
+ // the renderer calls this function immediately when we report a size change (QTMovieSizeDidChangeNotification)
+ // we can get into a feedback loop observing the size change and resetting the size, and this can cause
+ // QuickTime to miss resetting a movie's size when the media size changes (as happens with an rtsp movie
+ // once the rtsp server sends the track sizes). Instead we remember the size passed to paint() and resize
+ // the view when it changes.
+ // <rdar://problem/6336092> REGRESSION: rtsp movie does not resize correctly
}
void MediaPlayerPrivate::setVisible(bool b)
@@ -761,6 +862,9 @@ void MediaPlayerPrivate::setVisible(bool b)
void MediaPlayerPrivate::repaint()
{
+ if (m_hasUnsupportedTracks)
+ return;
+
#if DRAW_FRAME_RATE
if (m_startedPlaying) {
m_frameCountWhilePlaying++;
@@ -775,7 +879,7 @@ void MediaPlayerPrivate::repaint()
void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& r)
{
- if (context->paintingDisabled())
+ if (context->paintingDisabled() || m_hasUnsupportedTracks)
return;
NSView *view = m_qtMovieView.get();
id qtVideoRenderer = m_qtVideoRenderer.get();
@@ -802,12 +906,28 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& r)
[(id<WebKitVideoRenderingDetails>)qtVideoRenderer drawInRect:paintRect];
[NSGraphicsContext restoreGraphicsState];
} else {
- if (m_player->inMediaDocument() && r != m_rect) {
- // the QTMovieView needs to be placed in the proper location for document mode
- m_rect = r;
- [view setFrame:m_rect];
+ if (m_rect != r) {
+ m_rect = r;
+ if (m_player->inMediaDocument()) {
+ // the QTMovieView needs to be placed in the proper location for document mode
+ [view setFrame:m_rect];
+ }
+ else {
+ // We don't really need the QTMovieView in any specific location so let's just get it out of the way
+ // where it won't intercept events or try to bring up the context menu.
+ IntRect farAwayButCorrectSize(m_rect);
+ farAwayButCorrectSize.move(-1000000, -1000000);
+ [view setFrame:farAwayButCorrectSize];
+ }
}
- [view displayRectIgnoringOpacity:paintRect inContext:newContext];
+
+ if (m_player->inMediaDocument()) {
+ // If we're using a QTMovieView in a media document, the view may get layer-backed. AppKit won't update
+ // the layer hosting correctly if we call displayRectIgnoringOpacity:inContext:, so use displayRectIgnoringOpacity:
+ // in this case. See <rdar://problem/6702882>.
+ [view displayRectIgnoringOpacity:paintRect];
+ } else
+ [view displayRectIgnoringOpacity:paintRect inContext:newContext];
}
#if DRAW_FRAME_RATE
@@ -839,25 +959,57 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& r)
[m_objcObserver.get() setDelayCallbacks:NO];
}
-static HashSet<String> mimeTypeCache()
+static void addFileTypesToCache(NSArray * fileTypes, HashSet<String> &cache)
+{
+ int count = [fileTypes count];
+ for (int n = 0; n < count; n++) {
+ CFStringRef ext = reinterpret_cast<CFStringRef>([fileTypes objectAtIndex:n]);
+ RetainPtr<CFStringRef> uti(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, ext, NULL));
+ if (!uti)
+ continue;
+ RetainPtr<CFStringRef> mime(AdoptCF, UTTypeCopyPreferredTagWithClass(uti.get(), kUTTagClassMIMEType));
+
+ // UTI types are missing many media related MIME types supported by QTKit, see rdar://6434168,
+ // and not all third party movie importers register their types, so if we didn't find a type for
+ // this extension look it up in the hard coded table in the MIME type regsitry.
+ if (!mime) {
+ // -movieFileTypes: returns both file extensions and OSTypes. The later are surrounded by single
+ // quotes, eg. 'MooV', so don't bother looking at those.
+ if (CFStringGetCharacterAtIndex(ext, 0) != '\'') {
+ String mediaType = MIMETypeRegistry::getMediaMIMETypeForExtension(String(ext));
+ if (!mediaType.isEmpty())
+ mime.adoptCF(mediaType.createCFString());
+ }
+ }
+ if (!mime)
+ continue;
+ cache.add(mime.get());
+ }
+}
+
+static HashSet<String> mimeCommonTypesCache()
{
DEFINE_STATIC_LOCAL(HashSet<String>, cache, ());
static bool typeListInitialized = false;
if (!typeListInitialized) {
+ typeListInitialized = true;
NSArray* fileTypes = [QTMovie movieFileTypes:QTIncludeCommonTypes];
- int count = [fileTypes count];
- for (int n = 0; n < count; n++) {
- CFStringRef ext = reinterpret_cast<CFStringRef>([fileTypes objectAtIndex:n]);
- RetainPtr<CFStringRef> uti(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, ext, NULL));
- if (!uti)
- continue;
- RetainPtr<CFStringRef> mime(AdoptCF, UTTypeCopyPreferredTagWithClass(uti.get(), kUTTagClassMIMEType));
- if (!mime)
- continue;
- cache.add(mime.get());
- }
+ addFileTypesToCache(fileTypes, cache);
+ }
+
+ return cache;
+}
+
+static HashSet<String> mimeModernTypesCache()
+{
+ DEFINE_STATIC_LOCAL(HashSet<String>, cache, ());
+ static bool typeListInitialized = false;
+
+ if (!typeListInitialized) {
typeListInitialized = true;
+ NSArray* fileTypes = [QTMovie movieFileTypes:(QTMovieFileTypeOptions)wkQTIncludeOnlyModernMediaFileTypes()];
+ addFileTypesToCache(fileTypes, cache);
}
return cache;
@@ -865,14 +1017,21 @@ static HashSet<String> mimeTypeCache()
void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& types)
{
- types = mimeTypeCache();
+ // Note: this method starts QTKitServer if it isn't already running when in 64-bit because it has to return the list
+ // of every MIME type supported by QTKit.
+ types = mimeCommonTypesCache();
}
MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs)
{
- // only return "IsSupported" if there is no codecs parameter for now as there is no way to ask QT if it supports an
- // extended MIME type yet
- return mimeTypeCache().contains(type) ? (codecs && !codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported) : MediaPlayer::IsNotSupported;
+ // Only return "IsSupported" if there is no codecs parameter for now as there is no way to ask QT if it supports an
+ // extended MIME type yet.
+
+ // We check the "modern" type cache first, as it doesn't require QTKitServer to start.
+ if (mimeModernTypesCache().contains(type) || mimeCommonTypesCache().contains(type))
+ return (codecs && !codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported);
+
+ return MediaPlayer::IsNotSupported;
}
bool MediaPlayerPrivate::isAvailable()
@@ -900,6 +1059,7 @@ void MediaPlayerPrivate::disableUnsupportedTracks()
{
if (!m_qtMovie) {
m_enabledTrackCount = 0;
+ m_totalTrackCount = 0;
return;
}
@@ -911,15 +1071,19 @@ void MediaPlayerPrivate::disableUnsupportedTracks()
allowedTrackTypes->add(QTMediaTypeText);
allowedTrackTypes->add(QTMediaTypeBase);
allowedTrackTypes->add(QTMediaTypeMPEG);
- allowedTrackTypes->add("clcp");
- allowedTrackTypes->add("sbtl");
+ allowedTrackTypes->add("clcp"); // Closed caption
+ allowedTrackTypes->add("sbtl"); // Subtitle
+ allowedTrackTypes->add("odsm"); // MPEG-4 object descriptor stream
+ allowedTrackTypes->add("sdsm"); // MPEG-4 scene description stream
+ allowedTrackTypes->add("tmcd"); // timecode
+ allowedTrackTypes->add("tc64"); // timcode-64
}
NSArray *tracks = [m_qtMovie.get() tracks];
- unsigned trackCount = [tracks count];
- m_enabledTrackCount = trackCount;
- for (unsigned trackIndex = 0; trackIndex < trackCount; trackIndex++) {
+ m_totalTrackCount = [tracks count];
+ m_enabledTrackCount = m_totalTrackCount;
+ for (unsigned trackIndex = 0; trackIndex < m_totalTrackCount; trackIndex++) {
// Grab the track at the current index. If there isn't one there, then
// we can move onto the next one.
QTTrack *track = [tracks objectAtIndex:trackIndex];
@@ -931,24 +1095,18 @@ void MediaPlayerPrivate::disableUnsupportedTracks()
if (![track isEnabled])
continue;
- // Grab the track's media. We're going to check to see if we need to
- // disable the tracks. They could be unsupported.
- QTMedia *trackMedia = [track media];
- if (!trackMedia)
- continue;
-
- // Grab the media type for this track.
- NSString *mediaType = [trackMedia attributeForKey:QTMediaTypeAttribute];
+ // Get the track's media type.
+ NSString *mediaType = [track attributeForKey:QTTrackMediaTypeAttribute];
if (!mediaType)
continue;
-
+
// Test whether the media type is in our white list.
if (!allowedTrackTypes->contains(mediaType)) {
// If this track type is not allowed, then we need to disable it.
[track setEnabled:NO];
--m_enabledTrackCount;
}
-
+
// Disable chapter tracks. These are most likely to lead to trouble, as
// they will be composited under the video tracks, forcing QT to do extra
// work.
@@ -982,6 +1140,12 @@ void MediaPlayerPrivate::disableUnsupportedTracks()
}
}
+void MediaPlayerPrivate::sawUnsupportedTracks()
+{
+ m_hasUnsupportedTracks = true;
+ m_player->mediaPlayerClient()->mediaPlayerSawUnsupportedTracks(m_player);
+}
+
}
@implementation WebCoreMovieObserver
diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
index a3c10fa..cdde7cf 100644
--- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
+++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
@@ -58,7 +58,7 @@ static inline float scaleEmToUnits(float x, unsigned unitsPerEm) { return x * (c
static bool initFontData(SimpleFontData* fontData)
{
- if (!fontData->m_font.cgFont())
+ if (!fontData->platformData().cgFont())
return false;
#ifdef BUILDING_ON_TIGER
@@ -66,7 +66,7 @@ static bool initFontData(SimpleFontData* fontData)
if (ATSUCreateStyle(&fontStyle) != noErr)
return false;
- ATSUFontID fontId = fontData->m_font.m_atsuFontID;
+ ATSUFontID fontId = fontData->platformData().m_atsuFontID;
if (!fontId) {
ATSUDisposeStyle(fontStyle);
return false;
@@ -153,7 +153,7 @@ void SimpleFontData::platformInit()
m_shapesArabic = false;
#endif
- m_syntheticBoldOffset = m_font.m_syntheticBold ? 1.0f : 0.f;
+ m_syntheticBoldOffset = m_platformData.m_syntheticBold ? 1.0f : 0.f;
bool failedSetup = false;
if (!initFontData(this)) {
@@ -165,7 +165,7 @@ void SimpleFontData::platformInit()
// It overrides the normal "Times" family font.
// It also appears to have a corrupt regular variant.
NSString *fallbackFontFamily;
- if ([[m_font.font() familyName] isEqual:@"Times"])
+ if ([[m_platformData.font() familyName] isEqual:@"Times"])
fallbackFontFamily = @"Times New Roman";
else
fallbackFontFamily = webFallbackFontFamily();
@@ -173,12 +173,12 @@ void SimpleFontData::platformInit()
// Try setting up the alternate font.
// This is a last ditch effort to use a substitute font when something has gone wrong.
#if !ERROR_DISABLED
- RetainPtr<NSFont> initialFont = m_font.font();
+ RetainPtr<NSFont> initialFont = m_platformData.font();
#endif
- if (m_font.font())
- m_font.setFont([[NSFontManager sharedFontManager] convertFont:m_font.font() toFamily:fallbackFontFamily]);
+ if (m_platformData.font())
+ m_platformData.setFont([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toFamily:fallbackFontFamily]);
else
- m_font.setFont([NSFont fontWithName:fallbackFontFamily size:m_font.size()]);
+ m_platformData.setFont([NSFont fontWithName:fallbackFontFamily size:m_platformData.size()]);
#if !ERROR_DISABLED
NSString *filePath = pathFromFont(initialFont.get());
if (!filePath)
@@ -188,7 +188,7 @@ void SimpleFontData::platformInit()
if ([fallbackFontFamily isEqual:@"Times New Roman"]) {
// OK, couldn't setup Times New Roman as an alternate to Times, fallback
// on the system font. If this fails we have no alternative left.
- m_font.setFont([[NSFontManager sharedFontManager] convertFont:m_font.font() toFamily:webFallbackFontFamily()]);
+ m_platformData.setFont([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toFamily:webFallbackFontFamily()]);
if (!initFontData(this)) {
// We tried, Times, Times New Roman, and the system font. No joy. We have to give up.
LOG_ERROR("unable to initialize with font %@ at %@", initialFont.get(), filePath);
@@ -203,14 +203,14 @@ void SimpleFontData::platformInit()
// Report the problem.
LOG_ERROR("Corrupt font detected, using %@ in place of %@ located at \"%@\".",
- [m_font.font() familyName], [initialFont.get() familyName], filePath);
+ [m_platformData.font() familyName], [initialFont.get() familyName], filePath);
}
// If all else fails, try to set up using the system font.
// This is probably because Times and Times New Roman are both unavailable.
if (failedSetup) {
- m_font.setFont([NSFont systemFontOfSize:[m_font.font() pointSize]]);
- LOG_ERROR("failed to set up font, using system font %s", m_font.font());
+ m_platformData.setFont([NSFont systemFontOfSize:[m_platformData.font() pointSize]]);
+ LOG_ERROR("failed to set up font, using system font %s", m_platformData.font());
initFontData(this);
}
@@ -218,15 +218,15 @@ void SimpleFontData::platformInit()
int iDescent;
int iLineGap;
#ifdef BUILDING_ON_TIGER
- wkGetFontMetrics(m_font.cgFont(), &iAscent, &iDescent, &iLineGap, &m_unitsPerEm);
+ wkGetFontMetrics(m_platformData.cgFont(), &iAscent, &iDescent, &iLineGap, &m_unitsPerEm);
#else
- iAscent = CGFontGetAscent(m_font.cgFont());
- iDescent = CGFontGetDescent(m_font.cgFont());
- iLineGap = CGFontGetLeading(m_font.cgFont());
- m_unitsPerEm = CGFontGetUnitsPerEm(m_font.cgFont());
+ iAscent = CGFontGetAscent(m_platformData.cgFont());
+ iDescent = CGFontGetDescent(m_platformData.cgFont());
+ iLineGap = CGFontGetLeading(m_platformData.cgFont());
+ m_unitsPerEm = CGFontGetUnitsPerEm(m_platformData.cgFont());
#endif
- float pointSize = m_font.m_size;
+ 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;
@@ -236,7 +236,7 @@ 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.
- NSString *familyName = [m_font.font() familyName];
+ NSString *familyName = [m_platformData.font() familyName];
if ([familyName isEqualToString:@"Times"] || [familyName isEqualToString:@"Helvetica"] || [familyName isEqualToString:@"Courier"])
fAscent += floorf(((fAscent + fDescent) * 0.15f) + 0.5f);
else if ([familyName isEqualToString:@"Geeza Pro"]) {
@@ -264,14 +264,49 @@ void SimpleFontData::platformInit()
GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
NSGlyph xGlyph = glyphPageZero ? glyphPageZero->glyphDataForCharacter('x').glyph : 0;
if (xGlyph) {
- NSRect xBox = [m_font.font() boundingRectForGlyph:xGlyph];
+ NSRect xBox = [m_platformData.font() boundingRectForGlyph:xGlyph];
// Use the maximum of either width or height because "x" is nearly square
// and web pages that foolishly use this metric for width will be laid out
// poorly if we return an accurate height. Classic case is Times 13 point,
// which has an "x" that is 7x6 pixels.
m_xHeight = MAX(NSMaxX(xBox), NSMaxY(xBox));
} else
- m_xHeight = [m_font.font() xHeight];
+ m_xHeight = [m_platformData.font() xHeight];
+}
+
+void SimpleFontData::platformCharWidthInit()
+{
+ m_avgCharWidth = 0.f;
+
+ // Calculate avgCharWidth according to http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6OS2.html
+ // We can try grabbing it out of the OS/2 table or via ATSFontGetHorizontalMetrics, but
+ // ATSFontGetHorizontalMetrics never seems to return a non-zero value and the OS/2 table
+ // contains zero for a large number of fonts.
+ GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
+ if (glyphPageZero) {
+ static int weights[] = { 64, 14, 27, 35, 100, 20, 14, 42, 63, 3, 6, 35, 20, 56, 56, 17, 4, 49, 56, 71, 31, 10, 18, 3, 18, 2, 166 };
+ int numGlyphs = 27;
+ ASSERT(numGlyphs == sizeof(weights) / sizeof(int));
+ // Compute the weighted sum of the space character and the lowercase letters in the Latin alphabet.
+ float sum = 0.f;
+ int totalWeight = 0;
+ for (int i = 0; i < numGlyphs; i++) {
+ Glyph glyph = glyphPageZero->glyphDataForCharacter((i < 26 ? i + 'a' : ' ')).glyph;
+ if (glyph) {
+ totalWeight += weights[i];
+ sum += widthForGlyph(glyph) * weights[i];
+ }
+ }
+ if (sum > 0.f && totalWeight > 0)
+ m_avgCharWidth = sum / totalWeight;
+ }
+
+ m_maxCharWidth = 0.f;
+ if (m_platformData.font())
+ m_maxCharWidth = [m_platformData.font() maximumAdvancement].width;
+
+ // Fallback to a cross-platform estimate, which will populate these values if they are non-positive.
+ initCharWidths();
}
void SimpleFontData::platformDestroy()
@@ -290,13 +325,13 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes
{
if (!m_smallCapsFontData) {
if (isCustomFont()) {
- FontPlatformData smallCapsFontData(m_font);
+ FontPlatformData smallCapsFontData(m_platformData);
smallCapsFontData.m_size = smallCapsFontData.m_size * smallCapsFontSizeMultiplier;
m_smallCapsFontData = new SimpleFontData(smallCapsFontData, true, false);
} else {
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- float size = [m_font.font() pointSize] * smallCapsFontSizeMultiplier;
- FontPlatformData smallCapsFont([[NSFontManager sharedFontManager] convertFont:m_font.font() toSize:size]);
+ float size = [m_platformData.font() pointSize] * smallCapsFontSizeMultiplier;
+ FontPlatformData smallCapsFont([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toSize:size]);
// AppKit resets the type information (screen/printer) when you convert a font to a different size.
// We have to fix up the font that we're handed back.
@@ -304,11 +339,11 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes
if (smallCapsFont.font()) {
NSFontManager *fontManager = [NSFontManager sharedFontManager];
- NSFontTraitMask fontTraits = [fontManager traitsOfFont:m_font.font()];
+ NSFontTraitMask fontTraits = [fontManager traitsOfFont:m_platformData.font()];
- if (m_font.m_syntheticBold)
+ if (m_platformData.m_syntheticBold)
fontTraits |= NSBoldFontMask;
- if (m_font.m_syntheticOblique)
+ if (m_platformData.m_syntheticOblique)
fontTraits |= NSItalicFontMask;
NSFontTraitMask smallCapsFontTraits = [fontManager traitsOfFont:smallCapsFont.font()];
@@ -326,7 +361,7 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes
bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
{
NSString *string = [[NSString alloc] initWithCharactersNoCopy:const_cast<unichar*>(characters) length:length freeWhenDone:NO];
- NSCharacterSet *set = [[m_font.font() coveredCharacterSet] invertedSet];
+ NSCharacterSet *set = [[m_platformData.font() coveredCharacterSet] invertedSet];
bool result = set && [string rangeOfCharacterFromSet:set].location == NSNotFound;
[string release];
return result;
@@ -334,7 +369,7 @@ bool SimpleFontData::containsCharacters(const UChar* characters, int length) con
void SimpleFontData::determinePitch()
{
- NSFont* f = m_font.font();
+ NSFont* f = m_platformData.font();
// Special case Osaka-Mono.
// According to <rdar://problem/3999467>, we should treat Osaka-Mono as fixed pitch.
// Note that the AppKit does not report Osaka-Mono as fixed pitch.
@@ -356,11 +391,11 @@ void SimpleFontData::determinePitch()
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
- NSFont* font = m_font.font();
- float pointSize = m_font.m_size;
+ NSFont* font = m_platformData.font();
+ float pointSize = m_platformData.m_size;
CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize);
CGSize advance;
- if (!wkGetGlyphTransformedAdvances(m_font.cgFont(), font, &m, &glyph, &advance)) {
+ if (!wkGetGlyphTransformedAdvances(m_platformData.cgFont(), font, &m, &glyph, &advance)) {
LOG_ERROR("Unable to cache glyph widths for %@ %f", [font displayName], pointSize);
advance.width = 0;
}
@@ -374,9 +409,9 @@ void SimpleFontData::checkShapesArabic() const
m_checkedShapesArabic = true;
- ATSUFontID fontID = m_font.m_atsuFontID;
+ ATSUFontID fontID = m_platformData.m_atsuFontID;
if (!fontID) {
- LOG_ERROR("unable to get ATSUFontID for %@", m_font.font());
+ LOG_ERROR("unable to get ATSUFontID for %@", m_platformData.font());
return;
}
@@ -404,7 +439,7 @@ CTFontRef SimpleFontData::getCTFont() const
if (getNSFont())
return toCTFontRef(getNSFont());
if (!m_CTFont)
- m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_font.cgFont(), m_font.size(), NULL, NULL));
+ m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_platformData.cgFont(), m_platformData.size(), NULL, NULL));
return m_CTFont.get();
}
diff --git a/WebCore/platform/graphics/mac/WebLayer.mm b/WebCore/platform/graphics/mac/WebLayer.mm
index 267b5bc..fad3916 100644
--- a/WebCore/platform/graphics/mac/WebLayer.mm
+++ b/WebCore/platform/graphics/mac/WebLayer.mm
@@ -32,7 +32,6 @@
#import "GraphicsContext.h"
#import "GraphicsLayer.h"
#import <QuartzCore/QuartzCore.h>
-#import "WebCoreTextRenderer.h"
#import <wtf/UnusedParam.h>
using namespace WebCore;
diff --git a/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp b/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp
index 16c3c00..895887f 100644
--- a/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp
+++ b/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -161,11 +161,21 @@ struct nameTable {
#pragma pack()
-static void appendBigEndianStringToEOTHeader(Vector<uint8_t, 512>& eotHeader, const BigEndianUShort* string, unsigned short length)
+EOTHeader::EOTHeader()
{
- size_t size = eotHeader.size();
- eotHeader.resize(size + length + 2 * sizeof(unsigned short));
- UChar* dst = reinterpret_cast<UChar*>(eotHeader.data() + size);
+ m_buffer.resize(sizeof(EOTPrefix));
+}
+
+void EOTHeader::updateEOTSize(size_t fontDataSize)
+{
+ prefix()->eotSize = m_buffer.size() + fontDataSize;
+}
+
+void EOTHeader::appendBigEndianString(const BigEndianUShort* string, unsigned short length)
+{
+ size_t oldSize = m_buffer.size();
+ m_buffer.resize(oldSize + length + 2 * sizeof(unsigned short));
+ UChar* dst = reinterpret_cast<UChar*>(m_buffer.data() + oldSize);
unsigned i = 0;
dst[i++] = length;
unsigned numCharacters = length / 2;
@@ -174,7 +184,13 @@ static void appendBigEndianStringToEOTHeader(Vector<uint8_t, 512>& eotHeader, co
dst[i] = 0;
}
-bool getEOTHeader(SharedBuffer* fontData, Vector<uint8_t, 512>& eotHeader, size_t& overlayDst, size_t& overlaySrc, size_t& overlayLength)
+void EOTHeader::appendPaddingShort()
+{
+ unsigned short padding = 0;
+ m_buffer.append(reinterpret_cast<uint8_t*>(&padding), sizeof(padding));
+}
+
+bool getEOTHeader(SharedBuffer* fontData, EOTHeader& eotHeader, size_t& overlayDst, size_t& overlaySrc, size_t& overlayLength)
{
overlayDst = 0;
overlaySrc = 0;
@@ -183,8 +199,7 @@ bool getEOTHeader(SharedBuffer* fontData, Vector<uint8_t, 512>& eotHeader, size_
size_t dataLength = fontData->size();
const char* data = fontData->data();
- eotHeader.resize(sizeof(EOTPrefix));
- EOTPrefix* prefix = reinterpret_cast<EOTPrefix*>(eotHeader.data());
+ EOTPrefix* prefix = eotHeader.prefix();
prefix->fontDataSize = dataLength;
prefix->version = 0x00020001;
@@ -306,9 +321,9 @@ bool getEOTHeader(SharedBuffer* fontData, Vector<uint8_t, 512>& eotHeader, size_
prefix->reserved[3] = 0;
prefix->padding1 = 0;
- appendBigEndianStringToEOTHeader(eotHeader, familyName, familyNameLength);
- appendBigEndianStringToEOTHeader(eotHeader, subfamilyName, subfamilyNameLength);
- appendBigEndianStringToEOTHeader(eotHeader, versionString, versionStringLength);
+ eotHeader.appendBigEndianString(familyName, familyNameLength);
+ eotHeader.appendBigEndianString(subfamilyName, subfamilyNameLength);
+ eotHeader.appendBigEndianString(versionString, versionStringLength);
// If possible, ensure that the family name is a prefix of the full name.
if (fullNameLength >= familyNameLength && memcmp(familyName, fullName, familyNameLength)) {
@@ -316,13 +331,10 @@ bool getEOTHeader(SharedBuffer* fontData, Vector<uint8_t, 512>& eotHeader, size_
overlayDst = reinterpret_cast<const char*>(familyName) - data;
overlayLength = familyNameLength;
}
+ eotHeader.appendBigEndianString(fullName, fullNameLength);
- appendBigEndianStringToEOTHeader(eotHeader, fullName, fullNameLength);
-
- unsigned short padding = 0;
- eotHeader.append(reinterpret_cast<uint8_t*>(&padding), sizeof(padding));
-
- prefix->eotSize = eotHeader.size() + fontData->size();
+ eotHeader.appendPaddingShort();
+ eotHeader.updateEOTSize(fontData->size());
return true;
}
diff --git a/WebCore/platform/graphics/opentype/OpenTypeUtilities.h b/WebCore/platform/graphics/opentype/OpenTypeUtilities.h
index a67ffc7..13dad6f 100644
--- a/WebCore/platform/graphics/opentype/OpenTypeUtilities.h
+++ b/WebCore/platform/graphics/opentype/OpenTypeUtilities.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,9 +31,26 @@
namespace WebCore {
+struct BigEndianUShort;
+struct EOTPrefix;
class SharedBuffer;
-bool getEOTHeader(SharedBuffer* fontData, Vector<uint8_t, 512>& eotHeader, size_t& overlayDst, size_t& overlaySrc, size_t& overlayLength);
+struct EOTHeader {
+ EOTHeader();
+
+ size_t size() const { return m_buffer.size(); }
+ const uint8_t* data() const { return m_buffer.data(); }
+
+ EOTPrefix* prefix() { return reinterpret_cast<EOTPrefix*>(m_buffer.data()); }
+ void updateEOTSize(size_t);
+ void appendBigEndianString(const BigEndianUShort*, unsigned short length);
+ void appendPaddingShort();
+
+private:
+ Vector<uint8_t, 512> m_buffer;
+};
+
+bool getEOTHeader(SharedBuffer* fontData, EOTHeader& eotHeader, size_t& overlayDst, size_t& overlaySrc, size_t& overlayLength);
HANDLE renameAndActivateFont(SharedBuffer*, const String&);
} // namespace WebCore
diff --git a/WebCore/platform/graphics/qt/FontCacheQt.cpp b/WebCore/platform/graphics/qt/FontCacheQt.cpp
index 114f073..668912e 100644
--- a/WebCore/platform/graphics/qt/FontCacheQt.cpp
+++ b/WebCore/platform/graphics/qt/FontCacheQt.cpp
@@ -26,8 +26,11 @@
#include "FontDescription.h"
#include "FontPlatformData.h"
#include "Font.h"
+#include "StringHash.h"
#include <wtf/StdLibExtras.h>
+#include <QHash>
+
namespace WebCore {
FontCache* fontCache()
@@ -44,9 +47,31 @@ void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigne
{
}
+typedef QHash<FontDescription, FontPlatformData*> FontPlatformDataCache;
+
+// using Q_GLOBAL_STATIC leads to crash. TODO investigate the way to fix this.
+static FontPlatformDataCache* gFontPlatformDataCache;
+
+uint qHash(const FontDescription& key)
+{
+ uint value = CaseFoldingHash::hash(key.family().family());
+ value ^= key.computedPixelSize();
+ value ^= static_cast<int>(key.weight());
+ return value;
+}
+
FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& description, const AtomicString& family, bool checkingAlternateName)
{
- return new FontPlatformData(description);
+ if (!gFontPlatformDataCache)
+ gFontPlatformDataCache = new FontPlatformDataCache;
+
+ FontPlatformData* fontData = gFontPlatformDataCache->value(description, 0);
+ if (!fontData) {
+ fontData = new FontPlatformData(description);
+ gFontPlatformDataCache->insert(description, fontData);
+ }
+
+ return fontData;
}
SimpleFontData* FontCache::getCachedFontData(const FontPlatformData*)
@@ -71,4 +96,12 @@ void FontCache::removeClient(FontSelector*)
{
}
+void FontCache::invalidate()
+{
+ if (!gFontPlatformDataCache)
+ return;
+
+ gFontPlatformDataCache->clear();
+}
+
} // namespace WebCore
diff --git a/WebCore/platform/graphics/qt/FontFallbackListQt.cpp b/WebCore/platform/graphics/qt/FontFallbackListQt.cpp
index 22ae205..50627b7 100644
--- a/WebCore/platform/graphics/qt/FontFallbackListQt.cpp
+++ b/WebCore/platform/graphics/qt/FontFallbackListQt.cpp
@@ -42,8 +42,6 @@ FontFallbackList::FontFallbackList()
void FontFallbackList::invalidate(WTF::PassRefPtr<WebCore::FontSelector> fontSelector)
{
- releaseFontData();
- m_fontList.clear();
m_familyIndex = 0;
m_pitch = UnknownPitch;
m_loadingCustomFonts = false;
@@ -53,6 +51,9 @@ void FontFallbackList::invalidate(WTF::PassRefPtr<WebCore::FontSelector> fontSel
void FontFallbackList::releaseFontData()
{
+ if (m_fontList.size())
+ delete m_fontList[0].first;
+ m_fontList.clear();
}
void FontFallbackList::determinePitch(const WebCore::Font* font) const
@@ -90,7 +91,12 @@ const FontData* FontFallbackList::fontDataAt(const WebCore::Font* _font, unsigne
family = family->next();
}
- return new SimpleFontData(FontPlatformData(description), _font->wordSpacing(), _font->letterSpacing());
+ if (m_fontList.size())
+ return m_fontList[0].first;
+
+ const FontData* result = new SimpleFontData(FontPlatformData(description), _font->wordSpacing(), _font->letterSpacing());
+ m_fontList.append(pair<const FontData*, bool>(result, result->isCustomFont()));
+ return result;
}
const FontData* FontFallbackList::fontDataForCharacters(const WebCore::Font* font, const UChar*, int) const
diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp
index 9ed5915..5a4b7b2 100644
--- a/WebCore/platform/graphics/qt/FontQt.cpp
+++ b/WebCore/platform/graphics/qt/FontQt.cpp
@@ -183,7 +183,7 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float
p->drawText(pt, string, flags, run.padding());
}
-float Font::floatWidthForComplexText(const TextRun& run) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*) const
{
if (!run.length())
return 0;
diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index ccf4b06..ed7ac47 100644
--- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -99,7 +99,7 @@ static inline QPainter::CompositionMode toQtCompositionMode(CompositeOperator op
case CompositeHighlight:
return QPainter::CompositionMode_SourceOver;
case CompositePlusLighter:
- return QPainter::CompositionMode_SourceOver;
+ return QPainter::CompositionMode_Plus;
}
return QPainter::CompositionMode_SourceOver;
@@ -153,6 +153,18 @@ static Qt::PenStyle toQPenStyle(StrokeStyle style)
return Qt::NoPen;
}
+static inline Qt::FillRule toQtFillRule(WindRule rule)
+{
+ switch(rule) {
+ case RULE_EVENODD:
+ return Qt::OddEvenFill;
+ case RULE_NONZERO:
+ return Qt::WindingFill;
+ }
+ qDebug("Qt: unrecognized wind rule!");
+ return Qt::OddEvenFill;
+}
+
struct TransparencyLayer
{
TransparencyLayer(const QPainter* p, const QRect &rect)
@@ -563,7 +575,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
QPainter *p = m_data->p();
const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
- p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines);
+ p->setRenderHint(QPainter::Antialiasing, true);
p->drawArc(rect, startAngle * 16, angleSpan * 16);
@@ -606,6 +618,7 @@ void GraphicsContext::fillPath()
QPainter *p = m_data->p();
QPainterPath path = m_data->currentPath;
+ path.setFillRule(toQtFillRule(fillRule()));
switch (m_common->state.fillColorSpace) {
case SolidColorSpace:
@@ -634,6 +647,7 @@ void GraphicsContext::strokePath()
QPainter *p = m_data->p();
QPen pen = p->pen();
QPainterPath path = m_data->currentPath;
+ path.setFillRule(toQtFillRule(fillRule()));
switch (m_common->state.strokeColorSpace) {
case SolidColorSpace:
@@ -1097,7 +1111,13 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect,
rect.width() - (thickness * 2), rect.height() - (thickness * 2)));
path.setFillRule(Qt::OddEvenFill);
- m_data->p()->setClipPath(path, Qt::IntersectClip);
+
+ QPainter *p = m_data->p();
+
+ const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
+ p->setRenderHint(QPainter::Antialiasing, true);
+ p->setClipPath(path, Qt::IntersectClip);
+ p->setRenderHint(QPainter::Antialiasing, antiAlias);
}
void GraphicsContext::concatCTM(const TransformationMatrix& transform)
diff --git a/WebCore/platform/graphics/qt/IconQt.cpp b/WebCore/platform/graphics/qt/IconQt.cpp
index b04668c..c9f3ced 100644
--- a/WebCore/platform/graphics/qt/IconQt.cpp
+++ b/WebCore/platform/graphics/qt/IconQt.cpp
@@ -24,7 +24,6 @@
#include "GraphicsContext.h"
#include "PlatformString.h"
#include "IntRect.h"
-#include "NotImplemented.h"
#include <qpainter.h>
#include <qpixmap.h>
diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
index d748305..506a8ea 100644
--- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
@@ -47,7 +47,24 @@ ImageBufferData::ImageBufferData(const IntSize& size)
: m_pixmap(size)
{
m_pixmap.fill(QColor(Qt::transparent));
- m_painter.set(new QPainter(&m_pixmap));
+
+ QPainter* painter = new QPainter(&m_pixmap);
+ m_painter.set(painter);
+
+ // Since ImageBuffer is used mainly for Canvas, explicitly initialize
+ // its painter's pen and brush with the corresponding canvas defaults
+ // NOTE: keep in sync with CanvasRenderingContext2D::State
+ QPen pen = painter->pen();
+ pen.setColor(Qt::black);
+ pen.setWidth(1);
+ pen.setCapStyle(Qt::FlatCap);
+ pen.setJoinStyle(Qt::MiterJoin);
+ pen.setMiterLimit(10);
+ painter->setPen(pen);
+ QBrush brush = painter->brush();
+ brush.setColor(Qt::black);
+ painter->setBrush(brush);
+ painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
}
ImageBuffer::ImageBuffer(const IntSize& size, bool grayScale, bool& success)
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
index 394c7a7..cd32428 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
@@ -197,7 +197,8 @@ ImageDecoderQt* ImageDecoderQt::create(const SharedBuffer& data)
}
ImageDecoderQt::ImageDecoderQt(const QString &imageFormat)
- : m_imageFormat(imageFormat)
+ : m_hasAlphaChannel(false)
+ , m_imageFormat(imageFormat)
{
}
@@ -212,6 +213,7 @@ bool ImageDecoderQt::hasFirstImageHeader() const
void ImageDecoderQt::reset()
{
+ m_hasAlphaChannel = false;
m_failed = false;
m_imageList.clear();
m_pixmapCache.clear();
@@ -230,6 +232,9 @@ void ImageDecoderQt::setData(const IncomingData &data, bool allDataReceived)
const ReadContext::ReadResult readResult = readContext.read(allDataReceived);
+ if (hasFirstImageHeader())
+ m_hasAlphaChannel = m_imageList[0].m_image.hasAlphaChannel();
+
if (debugImageDecoderQt)
qDebug() << " read returns " << readResult;
@@ -280,7 +285,7 @@ int ImageDecoderQt::repetitionCount() const
bool ImageDecoderQt::supportsAlpha() const
{
- return hasFirstImageHeader() && m_imageList[0].m_image.hasAlphaChannel();
+ return m_hasAlphaChannel;
}
int ImageDecoderQt::duration(size_t index) const
@@ -314,6 +319,10 @@ QPixmap* ImageDecoderQt::imageAtIndex(size_t index) const
if (!m_pixmapCache.contains(index)) {
m_pixmapCache.insert(index,
QPixmap::fromImage(m_imageList[index].m_image));
+
+ // store null image since the converted pixmap is already in pixmap cache
+ Q_ASSERT(m_imageList[index].m_imageState == ImageComplete);
+ m_imageList[index].m_image = QImage();
}
return &m_pixmapCache[index];
}
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.h b/WebCore/platform/graphics/qt/ImageDecoderQt.h
index a2eb6aa..b8c3edd 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.h
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.h
@@ -81,8 +81,9 @@ private:
int m_duration;
};
+ bool m_hasAlphaChannel;
typedef QList<ImageData> ImageList;
- ImageList m_imageList;
+ mutable ImageList m_imageList;
mutable QHash<int, QPixmap> m_pixmapCache;
int m_loopCount;
QString m_imageFormat;
diff --git a/WebCore/platform/graphics/qt/ImageQt.cpp b/WebCore/platform/graphics/qt/ImageQt.cpp
index 3bc67ae..a2e96f3 100644
--- a/WebCore/platform/graphics/qt/ImageQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageQt.cpp
@@ -31,12 +31,12 @@
#include "config.h"
#include "Image.h"
+#include "ImageObserver.h"
#include "BitmapImage.h"
#include "FloatRect.h"
#include "PlatformString.h"
#include "GraphicsContext.h"
#include "TransformationMatrix.h"
-#include "NotImplemented.h"
#include "StillImageQt.h"
#include "qwebsettings.h"
@@ -117,6 +117,9 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
p->setBrushOrigin(phase);
p->fillRect(destRect, b);
ctxt->restore();
+
+ if (imageObserver())
+ imageObserver()->didDraw(this);
}
void BitmapImage::initPlatformData()
@@ -159,6 +162,9 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
painter->drawPixmap(dst, *image, src);
ctxt->restore();
+
+ if (imageObserver())
+ imageObserver()->didDraw(this);
}
void BitmapImage::checkForSolidColor()
diff --git a/WebCore/platform/graphics/qt/ImageSourceQt.cpp b/WebCore/platform/graphics/qt/ImageSourceQt.cpp
index 84de443..621728e 100644
--- a/WebCore/platform/graphics/qt/ImageSourceQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageSourceQt.cpp
@@ -29,7 +29,6 @@
#include "config.h"
#include "ImageSource.h"
#include "ImageDecoderQt.h"
-#include "NotImplemented.h"
#include "SharedBuffer.h"
#include <QBuffer>
diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp
index a8a3ea2..7569031 100644
--- a/WebCore/platform/graphics/qt/PathQt.cpp
+++ b/WebCore/platform/graphics/qt/PathQt.cpp
@@ -39,6 +39,7 @@
#include <QPainterPath>
#include <QTransform>
#include <QString>
+#include <wtf/OwnPtr.h>
#define _USE_MATH_DEFINES
#include <math.h>
@@ -91,7 +92,7 @@ bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point)
// FIXME: We should try to use a 'shared Context' instead of creating a new ImageBuffer
// on each call.
- std::auto_ptr<ImageBuffer> scratchImage = ImageBuffer::create(IntSize(1, 1), false);
+ OwnPtr<ImageBuffer> scratchImage = ImageBuffer::create(IntSize(1, 1), false);
GraphicsContext* gc = scratchImage->context();
QPainterPathStroker stroke;
applier->strokeStyle(gc);
@@ -123,7 +124,7 @@ FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
{
// FIXME: We should try to use a 'shared Context' instead of creating a new ImageBuffer
// on each call.
- std::auto_ptr<ImageBuffer> scratchImage = ImageBuffer::create(IntSize(1, 1), false);
+ OwnPtr<ImageBuffer> scratchImage = ImageBuffer::create(IntSize(1, 1), false);
GraphicsContext* gc = scratchImage->context();
QPainterPathStroker stroke;
if (applier) {
diff --git a/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp b/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
index 6cf4e55..f823f84 100644
--- a/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
+++ b/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
@@ -30,7 +30,7 @@ namespace WebCore {
void SimpleFontData::determinePitch()
{
- m_treatAsFixedPitch = m_font.font().fixedPitch();
+ m_treatAsFixedPitch = m_platformData.font().fixedPitch();
}
bool SimpleFontData::containsCharacters(const UChar*, int length) const
@@ -40,7 +40,7 @@ bool SimpleFontData::containsCharacters(const UChar*, int length) const
void SimpleFontData::platformInit()
{
- QFontMetrics fm(m_font.font());
+ QFontMetrics fm(m_platformData.font());
m_ascent = fm.ascent();
m_descent = fm.descent();
@@ -59,6 +59,13 @@ void SimpleFontData::platformGlyphInit()
m_missingGlyphData.glyph = 0;
}
+void SimpleFontData::platformCharWidthInit()
+{
+ QFontMetrics fm(m_platformData.font());
+ m_avgCharWidth = fm.averageCharWidth();
+ m_maxCharWidth = fm.maxWidth();
+}
+
void SimpleFontData::platformDestroy()
{
}
diff --git a/WebCore/platform/graphics/skia/GradientSkia.cpp b/WebCore/platform/graphics/skia/GradientSkia.cpp
index 2d2000c..ac7366c 100644
--- a/WebCore/platform/graphics/skia/GradientSkia.cpp
+++ b/WebCore/platform/graphics/skia/GradientSkia.cpp
@@ -60,12 +60,14 @@ static SkColor makeSkColor(float a, float r, float g, float b)
// ends as necessary.
static size_t totalStopsNeeded(const Gradient::ColorStop* stopData, size_t count)
{
+ // N.B.: The tests in this function should kept in sync with the ones in
+ // fillStops(), or badness happens.
const Gradient::ColorStop* stop = stopData;
size_t countUsed = count;
if (count < 1 || stop->stop > 0.0)
countUsed++;
stop += count - 1;
- if (count < 2 || stop->stop < 1.0)
+ if (count < 1 || stop->stop < 1.0)
countUsed++;
return countUsed;
}
diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
index 376fa4b..33ca23a 100644
--- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
@@ -449,10 +449,8 @@ void GraphicsContext::drawConvexPolygon(size_t numPoints,
return;
SkPaint paint;
- if (fillColor().alpha() > 0) {
- platformContext()->setupPaintForFilling(&paint);
- platformContext()->canvas()->drawPath(path, paint);
- }
+ platformContext()->setupPaintForFilling(&paint);
+ platformContext()->canvas()->drawPath(path, paint);
if (strokeStyle() != NoStroke) {
paint.reset();
@@ -472,10 +470,8 @@ void GraphicsContext::drawEllipse(const IntRect& elipseRect)
return;
SkPaint paint;
- if (fillColor().alpha() > 0) {
- platformContext()->setupPaintForFilling(&paint);
- platformContext()->canvas()->drawOval(rect, paint);
- }
+ platformContext()->setupPaintForFilling(&paint);
+ platformContext()->canvas()->drawOval(rect, paint);
if (strokeStyle() != NoStroke) {
paint.reset();
@@ -685,9 +681,6 @@ void GraphicsContext::fillPath()
const GraphicsContextState& state = m_common->state;
ColorSpace colorSpace = state.fillColorSpace;
- if (colorSpace == SolidColorSpace && !fillColor().alpha())
- return;
-
path.setFillType(state.fillRule == RULE_EVENODD ?
SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
@@ -718,9 +711,6 @@ void GraphicsContext::fillRect(const FloatRect& rect)
const GraphicsContextState& state = m_common->state;
ColorSpace colorSpace = state.fillColorSpace;
- if (colorSpace == SolidColorSpace && !fillColor().alpha())
- return;
-
SkPaint paint;
platformContext()->setupPaintForFilling(&paint);
@@ -739,9 +729,6 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
if (paintingDisabled())
return;
- if (!color.alpha())
- return;
-
SkRect r = rect;
if (!isRectSkiaSafe(getCTM(), r)) {
// Special case when the rectangle overflows fixed point. This is a
@@ -907,8 +894,13 @@ void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
// FIXME: This is lifted directly off SkiaSupport, lines 49-74
// so it is not guaranteed to work correctly.
size_t dashLength = dashes.size();
- if (!dashLength)
+ if (!dashLength) {
+ // If no dash is set, revert to solid stroke
+ // FIXME: do we need to set NoStroke in some cases?
+ platformContext()->setStrokeStyle(SolidStroke);
+ platformContext()->setDashPathEffect(0);
return;
+ }
size_t count = (dashLength % 2) == 0 ? dashLength : dashLength * 2;
SkScalar* intervals = new SkScalar[count];
@@ -962,6 +954,12 @@ void GraphicsContext::setPlatformShadow(const IntSize& size,
if (paintingDisabled())
return;
+ // Detect when there's no effective shadow and clear the looper.
+ if (size.width() == 0 && size.height() == 0 && blurInt == 0) {
+ platformContext()->setDrawLooper(NULL);
+ return;
+ }
+
double width = size.width();
double height = size.height();
double blur = blurInt;
@@ -1076,9 +1074,6 @@ void GraphicsContext::strokePath()
const GraphicsContextState& state = m_common->state;
ColorSpace colorSpace = state.strokeColorSpace;
- if (colorSpace == SolidColorSpace && !strokeColor().alpha())
- return;
-
SkPaint paint;
platformContext()->setupPaintForStroking(&paint, 0, 0);
@@ -1103,9 +1098,6 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
const GraphicsContextState& state = m_common->state;
ColorSpace colorSpace = state.strokeColorSpace;
- if (colorSpace == SolidColorSpace && !strokeColor().alpha())
- return;
-
SkPaint paint;
platformContext()->setupPaintForStroking(&paint, 0, 0);
paint.setStrokeWidth(WebCoreFloatToSkScalar(lineWidth));
diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
index 5e90491..600882d 100644
--- a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
@@ -36,7 +36,6 @@
#include "BitmapImageSingleFrameSkia.h"
#include "GraphicsContext.h"
#include "ImageData.h"
-#include "NotImplemented.h"
#include "PlatformContextSkia.h"
#include "PNGImageEncoder.h"
#include "SkiaUtils.h"
diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp
index d7f2830..cb089bb 100644
--- a/WebCore/platform/graphics/skia/ImageSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageSkia.cpp
@@ -38,7 +38,6 @@
#include "GraphicsContext.h"
#include "Logging.h"
#include "NativeImageSkia.h"
-#include "NotImplemented.h"
#include "PlatformContextSkia.h"
#include "PlatformString.h"
#include "SkiaUtils.h"
@@ -226,6 +225,12 @@ static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImag
SkPaint paint;
paint.setPorterDuffXfermode(compOp);
paint.setFilterBitmap(true);
+ int alpha = roundf(platformContext->getAlpha() * 256);
+ if (alpha > 255)
+ alpha = 255;
+ else if (alpha < 0)
+ alpha = 0;
+ paint.setAlpha(alpha);
skia::PlatformCanvas* canvas = platformContext->canvas();
@@ -305,7 +310,8 @@ void Image::drawPattern(GraphicsContext* context,
CompositeOperator compositeOp,
const FloatRect& destRect)
{
- if (destRect.isEmpty() || floatSrcRect.isEmpty())
+ FloatRect normSrcRect = normalizeRect(floatSrcRect);
+ if (destRect.isEmpty() || normSrcRect.isEmpty())
return; // nothing to draw
NativeImageSkia* bitmap = nativeImageForCurrentFrame();
@@ -316,7 +322,7 @@ void Image::drawPattern(GraphicsContext* context,
// it will internally reference the old bitmap's pixels, adjusting the row
// stride so the extra pixels appear as padding to the subsetted bitmap.
SkBitmap srcSubset;
- SkIRect srcRect = enclosingIntRect(floatSrcRect);
+ SkIRect srcRect = enclosingIntRect(normSrcRect);
bitmap->extractSubset(&srcSubset, srcRect);
SkBitmap resampled;
@@ -363,9 +369,9 @@ void Image::drawPattern(GraphicsContext* context,
// origin of the destination rect, which is what WebKit expects. Skia uses
// the coordinate system origin as the base for the patter. If WebKit wants
// a shifted image, it will shift it from there using the patternTransform.
- float adjustedX = phase.x() + floatSrcRect.x() *
+ float adjustedX = phase.x() + normSrcRect.x() *
narrowPrecisionToFloat(patternTransform.a());
- float adjustedY = phase.y() + floatSrcRect.y() *
+ float adjustedY = phase.y() + normSrcRect.y() *
narrowPrecisionToFloat(patternTransform.d());
matrix.postTranslate(SkFloatToScalar(adjustedX),
SkFloatToScalar(adjustedY));
diff --git a/WebCore/platform/graphics/skia/PathSkia.cpp b/WebCore/platform/graphics/skia/PathSkia.cpp
index 2700da8..9d9df52 100644
--- a/WebCore/platform/graphics/skia/PathSkia.cpp
+++ b/WebCore/platform/graphics/skia/PathSkia.cpp
@@ -81,9 +81,15 @@ void Path::translate(const FloatSize& size)
FloatRect Path::boundingRect() const
{
+ // FIXME: This #ifdef can go away once we're firmly using the new Skia.
+ // During the transition, this makes the code compatible with both versions.
+#ifdef SK_USE_OLD_255_TO_256
+ return m_path->getBounds();
+#else
SkRect rect;
m_path->computeBounds(&rect, SkPath::kExact_BoundsType);
return rect;
+#endif
}
void Path::moveTo(const FloatPoint& point)
@@ -275,9 +281,15 @@ static FloatRect boundingBoxForCurrentStroke(const GraphicsContext* context)
context->platformContext()->setupPaintForStroking(&paint, 0, 0);
SkPath boundingPath;
paint.getFillPath(context->platformContext()->currentPathInLocalCoordinates(), &boundingPath);
+ // FIXME: This #ifdef can go away once we're firmly using the new Skia.
+ // During the transition, this makes the code compatible with both versions.
+#ifdef SK_USE_OLD_255_TO_256
+ return boundingPath.getBounds();
+#else
SkRect r;
boundingPath.computeBounds(&r, SkPath::kExact_BoundsType);
return r;
+#endif
}
FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
index 6c633f2..74b2bfe 100644
--- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
@@ -277,13 +277,13 @@ void PlatformContextSkia::drawRect(SkRect rect)
if (oldFillColor != m_state->m_strokeColor)
setFillColor(m_state->m_strokeColor);
setupPaintForFilling(&paint);
- SkRect topBorder = { rect.fLeft, rect.fTop, rect.width(), 1 };
+ SkRect topBorder = { rect.fLeft, rect.fTop, rect.fRight, rect.fTop + 1 };
canvas()->drawRect(topBorder, paint);
- SkRect bottomBorder = { rect.fLeft, rect.fBottom - 1, rect.width(), 1 };
+ SkRect bottomBorder = { rect.fLeft, rect.fBottom - 1, rect.fRight, rect.fBottom };
canvas()->drawRect(bottomBorder, paint);
- SkRect leftBorder = { rect.fLeft, rect.fTop + 1, 1, rect.height() - 2 };
+ SkRect leftBorder = { rect.fLeft, rect.fTop + 1, rect.fLeft + 1, rect.fBottom - 1 };
canvas()->drawRect(leftBorder, paint);
- SkRect rightBorder = { rect.fRight - 1, rect.fTop + 1, 1, rect.height() - 2 };
+ SkRect rightBorder = { rect.fRight - 1, rect.fTop + 1, rect.fRight, rect.fBottom - 1 };
canvas()->drawRect(rightBorder, paint);
if (oldFillColor != m_state->m_strokeColor)
setFillColor(oldFillColor);
@@ -428,6 +428,11 @@ int PlatformContextSkia::getTextDrawingMode() const
return m_state->m_textDrawingMode;
}
+float PlatformContextSkia::getAlpha() const
+{
+ return m_state->m_alpha;
+}
+
void PlatformContextSkia::setTextDrawingMode(int mode)
{
// cTextClip is never used, so we assert that it isn't set:
diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.h b/WebCore/platform/graphics/skia/PlatformContextSkia.h
index 8850a6a..25495aa 100644
--- a/WebCore/platform/graphics/skia/PlatformContextSkia.h
+++ b/WebCore/platform/graphics/skia/PlatformContextSkia.h
@@ -130,6 +130,7 @@ public:
WebCore::StrokeStyle getStrokeStyle() const;
float getStrokeThickness() const;
int getTextDrawingMode() const;
+ float getAlpha() const;
void beginPath();
void addPath(const SkPath&);
diff --git a/WebCore/platform/graphics/skia/SkiaFontWin.cpp b/WebCore/platform/graphics/skia/SkiaFontWin.cpp
index d0cd4c5..7f12508 100644
--- a/WebCore/platform/graphics/skia/SkiaFontWin.cpp
+++ b/WebCore/platform/graphics/skia/SkiaFontWin.cpp
@@ -220,6 +220,16 @@ void SkiaWinOutlineCache::removePathsForFont(HFONT hfont)
deleteOutline(outlineCache.find(*i));
}
+bool windowsCanHandleDrawTextShadow(WebCore::GraphicsContext *context)
+{
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+
+ bool hasShadow = context->getShadow(shadowSize, shadowBlur, shadowColor);
+ return (hasShadow && (shadowBlur == 0) && (shadowColor.alpha() == 255) && (context->fillColor().alpha() == 255));
+}
+
bool windowsCanHandleTextDrawing(GraphicsContext* context)
{
// Check for non-translation transforms. Sometimes zooms will look better in
@@ -244,7 +254,7 @@ bool windowsCanHandleTextDrawing(GraphicsContext* context)
return false;
// Check for shadow effects.
- if (context->platformContext()->getDrawLooper())
+ if (context->platformContext()->getDrawLooper() && (!windowsCanHandleDrawTextShadow(context)))
return false;
return true;
diff --git a/WebCore/platform/graphics/skia/SkiaFontWin.h b/WebCore/platform/graphics/skia/SkiaFontWin.h
index 0e0c953..0bad30f 100644
--- a/WebCore/platform/graphics/skia/SkiaFontWin.h
+++ b/WebCore/platform/graphics/skia/SkiaFontWin.h
@@ -68,8 +68,12 @@ private:
// Remember that Skia's text drawing origin is the baseline, like WebKit, not
// the top, like Windows.
+// Returns true if the fillColor and shadowColor are opaque and the text-shadow
+// is not blurred.
+bool windowsCanHandleDrawTextShadow(GraphicsContext*);
+
// Returns true if advanced font rendering is recommended.
-bool windowsCanHandleTextDrawing(GraphicsContext* context);
+bool windowsCanHandleTextDrawing(GraphicsContext*);
// Note that the offsets parameter is optional. If not NULL it represents a
// per glyph offset (such as returned by ScriptPlace Windows API function).
diff --git a/WebCore/platform/graphics/skia/SkiaUtils.cpp b/WebCore/platform/graphics/skia/SkiaUtils.cpp
index 55cba37..4242e7d 100644
--- a/WebCore/platform/graphics/skia/SkiaUtils.cpp
+++ b/WebCore/platform/graphics/skia/SkiaUtils.cpp
@@ -47,7 +47,7 @@ static const struct CompositOpToPorterDuffMode {
uint8_t mPorterDuffMode;
} gMapCompositOpsToPorterDuffModes[] = {
{ CompositeClear, SkPorterDuff::kClear_Mode },
- { CompositeCopy, SkPorterDuff::kSrcOver_Mode }, // TODO
+ { CompositeCopy, SkPorterDuff::kSrc_Mode },
{ CompositeSourceOver, SkPorterDuff::kSrcOver_Mode },
{ CompositeSourceIn, SkPorterDuff::kSrcIn_Mode },
{ CompositeSourceOut, SkPorterDuff::kSrcOut_Mode },
@@ -59,7 +59,7 @@ static const struct CompositOpToPorterDuffMode {
{ CompositeXOR, SkPorterDuff::kXor_Mode },
{ CompositePlusDarker, SkPorterDuff::kDarken_Mode },
{ CompositeHighlight, SkPorterDuff::kSrcOver_Mode }, // TODO
- { CompositePlusLighter, SkPorterDuff::kLighten_Mode }
+ { CompositePlusLighter, SkPorterDuff::kAdd_Mode }
};
SkPorterDuff::Mode WebCoreCompositeToSkiaComposite(CompositeOperator op)
@@ -135,12 +135,7 @@ bool SkPathContainsPoint(SkPath* originalPath, const FloatPoint& point, SkPath::
int scale = 1;
SkRect bounds;
-#if PLATFORM(SGL)
- // this is the API from skia/trunk
bounds = originalPath->getBounds();
-#else
- originalPath->computeBounds(&bounds, SkPath::kFast_BoundsType);
-#endif
// We can immediately return false if the point is outside the bounding rect
if (!bounds.contains(SkFloatToScalar(point.x()), SkFloatToScalar(point.y())))
diff --git a/WebCore/platform/graphics/transforms/TransformationMatrix.cpp b/WebCore/platform/graphics/transforms/TransformationMatrix.cpp
index 63a7b8e..a358aaf 100644
--- a/WebCore/platform/graphics/transforms/TransformationMatrix.cpp
+++ b/WebCore/platform/graphics/transforms/TransformationMatrix.cpp
@@ -31,6 +31,7 @@
#include "FloatQuad.h"
#include "IntRect.h"
+#include <wtf/Assertions.h>
#include <wtf/MathExtras.h>
namespace WebCore {
@@ -556,6 +557,9 @@ FloatQuad TransformationMatrix::projectQuad(const FloatQuad& q) const
FloatPoint TransformationMatrix::mapPoint(const FloatPoint& p) const
{
+ if (isIdentityOrTranslation())
+ return FloatPoint(p.x() + static_cast<float>(m_matrix[3][0]), p.y() + static_cast<float>(m_matrix[3][1]));
+
double x, y;
multVecMatrix(p.x(), p.y(), x, y);
return FloatPoint(static_cast<float>(x), static_cast<float>(y));
@@ -563,20 +567,16 @@ FloatPoint TransformationMatrix::mapPoint(const FloatPoint& p) const
FloatPoint3D TransformationMatrix::mapPoint(const FloatPoint3D& p) const
{
+ if (isIdentityOrTranslation())
+ return FloatPoint3D(p.x() + static_cast<float>(m_matrix[3][0]),
+ p.y() + static_cast<float>(m_matrix[3][1]),
+ p.z() + static_cast<float>(m_matrix[3][2]));
+
double x, y, z;
multVecMatrix(p.x(), p.y(), p.z(), x, y, z);
return FloatPoint3D(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z));
}
-IntPoint TransformationMatrix::mapPoint(const IntPoint& point) const
-{
- double x, y;
- multVecMatrix(point.x(), point.y(), x, y);
-
- // Round the point.
- return IntPoint(lround(x), lround(y));
-}
-
IntRect TransformationMatrix::mapRect(const IntRect &rect) const
{
return enclosingIntRect(mapRect(FloatRect(rect)));
@@ -584,12 +584,24 @@ IntRect TransformationMatrix::mapRect(const IntRect &rect) const
FloatRect TransformationMatrix::mapRect(const FloatRect& r) const
{
+ if (isIdentityOrTranslation()) {
+ FloatRect mappedRect(r);
+ mappedRect.move(static_cast<float>(m_matrix[3][0]), static_cast<float>(m_matrix[3][1]));
+ return mappedRect;
+ }
+
FloatQuad resultQuad = mapQuad(FloatQuad(r));
return resultQuad.boundingBox();
}
FloatQuad TransformationMatrix::mapQuad(const FloatQuad& q) const
{
+ if (isIdentityOrTranslation()) {
+ FloatQuad mappedQuad(q);
+ mappedQuad.move(static_cast<float>(m_matrix[3][0]), static_cast<float>(m_matrix[3][1]));
+ return mappedQuad;
+ }
+
FloatQuad result;
result.setP1(mapPoint(q.p1()));
result.setP2(mapPoint(q.p2()));
@@ -781,38 +793,19 @@ TransformationMatrix& TransformationMatrix::rotate3d(double rx, double ry, doubl
TransformationMatrix& TransformationMatrix::translate(double tx, double ty)
{
-#ifdef ANDROID_FASTER_MATRIX
m_matrix[3][0] += tx * m_matrix[0][0] + ty * m_matrix[1][0];
m_matrix[3][1] += tx * m_matrix[0][1] + ty * m_matrix[1][1];
m_matrix[3][2] += tx * m_matrix[0][2] + ty * m_matrix[1][2];
m_matrix[3][3] += tx * m_matrix[0][3] + ty * m_matrix[1][3];
-#else
- // FIXME: optimize to avoid matrix copy
- TransformationMatrix mat;
- mat.m_matrix[3][0] = tx;
- mat.m_matrix[3][1] = ty;
-
- multLeft(mat);
-#endif
return *this;
}
TransformationMatrix& TransformationMatrix::translate3d(double tx, double ty, double tz)
{
-#ifdef ANDROID_FASTER_MATRIX
m_matrix[3][0] += tx * m_matrix[0][0] + ty * m_matrix[1][0] + tz * m_matrix[2][0];
m_matrix[3][1] += tx * m_matrix[0][1] + ty * m_matrix[1][1] + tz * m_matrix[2][1];
m_matrix[3][2] += tx * m_matrix[0][2] + ty * m_matrix[1][2] + tz * m_matrix[2][2];
m_matrix[3][3] += tx * m_matrix[0][3] + ty * m_matrix[1][3] + tz * m_matrix[2][3];
-#else
- // FIXME: optimize to avoid matrix copy
- TransformationMatrix mat;
- mat.m_matrix[3][0] = tx;
- mat.m_matrix[3][1] = ty;
- mat.m_matrix[3][2] = tz;
-
- multLeft(mat);
-#endif
return *this;
}
@@ -945,6 +938,9 @@ void TransformationMatrix::multVecMatrix(double x, double y, double z, double& r
bool TransformationMatrix::isInvertible() const
{
+ if (isIdentityOrTranslation())
+ return true;
+
double det = WebCore::determinant4x4(m_matrix);
if (fabs(det) < SMALL_NUMBER)
@@ -955,8 +951,19 @@ bool TransformationMatrix::isInvertible() const
TransformationMatrix TransformationMatrix::inverse() const
{
- TransformationMatrix invMat;
+ if (isIdentityOrTranslation()) {
+ // identity matrix
+ if (m_matrix[3][0] == 0 && m_matrix[3][1] == 0 && m_matrix[3][2] == 0)
+ return TransformationMatrix();
+
+ // translation
+ return TransformationMatrix(1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ -m_matrix[3][0], -m_matrix[3][1], -m_matrix[3][2], 1);
+ }
+ TransformationMatrix invMat;
bool inverted = WebCore::inverse(m_matrix, invMat.m_matrix);
if (!inverted)
return TransformationMatrix();
diff --git a/WebCore/platform/graphics/transforms/TransformationMatrix.h b/WebCore/platform/graphics/transforms/TransformationMatrix.h
index 62e4eb8..7b93e04 100644
--- a/WebCore/platform/graphics/transforms/TransformationMatrix.h
+++ b/WebCore/platform/graphics/transforms/TransformationMatrix.h
@@ -26,6 +26,10 @@
#ifndef TransformationMatrix_h
#define TransformationMatrix_h
+#include "FloatPoint.h"
+#include "IntPoint.h"
+#include <string.h> //for memcpy
+
#if PLATFORM(CG)
#include <CoreGraphics/CGAffineTransform.h>
#elif PLATFORM(CAIRO)
@@ -38,13 +42,9 @@
#include <wx/graphics.h>
#endif
-#include <string.h> //for memcpy
-
namespace WebCore {
-class IntPoint;
class IntRect;
-class FloatPoint;
class FloatPoint3D;
class FloatRect;
class FloatQuad;
@@ -114,7 +114,10 @@ public:
FloatPoint mapPoint(const FloatPoint&) const;
// Like the version above, except that it rounds the mapped point to the nearest integer value.
- IntPoint mapPoint(const IntPoint&) const;
+ IntPoint mapPoint(const IntPoint& p) const
+ {
+ return roundedIntPoint(mapPoint(FloatPoint(p)));
+ }
// If the matrix has 3D components, the z component of the result is
// dropped, effectively projecting the rect into the z=0 plane
@@ -313,6 +316,14 @@ private:
memcpy(m_matrix, m, sizeof(Matrix4));
}
+ bool isIdentityOrTranslation() const
+ {
+ return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0 &&
+ m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0 &&
+ m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0 &&
+ m_matrix[3][3] == 1;
+ }
+
Matrix4 m_matrix;
};
diff --git a/WebCore/platform/graphics/win/ColorSafari.cpp b/WebCore/platform/graphics/win/ColorSafari.cpp
index a04fd81..25b6b89 100644
--- a/WebCore/platform/graphics/win/ColorSafari.cpp
+++ b/WebCore/platform/graphics/win/ColorSafari.cpp
@@ -29,7 +29,6 @@
#include "config.h"
#include "Color.h"
-#include "NotImplemented.h"
#include <CoreGraphics/CGColor.h>
#include <SafariTheme/SafariTheme.h>
#include <wtf/Assertions.h>
diff --git a/WebCore/platform/graphics/win/FontCGWin.cpp b/WebCore/platform/graphics/win/FontCGWin.cpp
index feeb2ae..803f5db 100644
--- a/WebCore/platform/graphics/win/FontCGWin.cpp
+++ b/WebCore/platform/graphics/win/FontCGWin.cpp
@@ -181,7 +181,7 @@ static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData
SetWorldTransform(hdc, &xform);
}
- SelectObject(hdc, font->m_font.hfont());
+ SelectObject(hdc, font->platformData().hfont());
// Set the correct color.
if (drawIntoBitmap)
@@ -215,9 +215,9 @@ static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData
xform.eDy = point.y();
ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, reinterpret_cast<const WCHAR*>(glyphBuffer.glyphs(from)), numGlyphs, gdiAdvances.data());
- if (font->m_syntheticBoldOffset) {
+ if (font->syntheticBoldOffset()) {
xform.eM21 = 0;
- xform.eDx = font->m_syntheticBoldOffset;
+ xform.eDx = font->syntheticBoldOffset();
xform.eDy = 0;
ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, reinterpret_cast<const WCHAR*>(glyphBuffer.glyphs(from)), numGlyphs, gdiAdvances.data());
@@ -250,21 +250,21 @@ static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData
if (drawingMode & cTextFill) {
CGContextAddPath(cgContext, glyphPath.get());
CGContextFillPath(cgContext);
- if (font->m_syntheticBoldOffset) {
- CGContextTranslateCTM(cgContext, font->m_syntheticBoldOffset, 0);
+ if (font->syntheticBoldOffset()) {
+ CGContextTranslateCTM(cgContext, font->syntheticBoldOffset(), 0);
CGContextAddPath(cgContext, glyphPath.get());
CGContextFillPath(cgContext);
- CGContextTranslateCTM(cgContext, -font->m_syntheticBoldOffset, 0);
+ CGContextTranslateCTM(cgContext, -font->syntheticBoldOffset(), 0);
}
}
if (drawingMode & cTextStroke) {
CGContextAddPath(cgContext, glyphPath.get());
CGContextStrokePath(cgContext);
- if (font->m_syntheticBoldOffset) {
- CGContextTranslateCTM(cgContext, font->m_syntheticBoldOffset, 0);
+ if (font->syntheticBoldOffset()) {
+ CGContextTranslateCTM(cgContext, font->syntheticBoldOffset(), 0);
CGContextAddPath(cgContext, glyphPath.get());
CGContextStrokePath(cgContext);
- CGContextTranslateCTM(cgContext, -font->m_syntheticBoldOffset, 0);
+ CGContextTranslateCTM(cgContext, -font->syntheticBoldOffset(), 0);
}
}
@@ -341,8 +341,8 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo
graphicsContext->setFillColor(shadowFillColor);
CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowSize.width(), point.y() + translation.height() + shadowSize.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
- if (font->m_syntheticBoldOffset) {
- CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowSize.width() + font->m_syntheticBoldOffset, point.y() + translation.height() + shadowSize.height());
+ if (font->syntheticBoldOffset()) {
+ CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowSize.width() + font->syntheticBoldOffset(), point.y() + translation.height() + shadowSize.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
}
graphicsContext->setFillColor(fillColor);
@@ -350,8 +350,8 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo
CGContextSetTextPosition(cgContext, point.x() + translation.width(), point.y() + translation.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
- if (font->m_syntheticBoldOffset) {
- CGContextSetTextPosition(cgContext, point.x() + translation.width() + font->m_syntheticBoldOffset, point.y() + translation.height());
+ if (font->syntheticBoldOffset()) {
+ CGContextSetTextPosition(cgContext, point.x() + translation.width() + font->syntheticBoldOffset(), point.y() + translation.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
}
diff --git a/WebCore/platform/graphics/win/FontCustomPlatformData.cpp b/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
index 1ac3359..24db173 100644
--- a/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
@@ -116,7 +116,7 @@ size_t getBytesWithOffset(void *info, void* buffer, size_t offset, size_t count)
// Streams the concatenation of a header and font data.
class EOTStream {
public:
- EOTStream(const Vector<uint8_t, 512>& eotHeader, const SharedBuffer* fontData, size_t overlayDst, size_t overlaySrc, size_t overlayLength)
+ EOTStream(const EOTHeader& eotHeader, const SharedBuffer* fontData, size_t overlayDst, size_t overlaySrc, size_t overlayLength)
: m_eotHeader(eotHeader)
, m_fontData(fontData)
, m_overlayDst(overlayDst)
@@ -130,7 +130,7 @@ public:
size_t read(void* buffer, size_t count);
private:
- const Vector<uint8_t, 512>& m_eotHeader;
+ const EOTHeader& m_eotHeader;
const SharedBuffer* m_fontData;
size_t m_overlayDst;
size_t m_overlaySrc;
@@ -206,7 +206,7 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
// TTLoadEmbeddedFont works only with Embedded OpenType (.eot) data, so we need to create an EOT header
// and prepend it to the font data.
- Vector<uint8_t, 512> eotHeader;
+ EOTHeader eotHeader;
size_t overlayDst;
size_t overlaySrc;
size_t overlayLength;
diff --git a/WebCore/platform/graphics/win/FontWin.cpp b/WebCore/platform/graphics/win/FontWin.cpp
index 5e423e0..27d8dee 100644
--- a/WebCore/platform/graphics/win/FontWin.cpp
+++ b/WebCore/platform/graphics/win/FontWin.cpp
@@ -30,13 +30,17 @@
#include "GlyphBuffer.h"
#include "GraphicsContext.h"
#include "IntRect.h"
-#include "NotImplemented.h"
#include "SimpleFontData.h"
#include "UniscribeController.h"
#include <wtf/MathExtras.h>
namespace WebCore {
+bool Font::canReturnFallbackFontsForComplexText()
+{
+ return true;
+}
+
FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h,
int from, int to) const
{
@@ -85,9 +89,9 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
drawGlyphBuffer(context, glyphBuffer, run, startPoint);
}
-float Font::floatWidthForComplexText(const TextRun& run) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
{
- UniscribeController controller(this, run);
+ UniscribeController controller(this, run, fallbackFonts);
controller.advance(run.length());
return controller.runWidthSoFar();
}
diff --git a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
index da5b503..917631b 100644
--- a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
+++ b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
@@ -27,7 +27,6 @@
#include "GraphicsContext.h"
#include "TransformationMatrix.h"
-#include "NotImplemented.h"
#include "Path.h"
#include <CoreGraphics/CGBitmapContext.h>
diff --git a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
index 1980d18..ca3cb5d 100644
--- a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
+++ b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
@@ -27,7 +27,6 @@
#include "GraphicsContext.h"
#include "TransformationMatrix.h"
-#include "NotImplemented.h"
#include "Path.h"
#include <cairo-win32.h>
@@ -37,13 +36,61 @@ using namespace std;
namespace WebCore {
+static cairo_t* createCairoContextWithHDC(HDC hdc, bool hasAlpha)
+{
+ // Put the HDC In advanced mode so it will honor affine transforms.
+ SetGraphicsMode(hdc, GM_ADVANCED);
+
+ HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
+
+ BITMAP info;
+ GetObject(bitmap, sizeof(info), &info);
+ ASSERT(info.bmBitsPixel == 32);
+
+ cairo_surface_t* image = cairo_image_surface_create_for_data((unsigned char*)info.bmBits,
+ CAIRO_FORMAT_ARGB32,
+ info.bmWidth,
+ info.bmHeight,
+ info.bmWidthBytes);
+
+ cairo_t* context = cairo_create(image);
+ cairo_surface_destroy(image);
+
+ return context;
+}
+
+static BITMAPINFO bitmapInfoForSize(const IntSize& size)
+{
+ BITMAPINFO bitmapInfo;
+ bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bitmapInfo.bmiHeader.biWidth = size.width();
+ bitmapInfo.bmiHeader.biHeight = size.height();
+ bitmapInfo.bmiHeader.biPlanes = 1;
+ bitmapInfo.bmiHeader.biBitCount = 32;
+ bitmapInfo.bmiHeader.biCompression = BI_RGB;
+ bitmapInfo.bmiHeader.biSizeImage = 0;
+ bitmapInfo.bmiHeader.biXPelsPerMeter = 0;
+ bitmapInfo.bmiHeader.biYPelsPerMeter = 0;
+ bitmapInfo.bmiHeader.biClrUsed = 0;
+ bitmapInfo.bmiHeader.biClrImportant = 0;
+
+ return bitmapInfo;
+}
+
+static void fillWithClearColor(HBITMAP bitmap)
+{
+ BITMAP bmpInfo;
+ GetObject(bitmap, sizeof(bmpInfo), &bmpInfo);
+ int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
+ memset(bmpInfo.bmBits, 0, bufferSize);
+}
+
GraphicsContext::GraphicsContext(HDC dc, bool hasAlpha)
: m_common(createGraphicsContextPrivate())
, m_data(new GraphicsContextPlatformPrivate)
{
if (dc) {
- cairo_surface_t* surface = cairo_win32_surface_create(dc);
- m_data->cr = cairo_create(surface);
+ m_data->cr = createCairoContextWithHDC(dc, hasAlpha);
m_data->m_hdc = dc;
} else {
setPaintingDisabled(true);
@@ -60,52 +107,95 @@ GraphicsContext::GraphicsContext(HDC dc, bool hasAlpha)
HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
{
- // FIXME: We aren't really doing anything with the 'mayCreateBitmap' flag. This needs
- // to be addressed.
- if (dstRect.isEmpty())
- return 0;
-
- // This is probably wrong, and definitely out of date. Pulled from old SVN
- cairo_surface_t* surface = cairo_get_target(platformContext());
- HDC hdc = cairo_win32_surface_get_dc(surface);
- SaveDC(hdc);
-
- // FIXME: We need to make sure a clip is really set on the HDC.
- // Call SetWorldTransform to honor the current Cairo transform.
- SetGraphicsMode(hdc, GM_ADVANCED); // We need this call for themes to honor world transforms.
- cairo_matrix_t mat;
- cairo_get_matrix(platformContext(), &mat);
- XFORM xform;
- xform.eM11 = mat.xx;
- xform.eM12 = mat.xy;
- xform.eM21 = mat.yx;
- xform.eM22 = mat.yy;
- xform.eDx = mat.x0;
- xform.eDy = mat.y0;
- ::SetWorldTransform(hdc, &xform);
-
- return hdc;
+ // FIXME: Should a bitmap be created also when a shadow is set?
+ if (mayCreateBitmap && inTransparencyLayer()) {
+ if (dstRect.isEmpty())
+ return 0;
+
+ // Create a bitmap DC in which to draw.
+ BITMAPINFO bitmapInfo = bitmapInfoForSize(dstRect.size());
+
+ void* pixels = 0;
+ HBITMAP bitmap = ::CreateDIBSection(NULL, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0);
+ if (!bitmap)
+ return 0;
+
+ HDC bitmapDC = ::CreateCompatibleDC(m_data->m_hdc);
+ ::SelectObject(bitmapDC, bitmap);
+
+ // Fill our buffer with clear if we're going to alpha blend.
+ if (supportAlphaBlend)
+ fillWithClearColor(bitmap);
+
+ // Make sure we can do world transforms.
+ SetGraphicsMode(bitmapDC, GM_ADVANCED);
+
+ // Apply a translation to our context so that the drawing done will be at (0,0) of the bitmap.
+ XFORM xform;
+ xform.eM11 = 1.0f;
+ xform.eM12 = 0.0f;
+ xform.eM21 = 0.0f;
+ xform.eM22 = 1.0f;
+ xform.eDx = -dstRect.x();
+ xform.eDy = -dstRect.y();
+ ::SetWorldTransform(bitmapDC, &xform);
+
+ return bitmapDC;
+ }
+
+ cairo_surface_t* surface = cairo_win32_surface_create(m_data->m_hdc);
+ cairo_surface_flush(surface);
+ cairo_surface_destroy(surface);
+
+ m_data->save();
+
+ return m_data->m_hdc;
}
void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
{
- // FIXME: We aren't really doing anything with the 'mayCreateBitmap' flag. This needs
- // to be addressed.
- if (dstRect.isEmpty())
- return;
+ if (!mayCreateBitmap || !hdc || !inTransparencyLayer()) {
+ m_data->restore();
+ return;
+ }
- cairo_surface_t* surface = cairo_get_target(platformContext());
- HDC hdc2 = cairo_win32_surface_get_dc(surface);
- RestoreDC(hdc2, -1);
- cairo_surface_mark_dirty(surface);
+ if (dstRect.isEmpty())
+ return;
+
+ HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
+
+ BITMAP info;
+ GetObject(bitmap, sizeof(info), &info);
+ ASSERT(info.bmBitsPixel == 32);
+
+ // Need to make a cairo_surface_t out of the bitmap's pixel buffer and then draw
+ // it into our context.
+ cairo_surface_t* image = cairo_image_surface_create_for_data((unsigned char*)info.bmBits,
+ CAIRO_FORMAT_ARGB32,
+ info.bmWidth,
+ info.bmHeight,
+ info.bmWidthBytes);
+
+ // Scale the target surface to the new image size, and flip it
+ // so that when we set the srcImage as the surface it will draw
+ // right-side-up.
+ cairo_translate(m_data->cr, 0, dstRect.height());
+ cairo_scale(m_data->cr, dstRect.width(), -dstRect.height());
+ cairo_set_source_surface (m_data->cr, image, dstRect.x(), dstRect.y());
+
+ if (m_data->layers.size())
+ cairo_paint_with_alpha(m_data->cr, m_data->layers.last());
+ else
+ cairo_paint(m_data->cr);
+
+ // Delete all our junk.
+ cairo_surface_destroy(image);
+ ::DeleteDC(hdc);
+ ::DeleteObject(bitmap);
}
void GraphicsContextPlatformPrivate::concatCTM(const TransformationMatrix& transform)
{
- cairo_surface_t* surface = cairo_get_target(cr);
- HDC hdc = cairo_win32_surface_get_dc(surface);
- SaveDC(hdc);
-
const cairo_matrix_t* matrix = reinterpret_cast<const cairo_matrix_t*>(&transform);
XFORM xform;
@@ -116,7 +206,15 @@ void GraphicsContextPlatformPrivate::concatCTM(const TransformationMatrix& trans
xform.eDx = matrix->x0;
xform.eDy = matrix->y0;
- ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
+ ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
+}
+
+void GraphicsContextPlatformPrivate::syncContext(PlatformGraphicsContext* cr)
+{
+ cairo_surface_t* surface = cairo_get_target(cr);
+ m_hdc = cairo_win32_surface_get_dc(surface);
+
+ SetGraphicsMode(m_hdc, GM_ADVANCED); // We need this call for themes to honor world transforms.
}
}
diff --git a/WebCore/platform/graphics/win/ImageCairoWin.cpp b/WebCore/platform/graphics/win/ImageCairoWin.cpp
index 95bb7bc..06428b8 100644
--- a/WebCore/platform/graphics/win/ImageCairoWin.cpp
+++ b/WebCore/platform/graphics/win/ImageCairoWin.cpp
@@ -47,13 +47,17 @@ bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
memset(bmpInfo.bmBits, 255, bufferSize);
}
- HDC tempDC = CreateCompatibleDC(0);
- if (!tempDC) {
- LOG_ERROR("Failed to create in-memory DC for Image::blit()");
- return false;
- }
- SelectObject(tempDC, bmp);
- GraphicsContext gc(tempDC);
+ cairo_surface_t* image = cairo_image_surface_create_for_data((unsigned char*)bmpInfo.bmBits,
+ CAIRO_FORMAT_ARGB32,
+ bmpInfo.bmWidth,
+ bmpInfo.bmHeight,
+ bmpInfo.bmWidthBytes);
+
+
+ cairo_t* targetRef = cairo_create(image);
+ cairo_surface_destroy(image);
+
+ GraphicsContext gc(targetRef);
IntSize imageSize = BitmapImage::size();
if (size)
@@ -62,7 +66,7 @@ bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
draw(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), CompositeCopy);
// Do cleanup
- DeleteDC(tempDC);
+ cairo_destroy(targetRef);
return true;
}
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
index c293f49..35ea786 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
@@ -70,6 +70,8 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
, m_networkState(MediaPlayer::Empty)
, m_readyState(MediaPlayer::HaveNothing)
, m_enabledTrackCount(0)
+ , m_totalTrackCount(0)
+ , m_hasUnsupportedTracks(false)
, m_startedPlaying(false)
, m_isStreaming(false)
#if DRAW_FRAME_RATE
@@ -320,9 +322,17 @@ void MediaPlayerPrivate::updateStates()
long loadState = m_qtMovie ? m_qtMovie->loadState() : QTMovieLoadStateError;
- if (loadState >= QTMovieLoadStateLoaded && m_readyState < MediaPlayer::HaveMetadata && !m_player->inMediaDocument()) {
- m_qtMovie->disableUnsupportedTracks(m_enabledTrackCount);
- if (!m_enabledTrackCount)
+ if (loadState >= QTMovieLoadStateLoaded && m_readyState < MediaPlayer::HaveMetadata) {
+ m_qtMovie->disableUnsupportedTracks(m_enabledTrackCount, m_totalTrackCount);
+ if (m_player->inMediaDocument()) {
+ if (!m_enabledTrackCount || m_enabledTrackCount != m_totalTrackCount) {
+ // This is a type of media that we do not handle directly with a <video>
+ // element, eg. QuickTime VR, a movie with a sprite track, etc. Tell the
+ // MediaPlayerClient that we won't support it.
+ sawUnsupportedTracks();
+ return;
+ }
+ } else if (!m_enabledTrackCount)
loadState = QTMovieLoadStateError;
}
@@ -341,6 +351,14 @@ void MediaPlayerPrivate::updateStates()
m_networkState = MediaPlayer::Loading;
m_readyState = MediaPlayer::HaveNothing;
} else {
+ if (m_player->inMediaDocument()) {
+ // Something went wrong in the loading of media within a standalone file.
+ // This can occur with chained ref movies that eventually resolve to a
+ // file we don't support.
+ sawUnsupportedTracks();
+ return;
+ }
+
float loaded = maxTimeLoaded();
if (!loaded)
m_readyState = MediaPlayer::HaveNothing;
@@ -365,9 +383,18 @@ void MediaPlayerPrivate::updateStates()
m_player->readyStateChanged();
}
+void MediaPlayerPrivate::sawUnsupportedTracks()
+{
+ m_qtMovie->setDisabled(true);
+ m_hasUnsupportedTracks = true;
+ m_player->mediaPlayerClient()->mediaPlayerSawUnsupportedTracks(m_player);
+}
void MediaPlayerPrivate::didEnd()
{
+ if (m_hasUnsupportedTracks)
+ return;
+
m_startedPlaying = false;
#if DRAW_FRAME_RATE
m_timeStoppedPlaying = GetTickCount();
@@ -378,20 +405,21 @@ void MediaPlayerPrivate::didEnd()
void MediaPlayerPrivate::setSize(const IntSize& size)
{
- if (m_qtMovie)
- m_qtMovie->setSize(size.width(), size.height());
+ if (m_hasUnsupportedTracks || !m_qtMovie)
+ return;
+ m_qtMovie->setSize(size.width(), size.height());
}
void MediaPlayerPrivate::setVisible(bool b)
{
- if (!m_qtMovie)
+ if (m_hasUnsupportedTracks || !m_qtMovie)
return;
m_qtMovie->setVisible(b);
}
void MediaPlayerPrivate::paint(GraphicsContext* p, const IntRect& r)
{
- if (p->paintingDisabled() || !m_qtMovie)
+ if (p->paintingDisabled() || !m_qtMovie || m_hasUnsupportedTracks)
return;
HDC hdc = p->getWindowsContext(r);
m_qtMovie->paint(hdc, r.x(), r.y());
@@ -463,18 +491,27 @@ MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, c
void MediaPlayerPrivate::movieEnded(QTMovieWin* movie)
{
+ if (m_hasUnsupportedTracks)
+ return;
+
ASSERT(m_qtMovie.get() == movie);
didEnd();
}
void MediaPlayerPrivate::movieLoadStateChanged(QTMovieWin* movie)
{
+ if (m_hasUnsupportedTracks)
+ return;
+
ASSERT(m_qtMovie.get() == movie);
updateStates();
}
void MediaPlayerPrivate::movieTimeChanged(QTMovieWin* movie)
{
+ if (m_hasUnsupportedTracks)
+ return;
+
ASSERT(m_qtMovie.get() == movie);
updateStates();
m_player->timeChanged();
@@ -482,6 +519,9 @@ void MediaPlayerPrivate::movieTimeChanged(QTMovieWin* movie)
void MediaPlayerPrivate::movieNewImageAvailable(QTMovieWin* movie)
{
+ if (m_hasUnsupportedTracks)
+ return;
+
ASSERT(m_qtMovie.get() == movie);
#if DRAW_FRAME_RATE
if (m_startedPlaying) {
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
index 63aa62b..3207867 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
@@ -98,6 +98,7 @@ private:
void cancelSeek();
void seekTimerFired(Timer<MediaPlayerPrivate>*);
float maxTimeLoaded() const;
+ void sawUnsupportedTracks();
virtual void movieEnded(QTMovieWin*);
virtual void movieLoadStateChanged(QTMovieWin*);
@@ -118,6 +119,8 @@ private:
MediaPlayer::NetworkState m_networkState;
MediaPlayer::ReadyState m_readyState;
unsigned m_enabledTrackCount;
+ unsigned m_totalTrackCount;
+ bool m_hasUnsupportedTracks;
bool m_startedPlaying;
bool m_isStreaming;
#if DRAW_FRAME_RATE
diff --git a/WebCore/platform/graphics/win/QTMovieWin.cpp b/WebCore/platform/graphics/win/QTMovieWin.cpp
index 3f23698..1d10006 100644
--- a/WebCore/platform/graphics/win/QTMovieWin.cpp
+++ b/WebCore/platform/graphics/win/QTMovieWin.cpp
@@ -91,6 +91,7 @@ public:
void createGWorld();
void deleteGWorld();
void clearGWorld();
+ void cacheMovieScale();
void setSize(int, int);
@@ -112,6 +113,11 @@ public:
int m_gWorldHeight;
GWorldPtr m_savedGWorld;
long m_loadError;
+ float m_widthScaleFactor;
+ float m_heightScaleFactor;
+#if !ASSERT_DISABLED
+ bool m_scaleCached;
+#endif
};
QTMovieWinPrivate::QTMovieWinPrivate()
@@ -133,6 +139,11 @@ QTMovieWinPrivate::QTMovieWinPrivate()
, m_gWorldHeight(0)
, m_savedGWorld(0)
, m_loadError(0)
+ , m_widthScaleFactor(1)
+ , m_heightScaleFactor(1)
+#if !ASSERT_DISABLED
+ , m_scaleCached(false)
+#endif
{
}
@@ -179,6 +190,26 @@ void QTMovieWinPrivate::endTask()
updateTaskTimer();
}
+void QTMovieWinPrivate::cacheMovieScale()
+{
+ Rect naturalRect;
+ Rect initialRect;
+
+ GetMovieNaturalBoundsRect(m_movie, &naturalRect);
+ GetMovieBox(m_movie, &initialRect);
+
+ int naturalWidth = naturalRect.right - naturalRect.left;
+ int naturalHeight = naturalRect.bottom - naturalRect.top;
+
+ if (naturalWidth)
+ m_widthScaleFactor = (initialRect.right - initialRect.left) / naturalWidth;
+ if (naturalHeight)
+ m_heightScaleFactor = (initialRect.bottom - initialRect.top) / naturalHeight;
+#if !ASSERT_DISABLED
+ m_scaleCached = true;;
+#endif
+}
+
void QTMovieWinPrivate::task()
{
ASSERT(m_tasking);
@@ -192,20 +223,27 @@ void QTMovieWinPrivate::task()
// GetMovieLoadState documentation says that you should not call it more often than every quarter of a second.
if (systemTime() >= m_lastLoadStateCheckTime + 0.25 || m_loadError) {
- // If load fails QT's load state is kMovieLoadStateComplete.
+ // If load fails QT's load state is QTMovieLoadStateComplete.
// This is different from QTKit API and seems strange.
- long loadState = m_loadError ? kMovieLoadStateError : GetMovieLoadState(m_movie);
+ long loadState = m_loadError ? QTMovieLoadStateError : GetMovieLoadState(m_movie);
if (loadState != m_loadState) {
// we only need to erase the movie gworld when the load state changes to loaded while it
// is visible as the gworld is destroyed/created when visibility changes
- if (loadState >= QTMovieLoadStateLoaded && m_loadState < QTMovieLoadStateLoaded && m_visible)
- clearGWorld();
+ if (loadState >= QTMovieLoadStateLoaded && m_loadState < QTMovieLoadStateLoaded) {
+ if (m_visible)
+ clearGWorld();
+ cacheMovieScale();
+ }
m_loadState = loadState;
- if (!m_movieController && m_loadState >= kMovieLoadStateLoaded)
+ if (!m_movieController && m_loadState >= QTMovieLoadStateLoaded)
createMovieController();
m_client->movieLoadStateChanged(m_movieWin);
+ if (m_movieWin->m_disabled) {
+ endTask();
+ return;
+ }
}
m_lastLoadStateCheckTime = systemTime();
}
@@ -259,7 +297,7 @@ void QTMovieWinPrivate::registerDrawingCallback()
void QTMovieWinPrivate::drawingComplete()
{
- if (!m_gWorld || m_loadState < kMovieLoadStateLoaded)
+ if (!m_gWorld || m_movieWin->m_disabled || m_loadState < QTMovieLoadStateLoaded)
return;
m_client->movieNewImageAvailable(m_movieWin);
}
@@ -284,7 +322,7 @@ void QTMovieWinPrivate::updateGWorld()
void QTMovieWinPrivate::createGWorld()
{
ASSERT(!m_gWorld);
- if (!m_movie)
+ if (!m_movie || m_loadState < QTMovieLoadStateLoaded)
return;
m_gWorldWidth = max(cGWorldMinWidth, m_width);
@@ -334,8 +372,17 @@ void QTMovieWinPrivate::setSize(int width, int height)
return;
m_width = width;
m_height = height;
- if (!m_movie)
+
+ // Do not change movie box before reaching load state loaded as we grab
+ // the initial size when task() sees that state for the first time, and
+ // we need the initial size to be able to scale movie properly.
+ if (!m_movie || m_loadState < QTMovieLoadStateLoaded)
return;
+
+#if !ASSERT_DISABLED
+ ASSERT(m_scaleCached);
+#endif
+
Rect bounds;
bounds.top = 0;
bounds.left = 0;
@@ -364,6 +411,7 @@ void QTMovieWinPrivate::deleteGWorld()
QTMovieWin::QTMovieWin(QTMovieWinClient* client)
: m_private(new QTMovieWinPrivate())
+ , m_disabled(false)
{
m_private->m_movieWin = this;
m_private->m_client = client;
@@ -478,8 +526,8 @@ void QTMovieWin::getNaturalSize(int& width, int& height)
if (m_private->m_movie)
GetMovieNaturalBoundsRect(m_private->m_movie, &rect);
- width = rect.right;
- height = rect.bottom;
+ width = (rect.right - rect.left) * m_private->m_widthScaleFactor;
+ height = (rect.bottom - rect.top) * m_private->m_heightScaleFactor;
}
void QTMovieWin::setSize(int width, int height)
@@ -593,6 +641,7 @@ void QTMovieWin::load(const UChar* url, int len)
movieProps[moviePropCount].propStatus = 0;
moviePropCount++;
+ ASSERT(moviePropCount <= sizeof(movieProps)/sizeof(movieProps[0]));
m_private->m_loadError = NewMovieFromProperties(moviePropCount, movieProps, 0, NULL, &m_private->m_movie);
CFRelease(urlRef);
@@ -601,15 +650,24 @@ end:
// get the load fail callback quickly
if (m_private->m_loadError)
updateTaskTimer(0);
- else
+ else {
+ OSType mode = kQTApertureMode_CleanAperture;
+
+ // Set the aperture mode property on a movie to signal that we want aspect ratio
+ // and clean aperture dimensions. Don't worry about errors, we can't do anything if
+ // the installed version of QT doesn't support it and it isn't serious enough to
+ // warrant failing.
+ QTSetMovieProperty(m_private->m_movie, kQTPropertyClass_Visual, kQTVisualPropertyID_ApertureMode, sizeof(mode), &mode);
m_private->registerDrawingCallback();
+ }
CFRelease(urlStringRef);
}
-void QTMovieWin::disableUnsupportedTracks(unsigned& enabledTrackCount)
+void QTMovieWin::disableUnsupportedTracks(unsigned& enabledTrackCount, unsigned& totalTrackCount)
{
if (!m_private->m_movie) {
+ totalTrackCount = 0;
enabledTrackCount = 0;
return;
}
@@ -623,11 +681,16 @@ void QTMovieWin::disableUnsupportedTracks(unsigned& enabledTrackCount)
allowedTrackTypes->add(BaseMediaType);
allowedTrackTypes->add('clcp'); // Closed caption
allowedTrackTypes->add('sbtl'); // Subtitle
+ allowedTrackTypes->add('odsm'); // MPEG-4 object descriptor stream
+ allowedTrackTypes->add('sdsm'); // MPEG-4 scene description stream
+ allowedTrackTypes->add(TimeCodeMediaType);
+ allowedTrackTypes->add(TimeCode64MediaType);
}
long trackCount = GetMovieTrackCount(m_private->m_movie);
enabledTrackCount = trackCount;
-
+ totalTrackCount = trackCount;
+
// Track indexes are 1-based. yuck. These things must descend from old-
// school mac resources or something.
for (long trackIndex = 1; trackIndex <= trackCount; trackIndex++) {
@@ -716,6 +779,11 @@ void QTMovieWin::disableUnsupportedTracks(unsigned& enabledTrackCount)
}
}
+void QTMovieWin::setDisabled(bool b)
+{
+ m_disabled = b;
+}
+
bool QTMovieWin::hasVideo() const
{
diff --git a/WebCore/platform/graphics/win/QTMovieWin.h b/WebCore/platform/graphics/win/QTMovieWin.h
index 2186974..70cbef5 100644
--- a/WebCore/platform/graphics/win/QTMovieWin.h
+++ b/WebCore/platform/graphics/win/QTMovieWin.h
@@ -84,7 +84,8 @@ public:
void setVisible(bool);
void paint(HDC, int x, int y);
- void disableUnsupportedTracks(unsigned& enabledTrackCount);
+ void disableUnsupportedTracks(unsigned& enabledTrackCount, unsigned& totalTrackCount);
+ void setDisabled(bool);
bool hasVideo() const;
@@ -93,6 +94,7 @@ public:
private:
QTMovieWinPrivate* m_private;
+ bool m_disabled;
friend class QTMovieWinPrivate;
};
diff --git a/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
index 8b5ab87..aaa089a 100644
--- a/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
+++ b/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
@@ -52,27 +52,27 @@ static inline float scaleEmToUnits(float x, unsigned unitsPerEm) { return unitsP
void SimpleFontData::platformInit()
{
- m_syntheticBoldOffset = m_font.syntheticBold() ? 1.0f : 0.f;
+ m_syntheticBoldOffset = m_platformData.syntheticBold() ? 1.0f : 0.f;
m_scriptCache = 0;
m_scriptFontProperties = 0;
m_isSystemFont = false;
- if (m_font.useGDI())
+ if (m_platformData.useGDI())
return initGDIFont();
- CGFontRef font = m_font.cgFont();
+ CGFontRef font = m_platformData.cgFont();
int iAscent = CGFontGetAscent(font);
int iDescent = CGFontGetDescent(font);
int iLineGap = CGFontGetLeading(font);
m_unitsPerEm = CGFontGetUnitsPerEm(font);
- float pointSize = m_font.size();
+ 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;
if (!isCustomFont()) {
HDC dc = GetDC(0);
- HGDIOBJ oldFont = SelectObject(dc, m_font.hfont());
+ HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
int faceLength = GetTextFace(dc, 0, 0);
Vector<TCHAR> faceName(faceLength);
GetTextFace(dc, faceLength, faceName.data());
@@ -116,6 +116,16 @@ void SimpleFontData::platformInit()
}
}
+void SimpleFontData::platformCharWidthInit()
+{
+ // GDI Fonts init charwidths in initGDIFont.
+ if (!m_platformData.useGDI()) {
+ m_avgCharWidth = 0.f;
+ m_maxCharWidth = 0.f;
+ initCharWidths();
+ }
+}
+
void SimpleFontData::platformDestroy()
{
platformCommonDestroy();
@@ -123,11 +133,11 @@ void SimpleFontData::platformDestroy()
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
- if (m_font.useGDI())
+ if (m_platformData.useGDI())
return widthForGDIGlyph(glyph);
- CGFontRef font = m_font.cgFont();
- float pointSize = m_font.size();
+ CGFontRef font = m_platformData.cgFont();
+ float pointSize = m_platformData.size();
CGSize advance;
CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize);
diff --git a/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp
index 07d5305..2e51621 100644
--- a/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp
+++ b/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp
@@ -35,7 +35,6 @@
#include "FontCache.h"
#include "FontDescription.h"
#include "MathExtras.h"
-#include "NotImplemented.h"
#include <cairo.h>
#include <cairo-win32.h>
#include <mlang.h>
@@ -50,14 +49,16 @@ void SimpleFontData::platformInit()
m_isSystemFont = false;
m_syntheticBoldOffset = 0;
- if (m_font.useGDI())
+ m_syntheticBoldOffset = m_platformData.syntheticBold() ? 1.0f : 0.f;
+
+ if (m_platformData.useGDI())
return initGDIFont();
HDC hdc = GetDC(0);
SaveDC(hdc);
- cairo_scaled_font_t* scaledFont = m_font.scaledFont();
- const double metricsMultiplier = cairo_win32_scaled_font_get_metrics_factor(scaledFont) * m_font.size();
+ cairo_scaled_font_t* scaledFont = m_platformData.scaledFont();
+ const double metricsMultiplier = cairo_win32_scaled_font_get_metrics_factor(scaledFont) * m_platformData.size();
cairo_win32_scaled_font_select_font(scaledFont, hdc);
@@ -68,6 +69,8 @@ void SimpleFontData::platformInit()
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);
OUTLINETEXTMETRIC metrics;
if (GetOutlineTextMetrics(hdc, sizeof(metrics), &metrics) > 0) {
@@ -89,25 +92,30 @@ void SimpleFontData::platformInit()
ReleaseDC(0, hdc);
}
+void SimpleFontData::platformCharWidthInit()
+{
+ // charwidths are set in platformInit.
+}
+
void SimpleFontData::platformDestroy()
{
- cairo_font_face_destroy(m_font.fontFace());
- cairo_scaled_font_destroy(m_font.scaledFont());
+ cairo_font_face_destroy(m_platformData.fontFace());
+ cairo_scaled_font_destroy(m_platformData.scaledFont());
- DeleteObject(m_font.hfont());
+ DeleteObject(m_platformData.hfont());
platformCommonDestroy();
}
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
- if (m_font.useGDI())
+ if (m_platformData.useGDI())
return widthForGDIGlyph(glyph);
HDC hdc = GetDC(0);
SaveDC(hdc);
- cairo_scaled_font_t* scaledFont = m_font.scaledFont();
+ cairo_scaled_font_t* scaledFont = m_platformData.scaledFont();
cairo_win32_scaled_font_select_font(scaledFont, hdc);
int width;
@@ -118,14 +126,14 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
RestoreDC(hdc, -1);
ReleaseDC(0, hdc);
- const double metricsMultiplier = cairo_win32_scaled_font_get_metrics_factor(scaledFont) * m_font.size();
+ const double metricsMultiplier = cairo_win32_scaled_font_get_metrics_factor(scaledFont) * m_platformData.size();
return width * metricsMultiplier;
}
void SimpleFontData::setFont(cairo_t* cr) const
{
ASSERT(cr);
- m_font.setFont(cr);
+ m_platformData.setFont(cr);
}
}
diff --git a/WebCore/platform/graphics/win/SimpleFontDataWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
index 9d5c3b9..9835e9f 100644
--- a/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
+++ b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
@@ -63,7 +63,7 @@ bool SimpleFontData::shouldApplyMacAscentHack()
void SimpleFontData::initGDIFont()
{
HDC hdc = GetDC(0);
- HGDIOBJ oldFont = SelectObject(hdc, m_font.hfont());
+ HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont());
OUTLINETEXTMETRIC metrics;
GetOutlineTextMetrics(hdc, sizeof(metrics), &metrics);
TEXTMETRIC& textMetrics = metrics.otmTextMetrics;
@@ -71,6 +71,8 @@ void SimpleFontData::initGDIFont()
m_descent = textMetrics.tmDescent;
m_lineGap = textMetrics.tmExternalLeading;
m_lineSpacing = m_ascent + m_descent + m_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.
GLYPHMETRICS gm;
@@ -100,17 +102,17 @@ void SimpleFontData::platformCommonDestroy()
SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
{
if (!m_smallCapsFontData) {
- float smallCapsHeight = cSmallCapsFontSizeMultiplier * m_font.size();
+ float smallCapsHeight = cSmallCapsFontSizeMultiplier * m_platformData.size();
if (isCustomFont()) {
- FontPlatformData smallCapsFontData(m_font);
+ FontPlatformData smallCapsFontData(m_platformData);
smallCapsFontData.setSize(smallCapsHeight);
m_smallCapsFontData = new SimpleFontData(smallCapsFontData, true, false);
} else {
LOGFONT winfont;
- GetObject(m_font.hfont(), sizeof(LOGFONT), &winfont);
- winfont.lfHeight = -lroundf(smallCapsHeight * (m_font.useGDI() ? 1 : 32));
+ GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winfont);
+ winfont.lfHeight = -lroundf(smallCapsHeight * (m_platformData.useGDI() ? 1 : 32));
HFONT hfont = CreateFontIndirect(&winfont);
- m_smallCapsFontData = new SimpleFontData(FontPlatformData(hfont, smallCapsHeight, m_font.syntheticBold(), m_font.syntheticOblique(), m_font.useGDI()));
+ m_smallCapsFontData = new SimpleFontData(FontPlatformData(hfont, smallCapsHeight, m_platformData.syntheticBold(), m_platformData.syntheticOblique(), m_platformData.useGDI()));
}
}
return m_smallCapsFontData;
@@ -135,7 +137,7 @@ bool SimpleFontData::containsCharacters(const UChar* characters, int length) con
langFontLink->CodePageToCodePages(CP_ACP, &acpCodePages);
DWORD fontCodePages;
- langFontLink->GetFontCodePages(dc, m_font.hfont(), &fontCodePages);
+ langFontLink->GetFontCodePages(dc, m_platformData.hfont(), &fontCodePages);
DWORD actualCodePages;
long numCharactersProcessed;
@@ -162,7 +164,7 @@ void SimpleFontData::determinePitch()
// TEXTMETRICS have this. Set m_treatAsFixedPitch based off that.
HDC dc = GetDC(0);
SaveDC(dc);
- SelectObject(dc, m_font.hfont());
+ SelectObject(dc, m_platformData.hfont());
// Yes, this looks backwards, but the fixed pitch bit is actually set if the font
// is *not* fixed pitch. Unbelievable but true.
@@ -178,7 +180,7 @@ float SimpleFontData::widthForGDIGlyph(Glyph glyph) const
{
HDC hdc = GetDC(0);
SetGraphicsMode(hdc, GM_ADVANCED);
- HGDIOBJ oldFont = SelectObject(hdc, m_font.hfont());
+ HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont());
int width;
GetCharWidthI(hdc, glyph, 1, 0, &width);
SelectObject(hdc, oldFont);
@@ -196,7 +198,7 @@ SCRIPT_FONTPROPERTIES* SimpleFontData::scriptFontProperties() const
if (result == E_PENDING) {
HDC dc = GetDC(0);
SaveDC(dc);
- SelectObject(dc, m_font.hfont());
+ SelectObject(dc, m_platformData.hfont());
ScriptGetFontProperties(dc, scriptCache(), m_scriptFontProperties);
RestoreDC(dc, -1);
ReleaseDC(0, dc);
diff --git a/WebCore/platform/graphics/win/UniscribeController.cpp b/WebCore/platform/graphics/win/UniscribeController.cpp
index 371bc51..f382857 100644
--- a/WebCore/platform/graphics/win/UniscribeController.cpp
+++ b/WebCore/platform/graphics/win/UniscribeController.cpp
@@ -38,9 +38,10 @@ namespace WebCore {
// that does stuff in that method instead of doing everything in the constructor. Have advance()
// take the GlyphBuffer as an arg so that we don't have to populate the glyph buffer when
// measuring.
-UniscribeController::UniscribeController(const Font* font, const TextRun& run)
+UniscribeController::UniscribeController(const Font* font, const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts)
: m_font(*font)
, m_run(run)
+, m_fallbackFonts(fallbackFonts)
, m_end(run.length())
, m_currentCharacter(0)
, m_runWidthSoFar(0)
@@ -147,6 +148,9 @@ void UniscribeController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
smallCapsBuffer[index] = forceSmallCaps ? c : newC;
}
+ if (m_fallbackFonts && nextFontData != fontData && fontData != m_font.primaryFont())
+ m_fallbackFonts->add(fontData);
+
if (nextFontData != fontData || nextIsSmallCaps != isSmallCaps) {
int itemStart = m_run.rtl() ? index + 1 : indexOfFontTransition;
int itemLength = m_run.rtl() ? indexOfFontTransition - index : index - indexOfFontTransition;
@@ -158,6 +162,9 @@ void UniscribeController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
int itemLength = m_run.rtl() ? indexOfFontTransition + 1 : length - indexOfFontTransition;
if (itemLength) {
+ if (m_fallbackFonts && nextFontData != m_font.primaryFont())
+ m_fallbackFonts->add(nextFontData);
+
int itemStart = m_run.rtl() ? 0 : indexOfFontTransition;
m_currentCharacter = baseCharacter + itemStart;
itemizeShapeAndPlace((nextIsSmallCaps ? smallCapsBuffer.data() : cp) + itemStart, itemLength, nextFontData, glyphBuffer);
@@ -258,16 +265,16 @@ bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, const S
Vector<int> roundingHackWordBoundaries(glyphs.size());
roundingHackWordBoundaries.fill(-1);
- const float cLogicalScale = fontData->m_font.useGDI() ? 1.0f : 32.0f;
- unsigned logicalSpaceWidth = fontData->m_spaceWidth * cLogicalScale;
- float roundedSpaceWidth = roundf(fontData->m_spaceWidth);
+ const float cLogicalScale = fontData->platformData().useGDI() ? 1.0f : 32.0f;
+ unsigned logicalSpaceWidth = fontData->spaceWidth() * cLogicalScale;
+ float roundedSpaceWidth = roundf(fontData->spaceWidth());
for (int k = 0; k < len; k++) {
UChar ch = *(str + k);
if (Font::treatAsSpace(ch)) {
// Substitute in the space glyph at the appropriate place in the glyphs
// array.
- glyphs[clusters[k]] = fontData->m_spaceGlyph;
+ glyphs[clusters[k]] = fontData->spaceGlyph();
advances[clusters[k]] = logicalSpaceWidth;
spaceCharacters[clusters[k]] = m_currentCharacter + k + item.iCharPos;
}
@@ -300,15 +307,15 @@ bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, const S
offsetY = roundf(offsetY);
}
- advance += fontData->m_syntheticBoldOffset;
+ advance += fontData->syntheticBoldOffset();
// We special case spaces in two ways when applying word rounding.
// First, we round spaces to an adjusted width in all fonts.
// Second, in fixed-pitch fonts we ensure that all glyphs that
// match the width of the space glyph have the same width as the space glyph.
- if (roundedAdvance == roundedSpaceWidth && (fontData->m_treatAsFixedPitch || glyph == fontData->m_spaceGlyph) &&
+ if (roundedAdvance == roundedSpaceWidth && (fontData->pitch() == FixedPitch || glyph == fontData->spaceGlyph()) &&
m_run.applyWordRounding())
- advance = fontData->m_adjustedSpaceWidth;
+ advance = fontData->adjustedSpaceWidth();
if (hasExtraSpacing) {
// If we're a glyph with an advance, go ahead and add in letter-spacing.
@@ -317,7 +324,7 @@ bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, const S
advance += m_font.letterSpacing();
// Handle justification and word-spacing.
- if (glyph == fontData->m_spaceGlyph) {
+ if (glyph == fontData->spaceGlyph()) {
// 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) {
diff --git a/WebCore/platform/graphics/win/UniscribeController.h b/WebCore/platform/graphics/win/UniscribeController.h
index 6ea45e1..23b8108 100644
--- a/WebCore/platform/graphics/win/UniscribeController.h
+++ b/WebCore/platform/graphics/win/UniscribeController.h
@@ -38,7 +38,7 @@ namespace WebCore {
class UniscribeController {
public:
- UniscribeController(const Font*, const TextRun&);
+ UniscribeController(const Font*, const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0);
// Advance and measure/place up to the specified character.
void advance(unsigned to, GlyphBuffer* = 0);
@@ -60,6 +60,7 @@ private:
const Font& m_font;
const TextRun& m_run;
+ HashSet<const SimpleFontData*>* m_fallbackFonts;
SCRIPT_CONTROL m_control;
SCRIPT_STATE m_state;
diff --git a/WebCore/platform/graphics/wx/FontWx.cpp b/WebCore/platform/graphics/wx/FontWx.cpp
index 07223e9..04b2ec4 100644
--- a/WebCore/platform/graphics/wx/FontWx.cpp
+++ b/WebCore/platform/graphics/wx/FontWx.cpp
@@ -39,6 +39,11 @@
namespace WebCore {
+bool Font::canReturnFallbackFontsForComplexText()
+{
+ return false;
+}
+
void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
int from, int numGlyphs, const FloatPoint& point) const
{
@@ -63,7 +68,7 @@ void Font::drawComplexText(GraphicsContext* graphicsContext, const TextRun& run,
notImplemented();
}
-float Font::floatWidthForComplexText(const TextRun& run) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */) const
{
notImplemented();
return 0;
diff --git a/WebCore/platform/graphics/wx/ImageSourceWx.cpp b/WebCore/platform/graphics/wx/ImageSourceWx.cpp
index fc8ce71..2f71d62 100644
--- a/WebCore/platform/graphics/wx/ImageSourceWx.cpp
+++ b/WebCore/platform/graphics/wx/ImageSourceWx.cpp
@@ -37,6 +37,9 @@
#include <wx/defs.h>
#include <wx/bitmap.h>
+#if USE(WXGC)
+#include <wx/graphics.h>
+#endif
#include <wx/image.h>
#include <wx/rawbmp.h>
@@ -224,7 +227,14 @@ NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
bmp->UseAlpha();
#endif
ASSERT(bmp->IsOk());
+
+#if USE(WXGC)
+ wxGraphicsBitmap* bitmap = new wxGraphicsBitmap(wxGraphicsRenderer::GetDefaultRenderer()->CreateBitmap(*bmp));
+ delete bmp;
+ return bitmap;
+#else
return bmp;
+#endif
}
float ImageSource::frameDurationAtIndex(size_t index)
diff --git a/WebCore/platform/graphics/wx/ImageWx.cpp b/WebCore/platform/graphics/wx/ImageWx.cpp
index e1d435e..b0a993e 100644
--- a/WebCore/platform/graphics/wx/ImageWx.cpp
+++ b/WebCore/platform/graphics/wx/ImageWx.cpp
@@ -26,11 +26,12 @@
#include "config.h"
#include "Image.h"
-#include "TransformationMatrix.h"
#include "BitmapImage.h"
+#include "FloatConversion.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
-#include "NotImplemented.h"
+#include "ImageObserver.h"
+#include "TransformationMatrix.h"
#include <math.h>
#include <stdio.h>
@@ -98,13 +99,13 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatR
#if USE(WXGC)
wxGCDC* context = (wxGCDC*)ctxt->platformContext();
wxGraphicsContext* gc = context->GetGraphicsContext();
+ wxGraphicsBitmap* bitmap = frameAtIndex(m_currentFrame);
#else
wxWindowDC* context = ctxt->platformContext();
+ wxBitmap* bitmap = frameAtIndex(m_currentFrame);
#endif
startAnimation();
-
- wxBitmap* bitmap = frameAtIndex(m_currentFrame);
if (!bitmap) // If it's too early we won't have an image yet.
return;
@@ -129,17 +130,15 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatR
adjustedDestRect.setLocation(FloatPoint(dst.x() - src.x() / scaleX, dst.y() - src.y() / scaleY));
adjustedDestRect.setSize(FloatSize(selfSize.width() / scaleX, selfSize.height() / scaleY));
}
-
- // If the image is only partially loaded, then shrink the destination rect that we're drawing into accordingly.
- int currHeight = bitmap->GetHeight();
- if (currHeight < selfSize.height())
- adjustedDestRect.setHeight(adjustedDestRect.height() * currHeight / selfSize.height());
- gc->PushState();
gc->Clip(dst.x(), dst.y(), dst.width(), dst.height());
+#if wxCHECK_VERSION(2,9,0)
gc->DrawBitmap(*bitmap, adjustedDestRect.x(), adjustedDestRect.y(), adjustedDestRect.width(), adjustedDestRect.height());
- gc->PopState();
#else
+ gc->DrawGraphicsBitmap(*bitmap, adjustedDestRect.x(), adjustedDestRect.y(), adjustedDestRect.width(), adjustedDestRect.height());
+#endif
+
+#else // USE(WXGC)
IntRect srcIntRect(src);
IntRect dstIntRect(dst);
bool rescaling = false;
@@ -172,6 +171,9 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatR
#endif
ctxt->restore();
+
+ if (ImageObserver* observer = imageObserver())
+ observer->didDraw(this);
}
void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, CompositeOperator, const FloatRect& dstRect)
@@ -181,21 +183,29 @@ void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, c
#if USE(WXGC)
wxGCDC* context = (wxGCDC*)ctxt->platformContext();
+ wxGraphicsBitmap* bitmap = frameAtIndex(m_currentFrame);
#else
wxWindowDC* context = ctxt->platformContext();
+ wxBitmap* bitmap = frameAtIndex(m_currentFrame);
#endif
- ctxt->save();
- ctxt->clip(IntRect(dstRect.x(), dstRect.y(), dstRect.width(), dstRect.height()));
- wxBitmap* bitmap = frameAtIndex(m_currentFrame);
if (!bitmap) // If it's too early we won't have an image yet.
return;
+
+ ctxt->save();
+ ctxt->clip(IntRect(dstRect.x(), dstRect.y(), dstRect.width(), dstRect.height()));
float currentW = 0;
float currentH = 0;
#if USE(WXGC)
wxGraphicsContext* gc = context->GetGraphicsContext();
+
+ float adjustedX = phase.x() + srcRect.x() *
+ narrowPrecisionToFloat(patternTransform.a());
+ float adjustedY = phase.y() + srcRect.y() *
+ narrowPrecisionToFloat(patternTransform.d());
+
gc->ConcatTransform(patternTransform);
#else
wxMemoryDC mydc;
@@ -208,7 +218,11 @@ void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, c
while ( currentW < dstRect.width() && currentW < clientSize.x - origin.x ) {
while ( currentH < dstRect.height() && currentH < clientSize.y - origin.y) {
#if USE(WXGC)
- gc->DrawBitmap(*bitmap, (wxDouble)dstRect.x() + currentW, (wxDouble)dstRect.y() + currentH, (wxDouble)srcRect.width(), (wxDouble)srcRect.height());
+#if wxCHECK_VERSION(2,9,0)
+ gc->DrawBitmap(*bitmap, adjustedX + currentW, adjustedY + currentH, (wxDouble)srcRect.width(), (wxDouble)srcRect.height());
+#else
+ gc->DrawGraphicsBitmap(*bitmap, adjustedX + currentW, adjustedY + currentH, (wxDouble)srcRect.width(), (wxDouble)srcRect.height());
+#endif
#else
context->Blit((wxCoord)dstRect.x() + currentW, (wxCoord)dstRect.y() + currentH,
(wxCoord)srcRect.width(), (wxCoord)srcRect.height(), &mydc,
@@ -233,6 +247,8 @@ void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, c
startAnimation();
+ if (ImageObserver* observer = imageObserver())
+ observer->didDraw(this);
}
void BitmapImage::checkForSolidColor()
diff --git a/WebCore/platform/graphics/wx/PathWx.cpp b/WebCore/platform/graphics/wx/PathWx.cpp
index 60c71d5..04a952d 100644
--- a/WebCore/platform/graphics/wx/PathWx.cpp
+++ b/WebCore/platform/graphics/wx/PathWx.cpp
@@ -66,11 +66,12 @@ Path::Path()
Path::~Path()
{
+ clear();
}
Path::Path(const Path& path)
{
- m_path = (PlatformPath*)&path.m_path;
+ m_path = new wxGraphicsPath(*path.m_path);
}
bool Path::contains(const FloatPoint& point, const WindRule rule) const
@@ -89,7 +90,7 @@ bool Path::contains(const FloatPoint& point, const WindRule rule) const
void Path::translate(const FloatSize&)
{
- notImplemented();
+ notImplemented();
}
FloatRect Path::boundingRect() const
diff --git a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
index ab50518..2368f83 100644
--- a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
+++ b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
@@ -45,7 +45,7 @@ namespace WebCore
void SimpleFontData::platformInit()
{
- wxFont *font = m_font.font();
+ wxFont *font = m_platformData.font();
if (font && font->IsOk()) {
wxFontProperties props = wxFontProperties(font);
m_ascent = props.GetAscent();
@@ -57,6 +57,13 @@ void SimpleFontData::platformInit()
}
}
+void SimpleFontData::platformCharWidthInit()
+{
+ m_avgCharWidth = 0.f;
+ m_maxCharWidth = 0.f;
+ initCharWidths();
+}
+
void SimpleFontData::platformDestroy()
{
delete m_smallCapsFontData;
@@ -81,8 +88,8 @@ bool SimpleFontData::containsCharacters(const UChar* characters, int length) con
void SimpleFontData::determinePitch()
{
- if (m_font.font() && m_font.font()->Ok())
- m_treatAsFixedPitch = m_font.font()->IsFixedWidth();
+ if (m_platformData.font() && m_platformData.font()->Ok())
+ m_treatAsFixedPitch = m_platformData.font()->IsFixedWidth();
else
m_treatAsFixedPitch = false;
}
@@ -91,7 +98,7 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
// TODO: fix this! Make GetTextExtents a method of wxFont in 2.9
int width = 10;
- GetTextExtent(*m_font.font(), (wxChar)glyph, &width, NULL);
+ GetTextExtent(*m_platformData.font(), (wxChar)glyph, &width, NULL);
return width;
}
diff --git a/WebCore/platform/graphics/wx/TransformationMatrixWx.cpp b/WebCore/platform/graphics/wx/TransformationMatrixWx.cpp
index f21dc17..9684a3c 100644
--- a/WebCore/platform/graphics/wx/TransformationMatrixWx.cpp
+++ b/WebCore/platform/graphics/wx/TransformationMatrixWx.cpp
@@ -26,9 +26,9 @@
#include "config.h"
#include "TransformationMatrix.h"
+#include "Assertions.h"
#include "FloatRect.h"
#include "IntRect.h"
-#include "NotImplemented.h"
#include <stdio.h>
#include <wx/defs.h>
diff --git a/WebCore/platform/gtk/ContextMenuItemGtk.cpp b/WebCore/platform/gtk/ContextMenuItemGtk.cpp
index cf34640..aaec206 100644
--- a/WebCore/platform/gtk/ContextMenuItemGtk.cpp
+++ b/WebCore/platform/gtk/ContextMenuItemGtk.cpp
@@ -56,10 +56,8 @@ static const char* gtkStockIDFromContextMenuAction(const ContextMenuAction& acti
return GTK_STOCK_PASTE;
case ContextMenuItemTagDelete:
return GTK_STOCK_DELETE;
-#if GTK_CHECK_VERSION(2, 10, 0)
case ContextMenuItemTagSelectAll:
return GTK_STOCK_SELECT_ALL;
-#endif
case ContextMenuItemTagSpellingGuess:
return GTK_STOCK_INFO;
case ContextMenuItemTagIgnoreSpelling:
diff --git a/WebCore/platform/gtk/CursorGtk.cpp b/WebCore/platform/gtk/CursorGtk.cpp
index 76f6d00..115760e 100644
--- a/WebCore/platform/gtk/CursorGtk.cpp
+++ b/WebCore/platform/gtk/CursorGtk.cpp
@@ -28,7 +28,6 @@
#include "config.h"
#include "CursorGtk.h"
-#include "NotImplemented.h"
#include <wtf/Assertions.h>
#include <gdk/gdk.h>
@@ -63,7 +62,13 @@ Cursor::Cursor(const Cursor& other)
Cursor::Cursor(Image*, const IntPoint&)
{
- notImplemented();
+ // FIXME: We don't support images for cursors yet.
+ // This is just a placeholder to avoid crashes.
+ Cursor other(crossCursor());
+ m_impl = other.m_impl;
+
+ if (m_impl)
+ gdk_cursor_ref(m_impl);
}
Cursor::~Cursor()
@@ -204,13 +209,13 @@ const Cursor& northWestSouthEastResizeCursor()
const Cursor& columnResizeCursor()
{
- static Cursor c = gdk_cursor_new(GDK_DOUBLE_ARROW);
+ static Cursor c = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
return c;
}
const Cursor& rowResizeCursor()
{
- static Cursor c = gdk_cursor_new(GDK_DOUBLE_ARROW);
+ static Cursor c = gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
return c;
}
@@ -268,8 +273,8 @@ const Cursor& verticalTextCursor()
const Cursor& cellCursor()
{
- notImplemented();
- return pointerCursor();
+ static Cursor c = gdk_cursor_new(GDK_PLUS);
+ return c;
}
const Cursor& contextMenuCursor()
@@ -280,8 +285,8 @@ const Cursor& contextMenuCursor()
const Cursor& noDropCursor()
{
- notImplemented();
- return pointerCursor();
+ static Cursor c = customCursorNew(CustomCursorNoDrop);
+ return c;
}
const Cursor& copyCursor()
@@ -292,8 +297,8 @@ const Cursor& copyCursor()
const Cursor& progressCursor()
{
- notImplemented();
- return pointerCursor();
+ static Cursor c = customCursorNew(CustomCursorProgress);
+ return c;
}
const Cursor& aliasCursor()
@@ -304,14 +309,13 @@ const Cursor& aliasCursor()
const Cursor& noneCursor()
{
- notImplemented();
- return pointerCursor();
+ static Cursor c = customCursorNew(CustomCursorNone);
+ return c;
}
const Cursor& notAllowedCursor()
{
- notImplemented();
- return pointerCursor();
+ return noDropCursor();
}
const Cursor& zoomInCursor()
@@ -328,14 +332,14 @@ const Cursor& zoomOutCursor()
const Cursor& grabCursor()
{
- notImplemented();
- return pointerCursor();
+ static Cursor c = customCursorNew(CustomCursorGrab);
+ return c;
}
const Cursor& grabbingCursor()
{
- notImplemented();
- return pointerCursor();
+ static Cursor c = customCursorNew(CustomCursorGrabbing);
+ return c;
}
}
diff --git a/WebCore/platform/gtk/CursorGtk.h b/WebCore/platform/gtk/CursorGtk.h
index 73f05a9..85aaefa 100644
--- a/WebCore/platform/gtk/CursorGtk.h
+++ b/WebCore/platform/gtk/CursorGtk.h
@@ -1,23 +1,40 @@
-/*
- * Copyright (C) 2001 Tim Copperfield <timecop@network.email.ne.jp>
- * Copyright (C) 2007 Christian Dywan <christian@twotoasts.de>
+/* ***** 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.
*
- * 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.
+ * The Original Code is mozilla.org code.
*
- * 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.
+ * The Initial Developer of the Original Code is
+ * Tim Copperfield.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
*
- * 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.
+ * Contributor(s):
+ * Tim Copperfield <timecop@network.email.ne.jp>
+ * Christian Dywan <christian@twotoasts.de>
*
- */
+ * 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 ***** */
#ifndef CursorGtk_h
#define CursorGtk_h
@@ -191,31 +208,176 @@ static const char moz_zoom_out_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+/* MOZ_CURSOR_NOT_ALLOWED */
+static const char moz_not_allowed_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00,
+ 0xf0, 0xf0, 0x00, 0x00, 0x38, 0xc0, 0x01, 0x00, 0x7c, 0x80, 0x03, 0x00,
+ 0xec, 0x00, 0x03, 0x00, 0xce, 0x01, 0x07, 0x00, 0x86, 0x03, 0x06, 0x00,
+ 0x06, 0x07, 0x06, 0x00, 0x06, 0x0e, 0x06, 0x00, 0x06, 0x1c, 0x06, 0x00,
+ 0x0e, 0x38, 0x07, 0x00, 0x0c, 0x70, 0x03, 0x00, 0x1c, 0xe0, 0x03, 0x00,
+ 0x38, 0xc0, 0x01, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00,
+ 0x80, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static const char moz_not_allowed_mask_bits[] = {
+ 0x80, 0x1f, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00,
+ 0xf8, 0xff, 0x01, 0x00, 0xfc, 0xf0, 0x03, 0x00, 0xfe, 0xc0, 0x07, 0x00,
+ 0xfe, 0x81, 0x07, 0x00, 0xff, 0x83, 0x0f, 0x00, 0xcf, 0x07, 0x0f, 0x00,
+ 0x8f, 0x0f, 0x0f, 0x00, 0x0f, 0x1f, 0x0f, 0x00, 0x0f, 0x3e, 0x0f, 0x00,
+ 0x1f, 0xfc, 0x0f, 0x00, 0x1e, 0xf8, 0x07, 0x00, 0x3e, 0xf0, 0x07, 0x00,
+ 0xfc, 0xf0, 0x03, 0x00, 0xf8, 0xff, 0x01, 0x00, 0xf0, 0xff, 0x00, 0x00,
+ 0xe0, 0x7f, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+/* MOZ_CURSOR_SPINNING */
+static const char moz_spinning_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00,
+ 0xfc, 0x3b, 0x00, 0x00, 0x7c, 0x38, 0x00, 0x00, 0x6c, 0x54, 0x00, 0x00,
+ 0xc4, 0xdc, 0x00, 0x00, 0xc0, 0x44, 0x00, 0x00, 0x80, 0x39, 0x00, 0x00,
+ 0x80, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static const char moz_spinning_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x1e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
+ 0xfe, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x3b, 0x00, 0x00,
+ 0xfe, 0x7f, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00,
+ 0xee, 0xff, 0x01, 0x00, 0xe4, 0xff, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00,
+ 0xc0, 0x7f, 0x00, 0x00, 0x80, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+/* MOZ_CURSOR_NONE */
+static const char moz_none_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static const char moz_none_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+/* MOZ_CURSOR_HAND_GRAB */
+static const char moz_hand_grab_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
+ 0x60, 0x39, 0x00, 0x00, 0x90, 0x49, 0x00, 0x00, 0x90, 0x49, 0x01, 0x00,
+ 0x20, 0xc9, 0x02, 0x00, 0x20, 0x49, 0x02, 0x00, 0x58, 0x40, 0x02, 0x00,
+ 0x64, 0x00, 0x02, 0x00, 0x44, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x10, 0x80, 0x00, 0x00, 0x20, 0x80, 0x00, 0x00,
+ 0x40, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static const char moz_hand_grab_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x60, 0x3f, 0x00, 0x00,
+ 0xf0, 0x7f, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00, 0xf8, 0xff, 0x03, 0x00,
+ 0xf0, 0xff, 0x07, 0x00, 0xf8, 0xff, 0x07, 0x00, 0xfc, 0xff, 0x07, 0x00,
+ 0xfe, 0xff, 0x07, 0x00, 0xfe, 0xff, 0x03, 0x00, 0xfc, 0xff, 0x03, 0x00,
+ 0xf8, 0xff, 0x03, 0x00, 0xf8, 0xff, 0x01, 0x00, 0xf0, 0xff, 0x01, 0x00,
+ 0xe0, 0xff, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+/* MOZ_CURSOR_HAND_GRABBING */
+static const char moz_hand_grabbing_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0x36, 0x00, 0x00, 0x20, 0xc9, 0x00, 0x00, 0x20, 0x40, 0x01, 0x00,
+ 0x40, 0x00, 0x01, 0x00, 0x60, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x10, 0x80, 0x00, 0x00, 0x20, 0x80, 0x00, 0x00,
+ 0x40, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static const char moz_hand_grabbing_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x36, 0x00, 0x00,
+ 0xe0, 0xff, 0x00, 0x00, 0xf0, 0xff, 0x01, 0x00, 0xf0, 0xff, 0x03, 0x00,
+ 0xe0, 0xff, 0x03, 0x00, 0xf0, 0xff, 0x03, 0x00, 0xf8, 0xff, 0x03, 0x00,
+ 0xf8, 0xff, 0x03, 0x00, 0xf8, 0xff, 0x01, 0x00, 0xf0, 0xff, 0x01, 0x00,
+ 0xe0, 0xff, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
enum CustomCursorType {
- CustomCursorCopy = 0,
- CustomCursorAlias,
- CustomCursorContextMenu,
- CustomCursorZoomIn,
- CustomCursorZoomOut,
- CustomCursorVerticalText
-} ;
+ CustomCursorCopy = 0,
+ CustomCursorAlias,
+ CustomCursorContextMenu,
+ CustomCursorZoomIn,
+ CustomCursorZoomOut,
+ CustomCursorVerticalText,
+ CustomCursorNoDrop,
+ CustomCursorProgress,
+ CustomCursorNone,
+ CustomCursorGrab,
+ CustomCursorGrabbing,
+};
typedef struct {
- const char* name;
- const char* bits;
- const char* mask_bits;
- int hot_x;
- int hot_y;
+ const char* name;
+ const char* bits;
+ const char* mask_bits;
+ int hot_x;
+ int hot_y;
} CustomCursor;
// create custom pixmap cursor from cursors in nsGTKCursorData.h
static const CustomCursor CustomCursors[] = {
- { "copy", moz_copy_bits, moz_copy_mask_bits, 2, 2 },
- { "alias", moz_alias_bits, moz_alias_mask_bits, 2, 2 },
- { "context-menu", moz_menu_bits, moz_menu_mask_bits, 2, 2 },
- { "zoom-in", moz_zoom_in_bits, moz_zoom_in_mask_bits, 6, 6 },
- { "zoom-out", moz_zoom_out_bits, moz_zoom_out_mask_bits, 6, 6 },
- { "vertical-text", moz_vertical_text_bits, moz_vertical_text_mask_bits, 8, 4 },
+ { "copy", moz_copy_bits, moz_copy_mask_bits, 2, 2 },
+ { "alias", moz_alias_bits, moz_alias_mask_bits, 2, 2 },
+ { "context-menu", moz_menu_bits, moz_menu_mask_bits, 2, 2 },
+ { "zoom-in", moz_zoom_in_bits, moz_zoom_in_mask_bits, 6, 6 },
+ { "zoom-out", moz_zoom_out_bits, moz_zoom_out_mask_bits, 6, 6 },
+ { "vertical-text", moz_vertical_text_bits, moz_vertical_text_mask_bits, 8, 4 },
+ { "dnd-no-drop", moz_not_allowed_bits, moz_not_allowed_mask_bits, 9, 9 },
+ { "progress", moz_spinning_bits, moz_spinning_mask_bits, 2, 2},
+ { "none", moz_none_bits, moz_none_mask_bits, 0, 0 },
+ { "grab", moz_hand_grab_bits, moz_hand_grab_mask_bits, 10, 10 },
+ { "grabbing", moz_hand_grabbing_bits, moz_hand_grabbing_mask_bits, 10, 10 }
};
#endif // CursorGtk_h
diff --git a/WebCore/platform/gtk/FileChooserGtk.cpp b/WebCore/platform/gtk/FileChooserGtk.cpp
index e984718..a25d88b 100644
--- a/WebCore/platform/gtk/FileChooserGtk.cpp
+++ b/WebCore/platform/gtk/FileChooserGtk.cpp
@@ -34,7 +34,6 @@
#include "StringTruncator.h"
#include <glib.h>
-#include <glib/gi18n.h>
#include <gtk/gtk.h>
namespace WebCore {
diff --git a/WebCore/platform/gtk/FileSystemGtk.cpp b/WebCore/platform/gtk/FileSystemGtk.cpp
index 94e06db..fcdc863 100644
--- a/WebCore/platform/gtk/FileSystemGtk.cpp
+++ b/WebCore/platform/gtk/FileSystemGtk.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2007, 2009 Holger Hans Peter Freyther
* Copyright (C) 2008 Collabora, Ltd.
* Copyright (C) 2008 Apple Inc. All rights reserved.
*
@@ -22,8 +22,7 @@
#include "config.h"
#include "FileSystem.h"
-#include "guriescape.h"
-#include "NotImplemented.h"
+#include "GOwnPtr.h"
#include "PlatformString.h"
#include "CString.h"
@@ -180,6 +179,9 @@ String homeDirectoryPath()
String pathGetFileName(const String& pathName)
{
+ if (pathName.isEmpty())
+ return pathName;
+
char* tmpFilename = filenameFromString(pathName);
char* baseName = g_path_get_basename(tmpFilename);
String fileName = String::fromUTF8(baseName);
@@ -191,8 +193,10 @@ String pathGetFileName(const String& pathName)
String directoryName(const String& path)
{
- notImplemented();
- return String();
+ /* No null checking needed */
+ GOwnPtr<char> tmpFilename(filenameFromString(path));
+ GOwnPtr<char> dirname(g_path_get_dirname(tmpFilename.get()));
+ return String::fromUTF8(dirname.get());
}
Vector<String> listDirectory(const String& path, const String& filter)
diff --git a/WebCore/platform/gtk/GeolocationServiceGtk.cpp b/WebCore/platform/gtk/GeolocationServiceGtk.cpp
index cc69d44..fc15833 100644
--- a/WebCore/platform/gtk/GeolocationServiceGtk.cpp
+++ b/WebCore/platform/gtk/GeolocationServiceGtk.cpp
@@ -181,8 +181,8 @@ void GeolocationServiceGtk::updatePosition()
m_lastError = 0;
RefPtr<Coordinates> coordinates = Coordinates::create(m_latitude, m_longitude,
- m_altitude, m_accuracy,
- m_altitudeAccuracy, 0.0, 0.0);
+ true, m_altitude, m_accuracy,
+ true, m_altitudeAccuracy, false, 0.0, false, 0.0);
m_lastPosition = Geoposition::create(coordinates.release(), m_timestamp * 1000.0);
positionChanged();
}
diff --git a/WebCore/platform/gtk/GtkPluginWidget.cpp b/WebCore/platform/gtk/GtkPluginWidget.cpp
new file mode 100644
index 0000000..bc2dd92
--- /dev/null
+++ b/WebCore/platform/gtk/GtkPluginWidget.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2009 Holger Hans Peter Freyther
+ * 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 "GtkPluginWidget.h"
+
+#include "GraphicsContext.h"
+#include "ScrollView.h"
+
+#include <gtk/gtk.h>
+
+namespace WebCore {
+
+GtkPluginWidget::GtkPluginWidget(GtkWidget* widget)
+ : Widget(widget)
+{
+ gtk_widget_hide(widget);
+}
+
+void GtkPluginWidget::invalidateRect(const IntRect& _rect)
+{
+ /* no need to */
+ if (GTK_WIDGET_NO_WINDOW(platformWidget()))
+ return;
+
+ GdkWindow* window = platformWidget()->window;
+ if (!window)
+ return;
+
+ GdkRectangle rect = _rect;
+ gdk_window_invalidate_rect(window, &rect, FALSE);
+}
+
+void GtkPluginWidget::frameRectsChanged()
+{
+ IntRect rect = frameRect();
+ IntPoint loc = parent()->contentsToWindow(rect.location());
+ GtkAllocation allocation = { loc.x(), loc.y(), rect.width(), rect.height() };
+
+ gtk_widget_set_size_request(platformWidget(), rect.width(), rect.height());
+ gtk_widget_size_allocate(platformWidget(), &allocation);
+ gtk_widget_show(platformWidget());
+}
+
+void GtkPluginWidget::paint(GraphicsContext* context, const IntRect& rect)
+{
+ if (!context->gdkExposeEvent())
+ return;
+
+ /* only paint widgets with NO_WINDOW this way */
+ if (!GTK_WIDGET_NO_WINDOW(platformWidget()))
+ return;
+
+ GtkWidget* widget = platformWidget();
+ ASSERT(GTK_WIDGET_NO_WINDOW(widget));
+
+ GdkEvent* event = gdk_event_new(GDK_EXPOSE);
+ event->expose = *context->gdkExposeEvent();
+ event->expose.area = static_cast<GdkRectangle>(rect);
+
+ IntPoint loc = parent()->contentsToWindow(rect.location());
+
+ event->expose.area.x = loc.x();
+ event->expose.area.y = loc.y();
+
+ event->expose.region = gdk_region_rectangle(&event->expose.area);
+
+ /*
+ * This will be unref'ed by gdk_event_free.
+ */
+ g_object_ref(event->expose.window);
+
+ /*
+ * If we are going to paint do the translation and GtkAllocation manipulation.
+ */
+ if (!gdk_region_empty(event->expose.region))
+ gtk_widget_send_expose(widget, event);
+
+ gdk_event_free(event);
+}
+
+}
diff --git a/WebCore/platform/network/cf/ResourceResponseCFNet.h b/WebCore/platform/gtk/GtkPluginWidget.h
index 27144c6..cad3462 100644
--- a/WebCore/platform/network/cf/ResourceResponseCFNet.h
+++ b/WebCore/platform/gtk/GtkPluginWidget.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2009 Holger Hans Peter Freyther
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -20,20 +21,22 @@
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ResourceResponseCFNet_h
-#define ResourceResponseCFNet_h
+#ifndef GtkPluginWidget_h
+#define GtkPluginWidget_h
-typedef struct _CFURLResponse* CFURLResponseRef;
+#include "Widget.h"
namespace WebCore {
-
- class ResourceResponse;
-
- void getResourceResponse(ResourceResponse& response, CFURLResponseRef cfResponse);
-
+ class GtkPluginWidget : public Widget {
+ public:
+ GtkPluginWidget(GtkWidget*);
+ void invalidateRect(const IntRect&);
+ void frameRectsChanged();
+ void paint(GraphicsContext*, const IntRect&);
+ };
}
-#endif // ResourceResponseCFNet_h
+#endif
diff --git a/WebCore/platform/gtk/KeyEventGtk.cpp b/WebCore/platform/gtk/KeyEventGtk.cpp
index e0742f4..5875547 100644
--- a/WebCore/platform/gtk/KeyEventGtk.cpp
+++ b/WebCore/platform/gtk/KeyEventGtk.cpp
@@ -37,9 +37,6 @@
#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
-// GTK_CHECK_VERSION is defined in gtk/gtkversion.h
-#include <gtk/gtk.h>
-
namespace WebCore {
// FIXME: This is incomplete. We should change this to mirror
@@ -260,9 +257,10 @@ static int windowsKeyCodeForKeyEvent(unsigned int keycode)
case GDK_Help:
return VK_HELP; // (2F) HELP key
case GDK_0:
- case GDK_parenleft:
+ case GDK_parenright:
return VK_0; // (30) 0) key
case GDK_1:
+ case GDK_exclam:
return VK_1; // (31) 1 ! key
case GDK_2:
case GDK_at:
@@ -286,7 +284,7 @@ static int windowsKeyCodeForKeyEvent(unsigned int keycode)
case GDK_asterisk:
return VK_8; // (38) 8 key '*'
case GDK_9:
- case GDK_parenright:
+ case GDK_parenleft:
return VK_9; // (39) 9 key '('
case GDK_a:
case GDK_A:
@@ -536,12 +534,7 @@ PlatformKeyboardEvent::PlatformKeyboardEvent(GdkEventKey* event)
, m_shiftKey((event->state & GDK_SHIFT_MASK) || (event->keyval == GDK_3270_BackTab))
, m_ctrlKey(event->state & GDK_CONTROL_MASK)
, m_altKey(event->state & GDK_MOD1_MASK)
-#if GTK_CHECK_VERSION(2,10,0)
, m_metaKey(event->state & GDK_META_MASK)
-#else
- // GDK_MOD2_MASK doesn't always mean meta so we can't use it
- , m_metaKey(false)
-#endif
, m_gdkEventKey(event)
{
}
diff --git a/WebCore/platform/gtk/KeyboardCodes.h b/WebCore/platform/gtk/KeyboardCodes.h
deleted file mode 100644
index 3ad1243..0000000
--- a/WebCore/platform/gtk/KeyboardCodes.h
+++ /dev/null
@@ -1,543 +0,0 @@
-/*
- * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
- * 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 KeyboardCodes_h
-#define KeyboardCodes_h
-
-namespace WebCore {
-
-// VK_LBUTTON (01) Left mouse button
-// VK_RBUTTON (02) Right mouse button
-// VK_CANCEL (03) Control-break processing
-// VK_MBUTTON (04) Middle mouse button (three-button mouse)
-// VK_XBUTTON1 (05)
-// VK_XBUTTON2 (06)
-
-// VK_BACK (08) BACKSPACE key
-const int VK_BACK = 0x08;
-
-// VK_TAB (09) TAB key
-const int VK_TAB = 0x09;
-
-// VK_CLEAR (0C) CLEAR key
-const int VK_CLEAR = 0x0C;
-
-// VK_RETURN (0D)
-const int VK_RETURN = 0x0D;
-
-// VK_SHIFT (10) SHIFT key
-const int VK_SHIFT = 0x10;
-
-// VK_CONTROL (11) CTRL key
-const int VK_CONTROL = 0x11;
-
-// VK_MENU (12) ALT key
-const int VK_MENU = 0x12;
-
-// VK_PAUSE (13) PAUSE key
-const int VK_PAUSE = 0x13;
-
-// VK_CAPITAL (14) CAPS LOCK key
-const int VK_CAPITAL = 0x14;
-
-// VK_KANA (15) Input Method Editor (IME) Kana mode
-const int VK_KANA = 0x15;
-
-// VK_HANGUEL (15) IME Hanguel mode (maintained for compatibility; use VK_HANGUL)
-// VK_HANGUL (15) IME Hangul mode
-const int VK_HANGUL = 0x15;
-
-// VK_JUNJA (17) IME Junja mode
-const int VK_JUNJA = 0x17;
-
-// VK_FINAL (18) IME final mode
-const int VK_FINAL = 0x18;
-
-// VK_HANJA (19) IME Hanja mode
-const int VK_HANJA = 0x19;
-
-// VK_KANJI (19) IME Kanji mode
-const int VK_KANJI = 0x19;
-
-// VK_ESCAPE (1B) ESC key
-const int VK_ESCAPE = 0x1B;
-
-// VK_CONVERT (1C) IME convert
-const int VK_CONVERT = 0x1C;
-
-// VK_NONCONVERT (1D) IME nonconvert
-const int VK_NONCONVERT = 0x1D;
-
-// VK_ACCEPT (1E) IME accept
-const int VK_ACCEPT = 0x1E;
-
-// VK_MODECHANGE (1F) IME mode change request
-const int VK_MODECHANGE = 0x1F;
-
-// VK_SPACE (20) SPACEBAR
-const int VK_SPACE = 0x20;
-
-// VK_PRIOR (21) PAGE UP key
-const int VK_PRIOR = 0x21;
-
-// VK_NEXT (22) PAGE DOWN key
-const int VK_NEXT = 0x22;
-
-// VK_END (23) END key
-const int VK_END = 0x23;
-
-// VK_HOME (24) HOME key
-const int VK_HOME = 0x24;
-
-// VK_LEFT (25) LEFT ARROW key
-const int VK_LEFT = 0x25;
-
-// VK_UP (26) UP ARROW key
-const int VK_UP = 0x26;
-
-// VK_RIGHT (27) RIGHT ARROW key
-const int VK_RIGHT = 0x27;
-
-// VK_DOWN (28) DOWN ARROW key
-const int VK_DOWN = 0x28;
-
-// VK_SELECT (29) SELECT key
-const int VK_SELECT = 0x29;
-
-// VK_PRINT (2A) PRINT key
-const int VK_PRINT = 0x2A;
-
-// VK_EXECUTE (2B) EXECUTE key
-const int VK_EXECUTE = 0x2B;
-
-// VK_SNAPSHOT (2C) PRINT SCREEN key
-const int VK_SNAPSHOT = 0x2C;
-
-// VK_INSERT (2D) INS key
-const int VK_INSERT = 0x2D;
-
-// VK_DELETE (2E) DEL key
-const int VK_DELETE = 0x2E;
-
-// VK_HELP (2F) HELP key
-const int VK_HELP = 0x2F;
-
-// (30) 0 key
-const int VK_0 = 0x30;
-
-// (31) 1 key
-const int VK_1 = 0x31;
-
-// (32) 2 key
-const int VK_2 = 0x32;
-
-// (33) 3 key
-const int VK_3 = 0x33;
-
-// (34) 4 key
-const int VK_4 = 0x34;
-
-// (35) 5 key;
-
-const int VK_5 = 0x35;
-
-// (36) 6 key
-const int VK_6 = 0x36;
-
-// (37) 7 key
-const int VK_7 = 0x37;
-
-// (38) 8 key
-const int VK_8 = 0x38;
-
-// (39) 9 key
-const int VK_9 = 0x39;
-
-// (41) A key
-const int VK_A = 0x41;
-
-// (42) B key
-const int VK_B = 0x42;
-
-// (43) C key
-const int VK_C = 0x43;
-
-// (44) D key
-const int VK_D = 0x44;
-
-// (45) E key
-const int VK_E = 0x45;
-
-// (46) F key
-const int VK_F = 0x46;
-
-// (47) G key
-const int VK_G = 0x47;
-
-// (48) H key
-const int VK_H = 0x48;
-
-// (49) I key
-const int VK_I = 0x49;
-
-// (4A) J key
-const int VK_J = 0x4A;
-
-// (4B) K key
-const int VK_K = 0x4B;
-
-// (4C) L key
-const int VK_L = 0x4C;
-
-// (4D) M key
-const int VK_M = 0x4D;
-
-// (4E) N key
-const int VK_N = 0x4E;
-
-// (4F) O key
-const int VK_O = 0x4F;
-
-// (50) P key
-const int VK_P = 0x50;
-
-// (51) Q key
-const int VK_Q = 0x51;
-
-// (52) R key
-const int VK_R = 0x52;
-
-// (53) S key
-const int VK_S = 0x53;
-
-// (54) T key
-const int VK_T = 0x54;
-
-// (55) U key
-const int VK_U = 0x55;
-
-// (56) V key
-const int VK_V = 0x56;
-
-// (57) W key
-const int VK_W = 0x57;
-
-// (58) X key
-const int VK_X = 0x58;
-
-// (59) Y key
-const int VK_Y = 0x59;
-
-// (5A) Z key
-const int VK_Z = 0x5A;
-
-// VK_LWIN (5B) Left Windows key (Microsoft Natural keyboard)
-const int VK_LWIN = 0x5B;
-
-// VK_RWIN (5C) Right Windows key (Natural keyboard)
-const int VK_RWIN = 0x5C;
-
-// VK_APPS (5D) Applications key (Natural keyboard)
-const int VK_APPS = 0x5D;
-
-// VK_SLEEP (5F) Computer Sleep key
-const int VK_SLEEP = 0x5F;
-
-// VK_NUMPAD0 (60) Numeric keypad 0 key
-const int VK_NUMPAD0 = 0x60;
-
-// VK_NUMPAD1 (61) Numeric keypad 1 key
-const int VK_NUMPAD1 = 0x61;
-
-// VK_NUMPAD2 (62) Numeric keypad 2 key
-const int VK_NUMPAD2 = 0x62;
-
-// VK_NUMPAD3 (63) Numeric keypad 3 key
-const int VK_NUMPAD3 = 0x63;
-
-// VK_NUMPAD4 (64) Numeric keypad 4 key
-const int VK_NUMPAD4 = 0x64;
-
-// VK_NUMPAD5 (65) Numeric keypad 5 key
-const int VK_NUMPAD5 = 0x65;
-
-// VK_NUMPAD6 (66) Numeric keypad 6 key
-const int VK_NUMPAD6 = 0x66;
-
-// VK_NUMPAD7 (67) Numeric keypad 7 key
-const int VK_NUMPAD7 = 0x67;
-
-// VK_NUMPAD8 (68) Numeric keypad 8 key
-const int VK_NUMPAD8 = 0x68;
-
-// VK_NUMPAD9 (69) Numeric keypad 9 key
-const int VK_NUMPAD9 = 0x69;
-
-// VK_MULTIPLY (6A) Multiply key
-const int VK_MULTIPLY = 0x6A;
-
-// VK_ADD (6B) Add key
-const int VK_ADD = 0x6B;
-
-// VK_SEPARATOR (6C) Separator key
-const int VK_SEPARATOR = 0x6C;
-
-// VK_SUBTRACT (6D) Subtract key
-const int VK_SUBTRACT = 0x6D;
-
-// VK_DECIMAL (6E) Decimal key
-const int VK_DECIMAL = 0x6E;
-
-// VK_DIVIDE (6F) Divide key
-const int VK_DIVIDE = 0x6F;
-
-// VK_F1 (70) F1 key
-const int VK_F1 = 0x70;
-
-// VK_F2 (71) F2 key
-const int VK_F2 = 0x71;
-
-// VK_F3 (72) F3 key
-const int VK_F3 = 0x72;
-
-// VK_F4 (73) F4 key
-const int VK_F4 = 0x73;
-
-// VK_F5 (74) F5 key
-const int VK_F5 = 0x74;
-
-// VK_F6 (75) F6 key
-const int VK_F6 = 0x75;
-
-// VK_F7 (76) F7 key
-const int VK_F7 = 0x76;
-
-// VK_F8 (77) F8 key
-const int VK_F8 = 0x77;
-
-// VK_F9 (78) F9 key
-const int VK_F9 = 0x78;
-
-// VK_F10 (79) F10 key
-const int VK_F10 = 0x79;
-
-// VK_F11 (7A) F11 key
-const int VK_F11 = 0x7A;
-
-// VK_F12 (7B) F12 key
-const int VK_F12 = 0x7B;
-
-// VK_F13 (7C) F13 key
-const int VK_F13 = 0x7C;
-
-// VK_F14 (7D) F14 key
-const int VK_F14 = 0x7D;
-
-// VK_F15 (7E) F15 key
-const int VK_F15 = 0x7E;
-
-// VK_F16 (7F) F16 key
-const int VK_F16 = 0x7F;
-
-// VK_F17 (80H) F17 key
-const int VK_F17 = 0x80;
-
-// VK_F18 (81H) F18 key
-const int VK_F18 = 0x81;
-
-// VK_F19 (82H) F19 key
-const int VK_F19 = 0x82;
-
-// VK_F20 (83H) F20 key
-const int VK_F20 = 0x83;
-
-// VK_F21 (84H) F21 key
-const int VK_F21 = 0x84;
-
-// VK_F22 (85H) F22 key
-const int VK_F22 = 0x85;
-
-// VK_F23 (86H) F23 key
-const int VK_F23 = 0x86;
-
-// VK_F24 (87H) F24 key
-const int VK_F24 = 0x87;
-
-// VK_NUMLOCK (90) NUM LOCK key
-const int VK_NUMLOCK = 0x90;
-
-// VK_SCROLL (91) SCROLL LOCK key
-const int VK_SCROLL = 0x91;
-
-// VK_LSHIFT (A0) Left SHIFT key
-const int VK_LSHIFT = 0xA0;
-
-// VK_RSHIFT (A1) Right SHIFT key
-const int VK_RSHIFT = 0xA1;
-
-// VK_LCONTROL (A2) Left CONTROL key
-const int VK_LCONTROL = 0xA2;
-
-// VK_RCONTROL (A3) Right CONTROL key
-const int VK_RCONTROL = 0xA3;
-
-// VK_LMENU (A4) Left MENU key
-const int VK_LMENU = 0xA4;
-
-// VK_RMENU (A5) Right MENU key
-const int VK_RMENU = 0xA5;
-
-// VK_BROWSER_BACK (A6) Windows 2000/XP: Browser Back key
-const int VK_BROWSER_BACK = 0xA6;
-
-// VK_BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key
-const int VK_BROWSER_FORWARD = 0xA7;
-
-// VK_BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key
-const int VK_BROWSER_REFRESH = 0xA8;
-
-// VK_BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key
-const int VK_BROWSER_STOP = 0xA9;
-
-// VK_BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key
-const int VK_BROWSER_SEARCH = 0xAA;
-
-// VK_BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key
-const int VK_BROWSER_FAVORITES = 0xAB;
-
-// VK_BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key
-const int VK_BROWSER_HOME = 0xAC;
-
-// VK_VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key
-const int VK_VOLUME_MUTE = 0xAD;
-
-// VK_VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key
-const int VK_VOLUME_DOWN = 0xAE;
-
-// VK_VOLUME_UP (AF) Windows 2000/XP: Volume Up key
-const int VK_VOLUME_UP = 0xAF;
-
-// VK_MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key
-const int VK_MEDIA_NEXT_TRACK = 0xB0;
-
-// VK_MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key
-const int VK_MEDIA_PREV_TRACK = 0xB1;
-
-// VK_MEDIA_STOP (B2) Windows 2000/XP: Stop Media key
-const int VK_MEDIA_STOP = 0xB2;
-
-// VK_MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key
-const int VK_MEDIA_PLAY_PAUSE = 0xB3;
-
-// VK_LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key
-const int VK_MEDIA_LAUNCH_MAIL = 0xB4;
-
-// VK_LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key
-const int VK_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5;
-
-// VK_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key
-const int VK_MEDIA_LAUNCH_APP1 = 0xB6;
-
-// VK_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key
-const int VK_MEDIA_LAUNCH_APP2 = 0xB7;
-
-// VK_OEM_1 (BA) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ';:' key
-const int VK_OEM_1 = 0xBA;
-
-// VK_OEM_PLUS (BB) Windows 2000/XP: For any country/region, the '+' key
-const int VK_OEM_PLUS = 0xBB;
-
-// VK_OEM_COMMA (BC) Windows 2000/XP: For any country/region, the ',' key
-const int VK_OEM_COMMA = 0xBC;
-
-// VK_OEM_MINUS (BD) Windows 2000/XP: For any country/region, the '-' key
-const int VK_OEM_MINUS = 0xBD;
-
-// VK_OEM_PERIOD (BE) Windows 2000/XP: For any country/region, the '.' key
-const int VK_OEM_PERIOD = 0xBE;
-
-// VK_OEM_2 (BF) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key
-const int VK_OEM_2 = 0xBF;
-
-// VK_OEM_3 (C0) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key
-const int VK_OEM_3 = 0xC0;
-
-// VK_OEM_4 (DB) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key
-const int VK_OEM_4 = 0xDB;
-
-// VK_OEM_5 (DC) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key
-const int VK_OEM_5 = 0xDC;
-
-// VK_OEM_6 (DD) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key
-const int VK_OEM_6 = 0xDD;
-
-// VK_OEM_7 (DE) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key
-const int VK_OEM_7 = 0xDE;
-
-// VK_OEM_8 (DF) Used for miscellaneous characters; it can vary by keyboard.
-const int VK_OEM_8 = 0xDF;
-
-// VK_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard
-const int VK_OEM_102 = 0xE2;
-
-// VK_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key
-const int VK_PROCESSKEY = 0xE5;
-
-// VK_PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT,SendInput, WM_KEYDOWN, and WM_KEYUP
-const int VK_PACKET = 0xE7;
-
-// VK_ATTN (F6) Attn key
-const int VK_ATTN = 0xF6;
-
-// VK_CRSEL (F7) CrSel key
-const int VK_CRSEL = 0xF7;
-
-// VK_EXSEL (F8) ExSel key
-const int VK_EXSEL = 0xF8;
-
-// VK_EREOF (F9) Erase EOF key
-const int VK_EREOF = 0xF9;
-
-// VK_PLAY (FA) Play key
-const int VK_PLAY = 0xFA;
-
-// VK_ZOOM (FB) Zoom key
-const int VK_ZOOM = 0xFB;
-
-// VK_NONAME (FC) Reserved for future use
-const int VK_NONAME = 0xFC;
-
-// VK_PA1 (FD) PA1 key
-const int VK_PA1 = 0xFD;
-
-// VK_OEM_CLEAR (FE) Clear key
-const int VK_OEM_CLEAR = 0xFE;
-
-const int VK_UNKNOWN = 0;
-
-}
-
-#endif
diff --git a/WebCore/platform/gtk/LocalizedStringsGtk.cpp b/WebCore/platform/gtk/LocalizedStringsGtk.cpp
index 52d4f5f..70e3aff 100644
--- a/WebCore/platform/gtk/LocalizedStringsGtk.cpp
+++ b/WebCore/platform/gtk/LocalizedStringsGtk.cpp
@@ -30,11 +30,14 @@
#include "config.h"
#include "LocalizedStrings.h"
+#include "CString.h"
+#include "GOwnPtr.h"
+#include "IntSize.h"
#include "NotImplemented.h"
#include "PlatformString.h"
+#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
-#include <glib/gi18n.h>
namespace WebCore {
@@ -125,11 +128,7 @@ String contextMenuItemTagDelete()
String contextMenuItemTagSelectAll()
{
-#if GTK_CHECK_VERSION(2,10,0)
static String stockLabel = String::fromUTF8(gtkStockLabel(GTK_STOCK_SELECT_ALL));
-#else
- static String stockLabel = String::fromUTF8(_("Select _All"));
-#endif
return stockLabel;
}
@@ -339,8 +338,11 @@ String unknownFileSizeText()
String imageTitle(const String& filename, const IntSize& size)
{
- notImplemented();
- return String();
+ GOwnPtr<gchar> string(g_strdup_printf(C_("Title string for images", "%s (%dx%d pixels)"),
+ filename.utf8().data(),
+ size.width(), size.height()));
+
+ return String::fromUTF8(string.get());
}
}
diff --git a/WebCore/platform/gtk/MouseEventGtk.cpp b/WebCore/platform/gtk/MouseEventGtk.cpp
index 2400ebf..69f938f 100644
--- a/WebCore/platform/gtk/MouseEventGtk.cpp
+++ b/WebCore/platform/gtk/MouseEventGtk.cpp
@@ -31,9 +31,6 @@
#include <gdk/gdk.h>
-// GTK_CHECK_VERSION is defined in gtk/gtkversion.h
-#include <gtk/gtk.h>
-
namespace WebCore {
// FIXME: Would be even better to figure out which modifier is Alt instead of always using GDK_MOD1_MASK.
@@ -47,12 +44,7 @@ PlatformMouseEvent::PlatformMouseEvent(GdkEventButton* event)
m_shiftKey = event->state & GDK_SHIFT_MASK;
m_ctrlKey = event->state & GDK_CONTROL_MASK;
m_altKey = event->state & GDK_MOD1_MASK;
-#if GTK_CHECK_VERSION(2,10,0)
m_metaKey = event->state & GDK_META_MASK;
-#else
- // GDK_MOD2_MASK doesn't always mean meta so we can't use it
- m_metaKey = false;
-#endif
switch (event->type) {
case GDK_BUTTON_PRESS:
diff --git a/WebCore/platform/gtk/PasteboardGtk.cpp b/WebCore/platform/gtk/PasteboardGtk.cpp
index 15a7e64..062ecb8 100644
--- a/WebCore/platform/gtk/PasteboardGtk.cpp
+++ b/WebCore/platform/gtk/PasteboardGtk.cpp
@@ -103,7 +103,6 @@ void Pasteboard::setHelper(PasteboardHelper* helper)
void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
{
GtkClipboard* clipboard = m_helper->getClipboard(frame);
-#if GTK_CHECK_VERSION(2,10,0)
gchar* text = g_strdup(frame->selectedText().utf8().data());
gchar* markup = g_strdup(createMarkup(selectedRange, 0, AnnotateForInterchange).utf8().data());
PasteboardSelectionData* data = new PasteboardSelectionData(text, markup);
@@ -113,9 +112,6 @@ void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete,
gtk_clipboard_set_with_data(clipboard, targets, n_targets,
clipboard_get_contents_cb, clipboard_clear_contents_cb, data);
gtk_target_table_free(targets, n_targets);
-#else
- gtk_clipboard_set_text(clipboard, frame->selectedText().utf8().data(), frame->selectedText().utf8().length());
-#endif
}
void Pasteboard::writeURL(const KURL& url, const String&, Frame* frame)
@@ -124,14 +120,13 @@ void Pasteboard::writeURL(const KURL& url, const String&, Frame* frame)
return;
GtkClipboard* clipboard = m_helper->getClipboard(frame);
+ GtkClipboard* primary = m_helper->getPrimary(frame);
gtk_clipboard_set_text(clipboard, url.string().utf8().data(), url.string().utf8().length());
+ gtk_clipboard_set_text(primary, url.string().utf8().data(), url.string().utf8().length());
}
void Pasteboard::writeImage(Node* node, const KURL&, const String&)
{
- // TODO: Enable this when Image gets GdkPixbuf support
-
- /*
GtkClipboard* clipboard = gtk_clipboard_get_for_display(gdk_display_get_default(), GDK_SELECTION_CLIPBOARD);
ASSERT(node && node->renderer() && node->renderer()->isImage());
@@ -141,10 +136,9 @@ void Pasteboard::writeImage(Node* node, const KURL&, const String&)
Image* image = cachedImage->image();
ASSERT(image);
- gtk_clipboard_set_image(clipboard, image->pixbuf());
- */
-
- notImplemented();
+ GdkPixbuf* pixbuf = image->getGdkPixbuf();
+ gtk_clipboard_set_image(clipboard, pixbuf);
+ g_object_unref(pixbuf);
}
void Pasteboard::clear()
@@ -163,12 +157,8 @@ bool Pasteboard::canSmartReplace()
PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context,
bool allowPlainText, bool& chosePlainText)
{
-#if GTK_CHECK_VERSION(2,10,0)
GdkAtom textHtml = gdk_atom_intern_static_string("text/html");
-#else
- GdkAtom textHtml = gdk_atom_intern("text/html", false);
-#endif
- GtkClipboard* clipboard = m_helper->getClipboard(frame);
+ GtkClipboard* clipboard = m_helper->getCurrentTarget(frame);
chosePlainText = false;
if (GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, textHtml)) {
@@ -201,7 +191,7 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP
String Pasteboard::plainText(Frame* frame)
{
- GtkClipboard* clipboard = m_helper->getClipboard(frame);
+ GtkClipboard* clipboard = m_helper->getCurrentTarget(frame);
gchar* utf8 = gtk_clipboard_wait_for_text(clipboard);
diff --git a/WebCore/platform/gtk/PasteboardHelper.h b/WebCore/platform/gtk/PasteboardHelper.h
index 6bdc05e..9943a2d 100644
--- a/WebCore/platform/gtk/PasteboardHelper.h
+++ b/WebCore/platform/gtk/PasteboardHelper.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 Luca Bruno <lethalman88@gmail.com>
+ * Copyright (C) 2009 Holger Hans Peter Freyther
* All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -37,7 +38,9 @@ class PasteboardHelper {
public:
virtual ~PasteboardHelper() {};
+ virtual GtkClipboard* getCurrentTarget(Frame*) const = 0;
virtual GtkClipboard* getClipboard(Frame*) const = 0;
+ virtual GtkClipboard* getPrimary(Frame*) const = 0;
virtual GtkTargetList* getCopyTargetList(Frame*) const = 0;
virtual GtkTargetList* getPasteTargetList(Frame*) const = 0;
};
diff --git a/WebCore/platform/gtk/PlatformScreenGtk.cpp b/WebCore/platform/gtk/PlatformScreenGtk.cpp
index 3512be1..27985ef 100644
--- a/WebCore/platform/gtk/PlatformScreenGtk.cpp
+++ b/WebCore/platform/gtk/PlatformScreenGtk.cpp
@@ -31,7 +31,6 @@
#include "PlatformScreen.h"
#include "HostWindow.h"
-#include "NotImplemented.h"
#include "ScrollView.h"
#include "Widget.h"
diff --git a/WebCore/platform/gtk/PopupMenuGtk.cpp b/WebCore/platform/gtk/PopupMenuGtk.cpp
index 54b41ab..121d7b0 100644
--- a/WebCore/platform/gtk/PopupMenuGtk.cpp
+++ b/WebCore/platform/gtk/PopupMenuGtk.cpp
@@ -28,7 +28,6 @@
#include "CString.h"
#include "FrameView.h"
#include "HostWindow.h"
-#include "NotImplemented.h"
#include "PlatformString.h"
#include <gtk/gtk.h>
@@ -42,8 +41,11 @@ PopupMenu::PopupMenu(PopupMenuClient* client)
PopupMenu::~PopupMenu()
{
- if (m_popup)
+ if (m_popup) {
+ g_signal_handlers_disconnect_matched(m_popup, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
+ hide();
g_object_unref(m_popup);
+ }
}
void PopupMenu::show(const IntRect& rect, FrameView* view, int index)
diff --git a/WebCore/platform/gtk/RenderThemeGtk.cpp b/WebCore/platform/gtk/RenderThemeGtk.cpp
index ee462e0..a95f557 100644
--- a/WebCore/platform/gtk/RenderThemeGtk.cpp
+++ b/WebCore/platform/gtk/RenderThemeGtk.cpp
@@ -54,6 +54,14 @@ RenderThemeGtk::RenderThemeGtk()
}
}
+RenderThemeGtk::~RenderThemeGtk()
+{
+ if (mozGtkInitialized) {
+ moz_gtk_shutdown();
+ mozGtkInitialized = false;
+ }
+}
+
static bool supportsFocus(ControlPart appearance)
{
switch (appearance) {
diff --git a/WebCore/platform/gtk/RenderThemeGtk.h b/WebCore/platform/gtk/RenderThemeGtk.h
index 76f7a0a..82a87cb 100644
--- a/WebCore/platform/gtk/RenderThemeGtk.h
+++ b/WebCore/platform/gtk/RenderThemeGtk.h
@@ -36,6 +36,7 @@ namespace WebCore {
class RenderThemeGtk : public RenderTheme {
public:
RenderThemeGtk();
+ virtual ~RenderThemeGtk();
// A method asking if the theme's controls actually care about redrawing when hovered.
virtual bool supportsHover(const RenderStyle* style) const { return true; }
diff --git a/WebCore/platform/gtk/ScrollViewGtk.cpp b/WebCore/platform/gtk/ScrollViewGtk.cpp
index b3b6dd9..0f066fc 100644
--- a/WebCore/platform/gtk/ScrollViewGtk.cpp
+++ b/WebCore/platform/gtk/ScrollViewGtk.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2006, 2007, 2008 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
- * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2007, 2009 Holger Hans Peter Freyther
* Copyright (C) 2008 Collabora Ltd.
*
* All rights reserved.
@@ -35,7 +35,6 @@
#include "GraphicsContext.h"
#include "HostWindow.h"
#include "IntRect.h"
-#include "NotImplemented.h"
#include "PlatformMouseEvent.h"
#include "PlatformWheelEvent.h"
#include "ScrollbarGtk.h"
@@ -47,28 +46,6 @@ using namespace std;
namespace WebCore {
-static void adjustmentChanged(GtkAdjustment* adjustment, gpointer _that)
-{
- ScrollView* that = reinterpret_cast<ScrollView*>(_that);
-
- // Figure out if we really moved.
- IntSize newOffset = that->scrollOffset();
- if (adjustment == that->m_horizontalAdjustment)
- newOffset.setWidth(static_cast<int>(gtk_adjustment_get_value(adjustment)));
- else if (adjustment == that->m_verticalAdjustment)
- newOffset.setHeight(static_cast<int>(gtk_adjustment_get_value(adjustment)));
-
- IntSize scrollDelta = newOffset - that->scrollOffset();
- if (scrollDelta == IntSize())
- return;
- that->setScrollOffset(newOffset);
-
- if (that->scrollbarsSuppressed())
- return;
-
- that->scrollContents(scrollDelta);
-}
-
void ScrollView::platformInit()
{
m_horizontalAdjustment = 0;
@@ -77,15 +54,18 @@ void ScrollView::platformInit()
void ScrollView::platformDestroy()
{
- if (m_horizontalAdjustment) {
- g_signal_handlers_disconnect_by_func(G_OBJECT(m_horizontalAdjustment), (gpointer)adjustmentChanged, this);
- g_object_unref(m_horizontalAdjustment);
- }
+ m_horizontalAdjustment = 0;
+ m_verticalAdjustment = 0;
+}
- if (m_verticalAdjustment) {
- g_signal_handlers_disconnect_by_func(G_OBJECT(m_verticalAdjustment), (gpointer)adjustmentChanged, this);
- g_object_unref(m_verticalAdjustment);
- }
+PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientation)
+{
+ if (orientation == HorizontalScrollbar && m_horizontalAdjustment)
+ return ScrollbarGtk::createScrollbar(this, orientation, m_horizontalAdjustment);
+ else if (orientation == VerticalScrollbar && m_verticalAdjustment)
+ return ScrollbarGtk::createScrollbar(this, orientation, m_verticalAdjustment);
+ else
+ return Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
}
/*
@@ -96,30 +76,27 @@ void ScrollView::setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj)
{
ASSERT(!hadj == !vadj);
- if (m_horizontalAdjustment) {
- g_signal_handlers_disconnect_by_func(G_OBJECT(m_horizontalAdjustment), (gpointer)adjustmentChanged, this);
- g_signal_handlers_disconnect_by_func(G_OBJECT(m_verticalAdjustment), (gpointer)adjustmentChanged, this);
- g_object_unref(m_horizontalAdjustment);
- g_object_unref(m_verticalAdjustment);
- }
-
m_horizontalAdjustment = hadj;
m_verticalAdjustment = vadj;
+ // Reset the adjustments to a sane default
if (m_horizontalAdjustment) {
- g_signal_connect(m_horizontalAdjustment, "value-changed", G_CALLBACK(adjustmentChanged), this);
- g_signal_connect(m_verticalAdjustment, "value-changed", G_CALLBACK(adjustmentChanged), this);
-
- /*
- * disable the scrollbars (if we have any) as the GtkAdjustment over
- */
- setHasVerticalScrollbar(false);
- setHasHorizontalScrollbar(false);
+ m_horizontalAdjustment->lower = 0;
+ m_horizontalAdjustment->upper = 0;
+ m_horizontalAdjustment->value = 0;
+ gtk_adjustment_changed(m_horizontalAdjustment);
+ gtk_adjustment_value_changed(m_horizontalAdjustment);
- g_object_ref(m_horizontalAdjustment);
- g_object_ref(m_verticalAdjustment);
+ m_verticalAdjustment->lower = 0;
+ m_verticalAdjustment->upper = 0;
+ m_verticalAdjustment->value = 0;
+ gtk_adjustment_changed(m_verticalAdjustment);
+ gtk_adjustment_value_changed(m_verticalAdjustment);
}
+ /* reconsider having a scrollbar */
+ setHasVerticalScrollbar(false);
+ setHasHorizontalScrollbar(false);
updateScrollbars(m_scrollOffset);
}
@@ -144,52 +121,4 @@ void ScrollView::platformRemoveChild(Widget* child)
gtk_container_remove(GTK_CONTAINER(parent), child->platformWidget());
}
-bool ScrollView::platformHandleHorizontalAdjustment(const IntSize& scroll)
-{
- if (m_horizontalAdjustment) {
- m_horizontalAdjustment->page_size = visibleWidth();
- m_horizontalAdjustment->step_increment = visibleWidth() / 10.0;
- m_horizontalAdjustment->page_increment = visibleWidth() * 0.9;
- m_horizontalAdjustment->lower = 0;
- m_horizontalAdjustment->upper = contentsWidth();
- gtk_adjustment_changed(m_horizontalAdjustment);
-
- if (m_horizontalAdjustment->value != scroll.width()) {
- m_horizontalAdjustment->value = scroll.width();
- gtk_adjustment_value_changed(m_horizontalAdjustment);
- }
- return true;
- }
- return false;
-}
-
-bool ScrollView::platformHandleVerticalAdjustment(const IntSize& scroll)
-{
- if (m_verticalAdjustment) {
- m_verticalAdjustment->page_size = visibleHeight();
- m_verticalAdjustment->step_increment = visibleHeight() / 10.0;
- m_verticalAdjustment->page_increment = visibleHeight() * 0.9;
- m_verticalAdjustment->lower = 0;
- m_verticalAdjustment->upper = contentsHeight();
- gtk_adjustment_changed(m_verticalAdjustment);
-
- if (m_verticalAdjustment->value != scroll.height()) {
- m_verticalAdjustment->value = scroll.height();
- gtk_adjustment_value_changed(m_verticalAdjustment);
- }
- return true;
- }
- return false;
-}
-
-bool ScrollView::platformHasHorizontalAdjustment() const
-{
- return m_horizontalAdjustment != 0;
-}
-
-bool ScrollView::platformHasVerticalAdjustment() const
-{
- return m_verticalAdjustment != 0;
-}
-
}
diff --git a/WebCore/platform/gtk/ScrollbarGtk.cpp b/WebCore/platform/gtk/ScrollbarGtk.cpp
index 7543e23..d7f6d26 100644
--- a/WebCore/platform/gtk/ScrollbarGtk.cpp
+++ b/WebCore/platform/gtk/ScrollbarGtk.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Holger Hans Peter Freyther zecke@selfish.org
+ * Copyright (C) 2007, 2009 Holger Hans Peter Freyther zecke@selfish.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -22,7 +22,6 @@
#include "IntRect.h"
#include "GraphicsContext.h"
#include "FrameView.h"
-#include "NotImplemented.h"
#include "ScrollbarTheme.h"
#include "gtkdrawing.h"
@@ -35,6 +34,11 @@ PassRefPtr<Scrollbar> Scrollbar::createNativeScrollbar(ScrollbarClient* client,
return adoptRef(new ScrollbarGtk(client, orientation, size));
}
+PassRefPtr<ScrollbarGtk> ScrollbarGtk::createScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, GtkAdjustment* adj)
+{
+ return adoptRef(new ScrollbarGtk(client, orientation, adj));
+}
+
static gboolean gtkScrollEventCallback(GtkWidget* widget, GdkEventScroll* event, ScrollbarGtk*)
{
/* Scroll only if our parent rejects the scroll event. The rationale for
@@ -52,7 +56,8 @@ ScrollbarGtk::ScrollbarGtk(ScrollbarClient* client, ScrollbarOrientation orienta
gtk_hscrollbar_new(m_adjustment):
gtk_vscrollbar_new(m_adjustment);
gtk_widget_show(scrollBar);
- g_signal_connect(scrollBar, "value-changed", G_CALLBACK(ScrollbarGtk::gtkValueChanged), this);
+ g_object_ref(m_adjustment);
+ g_signal_connect(m_adjustment, "value-changed", G_CALLBACK(ScrollbarGtk::gtkValueChanged), this);
g_signal_connect(scrollBar, "scroll-event", G_CALLBACK(gtkScrollEventCallback), this);
setPlatformWidget(scrollBar);
@@ -65,6 +70,37 @@ ScrollbarGtk::ScrollbarGtk(ScrollbarClient* client, ScrollbarOrientation orienta
ScrollbarTheme::nativeTheme()->scrollbarThickness());
}
+// Create a ScrollbarGtk on top of an existing GtkAdjustment but do not create a
+// GtkScrollbar on top of this adjustment. The goal is to have a WebCore::Scrollbar
+// that will manipulate the GtkAdjustment properties, will react to the changed
+// value but will not consume any space on the screen and will not be painted
+// at all. It is achieved by not calling setPlatformWidget.
+ScrollbarGtk::ScrollbarGtk(ScrollbarClient* client, ScrollbarOrientation orientation, GtkAdjustment* adjustment)
+ : Scrollbar(client, orientation, RegularScrollbar)
+ , m_adjustment(adjustment)
+{
+ g_object_ref(m_adjustment);
+ g_signal_connect(m_adjustment, "value-changed", G_CALLBACK(ScrollbarGtk::gtkValueChanged), this);
+
+ // We have nothing to show as we are solely operating on the GtkAdjustment
+ resize(0, 0);
+}
+
+ScrollbarGtk::~ScrollbarGtk()
+{
+ g_signal_handlers_disconnect_by_func(G_OBJECT(m_adjustment), (gpointer)ScrollbarGtk::gtkValueChanged, this);
+
+ // For the case where we only operate on the GtkAdjustment it is best to
+ // reset the values so that the surrounding scrollbar gets updated, or
+ // e.g. for a GtkScrolledWindow the scrollbar gets hidden.
+ m_adjustment->lower = 0;
+ m_adjustment->upper = 0;
+ m_adjustment->value = 0;
+ gtk_adjustment_changed(m_adjustment);
+ gtk_adjustment_value_changed(m_adjustment);
+ g_object_unref(m_adjustment);
+}
+
IntPoint ScrollbarGtk::getLocationInParentWindow(const IntRect& rect)
{
IntPoint loc;
@@ -79,7 +115,7 @@ IntPoint ScrollbarGtk::getLocationInParentWindow(const IntRect& rect)
void ScrollbarGtk::frameRectsChanged()
{
- if (!parent())
+ if (!parent() || !platformWidget())
return;
IntPoint loc = getLocationInParentWindow(frameRect());
diff --git a/WebCore/platform/gtk/ScrollbarGtk.h b/WebCore/platform/gtk/ScrollbarGtk.h
index 1ef4c49..b4b5989 100644
--- a/WebCore/platform/gtk/ScrollbarGtk.h
+++ b/WebCore/platform/gtk/ScrollbarGtk.h
@@ -36,6 +36,8 @@ namespace WebCore {
class ScrollbarGtk : public Scrollbar {
public:
friend class Scrollbar;
+ friend class ScrollView;
+ ~ScrollbarGtk();
virtual void setFrameRect(const IntRect&);
virtual void paint(GraphicsContext*, const IntRect&);
@@ -50,7 +52,10 @@ public:
virtual void frameRectsChanged();
protected:
+ static PassRefPtr<ScrollbarGtk> createScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, GtkAdjustment*);
+
ScrollbarGtk(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize);
+ ScrollbarGtk(ScrollbarClient*, ScrollbarOrientation, GtkAdjustment*);
virtual void updateThumbPosition();
virtual void updateThumbProportion();
diff --git a/WebCore/platform/gtk/TemporaryLinkStubs.cpp b/WebCore/platform/gtk/TemporaryLinkStubs.cpp
index edabd10..8c12fcb 100644
--- a/WebCore/platform/gtk/TemporaryLinkStubs.cpp
+++ b/WebCore/platform/gtk/TemporaryLinkStubs.cpp
@@ -38,26 +38,10 @@
using namespace WebCore;
-// This function loads resources from WebKit
-// This does not belong here and I'm not sure where
-// it should go
-// I don't know what the plans or design is
-// for none code resources
-Vector<char> loadResourceIntoArray(const char* resourceName)
-{
- Vector<char> resource;
- //if (strcmp(resourceName,"missingImage") == 0) {
- //}
- return resource;
-}
-
-
/********************************************************/
/* Completely empty stubs (mostly to allow DRT to run): */
/********************************************************/
-void PluginView::invalidateRegion(NPRegion) { notImplemented(); }
-
namespace WebCore {
void getSupportedKeySizes(Vector<String>&) { notImplemented(); }
String signedPublicKeyAndChallengeString(unsigned keySizeIndex, const String &challengeString, const KURL &url) { return String(); }
diff --git a/WebCore/platform/gtk/WheelEventGtk.cpp b/WebCore/platform/gtk/WheelEventGtk.cpp
index 075bed2..404bf29 100644
--- a/WebCore/platform/gtk/WheelEventGtk.cpp
+++ b/WebCore/platform/gtk/WheelEventGtk.cpp
@@ -31,9 +31,6 @@
#include <gdk/gdk.h>
-// GTK_CHECK_VERSION is defined in gtk/gtkversion.h
-#include <gtk/gtk.h>
-
namespace WebCore {
// Keep this in sync with the other platform event constructors
@@ -69,12 +66,7 @@ PlatformWheelEvent::PlatformWheelEvent(GdkEventScroll* event)
m_shiftKey = event->state & GDK_SHIFT_MASK;
m_ctrlKey = event->state & GDK_CONTROL_MASK;
m_altKey = event->state & GDK_MOD1_MASK;
-#if GTK_CHECK_VERSION(2,10,0)
m_metaKey = event->state & GDK_META_MASK;
-#else
- // GDK_MOD2_MASK doesn't always mean meta so we can't use it
- m_metaKey = false;
-#endif
// FIXME: retrieve the user setting for the number of lines to scroll on each wheel event
m_deltaX *= static_cast<float>(cScrollbarPixelsPerLineStep);
diff --git a/WebCore/platform/gtk/WidgetGtk.cpp b/WebCore/platform/gtk/WidgetGtk.cpp
index 4f09e77..007f2ee 100644
--- a/WebCore/platform/gtk/WidgetGtk.cpp
+++ b/WebCore/platform/gtk/WidgetGtk.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
- * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2007, 2009 Holger Hans Peter Freyther
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,7 +33,6 @@
#include "GraphicsContext.h"
#include "HostWindow.h"
#include "IntRect.h"
-#include "NotImplemented.h"
#include "RenderObject.h"
#include <gdk/gdk.h>
@@ -99,9 +98,19 @@ void Widget::paint(GraphicsContext* context, const IntRect& rect)
{
}
-void Widget::setIsSelected(bool)
+void Widget::setIsSelected(bool isSelected)
{
- notImplemented();
+ if (!platformWidget())
+ return;
+
+ // See if the platformWidget has a webkit-widget-is-selected property
+ // and set it afterwards.
+ GParamSpec* spec = g_object_class_find_property(G_OBJECT_GET_CLASS(platformWidget()),
+ "webkit-widget-is-selected");
+ if (!spec)
+ return;
+
+ g_object_set(platformWidget(), "webkit-widget-is-selected", isSelected, NULL);
}
IntRect Widget::frameRect() const
diff --git a/WebCore/platform/gtk/gtk2drawing.c b/WebCore/platform/gtk/gtk2drawing.c
index dd46e74..1f62c96 100644
--- a/WebCore/platform/gtk/gtk2drawing.c
+++ b/WebCore/platform/gtk/gtk2drawing.c
@@ -49,6 +49,8 @@
#include <string.h>
#include "gtkdrawing.h"
+#include "Assertions.h"
+
#include <math.h>
#define XTHICKNESS(style) (style->xthickness)
@@ -56,6 +58,7 @@
#define WINDOW_IS_MAPPED(window) ((window) && GDK_IS_WINDOW(window) && gdk_window_is_visible(window))
static GtkWidget* gProtoWindow;
+static GtkWidget* gProtoLayout;
static GtkWidget* gButtonWidget;
static GtkWidget* gToggleButtonWidget;
static GtkWidget* gButtonArrowWidget;
@@ -101,7 +104,6 @@ static GtkWidget* gScrolledWindowWidget;
static style_prop_t style_prop_func;
static gboolean have_arrow_scaling;
-static gboolean have_2_10;
static gboolean is_initialized;
/* Because we have such an unconventional way of drawing widgets, signal to the GTK theme engine
@@ -134,14 +136,13 @@ ensure_window_widget()
static gint
setup_widget_prototype(GtkWidget* widget)
{
- static GtkWidget* protoLayout;
ensure_window_widget();
- if (!protoLayout) {
- protoLayout = gtk_fixed_new();
- gtk_container_add(GTK_CONTAINER(gProtoWindow), protoLayout);
+ if (!gProtoLayout) {
+ gProtoLayout = gtk_fixed_new();
+ gtk_container_add(GTK_CONTAINER(gProtoWindow), gProtoLayout);
}
- gtk_container_add(GTK_CONTAINER(protoLayout), widget);
+ gtk_container_add(GTK_CONTAINER(gProtoLayout), widget);
gtk_widget_realize(widget);
g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
return MOZ_GTK_SUCCESS;
@@ -409,8 +410,7 @@ moz_gtk_get_combo_box_entry_arrow(GtkWidget *widget, gpointer client_data)
g_object_add_weak_pointer(G_OBJECT(widget),
(gpointer) &gComboBoxEntryArrowWidget);
gtk_widget_realize(widget);
- g_object_set_data(G_OBJECT(widget), "transparent-bg-hint",
- GINT_TO_POINTER(TRUE));
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
}
}
@@ -502,8 +502,7 @@ ensure_toolbar_widget()
gToolbarWidget = gtk_toolbar_new();
gtk_container_add(GTK_CONTAINER(gHandleBoxWidget), gToolbarWidget);
gtk_widget_realize(gToolbarWidget);
- g_object_set_data(G_OBJECT(gToolbarWidget), "transparent-bg-hint",
- GINT_TO_POINTER(TRUE));
+ g_object_set_data(G_OBJECT(gToolbarWidget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
}
return MOZ_GTK_SUCCESS;
}
@@ -710,17 +709,17 @@ ensure_tree_header_cell_widget()
gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), firstTreeViewColumn);
gMiddleTreeViewColumn = gtk_tree_view_column_new();
- gtk_tree_view_column_set_title(GTK_TREE_VIEW_COLUMN(gMiddleTreeViewColumn), "M");
+ gtk_tree_view_column_set_title(gMiddleTreeViewColumn, "M");
gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget),
- GTK_TREE_VIEW_COLUMN(gMiddleTreeViewColumn));
+ gMiddleTreeViewColumn);
lastTreeViewColumn = gtk_tree_view_column_new();
gtk_tree_view_column_set_title(lastTreeViewColumn, "M");
gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), lastTreeViewColumn);
/* Use the middle column's header for our button */
- gTreeHeaderCellWidget = GTK_TREE_VIEW_COLUMN(gMiddleTreeViewColumn)->button;
- gTreeHeaderSortArrowWidget = GTK_TREE_VIEW_COLUMN(gMiddleTreeViewColumn)->arrow;
+ gTreeHeaderCellWidget = gMiddleTreeViewColumn->button;
+ gTreeHeaderSortArrowWidget = gMiddleTreeViewColumn->arrow;
g_object_set_data(G_OBJECT(gTreeHeaderCellWidget),
"transparent-bg-hint", GINT_TO_POINTER(TRUE));
g_object_set_data(G_OBJECT(gTreeHeaderSortArrowWidget),
@@ -880,9 +879,6 @@ moz_gtk_init()
have_arrow_scaling = (gtk_major_version > 2 ||
(gtk_major_version == 2 && gtk_minor_version >= 12));
- have_2_10 = (gtk_major_version > 2 ||
- (gtk_major_version == 2 && gtk_minor_version >= 10));
-
/* 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. */
@@ -953,10 +949,9 @@ gint
moz_gtk_button_get_inner_border(GtkWidget* widget, GtkBorder* inner_border)
{
static const GtkBorder default_inner_border = { 1, 1, 1, 1 };
- GtkBorder *tmp_border = NULL;
+ GtkBorder *tmp_border;
- if (have_2_10)
- gtk_widget_style_get (widget, "inner-border", &tmp_border, NULL);
+ gtk_widget_style_get (widget, "inner-border", &tmp_border, NULL);
if (tmp_border) {
*inner_border = *tmp_border;
@@ -971,8 +966,8 @@ moz_gtk_button_get_inner_border(GtkWidget* widget, GtkBorder* inner_border)
static gint
moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
GdkRectangle* cliprect, GtkWidgetState* state,
- gboolean selected, gboolean isradio,
- GtkTextDirection direction)
+ gboolean selected, gboolean inconsistent,
+ gboolean isradio, GtkTextDirection direction)
{
GtkStateType state_type = ConvertGtkState(state);
GtkShadowType shadow_type = (selected)?GTK_SHADOW_IN:GTK_SHADOW_OUT;
@@ -990,6 +985,12 @@ moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
w = gCheckboxWidget;
}
+ // "GetMinimumWidgetSize was ignored"
+ // FIXME: This assert causes a build failure in WebKitGTK+ debug
+ // builds, because it uses 'false' in its definition. We may want
+ // to force this file to be built with g++, by renaming it.
+ // ASSERT(rect->width == indicator_size);
+
/*
* vertically center in the box, since XUL sometimes ignores our
* GetMinimumWidgetSize in the vertical dimension
@@ -1022,6 +1023,17 @@ moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
}
}
else {
+ /*
+ * 'indeterminate' type on checkboxes. In GTK, the shadow type
+ * must also be changed for the state to be drawn.
+ */
+ if (inconsistent) {
+ gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(gCheckboxWidget), TRUE);
+ shadow_type = GTK_SHADOW_ETCHED_IN;
+ } else {
+ gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(gCheckboxWidget), FALSE);
+ }
+
gtk_paint_check(style, drawable, state_type, shadow_type, cliprect,
gCheckboxWidget, "checkbutton", x, y, width, height);
if (state->focused) {
@@ -1490,9 +1502,15 @@ static gint
moz_gtk_caret_paint(GdkDrawable* drawable, GdkRectangle* rect,
GdkRectangle* cliprect, GtkTextDirection direction)
{
+ GdkRectangle location = *rect;
+ if (direction == GTK_TEXT_DIR_RTL) {
+ /* gtk_draw_insertion_cursor ignores location.width */
+ location.x = rect->x + rect->width;
+ }
+
ensure_entry_widget();
gtk_draw_insertion_cursor(gEntryWidget, drawable, cliprect,
- rect, TRUE, direction, FALSE);
+ &location, TRUE, direction, FALSE);
return MOZ_GTK_SUCCESS;
}
@@ -1538,8 +1556,7 @@ moz_gtk_entry_paint(GdkDrawable* drawable, GdkRectangle* rect,
* If the theme is able to cope with transparency, then we can skip pre-filling
* and notify the theme it will paint directly on the canvas. */
if (theme_honors_transparency) {
- g_object_set_data(G_OBJECT(widget), "transparent-bg-hint",
- GINT_TO_POINTER(TRUE));
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
} else {
gdk_draw_rectangle(drawable, style->base_gc[bg_state], TRUE,
cliprect->x, cliprect->y, cliprect->width, cliprect->height);
@@ -1650,7 +1667,7 @@ moz_gtk_tree_header_cell_paint(GdkDrawable* drawable, GdkRectangle* rect,
GdkRectangle* cliprect, GtkWidgetState* state,
gboolean isSorted, GtkTextDirection direction)
{
- gtk_tree_view_column_set_sort_indicator(GTK_TREE_VIEW_COLUMN(gMiddleTreeViewColumn),
+ gtk_tree_view_column_set_sort_indicator(gMiddleTreeViewColumn,
isSorted);
moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL,
@@ -1742,8 +1759,8 @@ moz_gtk_combo_box_paint(GdkDrawable* drawable, GdkRectangle* rect,
gboolean ishtml, GtkTextDirection direction)
{
GdkRectangle arrow_rect, real_arrow_rect;
- gint arrow_size, separator_width = 0;
- gboolean wide_separators = FALSE;
+ gint arrow_size, separator_width;
+ gboolean wide_separators;
GtkStateType state_type = ConvertGtkState(state);
GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
GtkStyle* style;
@@ -1786,11 +1803,10 @@ moz_gtk_combo_box_paint(GdkDrawable* drawable, GdkRectangle* rect,
style = gComboBoxSeparatorWidget->style;
TSOffsetStyleGCs(style, rect->x, rect->y);
- if (have_2_10)
- gtk_widget_style_get(gComboBoxSeparatorWidget,
- "wide-separators", &wide_separators,
- "separator-width", &separator_width,
- NULL);
+ gtk_widget_style_get(gComboBoxSeparatorWidget,
+ "wide-separators", &wide_separators,
+ "separator-width", &separator_width,
+ NULL);
if (wide_separators) {
if (direction == GTK_TEXT_DIR_LTR)
@@ -2015,9 +2031,9 @@ moz_gtk_toolbar_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
GtkTextDirection direction)
{
GtkStyle* style;
- gint separator_width = 0;
+ gint separator_width;
gint paint_width;
- gboolean wide_separators = FALSE;
+ gboolean wide_separators;
/* Defined as constants in GTK+ 2.10.14 */
const double start_fraction = 0.2;
@@ -2028,11 +2044,10 @@ moz_gtk_toolbar_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
style = gToolbarSeparatorWidget->style;
- if (have_2_10)
- gtk_widget_style_get(gToolbarWidget,
- "wide-separators", &wide_separators,
- "separator-width", &separator_width,
- NULL);
+ gtk_widget_style_get(gToolbarWidget,
+ "wide-separators", &wide_separators,
+ "separator-width", &separator_width,
+ NULL);
TSOffsetStyleGCs(style, rect->x, rect->y);
@@ -2423,9 +2438,9 @@ moz_gtk_menu_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
GdkRectangle* cliprect, GtkTextDirection direction)
{
GtkStyle* style;
- gboolean wide_separators = FALSE;
- gint separator_height = 0;
- guint horizontal_padding = 0;
+ gboolean wide_separators;
+ gint separator_height;
+ guint horizontal_padding;
gint paint_height;
ensure_menu_separator_widget();
@@ -2433,13 +2448,9 @@ moz_gtk_menu_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
style = gMenuSeparatorWidget->style;
- if (have_2_10)
- gtk_widget_style_get(gMenuSeparatorWidget,
- "wide-separators", &wide_separators,
- "separator-height", &separator_height,
- NULL);
-
gtk_widget_style_get(gMenuSeparatorWidget,
+ "wide-separators", &wide_separators,
+ "separator-height", &separator_height,
"horizontal-padding", &horizontal_padding,
NULL);
@@ -2687,7 +2698,7 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
/* We need to account for the arrow on the dropdown, so text
* doesn't come too close to the arrow, or in some cases spill
* into the arrow. */
- gboolean ignored_interior_focus, wide_separators = FALSE;
+ gboolean ignored_interior_focus, wide_separators;
gint focus_width, focus_pad, separator_width;
GtkRequisition arrow_req;
@@ -2710,11 +2721,10 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
/* If there is no separator, don't try to count its width. */
separator_width = 0;
if (gComboBoxSeparatorWidget) {
- if (have_2_10)
- gtk_widget_style_get(gComboBoxSeparatorWidget,
- "wide-separators", &wide_separators,
- "separator-width", &separator_width,
- NULL);
+ gtk_widget_style_get(gComboBoxSeparatorWidget,
+ "wide-separators", &wide_separators,
+ "separator-width", &separator_width,
+ NULL);
if (!wide_separators)
separator_width =
@@ -2895,13 +2905,12 @@ moz_gtk_get_combo_box_entry_button_size(gint* width, gint* height)
gint
moz_gtk_get_tab_scroll_arrow_size(gint* width, gint* height)
{
- gint arrow_size = 16;
+ gint arrow_size;
ensure_tab_widget();
- if (have_2_10)
- gtk_widget_style_get(gTabWidget,
- "scroll-arrow-hlength", &arrow_size,
- NULL);
+ gtk_widget_style_get(gTabWidget,
+ "scroll-arrow-hlength", &arrow_size,
+ NULL);
*height = *width = arrow_size;
@@ -2924,22 +2933,18 @@ moz_gtk_get_downarrow_size(gint* width, gint* height)
gint
moz_gtk_get_toolbar_separator_width(gint* size)
{
- gboolean wide_separators = FALSE;
- gint separator_width = 0;
+ gboolean wide_separators;
+ gint separator_width;
GtkStyle* style;
ensure_toolbar_widget();
style = gToolbarWidget->style;
- if (have_2_10)
- gtk_widget_style_get(gToolbarWidget,
- "wide-separators", &wide_separators,
- "separator-width", &separator_width,
- NULL);
-
gtk_widget_style_get(gToolbarWidget,
"space-size", size,
+ "wide-separators", &wide_separators,
+ "separator-width", &separator_width,
NULL);
/* Just in case... */
@@ -2973,16 +2978,15 @@ moz_gtk_get_treeview_expander_size(gint* size)
gint
moz_gtk_get_menu_separator_height(gint *size)
{
- gboolean wide_separators = FALSE;
- gint separator_height = 0;
+ gboolean wide_separators;
+ gint separator_height;
ensure_menu_separator_widget();
- if (have_2_10)
- gtk_widget_style_get(gMenuSeparatorWidget,
- "wide-separators", &wide_separators,
- "separator-height", &separator_height,
- NULL);
+ gtk_widget_style_get(gMenuSeparatorWidget,
+ "wide-separators", &wide_separators,
+ "separator-height", &separator_height,
+ NULL);
if (wide_separators)
*size = separator_height + gMenuSeparatorWidget->style->ythickness;
@@ -3061,7 +3065,8 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
case MOZ_GTK_CHECKBUTTON:
case MOZ_GTK_RADIOBUTTON:
return moz_gtk_toggle_paint(drawable, rect, cliprect, state,
- (gboolean) flags,
+ !!(flags & MOZ_GTK_WIDGET_CHECKED),
+ !!(flags & MOZ_GTK_WIDGET_INCONSISTENT),
(widget == MOZ_GTK_RADIOBUTTON),
direction);
break;
@@ -3262,6 +3267,7 @@ moz_gtk_shutdown()
gtk_widget_destroy(gProtoWindow);
gProtoWindow = NULL;
+ gProtoLayout = NULL;
gButtonWidget = NULL;
gToggleButtonWidget = NULL;
gButtonArrowWidget = NULL;
diff --git a/WebCore/platform/gtk/gtkdrawing.h b/WebCore/platform/gtk/gtkdrawing.h
index eb6995a..1a33bfb 100644
--- a/WebCore/platform/gtk/gtkdrawing.h
+++ b/WebCore/platform/gtk/gtkdrawing.h
@@ -110,6 +110,10 @@ typedef gint (*style_prop_t)(GtkStyle*, const gchar*, gint);
#define MOZ_GTK_UNKNOWN_WIDGET -1
#define MOZ_GTK_UNSAFE_THEME -2
+/*** checkbox/radio flags ***/
+#define MOZ_GTK_WIDGET_CHECKED 1
+#define MOZ_GTK_WIDGET_INCONSISTENT (1 << 1)
+
/*** widget type constants ***/
typedef enum {
/* Paints a GtkButton. flags is a GtkReliefStyle. */
diff --git a/WebCore/platform/gtk/guriescape.c b/WebCore/platform/gtk/guriescape.c
deleted file mode 100644
index 0792587..0000000
--- a/WebCore/platform/gtk/guriescape.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2008 Collabora, Ltd.
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- * Copyright (C) 1997-2000 The GLib Team
- * Copyright (C) 2006-2007 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "guriescape.h"
-
-#include <string.h>
-
-#if !PLATFORM(WIN_OS) && !GLIB_CHECK_VERSION(2,16,0)
-
-/* is_valid, gunichar_ok and g_string_append_uri_escaped were copied for glib/gstring.c
- * in the glib package.
- *
- * Original copyright:
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * Modified by the GLib Team and others 1997-2000. See the AUTHORS
- * file for a list of people on the GLib Team. See the ChangeLog
- * files for a list of changes. These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/.
- *
- * Please don't change the indentation so it's easier to update these functions
- * if they are changed in glib.
- */
-static gboolean
-is_valid (char c, const char *reserved_chars_allowed)
-{
- if (g_ascii_isalnum (c) ||
- c == '-' ||
- c == '.' ||
- c == '_' ||
- c == '~')
- return TRUE;
-
- if (reserved_chars_allowed &&
- strchr (reserved_chars_allowed, c) != NULL)
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean
-gunichar_ok (gunichar c)
-{
- return
- (c != (gunichar) -2) &&
- (c != (gunichar) -1);
-}
-
-static GString *
-_webcore_g_string_append_uri_escaped (GString *string,
- const char *unescaped,
- const char *reserved_chars_allowed,
- gboolean allow_utf8)
-{
- unsigned char c;
- const char *end;
- static const gchar hex[16] = "0123456789ABCDEF";
-
- g_return_val_if_fail (string != NULL, NULL);
- g_return_val_if_fail (unescaped != NULL, NULL);
-
- end = unescaped + strlen (unescaped);
-
- while ((c = *unescaped) != 0)
- {
- if (c >= 0x80 && allow_utf8 &&
- gunichar_ok (g_utf8_get_char_validated (unescaped, end - unescaped)))
- {
- int len = g_utf8_skip [c];
- g_string_append_len (string, unescaped, len);
- unescaped += len;
- }
- else if (is_valid (c, reserved_chars_allowed))
- {
- g_string_append_c (string, c);
- unescaped++;
- }
- else
- {
- g_string_append_c (string, '%');
- g_string_append_c (string, hex[((guchar)c) >> 4]);
- g_string_append_c (string, hex[((guchar)c) & 0xf]);
- unescaped++;
- }
- }
-
- return string;
-}
-
-/* g_uri_escape_string, unescape_character, g_uri_unescape_segment and
- * g_uri_unescape_string were copied for glib/gurifuncs.c in the glib package
- * and prefixed with _webcore (if necessary) to avoid exporting a symbol with
- * the "g_" prefix.
- *
- * Original copyright:
- * Copyright (C) 2006-2007 Red Hat, Inc.
- * Author: Alexander Larsson <alexl@redhat.com>
- *
- * Please don't change the indentation so it's easier to update this function
- * if it's changed in glib.
- */
-char *
-_webcore_g_uri_escape_string (const char *unescaped,
- const char *reserved_chars_allowed,
- gboolean allow_utf8)
-{
- GString *s;
-
- g_return_val_if_fail (unescaped != NULL, NULL);
-
- s = g_string_sized_new (strlen (unescaped) + 10);
-
- _webcore_g_string_append_uri_escaped (s, unescaped, reserved_chars_allowed, allow_utf8);
-
- return g_string_free (s, FALSE);
-}
-
-static int
-unescape_character (const char *scanner)
-{
- int first_digit;
- int second_digit;
-
- first_digit = g_ascii_xdigit_value (*scanner++);
- if (first_digit < 0)
- return -1;
-
- second_digit = g_ascii_xdigit_value (*scanner++);
- if (second_digit < 0)
- return -1;
-
- return (first_digit << 4) | second_digit;
-}
-
-
-
-static char *
-_webcore_g_uri_unescape_segment (const char *escaped_string,
- const char *escaped_string_end,
- const char *illegal_characters)
-{
- const char *in;
- char *out, *result;
- gint character;
-
- if (escaped_string == NULL)
- return NULL;
-
- if (escaped_string_end == NULL)
- escaped_string_end = escaped_string + strlen (escaped_string);
-
- result = g_malloc (escaped_string_end - escaped_string + 1);
-
- out = result;
- for (in = escaped_string; in < escaped_string_end; in++)
- {
- character = *in;
-
- if (*in == '%')
- {
- in++;
-
- if (escaped_string_end - in < 2)
- {
- /* Invalid escaped char (to short) */
- g_free (result);
- return NULL;
- }
-
- character = unescape_character (in);
-
- /* Check for an illegal character. We consider '\0' illegal here. */
- if (character <= 0 ||
- (illegal_characters != NULL &&
- strchr (illegal_characters, (char)character) != NULL))
- {
- g_free (result);
- return NULL;
- }
-
- in++; /* The other char will be eaten in the loop header */
- }
- *out++ = (char)character;
- }
-
- *out = '\0';
-
- return result;
-}
-
-
-char *
-_webcore_g_uri_unescape_string (const char *escaped_string,
- const char *illegal_characters)
-{
- return _webcore_g_uri_unescape_segment (escaped_string, NULL, illegal_characters);
-}
-
-#endif /* #if !PLATFORM(WIN_OS) && !GLIB_CHECK_VERSION(2,16,0) */
diff --git a/WebCore/platform/gtk/guriescape.h b/WebCore/platform/gtk/guriescape.h
deleted file mode 100644
index 8c6662a..0000000
--- a/WebCore/platform/gtk/guriescape.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2008 Collabora, Ltd.
- *
- * 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 guriescape_h
-#define guriescape_h
-
-#include <glib.h>
-#include <wtf/Platform.h>
-
-G_BEGIN_DECLS
-
-#if !PLATFORM(WIN_OS) && !GLIB_CHECK_VERSION(2,16,0)
-
-#define g_uri_escape_string _webcore_g_uri_escape_string
-#define g_uri_unescape_string _webcore_g_uri_unescape_string
-
-char *_webcore_g_uri_escape_string (const char *unescaped,
- const char *reserved_chars_allowed,
- gboolean allow_utf8);
-
-char *_webcore_g_uri_unescape_string (const char *escaped_string,
- const char *illegal_characters);
-
-#endif
-
-G_END_DECLS
-
-#endif /* guriescape_h */
diff --git a/WebCore/platform/image-decoders/ImageDecoder.h b/WebCore/platform/image-decoders/ImageDecoder.h
index 17756ac..ca27b37 100644
--- a/WebCore/platform/image-decoders/ImageDecoder.h
+++ b/WebCore/platform/image-decoders/ImageDecoder.h
@@ -23,8 +23,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef IMAGE_DECODER_H_
-#define IMAGE_DECODER_H_
+#ifndef ImageDecoder_h
+#define ImageDecoder_h
#include "IntRect.h"
#include "ImageSource.h"
@@ -34,136 +34,145 @@
namespace WebCore {
-typedef Vector<unsigned> RGBA32Array;
-
-// The RGBA32Buffer 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.
-class RGBA32Buffer
-{
-public:
- enum FrameStatus { FrameEmpty, FramePartial, FrameComplete };
- enum FrameDisposalMethod {
- // If you change the numeric values of these, make sure you audit all
- // users, as some users may cast raw values to/from these constants.
- DisposeNotSpecified = 0, // Leave frame in framebuffer
- DisposeKeep = 1, // Leave frame in framebuffer
- DisposeOverwriteBgcolor = 2, // Clear frame to transparent
- DisposeOverwritePrevious = 3, // Clear frame to previous framebuffer contents
- };
+ typedef Vector<unsigned> RGBA32Array;
+
+ // The RGBA32Buffer 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.
+ class RGBA32Buffer {
+ public:
+ enum FrameStatus { FrameEmpty, FramePartial, FrameComplete };
+
+ enum FrameDisposalMethod {
+ // If you change the numeric values of these, make sure you audit all
+ // users, as some users may cast raw values to/from these constants.
+ DisposeNotSpecified, // Leave frame in framebuffer
+ DisposeKeep, // Leave frame in framebuffer
+ DisposeOverwriteBgcolor, // Clear frame to transparent
+ DisposeOverwritePrevious, // Clear frame to previous framebuffer contents
+ };
+
+ RGBA32Buffer()
+ : m_height(0)
+ , m_status(FrameEmpty)
+ , m_duration(0)
+ , m_disposalMethod(DisposeNotSpecified)
+ , m_hasAlpha(false)
+ {
+ }
+
+ void clear() {
+ m_bytes.clear();
+ m_status = FrameEmpty;
+ // NOTE: Do not reset other members here; clearFrameBufferCache() calls
+ // this to free the bitmap data, but other functions like
+ // initFrameBuffer() and frameComplete() may still need to read other
+ // metadata out of this frame later.
+ }
- RGBA32Buffer() : m_height(0), m_status(FrameEmpty), m_duration(0),
- m_disposalMethod(DisposeNotSpecified), m_hasAlpha(false)
- {}
-
- void clear() {
- m_bytes.clear();
- m_status = FrameEmpty;
- // NOTE: Do not reset other members here; clearFrameBufferCache() calls
- // this to free the bitmap data, but other functions like
- // initFrameBuffer() and frameComplete() may still need to read other
- // metadata out of this frame later.
- }
-
- const RGBA32Array& bytes() const { return m_bytes; }
- RGBA32Array& bytes() { return m_bytes; }
- const IntRect& rect() const { return m_rect; }
- unsigned height() const { return m_height; }
- FrameStatus status() const { return m_status; }
- unsigned duration() const { return m_duration; }
- FrameDisposalMethod disposalMethod() const { return m_disposalMethod; }
- bool hasAlpha() const { return m_hasAlpha; }
-
- void setRect(const IntRect& r) { m_rect = r; }
- void ensureHeight(unsigned rowIndex) { if (rowIndex > m_height) m_height = rowIndex; }
- void setStatus(FrameStatus s) { m_status = s; }
- void setDuration(unsigned duration) { m_duration = duration; }
- void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
- void setHasAlpha(bool alpha) { m_hasAlpha = alpha; }
-
- static void setRGBA(unsigned& pos, unsigned r, unsigned g, unsigned b, unsigned a)
- {
- // We store this data pre-multiplied.
- if (a == 0)
- pos = 0;
- else {
- if (a < 255) {
- float alphaPercent = a / 255.0f;
- r = static_cast<unsigned>(r * alphaPercent);
- g = static_cast<unsigned>(g * alphaPercent);
- b = static_cast<unsigned>(b * alphaPercent);
+ const RGBA32Array& bytes() const { return m_bytes; }
+ RGBA32Array& bytes() { return m_bytes; }
+ const IntRect& rect() const { return m_rect; }
+ unsigned height() const { return m_height; }
+ FrameStatus status() const { return m_status; }
+ unsigned duration() const { return m_duration; }
+ FrameDisposalMethod disposalMethod() const { return m_disposalMethod; }
+ bool hasAlpha() const { return m_hasAlpha; }
+
+ void setRect(const IntRect& r) { m_rect = r; }
+ void ensureHeight(unsigned rowIndex) { if (rowIndex > m_height) m_height = rowIndex; }
+ void setStatus(FrameStatus s) { m_status = s; }
+ void setDuration(unsigned duration) { m_duration = duration; }
+ void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
+ void setHasAlpha(bool alpha) { m_hasAlpha = alpha; }
+
+ static void setRGBA(unsigned& pos, unsigned r, unsigned g, unsigned b, unsigned a)
+ {
+ // We store this data pre-multiplied.
+ if (a == 0)
+ pos = 0;
+ else {
+ if (a < 255) {
+ float alphaPercent = a / 255.0f;
+ r = static_cast<unsigned>(r * alphaPercent);
+ g = static_cast<unsigned>(g * alphaPercent);
+ b = static_cast<unsigned>(b * alphaPercent);
+ }
+ pos = (a << 24 | r << 16 | g << 8 | b);
}
- pos = (a << 24 | r << 16 | g << 8 | b);
}
- }
-
-private:
- RGBA32Array m_bytes;
- 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.
- unsigned m_height; // The height (the number of rows we've fully decoded).
- 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_hasAlpha; // Whether or not any of the pixels in the buffer have transparency.
-};
-
-// 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.
-class ImageDecoder
-{
-public:
- ImageDecoder() :m_sizeAvailable(false), m_failed(false) {}
- virtual ~ImageDecoder() {}
-
- // The the filename extension usually associated with an undecoded image of this type.
- virtual String filenameExtension() const = 0;
-
- // All specific decoder plugins must do something with the data they are given.
- virtual void setData(SharedBuffer* data, bool allDataReceived) { m_data = data; }
-
- // Whether or not the size information has been decoded yet.
- virtual bool isSizeAvailable() const = 0;
-
- // Requests the size.
- virtual IntSize size() const { return m_size; }
-
- // 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).
- virtual int frameCount() { return 1; }
-
- // The number of repetitions to perform for an animation loop.
- virtual int repetitionCount() const { return cAnimationNone; }
-
- // Called to obtain the RGBA32Buffer full of decoded data for rendering. The
- // decoder plugin will decode as much of the frame as it can before handing
- // back the buffer.
- virtual RGBA32Buffer* frameBufferAtIndex(size_t index) = 0;
-
- // Whether or not the underlying image format even supports alpha transparency.
- virtual bool supportsAlpha() const { return true; }
-
- bool failed() const { return m_failed; }
- void setFailed() { m_failed = true; }
-
- // 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) { }
-
-protected:
- RefPtr<SharedBuffer> m_data; // The encoded data.
- Vector<RGBA32Buffer> m_frameBufferCache;
- bool m_sizeAvailable;
- mutable bool m_failed;
- IntSize m_size;
-};
-
-}
+
+ private:
+ RGBA32Array m_bytes;
+ 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.
+ unsigned m_height; // The height (the number of rows we've fully decoded).
+ 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_hasAlpha; // Whether or not any of the pixels in the buffer have transparency.
+ };
+
+ // 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.
+ class ImageDecoder {
+ public:
+ ImageDecoder()
+ : m_sizeAvailable(false)
+ , m_failed(false)
+ {
+ }
+
+ virtual ~ImageDecoder() {}
+
+ // The the filename extension usually associated with an undecoded image of this type.
+ virtual String filenameExtension() const = 0;
+
+ // All specific decoder plugins must do something with the data they are given.
+ virtual void setData(SharedBuffer* data, bool allDataReceived) { m_data = data; }
+
+ // Whether or not the size information has been decoded yet.
+ virtual bool isSizeAvailable() const = 0;
+
+ // Requests the size.
+ virtual IntSize size() const { return m_size; }
+
+ // 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).
+ virtual int frameCount() { return 1; }
+
+ // The number of repetitions to perform for an animation loop.
+ virtual int repetitionCount() const { return cAnimationNone; }
+
+ // Called to obtain the RGBA32Buffer full of decoded data for rendering. The
+ // decoder plugin will decode as much of the frame as it can before handing
+ // back the buffer.
+ virtual RGBA32Buffer* frameBufferAtIndex(size_t index) = 0;
+
+ // Whether or not the underlying image format even supports alpha transparency.
+ virtual bool supportsAlpha() const { return true; }
+
+ bool failed() const { return m_failed; }
+ void setFailed() { m_failed = true; }
+
+ // 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) { }
+
+ protected:
+ RefPtr<SharedBuffer> m_data; // The encoded data.
+ Vector<RGBA32Buffer> m_frameBufferCache;
+ bool m_sizeAvailable;
+ mutable bool m_failed;
+ IntSize m_size;
+ };
+
+} // namespace WebCore
#endif
diff --git a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp
index cfc141c..3b90bdc 100644
--- a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp
@@ -26,8 +26,6 @@
#include "config.h"
#include "BMPImageDecoder.h"
-#if PLATFORM(CAIRO) || PLATFORM(QT) || PLATFORM(WX)
-
namespace WebCore
{
@@ -41,6 +39,4 @@ RGBA32Buffer* BMPImageDecoder::frameBufferAtIndex(size_t index)
return 0;
}
-}
-
-#endif // PLATFORM(CAIRO)
+} // namespace WebCore
diff --git a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h
index d850cc7..a2d4b25 100644
--- a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h
+++ b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h
@@ -23,27 +23,26 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef BMP_DECODER_H_
-#define BMP_DECODER_H_
+#ifndef BMPImageDecoder_h
+#define BMPImageDecoder_h
#include "ImageDecoder.h"
namespace WebCore {
-class BMPImageReader;
+ class BMPImageReader;
-// This class decodes the BMP image format.
-class BMPImageDecoder : public ImageDecoder
-{
-public:
- virtual String filenameExtension() const { return "bmp"; }
+ // This class decodes the BMP image format.
+ class BMPImageDecoder : public ImageDecoder {
+ public:
+ virtual String filenameExtension() const { return "bmp"; }
- // Whether or not the size information has been decoded yet.
- virtual bool isSizeAvailable() const;
+ // Whether or not the size information has been decoded yet.
+ virtual bool isSizeAvailable() const;
- virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
-};
+ virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
+ };
-}
+} // namespace WebCore
#endif
diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
index 5b4b675..62d8b5b 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
@@ -27,17 +27,14 @@
#include "GIFImageDecoder.h"
#include "GIFImageReader.h"
-#if PLATFORM(CAIRO) || PLATFORM(QT) || PLATFORM(WX)
-
namespace WebCore {
-class GIFImageDecoderPrivate
-{
+class GIFImageDecoderPrivate {
public:
GIFImageDecoderPrivate(GIFImageDecoder* decoder = 0)
: m_reader(decoder)
+ , m_readOffset(0)
{
- m_readOffset = 0;
}
~GIFImageDecoderPrivate()
@@ -45,11 +42,11 @@ public:
m_reader.close();
}
- bool decode(const Vector<char>& data,
+ bool decode(SharedBuffer* data,
GIFImageDecoder::GIFQuery query = GIFImageDecoder::GIFFullQuery,
unsigned int haltFrame = -1)
{
- return m_reader.read((const unsigned char*)data.data() + m_readOffset, data.size() - m_readOffset,
+ return m_reader.read((const unsigned char*)data->data() + m_readOffset, data->size() - m_readOffset,
query,
haltFrame);
}
@@ -61,7 +58,8 @@ public:
bool isTransparent() const { return m_reader.frame_reader->is_transparent; }
- void getColorMap(unsigned char*& map, unsigned& size) const {
+ void getColorMap(unsigned char*& map, unsigned& size) const
+ {
if (m_reader.frame_reader->is_local_colormap_defined) {
map = m_reader.frame_reader->local_colormap;
size = (unsigned)m_reader.frame_reader->local_colormap_size;
@@ -86,8 +84,11 @@ private:
};
GIFImageDecoder::GIFImageDecoder()
-: m_frameCountValid(true), m_repetitionCount(cAnimationLoopOnce), m_reader(0)
-{}
+ : m_frameCountValid(true)
+ , m_repetitionCount(cAnimationLoopOnce)
+ , m_reader(0)
+{
+}
GIFImageDecoder::~GIFImageDecoder()
{
@@ -139,7 +140,10 @@ int GIFImageDecoder::frameCount()
// state, but for now we just crawl all the data. Note that this is no worse than what
// ImageIO does on Mac right now (it also crawls all the data again).
GIFImageDecoderPrivate reader;
- reader.decode(m_data->buffer(), GIFFrameCountQuery);
+ // This function may fail, but we want to keep any partial data it may
+ // have decoded, so don't mark it is invalid. If there is an overflow
+ // or some serious error, m_failed will have gotten set for us.
+ reader.decode(m_data.get(), GIFFrameCountQuery);
m_frameCountValid = true;
m_frameBufferCache.resize(reader.frameCount());
}
@@ -173,13 +177,12 @@ int GIFImageDecoder::repetitionCount() const
RGBA32Buffer* GIFImageDecoder::frameBufferAtIndex(size_t index)
{
- if (index >= frameCount())
+ if (index >= static_cast<size_t>(frameCount()))
return 0;
RGBA32Buffer& frame = m_frameBufferCache[index];
if (frame.status() != RGBA32Buffer::FrameComplete && m_reader)
- // Decode this frame.
- decode(GIFFullQuery, index+1);
+ decode(GIFFullQuery, index + 1); // Decode this frame.
return &frame;
}
@@ -239,7 +242,7 @@ void GIFImageDecoder::decode(GIFQuery query, unsigned haltAtFrame) const
if (m_failed)
return;
- m_failed = !m_reader->decode(m_data->buffer(), query, haltAtFrame);
+ m_failed = !m_reader->decode(m_data.get(), query, haltAtFrame);
if (m_failed) {
delete m_reader;
@@ -266,10 +269,10 @@ void GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
m_reader->frameWidth(), m_reader->frameHeight());
// Make sure the frameRect doesn't extend past the bottom-right of the buffer.
- if (frameRect.right() > m_size.width())
- frameRect.setWidth(m_size.width() - m_reader->frameXOffset());
- if (frameRect.bottom() > m_size.height())
- frameRect.setHeight(m_size.height() - m_reader->frameYOffset());
+ if (frameRect.right() > size().width())
+ frameRect.setWidth(size().width() - m_reader->frameXOffset());
+ if (frameRect.bottom() > size().height())
+ frameRect.setHeight(size().height() - m_reader->frameYOffset());
RGBA32Buffer* const buffer = &m_frameBufferCache[frameIndex];
buffer->setRect(frameRect);
@@ -287,14 +290,14 @@ void GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
// first frame specifies this method, it will get treated like
// DisposeOverwriteBgcolor below and reset to a completely empty image.)
const RGBA32Buffer* prevBuffer = &m_frameBufferCache[--frameIndex];
- ASSERT(prevBuffer->status() == RGBA32Buffer::FrameComplete);
RGBA32Buffer::FrameDisposalMethod prevMethod =
prevBuffer->disposalMethod();
- while ((frameIndex > 0) &&
- (prevMethod == RGBA32Buffer::DisposeOverwritePrevious)) {
+ while ((frameIndex > 0)
+ && (prevMethod == RGBA32Buffer::DisposeOverwritePrevious)) {
prevBuffer = &m_frameBufferCache[--frameIndex];
prevMethod = prevBuffer->disposalMethod();
}
+ ASSERT(prevBuffer->status() == RGBA32Buffer::FrameComplete);
if ((prevMethod == RGBA32Buffer::DisposeNotSpecified) ||
(prevMethod == RGBA32Buffer::DisposeKeep)) {
@@ -305,8 +308,8 @@ void GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
// We want to clear the previous frame to transparent, without
// affecting pixels in the image outside of the frame.
const IntRect& prevRect = prevBuffer->rect();
- if ((frameIndex == 0) ||
- prevRect.contains(IntRect(IntPoint(0, 0), m_size))) {
+ if ((frameIndex == 0)
+ || prevRect.contains(IntRect(IntPoint(0, 0), size()))) {
// Clearing the first frame, or a frame the size of the whole
// image, results in a completely empty image.
prepEmptyFrameBuffer(buffer);
@@ -321,7 +324,7 @@ void GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
buffer->setRGBA(*(currentRow + x), 0, 0, 0, 0);
}
if ((prevRect.width() > 0) && (prevRect.height() > 0))
- buffer->setHasAlpha(true);
+ buffer->setHasAlpha(true);
}
}
}
@@ -335,7 +338,7 @@ void GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
void GIFImageDecoder::prepEmptyFrameBuffer(RGBA32Buffer* buffer) const
{
- buffer->bytes().resize(m_size.width() * m_size.height());
+ buffer->bytes().resize(size().width() * size().height());
buffer->bytes().fill(0);
buffer->setHasAlpha(true);
}
@@ -353,8 +356,8 @@ void GIFImageDecoder::haveDecodedRow(unsigned frameIndex,
initFrameBuffer(frameIndex);
// Do nothing for bogus data.
- if (rowBuffer == 0 || static_cast<int>(m_reader->frameYOffset() + rowNumber) >= m_size.height())
- return;
+ if (rowBuffer == 0 || static_cast<int>(m_reader->frameYOffset() + rowNumber) >= size().height())
+ return;
unsigned colorMapSize;
unsigned char* colorMap;
@@ -369,12 +372,12 @@ void GIFImageDecoder::haveDecodedRow(unsigned frameIndex,
// within the overall image. The rows we are decoding are within this
// sub-rectangle. This means that if the GIF frame's sub-rectangle is (x,y,w,h) then row 0 is really row
// y, and each row goes from x to x+w.
- unsigned dstPos = (m_reader->frameYOffset() + rowNumber) * m_size.width() + m_reader->frameXOffset();
+ unsigned dstPos = (m_reader->frameYOffset() + rowNumber) * size().width() + m_reader->frameXOffset();
unsigned* dst = buffer.bytes().data() + dstPos;
- unsigned* dstEnd = dst + m_size.width() - m_reader->frameXOffset();
+ unsigned* dstEnd = dst + size().width() - m_reader->frameXOffset();
unsigned* currDst = dst;
unsigned char* currentRowByte = rowBuffer;
-
+
while (currentRowByte != rowEnd && currDst < dstEnd) {
if ((!m_reader->isTransparent() || *currentRowByte != m_reader->transparentPixel()) && *currentRowByte < colorMapSize) {
unsigned colorIndex = *currentRowByte * 3;
@@ -401,14 +404,14 @@ void GIFImageDecoder::haveDecodedRow(unsigned frameIndex,
if (repeatCount > 1) {
// Copy the row |repeatCount|-1 times.
unsigned num = currDst - dst;
- unsigned size = num * sizeof(unsigned);
- unsigned width = m_size.width();
- unsigned* end = buffer.bytes().data() + width * m_size.height();
+ unsigned data_size = num * sizeof(unsigned);
+ unsigned width = size().width();
+ unsigned* end = buffer.bytes().data() + width * size().height();
currDst = dst + width;
for (unsigned i = 1; i < repeatCount; i++) {
if (currDst + num > end) // Protect against a buffer overrun from a bogus repeatCount.
break;
- memcpy(currDst, dst, size);
+ memcpy(currDst, dst, data_size);
currDst += width;
}
}
@@ -434,9 +437,9 @@ void 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(0, 0), m_size))) {
+ if (buffer.rect().contains(IntRect(IntPoint(0, 0), size())))
buffer.setHasAlpha(false);
- } else if (frameIndex > 0) {
+ else if (frameIndex > 0) {
// Tricky case. This frame does not have alpha only if everywhere
// outside its rect doesn't have alpha. To know whether this is
// true, we check the start state of the frame -- if it doesn't have
@@ -446,9 +449,8 @@ void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration,
// don't affect the start state of this frame) the same way we do in
// initFrameBuffer().
const RGBA32Buffer* prevBuffer = &m_frameBufferCache[--frameIndex];
- while ((frameIndex > 0) &&
- (prevBuffer->disposalMethod() ==
- RGBA32Buffer::DisposeOverwritePrevious))
+ while ((frameIndex > 0)
+ && (prevBuffer->disposalMethod() == RGBA32Buffer::DisposeOverwritePrevious))
prevBuffer = &m_frameBufferCache[--frameIndex];
// Now, if we're at a DisposeNotSpecified or DisposeKeep frame, then
@@ -459,10 +461,8 @@ void 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() ==
- RGBA32Buffer::DisposeOverwriteBgcolor) &&
- !prevBuffer->hasAlpha() &&
- buffer.rect().contains(prevBuffer->rect()))
+ if ((prevBuffer->disposalMethod() == RGBA32Buffer::DisposeOverwriteBgcolor)
+ && !prevBuffer->hasAlpha() && buffer.rect().contains(prevBuffer->rect()))
buffer.setHasAlpha(false);
}
}
@@ -476,6 +476,4 @@ void GIFImageDecoder::gifComplete()
m_reader = 0;
}
-}
-
-#endif // PLATFORM(CAIRO)
+} // namespace WebCore
diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
index 02b43a2..abb55a4 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
+++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
@@ -23,70 +23,69 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef GIF_DECODER_H_
-#define GIF_DECODER_H_
+#ifndef GIFImageDecoder_h
+#define GIFImageDecoder_h
#include "ImageDecoder.h"
namespace WebCore {
-class GIFImageDecoderPrivate;
+ class GIFImageDecoderPrivate;
-// This class decodes the GIF image format.
-class GIFImageDecoder : public ImageDecoder
-{
-public:
- GIFImageDecoder();
- ~GIFImageDecoder();
+ // This class decodes the GIF image format.
+ class GIFImageDecoder : public ImageDecoder {
+ public:
+ GIFImageDecoder();
+ ~GIFImageDecoder();
- virtual String filenameExtension() const { return "gif"; }
+ virtual String filenameExtension() const { return "gif"; }
- // Take the data and store it.
- virtual void setData(SharedBuffer* data, bool allDataReceived);
+ // Take the data and store it.
+ virtual void setData(SharedBuffer* data, bool allDataReceived);
- // Whether or not the size information has been decoded yet.
- virtual bool isSizeAvailable() const;
+ // Whether or not the size information has been decoded yet.
+ virtual bool isSizeAvailable() const;
- // The total number of frames for the image. Will scan the image data for the answer
- // (without necessarily decoding all of the individual frames).
- virtual int frameCount();
+ // The total number of frames for the image. Will scan the image data for the answer
+ // (without necessarily decoding all of the individual frames).
+ virtual int frameCount();
- // The number of repetitions to perform for an animation loop.
- virtual int repetitionCount() const;
+ // The number of repetitions to perform for an animation loop.
+ virtual int repetitionCount() const;
- virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
+ virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
- virtual void clearFrameBufferCache(size_t clearBeforeFrame);
+ virtual void clearFrameBufferCache(size_t clearBeforeFrame);
- virtual unsigned frameDurationAtIndex(size_t index) { return 0; }
+ virtual unsigned frameDurationAtIndex(size_t index) { return 0; }
- enum GIFQuery { GIFFullQuery, GIFSizeQuery, GIFFrameCountQuery };
+ enum GIFQuery { GIFFullQuery, GIFSizeQuery, GIFFrameCountQuery };
- void decode(GIFQuery query, unsigned haltAtFrame) const;
+ void decode(GIFQuery, unsigned haltAtFrame) const;
- // Callbacks from the GIF reader.
- void sizeNowAvailable(unsigned width, unsigned height);
- void decodingHalted(unsigned bytesLeft);
- void haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber,
- unsigned repeatCount, bool writeTransparentPixels);
- void frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod);
- void gifComplete();
+ // Callbacks from the GIF reader.
+ void sizeNowAvailable(unsigned width, unsigned height);
+ void decodingHalted(unsigned bytesLeft);
+ void haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber,
+ unsigned repeatCount, bool writeTransparentPixels);
+ void frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod);
+ void gifComplete();
-private:
- // Called to initialize the frame buffer with the given index, based on the
- // previous frame's disposal method.
- void initFrameBuffer(unsigned frameIndex);
+ private:
+ // Called to initialize the frame buffer with the given index, based on the
+ // previous frame's disposal method.
+ void initFrameBuffer(unsigned frameIndex);
- // A helper for initFrameBuffer(), this sets the size of the buffer, and
- // fills it with transparent pixels.
- void prepEmptyFrameBuffer(RGBA32Buffer* buffer) const;
+ // A helper for initFrameBuffer(), this sets the size of the buffer, and
+ // fills it with transparent pixels.
+ void prepEmptyFrameBuffer(RGBA32Buffer*) const;
- bool m_frameCountValid;
- bool m_currentBufferSawAlpha;
- mutable int m_repetitionCount;
- mutable GIFImageDecoderPrivate* m_reader;
-};
+ bool m_frameCountValid;
+ bool m_currentBufferSawAlpha;
+ mutable int m_repetitionCount;
+ mutable GIFImageDecoderPrivate* m_reader;
+ };
-}
+} // namespace WebCore
#endif
diff --git a/WebCore/platform/image-decoders/gif/GIFImageReader.cpp b/WebCore/platform/image-decoders/gif/GIFImageReader.cpp
index 04347af..95ab40d 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageReader.cpp
+++ b/WebCore/platform/image-decoders/gif/GIFImageReader.cpp
@@ -78,8 +78,6 @@ mailing address.
#include <string.h>
#include "GIFImageDecoder.h"
-#if PLATFORM(CAIRO) || PLATFORM(QT) || PLATFORM(WX)
-
using WebCore::GIFImageDecoder;
// Define the Mozilla macro setup so that we can leave the macros alone.
@@ -939,5 +937,3 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len,
clientptr->decodingHalted(0);
return true;
}
-
-#endif // PLATFORM(CAIRO)
diff --git a/WebCore/platform/image-decoders/gif/GIFImageReader.h b/WebCore/platform/image-decoders/gif/GIFImageReader.h
index 855e6be..f0d127f 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageReader.h
+++ b/WebCore/platform/image-decoders/gif/GIFImageReader.h
@@ -35,8 +35,8 @@
*
* ***** END LICENSE BLOCK ***** */
-#ifndef _GIF_H_
-#define _GIF_H_
+#ifndef GIFImageReader_h
+#define GIFImageReader_h
// Define ourselves as the clientPtr. Mozilla just hacked their C++ callback class into this old C decoder,
// so we will too.
@@ -168,7 +168,7 @@ struct GIFImageReader {
unsigned screen_width; /* Logical screen width & height */
unsigned screen_height;
int global_colormap_size; /* Size of global colormap array. */
- int images_decoded; /* Counts completed frames for animated GIFs */
+ unsigned images_decoded; /* Counts completed frames for animated GIFs */
int images_count; /* Counted all frames seen so far (including incomplete frames) */
int loop_count; /* Netscape specific extension block to control
the number of animation loops a GIF renders. */
@@ -213,4 +213,3 @@ private:
};
#endif
-
diff --git a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp b/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp
index 019340d..5b1a88f 100644
--- a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp
@@ -26,8 +26,6 @@
#include "config.h"
#include "ICOImageDecoder.h"
-#if PLATFORM(CAIRO) || PLATFORM(QT) || PLATFORM(WX)
-
namespace WebCore
{
@@ -41,6 +39,4 @@ RGBA32Buffer* ICOImageDecoder::frameBufferAtIndex(size_t index)
return 0;
}
-}
-
-#endif // PLATFORM(CAIRO)
+} // namespace WebCore
diff --git a/WebCore/platform/image-decoders/ico/ICOImageDecoder.h b/WebCore/platform/image-decoders/ico/ICOImageDecoder.h
index a4f3dbd..56a74c3 100644
--- a/WebCore/platform/image-decoders/ico/ICOImageDecoder.h
+++ b/WebCore/platform/image-decoders/ico/ICOImageDecoder.h
@@ -23,27 +23,26 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ICO_DECODER_H_
-#define ICO_DECODER_H_
+#ifndef ICOImageDecoder_h
+#define ICOImageDecoder_h
#include "ImageDecoder.h"
namespace WebCore {
-class ICOImageReader;
+ class ICOImageReader;
-// This class decodes the ICO and CUR image formats.
-class ICOImageDecoder : public ImageDecoder
-{
-public:
- virtual String filenameExtension() const { return "ico"; }
+ // This class decodes the ICO and CUR image formats.
+ class ICOImageDecoder : public ImageDecoder {
+ public:
+ virtual String filenameExtension() const { return "ico"; }
- // Whether or not the size information has been decoded yet.
- virtual bool isSizeAvailable() const;
+ // Whether or not the size information has been decoded yet.
+ virtual bool isSizeAvailable() const;
- virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
-};
+ virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
+ };
-}
+} // namespace WebCore
#endif
diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
index 44e0e4c..38d90bd 100644
--- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
@@ -40,30 +40,13 @@
#include <assert.h>
#include <stdio.h>
-#if PLATFORM(CAIRO) || PLATFORM(QT) || PLATFORM(WX)
-
-#if COMPILER(MSVC)
-// Remove warnings from warning level 4.
-#pragma warning(disable : 4611) // warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable
-
-// if ADDRESS_TAG_BIT is dfined, INT32 has been declared as a typedef in the PlatformSDK (BaseTsd.h),
-// so we need to stop jpeglib.h from trying to #define it
-// see here for more info: http://www.cygwin.com/ml/cygwin/2004-07/msg01051.html
-# if defined(ADDRESS_TAG_BIT) && !defined(XMD_H)
-# define XMD_H
-# define VTK_JPEG_XMD_H
-# endif
-#endif // COMPILER(MSVC)
-
extern "C" {
#include "jpeglib.h"
}
#if COMPILER(MSVC)
-# if defined(VTK_JPEG_XMD_H)
-# undef VTK_JPEG_XMD_H
-# undef XMD_H
-# endif
+// Remove warnings from warning level 4.
+#pragma warning(disable : 4611) // warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable
#endif // COMPILER(MSVC)
#include <setjmp.h>
@@ -482,7 +465,7 @@ bool JPEGImageDecoder::outputScanlines()
if (buffer.status() == RGBA32Buffer::FrameEmpty) {
// Let's resize our buffer now to the correct width/height.
RGBA32Array& bytes = buffer.bytes();
- bytes.resize(m_size.width() * m_size.height());
+ bytes.resize(size().width() * size().height());
// Update our status to be partially complete.
buffer.setStatus(RGBA32Buffer::FramePartial);
@@ -503,7 +486,7 @@ bool JPEGImageDecoder::outputScanlines()
if (jpeg_read_scanlines(info, samples, 1) != 1)
return false;
JSAMPLE *j1 = samples[0];
- for (unsigned i = 0; i < info->output_width; ++i) {
+ for (unsigned x = 0; x < info->output_width; ++x) {
unsigned r = *j1++;
unsigned g = *j1++;
unsigned b = *j1++;
@@ -527,5 +510,3 @@ void JPEGImageDecoder::jpegComplete()
}
}
-
-#endif // PLATFORM(CAIRO)
diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
index b4d7b2a..c01bb5e 100644
--- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
+++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
@@ -23,52 +23,51 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JPEG_DECODER_H_
-#define JPEG_DECODER_H_
+#ifndef JPEGImageDecoder_h
+#define JPEGImageDecoder_h
#include "ImageDecoder.h"
namespace WebCore {
-class JPEGImageReader;
+ class JPEGImageReader;
-// This class decodes the JPEG image format.
-class JPEGImageDecoder : public ImageDecoder
-{
-public:
- JPEGImageDecoder();
- ~JPEGImageDecoder();
+ // This class decodes the JPEG image format.
+ class JPEGImageDecoder : public ImageDecoder {
+ public:
+ JPEGImageDecoder();
+ ~JPEGImageDecoder();
- virtual String filenameExtension() const { return "jpg"; }
+ virtual String filenameExtension() const { return "jpg"; }
- // Take the data and store it.
- virtual void setData(SharedBuffer* data, bool allDataReceived);
+ // Take the data and store it.
+ virtual void setData(SharedBuffer* data, bool allDataReceived);
- // Whether or not the size information has been decoded yet.
- virtual bool isSizeAvailable() const;
+ // Whether or not the size information has been decoded yet.
+ virtual bool isSizeAvailable() const;
- virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
-
- virtual bool supportsAlpha() const { return false; }
+ virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
+
+ virtual bool supportsAlpha() const { return false; }
- void decode(bool sizeOnly = false) const;
+ void decode(bool sizeOnly = false) const;
- JPEGImageReader* reader() { return m_reader; }
+ JPEGImageReader* reader() { return m_reader; }
- void setSize(int width, int height) {
- if (!m_sizeAvailable) {
- m_sizeAvailable = true;
- m_size = IntSize(width, height);
+ void setSize(int width, int height) {
+ if (!m_sizeAvailable) {
+ m_sizeAvailable = true;
+ m_size = IntSize(width, height);
+ }
}
- }
- bool outputScanlines();
- void jpegComplete();
+ bool outputScanlines();
+ void jpegComplete();
-private:
- mutable JPEGImageReader* m_reader;
-};
+ private:
+ mutable JPEGImageReader* m_reader;
+ };
-}
+} // namespace WebCore
#endif
diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
index 17143b1..dead8ca 100644
--- a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
@@ -40,12 +40,10 @@
#include "png.h"
#include "assert.h"
-#if PLATFORM(CAIRO) || PLATFORM(QT) || PLATFORM(WX)
-
#if COMPILER(MSVC)
// Remove warnings from warning level 4.
#pragma warning(disable : 4611) // warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable
-#endif
+#endif // COMPILER(MSVC)
namespace WebCore {
@@ -55,7 +53,7 @@ const double cDefaultGamma = 2.2;
const double cInverseGamma = 0.45455;
// Protect against large PNGs. See Mozilla's bug #251381 for more info.
-const long cMaxPNGSize = 1000000L;
+const unsigned long cMaxPNGSize = 1000000UL;
// Called if the decoding of the image fails.
static void PNGAPI decodingFailed(png_structp png_ptr, png_const_charp error_msg);
@@ -78,9 +76,12 @@ class PNGImageReader
{
public:
PNGImageReader(PNGImageDecoder* decoder)
- : m_readOffset(0), m_decodingSizeOnly(false), m_interlaceBuffer(0), m_hasAlpha(0)
+ : m_readOffset(0)
+ , m_decodingSizeOnly(false)
+ , m_interlaceBuffer(0)
+ , m_hasAlpha(0)
{
- m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, decodingFailed, decodingWarning);
+ m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, decodingFailed, decodingWarning);
m_info = png_create_info_struct(m_png);
png_set_progressive_read_fn(m_png, decoder, headerAvailable, rowAvailable, pngComplete);
}
@@ -92,8 +93,9 @@ public:
void close() {
if (m_png && m_info)
- png_destroy_read_struct(&m_png, &m_info, 0);
+ png_destroy_read_struct(&m_png, &m_info, 0); // Will zero the pointers.
delete []m_interlaceBuffer;
+ m_interlaceBuffer = 0;
m_readOffset = 0;
}
@@ -139,7 +141,7 @@ private:
};
PNGImageDecoder::PNGImageDecoder()
-: m_reader(0)
+ : m_reader(0)
{
m_frameBufferCache.resize(1);
}
@@ -224,6 +226,10 @@ void headerAvailable(png_structp png, png_infop info)
static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->headerAvailable();
}
+void PNGImageDecoder::decodingFailed() {
+ m_failed = true;
+}
+
void PNGImageDecoder::headerAvailable()
{
png_structp png = reader()->pngPtr();
@@ -312,16 +318,16 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex,
if (buffer.status() == RGBA32Buffer::FrameEmpty) {
// Let's resize our buffer now to the correct width/height.
RGBA32Array& bytes = buffer.bytes();
- bytes.resize(m_size.width() * m_size.height());
+ bytes.resize(size().width() * size().height());
// Update our status to be partially complete.
buffer.setStatus(RGBA32Buffer::FramePartial);
// For PNGs, the frame always fills the entire image.
- buffer.setRect(IntRect(0, 0, m_size.width(), m_size.height()));
+ buffer.setRect(IntRect(0, 0, size().width(), size().height()));
if (reader()->pngPtr()->interlaced)
- reader()->createInterlaceBuffer((reader()->hasAlpha() ? 4 : 3) * m_size.width() * m_size.height());
+ reader()->createInterlaceBuffer((reader()->hasAlpha() ? 4 : 3) * size().width() * size().height());
}
if (rowBuffer == 0)
@@ -361,17 +367,17 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex,
png_bytep row;
png_bytep interlaceBuffer = reader()->interlaceBuffer();
if (interlaceBuffer) {
- row = interlaceBuffer + (rowIndex * colorChannels * m_size.width());
+ row = interlaceBuffer + (rowIndex * colorChannels * size().width());
png_progressive_combine_row(png, row, rowBuffer);
}
else
row = rowBuffer;
// Copy the data into our buffer.
- int width = m_size.width();
+ int width = size().width();
unsigned* dst = buffer.bytes().data() + rowIndex * width;
bool sawAlpha = false;
- for (int i = 0; i < width; i++) {
+ for (int x = 0; x < width; x++) {
unsigned red = *row++;
unsigned green = *row++;
unsigned blue = *row++;
@@ -398,6 +404,4 @@ void PNGImageDecoder::pngComplete()
buffer.setStatus(RGBA32Buffer::FrameComplete);
}
-}
-
-#endif // PLATFORM(CAIRO)
+} // namespace WebCore
diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.h b/WebCore/platform/image-decoders/png/PNGImageDecoder.h
index 8c73785..c5264fd 100644
--- a/WebCore/platform/image-decoders/png/PNGImageDecoder.h
+++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.h
@@ -23,46 +23,45 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef PNG_DECODER_H_
-#define PNG_DECODER_H_
+#ifndef PNGImageDecoder_h
+#define PNGImageDecoder_h
#include "ImageDecoder.h"
namespace WebCore {
-class PNGImageReader;
+ class PNGImageReader;
-// This class decodes the PNG image format.
-class PNGImageDecoder : public ImageDecoder
-{
-public:
- PNGImageDecoder();
- ~PNGImageDecoder();
+ // This class decodes the PNG image format.
+ class PNGImageDecoder : public ImageDecoder {
+ public:
+ PNGImageDecoder();
+ ~PNGImageDecoder();
- virtual String filenameExtension() const { return "png"; }
+ virtual String filenameExtension() const { return "png"; }
- // Take the data and store it.
- virtual void setData(SharedBuffer* data, bool allDataReceived);
+ // Take the data and store it.
+ virtual void setData(SharedBuffer* data, bool allDataReceived);
- // Whether or not the size information has been decoded yet.
- virtual bool isSizeAvailable() const;
+ // Whether or not the size information has been decoded yet.
+ virtual bool isSizeAvailable() const;
- virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
+ virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
- void decode(bool sizeOnly = false) const;
+ void decode(bool sizeOnly = false) const;
- PNGImageReader* reader() { return m_reader; }
+ PNGImageReader* reader() { return m_reader; }
- // Callbacks from libpng
- void decodingFailed() { m_failed = true; }
- void headerAvailable();
- void rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, int interlacePass);
- void pngComplete();
+ // Callbacks from libpng
+ void decodingFailed();
+ void headerAvailable();
+ void rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, int interlacePass);
+ void pngComplete();
-private:
- mutable PNGImageReader* m_reader;
-};
+ private:
+ mutable PNGImageReader* m_reader;
+ };
-}
+} // namespace WebCore
#endif
diff --git a/WebCore/platform/image-decoders/skia/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/skia/GIFImageDecoder.cpp
index 2d77943..c03452a 100644
--- a/WebCore/platform/image-decoders/skia/GIFImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/skia/GIFImageDecoder.cpp
@@ -126,7 +126,7 @@ bool GIFImageDecoder::isSizeAvailable() const
decode(GIFSizeQuery, 0);
}
- return !m_failed && ImageDecoder::isSizeAvailable();
+ return ImageDecoder::isSizeAvailable();
}
// The total number of frames for the image. Will scan the image data for the answer
@@ -183,7 +183,7 @@ RGBA32Buffer* GIFImageDecoder::frameBufferAtIndex(size_t index)
RGBA32Buffer& frame = m_frameBufferCache[index];
if (frame.status() != RGBA32Buffer::FrameComplete && m_reader)
- decode(GIFFullQuery, index+1); // Decode this frame.
+ decode(GIFFullQuery, index + 1); // Decode this frame.
return &frame;
}
diff --git a/WebCore/platform/image-decoders/skia/GIFImageReader.h b/WebCore/platform/image-decoders/skia/GIFImageReader.h
index aa3d717..f0d127f 100644
--- a/WebCore/platform/image-decoders/skia/GIFImageReader.h
+++ b/WebCore/platform/image-decoders/skia/GIFImageReader.h
@@ -167,11 +167,11 @@ struct GIFImageReader {
int version; /* Either 89 for GIF89 or 87 for GIF87 */
unsigned screen_width; /* Logical screen width & height */
unsigned screen_height;
- int global_colormap_size; /* Size of global colormap array. */
- unsigned int images_decoded; /* Counts completed frames for animated GIFs */
- int images_count; /* Counted all frames seen so far (including incomplete frames) */
- int loop_count; /* Netscape specific extension block to control
- the number of animation loops a GIF renders. */
+ int global_colormap_size; /* Size of global colormap array. */
+ unsigned images_decoded; /* Counts completed frames for animated GIFs */
+ int images_count; /* Counted all frames seen so far (including incomplete frames) */
+ int loop_count; /* Netscape specific extension block to control
+ the number of animation loops a GIF renders. */
// Not really global, but convenient to locate here.
int count; /* Remaining # bytes in sub-block */
diff --git a/WebCore/platform/image-decoders/skia/ImageDecoder.h b/WebCore/platform/image-decoders/skia/ImageDecoder.h
index cddb69b..c198420 100644
--- a/WebCore/platform/image-decoders/skia/ImageDecoder.h
+++ b/WebCore/platform/image-decoders/skia/ImageDecoder.h
@@ -33,8 +33,6 @@
#include "PlatformString.h"
#include "SharedBuffer.h"
#include <wtf/Assertions.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
@@ -45,37 +43,8 @@
namespace WebCore {
- class RefCountedNativeImageSkia : public RefCounted<RefCountedNativeImageSkia> {
- public:
- static PassRefPtr<RefCountedNativeImageSkia> create()
- {
- return adoptRef(new RefCountedNativeImageSkia);
- }
-
- const NativeImageSkia& bitmap() const { return m_bitmap; }
- NativeImageSkia& bitmap() { return m_bitmap; }
-
- private:
- RefCountedNativeImageSkia() {}
- NativeImageSkia m_bitmap;
- };
-
- // The RGBA32Buffer 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.
- //
- // The image data of an RGBA32Buffer is kept in an SkBitmapRef, a refcounting
- // container for an SkBitmap. In all normal cases, the refcount should be
- // exactly one. The exception happens when resizing the vector<RGBA32Buffer> in
- // ImageDecoder::m_frameBufferCache, which copies all the buffers to the new
- // vector, thus transiently incrementing the refcount to two.
- //
- // The choice to use an SkBitmapRef instead of an SkBitmap is not because of
- // performance concerns -- SkBitmap refcounts its internal data anyway. Rather,
- // we need the aforementioned vector resize to preserve the exact underlying
- // SkBitmap object, since we may have already given its address to
- // BitmapImage::m_frames. Using an SkBitmap would mean that after ImageDecoder
- // resizes its vector, BitmapImage would be holding a pointer to garbage.
+ // The RGBA32Buffer 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.
class RGBA32Buffer {
public:
enum FrameStatus { FrameEmpty, FramePartial, FrameComplete };
@@ -94,14 +63,12 @@ namespace WebCore {
, m_duration(0)
, m_disposalMethod(DisposeNotSpecified)
{
- m_bitmapRef = RefCountedNativeImageSkia::create();
}
// This constructor doesn't create a new copy of the image data, it only
// increases the ref count of the existing bitmap.
RGBA32Buffer(const RGBA32Buffer& other)
{
- m_bitmapRef = RefCountedNativeImageSkia::create();
operator=(other);
}
@@ -120,18 +87,20 @@ namespace WebCore {
if (this == &other)
return *this;
- m_bitmapRef = other.m_bitmapRef;
+ m_bitmap = other.m_bitmap;
+ // Keep the pixels locked since we will be writing directly into the
+ // bitmap throughout this object's lifetime.
+ m_bitmap.lockPixels();
setRect(other.rect());
setStatus(other.status());
setDuration(other.duration());
setDisposalMethod(other.disposalMethod());
- setHasAlpha(other.hasAlpha());
return *this;
}
void clear()
{
- m_bitmapRef = RefCountedNativeImageSkia::create();
+ m_bitmap.reset();
m_status = FrameEmpty;
// NOTE: Do not reset other members here; clearFrameBufferCache()
// calls this to free the bitmap data, but other functions like
@@ -146,21 +115,13 @@ namespace WebCore {
if (this == &other)
return;
- m_bitmapRef = RefCountedNativeImageSkia::create();
- SkBitmap& bmp = bitmap();
- const SkBitmap& otherBmp = other.bitmap();
- bmp.setConfig(SkBitmap::kARGB_8888_Config, other.width(),
- other.height(), otherBmp.rowBytes());
- bmp.allocPixels();
- if (width() > 0 && height() > 0) {
- memcpy(bmp.getAddr32(0, 0),
- otherBmp.getAddr32(0, 0),
- otherBmp.rowBytes() * height());
- }
+ m_bitmap.reset();
+ const NativeImageSkia& otherBitmap = other.bitmap();
+ otherBitmap.copyTo(&m_bitmap, otherBitmap.config());
}
- NativeImageSkia& bitmap() { return m_bitmapRef->bitmap(); }
- const NativeImageSkia& bitmap() const { return m_bitmapRef->bitmap(); }
+ NativeImageSkia& bitmap() { return m_bitmap; }
+ const NativeImageSkia& bitmap() const { return m_bitmap; }
// Must be called before any pixels are written. Will return true on
// success, false if the memory allocation fails.
@@ -168,37 +129,36 @@ namespace WebCore {
{
// This function should only be called once, it will leak memory
// otherwise.
- SkBitmap& bmp = bitmap();
- ASSERT(bmp.width() == 0 && bmp.height() == 0);
- bmp.setConfig(SkBitmap::kARGB_8888_Config, width, height);
- if (!bmp.allocPixels())
+ ASSERT(m_bitmap.width() == 0 && m_bitmap.height() == 0);
+ m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
+ if (!m_bitmap.allocPixels())
return false; // Allocation failure, maybe the bitmap was too big.
// Clear the image.
- bmp.eraseARGB(0, 0, 0, 0);
+ m_bitmap.eraseARGB(0, 0, 0, 0);
return true;
}
- int width() const { return bitmap().width(); }
- int height() const { return bitmap().height(); }
+ int width() const { return m_bitmap.width(); }
+ int height() const { return m_bitmap.height(); }
const IntRect& rect() const { return m_rect; }
FrameStatus status() const { return m_status; }
unsigned duration() const { return m_duration; }
FrameDisposalMethod disposalMethod() const { return m_disposalMethod; }
- bool hasAlpha() const { return !bitmap().isOpaque(); }
+ bool hasAlpha() const { return !m_bitmap.isOpaque(); }
void setRect(const IntRect& r) { m_rect = r; }
void setStatus(FrameStatus s)
{
if (s == FrameComplete)
- m_bitmapRef->bitmap().setDataComplete(); // Tell the bitmap it's done.
+ m_bitmap.setDataComplete(); // Tell the bitmap it's done.
m_status = s;
}
void setDuration(unsigned duration) { m_duration = duration; }
void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
- void setHasAlpha(bool alpha) { bitmap().setIsOpaque(!alpha); }
+ void setHasAlpha(bool alpha) { m_bitmap.setIsOpaque(!alpha); }
static void setRGBA(uint32_t* dest, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
@@ -223,11 +183,11 @@ namespace WebCore {
void setRGBA(int x, int y, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
- setRGBA(bitmap().getAddr32(x, y), r, g, b, a);
+ setRGBA(m_bitmap.getAddr32(x, y), r, g, b, a);
}
private:
- RefPtr<RefCountedNativeImageSkia> m_bitmapRef;
+ NativeImageSkia m_bitmap;
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.
@@ -241,7 +201,12 @@ namespace WebCore {
// and the base class manages the RGBA32 frame cache.
class ImageDecoder {
public:
- ImageDecoder() : m_failed(false), m_sizeAvailable(false) {}
+ ImageDecoder()
+ : m_failed(false)
+ , m_sizeAvailable(false)
+ {
+ }
+
virtual ~ImageDecoder() {}
// The the filename extension usually associated with an undecoded image of this type.
diff --git a/WebCore/platform/image-decoders/skia/JPEGImageDecoder.cpp b/WebCore/platform/image-decoders/skia/JPEGImageDecoder.cpp
index 98f622e..ab74012 100644
--- a/WebCore/platform/image-decoders/skia/JPEGImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/skia/JPEGImageDecoder.cpp
@@ -99,7 +99,7 @@ public:
/* Allocate and initialize JPEG decompression object */
jpeg_create_decompress(&m_info);
- decoder_source_mgr* src = NULL;
+ decoder_source_mgr* src = 0;
if (!m_info.src) {
src = (decoder_source_mgr*)fastCalloc(sizeof(decoder_source_mgr), 1);
if (!src) {
@@ -421,7 +421,7 @@ bool JPEGImageDecoder::isSizeAvailable() const
decode(true);
}
- return !m_failed && ImageDecoder::isSizeAvailable();
+ return ImageDecoder::isSizeAvailable();
}
RGBA32Buffer* JPEGImageDecoder::frameBufferAtIndex(size_t index)
diff --git a/WebCore/platform/image-decoders/skia/PNGImageDecoder.cpp b/WebCore/platform/image-decoders/skia/PNGImageDecoder.cpp
index ec1ebbe..ad12b86 100644
--- a/WebCore/platform/image-decoders/skia/PNGImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/skia/PNGImageDecoder.cpp
@@ -72,9 +72,12 @@ class PNGImageReader
{
public:
PNGImageReader(PNGImageDecoder* decoder)
- : m_readOffset(0), m_decodingSizeOnly(false), m_interlaceBuffer(0), m_hasAlpha(0)
+ : m_readOffset(0)
+ , m_decodingSizeOnly(false)
+ , m_interlaceBuffer(0)
+ , m_hasAlpha(0)
{
- m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, decodingFailed, decodingWarning);
+ m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, decodingFailed, decodingWarning);
m_info = png_create_info_struct(m_png);
png_set_progressive_read_fn(m_png, decoder, headerAvailable, rowAvailable, pngComplete);
}
@@ -134,8 +137,9 @@ private:
};
PNGImageDecoder::PNGImageDecoder()
-: m_reader(0)
-{}
+ : m_reader(0)
+{
+}
PNGImageDecoder::~PNGImageDecoder()
{
@@ -169,7 +173,7 @@ bool PNGImageDecoder::isSizeAvailable() const
decode(true);
}
- return !m_failed && ImageDecoder::isSizeAvailable();
+ return ImageDecoder::isSizeAvailable();
}
RGBA32Buffer* PNGImageDecoder::frameBufferAtIndex(size_t index)
@@ -305,8 +309,7 @@ void PNGImageDecoder::headerAvailable()
void rowAvailable(png_structp png, png_bytep rowBuffer,
png_uint_32 rowIndex, int interlacePass)
{
- static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->rowAvailable(
- rowBuffer, rowIndex, interlacePass);
+ static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->rowAvailable(rowBuffer, rowIndex, interlacePass);
}
void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, int interlacePass)
diff --git a/WebCore/platform/image-decoders/skia/XBMImageDecoder.h b/WebCore/platform/image-decoders/skia/XBMImageDecoder.h
index 44c6be2..cdcf8e6 100644
--- a/WebCore/platform/image-decoders/skia/XBMImageDecoder.h
+++ b/WebCore/platform/image-decoders/skia/XBMImageDecoder.h
@@ -31,7 +31,6 @@
#ifndef XBMImageDecoder_h
#define XBMImageDecoder_h
-#include "config.h"
#include <string>
#include "ImageDecoder.h"
diff --git a/WebCore/platform/image-decoders/xbm/XBMImageDecoder.cpp b/WebCore/platform/image-decoders/xbm/XBMImageDecoder.cpp
index 30c5589..3e8ae57 100644
--- a/WebCore/platform/image-decoders/xbm/XBMImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/xbm/XBMImageDecoder.cpp
@@ -26,8 +26,6 @@
#include "config.h"
#include "XBMImageDecoder.h"
-#if PLATFORM(CAIRO) || PLATFORM(QT) || PLATFORM(WX)
-
namespace WebCore
{
@@ -41,6 +39,4 @@ RGBA32Buffer* XBMImageDecoder::frameBufferAtIndex(size_t index)
return 0;
}
-}
-
-#endif // PLATFORM(CAIRO)
+} // namespace WebCore
diff --git a/WebCore/platform/image-decoders/xbm/XBMImageDecoder.h b/WebCore/platform/image-decoders/xbm/XBMImageDecoder.h
index dc6d8d4..80cfb3f 100644
--- a/WebCore/platform/image-decoders/xbm/XBMImageDecoder.h
+++ b/WebCore/platform/image-decoders/xbm/XBMImageDecoder.h
@@ -23,27 +23,26 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef XBM_DECODER_H_
-#define XBM_DECODER_H_
+#ifndef XBMImageDecoder_h
+#define XBMImageDecoder_h
#include "ImageDecoder.h"
namespace WebCore {
-class XBMImageReader;
+ class XBMImageReader;
-// This class decodes the XBM image format.
-class XBMImageDecoder : public ImageDecoder
-{
-public:
- virtual String filenameExtension() const { return "xbm"; }
+ // This class decodes the XBM image format.
+ class XBMImageDecoder : public ImageDecoder {
+ public:
+ virtual String filenameExtension() const { return "xbm"; }
- // Whether or not the size information has been decoded yet.
- virtual bool isSizeAvailable() const;
+ // Whether or not the size information has been decoded yet.
+ virtual bool isSizeAvailable() const;
- virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
-};
+ virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
+ };
-}
+} // namespace WebCore
#endif
diff --git a/WebCore/platform/mac/ClipboardMac.mm b/WebCore/platform/mac/ClipboardMac.mm
index cfa334b..d1b66a7 100644
--- a/WebCore/platform/mac/ClipboardMac.mm
+++ b/WebCore/platform/mac/ClipboardMac.mm
@@ -39,6 +39,10 @@
#import "SecurityOrigin.h"
#import "WebCoreSystemInterface.h"
+#ifdef BUILDING_ON_TIGER
+typedef unsigned NSUInteger;
+#endif
+
namespace WebCore {
ClipboardMac::ClipboardMac(bool forDragging, NSPasteboard *pasteboard, ClipboardAccessPolicy policy, Frame *frame)
@@ -121,9 +125,8 @@ void ClipboardMac::clearData(const String& type)
// note NSPasteboard enforces changeCount itself on writing - can't write if not the owner
NSString *cocoaType = cocoaTypeFromMIMEType(type);
- if (cocoaType) {
+ if (cocoaType)
[m_pasteboard.get() setString:@"" forType:cocoaType];
- }
}
void ClipboardMac::clearAllData()
@@ -136,57 +139,71 @@ void ClipboardMac::clearAllData()
[m_pasteboard.get() declareTypes:[NSArray array] owner:nil];
}
+static NSArray *absoluteURLsFromPasteboardFilenames(NSPasteboard* pasteboard, bool onlyFirstURL)
+{
+ NSArray *fileList = [pasteboard propertyListForType:NSFilenamesPboardType];
+
+ // FIXME: Why does this code need to guard against bad values on the pasteboard?
+ ASSERT(!fileList || [fileList isKindOfClass:[NSArray class]]);
+ if (!fileList || ![fileList isKindOfClass:[NSArray class]] || ![fileList count])
+ return nil;
+
+ NSUInteger count = onlyFirstURL ? 1 : [fileList count];
+ NSMutableArray *urls = [NSMutableArray array];
+ for (NSUInteger i = 0; i < count; i++) {
+ NSString *string = [fileList objectAtIndex:i];
+
+ ASSERT([string isKindOfClass:[NSString class]]); // Added to understand why this if code is here
+ if (![string isKindOfClass:[NSString class]])
+ return nil; // Non-string object in the list, bail out! FIXME: When can this happen?
+
+ NSURL *url = [NSURL fileURLWithPath:string];
+ [urls addObject:[url absoluteString]];
+ }
+ return urls;
+}
+
+static NSArray *absoluteURLsFromPasteboard(NSPasteboard* pasteboard, bool onlyFirstURL)
+{
+ // NOTE: We must always check [availableTypes containsObject:] before accessing pasteboard data
+ // or CoreFoundation will printf when there is not data of the corresponding type.
+ NSArray *availableTypes = [pasteboard types];
+
+ // Try NSFilenamesPboardType because it contains a list
+ if ([availableTypes containsObject:NSFilenamesPboardType]) {
+ if (NSArray* absoluteURLs = absoluteURLsFromPasteboardFilenames(pasteboard, onlyFirstURL))
+ return absoluteURLs;
+ }
+
+ // Fallback to NSURLPboardType (which is a single URL)
+ if ([availableTypes containsObject:NSURLPboardType]) {
+ if (NSURL *url = [NSURL URLFromPasteboard:pasteboard])
+ return [NSArray arrayWithObject:[url absoluteString]];
+ }
+
+ // No file paths on the pasteboard, return nil
+ return nil;
+}
+
String ClipboardMac::getData(const String& type, bool& success) const
{
success = false;
if (policy() != ClipboardReadable)
return String();
-
+
NSString *cocoaType = cocoaTypeFromMIMEType(type);
NSString *cocoaValue = nil;
- NSArray *availableTypes = [m_pasteboard.get() types];
-
- // Fetch the data in different ways for the different Cocoa types
+ // Grab the value off the pasteboard corresponding to the cocoaType
if ([cocoaType isEqualToString:NSURLPboardType]) {
- // When both URL and filenames are present, filenames is superior since it can contain a list.
- // must check this or we get a printf from CF when there's no data of this type
- if ([availableTypes containsObject:NSFilenamesPboardType]) {
- NSArray *fileList = [m_pasteboard.get() propertyListForType:NSFilenamesPboardType];
- if (fileList && [fileList isKindOfClass:[NSArray class]]) {
- unsigned count = [fileList count];
- if (count > 0) {
- if (type != "text/uri-list")
- count = 1;
- NSMutableString *urls = [NSMutableString string];
- unsigned i;
- for (i = 0; i < count; i++) {
- if (i > 0) {
- [urls appendString:@"\n"];
- }
- NSString *string = [fileList objectAtIndex:i];
- if (![string isKindOfClass:[NSString class]])
- break;
- NSURL *url = [NSURL fileURLWithPath:string];
- [urls appendString:[url absoluteString]];
- }
- if (i == count)
- cocoaValue = urls;
- }
- }
- }
- if (!cocoaValue) {
- // must check this or we get a printf from CF when there's no data of this type
- if ([availableTypes containsObject:NSURLPboardType]) {
- NSURL *url = [NSURL URLFromPasteboard:m_pasteboard.get()];
- if (url) {
- cocoaValue = [url absoluteString];
- }
- }
- }
- } else if (cocoaType) {
+ // "URL" and "text/url-list" both map to NSURLPboardType in cocoaTypeFromMIMEType(), "URL" only wants the first URL
+ bool onlyFirstURL = (type == "URL");
+ NSArray *absoluteURLs = absoluteURLsFromPasteboard(m_pasteboard.get(), onlyFirstURL);
+ cocoaValue = [absoluteURLs componentsJoinedByString:@"\n"];
+ } else if ([cocoaType isEqualToString:NSStringPboardType]) {
+ cocoaValue = [[m_pasteboard.get() stringForType:cocoaType] precomposedStringWithCanonicalMapping];
+ } else if (cocoaType)
cocoaValue = [m_pasteboard.get() stringForType:cocoaType];
- }
// Enforce changeCount ourselves for security. We check after reading instead of before to be
// sure it doesn't change between our testing the change count and accessing the data.
@@ -244,18 +261,15 @@ HashSet<String> ClipboardMac::types() const
return HashSet<String>();
HashSet<String> result;
- if (types) {
- unsigned count = [types count];
- unsigned i;
- for (i = 0; i < count; i++) {
- NSString *pbType = [types objectAtIndex:i];
- if ([pbType isEqualToString:@"NeXT plain ascii pasteboard type"])
- continue; // skip this ancient type that gets auto-supplied by some system conversion
-
- String str = MIMETypeFromCocoaType(pbType);
- if (!result.contains(str))
- result.add(str);
- }
+ NSUInteger count = [types count];
+ for (NSUInteger i = 0; i < count; i++) {
+ NSString *pbType = [types objectAtIndex:i];
+ if ([pbType isEqualToString:@"NeXT plain ascii pasteboard type"])
+ continue; // skip this ancient type that gets auto-supplied by some system conversion
+
+ String str = MIMETypeFromCocoaType(pbType);
+ if (!result.contains(str))
+ result.add(str);
}
return result;
}
@@ -324,7 +338,7 @@ void ClipboardMac::declareAndWriteDragImage(Element* element, const KURL& url, c
{
ASSERT(frame);
if (Page* page = frame->page())
- page->dragController()->client()->declareAndWriteDragImage(m_pasteboard.get(), [DOMElement _wrapElement:element], url, title, frame);
+ page->dragController()->client()->declareAndWriteDragImage(m_pasteboard.get(), kit(element), url, title, frame);
}
DragImageRef ClipboardMac::createDragImage(IntPoint& loc) const
diff --git a/WebCore/platform/mac/CookieJar.mm b/WebCore/platform/mac/CookieJar.mm
index 94b7d77..d8df601 100644
--- a/WebCore/platform/mac/CookieJar.mm
+++ b/WebCore/platform/mac/CookieJar.mm
@@ -27,6 +27,7 @@
#import "CookieJar.h"
#import "BlockExceptions.h"
+#import "Document.h"
#import "KURL.h"
#import <wtf/RetainPtr.h>
@@ -84,7 +85,7 @@ String cookies(const Document*, const KURL& url)
return String();
}
-void setCookies(Document*, const KURL& url, const KURL& policyBaseURL, const String& cookieStr)
+void setCookies(Document* document, const KURL& url, const String& cookieStr)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
@@ -99,7 +100,7 @@ void setCookies(Document*, const KURL& url, const KURL& policyBaseURL, const Str
NSURL *cookieURL = url;
NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:[NSDictionary dictionaryWithObject:cookieString forKey:@"Set-Cookie"] forURL:cookieURL];
- [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:filterCookies(cookies).get() forURL:cookieURL mainDocumentURL:policyBaseURL];
+ [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:filterCookies(cookies).get() forURL:cookieURL mainDocumentURL:document->firstPartyForCookies()];
END_BLOCK_OBJC_EXCEPTIONS;
}
diff --git a/WebCore/platform/mac/DragDataMac.mm b/WebCore/platform/mac/DragDataMac.mm
index 5cf2e14..a7b751c 100644
--- a/WebCore/platform/mac/DragDataMac.mm
+++ b/WebCore/platform/mac/DragDataMac.mm
@@ -124,7 +124,7 @@ String DragData::asURL(String* title) const
PassRefPtr<DocumentFragment> DragData::asFragment(Document*) const
{
- return [m_pasteboardHelper->fragmentFromPasteboard([m_platformDragData draggingPasteboard]) _documentFragment];
+ return core(m_pasteboardHelper->fragmentFromPasteboard([m_platformDragData draggingPasteboard]));
}
}
diff --git a/WebCore/platform/mac/GeolocationServiceMac.mm b/WebCore/platform/mac/GeolocationServiceMac.mm
index c21b02c..01eca4a 100644
--- a/WebCore/platform/mac/GeolocationServiceMac.mm
+++ b/WebCore/platform/mac/GeolocationServiceMac.mm
@@ -153,26 +153,36 @@ void GeolocationServiceMac::errorOccurred(PassRefPtr<PositionError> error)
UNUSED_PARAM(oldLocation);
// Normalize
+ bool canProvideAltitude = true;
+ bool canProvideAltitudeAccuracy = true;
double altitude = newLocation.altitude;
double altitudeAccuracy = newLocation.verticalAccuracy;
if (altitudeAccuracy < 0.0) {
- altitudeAccuracy = 0.0;
- altitude = 0.0;
+ canProvideAltitude = false;
+ canProvideAltitudeAccuracy = false;
}
+
+ bool canProvideSpeed = true;
double speed = newLocation.speed;
if (speed < 0.0)
- speed = 0.0;
+ canProvideSpeed = false;
+
+ bool canProvideHeading = true;
double heading = newLocation.course;
if (heading < 0.0)
- heading = 0.0;
+ canProvideHeading = false;
WTF::RefPtr<WebCore::Coordinates> newCoordinates = WebCore::Coordinates::create(
newLocation.coordinate.latitude,
newLocation.coordinate.longitude,
+ canProvideAltitude,
altitude,
newLocation.horizontalAccuracy,
+ canProvideAltitudeAccuracy,
altitudeAccuracy,
+ canProvideHeading,
heading,
+ canProvideSpeed,
speed);
WTF::RefPtr<WebCore::Geoposition> newPosition = WebCore::Geoposition::create(
newCoordinates.release(),
diff --git a/WebCore/platform/mac/LocalizedStringsMac.mm b/WebCore/platform/mac/LocalizedStringsMac.mm
index d465758..ebb6d93 100644
--- a/WebCore/platform/mac/LocalizedStringsMac.mm
+++ b/WebCore/platform/mac/LocalizedStringsMac.mm
@@ -433,6 +433,110 @@ String contextMenuItemTagRightToLeft()
return String();
}
+String contextMenuItemTagCorrectSpellingAutomatically()
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return [[WebCoreViewFactory sharedFactory] contextMenuItemTagCorrectSpellingAutomatically];
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return String();
+}
+
+String contextMenuItemTagSubstitutionsMenu()
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return [[WebCoreViewFactory sharedFactory] contextMenuItemTagSubstitutionsMenu];
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return String();
+}
+
+String contextMenuItemTagShowSubstitutions(bool show)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return [[WebCoreViewFactory sharedFactory] contextMenuItemTagShowSubstitutions:show];
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return String();
+}
+
+String contextMenuItemTagSmartCopyPaste()
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return [[WebCoreViewFactory sharedFactory] contextMenuItemTagSmartCopyPaste];
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return String();
+}
+
+String contextMenuItemTagSmartQuotes()
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return [[WebCoreViewFactory sharedFactory] contextMenuItemTagSmartQuotes];
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return String();
+}
+
+String contextMenuItemTagSmartDashes()
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return [[WebCoreViewFactory sharedFactory] contextMenuItemTagSmartDashes];
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return String();
+}
+
+String contextMenuItemTagSmartLinks()
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return [[WebCoreViewFactory sharedFactory] contextMenuItemTagSmartLinks];
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return String();
+}
+
+String contextMenuItemTagTextReplacement()
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return [[WebCoreViewFactory sharedFactory] contextMenuItemTagTextReplacement];
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return String();
+}
+
+String contextMenuItemTagTransformationsMenu()
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return [[WebCoreViewFactory sharedFactory] contextMenuItemTagTransformationsMenu];
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return String();
+}
+
+String contextMenuItemTagMakeUpperCase()
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return [[WebCoreViewFactory sharedFactory] contextMenuItemTagMakeUpperCase];
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return String();
+}
+
+String contextMenuItemTagMakeLowerCase()
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return [[WebCoreViewFactory sharedFactory] contextMenuItemTagMakeLowerCase];
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return String();
+}
+
+String contextMenuItemTagCapitalize()
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return [[WebCoreViewFactory sharedFactory] contextMenuItemTagCapitalize];
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return String();
+}
+
+String contextMenuItemTagChangeBack(const String& replacedString)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return [[WebCoreViewFactory sharedFactory] contextMenuItemTagChangeBack:replacedString];
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return replacedString;
+}
+
String contextMenuItemTagInspectElement()
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
diff --git a/WebCore/platform/mac/PasteboardMac.mm b/WebCore/platform/mac/PasteboardMac.mm
index 36b00f6..c0e43b3 100644
--- a/WebCore/platform/mac/PasteboardMac.mm
+++ b/WebCore/platform/mac/PasteboardMac.mm
@@ -139,7 +139,7 @@ void Pasteboard::writeSelection(NSPasteboard* pasteboard, Range* selectedRange,
Pasteboard::generalPasteboard(); //Initialises pasteboard types
ASSERT(selectedRange);
- NSAttributedString *attributedString = [[[NSAttributedString alloc] _initWithDOMRange:[DOMRange _wrapRange:selectedRange]] autorelease];
+ NSAttributedString *attributedString = [[[NSAttributedString alloc] _initWithDOMRange:kit(selectedRange)] autorelease];
#ifdef BUILDING_ON_TIGER
// 4930197: Mail overrides [WebHTMLView pasteboardTypesForSelection] in order to add another type to the pasteboard
// after WebKit does. On Tiger we must call this function so that Mail code will be executed, meaning that
@@ -368,7 +368,7 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP
if (allowPlainText && [types containsObject:NSStringPboardType]) {
chosePlainText = true;
- RefPtr<DocumentFragment> fragment = createFragmentFromText(context.get(), [m_pasteboard.get() stringForType:NSStringPboardType]);
+ RefPtr<DocumentFragment> fragment = createFragmentFromText(context.get(), [[m_pasteboard.get() stringForType:NSStringPboardType] precomposedStringWithCanonicalMapping]);
if (fragment)
return fragment.release();
}
diff --git a/WebCore/platform/mac/PlatformMouseEventMac.mm b/WebCore/platform/mac/PlatformMouseEventMac.mm
index 8979124..74f694e 100644
--- a/WebCore/platform/mac/PlatformMouseEventMac.mm
+++ b/WebCore/platform/mac/PlatformMouseEventMac.mm
@@ -68,12 +68,12 @@ static int clickCountForEvent(NSEvent *event)
}
}
-IntPoint globalPoint(const NSPoint& windowPoint, NSWindow* window)
+IntPoint globalPoint(const NSPoint& windowPoint, NSWindow *window)
{
return IntPoint(flipScreenPoint([window convertBaseToScreen:windowPoint], screenForWindow(window)));
}
-IntPoint pointForEvent(NSEvent *event)
+IntPoint pointForEvent(NSEvent *event, NSView *windowView)
{
switch ([event type]) {
case NSLeftMouseDown:
@@ -86,11 +86,14 @@ IntPoint pointForEvent(NSEvent *event)
case NSOtherMouseUp:
case NSOtherMouseDragged:
case NSMouseMoved:
- case NSScrollWheel:
- // Note: This has its origin at the bottom left of the window.
- // The Y coordinate gets flipped by ScrollView::viewportToContents.
- // We should probably change both this and that to not use "bottom left origin" coordinates at all.
- return IntPoint([event locationInWindow]);
+ case NSScrollWheel: {
+ // Note: This will have its origin at the bottom left of the window unless windowView is flipped.
+ // In those cases, the Y coordinate gets flipped by Widget::convertFromContainingWindow.
+ NSPoint location = [event locationInWindow];
+ if (windowView)
+ location = [windowView convertPoint:location fromView:nil];
+ return IntPoint(location);
+ }
default:
return IntPoint();
}
@@ -139,8 +142,8 @@ static MouseEventType mouseEventForNSEvent(NSEvent* event)
}
}
-PlatformMouseEvent::PlatformMouseEvent(NSEvent* event)
- : m_position(pointForEvent(event))
+PlatformMouseEvent::PlatformMouseEvent(NSEvent* event, NSView *windowView)
+ : m_position(pointForEvent(event, windowView))
, m_globalPosition(globalPointForEvent(event))
, m_button(mouseButtonForEvent(event))
, m_eventType(mouseEventForNSEvent(event))
diff --git a/WebCore/platform/mac/RuntimeApplicationChecks.h b/WebCore/platform/mac/RuntimeApplicationChecks.h
new file mode 100644
index 0000000..44eedfa
--- /dev/null
+++ b/WebCore/platform/mac/RuntimeApplicationChecks.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 RuntimeApplicationChecks_h
+#define RuntimeApplicationChecks_h
+
+namespace WebCore {
+
+bool applicationIsAppleMail();
+bool applicationIsSafari();
+
+} // namespace WebCore
+
+#endif // RuntimeApplicationChecks_h
diff --git a/WebCore/platform/mac/RuntimeApplicationChecks.mm b/WebCore/platform/mac/RuntimeApplicationChecks.mm
new file mode 100644
index 0000000..1670185
--- /dev/null
+++ b/WebCore/platform/mac/RuntimeApplicationChecks.mm
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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.
+ */
+
+#import "config.h"
+#import "RuntimeApplicationChecks.h"
+
+
+namespace WebCore {
+
+bool applicationIsAppleMail()
+{
+ static const bool isAppleMail = [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.mail"];
+ return isAppleMail;
+}
+
+bool applicationIsSafari()
+{
+ static const bool isSafari = [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"];
+ return isSafari;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/mac/ScrollbarThemeMac.mm b/WebCore/platform/mac/ScrollbarThemeMac.mm
index 22bfe46..759a6e1 100644
--- a/WebCore/platform/mac/ScrollbarThemeMac.mm
+++ b/WebCore/platform/mac/ScrollbarThemeMac.mm
@@ -26,14 +26,9 @@
#include "config.h"
#include "ScrollbarThemeMac.h"
-#include "GraphicsContext.h"
#include "ImageBuffer.h"
-#include "IntRect.h"
-#include "Page.h"
#include "PlatformMouseEvent.h"
-#include "Scrollbar.h"
-#include "ScrollbarClient.h"
-#include "Settings.h"
+#include "ScrollView.h"
#include <Carbon/Carbon.h>
#include <wtf/StdLibExtras.h>
#include <wtf/UnusedParam.h>
@@ -371,9 +366,12 @@ bool ScrollbarThemeMac::paint(Scrollbar* scrollbar, GraphicsContext* context, co
trackInfo.attributes = 0;
if (scrollbar->orientation() == HorizontalScrollbar)
trackInfo.attributes |= kThemeTrackHorizontal;
- trackInfo.enableState = scrollbar->client()->isActive() ? kThemeTrackActive : kThemeTrackInactive;
+
if (!scrollbar->enabled())
trackInfo.enableState = kThemeTrackDisabled;
+ else
+ trackInfo.enableState = scrollbar->client()->isActive() ? kThemeTrackActive : kThemeTrackInactive;
+
if (hasThumb(scrollbar))
trackInfo.attributes |= kThemeTrackShowThumb;
else if (!hasButtons(scrollbar))
@@ -393,8 +391,8 @@ bool ScrollbarThemeMac::paint(Scrollbar* scrollbar, GraphicsContext* context, co
bufferRect.intersect(damageRect);
bufferRect.move(-scrollbar->frameRect().x(), -scrollbar->frameRect().y());
- auto_ptr<ImageBuffer> imageBuffer = ImageBuffer::create(bufferRect.size(), false);
- if (!imageBuffer.get())
+ OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(bufferRect.size(), false);
+ if (!imageBuffer)
return true;
HIThemeDrawTrack(&trackInfo, 0, imageBuffer->context()->platformContext(), kHIThemeOrientationNormal);
diff --git a/WebCore/platform/mac/WebCoreTextRenderer.h b/WebCore/platform/mac/SuddenTermination.mm
index 73753bc..513d01b 100644
--- a/WebCore/platform/mac/WebCoreTextRenderer.h
+++ b/WebCore/platform/mac/SuddenTermination.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,40 +10,36 @@
* 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
+ * 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
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#import <AppKit/NSFontManager.h>
-#import <CoreFoundation/CFString.h>
+#import "config.h"
+#import "SuddenTermination.h"
-#ifdef __OBJC__
-@class NSColor;
-@class NSFont;
-@class NSString;
-#endif
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
-#ifdef __cplusplus
-extern "C" {
-#endif
+namespace WebCore {
-extern void WebCoreDrawTextAtPoint(const UniChar*, unsigned length, NSPoint, NSFont*, NSColor*);
-extern float WebCoreTextFloatWidth(const UniChar*, unsigned length, NSFont*);
-extern void WebCoreSetShouldUseFontSmoothing(bool);
-extern bool WebCoreShouldUseFontSmoothing();
-extern void WebCoreSetAlwaysUsesComplexTextCodePath(bool);
-extern bool WebCoreAlwaysUsesComplexTextCodePath();
-extern NSFont* WebCoreFindFont(NSString* familyName, NSFontTraitMask, int weight, int size);
+void disableSuddenTermination()
+{
+ [[NSProcessInfo processInfo] disableSuddenTermination];
+}
-#ifdef __cplusplus
+void enableSuddenTermination()
+{
+ [[NSProcessInfo processInfo] enableSuddenTermination];
}
+
+} // namespace WebCore
+
#endif
diff --git a/WebCore/platform/mac/WebCoreSystemInterface.h b/WebCore/platform/mac/WebCoreSystemInterface.h
index 3feed69..cbe4aea 100644
--- a/WebCore/platform/mac/WebCoreSystemInterface.h
+++ b/WebCore/platform/mac/WebCoreSystemInterface.h
@@ -117,8 +117,11 @@ extern void (*wkGetWheelEventDeltas)(NSEvent*, float* deltaX, float* deltaY, BOO
extern BOOL (*wkHitTestMediaUIPart)(int part, int themeStyle, CGRect bounds, CGPoint point);
extern void (*wkMeasureMediaUIPart)(int part, int themeStyle, CGRect *bounds, CGSize *naturalSize);
extern void (*wkPopupMenu)(NSMenu*, NSPoint location, float width, NSView*, int selectedItem, NSFont*);
+extern unsigned (*wkQTIncludeOnlyModernMediaFileTypes)(void);
extern int (*wkQTMovieDataRate)(QTMovie*);
extern float (*wkQTMovieMaxTimeLoaded)(QTMovie*);
+extern NSString *(*wkQTMovieMaxTimeLoadedChangeNotification)(void);
+extern float (*wkQTMovieMaxTimeSeekable)(QTMovie*);
extern void (*wkQTMovieViewSetDrawSynchronously)(QTMovieView*, BOOL);
extern void (*wkSetCGFontRenderingMode)(CGContextRef, NSFont*);
extern void (*wkSetDragImage)(NSImage*, NSPoint offset);
@@ -130,6 +133,7 @@ extern void (*wkSetUpFontCache)();
extern void (*wkSignalCFReadStreamEnd)(CFReadStreamRef stream);
extern void (*wkSignalCFReadStreamError)(CFReadStreamRef stream, CFStreamError *error);
extern void (*wkSignalCFReadStreamHasBytes)(CFReadStreamRef stream);
+extern unsigned (*wkInitializeMaximumHTTPConnectionCountPerHost)(unsigned preferredConnectionCount);
#ifndef BUILDING_ON_TIGER
extern void (*wkGetGlyphsForCharacters)(CGFontRef, const UniChar[], CGGlyph[], size_t);
diff --git a/WebCore/platform/mac/WebCoreSystemInterface.mm b/WebCore/platform/mac/WebCoreSystemInterface.mm
index edd9d50..05d1da6 100644
--- a/WebCore/platform/mac/WebCoreSystemInterface.mm
+++ b/WebCore/platform/mac/WebCoreSystemInterface.mm
@@ -51,8 +51,11 @@ NSDate *(*wkGetNSURLResponseLastModifiedDate)(NSURLResponse *response);
BOOL (*wkGetNSURLResponseMustRevalidate)(NSURLResponse *response);
void (*wkGetWheelEventDeltas)(NSEvent*, float* deltaX, float* deltaY, BOOL* continuous);
void (*wkPopupMenu)(NSMenu*, NSPoint location, float width, NSView*, int selectedItem, NSFont*);
+unsigned (*wkQTIncludeOnlyModernMediaFileTypes)(void);
int (*wkQTMovieDataRate)(QTMovie*);
float (*wkQTMovieMaxTimeLoaded)(QTMovie*);
+NSString *(*wkQTMovieMaxTimeLoadedChangeNotification)(void);
+float (*wkQTMovieMaxTimeSeekable)(QTMovie*);
void (*wkQTMovieViewSetDrawSynchronously)(QTMovieView*, BOOL);
void (*wkSetCGFontRenderingMode)(CGContextRef, NSFont*);
void (*wkSetDragImage)(NSImage*, NSPoint offset);
@@ -74,6 +77,7 @@ CFReadStreamRef (*wkCreateCustomCFReadStream)(void *(*formCreate)(CFReadStreamRe
void (*wkSetNSURLConnectionDefersCallbacks)(NSURLConnection *, BOOL);
void (*wkSetNSURLRequestShouldContentSniff)(NSMutableURLRequest *, BOOL);
id (*wkCreateNSURLConnectionDelegateProxy)(void);
+unsigned (*wkInitializeMaximumHTTPConnectionCountPerHost)(unsigned preferredConnectionCount);
#ifndef BUILDING_ON_TIGER
void (*wkGetGlyphsForCharacters)(CGFontRef, const UniChar[], CGGlyph[], size_t);
diff --git a/WebCore/platform/mac/WebCoreTextRenderer.mm b/WebCore/platform/mac/WebCoreTextRenderer.mm
deleted file mode 100644
index ab053ef..0000000
--- a/WebCore/platform/mac/WebCoreTextRenderer.mm
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import "config.h"
-#import "WebCoreTextRenderer.h"
-
-#import "Font.h"
-#import "SimpleFontData.h"
-#import "GraphicsContext.h"
-#import "IntPoint.h"
-#import "WebFontCache.h"
-#import <AppKit/AppKit.h>
-
-using namespace WebCore;
-
-void WebCoreDrawTextAtPoint(const UniChar* buffer, unsigned length, NSPoint point, NSFont* font, NSColor* textColor)
-{
- NSGraphicsContext *nsContext = [NSGraphicsContext currentContext];
- CGContextRef cgContext = (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.0f, -1.0f);
-
- FontPlatformData f(font);
- Font renderer(f, ![[NSGraphicsContext currentContext] isDrawingToScreen]);
- TextRun run(buffer, length);
- run.disableRoundingHacks();
- CGFloat red, green, blue, alpha;
- [[textColor colorUsingColorSpaceName:NSDeviceRGBColorSpace] getRed:&red green:&green blue:&blue alpha:&alpha];
- graphicsContext.setFillColor(makeRGBA((int)(red * 255), (int)(green * 255), (int)(blue * 255), (int)(alpha * 255)));
- renderer.drawText(&graphicsContext, run, FloatPoint(point.x, (flipped ? point.y : (-1.0f * point.y))));
- if (!flipped)
- CGContextScaleCTM(cgContext, 1.0f, -1.0f);
-}
-
-float WebCoreTextFloatWidth(const UniChar* buffer, unsigned length , NSFont* font)
-{
- FontPlatformData f(font);
- Font renderer(f, ![[NSGraphicsContext currentContext] isDrawingToScreen]);
- TextRun run(buffer, length);
- run.disableRoundingHacks();
- return renderer.floatWidth(run);
-}
-
-static bool gShouldUseFontSmoothing = true;
-
-void WebCoreSetShouldUseFontSmoothing(bool smooth)
-{
- gShouldUseFontSmoothing = smooth;
-}
-
-bool WebCoreShouldUseFontSmoothing()
-{
- return gShouldUseFontSmoothing;
-}
-
-void WebCoreSetAlwaysUsesComplexTextCodePath(bool complex)
-{
- Font::setCodePath(complex ? Font::Complex : Font::Auto);
-}
-
-bool WebCoreAlwaysUsesComplexTextCodePath()
-{
- return Font::codePath() == Font::Complex;
-}
-
-NSFont* WebCoreFindFont(NSString* familyName, NSFontTraitMask traits, int weight, int size)
-{
- return [WebFontCache fontWithFamily:familyName traits:traits weight:weight size:size];
-}
diff --git a/WebCore/platform/mac/WebFontCache.h b/WebCore/platform/mac/WebFontCache.h
index 8d3e4dd..380f271 100644
--- a/WebCore/platform/mac/WebFontCache.h
+++ b/WebCore/platform/mac/WebFontCache.h
@@ -32,4 +32,6 @@
+ (NSFont *)fontWithFamily:(NSString *)desiredFamily traits:(NSFontTraitMask)desiredTraits weight:(int)desiredWeight size:(float)size;
+ (void)getTraits:(Vector<unsigned>&)traitsMasks inFamily:(NSString *)desiredFamily;
+// This older version of the interface is relied upon by some clients. WebCore doesn't use it.
++ (NSFont *)fontWithFamily:(NSString *)desiredFamily traits:(NSFontTraitMask)desiredTraits size:(float)size;
@end
diff --git a/WebCore/platform/mac/WebFontCache.mm b/WebCore/platform/mac/WebFontCache.mm
index ac70f06..22e6291 100644
--- a/WebCore/platform/mac/WebFontCache.mm
+++ b/WebCore/platform/mac/WebFontCache.mm
@@ -34,6 +34,7 @@
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
#import <math.h>
+#import <wtf/UnusedParam.h>
using namespace WebCore;
@@ -106,8 +107,13 @@ static BOOL betterChoice(NSFontTraitMask desiredTraits, int desiredWeight,
// Workaround for <rdar://problem/5781372>.
static inline void fixUpWeight(NSInteger& weight, NSString *fontName)
{
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ UNUSED_PARAM(weight);
+ UNUSED_PARAM(fontName);
+#else
if (weight == 3 && [fontName rangeOfString:@"ultralight" options:NSCaseInsensitiveSearch | NSBackwardsSearch | NSLiteralSearch].location != NSNotFound)
weight = 2;
+#endif
}
static inline FontTraitsMask toTraitsMask(NSFontTraitMask appKitTraits, NSInteger appKitWeight)
@@ -300,4 +306,10 @@ static inline FontTraitsMask toTraitsMask(NSFontTraitMask appKitTraits, NSIntege
return [self internalFontWithFamily:desiredFamily traits:desiredTraits weight:desiredWeight size:size];
}
++ (NSFont *)fontWithFamily:(NSString *)desiredFamily traits:(NSFontTraitMask)desiredTraits size:(float)size
+{
+ int desiredWeight = (desiredTraits & NSBoldFontMask) ? 9 : 5;
+ return [self fontWithFamily:desiredFamily traits:desiredTraits weight:desiredWeight size:size];
+}
+
@end
diff --git a/WebCore/platform/mac/WheelEventMac.mm b/WebCore/platform/mac/WheelEventMac.mm
index 5821139..f380e3e 100644
--- a/WebCore/platform/mac/WheelEventMac.mm
+++ b/WebCore/platform/mac/WheelEventMac.mm
@@ -32,8 +32,8 @@
namespace WebCore {
-PlatformWheelEvent::PlatformWheelEvent(NSEvent* event)
- : m_position(pointForEvent(event))
+PlatformWheelEvent::PlatformWheelEvent(NSEvent* event, NSView *windowView)
+ : m_position(pointForEvent(event, windowView))
, m_globalPosition(globalPointForEvent(event))
, m_granularity(ScrollByPixelWheelEvent)
, m_isAccepted(false)
diff --git a/WebCore/platform/mac/WidgetMac.mm b/WebCore/platform/mac/WidgetMac.mm
index ecd4f30..1aaf4b2 100644
--- a/WebCore/platform/mac/WidgetMac.mm
+++ b/WebCore/platform/mac/WidgetMac.mm
@@ -285,7 +285,9 @@ void Widget::afterMouseDown(NSView *view, Widget* widget)
IntPoint Widget::convertFromContainingWindow(const IntPoint& point) const
{
- if (!platformWidget() && parent()) {
+ if (!platformWidget()) {
+ if (!parent())
+ return point;
IntPoint result = parent()->convertFromContainingWindow(point);
result.move(parent()->scrollX() - x(), parent()->scrollY() - y());
return result;
@@ -300,7 +302,9 @@ IntPoint Widget::convertFromContainingWindow(const IntPoint& point) const
IntRect Widget::convertFromContainingWindow(const IntRect& rect) const
{
- if (!platformWidget() && parent()) {
+ if (!platformWidget()) {
+ if (!parent())
+ return rect;
IntRect result = parent()->convertFromContainingWindow(rect);
result.move(parent()->scrollX() - x(), parent()->scrollY() - y());
return result;
diff --git a/WebCore/platform/network/HTTPParsers.cpp b/WebCore/platform/network/HTTPParsers.cpp
index f36e9fb..e57401e 100644
--- a/WebCore/platform/network/HTTPParsers.cpp
+++ b/WebCore/platform/network/HTTPParsers.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/
*
* Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,11 @@
#include "config.h"
#include "HTTPParsers.h"
+#include "CString.h"
#include "PlatformString.h"
+#include <wtf/DateMath.h>
+
+using namespace WTF;
namespace WebCore {
@@ -40,12 +44,13 @@ static inline bool skipWhiteSpace(const String& str, int& pos, bool fromHttpEqui
{
int len = str.length();
- if (fromHttpEquivMeta)
+ if (fromHttpEquivMeta) {
while (pos != len && str[pos] <= ' ')
++pos;
- else
+ } else {
while (pos != len && (str[pos] == '\t' || str[pos] == ' '))
++pos;
+ }
return pos != len;
}
@@ -102,6 +107,11 @@ bool parseHTTPRefresh(const String& refresh, bool fromHttpEquivMeta, double& del
}
}
+double parseDate(const String& value)
+{
+ return parseDateFromNullTerminatedCharacters(value.utf8().data());
+}
+
String filenameFromHTTPContentDisposition(const String& value)
{
Vector<String> keyValuePairs;
@@ -135,14 +145,33 @@ String extractMIMETypeFromMediaType(const String& mediaType)
Vector<UChar, 64> mimeType;
unsigned length = mediaType.length();
mimeType.reserveCapacity(length);
- for (unsigned offset = 0; offset < length; offset++) {
- UChar c = mediaType[offset];
+ for (unsigned i = 0; i < length; i++) {
+ UChar c = mediaType[i];
+
if (c == ';')
break;
- else if (isSpaceOrNewline(c)) // FIXME: This seems wrong, " " is an invalid MIME type character according to RFC 2045. bug 8644
+
+ // While RFC 2616 does not allow it, other browsers allow multiple values in the HTTP media
+ // type header field, Content-Type. In such cases, the media type string passed here may contain
+ // the multiple values separated by commas. For now, this code ignores text after the first comma,
+ // which prevents it from simply failing to parse such types altogether. Later for better
+ // compatibility we could consider using the first or last valid MIME type instead.
+ // See https://bugs.webkit.org/show_bug.cgi?id=25352 for more discussion.
+ if (c == ',')
+ break;
+
+ // FIXME: The following is not correct. RFC 2616 allows linear white space before and
+ // after the MIME type, but not within the MIME type itself. And linear white space
+ // includes only a few specific ASCII characters; a small subset of isSpaceOrNewline.
+ // See https://bugs.webkit.org/show_bug.cgi?id=8644 for a bug tracking part of this.
+ if (isSpaceOrNewline(c))
continue;
+
mimeType.append(c);
}
+
+ if (mimeType.size() == length)
+ return mediaType;
return String(mimeType.data(), mimeType.size());
}
diff --git a/WebCore/platform/network/HTTPParsers.h b/WebCore/platform/network/HTTPParsers.h
index 28a9ce9..0648aee 100644
--- a/WebCore/platform/network/HTTPParsers.h
+++ b/WebCore/platform/network/HTTPParsers.h
@@ -34,6 +34,7 @@ namespace WebCore {
class String;
bool parseHTTPRefresh(const String& refresh, bool fromHttpEquivMeta, double& delay, String& url);
+ double parseDate(const String&);
String filenameFromHTTPContentDisposition(const String&);
String extractMIMETypeFromMediaType(const String&);
String extractCharsetFromMediaType(const String&);
diff --git a/WebCore/platform/network/ResourceHandle.cpp b/WebCore/platform/network/ResourceHandle.cpp
index 149411e..5a40b21 100644
--- a/WebCore/platform/network/ResourceHandle.cpp
+++ b/WebCore/platform/network/ResourceHandle.cpp
@@ -34,6 +34,8 @@
namespace WebCore {
+static bool shouldForceContentSniffing;
+
static bool portAllowed(const ResourceRequest&);
ResourceHandle::ResourceHandle(const ResourceRequest& request, ResourceHandleClient* client, bool defersLoading,
@@ -45,6 +47,9 @@ ResourceHandle::ResourceHandle(const ResourceRequest& request, ResourceHandleCli
PassRefPtr<ResourceHandle> ResourceHandle::create(const ResourceRequest& request, ResourceHandleClient* client,
Frame* frame, bool defersLoading, bool shouldContentSniff, bool mightDownloadFromHandle)
{
+ if (shouldContentSniff)
+ shouldContentSniff = shouldContentSniffURL(request.url());
+
RefPtr<ResourceHandle> newHandle(adoptRef(new ResourceHandle(request, client, defersLoading, shouldContentSniff, mightDownloadFromHandle)));
if (!request.url().isValid()) {
@@ -178,6 +183,7 @@ static bool portAllowed(const ResourceRequest& request)
993, // IMAP+SSL
995, // POP3+SSL
2049, // NFS
+ 3659, // apple-sasl / PasswordServer [Apple addition]
4045, // lockd
6000, // X11
};
@@ -199,4 +205,24 @@ static bool portAllowed(const ResourceRequest& request)
return false;
}
+bool ResourceHandle::shouldContentSniff() const
+{
+ return d->m_shouldContentSniff;
+}
+
+bool ResourceHandle::shouldContentSniffURL(const KURL& url)
+{
+#if PLATFORM(MAC)
+ if (shouldForceContentSniffing)
+ return true;
+#endif
+ // We shouldn't content sniff file URLs as their MIME type should be established via their extension.
+ return !url.protocolIs("file");
+}
+
+void ResourceHandle::forceContentSniffing()
+{
+ shouldForceContentSniffing = true;
+}
+
} // namespace WebCore
diff --git a/WebCore/platform/network/ResourceHandle.h b/WebCore/platform/network/ResourceHandle.h
index e3038ca..3b27b00 100644
--- a/WebCore/platform/network/ResourceHandle.h
+++ b/WebCore/platform/network/ResourceHandle.h
@@ -28,6 +28,7 @@
#include "AuthenticationChallenge.h"
#include "HTTPHeaderMap.h"
+#include "ThreadableLoader.h"
#include <wtf/OwnPtr.h>
#if USE(SOUP)
@@ -103,7 +104,7 @@ public:
// FIXME: should not need the Frame
static PassRefPtr<ResourceHandle> create(const ResourceRequest&, ResourceHandleClient*, Frame*, bool defersLoading, bool shouldContentSniff, bool mightDownloadFromHandle = false);
- static void loadResourceSynchronously(const ResourceRequest&, ResourceError&, ResourceResponse&, Vector<char>& data, Frame* frame);
+ static void loadResourceSynchronously(const ResourceRequest&, StoredCredentials, ResourceError&, ResourceResponse&, Vector<char>& data, Frame* frame);
static bool willLoadFromCache(ResourceRequest&);
#if PLATFORM(MAC)
static bool didSendBodyDataDelegateExists();
@@ -112,6 +113,7 @@ public:
~ResourceHandle();
#if PLATFORM(MAC) || USE(CFNETWORK)
+ void willSendRequest(ResourceRequest&, const ResourceResponse& redirectResponse);
bool shouldUseCredentialStorage();
#endif
#if PLATFORM(MAC) || USE(CFNETWORK) || USE(CURL)
@@ -148,6 +150,11 @@ public:
PassRefPtr<SharedBuffer> bufferedData();
static bool supportsBufferedData();
+ bool shouldContentSniff() const;
+ static bool shouldContentSniffURL(const KURL&);
+
+ static void forceContentSniffing();
+
#if USE(WININET)
void setHasReceivedResponse(bool = true);
bool hasReceivedResponse() const;
diff --git a/WebCore/platform/network/ResourceHandleClient.h b/WebCore/platform/network/ResourceHandleClient.h
index 54c27d2..c99be54 100644
--- a/WebCore/platform/network/ResourceHandleClient.h
+++ b/WebCore/platform/network/ResourceHandleClient.h
@@ -79,8 +79,6 @@ namespace WebCore {
virtual bool shouldUseCredentialStorage(ResourceHandle*) { return false; }
virtual void didReceiveAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge&) { }
virtual void didCancelAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge&) { }
- virtual void receivedCredential(ResourceHandle*, const AuthenticationChallenge&, const Credential&) { }
- virtual void receivedRequestToContinueWithoutCredential(ResourceHandle*, const AuthenticationChallenge&) { }
virtual void receivedCancellation(ResourceHandle*, const AuthenticationChallenge&) { }
#if PLATFORM(MAC)
diff --git a/WebCore/platform/network/ResourceHandleInternal.h b/WebCore/platform/network/ResourceHandleInternal.h
index c592a1a..b10c658 100644
--- a/WebCore/platform/network/ResourceHandleInternal.h
+++ b/WebCore/platform/network/ResourceHandleInternal.h
@@ -133,6 +133,7 @@ namespace WebCore {
#endif
#if PLATFORM(MAC)
, m_startWhenScheduled(false)
+ , m_needsSiteSpecificQuirks(false)
, m_currentMacChallenge(nil)
#elif USE(CFNETWORK)
, m_currentCFChallenge(0)
@@ -142,6 +143,10 @@ namespace WebCore {
#endif
, m_failureTimer(loader, &ResourceHandle::fireFailure)
{
+ const KURL& url = m_request.url();
+ m_user = url.user();
+ m_pass = url.pass();
+ m_request.removeCredentials();
}
~ResourceHandleInternal();
@@ -150,6 +155,10 @@ namespace WebCore {
ResourceHandleClient* m_client;
ResourceRequest m_request;
+
+ // Suggested credentials for the current redirection step.
+ String m_user;
+ String m_pass;
int status;
@@ -163,6 +172,7 @@ namespace WebCore {
RetainPtr<WebCoreResourceHandleAsDelegate> m_delegate;
RetainPtr<id> m_proxy;
bool m_startWhenScheduled;
+ bool m_needsSiteSpecificQuirks;
#endif
#if USE(WININET)
HANDLE m_fileHandle;
@@ -210,6 +220,8 @@ namespace WebCore {
#endif
QWebFrame* m_frame;
#endif
+
+ // FIXME: The platform challenge is almost identical to the one stored in m_currentWebChallenge, but it has a different sender. We only need to store a sender reference here.
#if PLATFORM(MAC)
NSURLAuthenticationChallenge *m_currentMacChallenge;
#endif
diff --git a/WebCore/platform/network/ResourceRequestBase.cpp b/WebCore/platform/network/ResourceRequestBase.cpp
index fd27718..bfa3dc6 100644
--- a/WebCore/platform/network/ResourceRequestBase.cpp
+++ b/WebCore/platform/network/ResourceRequestBase.cpp
@@ -42,7 +42,7 @@ auto_ptr<ResourceRequest> ResourceRequestBase::adopt(auto_ptr<CrossThreadResourc
request->setURL(data->m_url);
request->setCachePolicy(data->m_cachePolicy);
request->setTimeoutInterval(data->m_timeoutInterval);
- request->setMainDocumentURL(data->m_mainDocumentURL);
+ request->setFirstPartyForCookies(data->m_firstPartyForCookies);
request->setHTTPMethod(data->m_httpMethod);
request->updateResourceRequest();
@@ -72,7 +72,7 @@ auto_ptr<CrossThreadResourceRequestData> ResourceRequestBase::copyData() const
data->m_url = url().copy();
data->m_cachePolicy = cachePolicy();
data->m_timeoutInterval = timeoutInterval();
- data->m_mainDocumentURL = mainDocumentURL().copy();
+ data->m_firstPartyForCookies = firstPartyForCookies().copy();
data->m_httpMethod = httpMethod().copy();
data->m_httpHeaders.adopt(httpHeaderFields().copyData());
@@ -117,6 +117,16 @@ void ResourceRequestBase::setURL(const KURL& url)
m_platformRequestUpdated = false;
}
+void ResourceRequestBase::removeCredentials()
+{
+ updateResourceRequest();
+
+ m_url.setUser(String());
+ m_url.setPass(String());
+
+ m_platformRequestUpdated = false;
+}
+
ResourceRequestCachePolicy ResourceRequestBase::cachePolicy() const
{
updateResourceRequest();
@@ -151,18 +161,18 @@ void ResourceRequestBase::setTimeoutInterval(double timeoutInterval)
m_platformRequestUpdated = false;
}
-const KURL& ResourceRequestBase::mainDocumentURL() const
+const KURL& ResourceRequestBase::firstPartyForCookies() const
{
updateResourceRequest();
- return m_mainDocumentURL;
+ return m_firstPartyForCookies;
}
-void ResourceRequestBase::setMainDocumentURL(const KURL& mainDocumentURL)
+void ResourceRequestBase::setFirstPartyForCookies(const KURL& firstPartyForCookies)
{
updateResourceRequest();
- m_mainDocumentURL = mainDocumentURL;
+ m_firstPartyForCookies = firstPartyForCookies;
m_platformRequestUpdated = false;
}
@@ -284,7 +294,7 @@ bool equalIgnoringHeaderFields(const ResourceRequestBase& a, const ResourceReque
if (a.timeoutInterval() != b.timeoutInterval())
return false;
- if (a.mainDocumentURL() != b.mainDocumentURL())
+ if (a.firstPartyForCookies() != b.firstPartyForCookies())
return false;
if (a.httpMethod() != b.httpMethod())
@@ -345,4 +355,13 @@ void ResourceRequestBase::updateResourceRequest() const
m_resourceRequestUpdated = true;
}
+#if !PLATFORM(MAC) && !USE(CFNETWORK)
+unsigned initializeMaximumHTTPConnectionCountPerHost()
+{
+ // This is used by the loader to control the number of issued parallel load requests.
+ // Four seems to be a common default in HTTP frameworks.
+ return 4;
+}
+#endif
+
}
diff --git a/WebCore/platform/network/ResourceRequestBase.h b/WebCore/platform/network/ResourceRequestBase.h
index 4fd57e1..2d87d6e 100644
--- a/WebCore/platform/network/ResourceRequestBase.h
+++ b/WebCore/platform/network/ResourceRequestBase.h
@@ -63,14 +63,16 @@ namespace WebCore {
const KURL& url() const;
void setURL(const KURL& url);
+ void removeCredentials();
+
ResourceRequestCachePolicy cachePolicy() const;
void setCachePolicy(ResourceRequestCachePolicy cachePolicy);
double timeoutInterval() const;
void setTimeoutInterval(double timeoutInterval);
- const KURL& mainDocumentURL() const;
- void setMainDocumentURL(const KURL& mainDocumentURL);
+ const KURL& firstPartyForCookies() const;
+ void setFirstPartyForCookies(const KURL& firstPartyForCookies);
const String& httpMethod() const;
void setHTTPMethod(const String& httpMethod);
@@ -141,7 +143,7 @@ namespace WebCore {
ResourceRequestCachePolicy m_cachePolicy;
double m_timeoutInterval;
- KURL m_mainDocumentURL;
+ KURL m_firstPartyForCookies;
String m_httpMethod;
HTTPHeaderMap m_httpHeaderFields;
Vector<String> m_responseContentDispositionEncodingFallbackArray;
@@ -165,7 +167,7 @@ namespace WebCore {
ResourceRequestCachePolicy m_cachePolicy;
double m_timeoutInterval;
- KURL m_mainDocumentURL;
+ KURL m_firstPartyForCookies;
String m_httpMethod;
OwnPtr<CrossThreadHTTPHeaderMapData> m_httpHeaders;
@@ -173,6 +175,8 @@ namespace WebCore {
RefPtr<FormData> m_httpBody;
bool m_allowHTTPCookies;
};
+
+ unsigned initializeMaximumHTTPConnectionCountPerHost();
} // namespace WebCore
diff --git a/WebCore/platform/network/ResourceResponseBase.cpp b/WebCore/platform/network/ResourceResponseBase.cpp
index 60c0097..965759e 100644
--- a/WebCore/platform/network/ResourceResponseBase.cpp
+++ b/WebCore/platform/network/ResourceResponseBase.cpp
@@ -27,14 +27,45 @@
#include "config.h"
#include "ResourceResponseBase.h"
+#include "HTTPParsers.h"
#include "ResourceResponse.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/MathExtras.h>
+#include <wtf/StdLibExtras.h>
using namespace std;
namespace WebCore {
static void parseCacheHeader(const String& header, Vector<pair<String, String> >& result);
-static void parseCacheControlDirectiveValues(const String& directives, Vector<String>& result);
+
+ResourceResponseBase::ResourceResponseBase()
+ : m_expectedContentLength(0)
+ , m_httpStatusCode(0)
+ , m_isNull(true)
+ , m_haveParsedCacheControlHeader(false)
+ , m_haveParsedAgeHeader(false)
+ , m_haveParsedDateHeader(false)
+ , m_haveParsedExpiresHeader(false)
+ , m_haveParsedLastModifiedHeader(false)
+{
+}
+
+ResourceResponseBase::ResourceResponseBase(const KURL& url, const String& mimeType, long long expectedLength, const String& textEncodingName, const String& filename)
+ : m_url(url)
+ , m_mimeType(mimeType)
+ , m_expectedContentLength(expectedLength)
+ , m_textEncodingName(textEncodingName)
+ , m_suggestedFilename(filename)
+ , m_httpStatusCode(0)
+ , m_isNull(false)
+ , m_haveParsedCacheControlHeader(false)
+ , m_haveParsedAgeHeader(false)
+ , m_haveParsedDateHeader(false)
+ , m_haveParsedExpiresHeader(false)
+ , m_haveParsedLastModifiedHeader(false)
+{
+}
auto_ptr<ResourceResponse> ResourceResponseBase::adopt(auto_ptr<CrossThreadResourceResponseData> data)
{
@@ -50,12 +81,8 @@ auto_ptr<ResourceResponse> ResourceResponseBase::adopt(auto_ptr<CrossThreadResou
response->lazyInit();
response->m_httpHeaderFields.adopt(std::auto_ptr<CrossThreadHTTPHeaderMapData>(data->m_httpHeaders.release()));
-
- response->setExpirationDate(data->m_expirationDate);
response->setLastModifiedDate(data->m_lastModifiedDate);
- response->m_haveParsedCacheControl = data->m_haveParsedCacheControl;
- response->m_cacheControlContainsMustRevalidate = data->m_cacheControlContainsMustRevalidate;
- response->m_cacheControlContainsNoCache = data->m_cacheControlContainsNoCache;
+
return response;
}
@@ -70,11 +97,7 @@ auto_ptr<CrossThreadResourceResponseData> ResourceResponseBase::copyData() const
data->m_httpStatusCode = httpStatusCode();
data->m_httpStatusText = httpStatusText().copy();
data->m_httpHeaders.adopt(httpHeaderFields().copyData());
- data->m_expirationDate = expirationDate();
data->m_lastModifiedDate = lastModifiedDate();
- data->m_haveParsedCacheControl = m_haveParsedCacheControl;
- data->m_cacheControlContainsMustRevalidate = m_cacheControlContainsMustRevalidate;
- data->m_cacheControlContainsNoCache = m_cacheControlContainsNoCache;
return data;
}
@@ -201,9 +224,24 @@ String ResourceResponseBase::httpHeaderField(const AtomicString& name) const
void ResourceResponseBase::setHTTPHeaderField(const AtomicString& name, const String& value)
{
lazyInit();
+
+ DEFINE_STATIC_LOCAL(const AtomicString, ageHeader, ("age"));
+ DEFINE_STATIC_LOCAL(const AtomicString, cacheControlHeader, ("cache-control"));
+ DEFINE_STATIC_LOCAL(const AtomicString, dateHeader, ("date"));
+ DEFINE_STATIC_LOCAL(const AtomicString, expiresHeader, ("expires"));
+ DEFINE_STATIC_LOCAL(const AtomicString, lastModifiedHeader, ("last-modified"));
+ DEFINE_STATIC_LOCAL(const AtomicString, pragmaHeader, ("pragma"));
+ if (equalIgnoringCase(name, ageHeader))
+ m_haveParsedAgeHeader = false;
+ else if (equalIgnoringCase(name, cacheControlHeader) || equalIgnoringCase(name, pragmaHeader))
+ m_haveParsedCacheControlHeader = false;
+ else if (equalIgnoringCase(name, dateHeader))
+ m_haveParsedDateHeader = false;
+ else if (equalIgnoringCase(name, expiresHeader))
+ m_haveParsedExpiresHeader = false;
+ else if (equalIgnoringCase(name, lastModifiedHeader))
+ m_haveParsedLastModifiedHeader = false;
- if (equalIgnoringCase(name, "cache-control"))
- m_haveParsedCacheControl = false;
m_httpHeaderFields.set(name, value);
}
@@ -216,66 +254,156 @@ const HTTPHeaderMap& ResourceResponseBase::httpHeaderFields() const
void ResourceResponseBase::parseCacheControlDirectives() const
{
- ASSERT(!m_haveParsedCacheControl);
+ ASSERT(!m_haveParsedCacheControlHeader);
lazyInit();
- m_haveParsedCacheControl = true;
+ m_haveParsedCacheControlHeader = true;
+
m_cacheControlContainsMustRevalidate = false;
m_cacheControlContainsNoCache = false;
-
- String cacheControlValue = httpHeaderField("cache-control");
- if (cacheControlValue.isEmpty())
- return;
-
- // FIXME: It would probably be much more efficient to parse this without creating all these data structures.
-
- Vector<pair<String, String> > directives;
- parseCacheHeader(cacheControlValue, directives);
-
- size_t directivesSize = directives.size();
- for (size_t i = 0; i < directivesSize; ++i) {
- Vector<String> directiveValues;
- if ((equalIgnoringCase(directives[i].first, "private") || equalIgnoringCase(directives[i].first, "no-cache")) && !directives[i].second.isEmpty())
- parseCacheControlDirectiveValues(directives[i].second, directiveValues);
- else
- directiveValues.append(directives[i].first);
- for (size_t i = 0; i < directiveValues.size(); ++i) {
- if (equalIgnoringCase(directiveValues[i], "no-cache"))
+ m_cacheControlMaxAge = numeric_limits<double>::quiet_NaN();
+
+ DEFINE_STATIC_LOCAL(const AtomicString, cacheControlString, ("cache-control"));
+ DEFINE_STATIC_LOCAL(const AtomicString, noCacheDirective, ("no-cache"));
+ DEFINE_STATIC_LOCAL(const AtomicString, mustRevalidateDirective, ("must-revalidate"));
+ DEFINE_STATIC_LOCAL(const AtomicString, maxAgeDirective, ("max-age"));
+
+ String cacheControlValue = m_httpHeaderFields.get(cacheControlString);
+ if (!cacheControlValue.isEmpty()) {
+ Vector<pair<String, String> > directives;
+ parseCacheHeader(cacheControlValue, directives);
+
+ size_t directivesSize = directives.size();
+ for (size_t i = 0; i < directivesSize; ++i) {
+ // RFC2616 14.9.1: A no-cache directive with a value is only meaningful for proxy caches.
+ // It should be ignored by a browser level cache.
+ if (equalIgnoringCase(directives[i].first, noCacheDirective) && directives[i].second.isEmpty())
m_cacheControlContainsNoCache = true;
- else if (equalIgnoringCase(directiveValues[i], "must-revalidate"))
+ else if (equalIgnoringCase(directives[i].first, mustRevalidateDirective))
m_cacheControlContainsMustRevalidate = true;
+ else if (equalIgnoringCase(directives[i].first, maxAgeDirective)) {
+ bool ok;
+ double maxAge = directives[i].second.toDouble(&ok);
+ if (ok)
+ m_cacheControlMaxAge = maxAge;
+ }
}
}
+
+ if (!m_cacheControlContainsNoCache) {
+ // Handle Pragma: no-cache
+ // This is deprecated and equivalent to Cache-control: no-cache
+ // Don't bother tokenizing the value, it is not important
+ DEFINE_STATIC_LOCAL(const AtomicString, pragmaHeader, ("pragma"));
+ String pragmaValue = m_httpHeaderFields.get(pragmaHeader);
+ m_cacheControlContainsNoCache = pragmaValue.lower().contains(noCacheDirective);
+ }
+}
+
+bool ResourceResponseBase::cacheControlContainsNoCache() const
+{
+ if (!m_haveParsedCacheControlHeader)
+ parseCacheControlDirectives();
+ return m_cacheControlContainsNoCache;
}
-bool ResourceResponseBase::isAttachment() const
+bool ResourceResponseBase::cacheControlContainsMustRevalidate() const
{
- lazyInit();
+ if (!m_haveParsedCacheControlHeader)
+ parseCacheControlDirectives();
+ return m_cacheControlContainsMustRevalidate;
+}
- String value = m_httpHeaderFields.get("Content-Disposition");
- int loc = value.find(';');
- if (loc != -1)
- value = value.left(loc);
- value = value.stripWhiteSpace();
- return equalIgnoringCase(value, "attachment");
+double ResourceResponseBase::cacheControlMaxAge() const
+{
+ if (!m_haveParsedCacheControlHeader)
+ parseCacheControlDirectives();
+ return m_cacheControlMaxAge;
}
-void ResourceResponseBase::setExpirationDate(time_t expirationDate)
+static double parseDateValueInHeader(const HTTPHeaderMap& headers, const AtomicString& headerName)
+{
+ String headerValue = headers.get(headerName);
+ if (headerValue.isEmpty())
+ return std::numeric_limits<double>::quiet_NaN();
+ // This handles all date formats required by RFC2616:
+ // Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
+ // Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+ // Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
+ double dateInMilliseconds = parseDate(headerValue);
+ if (!isfinite(dateInMilliseconds))
+ return std::numeric_limits<double>::quiet_NaN();
+ return dateInMilliseconds / 1000;
+}
+
+double ResourceResponseBase::date() const
{
lazyInit();
- m_expirationDate = expirationDate;
+ if (!m_haveParsedDateHeader) {
+ DEFINE_STATIC_LOCAL(const AtomicString, headerName, ("date"));
+ m_date = parseDateValueInHeader(m_httpHeaderFields, headerName);
+ m_haveParsedDateHeader = true;
+ }
+ return m_date;
+}
+
+double ResourceResponseBase::age() const
+{
+ lazyInit();
+
+ if (!m_haveParsedAgeHeader) {
+ DEFINE_STATIC_LOCAL(const AtomicString, headerName, ("age"));
+ String headerValue = m_httpHeaderFields.get(headerName);
+ bool ok;
+ m_age = headerValue.toDouble(&ok);
+ if (!ok)
+ m_age = std::numeric_limits<double>::quiet_NaN();
+ m_haveParsedAgeHeader = true;
+ }
+ return m_age;
}
-time_t ResourceResponseBase::expirationDate() const
+double ResourceResponseBase::expires() const
{
lazyInit();
- return m_expirationDate;
+ if (!m_haveParsedExpiresHeader) {
+ DEFINE_STATIC_LOCAL(const AtomicString, headerName, ("expires"));
+ m_expires = parseDateValueInHeader(m_httpHeaderFields, headerName);
+ m_haveParsedExpiresHeader = true;
+ }
+ return m_expires;
+}
+
+double ResourceResponseBase::lastModified() const
+{
+ lazyInit();
+
+ if (!m_haveParsedLastModifiedHeader) {
+ DEFINE_STATIC_LOCAL(const AtomicString, headerName, ("last-modified"));
+ m_lastModified = parseDateValueInHeader(m_httpHeaderFields, headerName);
+ m_haveParsedLastModifiedHeader = true;
+ }
+ return m_lastModified;
}
-void ResourceResponseBase::setLastModifiedDate(time_t lastModifiedDate)
+bool ResourceResponseBase::isAttachment() const
+{
+ lazyInit();
+
+ DEFINE_STATIC_LOCAL(const AtomicString, headerName, ("content-disposition"));
+ String value = m_httpHeaderFields.get(headerName);
+ int loc = value.find(';');
+ if (loc != -1)
+ value = value.left(loc);
+ value = value.stripWhiteSpace();
+ DEFINE_STATIC_LOCAL(const AtomicString, attachmentString, ("attachment"));
+ return equalIgnoringCase(value, attachmentString);
+}
+
+void ResourceResponseBase::setLastModifiedDate(time_t lastModifiedDate)
{
lazyInit();
@@ -314,8 +442,6 @@ bool ResourceResponseBase::compare(const ResourceResponse& a, const ResourceResp
return false;
if (a.httpHeaderFields() != b.httpHeaderFields())
return false;
- if (a.expirationDate() != b.expirationDate())
- return false;
return ResourceResponse::platformCompare(a, b);
}
@@ -414,12 +540,4 @@ static void parseCacheHeader(const String& header, Vector<pair<String, String> >
}
}
-static void parseCacheControlDirectiveValues(const String& directives, Vector<String>& result)
-{
- directives.split(',', false, result);
- unsigned max = result.size();
- for (unsigned i = 0; i < max; ++i)
- result[i] = result[i].stripWhiteSpace();
-}
-
}
diff --git a/WebCore/platform/network/ResourceResponseBase.h b/WebCore/platform/network/ResourceResponseBase.h
index ff34a26..7138908 100644
--- a/WebCore/platform/network/ResourceResponseBase.h
+++ b/WebCore/platform/network/ResourceResponseBase.h
@@ -77,25 +77,21 @@ public:
bool isMultipart() const { return mimeType() == "multipart/x-mixed-replace"; }
bool isAttachment() const;
-
- void setExpirationDate(time_t);
- time_t expirationDate() const;
-
+
+ // FIXME: These are used by PluginStream on some platforms. Calculations may differ from just returning plain Last-odified header.
+ // Leaving it for now but this should go away in favor of generic solution.
void setLastModifiedDate(time_t);
- time_t lastModifiedDate() const;
-
- bool cacheControlContainsNoCache() const
- {
- if (!m_haveParsedCacheControl)
- parseCacheControlDirectives();
- return m_cacheControlContainsNoCache;
- }
- bool cacheControlContainsMustRevalidate() const
- {
- if (!m_haveParsedCacheControl)
- parseCacheControlDirectives();
- return m_cacheControlContainsMustRevalidate;
- }
+ time_t lastModifiedDate() const;
+
+ // These functions return parsed values of the corresponding response headers.
+ // NaN means that the header was not present or had invalid value.
+ bool cacheControlContainsNoCache() const;
+ bool cacheControlContainsMustRevalidate() const;
+ double cacheControlMaxAge() const;
+ double date() const;
+ double age() const;
+ double expires() const;
+ double lastModified() const;
// The ResourceResponse subclass may "shadow" this method to provide platform-specific memory usage information
unsigned memoryUsage() const
@@ -107,29 +103,8 @@ public:
static bool compare(const ResourceResponse& a, const ResourceResponse& b);
protected:
- ResourceResponseBase()
- : m_expectedContentLength(0)
- , m_httpStatusCode(0)
- , m_expirationDate(0)
- , m_lastModifiedDate(0)
- , m_isNull(true)
- , m_haveParsedCacheControl(false)
- {
- }
-
- ResourceResponseBase(const KURL& url, const String& mimeType, long long expectedLength, const String& textEncodingName, const String& filename)
- : m_url(url)
- , m_mimeType(mimeType)
- , m_expectedContentLength(expectedLength)
- , m_textEncodingName(textEncodingName)
- , m_suggestedFilename(filename)
- , m_httpStatusCode(0)
- , m_expirationDate(0)
- , m_lastModifiedDate(0)
- , m_isNull(false)
- , m_haveParsedCacheControl(false)
- {
- }
+ ResourceResponseBase();
+ ResourceResponseBase(const KURL& url, const String& mimeType, long long expectedLength, const String& textEncodingName, const String& filename);
void lazyInit() const;
@@ -147,16 +122,27 @@ protected:
int m_httpStatusCode;
String m_httpStatusText;
HTTPHeaderMap m_httpHeaderFields;
- time_t m_expirationDate;
time_t m_lastModifiedDate;
- bool m_isNull : 1;
+ bool m_isNull : 1;
+
private:
void parseCacheControlDirectives() const;
- mutable bool m_haveParsedCacheControl : 1;
- mutable bool m_cacheControlContainsMustRevalidate : 1;
+ mutable bool m_haveParsedCacheControlHeader : 1;
+ mutable bool m_haveParsedAgeHeader : 1;
+ mutable bool m_haveParsedDateHeader : 1;
+ mutable bool m_haveParsedExpiresHeader : 1;
+ mutable bool m_haveParsedLastModifiedHeader : 1;
+
mutable bool m_cacheControlContainsNoCache : 1;
+ mutable bool m_cacheControlContainsMustRevalidate : 1;
+ mutable double m_cacheControlMaxAge;
+
+ mutable double m_age;
+ mutable double m_date;
+ mutable double m_expires;
+ mutable double m_lastModified;
};
inline bool operator==(const ResourceResponse& a, const ResourceResponse& b) { return ResourceResponseBase::compare(a, b); }
@@ -171,11 +157,7 @@ struct CrossThreadResourceResponseData {
int m_httpStatusCode;
String m_httpStatusText;
OwnPtr<CrossThreadHTTPHeaderMapData> m_httpHeaders;
- time_t m_expirationDate;
time_t m_lastModifiedDate;
- bool m_haveParsedCacheControl : 1;
- bool m_cacheControlContainsMustRevalidate : 1;
- bool m_cacheControlContainsNoCache : 1;
};
} // namespace WebCore
diff --git a/WebCore/platform/network/android/Cookie.cpp b/WebCore/platform/network/android/Cookie.cpp
index 0b7aa45..c461e83 100644
--- a/WebCore/platform/network/android/Cookie.cpp
+++ b/WebCore/platform/network/android/Cookie.cpp
@@ -34,10 +34,10 @@ namespace WebCore {
class Document;
- void setCookies(Document* , const KURL& url, const KURL& policyBaseURL, const String& value)
+ void setCookies(Document*, const KURL& url, const String& value)
{
if (JavaSharedClient::GetCookieClient())
- JavaSharedClient::GetCookieClient()->setCookies(url, policyBaseURL, value);
+ JavaSharedClient::GetCookieClient()->setCookies(url, value);
}
String cookies(const Document* , const KURL& url)
diff --git a/WebCore/platform/network/android/CookieClient.h b/WebCore/platform/network/android/CookieClient.h
index 4b6ffef..7cb28a0 100644
--- a/WebCore/platform/network/android/CookieClient.h
+++ b/WebCore/platform/network/android/CookieClient.h
@@ -37,7 +37,7 @@ namespace android {
{
public:
virtual ~CookieClient() {}
- virtual void setCookies(const KURL& url, const KURL& docURL, const String& value) = 0;
+ virtual void setCookies(const KURL& url, const String& value) = 0;
virtual String cookies(const KURL& url) = 0;
virtual bool cookiesEnabled() = 0;
};
diff --git a/WebCore/platform/network/android/ResourceHandleAndroid.cpp b/WebCore/platform/network/android/ResourceHandleAndroid.cpp
index 59084ab..7fe8ecf 100644
--- a/WebCore/platform/network/android/ResourceHandleAndroid.cpp
+++ b/WebCore/platform/network/android/ResourceHandleAndroid.cpp
@@ -143,7 +143,8 @@ private:
WTF::Vector<char>* m_data;
};
-void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request,
+void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request,
+ StoredCredentials /*storedCredentials*/,
ResourceError& error, ResourceResponse& response, WTF::Vector<char>& data,
Frame* frame)
{
diff --git a/WebCore/platform/network/cf/AuthenticationCF.cpp b/WebCore/platform/network/cf/AuthenticationCF.cpp
index bb05a39..51d60a4 100644
--- a/WebCore/platform/network/cf/AuthenticationCF.cpp
+++ b/WebCore/platform/network/cf/AuthenticationCF.cpp
@@ -37,6 +37,8 @@
namespace WebCore {
+CFMutableDictionaryRef WebCoreCredentialStorage::m_storage;
+
AuthenticationChallenge::AuthenticationChallenge(const ProtectionSpace& protectionSpace,
const Credential& proposedCredential,
unsigned previousFailureCount,
diff --git a/WebCore/platform/network/cf/AuthenticationCF.h b/WebCore/platform/network/cf/AuthenticationCF.h
index 681e71f..d3fc014 100644
--- a/WebCore/platform/network/cf/AuthenticationCF.h
+++ b/WebCore/platform/network/cf/AuthenticationCF.h
@@ -43,6 +43,25 @@ CFURLProtectionSpaceRef createCF(const ProtectionSpace&);
Credential core(CFURLCredentialRef);
ProtectionSpace core(CFURLProtectionSpaceRef);
+class WebCoreCredentialStorage {
+public:
+ static void set(CFURLProtectionSpaceRef protectionSpace, CFURLCredentialRef credential)
+ {
+ if (!m_storage)
+ m_storage = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ CFDictionarySetValue(m_storage, protectionSpace, credential);
+ }
+
+ static CFURLCredentialRef get(CFURLProtectionSpaceRef protectionSpace)
+ {
+ if (!m_storage)
+ return 0;
+ return (CFURLCredentialRef)CFDictionaryGetValue(m_storage, protectionSpace);
+ }
+
+private:
+ static CFMutableDictionaryRef m_storage;
+};
}
diff --git a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
index 2dcbbed..1d5bf9f 100644
--- a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
+++ b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
@@ -37,7 +37,7 @@
#include "Frame.h"
#include "FrameLoader.h"
#include "Logging.h"
-#include "NotImplemented.h"
+#include "MIMETypeRegistry.h"
#include "ResourceError.h"
#include "ResourceResponse.h"
@@ -53,6 +53,38 @@
namespace WebCore {
+static CFStringRef WebCoreSynchronousLoaderRunLoopMode = CFSTR("WebCoreSynchronousLoaderRunLoopMode");
+
+class WebCoreSynchronousLoader {
+public:
+ static RetainPtr<CFDataRef> load(const ResourceRequest&, StoredCredentials, ResourceResponse&, ResourceError&);
+
+private:
+ WebCoreSynchronousLoader(ResourceResponse& response, ResourceError& error)
+ : m_isDone(false)
+ , m_response(response)
+ , m_error(error)
+ {
+ }
+
+ static CFURLRequestRef willSendRequest(CFURLConnectionRef, CFURLRequestRef, CFURLResponseRef, const void* clientInfo);
+ static void didReceiveResponse(CFURLConnectionRef, CFURLResponseRef, const void* clientInfo);
+ static void didReceiveData(CFURLConnectionRef, CFDataRef, CFIndex, const void* clientInfo);
+ static void didFinishLoading(CFURLConnectionRef, const void* clientInfo);
+ static void didFail(CFURLConnectionRef, CFErrorRef, const void* clientInfo);
+ static void didReceiveChallenge(CFURLConnectionRef, CFURLAuthChallengeRef, const void* clientInfo);
+ static Boolean shouldUseCredentialStorage(CFURLConnectionRef, const void* clientInfo);
+
+ bool m_isDone;
+ RetainPtr<CFURLRef> m_url;
+ RetainPtr<CFStringRef> m_user;
+ RetainPtr<CFStringRef> m_pass;
+ bool m_allowStoredCredentials;
+ ResourceResponse& m_response;
+ RetainPtr<CFMutableDataRef> m_data;
+ ResourceError& m_error;
+};
+
static HashSet<String>& allowsAnyHTTPSCertificateHosts()
{
static HashSet<String> hosts;
@@ -66,9 +98,16 @@ static HashMap<String, RetainPtr<CFDataRef> >& clientCerts()
return certs;
}
+static void setDefaultMIMEType(CFURLResponseRef response)
+{
+ static CFStringRef defaultMIMETypeString = defaultMIMEType().createCFString();
+
+ CFURLResponseSetMIMEType(response, defaultMIMETypeString);
+}
+
CFURLRequestRef willSendRequest(CFURLConnectionRef conn, CFURLRequestRef cfRequest, CFURLResponseRef cfRedirectResponse, const void* clientInfo)
{
- ResourceHandle* handle = (ResourceHandle*)clientInfo;
+ ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo));
if (!cfRedirectResponse) {
CFRetain(cfRequest);
@@ -78,8 +117,7 @@ CFURLRequestRef willSendRequest(CFURLConnectionRef conn, CFURLRequestRef cfReque
LOG(Network, "CFNet - willSendRequest(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().string().utf8().data());
ResourceRequest request(cfRequest);
- if (handle->client())
- handle->client()->willSendRequest(handle, request, cfRedirectResponse);
+ handle->willSendRequest(request, cfRedirectResponse);
cfRequest = request.cfURLRequest();
@@ -89,17 +127,25 @@ CFURLRequestRef willSendRequest(CFURLConnectionRef conn, CFURLRequestRef cfReque
void didReceiveResponse(CFURLConnectionRef conn, CFURLResponseRef cfResponse, const void* clientInfo)
{
- ResourceHandle* handle = (ResourceHandle*)clientInfo;
+ ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo));
LOG(Network, "CFNet - didReceiveResponse(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().string().utf8().data());
- if (handle->client())
- handle->client()->didReceiveResponse(handle, cfResponse);
+ if (!handle->client())
+ return;
+
+ if (!CFURLResponseGetMIMEType(cfResponse)) {
+ // We should never be applying the default MIMEType if we told the networking layer to do content sniffing for handle.
+ ASSERT(!handle->shouldContentSniff());
+ setDefaultMIMEType(cfResponse);
+ }
+
+ handle->client()->didReceiveResponse(handle, cfResponse);
}
void didReceiveData(CFURLConnectionRef conn, CFDataRef data, CFIndex originalLength, const void* clientInfo)
{
- ResourceHandle* handle = (ResourceHandle*)clientInfo;
+ ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo));
const UInt8* bytes = CFDataGetBytePtr(data);
CFIndex length = CFDataGetLength(data);
@@ -111,7 +157,7 @@ void didReceiveData(CFURLConnectionRef conn, CFDataRef data, CFIndex originalLen
static void didSendBodyData(CFURLConnectionRef conn, CFIndex bytesWritten, CFIndex totalBytesWritten, CFIndex totalBytesExpectedToWrite, const void *clientInfo)
{
- ResourceHandle* handle = (ResourceHandle*)clientInfo;
+ ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo));
if (!handle || !handle->client())
return;
handle->client()->didSendData(handle, totalBytesWritten, totalBytesExpectedToWrite);
@@ -131,7 +177,7 @@ static Boolean shouldUseCredentialStorageCallback(CFURLConnectionRef conn, const
void didFinishLoading(CFURLConnectionRef conn, const void* clientInfo)
{
- ResourceHandle* handle = (ResourceHandle*)clientInfo;
+ ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo));
LOG(Network, "CFNet - didFinishLoading(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().string().utf8().data());
@@ -141,7 +187,7 @@ void didFinishLoading(CFURLConnectionRef conn, const void* clientInfo)
void didFail(CFURLConnectionRef conn, CFErrorRef error, const void* clientInfo)
{
- ResourceHandle* handle = (ResourceHandle*)clientInfo;
+ ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo));
LOG(Network, "CFNet - didFail(conn=%p, handle=%p, error = %p) (%s)", conn, handle, error, handle->request().url().string().utf8().data());
@@ -151,7 +197,7 @@ void didFail(CFURLConnectionRef conn, CFErrorRef error, const void* clientInfo)
CFCachedURLResponseRef willCacheResponse(CFURLConnectionRef conn, CFCachedURLResponseRef cachedResponse, const void* clientInfo)
{
- ResourceHandle* handle = (ResourceHandle*)clientInfo;
+ ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo));
if (handle->client() && !handle->client()->shouldCacheResponse(handle, cachedResponse))
return 0;
@@ -174,7 +220,7 @@ CFCachedURLResponseRef willCacheResponse(CFURLConnectionRef conn, CFCachedURLRes
void didReceiveChallenge(CFURLConnectionRef conn, CFURLAuthChallengeRef challenge, const void* clientInfo)
{
- ResourceHandle* handle = (ResourceHandle*)clientInfo;
+ ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo));
ASSERT(handle);
LOG(Network, "CFNet - didReceiveChallenge(conn=%p, handle=%p (%s)", conn, handle, handle->request().url().string().utf8().data());
@@ -273,6 +319,8 @@ static CFURLRequestRef makeFinalRequest(const ResourceRequest& request, bool sho
sslProps.adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
CFDictionaryAddValue(sslProps.get(), kCFStreamSSLAllowsAnyRoot, kCFBooleanTrue);
CFDictionaryAddValue(sslProps.get(), kCFStreamSSLAllowsExpiredRoots, kCFBooleanTrue);
+ CFDictionaryAddValue(sslProps.get(), kCFStreamSSLAllowsExpiredCertificates, kCFBooleanTrue);
+ CFDictionaryAddValue(sslProps.get(), kCFStreamSSLValidatesCertificateChain, kCFBooleanFalse);
}
HashMap<String, RetainPtr<CFDataRef> >::iterator clientCert = clientCerts().find(request.url().host().lower());
@@ -300,9 +348,17 @@ bool ResourceHandle::start(Frame* frame)
if (!frame->page())
return false;
+ if ((!d->m_user.isEmpty() || !d->m_pass.isEmpty()) && !d->m_request.url().protocolInHTTPFamily()) {
+ // Credentials for ftp can only be passed in URL, the didReceiveAuthenticationChallenge delegate call won't be made.
+ KURL urlWithCredentials(d->m_request.url());
+ urlWithCredentials.setUser(d->m_user);
+ urlWithCredentials.setPass(d->m_pass);
+ d->m_request.setURL(urlWithCredentials);
+ }
+
RetainPtr<CFURLRequestRef> request(AdoptCF, makeFinalRequest(d->m_request, d->m_shouldContentSniff));
- CFURLConnectionClient_V3 client = { 3, this, 0, 0, 0, willSendRequest, didReceiveResponse, didReceiveData, NULL, didFinishLoading, didFail, willCacheResponse, didReceiveChallenge, didSendBodyData, shouldUseCredentialStorageCallback, 0};
+ CFURLConnectionClient_V3 client = { 3, this, 0, 0, 0, WebCore::willSendRequest, didReceiveResponse, didReceiveData, NULL, didFinishLoading, didFail, willCacheResponse, didReceiveChallenge, didSendBodyData, shouldUseCredentialStorageCallback, 0};
d->m_connection.adoptCF(CFURLConnectionCreate(0, request.get(), reinterpret_cast<CFURLConnectionClient*>(&client)));
@@ -334,6 +390,16 @@ bool ResourceHandle::supportsBufferedData()
return false;
}
+void ResourceHandle::willSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse)
+{
+ const KURL& url = request.url();
+ d->m_user = url.user();
+ d->m_pass = url.pass();
+ request.removeCredentials();
+
+ client()->willSendRequest(this, request, redirectResponse);
+}
+
bool ResourceHandle::shouldUseCredentialStorage()
{
LOG(Network, "CFNet - shouldUseCredentialStorage()");
@@ -351,7 +417,29 @@ void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChall
// Since CFURLConnection networking relies on keeping a reference to the original CFURLAuthChallengeRef,
// we make sure that is actually present
ASSERT(challenge.cfURLAuthChallengeRef());
-
+
+ if (!d->m_user.isNull() && !d->m_pass.isNull()) {
+ RetainPtr<CFStringRef> user(AdoptCF, d->m_user.createCFString());
+ RetainPtr<CFStringRef> pass(AdoptCF, d->m_pass.createCFString());
+ RetainPtr<CFURLCredentialRef> credential(AdoptCF,
+ CFURLCredentialCreate(kCFAllocatorDefault, user.get(), pass.get(), 0, kCFURLCredentialPersistenceNone));
+ WebCoreCredentialStorage::set(CFURLAuthChallengeGetProtectionSpace(challenge.cfURLAuthChallengeRef()), credential.get());
+ CFURLConnectionUseCredential(d->m_connection.get(), credential.get(), challenge.cfURLAuthChallengeRef());
+ d->m_user = String();
+ d->m_pass = String();
+ // FIXME: Per the specification, the user shouldn't be asked for credentials if there were incorrect ones provided explicitly.
+ return;
+ }
+
+ if (!challenge.previousFailureCount() && (!client() || client()->shouldUseCredentialStorage(this))) {
+ CFURLCredentialRef credential = WebCoreCredentialStorage::get(CFURLAuthChallengeGetProtectionSpace(challenge.cfURLAuthChallengeRef()));
+ if (credential) {
+ ASSERT(CFURLCredentialGetPersistence(credential) == kCFURLCredentialPersistenceNone);
+ CFURLConnectionUseCredential(d->m_connection.get(), credential, challenge.cfURLAuthChallengeRef());
+ return;
+ }
+ }
+
d->m_currentCFChallenge = challenge.cfURLAuthChallengeRef();
d->m_currentWebChallenge = AuthenticationChallenge(d->m_currentCFChallenge, this);
@@ -367,9 +455,17 @@ void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge
if (challenge != d->m_currentWebChallenge)
return;
- CFURLCredentialRef cfCredential = createCF(credential);
- CFURLConnectionUseCredential(d->m_connection.get(), cfCredential, challenge.cfURLAuthChallengeRef());
- CFRelease(cfCredential);
+ if (credential.persistence() == CredentialPersistenceForSession) {
+ // Manage per-session credentials internally, because once NSURLCredentialPersistencePerSession is used, there is no way
+ // to ignore it for a particular request (short of removing it altogether).
+ Credential webCredential(credential.user(), credential.password(), CredentialPersistenceNone);
+ RetainPtr<CFURLCredentialRef> cfCredential(AdoptCF, createCF(webCredential));
+ WebCoreCredentialStorage::set(CFURLAuthChallengeGetProtectionSpace(challenge.cfURLAuthChallengeRef()), cfCredential.get());
+ CFURLConnectionUseCredential(d->m_connection.get(), cfCredential.get(), challenge.cfURLAuthChallengeRef());
+ } else {
+ RetainPtr<CFURLCredentialRef> cfCredential(AdoptCF, createCF(credential));
+ CFURLConnectionUseCredential(d->m_connection.get(), cfCredential.get(), challenge.cfURLAuthChallengeRef());
+ }
clearAuthentication();
}
@@ -408,31 +504,27 @@ CFURLConnectionRef ResourceHandle::releaseConnectionForDownload()
return d->m_connection.releaseRef();
}
-void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& vector, Frame*)
+void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& vector, Frame*)
{
ASSERT(!request.isEmpty());
- CFURLResponseRef cfResponse = 0;
- CFErrorRef cfError = 0;
- RetainPtr<CFURLRequestRef> cfRequest(AdoptCF, makeFinalRequest(request, true));
- CFDataRef data = CFURLConnectionSendSynchronousRequest(cfRequest.get(), &cfResponse, &cfError, request.timeoutInterval());
-
- if (cfError) {
- error = cfError;
- CFRelease(cfError);
+ RetainPtr<CFDataRef> data = WebCoreSynchronousLoader::load(request, storedCredentials, response, error);
+ if (!error.isNull()) {
response = ResourceResponse(request.url(), String(), 0, String(), String());
- response.setHTTPStatusCode(404);
- } else {
- response = cfResponse;
- if (cfResponse)
- CFRelease(cfResponse);
+
+ CFErrorRef cfError = error;
+ CFStringRef domain = CFErrorGetDomain(cfError);
+ // FIXME: Return the actual response for failed authentication.
+ if (domain == kCFErrorDomainCFNetwork)
+ response.setHTTPStatusCode(CFErrorGetCode(cfError));
+ else
+ response.setHTTPStatusCode(404);
}
if (data) {
ASSERT(vector.isEmpty());
- vector.append(CFDataGetBytePtr(data), CFDataGetLength(data));
- CFRelease(data);
+ vector.append(CFDataGetBytePtr(data.get()), CFDataGetLength(data.get()));
}
}
@@ -480,4 +572,142 @@ bool ResourceHandle::willLoadFromCache(ResourceRequest& request)
return cached;
}
+CFURLRequestRef WebCoreSynchronousLoader::willSendRequest(CFURLConnectionRef, CFURLRequestRef cfRequest, CFURLResponseRef cfRedirectResponse, const void* clientInfo)
+{
+ WebCoreSynchronousLoader* loader = static_cast<WebCoreSynchronousLoader*>(const_cast<void*>(clientInfo));
+
+ // FIXME: This needs to be fixed to follow the redirect correctly even for cross-domain requests.
+ if (loader->m_url && !protocolHostAndPortAreEqual(loader->m_url.get(), CFURLRequestGetURL(cfRequest))) {
+ RetainPtr<CFErrorRef> cfError(AdoptCF, CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainCFNetwork, kCFURLErrorBadServerResponse, 0));
+ loader->m_error = cfError.get();
+ loader->m_isDone = true;
+ return 0;
+ }
+
+ loader->m_url = CFURLRequestGetURL(cfRequest);
+
+ if (cfRedirectResponse) {
+ // Take user/pass out of the URL.
+ loader->m_user.adoptCF(CFURLCopyUserName(loader->m_url.get()));
+ loader->m_pass.adoptCF(CFURLCopyPassword(loader->m_url.get()));
+ if (loader->m_user || loader->m_pass) {
+ ResourceRequest requestWithoutCredentials = cfRequest;
+ requestWithoutCredentials.removeCredentials();
+ cfRequest = requestWithoutCredentials.cfURLRequest();
+ }
+ }
+
+ CFRetain(cfRequest);
+ return cfRequest;
+}
+
+void WebCoreSynchronousLoader::didReceiveResponse(CFURLConnectionRef, CFURLResponseRef cfResponse, const void* clientInfo)
+{
+ WebCoreSynchronousLoader* loader = static_cast<WebCoreSynchronousLoader*>(const_cast<void*>(clientInfo));
+
+ loader->m_response = cfResponse;
+}
+
+void WebCoreSynchronousLoader::didReceiveData(CFURLConnectionRef, CFDataRef data, CFIndex originalLength, const void* clientInfo)
+{
+ WebCoreSynchronousLoader* loader = static_cast<WebCoreSynchronousLoader*>(const_cast<void*>(clientInfo));
+
+ if (!loader->m_data)
+ loader->m_data.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, 0));
+
+ const UInt8* bytes = CFDataGetBytePtr(data);
+ CFIndex length = CFDataGetLength(data);
+
+ CFDataAppendBytes(loader->m_data.get(), bytes, length);
+}
+
+void WebCoreSynchronousLoader::didFinishLoading(CFURLConnectionRef, const void* clientInfo)
+{
+ WebCoreSynchronousLoader* loader = static_cast<WebCoreSynchronousLoader*>(const_cast<void*>(clientInfo));
+
+ loader->m_isDone = true;
+}
+
+void WebCoreSynchronousLoader::didFail(CFURLConnectionRef, CFErrorRef error, const void* clientInfo)
+{
+ WebCoreSynchronousLoader* loader = static_cast<WebCoreSynchronousLoader*>(const_cast<void*>(clientInfo));
+
+ loader->m_error = error;
+ loader->m_isDone = true;
+}
+
+void WebCoreSynchronousLoader::didReceiveChallenge(CFURLConnectionRef conn, CFURLAuthChallengeRef challenge, const void* clientInfo)
+{
+ WebCoreSynchronousLoader* loader = static_cast<WebCoreSynchronousLoader*>(const_cast<void*>(clientInfo));
+
+ if (loader->m_user && loader->m_pass) {
+ RetainPtr<CFURLCredentialRef> credential(AdoptCF,
+ CFURLCredentialCreate(kCFAllocatorDefault, loader->m_user.get(), loader->m_pass.get(), 0, kCFURLCredentialPersistenceNone));
+ WebCoreCredentialStorage::set(CFURLAuthChallengeGetProtectionSpace(challenge), credential.get());
+ CFURLConnectionUseCredential(conn, credential.get(), challenge);
+ loader->m_user = 0;
+ loader->m_pass = 0;
+ return;
+ }
+ if (!CFURLAuthChallengeGetPreviousFailureCount(challenge) && loader->m_allowStoredCredentials) {
+ CFURLCredentialRef credential = WebCoreCredentialStorage::get(CFURLAuthChallengeGetProtectionSpace(challenge));
+ if (credential) {
+ ASSERT(CFURLCredentialGetPersistence(credential) == kCFURLCredentialPersistenceNone);
+ CFURLConnectionUseCredential(conn, credential, challenge);
+ return;
+ }
+ }
+ // FIXME: The user should be asked for credentials, as in async case.
+ CFURLConnectionUseCredential(conn, 0, challenge);
+}
+
+Boolean WebCoreSynchronousLoader::shouldUseCredentialStorage(CFURLConnectionRef, const void* clientInfo)
+{
+ WebCoreSynchronousLoader* loader = static_cast<WebCoreSynchronousLoader*>(const_cast<void*>(clientInfo));
+
+ // FIXME: We should ask FrameLoaderClient whether using credential storage is globally forbidden.
+ return loader->m_allowStoredCredentials;
+}
+
+RetainPtr<CFDataRef> WebCoreSynchronousLoader::load(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceResponse& response, ResourceError& error)
+{
+ ASSERT(response.isNull());
+ ASSERT(error.isNull());
+
+ WebCoreSynchronousLoader loader(response, error);
+
+ KURL url = request.url();
+
+ loader.m_user.adoptCF(url.user().createCFString());
+ loader.m_pass.adoptCF(url.pass().createCFString());
+ loader.m_allowStoredCredentials = (storedCredentials == AllowStoredCredentials);
+
+ // Take user/pass out of the URL.
+ // Credentials for ftp can only be passed in URL, the didReceiveAuthenticationChallenge delegate call won't be made.
+ RetainPtr<CFURLRequestRef> cfRequest;
+ if ((loader.m_user || loader.m_pass) && url.protocolInHTTPFamily()) {
+ ResourceRequest requestWithoutCredentials(request);
+ requestWithoutCredentials.removeCredentials();
+ cfRequest.adoptCF(makeFinalRequest(requestWithoutCredentials, ResourceHandle::shouldContentSniffURL(requestWithoutCredentials.url())));
+ } else
+ cfRequest.adoptCF(makeFinalRequest(request, ResourceHandle::shouldContentSniffURL(request.url())));
+
+ CFURLConnectionClient_V3 client = { 3, &loader, 0, 0, 0, willSendRequest, didReceiveResponse, didReceiveData, 0, didFinishLoading, didFail, 0, didReceiveChallenge, 0, shouldUseCredentialStorage, 0 };
+ RetainPtr<CFURLConnectionRef> connection(AdoptCF, CFURLConnectionCreate(kCFAllocatorDefault, cfRequest.get(), reinterpret_cast<CFURLConnectionClient*>(&client)));
+
+ CFURLConnectionScheduleWithRunLoop(connection.get(), CFRunLoopGetCurrent(), WebCoreSynchronousLoaderRunLoopMode);
+ CFURLConnectionScheduleDownloadWithRunLoop(connection.get(), CFRunLoopGetCurrent(), WebCoreSynchronousLoaderRunLoopMode);
+ CFURLConnectionStart(connection.get());
+
+ while (!loader.m_isDone)
+ CFRunLoopRunInMode(WebCoreSynchronousLoaderRunLoopMode, UINT_MAX, true);
+
+ CFURLConnectionCancel(connection.get());
+
+ if (error.isNull() && loader.m_response.mimeType().isNull())
+ setDefaultMIMEType(loader.m_response.cfURLResponse());
+
+ return loader.m_data;
+}
+
} // namespace WebCore
diff --git a/WebCore/platform/network/cf/ResourceRequestCFNet.cpp b/WebCore/platform/network/cf/ResourceRequestCFNet.cpp
index df6bbf9..7355401 100644
--- a/WebCore/platform/network/cf/ResourceRequestCFNet.cpp
+++ b/WebCore/platform/network/cf/ResourceRequestCFNet.cpp
@@ -30,6 +30,7 @@
#include "ResourceRequest.h"
#include <CFNetwork/CFURLRequestPriv.h>
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
namespace WebCore {
@@ -95,13 +96,15 @@ void ResourceRequest::doUpdatePlatformRequest()
CFMutableURLRequestRef cfRequest;
RetainPtr<CFURLRef> url(AdoptCF, ResourceRequest::url().createCFURL());
- RetainPtr<CFURLRef> mainDocumentURL(AdoptCF, ResourceRequest::mainDocumentURL().createCFURL());
+ RetainPtr<CFURLRef> firstPartyForCookies(AdoptCF, ResourceRequest::firstPartyForCookies().createCFURL());
if (m_cfRequest) {
cfRequest = CFURLRequestCreateMutableCopy(0, m_cfRequest.get());
CFURLRequestSetURL(cfRequest, url.get());
- CFURLRequestSetMainDocumentURL(cfRequest, mainDocumentURL.get());
+ CFURLRequestSetMainDocumentURL(cfRequest, firstPartyForCookies.get());
+ CFURLRequestSetCachePolicy(cfRequest, (CFURLRequestCachePolicy)cachePolicy());
+ CFURLRequestSetTimeoutInterval(cfRequest, timeoutInterval());
} else {
- cfRequest = CFURLRequestCreateMutable(0, url.get(), (CFURLRequestCachePolicy)cachePolicy(), timeoutInterval(), mainDocumentURL.get());
+ cfRequest = CFURLRequestCreateMutable(0, url.get(), (CFURLRequestCachePolicy)cachePolicy(), timeoutInterval(), firstPartyForCookies.get());
}
RetainPtr<CFStringRef> requestMethod(AdoptCF, httpMethod().createCFString());
@@ -138,7 +141,7 @@ void ResourceRequest::doUpdateResourceRequest()
m_cachePolicy = (ResourceRequestCachePolicy)CFURLRequestGetCachePolicy(m_cfRequest.get());
m_timeoutInterval = CFURLRequestGetTimeoutInterval(m_cfRequest.get());
- m_mainDocumentURL = CFURLRequestGetMainDocumentURL(m_cfRequest.get());
+ m_firstPartyForCookies = CFURLRequestGetMainDocumentURL(m_cfRequest.get());
if (CFStringRef method = CFURLRequestCopyHTTPRequestMethod(m_cfRequest.get())) {
m_httpMethod = method;
CFRelease(method);
@@ -162,11 +165,17 @@ void ResourceRequest::doUpdateResourceRequest()
for (CFIndex i = 0; i < count; ++i) {
CFStringEncoding encoding = reinterpret_cast<CFIndex>(CFArrayGetValueAtIndex(encodingFallbacks.get(), i));
if (encoding != kCFStringEncodingInvalidId)
- m_responseContentDispositionEncodingFallbackArray.append(CFStringGetNameOfEncoding(encoding));
+ m_responseContentDispositionEncodingFallbackArray.append(CFStringConvertEncodingToIANACharSetName(encoding));
}
}
m_httpBody = httpBodyFromRequest(m_cfRequest.get());
}
+unsigned initializeMaximumHTTPConnectionCountPerHost()
+{
+ static const unsigned preferredConnectionCount = 6;
+ return wkInitializeMaximumHTTPConnectionCountPerHost(preferredConnectionCount);
+}
+
}
diff --git a/WebCore/platform/network/cf/ResourceResponseCFNet.cpp b/WebCore/platform/network/cf/ResourceResponseCFNet.cpp
index 79efe89..95e9aff 100644
--- a/WebCore/platform/network/cf/ResourceResponseCFNet.cpp
+++ b/WebCore/platform/network/cf/ResourceResponseCFNet.cpp
@@ -24,11 +24,10 @@
*/
#include "config.h"
-#include "ResourceResponseCFNet.h"
+#include "ResourceResponse.h"
#include "HTTPParsers.h"
#include "MIMETypeRegistry.h"
-#include "ResourceResponse.h"
#include <CFNetwork/CFURLResponsePriv.h>
#include <wtf/RetainPtr.h>
@@ -80,7 +79,6 @@ void ResourceResponse::platformLazyInit()
m_expectedContentLength = CFURLResponseGetExpectedContentLength(m_cfResponse.get());
m_textEncodingName = CFURLResponseGetTextEncodingName(m_cfResponse.get());
- m_expirationDate = toTimeT(CFURLResponseGetExpirationTime(m_cfResponse.get()));
m_lastModifiedDate = toTimeT(CFURLResponseGetLastModifiedDate(m_cfResponse.get()));
RetainPtr<CFStringRef> suggestedFilename(AdoptCF, CFURLResponseCopySuggestedFilename(m_cfResponse.get()));
@@ -92,9 +90,11 @@ void ResourceResponse::platformLazyInit()
RetainPtr<CFStringRef> statusLine(AdoptCF, CFHTTPMessageCopyResponseStatusLine(httpResponse));
String statusText(statusLine.get());
- int spacePos = statusText.find(" ");
- if (spacePos != -1)
- statusText = statusText.substring(spacePos + 1);
+ int spacePos = statusText.find(' ');
+ // Remove the status code from the status text.
+ spacePos = statusText.find(' ', spacePos + 1);
+ statusText = statusText.substring(spacePos + 1);
+
m_httpStatusText = statusText;
RetainPtr<CFDictionaryRef> headers(AdoptCF, CFHTTPMessageCopyAllHeaderFields(httpResponse));
diff --git a/WebCore/platform/network/chromium/CookieJarChromium.cpp b/WebCore/platform/network/chromium/CookieJarChromium.cpp
index 50cab3b..65be451 100644
--- a/WebCore/platform/network/chromium/CookieJarChromium.cpp
+++ b/WebCore/platform/network/chromium/CookieJarChromium.cpp
@@ -36,16 +36,14 @@
namespace WebCore {
-void setCookies(Document* document, const KURL& url, const KURL& policyURL, const String& value)
+void setCookies(Document* document, const KURL& url, const String& value)
{
- // We ignore the policyURL and compute it directly ourselves to ensure
- // consistency with the cookies() method below.
- ChromiumBridge::setCookies(url, document->policyBaseURL(), value);
+ ChromiumBridge::setCookies(url, document->firstPartyForCookies(), value);
}
String cookies(const Document* document, const KURL& url)
{
- return ChromiumBridge::cookies(url, document->policyBaseURL());
+ return ChromiumBridge::cookies(url, document->firstPartyForCookies());
}
bool cookiesEnabled(const Document*)
diff --git a/WebCore/platform/network/chromium/ResourceRequest.h b/WebCore/platform/network/chromium/ResourceRequest.h
index b14dba6..aa76de4 100644
--- a/WebCore/platform/network/chromium/ResourceRequest.h
+++ b/WebCore/platform/network/chromium/ResourceRequest.h
@@ -49,6 +49,7 @@ namespace WebCore {
: ResourceRequestBase(KURL(url), UseProtocolCachePolicy)
, m_requestorID(0)
, m_requestorProcessID(0)
+ , m_appCacheContextID(0)
, m_targetType(TargetIsSubResource)
{
}
@@ -57,6 +58,7 @@ namespace WebCore {
: ResourceRequestBase(url, UseProtocolCachePolicy)
, m_requestorID(0)
, m_requestorProcessID(0)
+ , m_appCacheContextID(0)
, m_targetType(TargetIsSubResource)
, m_securityInfo(securityInfo)
{
@@ -66,6 +68,7 @@ namespace WebCore {
: ResourceRequestBase(url, UseProtocolCachePolicy)
, m_requestorID(0)
, m_requestorProcessID(0)
+ , m_appCacheContextID(0)
, m_targetType(TargetIsSubResource)
{
}
@@ -74,6 +77,7 @@ namespace WebCore {
: ResourceRequestBase(url, policy)
, m_requestorID(0)
, m_requestorProcessID(0)
+ , m_appCacheContextID(0)
, m_targetType(TargetIsSubResource)
{
setHTTPReferrer(referrer);
@@ -83,6 +87,7 @@ namespace WebCore {
: ResourceRequestBase(KURL(), UseProtocolCachePolicy)
, m_requestorID(0)
, m_requestorProcessID(0)
+ , m_appCacheContextID(0)
, m_targetType(TargetIsSubResource)
{
}
@@ -95,10 +100,6 @@ namespace WebCore {
TargetType targetType() const { return m_targetType; }
void setTargetType(TargetType type) { m_targetType = type; }
- // The document's policy base url.
- KURL policyURL() const { return m_policyURL; }
- void setPolicyURL(const KURL& policyURL) { m_policyURL = policyURL; }
-
// The process id of the process from which this request originated. In
// the case of out-of-process plugins, this allows to link back the
// request to the plugin process (as it is processed through a render
@@ -106,6 +107,10 @@ namespace WebCore {
int requestorProcessID() const { return m_requestorProcessID; }
void setRequestorProcessID(int requestorProcessID) { m_requestorProcessID = requestorProcessID; }
+ // Allows the request to be matched up with its app cache context.
+ int appCacheContextID() const { return m_appCacheContextID; }
+ void setAppCacheContextID(int id) { m_appCacheContextID = id; }
+
// Opaque buffer that describes the security state (including SSL
// connection state) for the resource that should be reported when the
// resource has been loaded. This is used to simulate secure
@@ -123,9 +128,9 @@ namespace WebCore {
int m_requestorID;
int m_requestorProcessID;
+ int m_appCacheContextID;
TargetType m_targetType;
CString m_securityInfo;
- KURL m_policyURL;
};
} // namespace WebCore
diff --git a/WebCore/platform/network/chromium/ResourceResponse.h b/WebCore/platform/network/chromium/ResourceResponse.h
index 256df74..6c928c0 100644
--- a/WebCore/platform/network/chromium/ResourceResponse.h
+++ b/WebCore/platform/network/chromium/ResourceResponse.h
@@ -37,12 +37,14 @@ namespace WebCore {
public:
ResourceResponse()
: m_isContentFiltered(false)
+ , m_appCacheID(0)
{
}
ResourceResponse(const KURL& url, const String& mimeType, long long expectedLength, const String& textEncodingName, const String& filename)
- : ResourceResponseBase(url, mimeType, expectedLength, textEncodingName, filename),
- m_isContentFiltered(false)
+ : ResourceResponseBase(url, mimeType, expectedLength, textEncodingName, filename)
+ , m_isContentFiltered(false)
+ , m_appCacheID(0)
{
}
@@ -58,6 +60,12 @@ namespace WebCore {
m_isContentFiltered = isContentFiltered;
}
+ long long getAppCacheID() const { return m_appCacheID; }
+ void setAppCacheID(long long id)
+ {
+ m_appCacheID = id;
+ }
+
private:
friend class ResourceResponseBase;
@@ -74,6 +82,10 @@ namespace WebCore {
// Whether the contents for this response has been altered/blocked (usually
// for security reasons.
bool m_isContentFiltered;
+
+ // The id of the appcache this response was retrieved from, or zero if
+ // the response was not retrieved from an appcache.
+ long long m_appCacheID;
};
} // namespace WebCore
diff --git a/WebCore/platform/network/curl/CookieJarCurl.cpp b/WebCore/platform/network/curl/CookieJarCurl.cpp
index 2f76ebc..5ac0f9c 100644
--- a/WebCore/platform/network/curl/CookieJarCurl.cpp
+++ b/WebCore/platform/network/curl/CookieJarCurl.cpp
@@ -17,6 +17,7 @@
#include "config.h"
#include "CookieJar.h"
+#include "Document.h"
#include "KURL.h"
#include "PlatformString.h"
#include "StringHash.h"
@@ -27,7 +28,7 @@ namespace WebCore {
static HashMap<String, String> cookieJar;
-void setCookies(Document* /*document*/, const KURL& url, const KURL& /*policyURL*/, const String& value)
+void setCookies(Document* /*document*/, const KURL& url, const String& value)
{
cookieJar.set(url.string(), value);
}
diff --git a/WebCore/platform/network/curl/ResourceHandleCurl.cpp b/WebCore/platform/network/curl/ResourceHandleCurl.cpp
index ca24ec5..a2e692c 100644
--- a/WebCore/platform/network/curl/ResourceHandleCurl.cpp
+++ b/WebCore/platform/network/curl/ResourceHandleCurl.cpp
@@ -191,7 +191,7 @@ bool ResourceHandle::loadsBlocked()
return false;
}
-void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame*)
+void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame*)
{
WebCoreSynchronousLoader syncLoader;
ResourceHandle handle(request, &syncLoader, true, false, true);
diff --git a/WebCore/platform/network/curl/ResourceHandleManager.cpp b/WebCore/platform/network/curl/ResourceHandleManager.cpp
index 6f009db..c61ad4f 100644
--- a/WebCore/platform/network/curl/ResourceHandleManager.cpp
+++ b/WebCore/platform/network/curl/ResourceHandleManager.cpp
@@ -46,12 +46,6 @@
#include <stdio.h>
#include <wtf/Vector.h>
-#if PLATFORM(GTK)
- #if GLIB_CHECK_VERSION(2,12,0)
- #define USE_GLIB_BASE64
- #endif
-#endif
-
namespace WebCore {
const int selectTimeoutMS = 5;
@@ -320,13 +314,13 @@ void ResourceHandleManager::downloadTimerCallback(Timer<ResourceHandleManager>*
if (d->client())
d->client()->didFinishLoading(job);
} else {
-#ifndef NDEBUG
char* url = 0;
curl_easy_getinfo(d->m_handle, CURLINFO_EFFECTIVE_URL, &url);
+#ifndef NDEBUG
fprintf(stderr, "Curl ERROR for url='%s', error: '%s'\n", url, curl_easy_strerror(msg->data.result));
#endif
if (d->client())
- d->client()->didFail(job, ResourceError());
+ d->client()->didFail(job, ResourceError(String(), msg->data.result, String(url), String(curl_easy_strerror(msg->data.result))));
}
removeFromCurl(job);
@@ -512,20 +506,10 @@ static void parseDataUrl(ResourceHandle* handle)
response.setTextEncodingName(charset);
client->didReceiveResponse(handle, response);
- // Use the GLib Base64 if available, since WebCore's decoder isn't
- // general-purpose and fails on Acid3 test 97 (whitespace).
-#ifdef USE_GLIB_BASE64
- size_t outLength = 0;
- char* outData = 0;
- outData = reinterpret_cast<char*>(g_base64_decode(data.utf8().data(), &outLength));
- if (outData && outLength > 0)
- client->didReceiveData(handle, outData, outLength, 0);
- g_free(outData);
-#else
+ // WebCore's decoder fails on Acid3 test 97 (whitespace).
Vector<char> out;
if (base64Decode(data.latin1().data(), data.latin1().length(), out) && out.size() > 0)
client->didReceiveData(handle, out.data(), out.size(), 0);
-#endif
} else {
// We have to convert to UTF-16 early due to limitations in KURL
data = decodeURLEscapeSequences(data, TextEncoding(charset));
@@ -606,8 +590,11 @@ void ResourceHandleManager::initializeHandle(ResourceHandle* job)
if (kurl.isLocalFile()) {
String query = kurl.query();
// Remove any query part sent to a local file.
- if (!query.isEmpty())
- url = url.left(url.find(query));
+ if (!query.isEmpty()) {
+ int queryIndex = url.find(query);
+ if (queryIndex != -1)
+ url = url.left(queryIndex - 1);
+ }
// Determine the MIME type based on the path.
d->m_response.setMimeType(MIMETypeRegistry::getMIMETypeForPath(url));
}
diff --git a/WebCore/platform/network/mac/AuthenticationMac.h b/WebCore/platform/network/mac/AuthenticationMac.h
index f55ac24..7fb6bee 100644
--- a/WebCore/platform/network/mac/AuthenticationMac.h
+++ b/WebCore/platform/network/mac/AuthenticationMac.h
@@ -45,6 +45,24 @@ AuthenticationChallenge core(NSURLAuthenticationChallenge *);
ProtectionSpace core(NSURLProtectionSpace *);
Credential core(NSURLCredential *);
+class WebCoreCredentialStorage {
+public:
+ static void set(NSURLCredential *credential, NSURLProtectionSpace *protectionSpace)
+ {
+ if (!m_storage)
+ m_storage = [[NSMutableDictionary alloc] init];
+ [m_storage setObject:credential forKey:protectionSpace];
+ }
+
+ static NSURLCredential *get(NSURLProtectionSpace *protectionSpace)
+ {
+ return static_cast<NSURLCredential *>([m_storage objectForKey:protectionSpace]);
+ }
+
+private:
+ static NSMutableDictionary* m_storage;
+};
+
}
#endif
diff --git a/WebCore/platform/network/mac/AuthenticationMac.mm b/WebCore/platform/network/mac/AuthenticationMac.mm
index 54e7681..961a79d 100644
--- a/WebCore/platform/network/mac/AuthenticationMac.mm
+++ b/WebCore/platform/network/mac/AuthenticationMac.mm
@@ -37,6 +37,8 @@
namespace WebCore {
+NSMutableDictionary* WebCoreCredentialStorage::m_storage;
+
AuthenticationChallenge::AuthenticationChallenge(const ProtectionSpace& protectionSpace,
const Credential& proposedCredential,
unsigned previousFailureCount,
diff --git a/WebCore/platform/network/mac/ResourceHandleMac.mm b/WebCore/platform/network/mac/ResourceHandleMac.mm
index 9bc322d..3af1b97 100644
--- a/WebCore/platform/network/mac/ResourceHandleMac.mm
+++ b/WebCore/platform/network/mac/ResourceHandleMac.mm
@@ -33,15 +33,23 @@
#import "FormDataStreamMac.h"
#import "Frame.h"
#import "FrameLoader.h"
+#import "Logging.h"
+#import "MIMETypeRegistry.h"
#import "Page.h"
#import "ResourceError.h"
#import "ResourceResponse.h"
#import "SchedulePair.h"
+#import "Settings.h"
#import "SharedBuffer.h"
#import "SubresourceLoader.h"
#import "WebCoreSystemInterface.h"
+#import "WebCoreURLResponse.h"
#import <wtf/UnusedParam.h>
+#ifndef BUILDING_ON_TIGER
+#import <objc/objc-class.h>
+#endif
+
#ifdef BUILDING_ON_TIGER
typedef int NSInteger;
#endif
@@ -51,9 +59,6 @@ using namespace WebCore;
@interface WebCoreResourceHandleAsDelegate : NSObject <NSURLAuthenticationChallengeSender>
{
ResourceHandle* m_handle;
-#ifndef BUILDING_ON_TIGER
- NSURL *m_url;
-#endif
}
- (id)initWithHandle:(ResourceHandle*)handle;
- (void)detachHandle;
@@ -63,20 +68,34 @@ using namespace WebCore;
- (NSData *)_bufferedData;
@end
+@interface NSURLResponse (Details)
+- (void)_setMIMEType:(NSString *)type;
+@end
+
+@interface NSURLRequest (Details)
+- (id)_propertyForKey:(NSString *)key;
+@end
+
#ifndef BUILDING_ON_TIGER
@interface WebCoreSynchronousLoader : NSObject {
NSURL *m_url;
+ NSString *m_user;
+ NSString *m_pass;
+ BOOL m_allowStoredCredentials;
NSURLResponse *m_response;
NSMutableData *m_data;
NSError *m_error;
BOOL m_isDone;
}
-+ (NSData *)loadRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error;
++ (NSData *)loadRequest:(NSURLRequest *)request allowStoredCredentials:(BOOL)allowStoredCredentials returningResponse:(NSURLResponse **)response error:(NSError **)error;
@end
static NSString *WebCoreSynchronousLoaderRunLoopMode = @"WebCoreSynchronousLoaderRunLoopMode";
+static IMP oldNSURLResponseMIMETypeIMP = 0;
+static NSString *webNSURLResponseMIMEType(id, SEL);
+
#endif
namespace WebCore {
@@ -113,6 +132,8 @@ ResourceHandleInternal::~ResourceHandleInternal()
ResourceHandle::~ResourceHandle()
{
releaseDelegate();
+
+ LOG(Network, "Handle %p destroyed", this);
}
static const double MaxFoundationVersionWithoutdidSendBodyDataDelegate = 677.21;
@@ -150,9 +171,19 @@ bool ResourceHandle::start(Frame* frame)
} else
delegate = ResourceHandle::delegate();
+ if ((!d->m_user.isEmpty() || !d->m_pass.isEmpty()) && !d->m_request.url().protocolInHTTPFamily()) {
+ // Credentials for ftp can only be passed in URL, the connection:didReceiveAuthenticationChallenge: delegate call won't be made.
+ KURL urlWithCredentials(d->m_request.url());
+ urlWithCredentials.setUser(d->m_user);
+ urlWithCredentials.setPass(d->m_pass);
+ d->m_request.setURL(urlWithCredentials);
+ }
+
if (!ResourceHandle::didSendBodyDataDelegateExists())
associateStreamWithResourceHandle([d->m_request.nsURLRequest() HTTPBodyStream], this);
+ d->m_needsSiteSpecificQuirks = frame->settings() && frame->settings()->needsSiteSpecificQuirks();
+
NSURLConnection *connection;
if (d->m_shouldContentSniff)
@@ -195,6 +226,8 @@ bool ResourceHandle::start(Frame* frame)
#ifndef NDEBUG
isInitializingConnection = NO;
#endif
+
+ LOG(Network, "Handle %p starting connection %p for %@", this, connection, d->m_request.nsURLRequest());
d->m_connection = connection;
@@ -214,6 +247,8 @@ bool ResourceHandle::start(Frame* frame)
void ResourceHandle::cancel()
{
+ LOG(Network, "Handle %p cancel connection %p", this, d->m_connection.get());
+
if (!ResourceHandle::didSendBodyDataDelegateExists())
disassociateStreamWithResourceHandle([d->m_request.nsURLRequest() HTTPBodyStream]);
[d->m_connection.get() cancel];
@@ -221,6 +256,8 @@ void ResourceHandle::cancel()
void ResourceHandle::setDefersLoading(bool defers)
{
+ LOG(Network, "Handle %p setDefersLoading(%s)", this, defers ? "true" : "false");
+
d->m_defersLoading = defers;
if (d->m_connection)
wkSetNSURLConnectionDefersCallbacks(d->m_connection.get(), defers);
@@ -313,6 +350,7 @@ bool ResourceHandle::loadsBlocked()
bool ResourceHandle::willLoadFromCache(ResourceRequest& request)
{
+#ifndef BUILDING_ON_TIGER
request.setCachePolicy(ReturnCacheDataDontLoad);
NSURLResponse *nsURLResponse = nil;
BEGIN_BLOCK_OBJC_EXCEPTIONS;
@@ -322,9 +360,14 @@ bool ResourceHandle::willLoadFromCache(ResourceRequest& request)
END_BLOCK_OBJC_EXCEPTIONS;
return nsURLResponse;
+#else
+ // <rdar://problem/6803217> - Re-enable after <rdar://problem/6786454> is resolved.
+ UNUSED_PARAM(request);
+ return false;
+#endif
}
-void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame*)
+void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame*)
{
NSError *nsError = nil;
@@ -333,12 +376,21 @@ void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, R
ASSERT(!request.isEmpty());
+ NSURLRequest *nsRequest;
+ if (!shouldContentSniffURL(request.url())) {
+ NSMutableURLRequest *mutableRequest = [[request.nsURLRequest() mutableCopy] autorelease];
+ wkSetNSURLRequestShouldContentSniff(mutableRequest, NO);
+ nsRequest = mutableRequest;
+ } else
+ nsRequest = request.nsURLRequest();
+
BEGIN_BLOCK_OBJC_EXCEPTIONS;
#ifndef BUILDING_ON_TIGER
- result = [WebCoreSynchronousLoader loadRequest:request.nsURLRequest() returningResponse:&nsURLResponse error:&nsError];
+ result = [WebCoreSynchronousLoader loadRequest:nsRequest allowStoredCredentials:(storedCredentials == AllowStoredCredentials) returningResponse:&nsURLResponse error:&nsError];
#else
- result = [NSURLConnection sendSynchronousRequest:request.nsURLRequest() returningResponse:&nsURLResponse error:&nsError];
+ UNUSED_PARAM(storedCredentials);
+ result = [NSURLConnection sendSynchronousRequest:nsRequest returningResponse:&nsURLResponse error:&nsError];
#endif
END_BLOCK_OBJC_EXCEPTIONS;
@@ -365,6 +417,16 @@ void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, R
error = nsError;
}
+void ResourceHandle::willSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse)
+{
+ const KURL& url = request.url();
+ d->m_user = url.user();
+ d->m_pass = url.pass();
+ request.removeCredentials();
+
+ client()->willSendRequest(this, request, redirectResponse);
+}
+
bool ResourceHandle::shouldUseCredentialStorage()
{
if (client())
@@ -380,7 +442,29 @@ void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChall
// Since NSURLConnection networking relies on keeping a reference to the original NSURLAuthenticationChallenge,
// we make sure that is actually present
ASSERT(challenge.nsURLAuthenticationChallenge());
-
+
+ if (!d->m_user.isNull() && !d->m_pass.isNull()) {
+ NSURLCredential *credential = [[NSURLCredential alloc] initWithUser:d->m_user
+ password:d->m_pass
+ persistence:NSURLCredentialPersistenceNone];
+ d->m_currentMacChallenge = challenge.nsURLAuthenticationChallenge();
+ d->m_currentWebChallenge = challenge;
+ receivedCredential(challenge, core(credential));
+ [credential release];
+ // FIXME: Per the specification, the user shouldn't be asked for credentials if there were incorrect ones provided explicitly.
+ d->m_user = String();
+ d->m_pass = String();
+ return;
+ }
+
+ if (!challenge.previousFailureCount() && (!client() || client()->shouldUseCredentialStorage(this))) {
+ NSURLCredential *credential = WebCoreCredentialStorage::get([mac(challenge) protectionSpace]);
+ if (credential) {
+ [challenge.sender() useCredential:credential forAuthenticationChallenge:mac(challenge)];
+ return;
+ }
+ }
+
d->m_currentMacChallenge = challenge.nsURLAuthenticationChallenge();
NSURLAuthenticationChallenge *webChallenge = [[NSURLAuthenticationChallenge alloc] initWithAuthenticationChallenge:d->m_currentMacChallenge
sender:(id<NSURLAuthenticationChallengeSender>)delegate()];
@@ -407,7 +491,24 @@ void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge
if (challenge != d->m_currentWebChallenge)
return;
- [[d->m_currentMacChallenge sender] useCredential:mac(credential) forAuthenticationChallenge:d->m_currentMacChallenge];
+#ifdef BUILDING_ON_TIGER
+ if (credential.persistence() == CredentialPersistenceNone) {
+ // NSURLCredentialPersistenceNone doesn't work on Tiger, so we have to use session persistence.
+ Credential webCredential(credential.user(), credential.password(), CredentialPersistenceForSession);
+ WebCoreCredentialStorage::set(mac(webCredential), [d->m_currentMacChallenge protectionSpace]);
+ [[d->m_currentMacChallenge sender] useCredential:mac(webCredential) forAuthenticationChallenge:d->m_currentMacChallenge];
+ } else
+#else
+ if (credential.persistence() == CredentialPersistenceForSession && (!d->m_needsSiteSpecificQuirks || ![[[mac(challenge) protectionSpace] host] isEqualToString:@"gallery.me.com"])) {
+ // Manage per-session credentials internally, because once NSURLCredentialPersistenceForSession is used, there is no way
+ // to ignore it for a particular request (short of removing it altogether).
+ // <rdar://problem/6867598> gallery.me.com is temporarily whitelisted, so that QuickTime plug-in could see the credentials.
+ Credential webCredential(credential.user(), credential.password(), CredentialPersistenceNone);
+ WebCoreCredentialStorage::set(mac(webCredential), [d->m_currentMacChallenge protectionSpace]);
+ [[d->m_currentMacChallenge sender] useCredential:mac(webCredential) forAuthenticationChallenge:d->m_currentMacChallenge];
+ } else
+#endif
+ [[d->m_currentMacChallenge sender] useCredential:mac(credential) forAuthenticationChallenge:d->m_currentMacChallenge];
clearAuthentication();
}
@@ -445,22 +546,14 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
return self;
}
-#ifndef BUILDING_ON_TIGER
-- (void)dealloc
-{
- [m_url release];
- [super dealloc];
-}
-#endif
-
- (void)detachHandle
{
m_handle = 0;
}
-- (NSURLRequest *)connection:(NSURLConnection *)unusedConnection willSendRequest:(NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse
+- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse
{
- UNUSED_PARAM(unusedConnection);
+ UNUSED_PARAM(connection);
// the willSendRequest call may cancel this load, in which case self could be deallocated
RetainPtr<WebCoreResourceHandleAsDelegate> protect(self);
@@ -472,14 +565,11 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
if (!redirectResponse)
return newRequest;
+ LOG(Network, "Handle %p delegate connection:%p willSendRequest:%@ redirectResponse:%p", m_handle, connection, [newRequest description], redirectResponse);
+
CallbackGuard guard;
ResourceRequest request = newRequest;
- m_handle->client()->willSendRequest(m_handle, request, redirectResponse);
-#ifndef BUILDING_ON_TIGER
- NSURL *copy = [[request.nsURLRequest() URL] copy];
- [m_url release];
- m_url = copy;
-#endif
+ m_handle->willSendRequest(request, redirectResponse);
if (!ResourceHandle::didSendBodyDataDelegateExists()) {
// The client may change the request's body stream, in which case we have to re-associate
@@ -495,9 +585,11 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
return request.nsURLRequest();
}
-- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)unusedConnection
+- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection
{
- UNUSED_PARAM(unusedConnection);
+ UNUSED_PARAM(connection);
+
+ LOG(Network, "Handle %p delegate connectionShouldUseCredentialStorage:%p", m_handle, connection);
if (!m_handle)
return NO;
@@ -506,35 +598,23 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
return m_handle->shouldUseCredentialStorage();
}
-- (void)connection:(NSURLConnection *)unusedConnection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
+- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
- UNUSED_PARAM(unusedConnection);
+ UNUSED_PARAM(connection);
+
+ LOG(Network, "Handle %p delegate connection:%p didReceiveAuthenticationChallenge:%p", m_handle, connection, challenge);
-#ifndef BUILDING_ON_TIGER
- if ([challenge previousFailureCount] == 0) {
- NSString *user = [m_url user];
- NSString *password = [m_url password];
-
- if (user && password) {
- NSURLCredential *credential = [[NSURLCredential alloc] initWithUser:user
- password:password
- persistence:NSURLCredentialPersistenceForSession];
- [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
- [credential release];
- return;
- }
- }
-#endif
-
if (!m_handle)
return;
CallbackGuard guard;
m_handle->didReceiveAuthenticationChallenge(core(challenge));
}
-- (void)connection:(NSURLConnection *)unusedConnection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
+- (void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
- UNUSED_PARAM(unusedConnection);
+ UNUSED_PARAM(connection);
+
+ LOG(Network, "Handle %p delegate connection:%p didCancelAuthenticationChallenge:%p", m_handle, connection, challenge);
if (!m_handle)
return;
@@ -542,19 +622,51 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
m_handle->didCancelAuthenticationChallenge(core(challenge));
}
-- (void)connection:(NSURLConnection *)unusedConnection didReceiveResponse:(NSURLResponse *)r
+- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)r
{
- UNUSED_PARAM(unusedConnection);
+ UNUSED_PARAM(connection);
+
+ LOG(Network, "Handle %p delegate connection:%p didReceiveResponse:%p (HTTP status %d)", m_handle, connection, r, [r respondsToSelector:@selector(statusCode)] ? [(id)r statusCode] : 0);
if (!m_handle || !m_handle->client())
return;
CallbackGuard guard;
+
+#ifndef BUILDING_ON_TIGER
+ if (!oldNSURLResponseMIMETypeIMP) {
+ Method nsURLResponseMIMETypeMethod = class_getInstanceMethod(objc_getClass("NSURLResponse"), @selector(MIMEType));
+ ASSERT(nsURLResponseMIMETypeMethod);
+ oldNSURLResponseMIMETypeIMP = method_setImplementation(nsURLResponseMIMETypeMethod, (IMP)webNSURLResponseMIMEType);
+ }
+#endif
+
+ if ([m_handle->request().nsURLRequest() _propertyForKey:@"ForceHTMLMIMEType"])
+ [r _setMIMEType:@"text/html"];
+
+#if ENABLE(WML)
+ const KURL& url = [r URL];
+ if (url.isLocalFile()) {
+ // FIXME: Workaround for <rdar://problem/6917571>: The WML file extension ".wml" is not mapped to
+ // the right MIME type, work around that CFNetwork problem, to unbreak WML support for local files.
+ const String& path = url.path();
+
+ DEFINE_STATIC_LOCAL(const String, wmlExt, (".wml"));
+ if (path.endsWith(wmlExt, false)) {
+ static NSString* defaultMIMETypeString = [(NSString*) defaultMIMEType() retain];
+ if ([[r _webcore_MIMEType] isEqualToString:defaultMIMETypeString])
+ [r _setMIMEType:@"text/vnd.wap.wml"];
+ }
+ }
+#endif
+
m_handle->client()->didReceiveResponse(m_handle, r);
}
-- (void)connection:(NSURLConnection *)unusedConnection didReceiveData:(NSData *)data lengthReceived:(long long)lengthReceived
+- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data lengthReceived:(long long)lengthReceived
{
- UNUSED_PARAM(unusedConnection);
+ UNUSED_PARAM(connection);
+
+ LOG(Network, "Handle %p delegate connection:%p didReceiveData:%p lengthReceived:%lld", m_handle, connection, data, lengthReceived);
if (!m_handle || !m_handle->client())
return;
@@ -565,9 +677,11 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
m_handle->client()->didReceiveData(m_handle, (const char*)[data bytes], [data length], static_cast<int>(lengthReceived));
}
-- (void)connection:(NSURLConnection *)unusedConnection willStopBufferingData:(NSData *)data
+- (void)connection:(NSURLConnection *)connection willStopBufferingData:(NSData *)data
{
- UNUSED_PARAM(unusedConnection);
+ UNUSED_PARAM(connection);
+
+ LOG(Network, "Handle %p delegate connection:%p willStopBufferingData:%p", m_handle, connection, data);
if (!m_handle || !m_handle->client())
return;
@@ -578,10 +692,12 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
m_handle->client()->willStopBufferingData(m_handle, (const char*)[data bytes], static_cast<int>([data length]));
}
-- (void)connection:(NSURLConnection *)unusedConnection didSendBodyData:(NSInteger)unusedBytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
+- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
{
- UNUSED_PARAM(unusedConnection);
- UNUSED_PARAM(unusedBytesWritten);
+ UNUSED_PARAM(connection);
+ UNUSED_PARAM(bytesWritten);
+
+ LOG(Network, "Handle %p delegate connection:%p didSendBodyData:%d totalBytesWritten:%d totalBytesExpectedToWrite:%d", m_handle, connection, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
if (!m_handle || !m_handle->client())
return;
@@ -589,9 +705,11 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
m_handle->client()->didSendData(m_handle, totalBytesWritten, totalBytesExpectedToWrite);
}
-- (void)connectionDidFinishLoading:(NSURLConnection *)unusedConnection
+- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
- UNUSED_PARAM(unusedConnection);
+ UNUSED_PARAM(connection);
+
+ LOG(Network, "Handle %p delegate connectionDidFinishLoading:%p", m_handle, connection);
if (!m_handle || !m_handle->client())
return;
@@ -603,9 +721,11 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
m_handle->client()->didFinishLoading(m_handle);
}
-- (void)connection:(NSURLConnection *)unusedConnection didFailWithError:(NSError *)error
+- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
- UNUSED_PARAM(unusedConnection);
+ UNUSED_PARAM(connection);
+
+ LOG(Network, "Handle %p delegate connection:%p didFailWithError:%@", m_handle, connection, error);
if (!m_handle || !m_handle->client())
return;
@@ -630,6 +750,8 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
+ LOG(Network, "Handle %p delegate connection:%p willCacheResponse:%p", m_handle, connection, cachedResponse);
+
#ifdef BUILDING_ON_TIGER
// On Tiger CFURLConnection can sometimes call the connection:willCacheResponse: delegate method on
// a secondary thread instead of the main thread. If this happens perform the work on the main thread.
@@ -717,6 +839,8 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
- (void)dealloc
{
[m_url release];
+ [m_user release];
+ [m_pass release];
[m_response release];
[m_data release];
[m_error release];
@@ -724,36 +848,71 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
[super dealloc];
}
-- (NSURLRequest *)connection:(NSURLConnection *)unusedConnection willSendRequest:(NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)unusedRedirectResponse
+- (NSURLRequest *)connection:(NSURLConnection *)unusedConnection willSendRequest:(NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse
{
UNUSED_PARAM(unusedConnection);
- UNUSED_PARAM(unusedRedirectResponse);
+
+ // FIXME: This needs to be fixed to follow the redirect correctly even for cross-domain requests.
+ if (m_url && !protocolHostAndPortAreEqual(m_url, [newRequest URL])) {
+ m_error = [[NSError alloc] initWithDomain:NSURLErrorDomain code:NSURLErrorBadServerResponse userInfo:nil];
+ m_isDone = YES;
+ return nil;
+ }
NSURL *copy = [[newRequest URL] copy];
[m_url release];
m_url = copy;
+ if (redirectResponse) {
+ // Take user/pass out of the URL.
+ [m_user release];
+ [m_pass release];
+ m_user = [[m_url user] copy];
+ m_pass = [[m_url password] copy];
+ if (m_user || m_pass) {
+ ResourceRequest requestWithoutCredentials = newRequest;
+ requestWithoutCredentials.removeCredentials();
+ return requestWithoutCredentials.nsURLRequest();
+ }
+ }
+
return newRequest;
}
+- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)unusedConnection
+{
+ UNUSED_PARAM(unusedConnection);
+
+ // FIXME: We should ask FrameLoaderClient whether using credential storage is globally forbidden.
+ return m_allowStoredCredentials;
+}
+
- (void)connection:(NSURLConnection *)unusedConnection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
UNUSED_PARAM(unusedConnection);
- if ([challenge previousFailureCount] == 0) {
- NSString *user = [m_url user];
- NSString *password = [m_url password];
-
- if (user && password) {
- NSURLCredential *credential = [[NSURLCredential alloc] initWithUser:user
- password:password
- persistence:NSURLCredentialPersistenceForSession];
+ if (m_user && m_pass) {
+ NSURLCredential *credential = [[NSURLCredential alloc] initWithUser:m_user
+ password:m_pass
+ persistence:NSURLCredentialPersistenceNone];
+ WebCoreCredentialStorage::set(credential, [challenge protectionSpace]);
+ [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
+ [credential release];
+ [m_user release];
+ [m_pass release];
+ m_user = 0;
+ m_pass = 0;
+ return;
+ }
+ if ([challenge previousFailureCount] == 0 && m_allowStoredCredentials) {
+ NSURLCredential *credential = WebCoreCredentialStorage::get([challenge protectionSpace]);
+ ASSERT([credential persistence] == NSURLCredentialPersistenceNone);
+ if (credential) {
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
- [credential release];
return;
}
}
-
+ // FIXME: The user should be asked for credentials, as in async case.
[[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];
}
@@ -809,11 +968,26 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
return [[m_error retain] autorelease];
}
-+ (NSData *)loadRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error
++ (NSData *)loadRequest:(NSURLRequest *)request allowStoredCredentials:(BOOL)allowStoredCredentials returningResponse:(NSURLResponse **)response error:(NSError **)error
{
WebCoreSynchronousLoader *delegate = [[WebCoreSynchronousLoader alloc] init];
-
- NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate startImmediately:NO];
+
+ NSURL *url = [request URL];
+ delegate->m_user = [[url user] copy];
+ delegate->m_pass = [[url password] copy];
+ delegate->m_allowStoredCredentials = allowStoredCredentials;
+
+ NSURLConnection *connection;
+
+ // Take user/pass out of the URL.
+ // Credentials for ftp can only be passed in URL, the connection:didReceiveAuthenticationChallenge: delegate call won't be made.
+ if ((delegate->m_user || delegate->m_pass) && KURL(url).protocolInHTTPFamily()) {
+ ResourceRequest requestWithoutCredentials = request;
+ requestWithoutCredentials.removeCredentials();
+ connection = [[NSURLConnection alloc] initWithRequest:requestWithoutCredentials.nsURLRequest() delegate:delegate startImmediately:NO];
+ } else
+ connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate startImmediately:NO];
+
[connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:WebCoreSynchronousLoaderRunLoopMode];
[connection start];
@@ -834,4 +1008,14 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
@end
+static NSString *webNSURLResponseMIMEType(id self, SEL _cmd)
+{
+ ASSERT(oldNSURLResponseMIMETypeIMP);
+ if (NSString *result = oldNSURLResponseMIMETypeIMP(self, _cmd))
+ return result;
+
+ static NSString *defaultMIMETypeString = [(NSString *)defaultMIMEType() retain];
+ return defaultMIMETypeString;
+}
+
#endif
diff --git a/WebCore/platform/network/mac/ResourceRequestMac.mm b/WebCore/platform/network/mac/ResourceRequestMac.mm
index 92c37ee..6bb36a0 100644
--- a/WebCore/platform/network/mac/ResourceRequestMac.mm
+++ b/WebCore/platform/network/mac/ResourceRequestMac.mm
@@ -57,7 +57,7 @@ void ResourceRequest::doUpdateResourceRequest()
m_url = [m_nsRequest.get() URL];
m_cachePolicy = (ResourceRequestCachePolicy)[m_nsRequest.get() cachePolicy];
m_timeoutInterval = [m_nsRequest.get() timeoutInterval];
- m_mainDocumentURL = [m_nsRequest.get() mainDocumentURL];
+ m_firstPartyForCookies = [m_nsRequest.get() mainDocumentURL];
if (NSString* method = [m_nsRequest.get() HTTPMethod])
m_httpMethod = method;
@@ -78,7 +78,7 @@ void ResourceRequest::doUpdateResourceRequest()
for (NSUInteger i = 0; i < count; ++i) {
CFStringEncoding encoding = CFStringConvertNSStringEncodingToEncoding([(NSNumber *)[encodingFallbacks objectAtIndex:i] unsignedLongValue]);
if (encoding != kCFStringEncodingInvalidId)
- m_responseContentDispositionEncodingFallbackArray.append(CFStringGetNameOfEncoding(encoding));
+ m_responseContentDispositionEncodingFallbackArray.append(CFStringConvertEncodingToIANACharSetName(encoding));
}
}
@@ -110,7 +110,7 @@ void ResourceRequest::doUpdatePlatformRequest()
[nsRequest setCachePolicy:(NSURLRequestCachePolicy)cachePolicy()];
if (timeoutInterval() != unspecifiedTimeoutInterval)
[nsRequest setTimeoutInterval:timeoutInterval()];
- [nsRequest setMainDocumentURL:mainDocumentURL()];
+ [nsRequest setMainDocumentURL:firstPartyForCookies()];
if (!httpMethod().isEmpty())
[nsRequest setHTTPMethod:httpMethod()];
[nsRequest setHTTPShouldHandleCookies:allowHTTPCookies()];
@@ -146,5 +146,11 @@ 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);
+}
}
diff --git a/WebCore/platform/network/mac/ResourceResponseMac.mm b/WebCore/platform/network/mac/ResourceResponseMac.mm
index d501b31..60a4dc6 100644
--- a/WebCore/platform/network/mac/ResourceResponseMac.mm
+++ b/WebCore/platform/network/mac/ResourceResponseMac.mm
@@ -74,12 +74,6 @@ void ResourceResponse::platformLazyInit()
m_textEncodingName = [m_nsResponse.get() textEncodingName];
m_suggestedFilename = [m_nsResponse.get() suggestedFilename];
- const time_t maxTime = std::numeric_limits<time_t>::max();
-
- NSTimeInterval expiration = [m_nsResponse.get() _calculatedExpiration];
- expiration += kCFAbsoluteTimeIntervalSince1970;
- m_expirationDate = expiration > maxTime ? maxTime : static_cast<time_t>(expiration);
-
if ([m_nsResponse.get() isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)m_nsResponse.get();
diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
index 2c730a6..06b60bf 100644
--- a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
+++ b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
@@ -136,7 +136,6 @@ QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadMode load
, m_redirected(false)
, m_responseSent(false)
, m_loadMode(loadMode)
- , m_startTime(0)
, m_shouldStart(true)
, m_shouldFinish(false)
, m_shouldSendResponse(false)
@@ -174,6 +173,7 @@ void QNetworkReplyHandler::abort()
if (m_reply) {
QNetworkReply* reply = release();
reply->abort();
+ reply->deleteLater();
deleteLater();
}
}
@@ -291,7 +291,7 @@ void QNetworkReplyHandler::sendResponseIfNeeded()
}
if (isLocalFileReply)
- response.setExpirationDate(m_startTime);
+ response.setHTTPHeaderField(QString::fromAscii("Cache-Control"), QString::fromAscii("no-cache"));
QUrl redirection = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
if (redirection.isValid()) {
@@ -354,8 +354,6 @@ void QNetworkReplyHandler::start()
&& (!url.toLocalFile().isEmpty() || url.scheme() == QLatin1String("data")))
m_method = QNetworkAccessManager::GetOperation;
- m_startTime = QDateTime::currentDateTime().toTime_t();
-
switch (m_method) {
case QNetworkAccessManager::GetOperation:
m_reply = manager->get(m_request);
diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.h b/WebCore/platform/network/qt/QNetworkReplyHandler.h
index 98be28d..3de6d88 100644
--- a/WebCore/platform/network/qt/QNetworkReplyHandler.h
+++ b/WebCore/platform/network/qt/QNetworkReplyHandler.h
@@ -72,7 +72,6 @@ private:
LoadMode m_loadMode;
QNetworkAccessManager::Operation m_method;
QNetworkRequest m_request;
- uint m_startTime;
// defer state holding
bool m_shouldStart;
diff --git a/WebCore/platform/network/qt/ResourceHandleQt.cpp b/WebCore/platform/network/qt/ResourceHandleQt.cpp
index 7af5895..c5816a4 100644
--- a/WebCore/platform/network/qt/ResourceHandleQt.cpp
+++ b/WebCore/platform/network/qt/ResourceHandleQt.cpp
@@ -171,7 +171,7 @@ PassRefPtr<SharedBuffer> ResourceHandle::bufferedData()
return 0;
}
-void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame* frame)
+void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials /*storedCredentials*/, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame* frame)
{
WebCoreSynchronousLoader syncLoader;
ResourceHandle handle(request, &syncLoader, true, false, true);
diff --git a/WebCore/platform/network/qt/ResourceRequestQt.cpp b/WebCore/platform/network/qt/ResourceRequestQt.cpp
index 9308878..c8f6ad5 100644
--- a/WebCore/platform/network/qt/ResourceRequestQt.cpp
+++ b/WebCore/platform/network/qt/ResourceRequestQt.cpp
@@ -41,6 +41,22 @@ QNetworkRequest ResourceRequest::toNetworkRequest() const
request.setRawHeader(name, value);
}
+ switch (cachePolicy()) {
+ case ReloadIgnoringCacheData:
+ request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
+ break;
+ case ReturnCacheDataElseLoad:
+ request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
+ break;
+ case ReturnCacheDataDontLoad:
+ request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache);
+ break;
+ case UseProtocolCachePolicy:
+ // QNetworkRequest::PreferNetwork
+ default:
+ break;
+ }
+
return request;
}
diff --git a/WebCore/platform/network/soup/CookieJarSoup.cpp b/WebCore/platform/network/soup/CookieJarSoup.cpp
index e3064e1..705fdf2 100644
--- a/WebCore/platform/network/soup/CookieJarSoup.cpp
+++ b/WebCore/platform/network/soup/CookieJarSoup.cpp
@@ -22,6 +22,7 @@
#include "CookieJarSoup.h"
#include "CString.h"
+#include "Document.h"
#include "KURL.h"
namespace WebCore {
@@ -52,7 +53,7 @@ void setDefaultCookieJar(SoupCookieJar* jar)
g_object_ref(cookieJar);
}
-void setCookies(Document* /*document*/, const KURL& url, const KURL& /*policyURL*/, const String& value)
+void setCookies(Document* /*document*/, const KURL& url, const String& value)
{
SoupCookieJar* jar = defaultCookieJar();
if (!jar)
diff --git a/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/WebCore/platform/network/soup/ResourceHandleSoup.cpp
index 1b91e32..6be13e2 100644
--- a/WebCore/platform/network/soup/ResourceHandleSoup.cpp
+++ b/WebCore/platform/network/soup/ResourceHandleSoup.cpp
@@ -53,10 +53,6 @@
#include <sys/stat.h>
#include <unistd.h>
-#if PLATFORM(GTK)
-#define USE_GLIB_BASE64
-#endif
-
namespace WebCore {
class WebCoreSynchronousLoader : public ResourceHandleClient, Noncopyable {
@@ -121,14 +117,6 @@ void WebCoreSynchronousLoader::run()
g_main_loop_run(m_mainLoop);
}
-enum
-{
- ERROR_TRANSPORT,
- ERROR_UNKNOWN_PROTOCOL,
- ERROR_BAD_NON_HTTP_METHOD,
- ERROR_UNABLE_TO_OPEN_FILE,
-};
-
static void cleanupGioOperation(ResourceHandleInternal* handle);
ResourceHandleInternal::~ResourceHandleInternal()
@@ -148,6 +136,9 @@ ResourceHandleInternal::~ResourceHandleInternal()
ResourceHandle::~ResourceHandle()
{
+ if (d->m_msg)
+ g_signal_handlers_disconnect_matched(d->m_msg, G_SIGNAL_MATCH_DATA,
+ 0, 0, 0, 0, this);
}
static void fillResponseFromMessage(SoupMessage* msg, ResourceResponse* response)
@@ -171,17 +162,24 @@ static void fillResponseFromMessage(SoupMessage* msg, ResourceResponse* response
contentType = contentTypes[0];
if (contentTypeParameters) {
+ GString* parametersString = g_string_new(0);
GHashTableIter hashTableIter;
- gpointer hashKey;
- gpointer hashValue;
+ const char* hashKey;
+ const char* hashValue;
g_hash_table_iter_init(&hashTableIter, contentTypeParameters);
- while (g_hash_table_iter_next(&hashTableIter, &hashKey, &hashValue)) {
- contentType += String("; ");
- contentType += String(static_cast<char*>(hashKey));
- contentType += String("=");
- contentType += String(static_cast<char*>(hashValue));
+ while (g_hash_table_iter_next(&hashTableIter, reinterpret_cast<void**>(const_cast<char**>(&hashKey)), reinterpret_cast<void**>(const_cast<char**>(&hashValue)))) {
+ // Work-around bug in soup which causes a crash;
+ // See http://bugzilla.gnome.org/show_bug.cgi?id=577728
+ if (!hashValue)
+ hashValue = "";
+
+ g_string_append(parametersString, "; ");
+ soup_header_g_string_append_param(parametersString, hashKey, hashValue);
}
+ contentType += String(parametersString->str);
+
+ g_string_free(parametersString, true);
g_hash_table_destroy(contentTypeParameters);
}
@@ -228,8 +226,6 @@ static void restartedCallback(SoupMessage* msg, gpointer data)
fillResponseFromMessage(msg, &response);
if (d->client())
d->client()->willSendRequest(handle, request, response);
-
- d->m_request.setURL(newURL);
}
static void gotHeadersCallback(SoupMessage* msg, gpointer data)
@@ -258,11 +254,12 @@ static void gotHeadersCallback(SoupMessage* msg, gpointer data)
// sniffing the contents of the file, and then report that we got
// headers; we will not do content sniffing for 304 responses,
// though, since they do not have a body.
+ const char* contentType = soup_message_headers_get_content_type(msg->response_headers, NULL);
if ((msg->status_code != SOUP_STATUS_NOT_MODIFIED)
- && !soup_message_headers_get_content_type(msg->response_headers, NULL))
+ && (!contentType || !g_ascii_strcasecmp(contentType, "text/plain")))
return;
- ResourceHandle* handle = static_cast<ResourceHandle*>(data);
+ RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data);
if (!handle)
return;
ResourceHandleInternal* d = handle->getInternal();
@@ -273,8 +270,8 @@ static void gotHeadersCallback(SoupMessage* msg, gpointer data)
return;
fillResponseFromMessage(msg, &d->m_response);
- client->didReceiveResponse(handle, d->m_response);
d->m_reportedHeaders = true;
+ client->didReceiveResponse(handle.get(), d->m_response);
}
static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data)
@@ -284,7 +281,7 @@ static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data)
|| (msg->status_code == SOUP_STATUS_UNAUTHORIZED))
return;
- ResourceHandle* handle = static_cast<ResourceHandle*>(data);
+ RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data);
if (!handle)
return;
ResourceHandleInternal* d = handle->getInternal();
@@ -301,11 +298,15 @@ static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data)
g_free(contentType);
fillResponseFromMessage(msg, &d->m_response);
- client->didReceiveResponse(handle, d->m_response);
+ client->didReceiveResponse(handle.get(), d->m_response);
d->m_reportedHeaders = true;
+
+ // the didReceiveResponse call above may have cancelled the request
+ if (d->m_cancelled)
+ return;
}
- client->didReceiveData(handle, chunk->data, chunk->length, false);
+ client->didReceiveData(handle.get(), chunk->data, chunk->length, false);
}
// Called at the end of the message, with all the necessary about the last informations.
@@ -327,9 +328,10 @@ static void finishedCallback(SoupSession *session, SoupMessage* msg, gpointer da
return;
if (SOUP_STATUS_IS_TRANSPORT_ERROR(msg->status_code)) {
- char* uri = soup_uri_to_string(soup_message_get_uri(msg), false);
- ResourceError error("webkit-network-error", ERROR_TRANSPORT, uri, String::fromUTF8(msg->reason_phrase));
- g_free(uri);
+ ResourceError error(g_quark_to_string(SOUP_HTTP_ERROR),
+ msg->status_code,
+ soup_uri_to_string(soup_message_get_uri(msg), false),
+ String::fromUTF8(msg->reason_phrase));
client->didFail(handle.get(), error);
return;
}
@@ -354,8 +356,11 @@ static gboolean parseDataUrl(gpointer callback_data)
{
ResourceHandle* handle = static_cast<ResourceHandle*>(callback_data);
ResourceHandleClient* client = handle->client();
+ ResourceHandleInternal* d = handle->getInternal();
+ if (d->m_cancelled)
+ return false;
- handle->getInternal()->m_idleHandler = 0;
+ d->m_idleHandler = 0;
ASSERT(client);
if (!client)
@@ -391,27 +396,31 @@ static gboolean parseDataUrl(gpointer callback_data)
response.setTextEncodingName(charset);
client->didReceiveResponse(handle, response);
- // Use the GLib Base64 if available, since WebCore's decoder isn't
+ if (d->m_cancelled)
+ return false;
+
+ // Use the GLib Base64, since WebCore's decoder isn't
// general-purpose and fails on Acid3 test 97 (whitespace).
-#ifdef USE_GLIB_BASE64
size_t outLength = 0;
char* outData = 0;
outData = reinterpret_cast<char*>(g_base64_decode(data.utf8().data(), &outLength));
if (outData && outLength > 0)
client->didReceiveData(handle, outData, outLength, 0);
g_free(outData);
-#else
- Vector<char> out;
- if (base64Decode(data.latin1().data(), data.latin1().length(), out) && out.size() > 0)
- client->didReceiveData(handle, out.data(), out.size(), 0);
-#endif
} else {
// We have to convert to UTF-16 early due to limitations in KURL
data = decodeURLEscapeSequences(data, TextEncoding(charset));
response.setTextEncodingName("UTF-16");
client->didReceiveResponse(handle, response);
+
+ if (d->m_cancelled)
+ return false;
+
if (data.length() > 0)
client->didReceiveData(handle, reinterpret_cast<const char*>(data.characters()), data.length() * sizeof(UChar), 0);
+
+ if (d->m_cancelled)
+ return false;
}
client->didFinishLoading(handle);
@@ -459,20 +468,12 @@ bool ResourceHandle::startHttp(String urlString)
SoupSession* session = defaultSession();
ensureSessionIsInitialized(session);
- SoupMessage* msg;
- msg = soup_message_new(request().httpMethod().utf8().data(), urlString.utf8().data());
- g_signal_connect(msg, "restarted", G_CALLBACK(restartedCallback), this);
- g_signal_connect(msg, "got-headers", G_CALLBACK(gotHeadersCallback), this);
- g_signal_connect(msg, "got-chunk", G_CALLBACK(gotChunkCallback), this);
-
- g_object_set_data(G_OBJECT(msg), "resourceHandle", reinterpret_cast<void*>(this));
+ d->m_msg = request().toSoupMessage();
+ g_signal_connect(d->m_msg, "restarted", G_CALLBACK(restartedCallback), this);
+ g_signal_connect(d->m_msg, "got-headers", G_CALLBACK(gotHeadersCallback), this);
+ g_signal_connect(d->m_msg, "got-chunk", G_CALLBACK(gotChunkCallback), this);
- HTTPHeaderMap customHeaders = d->m_request.httpHeaderFields();
- if (!customHeaders.isEmpty()) {
- HTTPHeaderMap::const_iterator end = customHeaders.end();
- for (HTTPHeaderMap::const_iterator it = customHeaders.begin(); it != end; ++it)
- soup_message_headers_append(msg->request_headers, it->first.string().utf8().data(), it->second.utf8().data());
- }
+ g_object_set_data(G_OBJECT(d->m_msg), "resourceHandle", reinterpret_cast<void*>(this));
FormData* httpBody = d->m_request.httpBody();
if (httpBody && !httpBody->isEmpty()) {
@@ -482,7 +483,7 @@ bool ResourceHandle::startHttp(String urlString)
if (numElements < 2) {
Vector<char> body;
httpBody->flatten(body);
- soup_message_set_request(msg, d->m_request.httpContentType().utf8().data(),
+ soup_message_set_request(d->m_msg, d->m_request.httpContentType().utf8().data(),
SOUP_MEMORY_COPY, body.data(), body.size());
} else {
/*
@@ -491,12 +492,12 @@ bool ResourceHandle::startHttp(String urlString)
* copying into memory; TODO: support upload of non-local
* (think sftp://) files by using GIO?
*/
- soup_message_body_set_accumulate(msg->request_body, FALSE);
+ soup_message_body_set_accumulate(d->m_msg->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(msg->request_body, SOUP_MEMORY_TEMPORARY, element.m_data.data(), element.m_data.size());
+ soup_message_body_append(d->m_msg->request_body, SOUP_MEMORY_TEMPORARY, element.m_data.data(), element.m_data.size());
else {
/*
* mapping for uploaded files code inspired by technique used in
@@ -509,53 +510,50 @@ bool ResourceHandle::startHttp(String urlString)
g_free(fileName);
if (error) {
- ResourceError resourceError("webkit-network-error", ERROR_UNABLE_TO_OPEN_FILE, urlString, error->message);
+ ResourceError resourceError(g_quark_to_string(SOUP_HTTP_ERROR),
+ d->m_msg->status_code,
+ urlString,
+ String::fromUTF8(error->message));
g_error_free(error);
d->client()->didFail(this, resourceError);
- g_object_unref(msg);
+ g_signal_handlers_disconnect_matched(d->m_msg, G_SIGNAL_MATCH_DATA,
+ 0, 0, 0, 0, this);
+ g_object_unref(d->m_msg);
+ d->m_msg = 0;
+
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_free));
- soup_message_body_append_buffer(msg->request_body, soupBuffer);
+ soup_message_body_append_buffer(d->m_msg->request_body, soupBuffer);
soup_buffer_free(soupBuffer);
}
}
}
}
- d->m_msg = static_cast<SoupMessage*>(g_object_ref(msg));
// balanced by a deref() in finishedCallback, which should always run
ref();
+ // FIXME: For now, we cannot accept content encoded in anything
+ // other than identity, so force servers to do it our way. When
+ // libsoup gets proper Content-Encoding support we will want to
+ // use it here instead.
+ soup_message_headers_replace(d->m_msg->request_headers, "Accept-Encoding", "identity");
+
+ // Balanced in ResourceHandleInternal's destructor; we need to
+ // keep our own ref, because after queueing the message, the
+ // session owns the initial reference.
+ g_object_ref(d->m_msg);
soup_session_queue_message(session, d->m_msg, finishedCallback, this);
return true;
}
-static gboolean reportUnknownProtocolError(gpointer callback_data)
-{
- ResourceHandle* handle = static_cast<ResourceHandle*>(callback_data);
- ResourceHandleInternal* d = handle->getInternal();
- ResourceHandleClient* client = handle->client();
-
- if (d->m_cancelled || !client) {
- handle->deref();
- return false;
- }
-
- KURL url = handle->request().url();
- ResourceError error("webkit-network-error", ERROR_UNKNOWN_PROTOCOL, url.string(), url.protocol());
- client->didFail(handle, error);
-
- handle->deref();
- return false;
-}
-
bool ResourceHandle::start(Frame* frame)
{
ASSERT(!d->m_msg);
@@ -585,11 +583,9 @@ bool ResourceHandle::start(Frame* frame)
// FIXME: should we be doing any other protocols here?
return startGio(url);
- // Error must not be reported immediately, but through an idle function.
- // Despite error, we should return true so a proper handle is created,
- // to which this failure can be reported.
- ref();
- d->m_idleHandler = g_idle_add(reportUnknownProtocolError, this);
+ // Error must not be reported immediately
+ this->scheduleFailure(InvalidURLFailure);
+
return true;
}
@@ -632,7 +628,7 @@ bool ResourceHandle::willLoadFromCache(ResourceRequest&)
return false;
}
-void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame* frame)
+void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials /*storedCredentials*/, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame* frame)
{
WebCoreSynchronousLoader syncLoader(error, response, data);
ResourceHandle handle(request, &syncLoader, true, false, true);
@@ -643,15 +639,6 @@ void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, R
// GIO-based loader
-static inline ResourceError networkErrorForFile(GFile* file, GError* error)
-{
- // FIXME: Map gio errors to a more detailed error code when we have it in WebKit.
- gchar* uri = g_file_get_uri(file);
- ResourceError resourceError("webkit-network-error", ERROR_TRANSPORT, uri, error ? String::fromUTF8(error->message) : String());
- g_free(uri);
- return resourceError;
-}
-
static void cleanupGioOperation(ResourceHandleInternal* d)
{
if (d->m_gfile) {
@@ -710,7 +697,10 @@ static void readCallback(GObject* source, GAsyncResult* res, gpointer)
gssize bytesRead = g_input_stream_read_finish(d->m_inputStream, res, &error);
if (error) {
- ResourceError resourceError = networkErrorForFile(d->m_gfile, error);
+ ResourceError resourceError(g_quark_to_string(G_IO_ERROR),
+ error->code,
+ g_file_get_uri(d->m_gfile),
+ error ? String::fromUTF8(error->message) : String());
g_error_free(error);
cleanupGioOperation(d);
client->didFail(handle.get(), resourceError);
@@ -753,7 +743,11 @@ static void openCallback(GObject* source, GAsyncResult* res, gpointer)
GError *error = 0;
GFileInputStream* in = g_file_read_finish(G_FILE(source), res, &error);
if (error) {
- ResourceError resourceError = networkErrorForFile(d->m_gfile, error);
+ ResourceError resourceError(g_quark_to_string(G_IO_ERROR),
+ error->code,
+ g_file_get_uri(d->m_gfile),
+ error ? String::fromUTF8(error->message) : String());
+
g_error_free(error);
cleanupGioOperation(d);
client->didFail(handle, resourceError);
@@ -800,8 +794,10 @@ static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer)
// server (and then keep track of the fact that we mounted it,
// and set a timeout to unmount it later after it's been idle
// for a while).
-
- ResourceError resourceError = networkErrorForFile(d->m_gfile, error);
+ ResourceError resourceError(g_quark_to_string(G_IO_ERROR),
+ error->code,
+ g_file_get_uri(d->m_gfile),
+ error ? String::fromUTF8(error->message) : String());
g_error_free(error);
cleanupGioOperation(d);
client->didFail(handle, resourceError);
@@ -811,8 +807,10 @@ static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer)
if (g_file_info_get_file_type(info) != G_FILE_TYPE_REGULAR) {
// FIXME: what if the URI points to a directory? Should we
// generate a listing? How? What do other backends do here?
-
- ResourceError resourceError = networkErrorForFile(d->m_gfile, 0);
+ ResourceError resourceError(g_quark_to_string(G_IO_ERROR),
+ G_IO_ERROR_FAILED,
+ g_file_get_uri(d->m_gfile),
+ String());
cleanupGioOperation(d);
client->didFail(handle, resourceError);
return;
@@ -834,7 +832,9 @@ static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer)
bool ResourceHandle::startGio(KURL url)
{
if (request().httpMethod() != "GET" && request().httpMethod() != "POST") {
- ResourceError error("webkit-network-error", ERROR_BAD_NON_HTTP_METHOD, url.string(), request().httpMethod());
+ ResourceError error(g_quark_to_string(SOUP_HTTP_ERROR),
+ SOUP_STATUS_METHOD_NOT_ALLOWED,
+ url.string(), request().httpMethod());
d->client()->didFail(this, error);
return false;
}
@@ -846,12 +846,14 @@ bool ResourceHandle::startGio(KURL url)
url.setQuery(String());
url.setPort(0);
+#if !PLATFORM(WIN_OS)
// we avoid the escaping for local files, because
// g_filename_from_uri (used internally by GFile) has problems
// decoding strings with arbitrary percent signs
if (url.isLocalFile())
d->m_gfile = g_file_new_for_path(url.prettyURL().utf8().data() + sizeof("file://") - 1);
else
+#endif
d->m_gfile = g_file_new_for_uri(url.string().utf8().data());
g_object_set_data(G_OBJECT(d->m_gfile), "webkit-resource", this);
d->m_cancellable = g_cancellable_new();
diff --git a/WebCore/platform/network/soup/ResourceRequest.h b/WebCore/platform/network/soup/ResourceRequest.h
index efb1240..82b4eb9 100644
--- a/WebCore/platform/network/soup/ResourceRequest.h
+++ b/WebCore/platform/network/soup/ResourceRequest.h
@@ -29,6 +29,8 @@
#include "ResourceRequestBase.h"
+#include <libsoup/soup.h>
+
namespace WebCore {
struct ResourceRequest : ResourceRequestBase {
@@ -54,11 +56,20 @@ namespace WebCore {
{
}
+ ResourceRequest(SoupMessage* soupMessage)
+ : ResourceRequestBase(KURL(), UseProtocolCachePolicy)
+ {
+ updateFromSoupMessage(soupMessage);
+ }
+
+ SoupMessage* toSoupMessage() const;
+ void updateFromSoupMessage(SoupMessage* soupMessage);
+
private:
- friend class ResourceRequestBase;
+ friend struct ResourceRequestBase;
- void doUpdatePlatformRequest() {}
- void doUpdateResourceRequest() {}
+ void doUpdatePlatformRequest() {};
+ void doUpdateResourceRequest() {};
};
} // namespace WebCore
diff --git a/WebCore/platform/network/soup/ResourceRequestSoup.cpp b/WebCore/platform/network/soup/ResourceRequestSoup.cpp
new file mode 100644
index 0000000..f2011bb
--- /dev/null
+++ b/WebCore/platform/network/soup/ResourceRequestSoup.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2009 Gustavo Noronha Silva
+ *
+ * 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; 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 "ResourceRequest.h"
+
+#include "CString.h"
+#include "GOwnPtr.h"
+#include "PlatformString.h"
+
+#include <libsoup/soup.h>
+
+using namespace std;
+
+namespace WebCore {
+
+SoupMessage* ResourceRequest::toSoupMessage() const
+{
+ SoupMessage* soupMessage = soup_message_new(httpMethod().utf8().data(), url().string().utf8().data());
+ if (!soupMessage)
+ return 0;
+
+ HTTPHeaderMap headers = httpHeaderFields();
+ SoupMessageHeaders* soupHeaders = soupMessage->request_headers;
+ if (!headers.isEmpty()) {
+ HTTPHeaderMap::const_iterator end = headers.end();
+ for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it)
+ soup_message_headers_append(soupHeaders, it->first.string().utf8().data(), it->second.utf8().data());
+ }
+
+ // Body data is only handled at ResourceHandleSoup::startHttp for
+ // now; this is because this may not be a good place to go
+ // openning and mmapping files. We should maybe revisit this.
+ return soupMessage;
+}
+
+void ResourceRequest::updateFromSoupMessage(SoupMessage* soupMessage)
+{
+ SoupURI* soupURI = soup_message_get_uri(soupMessage);
+ GOwnPtr<gchar> uri(soup_uri_to_string(soupURI, FALSE));
+ m_url = KURL(KURL(), String::fromUTF8(uri.get()));
+
+ m_httpMethod = String::fromUTF8(soupMessage->method);
+
+ SoupMessageHeadersIter headersIter;
+ const char* headerName;
+ const char* headerValue;
+
+ soup_message_headers_iter_init(&headersIter, soupMessage->request_headers);
+ while (soup_message_headers_iter_next(&headersIter, &headerName, &headerValue))
+ m_httpHeaderFields.set(String::fromUTF8(headerName), String::fromUTF8(headerValue));
+
+ m_httpBody = FormData::create(soupMessage->request_body->data, soupMessage->request_body->length);
+
+ // FIXME: m_allowHTTPCookies and m_firstPartyForCookies should
+ // probably be handled here and on doUpdatePlatformRequest
+ // somehow.
+}
+
+}
diff --git a/WebCore/platform/network/win/CookieJarCFNetWin.cpp b/WebCore/platform/network/win/CookieJarCFNetWin.cpp
index 7e64813..af9e3f3 100644
--- a/WebCore/platform/network/win/CookieJarCFNetWin.cpp
+++ b/WebCore/platform/network/win/CookieJarCFNetWin.cpp
@@ -63,7 +63,7 @@ static RetainPtr<CFArrayRef> filterCookies(CFArrayRef unfilteredCookies)
return filteredCookies;
}
-void setCookies(Document* /*document*/, const KURL& url, const KURL& policyURL, const String& value)
+void setCookies(Document* document, const KURL& url, const String& value)
{
// <rdar://problem/5632883> CFHTTPCookieStorage stores an empty cookie, which would be sent as "Cookie: =".
if (value.isEmpty())
@@ -74,7 +74,7 @@ void setCookies(Document* /*document*/, const KURL& url, const KURL& policyURL,
return;
RetainPtr<CFURLRef> urlCF(AdoptCF, url.createCFURL());
- RetainPtr<CFURLRef> policyURLCF(AdoptCF, policyURL.createCFURL());
+ RetainPtr<CFURLRef> firstPartyForCookiesCF(AdoptCF, document->firstPartyForCookies().createCFURL());
// <http://bugs.webkit.org/show_bug.cgi?id=6531>, <rdar://4409034>
// cookiesWithResponseHeaderFields doesn't parse cookies without a value
@@ -88,7 +88,7 @@ void setCookies(Document* /*document*/, const KURL& url, const KURL& policyURL,
RetainPtr<CFArrayRef> cookiesCF(AdoptCF, CFHTTPCookieCreateWithResponseHeaderFields(kCFAllocatorDefault,
headerFieldsCF.get(), urlCF.get()));
- CFHTTPCookieStorageSetCookies(cookieStorage, filterCookies(cookiesCF.get()).get(), urlCF.get(), policyURLCF.get());
+ CFHTTPCookieStorageSetCookies(cookieStorage, filterCookies(cookiesCF.get()).get(), urlCF.get(), firstPartyForCookiesCF.get());
}
String cookies(const Document* /*document*/, const KURL& url)
diff --git a/WebCore/platform/network/win/CookieJarWin.cpp b/WebCore/platform/network/win/CookieJarWin.cpp
index cdafb1b..41d12d9 100644
--- a/WebCore/platform/network/win/CookieJarWin.cpp
+++ b/WebCore/platform/network/win/CookieJarWin.cpp
@@ -36,9 +36,9 @@
namespace WebCore {
-void setCookies(Document* /*document*/, const KURL& url, const KURL& policyURL, const String& value)
+void setCookies(Document* /*document*/, const KURL& url, const String& value)
{
- // FIXME: Deal with the policy URL.
+ // FIXME: Deal with document->firstPartyForCookies().
String str = url.string();
String val = value;
InternetSetCookie(str.charactersWithNullTermination(), 0, val.charactersWithNullTermination());
diff --git a/WebCore/platform/posix/FileSystemPOSIX.cpp b/WebCore/platform/posix/FileSystemPOSIX.cpp
index c1bef60..e55b8a4 100644
--- a/WebCore/platform/posix/FileSystemPOSIX.cpp
+++ b/WebCore/platform/posix/FileSystemPOSIX.cpp
@@ -30,7 +30,6 @@
#include "FileSystem.h"
#include "CString.h"
-#include "NotImplemented.h"
#include "PlatformString.h"
#include <sys/stat.h>
diff --git a/WebCore/platform/qt/ContextMenuQt.cpp b/WebCore/platform/qt/ContextMenuQt.cpp
index 3e093b1..063a46b 100644
--- a/WebCore/platform/qt/ContextMenuQt.cpp
+++ b/WebCore/platform/qt/ContextMenuQt.cpp
@@ -26,7 +26,6 @@
#include "config.h"
#include "ContextMenu.h"
-#include "MenuEventProxy.h"
#include <wtf/Assertions.h>
diff --git a/WebCore/platform/qt/CookieJarQt.cpp b/WebCore/platform/qt/CookieJarQt.cpp
index 4077407..40d9309 100644
--- a/WebCore/platform/qt/CookieJarQt.cpp
+++ b/WebCore/platform/qt/CookieJarQt.cpp
@@ -28,11 +28,11 @@
#include "config.h"
#include "CookieJar.h"
+#include "Document.h"
#include "KURL.h"
#include "PlatformString.h"
#if QT_VERSION >= 0x040400
-#include "Document.h"
#include "qwebpage.h"
#include "qwebframe.h"
#include "FrameLoaderClientQt.h"
@@ -61,10 +61,10 @@ static QNetworkCookieJar *cookieJar(const Document *document)
}
#endif
-void setCookies(Document* document, const KURL& url, const KURL& policyURL, const String& value)
+void setCookies(Document* document, const KURL& url, const String& value)
{
QUrl u(url);
- QUrl p(policyURL);
+ QUrl p(document->firstPartyForCookies());
#if QT_VERSION >= 0x040400
QNetworkCookieJar* jar = cookieJar(document);
if (!jar)
diff --git a/WebCore/platform/qt/DragDataQt.cpp b/WebCore/platform/qt/DragDataQt.cpp
index 9d95373..bc5cce1 100644
--- a/WebCore/platform/qt/DragDataQt.cpp
+++ b/WebCore/platform/qt/DragDataQt.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,7 +30,6 @@
#include "Document.h"
#include "DocumentFragment.h"
#include "markup.h"
-#include "NotImplemented.h"
#include <QList>
#include <QMimeData>
@@ -126,6 +125,10 @@ String DragData::asURL(String* title) const
if (!m_platformDragData)
return String();
QList<QUrl> urls = m_platformDragData->urls();
+
+ if (urls.isEmpty())
+ return String();
+
return urls.first().toString();
}
diff --git a/WebCore/platform/qt/FileSystemQt.cpp b/WebCore/platform/qt/FileSystemQt.cpp
index 8a272c1..a17f3ab 100644
--- a/WebCore/platform/qt/FileSystemQt.cpp
+++ b/WebCore/platform/qt/FileSystemQt.cpp
@@ -33,7 +33,6 @@
#include "FileSystem.h"
#include "CString.h"
-#include "NotImplemented.h"
#include "PlatformString.h"
#include <QDateTime>
diff --git a/WebCore/platform/qt/Localizations.cpp b/WebCore/platform/qt/Localizations.cpp
index cb805f9..a6c7513 100644
--- a/WebCore/platform/qt/Localizations.cpp
+++ b/WebCore/platform/qt/Localizations.cpp
@@ -30,7 +30,6 @@
#include "IntSize.h"
#include "LocalizedStrings.h"
-#include "NotImplemented.h"
#include "PlatformString.h"
#include <QCoreApplication>
@@ -245,12 +244,12 @@ String contextMenuItemTagDefaultDirection()
String contextMenuItemTagLeftToRight()
{
- return QCoreApplication::translate("QWebPage", "LTR", "Left to Right context menu item");
+ return QCoreApplication::translate("QWebPage", "Left to Right", "Left to Right context menu item");
}
String contextMenuItemTagRightToLeft()
{
- return QCoreApplication::translate("QWebPage", "RTL", "Right to Left context menu item");
+ return QCoreApplication::translate("QWebPage", "Right to Left", "Right to Left context menu item");
}
String contextMenuItemTagInspectElement()
diff --git a/WebCore/platform/qt/MenuEventProxy.h b/WebCore/platform/qt/MenuEventProxy.h
deleted file mode 100644
index 658d1ee..0000000
--- a/WebCore/platform/qt/MenuEventProxy.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2007 Staikos Computing Services Inc. <info@staikos.net>
- *
- * 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 MENUEVENTPROXY_H
-#define MENUEVENTPROXY_H
-
-#include "Platform.h"
-#include <qobject.h>
-#include <qmap.h>
-#include "ContextMenu.h"
-#include "ContextMenuItem.h"
-#include "ContextMenuController.h"
-
-namespace WebCore {
-class MenuEventProxy : public QObject {
- Q_OBJECT
- public:
- MenuEventProxy(WebCore::ContextMenu *m) : m_m(m) {}
- ~MenuEventProxy() {}
-
- void map(QAction* action, unsigned actionTag) { _map[action] = actionTag; }
-
- public slots:
- void trigger(QAction *action) {
- WebCore::ContextMenuItem item(WebCore::ActionType, static_cast<WebCore::ContextMenuAction>(_map[action]), WebCore::String());
- m_m->controller()->contextMenuItemSelected(&item);
- }
-
- private:
- WebCore::ContextMenu *m_m;
- QMap<QAction*, unsigned> _map;
-};
-
-}
-
-#endif
-// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/qt/PopupMenuQt.cpp b/WebCore/platform/qt/PopupMenuQt.cpp
index 76728fa..a7d6643 100644
--- a/WebCore/platform/qt/PopupMenuQt.cpp
+++ b/WebCore/platform/qt/PopupMenuQt.cpp
@@ -30,7 +30,6 @@
#include "FrameView.h"
#include "HostWindow.h"
#include "PopupMenuClient.h"
-#include "NotImplemented.h"
#include "QWebPopup.h"
#include <QAction>
diff --git a/WebCore/platform/qt/QWebPopup.cpp b/WebCore/platform/qt/QWebPopup.cpp
index 4d57c9b..f437c27 100644
--- a/WebCore/platform/qt/QWebPopup.cpp
+++ b/WebCore/platform/qt/QWebPopup.cpp
@@ -82,4 +82,6 @@ void QWebPopup::activeChanged(int index)
m_client->valueChanged(index);
}
-}
+} // namespace WebCore
+
+#include "moc_QWebPopup.cpp"
diff --git a/WebCore/platform/qt/RenderThemeQt.cpp b/WebCore/platform/qt/RenderThemeQt.cpp
index 942e95b..b16cbc4 100644
--- a/WebCore/platform/qt/RenderThemeQt.cpp
+++ b/WebCore/platform/qt/RenderThemeQt.cpp
@@ -41,6 +41,7 @@
#include <QWidget>
#include <QPainter>
#include <QPushButton>
+#include <QLineEdit>
#include <QStyleFactory>
#include <QStyleOptionButton>
#include <QStyleOptionFrameV2>
@@ -124,6 +125,12 @@ RenderThemeQt::RenderThemeQt()
#endif
m_fallbackStyle = 0;
+
+ // this will need to be regenerated when the style changes
+ QLineEdit lineEdit;
+ QStyleOptionFrameV2 opt;
+ m_frameLineWidth = QApplication::style()->pixelMetric(QStyle::PM_DefaultFrameWidth,
+ &opt, &lineEdit);
}
RenderThemeQt::~RenderThemeQt()
@@ -272,7 +279,7 @@ int RenderThemeQt::minimumMenuListSize(RenderStyle*) const
return 7 * fm.width(QLatin1Char('x'));
}
-static void computeSizeBasedOnStyle(RenderStyle* renderStyle)
+void RenderThemeQt::computeSizeBasedOnStyle(RenderStyle* renderStyle) const
{
// If the width and height are both specified, then we have nothing to do.
if (!renderStyle->width().isIntrinsicOrAuto() && !renderStyle->height().isAuto())
@@ -339,13 +346,15 @@ static void computeSizeBasedOnStyle(RenderStyle* renderStyle)
int h = qMax(fm.lineSpacing(), 14) + 2*verticalMargin;
int w = fm.width(QLatin1Char('x')) * 17 + 2*horizontalMargin;
QStyleOptionFrameV2 opt;
- opt.lineWidth = applicationStyle->pixelMetric(QStyle::PM_DefaultFrameWidth,
- &opt, 0);
+ opt.lineWidth = m_frameLineWidth;
QSize sz = applicationStyle->sizeFromContents(QStyle::CT_LineEdit,
- &opt,
- QSize(w, h).expandedTo(QApplication::globalStrut()),
- 0);
+ &opt,
+ QSize(w, h).expandedTo(QApplication::globalStrut()),
+ 0);
size.setHeight(sz.height());
+
+ renderStyle->setPaddingLeft(Length(opt.lineWidth, Fixed));
+ renderStyle->setPaddingRight(Length(opt.lineWidth, Fixed));
break;
}
default:
@@ -486,6 +495,9 @@ void RenderThemeQt::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style,
{
style->setBackgroundColor(Color::transparent);
style->setColor(QApplication::palette().text().color());
+ style->resetBorder();
+ style->resetPadding();
+ computeSizeBasedOnStyle(style);
}
bool RenderThemeQt::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
@@ -499,7 +511,7 @@ bool RenderThemeQt::paintTextField(RenderObject* o, const RenderObject::PaintInf
panel.initFrom(p.widget);
panel.rect = r;
- panel.lineWidth = p.style->pixelMetric(QStyle::PM_DefaultFrameWidth, &panel, p.widget);
+ panel.lineWidth = m_frameLineWidth;
panel.state |= QStyle::State_Sunken;
panel.features = QStyleOptionFrameV2::None;
@@ -729,6 +741,10 @@ ControlPart RenderThemeQt::applyTheme(QStyleOption& option, RenderObject* o) con
if (isHovered(o))
option.state |= QStyle::State_MouseOver;
+ option.direction = Qt::LeftToRight;
+ if (o->style() && o->style()->direction() == WebCore::RTL)
+ option.direction = Qt::RightToLeft;
+
ControlPart result = o->style()->appearance();
switch (result) {
diff --git a/WebCore/platform/qt/RenderThemeQt.h b/WebCore/platform/qt/RenderThemeQt.h
index b4a5064..5c78a72 100644
--- a/WebCore/platform/qt/RenderThemeQt.h
+++ b/WebCore/platform/qt/RenderThemeQt.h
@@ -128,6 +128,7 @@ private:
void paintMediaBackground(QPainter* painter, const IntRect& r) const;
QColor getMediaControlForegroundColor(RenderObject* o = 0) const;
#endif
+ void computeSizeBasedOnStyle(RenderStyle* renderStyle) const;
private:
bool supportsFocus(ControlPart) const;
@@ -144,6 +145,8 @@ private:
QStyle* m_fallbackStyle;
QStyle* fallbackStyle();
+
+ int m_frameLineWidth;
};
class StylePainter
diff --git a/WebCore/platform/qt/ScrollViewQt.cpp b/WebCore/platform/qt/ScrollViewQt.cpp
index 76d9f01..48885d3 100644
--- a/WebCore/platform/qt/ScrollViewQt.cpp
+++ b/WebCore/platform/qt/ScrollViewQt.cpp
@@ -36,27 +36,33 @@ namespace WebCore {
void ScrollView::platformInit()
{
- m_widgetsThatPreventBlitting = 0;
+ m_widgetsPreventingBlitting = 0;
}
void ScrollView::platformDestroy()
{
}
-void ScrollView::platformAddChild(Widget* child)
+// Windowed plugins are using native windows and are thus preventing
+// us from doing any kind of scrolling optimization.
+
+void ScrollView::adjustWidgetsPreventingBlittingCount(int delta)
{
- root()->m_widgetsThatPreventBlitting++;
+ m_widgetsPreventingBlitting += delta;
if (parent())
- parent()->platformAddChild(child);
+ parent()->adjustWidgetsPreventingBlittingCount(delta);
+}
+
+void ScrollView::platformAddChild(Widget* child)
+{
+ adjustWidgetsPreventingBlittingCount(1);
}
void ScrollView::platformRemoveChild(Widget* child)
{
- ASSERT(root()->m_widgetsThatPreventBlitting);
- root()->m_widgetsThatPreventBlitting--;
child->hide();
+ adjustWidgetsPreventingBlittingCount(-1);
}
}
-
// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/qt/TemporaryLinkStubs.cpp b/WebCore/platform/qt/TemporaryLinkStubs.cpp
index ff0b27d..f76eb43 100644
--- a/WebCore/platform/qt/TemporaryLinkStubs.cpp
+++ b/WebCore/platform/qt/TemporaryLinkStubs.cpp
@@ -74,39 +74,6 @@
using namespace WebCore;
-#if (!defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC32)) || defined(Q_OS_WINCE)
-
-bool PluginPackage::fetchInfo() { notImplemented(); return false; }
-unsigned PluginPackage::hash() const { notImplemented(); return 0; }
-bool PluginPackage::equal(const PluginPackage&, const PluginPackage&) { notImplemented(); return false; }
-int PluginPackage::compareFileVersion(const PlatformModuleVersion&) const { notImplemented(); return -1; }
-
-void PluginView::setNPWindowRect(const IntRect&) { notImplemented(); }
-const char* PluginView::userAgent() { notImplemented(); return 0; }
-#if ENABLE(NETSCAPE_PLUGIN_API)
-const char* PluginView::userAgentStatic() { notImplemented(); return 0; }
-#endif
-void PluginView::invalidateRect(NPRect*) { notImplemented(); }
-void PluginView::invalidateRect(const IntRect&) { notImplemented(); }
-void PluginView::invalidateRegion(NPRegion) { notImplemented(); }
-void PluginView::forceRedraw() { notImplemented(); }
-void PluginView::setFocus() { Widget::setFocus(); }
-void PluginView::show() { Widget::show(); }
-void PluginView::hide() { Widget::hide(); }
-void PluginView::paint(GraphicsContext*, const IntRect&) { notImplemented(); }
-void PluginView::setParent(ScrollView* view) { Widget::setParent(view); }
-void PluginView::setParentVisible(bool) { notImplemented(); }
-void PluginView::updatePluginWidget() { notImplemented(); }
-void PluginView::handleKeyboardEvent(KeyboardEvent*) { notImplemented(); }
-void PluginView::handleMouseEvent(MouseEvent*) { notImplemented(); }
-NPError PluginView::handlePostReadFile(Vector<char>&, uint32, const char*) { notImplemented(); return NPERR_GENERIC_ERROR; }
-NPError PluginView::getValue(NPNVariable, void*) { notImplemented(); return NPERR_GENERIC_ERROR; }
-#if ENABLE(NETSCAPE_PLUGIN_API)
-NPError PluginView::getValueStatic(NPNVariable, void*) { return NPERR_GENERIC_ERROR; }
-#endif
-PluginView::~PluginView() {}
-#endif
-
#if defined(Q_OS_WINCE)
Vector<String> PluginDatabase::defaultPluginDirectories() { notImplemented(); return Vector<String>(); }
void PluginDatabase::getPluginPathsInDirectories(HashSet<String>& paths) const { notImplemented(); }
diff --git a/WebCore/platform/text/AtomicString.cpp b/WebCore/platform/text/AtomicString.cpp
index d85f5ee..409439e 100644
--- a/WebCore/platform/text/AtomicString.cpp
+++ b/WebCore/platform/text/AtomicString.cpp
@@ -206,7 +206,7 @@ PassRefPtr<StringImpl> AtomicString::add(const UChar* s)
PassRefPtr<StringImpl> AtomicString::add(StringImpl* r)
{
- if (!r || r->m_inTable)
+ if (!r || r->inTable())
return r;
if (r->length() == 0)
@@ -214,7 +214,7 @@ PassRefPtr<StringImpl> AtomicString::add(StringImpl* r)
StringImpl* result = *stringTable().add(r).first;
if (result == r)
- r->m_inTable = true;
+ r->setInTable();
return result;
}
diff --git a/WebCore/platform/text/AtomicString.h b/WebCore/platform/text/AtomicString.h
index f4efab9..3307a2d 100644
--- a/WebCore/platform/text/AtomicString.h
+++ b/WebCore/platform/text/AtomicString.h
@@ -67,17 +67,21 @@ public:
UChar operator[](unsigned int i) const { return m_string[i]; }
bool contains(UChar c) const { return m_string.contains(c); }
- bool contains(const AtomicString& s, bool caseSensitive = true) const
- { return m_string.contains(s.string(), caseSensitive); }
+ bool contains(const char* s, bool caseSensitive = true) const
+ { return m_string.contains(s, caseSensitive); }
+ bool contains(const String& s, bool caseSensitive = true) const
+ { return m_string.contains(s, caseSensitive); }
int find(UChar c, int start = 0) const { return m_string.find(c, start); }
- int find(const AtomicString& s, int start = 0, bool caseSentitive = true) const
- { return m_string.find(s.string(), start, caseSentitive); }
+ int find(const char* s, int start = 0, bool caseSentitive = true) const
+ { return m_string.find(s, start, caseSentitive); }
+ int find(const String& s, int start = 0, bool caseSentitive = true) const
+ { return m_string.find(s, start, caseSentitive); }
- bool startsWith(const AtomicString& s, bool caseSensitive = true) const
- { return m_string.startsWith(s.string(), caseSensitive); }
- bool endsWith(const AtomicString& s, bool caseSensitive = true) const
- { return m_string.endsWith(s.string(), caseSensitive); }
+ bool startsWith(const String& s, bool caseSensitive = true) const
+ { return m_string.startsWith(s, caseSensitive); }
+ bool endsWith(const String& s, bool caseSensitive = true) const
+ { return m_string.endsWith(s, caseSensitive); }
int toInt(bool* ok = 0) const { return m_string.toInt(ok); }
double toDouble(bool* ok = 0) const { return m_string.toDouble(ok); }
diff --git a/WebCore/platform/text/BidiContext.cpp b/WebCore/platform/text/BidiContext.cpp
index ef3c225..546571e 100644
--- a/WebCore/platform/text/BidiContext.cpp
+++ b/WebCore/platform/text/BidiContext.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2003, 2004, 2006, 2007 Apple Inc. All right reserved.
+ * Copyright (C) 2003, 2004, 2006, 2007, 2009 Apple Inc. All right reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -22,8 +22,37 @@
#include "config.h"
#include "BidiContext.h"
+#include <wtf/StdLibExtras.h>
+
namespace WebCore {
+using namespace WTF::Unicode;
+
+PassRefPtr<BidiContext> BidiContext::create(unsigned char level, Direction direction, bool override, BidiContext* parent)
+{
+ ASSERT(direction == level % 2 ? RightToLeft : LeftToRight);
+
+ if (parent)
+ return adoptRef(new BidiContext(level, direction, override, parent));
+
+ ASSERT(level <= 1);
+ if (!level) {
+ DEFINE_STATIC_LOCAL(BidiContext, ltrContext, (0, LeftToRight, false, 0));
+ if (!override)
+ return &ltrContext;
+
+ DEFINE_STATIC_LOCAL(BidiContext, ltrOverrideContext, (0, LeftToRight, true, 0));
+ return &ltrOverrideContext;
+ }
+
+ DEFINE_STATIC_LOCAL(BidiContext, rtlContext, (1, RightToLeft, false, 0));
+ if (!override)
+ return &rtlContext;
+
+ DEFINE_STATIC_LOCAL(BidiContext, rtlOverrideContext, (1, RightToLeft, true, 0));
+ return &rtlOverrideContext;
+}
+
bool operator==(const BidiContext& c1, const BidiContext& c2)
{
if (&c1 == &c2)
diff --git a/WebCore/platform/text/BidiContext.h b/WebCore/platform/text/BidiContext.h
index 89123c8..8791605 100644
--- a/WebCore/platform/text/BidiContext.h
+++ b/WebCore/platform/text/BidiContext.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2003, 2004, 2006, 2007 Apple Inc. All right reserved.
+ * Copyright (C) 2003, 2004, 2006, 2007, 2009 Apple Inc. All right reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -23,31 +23,17 @@
#define BidiContext_h
#include <wtf/Assertions.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
#include <wtf/unicode/Unicode.h>
namespace WebCore {
// Used to keep track of explicit embeddings.
-class BidiContext {
+class BidiContext : public RefCounted<BidiContext> {
public:
- BidiContext(unsigned char level, WTF::Unicode::Direction direction, bool override = false, BidiContext* parent = 0)
- : m_level(level)
- , m_direction(direction)
- , m_override(override)
- , m_parent(parent)
- , m_refCount(0)
- {
- ASSERT(direction == WTF::Unicode::LeftToRight || direction == WTF::Unicode::RightToLeft);
- }
-
- void ref() const { m_refCount++; }
- void deref() const
- {
- m_refCount--;
- if (m_refCount <= 0)
- delete this;
- }
+ static PassRefPtr<BidiContext> create(unsigned char level, WTF::Unicode::Direction direction, bool override = false, BidiContext* parent = 0);
BidiContext* parent() const { return m_parent.get(); }
unsigned char level() const { return m_level; }
@@ -55,11 +41,18 @@ public:
bool override() const { return m_override; }
private:
+ BidiContext(unsigned char level, WTF::Unicode::Direction direction, bool override, BidiContext* parent)
+ : m_level(level)
+ , m_direction(direction)
+ , m_override(override)
+ , m_parent(parent)
+ {
+ }
+
unsigned char m_level;
unsigned m_direction : 5; // Direction
bool m_override : 1;
RefPtr<BidiContext> m_parent;
- mutable int m_refCount;
};
bool operator==(const BidiContext&, const BidiContext&);
diff --git a/WebCore/platform/text/BidiResolver.h b/WebCore/platform/text/BidiResolver.h
index 8288be4..b6c2e88 100644
--- a/WebCore/platform/text/BidiResolver.h
+++ b/WebCore/platform/text/BidiResolver.h
@@ -402,7 +402,7 @@ void BidiResolver<Iterator, Run>::commitExplicitEmbedding()
level &= ~1;
}
if (level < 61)
- toContext = new BidiContext(level, direction, override, toContext.get());
+ toContext = BidiContext::create(level, direction, override, toContext.get());
}
}
diff --git a/WebCore/platform/text/CharacterNames.h b/WebCore/platform/text/CharacterNames.h
index f589a6c..5b1a337 100644
--- a/WebCore/platform/text/CharacterNames.h
+++ b/WebCore/platform/text/CharacterNames.h
@@ -37,6 +37,7 @@ namespace WebCore {
const UChar blackSquare = 0x25A0;
const UChar bullet = 0x2022;
+ const UChar hebrewPunctuationGershayim = 0x05F4;
const UChar horizontalEllipsis = 0x2026;
const UChar ideographicSpace = 0x3000;
const UChar ideographicComma = 0x3001;
@@ -49,6 +50,7 @@ namespace WebCore {
const UChar objectReplacementCharacter = 0xFFFC;
const UChar popDirectionalFormatting = 0x202C;
const UChar replacementCharacter = 0xFFFD;
+ const UChar rightSingleQuotationMark = 0x2019;
const UChar rightToLeftMark = 0x200F;
const UChar rightToLeftEmbed = 0x202B;
const UChar rightToLeftOverride = 0x202E;
diff --git a/WebCore/platform/text/PlatformString.h b/WebCore/platform/text/PlatformString.h
index a1541d2..1cc60b2 100644
--- a/WebCore/platform/text/PlatformString.h
+++ b/WebCore/platform/text/PlatformString.h
@@ -162,6 +162,11 @@ public:
static String format(const char *, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
+ // Returns an uninitialized string. The characters needs to be written
+ // into the buffer returned in data before the returned string is used.
+ // Failure to do this will have unpredictable results.
+ static String createUninitialized(unsigned length, UChar*& data) { return StringImpl::createUninitialized(length, data); }
+
void split(const String& separator, Vector<String>& result) const;
void split(const String& separator, bool allowEmptyEntries, Vector<String>& result) const;
void split(UChar separator, Vector<String>& result) const;
diff --git a/WebCore/platform/text/String.cpp b/WebCore/platform/text/String.cpp
index 733b661..cd87e2c 100644
--- a/WebCore/platform/text/String.cpp
+++ b/WebCore/platform/text/String.cpp
@@ -85,10 +85,12 @@ void String::append(const String& str)
// call to fastMalloc every single time.
if (str.m_impl) {
if (m_impl) {
- StringBuffer buffer(m_impl->length() + str.length());
- memcpy(buffer.characters(), m_impl->characters(), m_impl->length() * sizeof(UChar));
- memcpy(buffer.characters() + m_impl->length(), str.characters(), str.length() * sizeof(UChar));
- m_impl = StringImpl::adopt(buffer);
+ UChar* data;
+ RefPtr<StringImpl> newImpl =
+ StringImpl::createUninitialized(m_impl->length() + str.length(), data);
+ memcpy(data, m_impl->characters(), m_impl->length() * sizeof(UChar));
+ memcpy(data + m_impl->length(), str.characters(), str.length() * sizeof(UChar));
+ m_impl = newImpl.release();
} else
m_impl = str.m_impl;
}
@@ -101,10 +103,12 @@ void String::append(char c)
// one String is pointing at this StringImpl, but even then it's going to require a
// call to fastMalloc every single time.
if (m_impl) {
- StringBuffer buffer(m_impl->length() + 1);
- memcpy(buffer.characters(), m_impl->characters(), m_impl->length() * sizeof(UChar));
- buffer[m_impl->length()] = c;
- m_impl = StringImpl::adopt(buffer);
+ UChar* data;
+ RefPtr<StringImpl> newImpl =
+ StringImpl::createUninitialized(m_impl->length() + 1, data);
+ memcpy(data, m_impl->characters(), m_impl->length() * sizeof(UChar));
+ data[m_impl->length()] = c;
+ m_impl = newImpl.release();
} else
m_impl = StringImpl::create(&c, 1);
}
@@ -116,10 +120,12 @@ void String::append(UChar c)
// one String is pointing at this StringImpl, but even then it's going to require a
// call to fastMalloc every single time.
if (m_impl) {
- StringBuffer buffer(m_impl->length() + 1);
- memcpy(buffer.characters(), m_impl->characters(), m_impl->length() * sizeof(UChar));
- buffer[m_impl->length()] = c;
- m_impl = StringImpl::adopt(buffer);
+ UChar* data;
+ RefPtr<StringImpl> newImpl =
+ StringImpl::createUninitialized(m_impl->length() + 1, data);
+ memcpy(data, m_impl->characters(), m_impl->length() * sizeof(UChar));
+ data[m_impl->length()] = c;
+ m_impl = newImpl.release();
} else
m_impl = StringImpl::create(&c, 1);
}
@@ -170,10 +176,12 @@ void String::append(const UChar* charactersToAppend, unsigned lengthToAppend)
return;
ASSERT(charactersToAppend);
- StringBuffer buffer(length() + lengthToAppend);
- memcpy(buffer.characters(), characters(), length() * sizeof(UChar));
- memcpy(buffer.characters() + length(), charactersToAppend, lengthToAppend * sizeof(UChar));
- m_impl = StringImpl::adopt(buffer);
+ UChar* data;
+ RefPtr<StringImpl> newImpl =
+ StringImpl::createUninitialized(length() + lengthToAppend, data);
+ memcpy(data, characters(), length() * sizeof(UChar));
+ memcpy(data + length(), charactersToAppend, lengthToAppend * sizeof(UChar));
+ m_impl = newImpl.release();
}
void String::insert(const UChar* charactersToInsert, unsigned lengthToInsert, unsigned position)
@@ -189,11 +197,13 @@ void String::insert(const UChar* charactersToInsert, unsigned lengthToInsert, un
return;
ASSERT(charactersToInsert);
- StringBuffer buffer(length() + lengthToInsert);
- memcpy(buffer.characters(), characters(), position * sizeof(UChar));
- memcpy(buffer.characters() + position, charactersToInsert, lengthToInsert * sizeof(UChar));
- memcpy(buffer.characters() + position + lengthToInsert, characters() + position, (length() - position) * sizeof(UChar));
- m_impl = StringImpl::adopt(buffer);
+ UChar* data;
+ RefPtr<StringImpl> newImpl =
+ StringImpl::createUninitialized(length() + lengthToInsert, data);
+ memcpy(data, characters(), position * sizeof(UChar));
+ memcpy(data + position, charactersToInsert, lengthToInsert * sizeof(UChar));
+ memcpy(data + position + lengthToInsert, characters() + position, (length() - position) * sizeof(UChar));
+ m_impl = newImpl.release();
}
UChar String::operator[](unsigned i) const
@@ -221,9 +231,10 @@ void String::truncate(unsigned position)
{
if (position >= length())
return;
- StringBuffer buffer(position);
- memcpy(buffer.characters(), characters(), position * sizeof(UChar));
- m_impl = StringImpl::adopt(buffer);
+ UChar* data;
+ RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(position, data);
+ memcpy(data, characters(), position * sizeof(UChar));
+ m_impl = newImpl.release();
}
void String::remove(unsigned position, int lengthToRemove)
@@ -234,11 +245,13 @@ void String::remove(unsigned position, int lengthToRemove)
return;
if (static_cast<unsigned>(lengthToRemove) > length() - position)
lengthToRemove = length() - position;
- StringBuffer buffer(length() - lengthToRemove);
- memcpy(buffer.characters(), characters(), position * sizeof(UChar));
- memcpy(buffer.characters() + position, characters() + position + lengthToRemove,
+ UChar* data;
+ RefPtr<StringImpl> newImpl =
+ StringImpl::createUninitialized(length() - lengthToRemove, data);
+ memcpy(data, characters(), position * sizeof(UChar));
+ memcpy(data + position, characters() + position + lengthToRemove,
(length() - lengthToRemove - position) * sizeof(UChar));
- m_impl = StringImpl::adopt(buffer);
+ m_impl = newImpl.release();
}
String String::substring(unsigned pos, unsigned len) const
@@ -637,21 +650,21 @@ String::String(const Identifier& str)
{
if (str.isNull())
return;
- m_impl = StringImpl::create(str.data(), str.size());
+ m_impl = StringImpl::create(str.ustring());
}
String::String(const UString& str)
{
if (str.isNull())
return;
- m_impl = StringImpl::create(str.data(), str.size());
+ m_impl = StringImpl::create(str);
}
String::operator UString() const
{
if (!m_impl)
return UString();
- return UString(m_impl->characters(), m_impl->length());
+ return m_impl->ustring();
}
#endif
diff --git a/WebCore/platform/text/StringBuilder.cpp b/WebCore/platform/text/StringBuilder.cpp
index 0e9555c..c21e366 100644
--- a/WebCore/platform/text/StringBuilder.cpp
+++ b/WebCore/platform/text/StringBuilder.cpp
@@ -79,9 +79,10 @@ String StringBuilder::toString() const
if (count == 1)
return m_strings[0];
- StringBuffer buffer(m_totalLength);
+ UChar* buffer;
+ String result = String::createUninitialized(m_totalLength, buffer);
- UChar* p = buffer.characters();
+ UChar* p = buffer;
for (unsigned i = 0; i < count; ++i) {
StringImpl* string = m_strings[i].impl();
unsigned length = string->length();
@@ -89,9 +90,9 @@ String StringBuilder::toString() const
p += length;
}
- ASSERT(p == m_totalLength + buffer.characters());
+ ASSERT(p == m_totalLength + buffer);
- return String::adopt(buffer);
+ return result;
}
}
diff --git a/WebCore/platform/text/StringImpl.cpp b/WebCore/platform/text/StringImpl.cpp
index 6bba990..8bc4dde 100644
--- a/WebCore/platform/text/StringImpl.cpp
+++ b/WebCore/platform/text/StringImpl.cpp
@@ -44,6 +44,8 @@ using namespace Unicode;
namespace WebCore {
+static const unsigned minLengthToShare = 20;
+
static inline UChar* newUCharVector(unsigned n)
{
return static_cast<UChar*>(fastMalloc(sizeof(UChar) * n));
@@ -80,8 +82,6 @@ StringImpl::StringImpl()
: m_length(0)
, m_data(0)
, m_hash(0)
- , m_inTable(false)
- , m_hasTerminatingNullCharacter(false)
, m_bufferIsInternal(false)
{
// Ensure that the hash is computed so that AtomicStringHash can call existingHash()
@@ -96,8 +96,6 @@ StringImpl::StringImpl()
inline StringImpl::StringImpl(const UChar* characters, unsigned length)
: m_length(length)
, m_hash(0)
- , m_inTable(false)
- , m_hasTerminatingNullCharacter(false)
, m_bufferIsInternal(false)
{
UChar* data = newUCharVector(length);
@@ -108,10 +106,9 @@ inline StringImpl::StringImpl(const UChar* characters, unsigned length)
inline StringImpl::StringImpl(const StringImpl& str, WithTerminatingNullCharacter)
: m_length(str.m_length)
, m_hash(str.m_hash)
- , m_inTable(false)
- , m_hasTerminatingNullCharacter(true)
, m_bufferIsInternal(false)
{
+ m_sharedBufferAndFlags.setFlag(HasTerminatingNullCharacter);
UChar* data = newUCharVector(str.m_length + 1);
memcpy(data, str.m_data, str.m_length * sizeof(UChar));
data[str.m_length] = 0;
@@ -121,8 +118,6 @@ inline StringImpl::StringImpl(const StringImpl& str, WithTerminatingNullCharacte
inline StringImpl::StringImpl(const char* characters, unsigned length)
: m_length(length)
, m_hash(0)
- , m_inTable(false)
- , m_hasTerminatingNullCharacter(false)
, m_bufferIsInternal(false)
{
ASSERT(characters);
@@ -140,8 +135,6 @@ inline StringImpl::StringImpl(UChar* characters, unsigned length, AdoptBuffer)
: m_length(length)
, m_data(characters)
, m_hash(0)
- , m_inTable(false)
- , m_hasTerminatingNullCharacter(false)
, m_bufferIsInternal(false)
{
ASSERT(characters);
@@ -152,14 +145,13 @@ inline StringImpl::StringImpl(UChar* characters, unsigned length, AdoptBuffer)
StringImpl::StringImpl(const UChar* characters, unsigned length, unsigned hash)
: m_length(length)
, m_hash(hash)
- , m_inTable(true)
- , m_hasTerminatingNullCharacter(false)
, m_bufferIsInternal(false)
{
ASSERT(hash);
ASSERT(characters);
ASSERT(length);
+ setInTable();
UChar* data = newUCharVector(length);
memcpy(data, characters, length * sizeof(UChar));
m_data = data;
@@ -169,14 +161,13 @@ StringImpl::StringImpl(const UChar* characters, unsigned length, unsigned hash)
StringImpl::StringImpl(const char* characters, unsigned length, unsigned hash)
: m_length(length)
, m_hash(hash)
- , m_inTable(true)
- , m_hasTerminatingNullCharacter(false)
, m_bufferIsInternal(false)
{
ASSERT(hash);
ASSERT(characters);
ASSERT(length);
+ setInTable();
UChar* data = newUCharVector(length);
for (unsigned i = 0; i != length; ++i) {
unsigned char c = characters[i];
@@ -187,10 +178,15 @@ StringImpl::StringImpl(const char* characters, unsigned length, unsigned hash)
StringImpl::~StringImpl()
{
- if (m_inTable)
+ if (inTable())
AtomicString::remove(this);
- if (!m_bufferIsInternal)
- deleteUCharVector(m_data);
+ if (!m_bufferIsInternal) {
+ SharedUChar* sharedBuffer = m_sharedBufferAndFlags.get();
+ if (sharedBuffer)
+ sharedBuffer->deref();
+ else
+ deleteUCharVector(m_data);
+ }
}
StringImpl* StringImpl::empty()
@@ -264,7 +260,8 @@ bool StringImpl::isLower()
PassRefPtr<StringImpl> StringImpl::lower()
{
- StringBuffer data(m_length);
+ UChar* data;
+ PassRefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
int32_t length = m_length;
// Do a faster loop for the case where all the characters are ASCII.
@@ -275,23 +272,24 @@ PassRefPtr<StringImpl> StringImpl::lower()
data[i] = toASCIILower(c);
}
if (!(ored & ~0x7F))
- return adopt(data);
+ return newImpl;
// Do a slower implementation for cases that include non-ASCII characters.
bool error;
- int32_t realLength = Unicode::toLower(data.characters(), length, m_data, m_length, &error);
+ int32_t realLength = Unicode::toLower(data, length, m_data, m_length, &error);
if (!error && realLength == length)
- return adopt(data);
- data.resize(realLength);
- Unicode::toLower(data.characters(), realLength, m_data, m_length, &error);
+ return newImpl;
+ newImpl = createUninitialized(realLength, data);
+ Unicode::toLower(data, realLength, m_data, m_length, &error);
if (error)
return this;
- return adopt(data);
+ return newImpl;
}
PassRefPtr<StringImpl> StringImpl::upper()
{
- StringBuffer data(m_length);
+ UChar* data;
+ PassRefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
int32_t length = m_length;
// Do a faster loop for the case where all the characters are ASCII.
@@ -302,32 +300,34 @@ PassRefPtr<StringImpl> StringImpl::upper()
data[i] = toASCIIUpper(c);
}
if (!(ored & ~0x7F))
- return adopt(data);
+ return newImpl;
// Do a slower implementation for cases that include non-ASCII characters.
bool error;
- int32_t realLength = Unicode::toUpper(data.characters(), length, m_data, m_length, &error);
+ int32_t realLength = Unicode::toUpper(data, length, m_data, m_length, &error);
if (!error && realLength == length)
- return adopt(data);
- data.resize(realLength);
- Unicode::toUpper(data.characters(), realLength, m_data, m_length, &error);
+ return newImpl;
+ newImpl = createUninitialized(realLength, data);
+ Unicode::toUpper(data, realLength, m_data, m_length, &error);
if (error)
return this;
- return adopt(data);
+ return newImpl;
}
PassRefPtr<StringImpl> StringImpl::secure(UChar aChar)
{
- int length = m_length;
- StringBuffer data(length);
+ UChar* data;
+ PassRefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
+ int32_t length = m_length;
for (int i = 0; i < length; ++i)
data[i] = aChar;
- return adopt(data);
+ return newImpl;
}
PassRefPtr<StringImpl> StringImpl::foldCase()
{
- StringBuffer data(m_length);
+ UChar* data;
+ PassRefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
int32_t length = m_length;
// Do a faster loop for the case where all the characters are ASCII.
@@ -338,18 +338,18 @@ PassRefPtr<StringImpl> StringImpl::foldCase()
data[i] = toASCIILower(c);
}
if (!(ored & ~0x7F))
- return adopt(data);
+ return newImpl;
// Do a slower implementation for cases that include non-ASCII characters.
bool error;
- int32_t realLength = Unicode::foldCase(data.characters(), length, m_data, m_length, &error);
+ int32_t realLength = Unicode::foldCase(data, length, m_data, m_length, &error);
if (!error && realLength == length)
- return adopt(data);
- data.resize(realLength);
- Unicode::foldCase(data.characters(), realLength, m_data, m_length, &error);
+ return newImpl;
+ newImpl = createUninitialized(realLength, data);
+ Unicode::foldCase(data, realLength, m_data, m_length, &error);
if (error)
return this;
- return adopt(data);
+ return newImpl;
}
PassRefPtr<StringImpl> StringImpl::stripWhiteSpace()
@@ -727,14 +727,16 @@ PassRefPtr<StringImpl> StringImpl::replace(UChar oldC, UChar newC)
if (i == m_length)
return this;
- StringBuffer data(m_length);
+ UChar* data;
+ PassRefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
+
for (i = 0; i != m_length; ++i) {
UChar ch = m_data[i];
if (ch == oldC)
ch = newC;
data[i] = ch;
}
- return adopt(data);
+ return newImpl;
}
PassRefPtr<StringImpl> StringImpl::replace(unsigned position, unsigned lengthToReplace, StringImpl* str)
@@ -744,13 +746,15 @@ PassRefPtr<StringImpl> StringImpl::replace(unsigned position, unsigned lengthToR
unsigned lengthToInsert = str ? str->length() : 0;
if (!lengthToReplace && !lengthToInsert)
return this;
- StringBuffer buffer(length() - lengthToReplace + lengthToInsert);
- memcpy(buffer.characters(), characters(), position * sizeof(UChar));
+ UChar* data;
+ PassRefPtr<StringImpl> newImpl =
+ createUninitialized(length() - lengthToReplace + lengthToInsert, data);
+ memcpy(data, characters(), position * sizeof(UChar));
if (str)
- memcpy(buffer.characters() + position, str->characters(), lengthToInsert * sizeof(UChar));
- memcpy(buffer.characters() + position + lengthToInsert, characters() + position + lengthToReplace,
+ memcpy(data + position, str->characters(), lengthToInsert * sizeof(UChar));
+ memcpy(data + position + lengthToInsert, characters() + position + lengthToReplace,
(length() - position - lengthToReplace) * sizeof(UChar));
- return adopt(buffer);
+ return newImpl;
}
PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacement)
@@ -772,8 +776,10 @@ PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacemen
if (!matchCount)
return this;
- StringBuffer data(m_length - matchCount + (matchCount * repStrLength));
-
+ UChar* data;
+ PassRefPtr<StringImpl> newImpl =
+ createUninitialized(m_length - matchCount + (matchCount * repStrLength), data);
+
// Construct the new data
int srcSegmentEnd;
int srcSegmentLength;
@@ -782,19 +788,19 @@ PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacemen
while ((srcSegmentEnd = find(pattern, srcSegmentStart)) >= 0) {
srcSegmentLength = srcSegmentEnd - srcSegmentStart;
- memcpy(data.characters() + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
+ memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
dstOffset += srcSegmentLength;
- memcpy(data.characters() + dstOffset, replacement->m_data, repStrLength * sizeof(UChar));
+ memcpy(data + dstOffset, replacement->m_data, repStrLength * sizeof(UChar));
dstOffset += repStrLength;
srcSegmentStart = srcSegmentEnd + 1;
}
srcSegmentLength = m_length - srcSegmentStart;
- memcpy(data.characters() + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
+ memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
- ASSERT(dstOffset + srcSegmentLength == static_cast<int>(data.length()));
+ ASSERT(dstOffset + srcSegmentLength == static_cast<int>(newImpl->length()));
- return adopt(data);
+ return newImpl;
}
PassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* replacement)
@@ -820,7 +826,9 @@ PassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* repl
if (!matchCount)
return this;
- StringBuffer data(m_length + matchCount * (repStrLength - patternLength));
+ UChar* data;
+ PassRefPtr<StringImpl> newImpl =
+ createUninitialized(m_length + matchCount * (repStrLength - patternLength), data);
// Construct the new data
int srcSegmentEnd;
@@ -830,19 +838,19 @@ PassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* repl
while ((srcSegmentEnd = find(pattern, srcSegmentStart)) >= 0) {
srcSegmentLength = srcSegmentEnd - srcSegmentStart;
- memcpy(data.characters() + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
+ memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
dstOffset += srcSegmentLength;
- memcpy(data.characters() + dstOffset, replacement->m_data, repStrLength * sizeof(UChar));
+ memcpy(data + dstOffset, replacement->m_data, repStrLength * sizeof(UChar));
dstOffset += repStrLength;
srcSegmentStart = srcSegmentEnd + patternLength;
}
srcSegmentLength = m_length - srcSegmentStart;
- memcpy(data.characters() + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
+ memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
- ASSERT(dstOffset + srcSegmentLength == static_cast<int>(data.length()));
+ ASSERT(dstOffset + srcSegmentLength == static_cast<int>(newImpl->length()));
- return adopt(data);
+ return newImpl;
}
bool equal(StringImpl* a, StringImpl* b)
@@ -965,41 +973,47 @@ PassRefPtr<StringImpl> StringImpl::adopt(Vector<UChar>& vector)
return adoptRef(new StringImpl(vector.releaseBuffer(), size, AdoptBuffer()));
}
-PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length)
+PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, UChar*& data)
{
- if (!characters || !length)
+ if (!length) {
+ data = 0;
return empty();
+ }
// Allocate a single buffer large enough to contain the StringImpl
// struct as well as the data which it contains. This removes one
// heap allocation from this call.
size_t size = sizeof(StringImpl) + length * sizeof(UChar);
char* buffer = static_cast<char*>(fastMalloc(size));
- UChar* data = reinterpret_cast<UChar*>(buffer + sizeof(StringImpl));
- memcpy(data, characters, length * sizeof(UChar));
+ data = reinterpret_cast<UChar*>(buffer + sizeof(StringImpl));
StringImpl* string = new (buffer) StringImpl(data, length, AdoptBuffer());
string->m_bufferIsInternal = true;
return adoptRef(string);
}
+PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length)
+{
+ if (!characters || !length)
+ return empty();
+
+ UChar* data;
+ PassRefPtr<StringImpl> string = createUninitialized(length, data);
+ memcpy(data, characters, length * sizeof(UChar));
+ return string;
+}
+
PassRefPtr<StringImpl> StringImpl::create(const char* characters, unsigned length)
{
if (!characters || !length)
return empty();
- // Allocate a single buffer large enough to contain the StringImpl
- // struct as well as the data which it contains. This removes one
- // heap allocation from this call.
- size_t size = sizeof(StringImpl) + length * sizeof(UChar);
- char* buffer = static_cast<char*>(fastMalloc(size));
- UChar* data = reinterpret_cast<UChar*>(buffer + sizeof(StringImpl));
+ UChar* data;
+ PassRefPtr<StringImpl> string = createUninitialized(length, data);
for (unsigned i = 0; i != length; ++i) {
unsigned char c = characters[i];
data[i] = c;
}
- StringImpl* string = new (buffer) StringImpl(data, length, AdoptBuffer());
- string->m_bufferIsInternal = true;
- return adoptRef(string);
+ return string;
}
PassRefPtr<StringImpl> StringImpl::create(const char* string)
@@ -1009,6 +1023,29 @@ PassRefPtr<StringImpl> StringImpl::create(const char* string)
return create(string, strlen(string));
}
+#if USE(JSC)
+PassRefPtr<StringImpl> StringImpl::create(const JSC::UString& str)
+{
+ SharedUChar* sharedBuffer = const_cast<JSC::UString*>(&str)->rep()->baseString()->sharedBuffer();
+ if (sharedBuffer) {
+ PassRefPtr<StringImpl> impl = adoptRef(new StringImpl(const_cast<UChar*>(str.data()), str.size(), AdoptBuffer()));
+ sharedBuffer->ref();
+ impl->m_sharedBufferAndFlags.set(sharedBuffer);
+ return impl;
+ }
+ return StringImpl::create(str.data(), str.size());
+}
+
+JSC::UString StringImpl::ustring()
+{
+ SharedUChar* sharedBuffer = StringImpl::sharedBuffer();
+ if (sharedBuffer)
+ return JSC::UString::Rep::create(const_cast<UChar*>(m_data), m_length, sharedBuffer);
+
+ return JSC::UString(m_data, m_length);
+}
+#endif
+
PassRefPtr<StringImpl> StringImpl::createWithTerminatingNullCharacter(const StringImpl& string)
{
return adoptRef(new StringImpl(string, WithTerminatingNullCharacter()));
@@ -1019,4 +1056,15 @@ PassRefPtr<StringImpl> StringImpl::copy()
return create(m_data, m_length);
}
+StringImpl::SharedUChar* StringImpl::sharedBuffer()
+{
+ if (m_length < minLengthToShare || m_bufferIsInternal)
+ return 0;
+
+ if (!m_sharedBufferAndFlags.get())
+ m_sharedBufferAndFlags.set(SharedUChar::create(new OwnFastMallocPtr<UChar>(const_cast<UChar*>(m_data))).releaseRef());
+ return m_sharedBufferAndFlags.get();
+}
+
+
} // namespace WebCore
diff --git a/WebCore/platform/text/StringImpl.h b/WebCore/platform/text/StringImpl.h
index 1242f27..f591800 100644
--- a/WebCore/platform/text/StringImpl.h
+++ b/WebCore/platform/text/StringImpl.h
@@ -1,6 +1,7 @@
/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google 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
@@ -24,11 +25,18 @@
#include <limits.h>
#include <wtf/ASCIICType.h>
+#include <wtf/CrossThreadRefCounted.h>
+#include <wtf/OwnFastMallocPtr.h>
#include <wtf/PassRefPtr.h>
+#include <wtf/PtrAndFlags.h>
#include <wtf/RefCounted.h>
#include <wtf/Vector.h>
#include <wtf/unicode/Unicode.h>
+#if USE(JSC)
+#include <runtime/UString.h>
+#endif
+
#if PLATFORM(CF) || (PLATFORM(QT) && PLATFORM(DARWIN))
typedef const struct __CFString * CFStringRef;
#endif
@@ -72,23 +80,34 @@ private:
StringImpl(const UChar*, unsigned length, unsigned hash);
StringImpl(const char*, unsigned length, unsigned hash);
+ typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar;
+
public:
~StringImpl();
static PassRefPtr<StringImpl> create(const UChar*, unsigned length);
static PassRefPtr<StringImpl> create(const char*, unsigned length);
static PassRefPtr<StringImpl> create(const char*);
+ static PassRefPtr<StringImpl> createUninitialized(unsigned length, UChar*& data);
static PassRefPtr<StringImpl> createWithTerminatingNullCharacter(const StringImpl&);
static PassRefPtr<StringImpl> createStrippingNullCharacters(const UChar*, unsigned length);
static PassRefPtr<StringImpl> adopt(StringBuffer&);
static PassRefPtr<StringImpl> adopt(Vector<UChar>&);
+#if USE(JSC)
+ static PassRefPtr<StringImpl> create(const JSC::UString&);
+ JSC::UString ustring();
+#endif
+ SharedUChar* sharedBuffer();
const UChar* characters() { return m_data; }
unsigned length() { return m_length; }
- bool hasTerminatingNullCharacter() { return m_hasTerminatingNullCharacter; }
+ bool hasTerminatingNullCharacter() const { return m_sharedBufferAndFlags.isFlagSet(HasTerminatingNullCharacter); }
+
+ bool inTable() const { return m_sharedBufferAndFlags.isFlagSet(InTable); }
+ void setInTable() { return m_sharedBufferAndFlags.setFlag(InTable); }
unsigned hash() { if (m_hash == 0) m_hash = computeHash(m_data, m_length); return m_hash; }
unsigned existingHash() const { ASSERT(m_hash); return m_hash; }
@@ -176,11 +195,16 @@ private:
static PassRefPtr<StringImpl> createStrippingNullCharactersSlowCase(const UChar*, unsigned length);
+ enum StringImplFlags {
+ HasTerminatingNullCharacter,
+ InTable,
+ };
+
unsigned m_length;
const UChar* m_data;
mutable unsigned m_hash;
- bool m_inTable;
- bool m_hasTerminatingNullCharacter;
+ PtrAndFlags<SharedUChar, StringImplFlags> m_sharedBufferAndFlags;
+
// In some cases, we allocate the StringImpl struct and its data
// within a single heap buffer. In this case, the m_data pointer
// is an "internal buffer", and does not need to be deallocated.
diff --git a/WebCore/platform/text/TextBoundaries.h b/WebCore/platform/text/TextBoundaries.h
index 118dd1a..7eb9cab 100644
--- a/WebCore/platform/text/TextBoundaries.h
+++ b/WebCore/platform/text/TextBoundaries.h
@@ -30,6 +30,11 @@
namespace WebCore {
+ inline bool requiresContextForWordBoundary(UChar32 ch)
+ {
+ return WTF::Unicode::hasLineBreakingPropertyComplexContext(ch);
+ }
+
void findWordBoundary(const UChar*, int len, int position, int* start, int* end);
int findNextWordFromIndex(const UChar*, int len, int position, bool forward);
diff --git a/WebCore/platform/text/TextBoundariesICU.cpp b/WebCore/platform/text/TextBoundariesICU.cpp
index d226048..b1e8ee2 100644
--- a/WebCore/platform/text/TextBoundariesICU.cpp
+++ b/WebCore/platform/text/TextBoundariesICU.cpp
@@ -27,6 +27,7 @@
#include "TextBoundaries.h"
#include <unicode/ubrk.h>
+#include <unicode/uchar.h>
#include "StringImpl.h"
#include "TextBreakIterator.h"
diff --git a/WebCore/platform/text/TextCodec.h b/WebCore/platform/text/TextCodec.h
index 0a56262..df42582 100644
--- a/WebCore/platform/text/TextCodec.h
+++ b/WebCore/platform/text/TextCodec.h
@@ -29,6 +29,7 @@
#include <memory>
#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>
#include <wtf/unicode/Unicode.h>
@@ -76,7 +77,7 @@ namespace WebCore {
typedef void (*EncodingNameRegistrar)(const char* alias, const char* name);
- typedef std::auto_ptr<TextCodec> (*NewTextCodecFunction)(const TextEncoding&, const void* additionalData);
+ typedef PassOwnPtr<TextCodec> (*NewTextCodecFunction)(const TextEncoding&, const void* additionalData);
typedef void (*TextCodecRegistrar)(const char* name, NewTextCodecFunction, const void* additionalData);
} // namespace WebCore
diff --git a/WebCore/platform/text/TextCodecICU.cpp b/WebCore/platform/text/TextCodecICU.cpp
index 72054fa..b8e40a9 100644
--- a/WebCore/platform/text/TextCodecICU.cpp
+++ b/WebCore/platform/text/TextCodecICU.cpp
@@ -34,10 +34,10 @@
#include <unicode/ucnv.h>
#include <unicode/ucnv_cb.h>
#include <wtf/Assertions.h>
+#include <wtf/PassOwnPtr.h>
#include <wtf/StringExtras.h>
#include <wtf/Threading.h>
-using std::auto_ptr;
using std::min;
namespace WebCore {
@@ -55,9 +55,9 @@ static UConverter*& cachedConverterICU()
return threadGlobalData().cachedConverterICU().converter;
}
-static auto_ptr<TextCodec> newTextCodecICU(const TextEncoding& encoding, const void*)
+static PassOwnPtr<TextCodec> newTextCodecICU(const TextEncoding& encoding, const void*)
{
- return auto_ptr<TextCodec>(new TextCodecICU(encoding));
+ return new TextCodecICU(encoding);
}
void TextCodecICU::registerBaseEncodingNames(EncodingNameRegistrar registrar)
diff --git a/WebCore/platform/text/TextCodecICU.h b/WebCore/platform/text/TextCodecICU.h
index f07758f..bf517f7 100644
--- a/WebCore/platform/text/TextCodecICU.h
+++ b/WebCore/platform/text/TextCodecICU.h
@@ -30,6 +30,8 @@
#include "TextCodec.h"
#include "TextEncoding.h"
+#include <unicode/utypes.h>
+
typedef struct UConverter UConverter;
namespace WebCore {
diff --git a/WebCore/platform/text/TextCodecLatin1.cpp b/WebCore/platform/text/TextCodecLatin1.cpp
index 50f9f97..cfdc5b9 100644
--- a/WebCore/platform/text/TextCodecLatin1.cpp
+++ b/WebCore/platform/text/TextCodecLatin1.cpp
@@ -30,8 +30,7 @@
#include "PlatformString.h"
#include "StringBuffer.h"
#include <stdio.h>
-
-using std::auto_ptr;
+#include <wtf/PassOwnPtr.h>
namespace WebCore {
@@ -104,9 +103,9 @@ void TextCodecLatin1::registerEncodingNames(EncodingNameRegistrar registrar)
registrar("x-ansi", "US-ASCII");
}
-static auto_ptr<TextCodec> newStreamingTextDecoderWindowsLatin1(const TextEncoding&, const void*)
+static PassOwnPtr<TextCodec> newStreamingTextDecoderWindowsLatin1(const TextEncoding&, const void*)
{
- return auto_ptr<TextCodec>(new TextCodecLatin1);
+ return new TextCodecLatin1;
}
void TextCodecLatin1::registerCodecs(TextCodecRegistrar registrar)
@@ -120,7 +119,8 @@ void TextCodecLatin1::registerCodecs(TextCodecRegistrar registrar)
String TextCodecLatin1::decode(const char* bytes, size_t length, bool, bool, bool&)
{
- StringBuffer characters(length);
+ UChar* characters;
+ String result = String::createUninitialized(length, characters);
// Convert the string a fast way and simultaneously do an efficient check to see if it's all ASCII.
unsigned char ored = 0;
@@ -131,7 +131,7 @@ String TextCodecLatin1::decode(const char* bytes, size_t length, bool, bool, boo
}
if (!(ored & 0x80))
- return String::adopt(characters);
+ return result;
// Convert the slightly slower way when there are non-ASCII characters.
for (size_t i = 0; i < length; ++i) {
@@ -139,7 +139,7 @@ String TextCodecLatin1::decode(const char* bytes, size_t length, bool, bool, boo
characters[i] = table[c];
}
- return String::adopt(characters);
+ return result;
}
static CString encodeComplexWindowsLatin1(const UChar* characters, size_t length, UnencodableHandling handling)
diff --git a/WebCore/platform/text/TextCodecUTF16.cpp b/WebCore/platform/text/TextCodecUTF16.cpp
index a4d0d28..db77000 100644
--- a/WebCore/platform/text/TextCodecUTF16.cpp
+++ b/WebCore/platform/text/TextCodecUTF16.cpp
@@ -29,8 +29,7 @@
#include "CString.h"
#include "PlatformString.h"
#include "StringBuffer.h"
-
-using std::auto_ptr;
+#include <wtf/PassOwnPtr.h>
namespace WebCore {
@@ -49,14 +48,14 @@ void TextCodecUTF16::registerEncodingNames(EncodingNameRegistrar registrar)
registrar("unicodeFFFE", "UTF-16BE");
}
-static auto_ptr<TextCodec> newStreamingTextDecoderUTF16LE(const TextEncoding&, const void*)
+static PassOwnPtr<TextCodec> newStreamingTextDecoderUTF16LE(const TextEncoding&, const void*)
{
- return auto_ptr<TextCodec>(new TextCodecUTF16(true));
+ return new TextCodecUTF16(true);
}
-static auto_ptr<TextCodec> newStreamingTextDecoderUTF16BE(const TextEncoding&, const void*)
+static PassOwnPtr<TextCodec> newStreamingTextDecoderUTF16BE(const TextEncoding&, const void*)
{
- return auto_ptr<TextCodec>(new TextCodecUTF16(false));
+ return new TextCodecUTF16(false);
}
void TextCodecUTF16::registerCodecs(TextCodecRegistrar registrar)
diff --git a/WebCore/platform/text/TextCodecUserDefined.cpp b/WebCore/platform/text/TextCodecUserDefined.cpp
index 2dae0f3..b7c8896 100644
--- a/WebCore/platform/text/TextCodecUserDefined.cpp
+++ b/WebCore/platform/text/TextCodecUserDefined.cpp
@@ -30,8 +30,7 @@
#include "PlatformString.h"
#include "StringBuffer.h"
#include <stdio.h>
-
-using std::auto_ptr;
+#include <wtf/PassOwnPtr.h>
namespace WebCore {
@@ -40,9 +39,9 @@ void TextCodecUserDefined::registerEncodingNames(EncodingNameRegistrar registrar
registrar("x-user-defined", "x-user-defined");
}
-static auto_ptr<TextCodec> newStreamingTextDecoderUserDefined(const TextEncoding&, const void*)
+static PassOwnPtr<TextCodec> newStreamingTextDecoderUserDefined(const TextEncoding&, const void*)
{
- return auto_ptr<TextCodec>(new TextCodecUserDefined);
+ return new TextCodecUserDefined;
}
void TextCodecUserDefined::registerCodecs(TextCodecRegistrar registrar)
@@ -52,14 +51,15 @@ void TextCodecUserDefined::registerCodecs(TextCodecRegistrar registrar)
String TextCodecUserDefined::decode(const char* bytes, size_t length, bool, bool, bool&)
{
- StringBuffer buffer(length);
+ UChar* buffer;
+ String result = String::createUninitialized(length, buffer);
for (size_t i = 0; i < length; ++i) {
signed char c = bytes[i];
buffer[i] = c & 0xF7FF;
}
- return String::adopt(buffer);
+ return result;
}
static CString encodeComplexUserDefined(const UChar* characters, size_t length, UnencodableHandling handling)
diff --git a/WebCore/platform/text/TextEncoding.cpp b/WebCore/platform/text/TextEncoding.cpp
index ed58412..5fa927b 100644
--- a/WebCore/platform/text/TextEncoding.cpp
+++ b/WebCore/platform/text/TextEncoding.cpp
@@ -31,7 +31,7 @@
#include "PlatformString.h"
#include "TextCodec.h"
#include "TextEncodingRegistry.h"
-#if USE(ICU_UNICODE)
+#if USE(ICU_UNICODE) || USE(GLIB_ICU_UNICODE_HYBRID)
#include <unicode/unorm.h>
#elif USE(QT4_UNICODE)
#include <QString>
@@ -83,7 +83,7 @@ CString TextEncoding::encode(const UChar* characters, size_t length, Unencodable
if (!length)
return "";
-#if USE(ICU_UNICODE)
+#if USE(ICU_UNICODE) || USE(GLIB_ICU_UNICODE_HYBRID)
// FIXME: What's the right place to do normalization?
// It's a little strange to do it inside the encode function.
// Perhaps normalization should be an explicit step done before calling encode.
@@ -116,6 +116,24 @@ CString TextEncoding::encode(const UChar* characters, size_t length, Unencodable
#endif
}
+const char* TextEncoding::domName() const
+{
+ if (noExtendedTextEncodingNameUsed())
+ return m_name;
+
+ // We treat EUC-KR as windows-949 (its superset), but need to expose
+ // the name 'EUC-KR' because the name 'windows-949' is not recognized by
+ // most Korean web servers even though they do use the encoding
+ // 'windows-949' with the name 'EUC-KR'.
+ // FIXME: This is not thread-safe. At the moment, this function is
+ // only accessed in a single thread, but eventually has to be made
+ // thread-safe along with usesVisualOrdering().
+ static const char* const a = atomicCanonicalTextEncodingName("windows-949");
+ if (m_name == a)
+ return "EUC-KR";
+ return m_name;
+}
+
bool TextEncoding::usesVisualOrdering() const
{
if (noExtendedTextEncodingNameUsed())
diff --git a/WebCore/platform/text/TextEncoding.h b/WebCore/platform/text/TextEncoding.h
index b3909f7..a99bfc8 100644
--- a/WebCore/platform/text/TextEncoding.h
+++ b/WebCore/platform/text/TextEncoding.h
@@ -42,6 +42,7 @@ namespace WebCore {
bool isValid() const { return m_name; }
const char* name() const { return m_name; }
+ const char* domName() const; // name exposed via DOM
bool usesVisualOrdering() const;
bool isJapanese() const;
diff --git a/WebCore/platform/text/TextEncodingDetectorICU.cpp b/WebCore/platform/text/TextEncodingDetectorICU.cpp
index 26c997e..fcb2aa9 100644
--- a/WebCore/platform/text/TextEncodingDetectorICU.cpp
+++ b/WebCore/platform/text/TextEncodingDetectorICU.cpp
@@ -32,7 +32,7 @@
#include "TextEncodingDetector.h"
#include "TextEncoding.h"
-#include "UnusedParam.h"
+#include <wtf/UnusedParam.h>
#ifndef BUILDING_ON_TIGER
#include "unicode/ucnv.h"
diff --git a/WebCore/platform/text/TextEncodingDetectorNone.cpp b/WebCore/platform/text/TextEncodingDetectorNone.cpp
index 2655f08..3b62bc5 100644
--- a/WebCore/platform/text/TextEncodingDetectorNone.cpp
+++ b/WebCore/platform/text/TextEncodingDetectorNone.cpp
@@ -32,18 +32,11 @@
#include "TextEncodingDetector.h"
#include "TextEncoding.h"
-#include "UnusedParam.h"
namespace WebCore {
-bool detectTextEncoding(const char* data, size_t len,
- const char* hintEncodingName,
- TextEncoding* detectedEncoding)
+bool detectTextEncoding(const char*, size_t, const char*, TextEncoding* detectedEncoding)
{
- UNUSED_PARAM(data)
- UNUSED_PARAM(len)
- UNUSED_PARAM(hintEncodingName)
-
*detectedEncoding = TextEncoding();
return false;
}
diff --git a/WebCore/platform/text/TextEncodingRegistry.cpp b/WebCore/platform/text/TextEncodingRegistry.cpp
index 2d89fac..3c9d65f 100644
--- a/WebCore/platform/text/TextEncodingRegistry.cpp
+++ b/WebCore/platform/text/TextEncodingRegistry.cpp
@@ -38,7 +38,7 @@
#include <wtf/StringExtras.h>
#include <wtf/Threading.h>
-#if USE(ICU_UNICODE)
+#if USE(ICU_UNICODE) || USE(GLIB_ICU_UNICODE_HYBRID)
#include "TextCodecICU.h"
#endif
#if PLATFORM(MAC)
@@ -185,7 +185,7 @@ static void buildBaseTextCodecMaps()
TextCodecUserDefined::registerEncodingNames(addToTextEncodingNameMap);
TextCodecUserDefined::registerCodecs(addToTextCodecMap);
-#if USE(ICU_UNICODE)
+#if USE(ICU_UNICODE) || USE(GLIB_ICU_UNICODE_HYBRID)
TextCodecICU::registerBaseEncodingNames(addToTextEncodingNameMap);
TextCodecICU::registerBaseCodecs(addToTextCodecMap);
#endif
@@ -193,7 +193,7 @@ static void buildBaseTextCodecMaps()
static void extendTextCodecMaps()
{
-#if USE(ICU_UNICODE)
+#if USE(ICU_UNICODE) || USE(GLIB_ICU_UNICODE_HYBRID)
TextCodecICU::registerExtendedEncodingNames(addToTextEncodingNameMap);
TextCodecICU::registerExtendedCodecs(addToTextCodecMap);
#endif
@@ -209,7 +209,7 @@ static void extendTextCodecMaps()
#endif
}
-std::auto_ptr<TextCodec> newTextCodec(const TextEncoding& encoding)
+PassOwnPtr<TextCodec> newTextCodec(const TextEncoding& encoding)
{
MutexLocker lock(encodingRegistryMutex());
diff --git a/WebCore/platform/text/TextEncodingRegistry.h b/WebCore/platform/text/TextEncodingRegistry.h
index d204734..e6950cf 100644
--- a/WebCore/platform/text/TextEncodingRegistry.h
+++ b/WebCore/platform/text/TextEncodingRegistry.h
@@ -27,6 +27,7 @@
#define TextEncodingRegistry_h
#include <memory>
+#include <wtf/PassOwnPtr.h>
#include <wtf/unicode/Unicode.h>
namespace WebCore {
@@ -36,7 +37,7 @@ namespace WebCore {
// Use TextResourceDecoder::decode to decode resources, since it handles BOMs.
// Use TextEncoding::encode to encode, since it takes care of normalization.
- std::auto_ptr<TextCodec> newTextCodec(const TextEncoding&);
+ PassOwnPtr<TextCodec> newTextCodec(const TextEncoding&);
// Only TextEncoding should use this function directly.
const char* atomicCanonicalTextEncodingName(const char* alias);
diff --git a/WebCore/platform/text/mac/TextBoundaries.mm b/WebCore/platform/text/mac/TextBoundaries.mm
index ff1dfd2..bd7ddf8 100644
--- a/WebCore/platform/text/mac/TextBoundaries.mm
+++ b/WebCore/platform/text/mac/TextBoundaries.mm
@@ -26,6 +26,8 @@
#import "config.h"
#import "TextBoundaries.h"
+using namespace WTF::Unicode;
+
namespace WebCore {
void findWordBoundary(const UChar* chars, int len, int position, int* start, int* end)
diff --git a/WebCore/platform/text/mac/TextCodecMac.cpp b/WebCore/platform/text/mac/TextCodecMac.cpp
index 3baf21f..93b9da2 100644
--- a/WebCore/platform/text/mac/TextCodecMac.cpp
+++ b/WebCore/platform/text/mac/TextCodecMac.cpp
@@ -33,9 +33,9 @@
#include "PlatformString.h"
#include "ThreadGlobalData.h"
#include <wtf/Assertions.h>
+#include <wtf/PassOwnPtr.h>
#include <wtf/Threading.h>
-using std::auto_ptr;
using std::min;
namespace WebCore {
@@ -64,9 +64,9 @@ void TextCodecMac::registerEncodingNames(EncodingNameRegistrar registrar)
}
}
-static auto_ptr<TextCodec> newTextCodecMac(const TextEncoding&, const void* additionalData)
+static PassOwnPtr<TextCodec> newTextCodecMac(const TextEncoding&, const void* additionalData)
{
- return auto_ptr<TextCodec>(new TextCodecMac(*static_cast<const TECTextEncodingID*>(additionalData)));
+ return new TextCodecMac(*static_cast<const TECTextEncodingID*>(additionalData));
}
void TextCodecMac::registerCodecs(TextCodecRegistrar registrar)
diff --git a/WebCore/platform/text/qt/TextBreakIteratorQt.cpp b/WebCore/platform/text/qt/TextBreakIteratorQt.cpp
index 4dc23ee..06e8f37 100644
--- a/WebCore/platform/text/qt/TextBreakIteratorQt.cpp
+++ b/WebCore/platform/text/qt/TextBreakIteratorQt.cpp
@@ -20,6 +20,7 @@
*
*/
+#include "config.h"
#include "TextBreakIterator.h"
#if QT_VERSION >= 0x040400
diff --git a/WebCore/platform/text/qt/TextCodecQt.cpp b/WebCore/platform/text/qt/TextCodecQt.cpp
index 0f385dd..c6c02cf 100644
--- a/WebCore/platform/text/qt/TextCodecQt.cpp
+++ b/WebCore/platform/text/qt/TextCodecQt.cpp
@@ -63,9 +63,9 @@ void TextCodecQt::registerEncodingNames(EncodingNameRegistrar registrar)
}
}
-static std::auto_ptr<TextCodec> newTextCodecQt(const TextEncoding& encoding, const void*)
+static PassOwnPtr<TextCodec> newTextCodecQt(const TextEncoding& encoding, const void*)
{
- return std::auto_ptr<TextCodec>(new TextCodecQt(encoding));
+ return new TextCodecQt(encoding);
}
void TextCodecQt::registerCodecs(TextCodecRegistrar registrar)
diff --git a/WebCore/platform/text/win/TextBreakIteratorInternalICUWin.cpp b/WebCore/platform/text/win/TextBreakIteratorInternalICUWin.cpp
index 14cf130..ce436df 100644
--- a/WebCore/platform/text/win/TextBreakIteratorInternalICUWin.cpp
+++ b/WebCore/platform/text/win/TextBreakIteratorInternalICUWin.cpp
@@ -25,7 +25,11 @@ namespace WebCore {
const char* currentTextBreakLocaleID()
{
- return "en_us";
+ // Using en_US_POSIX now so word selection in address field works as expected as before (double-clicking
+ // in a URL selects a word delimited by periods rather than selecting the entire URL).
+ // However, this is not entirely correct - we should honor the system locale in the normal case.
+ // FIXME: <rdar://problem/6786703> Should use system locale for text breaking
+ return "en_US_POSIX";
}
}
diff --git a/WebCore/platform/win/ClipboardUtilitiesWin.cpp b/WebCore/platform/win/ClipboardUtilitiesWin.cpp
index 3762a1a..0358b7a 100644
--- a/WebCore/platform/win/ClipboardUtilitiesWin.cpp
+++ b/WebCore/platform/win/ClipboardUtilitiesWin.cpp
@@ -291,7 +291,12 @@ static bool urlFromPath(CFStringRef path, String& url)
if (!cfURL)
return false;
- url = String(CFURLGetString(cfURL.get()));
+ url = CFURLGetString(cfURL.get());
+
+ // Work around <rdar://problem/6708300>, where CFURLCreateWithFileSystemPath makes URLs with "localhost".
+ if (url.startsWith("file://localhost/"))
+ url.remove(7, 9);
+
return true;
}
diff --git a/WebCore/platform/win/EditorWin.cpp b/WebCore/platform/win/EditorWin.cpp
index 813eb78..09abdbd 100644
--- a/WebCore/platform/win/EditorWin.cpp
+++ b/WebCore/platform/win/EditorWin.cpp
@@ -31,7 +31,6 @@
#include "Document.h"
#include "Element.h"
#include "htmlediting.h"
-#include "NotImplemented.h"
#include "TextIterator.h"
#include "visible_units.h"
diff --git a/WebCore/platform/win/Language.cpp b/WebCore/platform/win/Language.cpp
index 787c5a3..588c5df 100644
--- a/WebCore/platform/win/Language.cpp
+++ b/WebCore/platform/win/Language.cpp
@@ -37,11 +37,11 @@ static String localeInfo(LCTYPE localeType, const String& fallback)
int localeChars = GetLocaleInfo(langID, localeType, 0, 0);
if (!localeChars)
return fallback;
- Vector<WCHAR> localeNameBuf(localeChars);
- localeChars = GetLocaleInfo(langID, localeType, localeNameBuf.data(), localeChars);
+ UChar* localeNameBuf;
+ String localeName = String::createUninitialized(localeChars, localeNameBuf);
+ localeChars = GetLocaleInfo(langID, localeType, localeNameBuf, localeChars);
if (!localeChars)
return fallback;
- String localeName = String::adopt(localeNameBuf);
if (localeName.isEmpty())
return fallback;
diff --git a/WebCore/platform/win/PasteboardWin.cpp b/WebCore/platform/win/PasteboardWin.cpp
index 506cc7b..8cf9bf2 100644
--- a/WebCore/platform/win/PasteboardWin.cpp
+++ b/WebCore/platform/win/PasteboardWin.cpp
@@ -35,7 +35,6 @@
#include "HitTestResult.h"
#include "Image.h"
#include "KURL.h"
-#include "NotImplemented.h"
#include "Page.h"
#include "Range.h"
#include "RenderImage.h"
diff --git a/WebCore/platform/win/PopupMenuWin.cpp b/WebCore/platform/win/PopupMenuWin.cpp
index 52f2eb9..2b4749a 100644
--- a/WebCore/platform/win/PopupMenuWin.cpp
+++ b/WebCore/platform/win/PopupMenuWin.cpp
@@ -123,9 +123,7 @@ void PopupMenu::show(const IntRect& r, FrameView* v, int index)
// Determine whether we should animate our popups
// Note: Must use 'BOOL' and 'FALSE' instead of 'bool' and 'false' to avoid stack corruption with SystemParametersInfo
BOOL shouldAnimate = FALSE;
-#ifdef CAN_ANIMATE_TRANSPARENT_WINDOWS_SMOOTHLY
::SystemParametersInfo(SPI_GETCOMBOBOXANIMATION, 0, &shouldAnimate, 0);
-#endif
if (shouldAnimate) {
RECT viewRect = {0};
@@ -598,7 +596,7 @@ static ATOM registerPopup()
wcex.cbSize = sizeof(WNDCLASSEX);
- wcex.style = 0;
+ wcex.style = CS_DROPSHADOW;
wcex.lpfnWndProc = PopupWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(PopupMenu*); // For the PopupMenu pointer
diff --git a/WebCore/platform/win/ScrollbarThemeWin.cpp b/WebCore/platform/win/ScrollbarThemeWin.cpp
index e13d893..2ee3512 100644
--- a/WebCore/platform/win/ScrollbarThemeWin.cpp
+++ b/WebCore/platform/win/ScrollbarThemeWin.cpp
@@ -30,6 +30,7 @@
#include "PlatformMouseEvent.h"
#include "Scrollbar.h"
#include "SoftLinking.h"
+#include "SystemInfo.h"
// Generic state constants
#define TS_NORMAL 1
@@ -61,7 +62,6 @@ using namespace std;
namespace WebCore {
static HANDLE scrollbarTheme;
-static bool haveTheme;
static bool runningVista;
// FIXME: Refactor the soft-linking code so that it can be shared with RenderThemeWin
@@ -72,27 +72,17 @@ SOFT_LINK(uxtheme, DrawThemeBackground, HRESULT, WINAPI, (HANDLE hTheme, HDC hdc
SOFT_LINK(uxtheme, IsThemeActive, BOOL, WINAPI, (), ())
SOFT_LINK(uxtheme, IsThemeBackgroundPartiallyTransparent, BOOL, WINAPI, (HANDLE hTheme, int iPartId, int iStateId), (hTheme, iPartId, iStateId))
-static bool isRunningOnVistaOrLater()
-{
- static bool os = false;
- static bool initialized = false;
- if (!initialized) {
- OSVERSIONINFOEX vi = {sizeof(vi), 0};
- GetVersionEx((OSVERSIONINFO*)&vi);
-
- // NOTE: This does not work under a debugger - Vista shims Visual Studio,
- // making it believe it is xpsp2, which is inherited by debugged applications
- os = vi.dwMajorVersion >= 6;
- initialized = true;
- }
- return os;
-}
+// Constants used to figure the drag rect outside which we should snap the
+// scrollbar thumb back to its origin. These calculations are based on
+// observing the behavior of the MSVC8 main window scrollbar + some
+// guessing/extrapolation.
+static const int kOffEndMultiplier = 3;
+static const int kOffSideMultiplier = 8;
static void checkAndInitScrollbarTheme()
{
- if (uxthemeLibrary() && !scrollbarTheme)
+ if (uxthemeLibrary() && !scrollbarTheme && IsThemeActive())
scrollbarTheme = OpenThemeData(0, L"Scrollbar");
- haveTheme = scrollbarTheme && IsThemeActive();
}
#if !USE(SAFARI_THEME)
@@ -127,8 +117,11 @@ int ScrollbarThemeWin::scrollbarThickness(ScrollbarControlSize)
void ScrollbarThemeWin::themeChanged()
{
- if (haveTheme)
- CloseThemeData(scrollbarTheme);
+ if (!scrollbarTheme)
+ return;
+
+ CloseThemeData(scrollbarTheme);
+ scrollbarTheme = 0;
}
bool ScrollbarThemeWin::invalidateOnMouseEnterExit()
@@ -194,6 +187,29 @@ IntRect ScrollbarThemeWin::trackRect(Scrollbar* scrollbar, bool)
return IntRect(scrollbar->x(), scrollbar->y() + thickness, thickness, scrollbar->height() - 2 * thickness);
}
+bool ScrollbarThemeWin::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& evt)
+{
+ return evt.shiftKey() && evt.button() == LeftButton;
+}
+
+bool ScrollbarThemeWin::shouldSnapBackToDragOrigin(Scrollbar* scrollbar, const PlatformMouseEvent& evt)
+{
+ // Find the rect within which we shouldn't snap, by expanding the track rect
+ // in both dimensions.
+ IntRect rect = trackRect(scrollbar);
+ const bool horz = scrollbar->orientation() == HorizontalScrollbar;
+ const int thickness = scrollbarThickness(scrollbar->controlSize());
+ rect.inflateX((horz ? kOffEndMultiplier : kOffSideMultiplier) * thickness);
+ rect.inflateY((horz ? kOffSideMultiplier : kOffEndMultiplier) * thickness);
+
+ // Convert the event to local coordinates.
+ IntPoint mousePosition = scrollbar->convertFromContainingWindow(evt.pos());
+ mousePosition.move(scrollbar->x(), scrollbar->y());
+
+ // We should snap iff the event is outside our calculated rect.
+ return !rect.contains(mousePosition);
+}
+
void ScrollbarThemeWin::paintTrackBackground(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
{
// Just assume a forward track part. We only paint the track as a single piece when there is no thumb.
@@ -354,10 +370,5 @@ void ScrollbarThemeWin::paintThumb(GraphicsContext* context, Scrollbar* scrollba
context->releaseWindowsContext(hdc, rect, alphaBlend);
}
-bool ScrollbarThemeWin::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& evt)
-{
- return evt.shiftKey() && evt.button() == LeftButton;
-}
-
}
diff --git a/WebCore/platform/win/ScrollbarThemeWin.h b/WebCore/platform/win/ScrollbarThemeWin.h
index 92e2523..cd2f176 100644
--- a/WebCore/platform/win/ScrollbarThemeWin.h
+++ b/WebCore/platform/win/ScrollbarThemeWin.h
@@ -50,6 +50,7 @@ protected:
virtual IntRect trackRect(Scrollbar*, bool painting = false);
virtual bool shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent&);
+ virtual bool shouldSnapBackToDragOrigin(Scrollbar*, const PlatformMouseEvent&);
virtual void paintTrackBackground(GraphicsContext*, Scrollbar*, const IntRect&);
virtual void paintTrackPiece(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarPart);
diff --git a/WebCore/platform/win/SystemInfo.cpp b/WebCore/platform/win/SystemInfo.cpp
new file mode 100644
index 0000000..ba20ddd
--- /dev/null
+++ b/WebCore/platform/win/SystemInfo.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SystemInfo.h"
+
+namespace WebCore {
+
+bool isRunningOnVistaOrLater()
+{
+ static bool isVistaOrLater;
+ static bool initialized;
+
+ if (initialized)
+ return isVistaOrLater;
+
+ initialized = true;
+
+ OSVERSIONINFOEX vi = {0};
+ vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&vi));
+
+ isVistaOrLater = vi.dwMajorVersion >= 6;
+
+ return isVistaOrLater;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/win/SystemInfo.h b/WebCore/platform/win/SystemInfo.h
new file mode 100644
index 0000000..9f2c2a0
--- /dev/null
+++ b/WebCore/platform/win/SystemInfo.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SystemInfo_h
+#define SystemInfo_h
+
+namespace WebCore {
+
+bool isRunningOnVistaOrLater();
+
+} // namespace WebCore
+
+#endif // SystemInfo_h
diff --git a/WebCore/platform/win/WidgetWin.cpp b/WebCore/platform/win/WidgetWin.cpp
index 93dbf42..2272027 100644
--- a/WebCore/platform/win/WidgetWin.cpp
+++ b/WebCore/platform/win/WidgetWin.cpp
@@ -29,10 +29,12 @@
#include "Cursor.h"
#include "Document.h"
#include "Element.h"
-#include "GraphicsContext.h"
+#include "FrameView.h"
#include "FrameWin.h"
+#include "GraphicsContext.h"
#include "IntRect.h"
-#include "FrameView.h"
+#include "Page.h"
+
#include <winsock2.h>
#include <windows.h>
@@ -61,17 +63,37 @@ bool ignoreNextSetCursor = false;
void Widget::setCursor(const Cursor& cursor)
{
- // This is set by PluginViewWin so it can ignore set setCursor call made by
+ // This is set by PluginViewWin so it can ignore the setCursor call made by
// EventHandler.cpp.
if (ignoreNextSetCursor) {
ignoreNextSetCursor = false;
return;
}
- if (HCURSOR c = cursor.impl()->nativeCursor()) {
- lastSetCursor = c;
- SetCursor(c);
+ if (!cursor.impl()->nativeCursor())
+ return;
+
+ lastSetCursor = cursor.impl()->nativeCursor();
+
+ ScrollView* view = root();
+ if (!view || !view->isFrameView()) {
+ SetCursor(lastSetCursor);
+ return;
+ }
+
+ Frame* frame = static_cast<FrameView*>(view)->frame();
+ if (!frame) {
+ SetCursor(lastSetCursor);
+ return;
+ }
+
+ Page* page = frame->page();
+ if (!page) {
+ SetCursor(lastSetCursor);
+ return;
}
+
+ page->chrome()->setCursor(lastSetCursor);
}
void Widget::paint(GraphicsContext*, const IntRect&)
diff --git a/WebCore/platform/wx/KeyboardEventWx.cpp b/WebCore/platform/wx/KeyboardEventWx.cpp
index 8be87ac..7f57073 100644
--- a/WebCore/platform/wx/KeyboardEventWx.cpp
+++ b/WebCore/platform/wx/KeyboardEventWx.cpp
@@ -27,7 +27,6 @@
#include "PlatformKeyboardEvent.h"
#include "KeyboardCodes.h"
-#include "NotImplemented.h"
#include <wx/defs.h>
#include <wx/event.h>
@@ -163,14 +162,17 @@ static int windowsKeyCodeForKeyEvent(unsigned int keycode)
return VK_DECIMAL; // (6E) Decimal key
case WXK_DIVIDE:
return VK_DIVIDE; // (6F) Divide key
-
+ case WXK_NUMPAD_SEPARATOR:
+ return VK_SEPARATOR;
case WXK_BACK:
return VK_BACK; // (08) BACKSPACE key
case WXK_TAB:
+ case WXK_NUMPAD_TAB:
return VK_TAB; // (09) TAB key
case WXK_CLEAR:
return VK_CLEAR; // (0C) CLEAR key
+ case WXK_NUMPAD_ENTER:
case WXK_RETURN:
return VK_RETURN; //(0D) Return key
case WXK_SHIFT:
@@ -204,22 +206,31 @@ static int windowsKeyCodeForKeyEvent(unsigned int keycode)
// VK_NONCONVERT (1D) IME nonconvert
// VK_ACCEPT (1E) IME accept
// VK_MODECHANGE (1F) IME mode change request
+ case WXK_NUMPAD_SPACE:
case WXK_SPACE:
return VK_SPACE; // (20) SPACEBAR
+ case WXK_NUMPAD_PAGEUP:
case WXK_PAGEUP:
return VK_PRIOR; // (21) PAGE UP key
+ case WXK_NUMPAD_PAGEDOWN:
case WXK_PAGEDOWN:
return VK_NEXT; // (22) PAGE DOWN key
+ case WXK_NUMPAD_END:
case WXK_END:
return VK_END; // (23) END key
+ case WXK_NUMPAD_HOME:
case WXK_HOME:
return VK_HOME; // (24) HOME key
+ case WXK_NUMPAD_LEFT:
case WXK_LEFT:
return VK_LEFT; // (25) LEFT ARROW key
+ case WXK_NUMPAD_UP:
case WXK_UP:
return VK_UP; // (26) UP ARROW key
+ case WXK_NUMPAD_RIGHT:
case WXK_RIGHT:
return VK_RIGHT; // (27) RIGHT ARROW key
+ case WXK_NUMPAD_DOWN:
case WXK_DOWN:
return VK_DOWN; // (28) DOWN ARROW key
case WXK_SELECT:
@@ -228,11 +239,12 @@ static int windowsKeyCodeForKeyEvent(unsigned int keycode)
return VK_PRINT; // (2A) PRINT key
case WXK_EXECUTE:
return VK_EXECUTE;// (2B) EXECUTE key
- //dunno on this
- //case WXK_PrintScreen:
- // return VK_SNAPSHOT; // (2C) PRINT SCREEN key
+ case WXK_SNAPSHOT:
+ return VK_SNAPSHOT; // (2C) PRINT SCREEN key
+ case WXK_NUMPAD_INSERT:
case WXK_INSERT:
return VK_INSERT; // (2D) INS key
+ case WXK_NUMPAD_DELETE:
case WXK_DELETE:
return VK_DELETE; // (2E) DEL key
case WXK_HELP:
@@ -336,7 +348,15 @@ PlatformKeyboardEvent::PlatformKeyboardEvent(wxKeyEvent& event)
if (m_type != Char)
m_keyIdentifier = keyIdentifierForWxKeyCode(event.GetKeyCode());
else {
- m_text = wxString(event.GetUnicodeKey());
+ //ENTER is an editing command processed as a char (only Enter and Tab are)
+ //unfortunately the unicode key for numpad_enter (370) is NOT what we want here (13)
+ //The unicode values for normal enter and tab are the same as the ASCII values, thus ok
+ //Note that I think this a wx bug, as the Character Code is actually 13 when
+ //numpad_enter is a CHAR event.
+ if (event.GetKeyCode() == 13 && event.GetUnicodeKey() == wxChar(370))
+ m_text = "\r";
+ else
+ m_text = wxString(event.GetUnicodeKey());
m_unmodifiedText = m_text;
}
m_autoRepeat = false; // FIXME: not correct.
diff --git a/WebCore/platform/wx/LoggingWx.cpp b/WebCore/platform/wx/LoggingWx.cpp
index 006712c..4d8a437 100644
--- a/WebCore/platform/wx/LoggingWx.cpp
+++ b/WebCore/platform/wx/LoggingWx.cpp
@@ -26,11 +26,39 @@
#include "config.h"
#include "Logging.h"
+#include "CString.h"
+#include "PlatformString.h"
+#include <wtf/Vector.h>
+
+#include <wx/defs.h>
+#include <wx/utils.h>
+
namespace WebCore {
void InitializeLoggingChannelsIfNecessary()
{
- LogNotYetImplemented.state = WTFLogChannelOn;
+ static bool haveInitializedLoggingChannels = false;
+ if (haveInitializedLoggingChannels)
+ return;
+
+ haveInitializedLoggingChannels = true;
+
+ wxString loggingEnv;
+ wxGetEnv(wxT("WX_WEBKIT_LOG"), &loggingEnv);
+ if (loggingEnv == wxEmptyString)
+ return;
+
+ String wkLoggingEnv = loggingEnv;
+ Vector<String> logs;
+
+ wkLoggingEnv.split(",", logs);
+
+ for (size_t i = 0; i < logs.size(); ++i) {
+ WTFLogChannel* channel = getChannelFromName(logs[i]);
+
+ if (channel)
+ channel->state = WTFLogChannelOn;
+ }
}
}
diff --git a/WebCore/platform/wx/MouseEventWx.cpp b/WebCore/platform/wx/MouseEventWx.cpp
index a02d7ba..4f39598 100644
--- a/WebCore/platform/wx/MouseEventWx.cpp
+++ b/WebCore/platform/wx/MouseEventWx.cpp
@@ -33,7 +33,7 @@
namespace WebCore {
-PlatformMouseEvent::PlatformMouseEvent(const wxMouseEvent& event, const wxPoint& globalPoint)
+PlatformMouseEvent::PlatformMouseEvent(const wxMouseEvent& event, const wxPoint& globalPoint, int clickCount)
: m_position(event.GetPosition())
, m_globalPosition(globalPoint)
, m_shiftKey(event.ShiftDown())
@@ -67,7 +67,7 @@ PlatformMouseEvent::PlatformMouseEvent(const wxMouseEvent& event, const wxPoint&
if (m_eventType == MouseEventMoved)
m_clickCount = 0;
else
- m_clickCount = event.ButtonDClick() ? 2 : 1;
+ m_clickCount = clickCount;
m_timestamp = WTF::currentTime();
}
diff --git a/WebCore/platform/wx/PopupMenuWx.cpp b/WebCore/platform/wx/PopupMenuWx.cpp
index 4563b77..660282c 100644
--- a/WebCore/platform/wx/PopupMenuWx.cpp
+++ b/WebCore/platform/wx/PopupMenuWx.cpp
@@ -25,7 +25,6 @@
#include "Frame.h"
#include "FrameView.h"
-#include "NotImplemented.h"
#include "PopupMenuClient.h"
#include "PlatformString.h"
diff --git a/WebCore/platform/wx/RenderThemeWx.cpp b/WebCore/platform/wx/RenderThemeWx.cpp
index 9b6dea5..a26416f 100644
--- a/WebCore/platform/wx/RenderThemeWx.cpp
+++ b/WebCore/platform/wx/RenderThemeWx.cpp
@@ -32,10 +32,10 @@
#include "NotImplemented.h"
#include "RenderView.h"
-#include "WebKit/wx/WebView.h"
+#include <wx/defs.h>
+#include <wx/dc.h>
#include <wx/dcgraph.h>
-#include <wx/defs.h>
#include <wx/renderer.h>
#include <wx/dcclient.h>
#include <wx/scrolwin.h>
diff --git a/WebCore/platform/wx/ScrollViewWx.cpp b/WebCore/platform/wx/ScrollViewWx.cpp
index 254ac9f..f556894 100644
--- a/WebCore/platform/wx/ScrollViewWx.cpp
+++ b/WebCore/platform/wx/ScrollViewWx.cpp
@@ -191,12 +191,12 @@ void ScrollView::platformSetScrollPosition(const IntPoint& scrollPoint)
if (newScrollOffset.x < 0)
newScrollOffset.x = 0;
else if (newScrollOffset.x + cRect.width > vRect.width)
- newScrollOffset.x = max(0, vRect.width - cRect.width - 1);
+ newScrollOffset.x = max(0, vRect.width - cRect.width);
if (newScrollOffset.y < 0)
newScrollOffset.y = 0;
else if (newScrollOffset.y + cRect.height > vRect.height)
- newScrollOffset.y = max(0, vRect.height - cRect.height - 1);
+ newScrollOffset.y = max(0, vRect.height - cRect.height);
if (newScrollOffset == scrollOffset)
return;
@@ -291,8 +291,8 @@ void ScrollView::platformSetScrollbarModes()
needsAdjust = true;
}
- if (m_data->vScrollbarMode != horizontalScrollbarMode() ) {
- m_data->vScrollbarMode = horizontalScrollbarMode();
+ if (m_data->vScrollbarMode != verticalScrollbarMode() ) {
+ m_data->vScrollbarMode = verticalScrollbarMode();
needsAdjust = true;
}
diff --git a/WebCore/platform/wx/SharedTimerWx.cpp b/WebCore/platform/wx/SharedTimerWx.cpp
index d95457b..b2b22e4 100644
--- a/WebCore/platform/wx/SharedTimerWx.cpp
+++ b/WebCore/platform/wx/SharedTimerWx.cpp
@@ -26,7 +26,6 @@
#include "config.h"
#include "SharedTimer.h"
-#include "NotImplemented.h"
#include "Widget.h"
#include <wtf/Assertions.h>
@@ -79,28 +78,10 @@ void setSharedTimerFireTime(double fireTime)
wkTimer = new WebKitTimer();
unsigned int intervalInMS = interval * 1000;
- if (interval < 0) {
-#ifndef NDEBUG
- // TODO: We may eventually want to assert here, to track
- // what calls are leading to this condition. It seems to happen
- // mostly with repeating timers.
- fprintf(stderr, "WARNING: setSharedTimerFireTime: fire time is < 0 ms\n");
-#endif
- intervalInMS = 0;
- }
-
- // FIXME: We should mimic the Windows port's behavior and add the timer fired
- // event to the event queue directly rather than making an artifical delay.
- // However, wx won't allow us to assign a simple callback function - we'd have
- // to create a fake wxEvtHandler-derived class with a timer event handler
- // function. Until there's a better way, this way is at least far less
- // hacky.
- if (intervalInMS < 10)
-#if __WXMSW__
- intervalInMS = 10;
-#else
+
+ // sanity check
+ if (intervalInMS < 1)
intervalInMS = 1;
-#endif
wkTimer->Start(intervalInMS, wxTIMER_ONE_SHOT);
}
diff --git a/WebCore/platform/wx/TemporaryLinkStubs.cpp b/WebCore/platform/wx/TemporaryLinkStubs.cpp
index d8c6046..dfd2ad5 100644
--- a/WebCore/platform/wx/TemporaryLinkStubs.cpp
+++ b/WebCore/platform/wx/TemporaryLinkStubs.cpp
@@ -97,11 +97,6 @@ DragImageRef Frame::dragImageForSelection() { notImplemented(); return 0; }
void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) { notImplemented(); }
-// cookies (we'll need a place to store these
-void WebCore::setCookies(Document* document, const KURL& url, const KURL& policyURL, const String& value) { notImplemented(); }
-String WebCore::cookies(const Document* document, const KURL& url) { notImplemented(); return String(); }
-bool WebCore::cookiesEnabled(const Document* document) { notImplemented(); return false; }
-
/********************************************************/
/* Completely empty stubs (mostly to allow DRT to run): */
/********************************************************/
diff --git a/WebCore/platform/wx/WidgetWx.cpp b/WebCore/platform/wx/WidgetWx.cpp
index 37097fe..bb4fd2a 100644
--- a/WebCore/platform/wx/WidgetWx.cpp
+++ b/WebCore/platform/wx/WidgetWx.cpp
@@ -45,8 +45,8 @@ Widget::~Widget()
void Widget::setFocus()
{
- if (platformWidget())
- platformWidget()->SetFocus();
+ if (PlatformWidget widget = platformWidget())
+ widget->SetFocus();
}
void Widget::setCursor(const Cursor& cursor)
@@ -57,38 +57,43 @@ void Widget::setCursor(const Cursor& cursor)
void Widget::show()
{
- if (platformWidget())
- platformWidget()->Show();
+ if (PlatformWidget widget = platformWidget())
+ widget->Show();
}
void Widget::hide()
{
- if (platformWidget())
- platformWidget()->Hide();
+ if (PlatformWidget widget = platformWidget())
+ widget->Hide();
}
IntRect Widget::frameRect() const
{
- if (platformWidget())
- return platformWidget()->GetRect();
+ if (PlatformWidget widget = platformWidget())
+ return widget->GetRect();
+
return m_frame;
}
void Widget::setFrameRect(const IntRect& rect)
{
- if (platformWidget())
- platformWidget()->SetSize(rect);
+ if (PlatformWidget widget = platformWidget())
+ widget->SetSize(rect);
+
m_frame = rect;
}
void Widget::invalidateRect(const IntRect& r)
{
- if (platformWidget())
- platformWidget()->RefreshRect(r);
+ if (PlatformWidget widget = platformWidget())
+ widget->RefreshRect(r);
}
void Widget::paint(GraphicsContext*,const IntRect& r)
{
+ invalidateRect(r);
+ if (PlatformWidget widget = platformWidget())
+ widget->Update();
}
}
diff --git a/WebCore/platform/wx/wxcode/mac/carbon/fontprops.cpp b/WebCore/platform/wx/wxcode/mac/carbon/fontprops.cpp
index 447a3d0..653f142 100644
--- a/WebCore/platform/wx/wxcode/mac/carbon/fontprops.cpp
+++ b/WebCore/platform/wx/wxcode/mac/carbon/fontprops.cpp
@@ -23,11 +23,17 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "config.h"
+#include "fontprops.h"
+
#include <ApplicationServices/ApplicationServices.h>
#include <wx/defs.h>
#include <wx/gdicmn.h>
-#include "fontprops.h"
+
+#ifdef BUILDING_ON_TIGER
+void (*wkGetFontMetrics)(CGFontRef, int* ascent, int* descent, int* lineGap, unsigned* unitsPerEm);
+#endif
const float smallCapsFontSizeMultiplier = 0.7f;
const float contextDPI = 72.0f;
@@ -39,7 +45,7 @@ m_ascent(0), m_descent(0), m_lineGap(0), m_lineSpacing(0), m_xHeight(0)
CGFontRef cgFont;
#ifdef wxOSX_USE_CORE_TEXT && wxOSX_USE_CORE_TEXT
- cgFont = CTFontCopyGraphicsFont((CTFontRef)font->MacGetCTFont(), NULL);
+ cgFont = CTFontCopyGraphicsFont((CTFontRef)font->OSXGetCTFont(), NULL);
#else
ATSFontRef fontRef;
@@ -53,7 +59,7 @@ m_ascent(0), m_descent(0), m_lineGap(0), m_lineSpacing(0), m_xHeight(0)
int iAscent;
int iDescent;
int iLineGap;
- float unitsPerEm;
+ unsigned unitsPerEm;
#ifdef BUILDING_ON_TIGER
wkGetFontMetrics(cgFont, &iAscent, &iDescent, &iLineGap, &unitsPerEm);
#else
@@ -76,6 +82,9 @@ m_ascent(0), m_descent(0), m_lineGap(0), m_lineSpacing(0), m_xHeight(0)
m_lineSpacing = m_ascent + m_descent + m_lineGap;
}
+
+ if (cgFont)
+ CGFontRelease(cgFont);
}
diff --git a/WebCore/platform/wx/wxcode/mac/carbon/non-kerned-drawing.cpp b/WebCore/platform/wx/wxcode/mac/carbon/non-kerned-drawing.cpp
index 6eaa765..e5c60d6 100644
--- a/WebCore/platform/wx/wxcode/mac/carbon/non-kerned-drawing.cpp
+++ b/WebCore/platform/wx/wxcode/mac/carbon/non-kerned-drawing.cpp
@@ -24,44 +24,95 @@
*/
#include "config.h"
+#include "FloatSize.h"
#include "GlyphBuffer.h"
#include "GraphicsContext.h"
#include "SimpleFontData.h"
+#include <wtf/Vector.h>
+
+#include <ApplicationServices/ApplicationServices.h>
+
+#include <dlfcn.h>
#include <wx/defs.h>
#include <wx/dcclient.h>
#include <wx/dcgraph.h>
#include <wx/gdicmn.h>
-#include <vector>
+
+
+// Unfortunately we need access to a private function to get the character -> glyph conversion needed to
+// allow us to use CGContextShowGlyphsWithAdvances
+// Note that on < 10.5, the function is called CGFontGetGlyphsForUnicodes, so we need to detect and deal
+// with this.
+typedef void (*CGFontGetGlyphsForUnicharsPtr)(CGFontRef, const UniChar[], const CGGlyph[], size_t);
+static CGFontGetGlyphsForUnicharsPtr CGFontGetGlyphsForUnichars = (CGFontGetGlyphsForUnicharsPtr)dlsym(RTLD_DEFAULT, "CGFontGetGlyphsForUnichars");
namespace WebCore {
void drawTextWithSpacing(GraphicsContext* graphicsContext, const SimpleFontData* font, const wxColour& color, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point)
{
-#if USE(WXGC)
+ graphicsContext->save();
+
wxGCDC* dc = static_cast<wxGCDC*>(graphicsContext->platformContext());
+
+ wxFont* wxfont = font->getWxFont();
+ graphicsContext->setFillColor(graphicsContext->fillColor());
+
+ CGContextRef cgContext = static_cast<CGContextRef>(dc->GetGraphicsContext()->GetNativeContext());
+
+ CGFontRef cgFont;
+
+#ifdef wxOSX_USE_CORE_TEXT && wxOSX_USE_CORE_TEXT
+ cgFont = CTFontCopyGraphicsFont((CTFontRef)font->OSXGetCTFont(), NULL);
#else
- wxDC* dc = graphicsContext->platformContext();
+ ATSFontRef fontRef;
+
+ fontRef = FMGetATSFontRefFromFont(wxfont->MacGetATSUFontID());
+
+ if (fontRef)
+ cgFont = CGFontCreateWithPlatformFont((void*)&fontRef);
#endif
+
+ CGContextSetFont(cgContext, cgFont);
- wxFont* wxfont = font->getWxFont();
- if (wxfont->IsOk())
- dc->SetFont(*wxfont);
- dc->SetTextForeground(color);
-
- // convert glyphs to wxString
- GlyphBufferGlyph* glyphs = const_cast<GlyphBufferGlyph*>(glyphBuffer.glyphs(from));
- int offset = point.x();
- wxString text = wxEmptyString;
- for (unsigned i = 0; i < numGlyphs; i++) {
- text = text.Append((wxChar)glyphs[i]);
- offset += glyphBuffer.advanceAt(from + i);
+ CGContextSetFontSize(cgContext, wxfont->GetPointSize());
+
+ CGFloat red, green, blue, alpha;
+ graphicsContext->fillColor().getRGBA(red, green, blue, alpha);
+ CGContextSetRGBFillColor(cgContext, red, green, blue, alpha);
+
+ CGAffineTransform matrix = CGAffineTransformIdentity;
+ matrix.b = -matrix.b;
+ matrix.d = -matrix.d;
+
+ CGContextSetTextMatrix(cgContext, matrix);
+
+ CGContextSetTextPosition(cgContext, point.x(), point.y());
+
+ const FloatSize* advanceSizes = static_cast<const FloatSize*>(glyphBuffer.advances(from));
+ int size = glyphBuffer.size() - from;
+ CGSize sizes[size];
+ CGGlyph glyphs[numGlyphs];
+
+ // if the function doesn't exist, we're probably on tiger and need to grab the
+ // function under its old name, CGFontGetGlyphsForUnicodes
+ if (!CGFontGetGlyphsForUnichars)
+ CGFontGetGlyphsForUnichars = (CGFontGetGlyphsForUnicharsPtr)dlsym(RTLD_DEFAULT, "CGFontGetGlyphsForUnicodes");
+
+ // Let's make sure we got the function under one name or another!
+ ASSERT(CGFontGetGlyphsForUnichars);
+ CGFontGetGlyphsForUnichars(cgFont, glyphBuffer.glyphs(from), glyphs, numGlyphs);
+
+ for (int i = 0; i < size; i++) {
+ FloatSize fsize = advanceSizes[i];
+ sizes[i] = CGSizeMake(fsize.width(), fsize.height());
}
- // NOTE: The wx API actually adds the ascent to the y value internally,
- // so we have to subtract it from the y point here so that the ascent
- // isn't added twice.
- dc->DrawText(text, (wxCoord)point.x(), int(point.y() - font->ascent()));
+ CGContextShowGlyphsWithAdvances(cgContext, glyphs, sizes, numGlyphs);
+
+ if (cgFont)
+ CGFontRelease(cgFont);
+ graphicsContext->restore();
}
}
diff --git a/WebCore/platform/wx/wxcode/win/fontprops.cpp b/WebCore/platform/wx/wxcode/win/fontprops.cpp
index 1314691..531db08 100644
--- a/WebCore/platform/wx/wxcode/win/fontprops.cpp
+++ b/WebCore/platform/wx/wxcode/win/fontprops.cpp
@@ -91,7 +91,7 @@ void GetTextExtent( const wxFont& font, const wxString& str, wxCoord *width, wxC
// accounts for under/overhang of the first/last character while we want
// just the bounding rect for this string so adjust the width as needed
// (using API not available in 2002 SDKs of WinCE)
- if ( len > 0 )
+ if ( len > 1 )
{
ABC width;
const wxChar chFirst = *str.begin();
diff --git a/WebCore/platform/wx/wxcode/win/non-kerned-drawing.cpp b/WebCore/platform/wx/wxcode/win/non-kerned-drawing.cpp
index 7d1e924..d2513d7 100644
--- a/WebCore/platform/wx/wxcode/win/non-kerned-drawing.cpp
+++ b/WebCore/platform/wx/wxcode/win/non-kerned-drawing.cpp
@@ -30,6 +30,7 @@
#include <wx/defs.h>
#include <wx/dcclient.h>
+#include <wx/dcgraph.h>
#include <wx/gdicmn.h>
#include <vector>